1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Multisample interpolation tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fShaderMultisampleInterpolationTests.hpp"
25 #include "es31fMultisampleShaderRenderCase.hpp"
26 #include "tcuTestLog.hpp"
27 #include "tcuRGBA.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "tcuRenderTarget.hpp"
31 #include "gluContextInfo.hpp"
32 #include "gluShaderProgram.hpp"
33 #include "gluRenderContext.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36 #include "deArrayUtil.hpp"
37 #include "deStringUtil.hpp"
38 #include "deMath.h"
39
40 #include <map>
41
42 namespace deqp
43 {
44 namespace gles31
45 {
46 namespace Functional
47 {
48 namespace
49 {
50
specializeShader(const std::string& shaderSource, const glu::ContextType& contextType)51 static std::string specializeShader(const std::string& shaderSource, const glu::ContextType& contextType)
52 {
53 const bool isES32orGL45 = glu::contextSupports(contextType, glu::ApiType::es(3, 2)) ||
54 glu::contextSupports(contextType, glu::ApiType::core(4, 5));
55
56 std::map<std::string, std::string> args;
57 args["GLSL_VERSION_DECL"] = glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(contextType));
58 args["GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION"] = isES32orGL45 ? "" : "#extension GL_OES_shader_multisample_interpolation : require\n";
59 args["GLSL_EXT_SAMPLE_VARIABLES"] = isES32orGL45 ? "" : "#extension GL_OES_sample_variables : require\n";
60
61 return tcu::StringTemplate(shaderSource).specialize(args);
62 }
63
checkSupport(Context& ctx)64 static bool checkSupport(Context& ctx)
65 {
66 auto ctxType = ctx.getRenderContext().getType();
67 return glu::contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
68 glu::contextSupports(ctxType, glu::ApiType::core(4, 5));
69 }
70
verifyGreenImage(const tcu::Surface& image, tcu::TestLog& log)71 static bool verifyGreenImage (const tcu::Surface& image, tcu::TestLog& log)
72 {
73 bool error = false;
74
75 log << tcu::TestLog::Message << "Verifying result image, expecting green." << tcu::TestLog::EndMessage;
76
77 // all pixels must be green
78
79 for (int y = 0; y < image.getHeight(); ++y)
80 for (int x = 0; x < image.getWidth(); ++x)
81 {
82 const tcu::RGBA color = image.getPixel(x, y);
83 const int greenThreshold = 8;
84
85 if (color.getRed() > 0 || color.getGreen() < 255-greenThreshold || color.getBlue() > 0)
86 error = true;
87 }
88
89 if (error)
90 log << tcu::TestLog::Image("ResultImage", "Result Image", image.getAccess())
91 << tcu::TestLog::Message
92 << "Image verification failed."
93 << tcu::TestLog::EndMessage;
94 else
95 log << tcu::TestLog::Image("ResultImage", "Result Image", image.getAccess())
96 << tcu::TestLog::Message
97 << "Image verification passed."
98 << tcu::TestLog::EndMessage;
99
100 return !error;
101 }
102
103 class MultisampleShadeCountRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
104 {
105 public:
106 MultisampleShadeCountRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
107 virtual ~MultisampleShadeCountRenderCase (void);
108
109 void init (void);
110
111 private:
112 enum
113 {
114 RENDER_SIZE = 128
115 };
116
117 virtual std::string getIterationDescription (int iteration) const;
118 bool verifyImage (const tcu::Surface& resultImage);
119 };
120
MultisampleShadeCountRenderCase(Context& context, const char* name, const char* description, int numSamples, RenderTarget target)121 MultisampleShadeCountRenderCase::MultisampleShadeCountRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
122 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_PER_ITERATION_SHADER)
123 {
124 m_numIterations = -1; // must be set by deriving class
125 }
126
~MultisampleShadeCountRenderCase(void)127 MultisampleShadeCountRenderCase::~MultisampleShadeCountRenderCase (void)
128 {
129 }
130
init(void)131 void MultisampleShadeCountRenderCase::init (void)
132 {
133 // requirements
134 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
135 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
136
137 MultisampleShaderRenderUtil::MultisampleRenderCase::init();
138 }
139
getIterationDescription(int iteration) const140 std::string MultisampleShadeCountRenderCase::getIterationDescription (int iteration) const
141 {
142 // must be overriden
143 DE_UNREF(iteration);
144 DE_ASSERT(false);
145 return "";
146 }
147
verifyImage(const tcu::Surface& resultImage)148 bool MultisampleShadeCountRenderCase::verifyImage (const tcu::Surface& resultImage)
149 {
150 const bool isSingleSampleTarget = (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1);
151 const int numShadesRequired = (isSingleSampleTarget) ? (2) : (m_numTargetSamples + 1);
152 const int rareThreshold = 100;
153 int rareCount = 0;
154 std::map<deUint32, int> shadeFrequency;
155
156 m_testCtx.getLog()
157 << tcu::TestLog::Image("ResultImage", "Result Image", resultImage.getAccess())
158 << tcu::TestLog::Message
159 << "Verifying image has (at least) " << numShadesRequired << " different shades.\n"
160 << "Excluding pixels with no full coverage (pixels on the shared edge of the triangle pair)."
161 << tcu::TestLog::EndMessage;
162
163 for (int y = 0; y < RENDER_SIZE; ++y)
164 for (int x = 0; x < RENDER_SIZE; ++x)
165 {
166 const tcu::RGBA color = resultImage.getPixel(x, y);
167 const deUint32 packed = ((deUint32)color.getRed()) + ((deUint32)color.getGreen() << 8) + ((deUint32)color.getGreen() << 16);
168
169 // on the triangle edge, skip
170 if (x == y)
171 continue;
172
173 if (shadeFrequency.find(packed) == shadeFrequency.end())
174 shadeFrequency[packed] = 1;
175 else
176 shadeFrequency[packed] = shadeFrequency[packed] + 1;
177 }
178
179 for (std::map<deUint32, int>::const_iterator it = shadeFrequency.begin(); it != shadeFrequency.end(); ++it)
180 if (it->second < rareThreshold)
181 rareCount++;
182
183 m_testCtx.getLog()
184 << tcu::TestLog::Message
185 << "Found " << (int)shadeFrequency.size() << " different shades.\n"
186 << "\tRare (less than " << rareThreshold << " pixels): " << rareCount << "\n"
187 << "\tCommon: " << (int)shadeFrequency.size() - rareCount << "\n"
188 << tcu::TestLog::EndMessage;
189
190 if ((int)shadeFrequency.size() < numShadesRequired)
191 {
192 m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage;
193 return false;
194 }
195 return true;
196 }
197
198 class SampleQualifierRenderCase : public MultisampleShadeCountRenderCase
199 {
200 public:
201 SampleQualifierRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
202 ~SampleQualifierRenderCase (void);
203
204 void init (void);
205
206 private:
207 std::string genVertexSource (int numTargetSamples) const;
208 std::string genFragmentSource (int numTargetSamples) const;
209 std::string getIterationDescription (int iteration) const;
210 };
211
SampleQualifierRenderCase(Context& context, const char* name, const char* description, int numSamples, RenderTarget target)212 SampleQualifierRenderCase::SampleQualifierRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
213 : MultisampleShadeCountRenderCase(context, name, description, numSamples, target)
214 {
215 m_numIterations = 6; // float, vec2, .3, .4, array, struct
216 }
217
~SampleQualifierRenderCase(void)218 SampleQualifierRenderCase::~SampleQualifierRenderCase (void)
219 {
220 }
221
init(void)222 void SampleQualifierRenderCase::init (void)
223 {
224 const bool isSingleSampleTarget = (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1);
225
226 // test purpose and expectations
227 if (isSingleSampleTarget)
228 {
229 m_testCtx.getLog()
230 << tcu::TestLog::Message
231 << "Verifying that a sample-qualified varying is given different values for different samples.\n"
232 << " Render high-frequency function, map result to black/white.\n"
233 << " => Resulting image image should contain both black and white pixels.\n"
234 << tcu::TestLog::EndMessage;
235 }
236 else
237 {
238 m_testCtx.getLog()
239 << tcu::TestLog::Message
240 << "Verifying that a sample-qualified varying is given different values for different samples.\n"
241 << " Render high-frequency function, map result to black/white.\n"
242 << " => Resulting image should contain n+1 shades of gray, n = sample count.\n"
243 << tcu::TestLog::EndMessage;
244 }
245
246 MultisampleShadeCountRenderCase::init();
247 }
248
genVertexSource(int numTargetSamples) const249 std::string SampleQualifierRenderCase::genVertexSource (int numTargetSamples) const
250 {
251 DE_UNREF(numTargetSamples);
252
253 std::ostringstream buf;
254
255 buf << "${GLSL_VERSION_DECL}\n"
256 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
257 "in highp vec4 a_position;\n";
258
259 if (m_iteration == 0)
260 buf << "sample out highp float v_input;\n";
261 else if (m_iteration == 1)
262 buf << "sample out highp vec2 v_input;\n";
263 else if (m_iteration == 2)
264 buf << "sample out highp vec3 v_input;\n";
265 else if (m_iteration == 3)
266 buf << "sample out highp vec4 v_input;\n";
267 else if (m_iteration == 4)
268 buf << "sample out highp float[2] v_input;\n";
269 else if (m_iteration == 5)
270 buf << "struct VaryingStruct { highp float a; highp float b; };\n"
271 "sample out VaryingStruct v_input;\n";
272 else
273 DE_ASSERT(false);
274
275 buf << "void main (void)\n"
276 "{\n"
277 " gl_Position = a_position;\n";
278
279 if (m_iteration == 0)
280 buf << " v_input = a_position.x + exp(a_position.y) + step(0.9, a_position.x)*step(a_position.y, -0.9)*8.0;\n";
281 else if (m_iteration == 1)
282 buf << " v_input = a_position.xy;\n";
283 else if (m_iteration == 2)
284 buf << " v_input = vec3(a_position.xy, a_position.x * 2.0 - a_position.y);\n";
285 else if (m_iteration == 3)
286 buf << " v_input = vec4(a_position.xy, a_position.x * 2.0 - a_position.y, a_position.x*a_position.y);\n";
287 else if (m_iteration == 4)
288 buf << " v_input[0] = a_position.x;\n"
289 " v_input[1] = a_position.y;\n";
290 else if (m_iteration == 5)
291 buf << " v_input.a = a_position.x;\n"
292 " v_input.b = a_position.y;\n";
293 else
294 DE_ASSERT(false);
295
296 buf << "}";
297
298 return specializeShader(buf.str(), m_context.getRenderContext().getType());
299 }
300
genFragmentSource(int numTargetSamples) const301 std::string SampleQualifierRenderCase::genFragmentSource (int numTargetSamples) const
302 {
303 DE_UNREF(numTargetSamples);
304
305 std::ostringstream buf;
306
307 buf << "${GLSL_VERSION_DECL}\n"
308 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}";
309
310 if (m_iteration == 0)
311 buf << "sample in highp float v_input;\n";
312 else if (m_iteration == 1)
313 buf << "sample in highp vec2 v_input;\n";
314 else if (m_iteration == 2)
315 buf << "sample in highp vec3 v_input;\n";
316 else if (m_iteration == 3)
317 buf << "sample in highp vec4 v_input;\n";
318 else if (m_iteration == 4)
319 buf << "sample in highp float[2] v_input;\n";
320 else if (m_iteration == 5)
321 buf << "struct VaryingStruct { highp float a; highp float b; };\n"
322 "sample in VaryingStruct v_input;\n";
323 else
324 DE_ASSERT(false);
325
326 buf << "layout(location = 0) out mediump vec4 fragColor;\n"
327 "void main (void)\n"
328 "{\n";
329
330 if (m_iteration == 0)
331 buf << " highp float field = exp(v_input) + v_input*v_input;\n";
332 else if (m_iteration == 1)
333 buf << " highp float field = dot(v_input.xy, v_input.xy) + dot(21.0 * v_input.xx, sin(3.1 * v_input.xy));\n";
334 else if (m_iteration == 2)
335 buf << " highp float field = dot(v_input.xy, v_input.xy) + dot(21.0 * v_input.zx, sin(3.1 * v_input.zy));\n";
336 else if (m_iteration == 3)
337 buf << " highp float field = dot(v_input.xy, v_input.zw) + dot(21.0 * v_input.zy, sin(3.1 * v_input.zw));\n";
338 else if (m_iteration == 4)
339 buf << " highp float field = dot(vec2(v_input[0], v_input[1]), vec2(v_input[0], v_input[1])) + dot(21.0 * vec2(v_input[0]), sin(3.1 * vec2(v_input[0], v_input[1])));\n";
340 else if (m_iteration == 5)
341 buf << " highp float field = dot(vec2(v_input.a, v_input.b), vec2(v_input.a, v_input.b)) + dot(21.0 * vec2(v_input.a), sin(3.1 * vec2(v_input.a, v_input.b)));\n";
342 else
343 DE_ASSERT(false);
344
345 buf << " fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
346 "\n"
347 " if (fract(field) > 0.5)\n"
348 " fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
349 "}";
350
351 return specializeShader(buf.str(), m_context.getRenderContext().getType());
352 }
353
getIterationDescription(int iteration) const354 std::string SampleQualifierRenderCase::getIterationDescription (int iteration) const
355 {
356 if (iteration == 0)
357 return "Test with float varying";
358 else if (iteration == 1)
359 return "Test with vec2 varying";
360 else if (iteration == 2)
361 return "Test with vec3 varying";
362 else if (iteration == 3)
363 return "Test with vec4 varying";
364 else if (iteration == 4)
365 return "Test with array varying";
366 else if (iteration == 5)
367 return "Test with struct varying";
368
369 DE_ASSERT(false);
370 return "";
371 }
372
373 class InterpolateAtSampleRenderCase : public MultisampleShadeCountRenderCase
374 {
375 public:
376 enum IndexingMode
377 {
378 INDEXING_STATIC,
379 INDEXING_DYNAMIC,
380
381 INDEXING_LAST
382 };
383 InterpolateAtSampleRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, IndexingMode mode);
384 ~InterpolateAtSampleRenderCase (void);
385
386 void init (void);
387 void preDraw (void);
388
389 private:
390 std::string genVertexSource (int numTargetSamples) const;
391 std::string genFragmentSource (int numTargetSamples) const;
392 std::string getIterationDescription (int iteration) const;
393
394 const IndexingMode m_indexMode;
395 };
396
InterpolateAtSampleRenderCase(Context& context, const char* name, const char* description, int numSamples, RenderTarget target, IndexingMode mode)397 InterpolateAtSampleRenderCase::InterpolateAtSampleRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, IndexingMode mode)
398 : MultisampleShadeCountRenderCase (context, name, description, numSamples, target)
399 , m_indexMode (mode)
400 {
401 DE_ASSERT(mode < INDEXING_LAST);
402
403 m_numIterations = 5; // float, vec2, .3, .4, array
404 }
405
406 InterpolateAtSampleRenderCase::~InterpolateAtSampleRenderCase (void)
407 {
408 }
409
410 void InterpolateAtSampleRenderCase::init (void)
411 {
412 const bool isSingleSampleTarget = (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1);
413
414 // test purpose and expectations
415 if (isSingleSampleTarget)
416 {
417 m_testCtx.getLog()
418 << tcu::TestLog::Message
419 << "Verifying that a interpolateAtSample returns different values for different samples.\n"
420 << " Render high-frequency function, map result to black/white.\n"
421 << " => Resulting image image should contain both black and white pixels.\n"
422 << tcu::TestLog::EndMessage;
423 }
424 else
425 {
426 m_testCtx.getLog()
427 << tcu::TestLog::Message
428 << "Verifying that a interpolateAtSample returns different values for different samples.\n"
429 << " Render high-frequency function, map result to black/white.\n"
430 << " => Resulting image should contain n+1 shades of gray, n = sample count.\n"
431 << tcu::TestLog::EndMessage;
432 }
433
434 MultisampleShadeCountRenderCase::init();
435 }
436
437 void InterpolateAtSampleRenderCase::preDraw (void)
438 {
439 if (m_indexMode == INDEXING_DYNAMIC)
440 {
441 const deInt32 range = m_numTargetSamples;
442 const deInt32 offset = 1;
443 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
444 const deInt32 offsetLoc = gl.getUniformLocation(m_program->getProgram(), "u_offset");
445 const deInt32 rangeLoc = gl.getUniformLocation(m_program->getProgram(), "u_range");
446
447 if (offsetLoc == -1)
448 throw tcu::TestError("Location of u_offset was -1");
449 if (rangeLoc == -1)
450 throw tcu::TestError("Location of u_range was -1");
451
452 gl.uniform1i(offsetLoc, 0);
453 gl.uniform1i(rangeLoc, m_numTargetSamples);
454 GLU_EXPECT_NO_ERROR(gl.getError(), "set uniforms");
455
456 m_testCtx.getLog()
457 << tcu::TestLog::Message
458 << "Set u_offset = " << offset << "\n"
459 << "Set u_range = " << range
460 << tcu::TestLog::EndMessage;
461 }
462 }
463
464 std::string InterpolateAtSampleRenderCase::genVertexSource (int numTargetSamples) const
465 {
466 DE_UNREF(numTargetSamples);
467
468 std::ostringstream buf;
469
470 buf << "${GLSL_VERSION_DECL}\n"
471 "in highp vec4 a_position;\n";
472
473 if (m_iteration == 0)
474 buf << "out highp float v_input;\n";
475 else if (m_iteration == 1)
476 buf << "out highp vec2 v_input;\n";
477 else if (m_iteration == 2)
478 buf << "out highp vec3 v_input;\n";
479 else if (m_iteration == 3)
480 buf << "out highp vec4 v_input;\n";
481 else if (m_iteration == 4)
482 buf << "out highp vec2[2] v_input;\n";
483 else
484 DE_ASSERT(false);
485
486 buf << "void main (void)\n"
487 "{\n"
488 " gl_Position = a_position;\n";
489
490 if (m_iteration == 0)
491 buf << " v_input = a_position.x + exp(a_position.y) + step(0.9, a_position.x)*step(a_position.y, -0.9)*8.0;\n";
492 else if (m_iteration == 1)
493 buf << " v_input = a_position.xy;\n";
494 else if (m_iteration == 2)
495 buf << " v_input = vec3(a_position.xy, a_position.x * 2.0 - a_position.y);\n";
496 else if (m_iteration == 3)
497 buf << " v_input = vec4(a_position.xy, a_position.x * 2.0 - a_position.y, a_position.x*a_position.y);\n";
498 else if (m_iteration == 4)
499 buf << " v_input[0] = a_position.yx + vec2(0.5, 0.5);\n"
500 " v_input[1] = a_position.xy;\n";
501 else
502 DE_ASSERT(false);
503
504 buf << "}";
505
506 return specializeShader(buf.str(), m_context.getRenderContext().getType());
507 }
508
509 std::string InterpolateAtSampleRenderCase::genFragmentSource (int numTargetSamples) const
510 {
511 std::ostringstream buf;
512
513 buf << "${GLSL_VERSION_DECL}\n"
514 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}";
515
516 if (m_iteration == 0)
517 buf << "in highp float v_input;\n";
518 else if (m_iteration == 1)
519 buf << "in highp vec2 v_input;\n";
520 else if (m_iteration == 2)
521 buf << "in highp vec3 v_input;\n";
522 else if (m_iteration == 3)
523 buf << "in highp vec4 v_input;\n";
524 else if (m_iteration == 4)
525 buf << "in highp vec2[2] v_input;\n";
526 else
527 DE_ASSERT(false);
528
529 buf << "layout(location = 0) out mediump vec4 fragColor;\n";
530
531 if (m_indexMode == INDEXING_DYNAMIC)
532 buf << "uniform highp int u_offset;\n"
533 "uniform highp int u_range;\n";
534
535 buf << "void main (void)\n"
536 "{\n"
537 " mediump int coverage = 0;\n"
538 "\n";
539
540 if (m_indexMode == INDEXING_STATIC)
541 {
542 for (int ndx = 0; ndx < numTargetSamples; ++ndx)
543 {
544 if (m_iteration == 0)
545 buf << " highp float sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n";
546 else if (m_iteration == 1)
547 buf << " highp vec2 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n";
548 else if (m_iteration == 2)
549 buf << " highp vec3 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n";
550 else if (m_iteration == 3)
551 buf << " highp vec4 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n";
552 else if (m_iteration == 4)
553 buf << " highp vec2 sampleInput" << ndx << " = interpolateAtSample(v_input[1], " << ndx << ");\n";
554 else
555 DE_ASSERT(false);
556 }
557 buf << "\n";
558
559 for (int ndx = 0; ndx < numTargetSamples; ++ndx)
560 {
561 if (m_iteration == 0)
562 buf << " highp float field" << ndx << " = exp(sampleInput" << ndx << ") + sampleInput" << ndx << "*sampleInput" << ndx << ";\n";
563 else if (m_iteration == 1 || m_iteration == 4)
564 buf << " highp float field" << ndx << " = dot(sampleInput" << ndx << ", sampleInput" << ndx << ") + dot(21.0 * sampleInput" << ndx << ".xx, sin(3.1 * sampleInput" << ndx << "));\n";
565 else if (m_iteration == 2)
566 buf << " highp float field" << ndx << " = dot(sampleInput" << ndx << ".xy, sampleInput" << ndx << ".xy) + dot(21.0 * sampleInput" << ndx << ".zx, sin(3.1 * sampleInput" << ndx << ".zy));\n";
567 else if (m_iteration == 3)
568 buf << " highp float field" << ndx << " = dot(sampleInput" << ndx << ".xy, sampleInput" << ndx << ".zw) + dot(21.0 * sampleInput" << ndx << ".zy, sin(3.1 * sampleInput" << ndx << ".zw));\n";
569 else
570 DE_ASSERT(false);
571 }
572 buf << "\n";
573
574 for (int ndx = 0; ndx < numTargetSamples; ++ndx)
575 buf << " if (fract(field" << ndx << ") <= 0.5)\n"
576 " ++coverage;\n";
577 }
578 else if (m_indexMode == INDEXING_DYNAMIC)
579 {
580 buf << " for (int ndx = 0; ndx < " << numTargetSamples << "; ++ndx)\n"
581 " {\n";
582
583 if (m_iteration == 0)
584 buf << " highp float sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n";
585 else if (m_iteration == 1)
586 buf << " highp vec2 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n";
587 else if (m_iteration == 2)
588 buf << " highp vec3 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n";
589 else if (m_iteration == 3)
590 buf << " highp vec4 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n";
591 else if (m_iteration == 4)
592 buf << " highp vec2 sampleInput = interpolateAtSample(v_input[1], (u_offset + ndx) % u_range);\n";
593 else
594 DE_ASSERT(false);
595
596 if (m_iteration == 0)
597 buf << " highp float field = exp(sampleInput) + sampleInput*sampleInput;\n";
598 else if (m_iteration == 1 || m_iteration == 4)
599 buf << " highp float field = dot(sampleInput, sampleInput) + dot(21.0 * sampleInput.xx, sin(3.1 * sampleInput));\n";
600 else if (m_iteration == 2)
601 buf << " highp float field = dot(sampleInput.xy, sampleInput.xy) + dot(21.0 * sampleInput.zx, sin(3.1 * sampleInput.zy));\n";
602 else if (m_iteration == 3)
603 buf << " highp float field = dot(sampleInput.xy, sampleInput.zw) + dot(21.0 * sampleInput.zy, sin(3.1 * sampleInput.zw));\n";
604 else
605 DE_ASSERT(false);
606
607 buf << " if (fract(field) <= 0.5)\n"
608 " ++coverage;\n"
609 " }\n";
610 }
611
612 buf << " fragColor = vec4(vec3(float(coverage) / float(" << numTargetSamples << ")), 1.0);\n"
613 "}";
614
615 return specializeShader(buf.str(), m_context.getRenderContext().getType());
616 }
617
618 std::string InterpolateAtSampleRenderCase::getIterationDescription (int iteration) const
619 {
620 if (iteration == 0)
621 return "Test with float varying";
622 else if (iteration < 4)
623 return "Test with vec" + de::toString(iteration+1) + " varying";
624 else if (iteration == 4)
625 return "Test with array varying";
626
627 DE_ASSERT(false);
628 return "";
629 }
630
631 class SingleSampleInterpolateAtSampleCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
632 {
633 public:
634 enum SampleCase
635 {
636 SAMPLE_0 = 0,
637 SAMPLE_N,
638
639 SAMPLE_LAST
640 };
641
642 SingleSampleInterpolateAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, SampleCase sampleCase);
643 virtual ~SingleSampleInterpolateAtSampleCase (void);
644
645 void init (void);
646
647 private:
648 enum
649 {
650 RENDER_SIZE = 32
651 };
652
653 std::string genVertexSource (int numTargetSamples) const;
654 std::string genFragmentSource (int numTargetSamples) const;
655 bool verifyImage (const tcu::Surface& resultImage);
656
657 const SampleCase m_sampleCase;
658 };
659
660 SingleSampleInterpolateAtSampleCase::SingleSampleInterpolateAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, SampleCase sampleCase)
661 : MultisampleShaderRenderUtil::MultisampleRenderCase (context, name, description, numSamples, target, RENDER_SIZE)
662 , m_sampleCase (sampleCase)
663 {
664 DE_ASSERT(numSamples == 0);
665 DE_ASSERT(sampleCase < SAMPLE_LAST);
666 }
667
668 SingleSampleInterpolateAtSampleCase::~SingleSampleInterpolateAtSampleCase (void)
669 {
670 }
671
672 void SingleSampleInterpolateAtSampleCase::init (void)
673 {
674 // requirements
675 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
676 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
677 if (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1)
678 TCU_THROW(NotSupportedError, "Non-multisample framebuffer required");
679
680 // test purpose and expectations
681 m_testCtx.getLog()
682 << tcu::TestLog::Message
683 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
684 << " Interpolate varying containing screen space location.\n"
685 << " => fract(screen space location) should be (about) (0.5, 0.5)\n"
686 << tcu::TestLog::EndMessage;
687
688 MultisampleShaderRenderUtil::MultisampleRenderCase::init();
689 }
690
691 std::string SingleSampleInterpolateAtSampleCase::genVertexSource (int numTargetSamples) const
692 {
693 DE_UNREF(numTargetSamples);
694
695 std::ostringstream buf;
696
697 buf << "${GLSL_VERSION_DECL}\n"
698 "in highp vec4 a_position;\n"
699 "out highp vec2 v_position;\n"
700 "void main (void)\n"
701 "{\n"
702 " gl_Position = a_position;\n"
703 " v_position = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n"
704 "}\n";
705
706 return specializeShader(buf.str(), m_context.getRenderContext().getType());
707 }
708
709 std::string SingleSampleInterpolateAtSampleCase::genFragmentSource (int numTargetSamples) const
710 {
711 DE_UNREF(numTargetSamples);
712
713 std::ostringstream buf;
714
715 buf << "${GLSL_VERSION_DECL}\n"
716 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
717 "in highp vec2 v_position;\n"
718 "layout(location = 0) out mediump vec4 fragColor;\n"
719 "void main (void)\n"
720 "{\n"
721 " const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"; // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
722
723 if (m_sampleCase == SAMPLE_0)
724 {
725 buf << " highp vec2 samplePosition = interpolateAtSample(v_position, 0);\n"
726 " highp vec2 positionInsideAPixel = fract(samplePosition);\n"
727 "\n"
728 " if (abs(positionInsideAPixel.x - 0.5) <= threshold && abs(positionInsideAPixel.y - 0.5) <= threshold)\n"
729 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
730 " else\n"
731 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
732 "}\n";
733 }
734 else if (m_sampleCase == SAMPLE_N)
735 {
736 buf << " bool allOk = true;\n"
737 " for (int sampleNdx = 159; sampleNdx < 163; ++sampleNdx)\n"
738 " {\n"
739 " highp vec2 samplePosition = interpolateAtSample(v_position, sampleNdx);\n"
740 " highp vec2 positionInsideAPixel = fract(samplePosition);\n"
741 " if (abs(positionInsideAPixel.x - 0.5) > threshold || abs(positionInsideAPixel.y - 0.5) > threshold)\n"
742 " allOk = false;\n"
743 " }\n"
744 "\n"
745 " if (allOk)\n"
746 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
747 " else\n"
748 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
749 "}\n";
750 }
751 else
752 DE_ASSERT(false);
753
754 return specializeShader(buf.str(), m_context.getRenderContext().getType());
755 }
756
757 bool SingleSampleInterpolateAtSampleCase::verifyImage (const tcu::Surface& resultImage)
758 {
759 return verifyGreenImage(resultImage, m_testCtx.getLog());
760 }
761
762 class CentroidRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
763 {
764 public:
765 CentroidRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, int renderSize);
766 virtual ~CentroidRenderCase (void);
767
768 void init (void);
769
770 private:
771 void setupRenderData (void);
772 };
773
774 CentroidRenderCase::CentroidRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, int renderSize)
775 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, renderSize)
776 {
777 }
778
779 CentroidRenderCase::~CentroidRenderCase (void)
780 {
781 }
782
783 void CentroidRenderCase::init (void)
784 {
785 // requirements
786 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
787 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
788
789 MultisampleShaderRenderUtil::MultisampleRenderCase::init();
790 }
791
792 void CentroidRenderCase::setupRenderData (void)
793 {
794 const int numTriangles = 200;
795 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
796 std::vector<tcu::Vec4> data (numTriangles * 3 * 3);
797
798 m_renderMode = GL_TRIANGLES;
799 m_renderCount = numTriangles * 3;
800 m_renderSceneDescription = "triangle fan of narrow triangles";
801
802 m_renderAttribs["a_position"].offset = 0;
803 m_renderAttribs["a_position"].stride = (int)sizeof(float[4]) * 3;
804 m_renderAttribs["a_barycentricsA"].offset = (int)sizeof(float[4]);
805 m_renderAttribs["a_barycentricsA"].stride = (int)sizeof(float[4]) * 3;
806 m_renderAttribs["a_barycentricsB"].offset = (int)sizeof(float[4]) * 2;
807 m_renderAttribs["a_barycentricsB"].stride = (int)sizeof(float[4]) * 3;
808
809 for (int triangleNdx = 0; triangleNdx < numTriangles; ++triangleNdx)
810 {
811 const float angle = ((float)triangleNdx) / (float)numTriangles * 2.0f * DE_PI;
812 const float nextAngle = ((float)triangleNdx + 1.0f) / (float)numTriangles * 2.0f * DE_PI;
813
814 data[(triangleNdx * 3 + 0) * 3 + 0] = tcu::Vec4(0.2f, -0.3f, 0.0f, 1.0f);
815 data[(triangleNdx * 3 + 0) * 3 + 1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
816 data[(triangleNdx * 3 + 0) * 3 + 2] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
817
818 data[(triangleNdx * 3 + 1) * 3 + 0] = tcu::Vec4(2.0f * deFloatCos(angle), 2.0f * deFloatSin(angle), 0.0f, 1.0f);
819 data[(triangleNdx * 3 + 1) * 3 + 1] = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f);
820 data[(triangleNdx * 3 + 1) * 3 + 2] = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f);
821
822 data[(triangleNdx * 3 + 2) * 3 + 0] = tcu::Vec4(2.0f * deFloatCos(nextAngle), 2.0f * deFloatSin(nextAngle), 0.0f, 1.0f);
823 data[(triangleNdx * 3 + 2) * 3 + 1] = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f);
824 data[(triangleNdx * 3 + 2) * 3 + 2] = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f);
825 }
826
827 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer);
828 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(data.size() * sizeof(tcu::Vec4)), data[0].getPtr(), GL_STATIC_DRAW);
829 }
830
831 class CentroidQualifierAtSampleCase : public CentroidRenderCase
832 {
833 public:
834 CentroidQualifierAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
835 virtual ~CentroidQualifierAtSampleCase (void);
836
837 void init (void);
838
839 private:
840 enum
841 {
842 RENDER_SIZE = 128
843 };
844
845 std::string genVertexSource (int numTargetSamples) const;
846 std::string genFragmentSource (int numTargetSamples) const;
847 bool verifyImage (const tcu::Surface& resultImage);
848 };
849
850 CentroidQualifierAtSampleCase::CentroidQualifierAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
851 : CentroidRenderCase(context, name, description, numSamples, target, RENDER_SIZE)
852 {
853 }
854
855 CentroidQualifierAtSampleCase::~CentroidQualifierAtSampleCase (void)
856 {
857 }
858
859 void CentroidQualifierAtSampleCase::init (void)
860 {
861 // test purpose and expectations
862 m_testCtx.getLog()
863 << tcu::TestLog::Message
864 << "Verifying that interpolateAtSample ignores the centroid-qualifier.\n"
865 << " Draw a fan of narrow triangles (large number of pixels on the edges).\n"
866 << " Set varyings 'barycentricsA' and 'barycentricsB' to contain barycentric coordinates.\n"
867 << " Add centroid-qualifier for barycentricsB.\n"
868 << " => interpolateAtSample(barycentricsB, N) ~= interpolateAtSample(barycentricsA, N)\n"
869 << tcu::TestLog::EndMessage;
870
871 CentroidRenderCase::init();
872 }
873
874 std::string CentroidQualifierAtSampleCase::genVertexSource (int numTargetSamples) const
875 {
876 DE_UNREF(numTargetSamples);
877
878 std::ostringstream buf;
879
880 buf << "${GLSL_VERSION_DECL}\n"
881 "in highp vec4 a_position;\n"
882 "in highp vec4 a_barycentricsA;\n"
883 "in highp vec4 a_barycentricsB;\n"
884 "out highp vec3 v_barycentricsA;\n"
885 "centroid out highp vec3 v_barycentricsB;\n"
886 "void main (void)\n"
887 "{\n"
888 " gl_Position = a_position;\n"
889 " v_barycentricsA = a_barycentricsA.xyz;\n"
890 " v_barycentricsB = a_barycentricsB.xyz;\n"
891 "}\n";
892
893 return specializeShader(buf.str(), m_context.getRenderContext().getType());
894 }
895
896 std::string CentroidQualifierAtSampleCase::genFragmentSource (int numTargetSamples) const
897 {
898 DE_UNREF(numTargetSamples);
899
900 std::ostringstream buf;
901
902 buf << "${GLSL_VERSION_DECL}\n"
903 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
904 "in highp vec3 v_barycentricsA;\n"
905 "centroid in highp vec3 v_barycentricsB;\n"
906 "layout(location = 0) out mediump vec4 fragColor;\n"
907 "void main (void)\n"
908 "{\n"
909 " const highp float threshold = 0.0005;\n"
910 " bool allOk = true;\n"
911 "\n"
912 " for (int sampleNdx = 0; sampleNdx < " << numTargetSamples << "; ++sampleNdx)\n"
913 " {\n"
914 " highp vec3 sampleA = interpolateAtSample(v_barycentricsA, sampleNdx);\n"
915 " highp vec3 sampleB = interpolateAtSample(v_barycentricsB, sampleNdx);\n"
916 " bool valuesEqual = all(lessThan(abs(sampleA - sampleB), vec3(threshold)));\n"
917 " if (!valuesEqual)\n"
918 " allOk = false;\n"
919 " }\n"
920 "\n"
921 " if (allOk)\n"
922 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
923 " else\n"
924 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
925 "}\n";
926
927 return specializeShader(buf.str(), m_context.getRenderContext().getType());
928 }
929
930 bool CentroidQualifierAtSampleCase::verifyImage (const tcu::Surface& resultImage)
931 {
932 return verifyGreenImage(resultImage, m_testCtx.getLog());
933 }
934
935 class InterpolateAtSampleIDCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
936 {
937 public:
938 InterpolateAtSampleIDCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
939 virtual ~InterpolateAtSampleIDCase (void);
940
941 void init (void);
942 private:
943 enum
944 {
945 RENDER_SIZE = 32
946 };
947
948 std::string genVertexSource (int numTargetSamples) const;
949 std::string genFragmentSource (int numTargetSamples) const;
950 bool verifyImage (const tcu::Surface& resultImage);
951 };
952
953 InterpolateAtSampleIDCase::InterpolateAtSampleIDCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
954 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE)
955 {
956 }
957
958 InterpolateAtSampleIDCase::~InterpolateAtSampleIDCase (void)
959 {
960 }
961
962 void InterpolateAtSampleIDCase::init (void)
963 {
964 // requirements
965 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
966 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
967 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables"))
968 TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_variables extension");
969
970 // test purpose and expectations
971 m_testCtx.getLog()
972 << tcu::TestLog::Message
973 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
974 << " Interpolate varying containing screen space location.\n"
975 << " => interpolateAtSample(varying, sampleID) = varying"
976 << tcu::TestLog::EndMessage;
977
978 MultisampleShaderRenderUtil::MultisampleRenderCase::init();
979 }
980
981 std::string InterpolateAtSampleIDCase::genVertexSource (int numTargetSamples) const
982 {
983 DE_UNREF(numTargetSamples);
984
985 std::ostringstream buf;
986
987 buf << "${GLSL_VERSION_DECL}\n"
988 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
989 "in highp vec4 a_position;\n"
990 "sample out highp vec2 v_screenPosition;\n"
991 "void main (void)\n"
992 "{\n"
993 " gl_Position = a_position;\n"
994 " v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n"
995 "}\n";
996
997 return specializeShader(buf.str(), m_context.getRenderContext().getType());
998 }
999
1000 std::string InterpolateAtSampleIDCase::genFragmentSource (int numTargetSamples) const
1001 {
1002 DE_UNREF(numTargetSamples);
1003
1004 std::ostringstream buf;
1005
1006 buf << "${GLSL_VERSION_DECL}\n"
1007 "${GLSL_EXT_SAMPLE_VARIABLES}"
1008 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1009 "sample in highp vec2 v_screenPosition;\n"
1010 "layout(location = 0) out mediump vec4 fragColor;\n"
1011 "void main (void)\n"
1012 "{\n"
1013 " const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
1014 "\n"
1015 " highp vec2 offsetValue = interpolateAtSample(v_screenPosition, gl_SampleID);\n"
1016 " highp vec2 refValue = v_screenPosition;\n"
1017 "\n"
1018 " bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n"
1019 " if (valuesEqual)\n"
1020 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1021 " else\n"
1022 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1023 "}\n";
1024
1025 return specializeShader(buf.str(), m_context.getRenderContext().getType());
1026 }
1027
1028 bool InterpolateAtSampleIDCase::verifyImage (const tcu::Surface& resultImage)
1029 {
1030 return verifyGreenImage(resultImage, m_testCtx.getLog());
1031 }
1032
1033 class InterpolateAtCentroidCase : public CentroidRenderCase
1034 {
1035 public:
1036 enum TestType
1037 {
1038 TEST_CONSISTENCY = 0,
1039 TEST_ARRAY_ELEMENT,
1040
1041 TEST_LAST
1042 };
1043
1044 InterpolateAtCentroidCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType type);
1045 virtual ~InterpolateAtCentroidCase (void);
1046
1047 void init (void);
1048
1049 private:
1050 enum
1051 {
1052 RENDER_SIZE = 128
1053 };
1054
1055 std::string genVertexSource (int numTargetSamples) const;
1056 std::string genFragmentSource (int numTargetSamples) const;
1057 bool verifyImage (const tcu::Surface& resultImage);
1058
1059 const TestType m_type;
1060 };
1061
1062 InterpolateAtCentroidCase::InterpolateAtCentroidCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType type)
1063 : CentroidRenderCase (context, name, description, numSamples, target, RENDER_SIZE)
1064 , m_type (type)
1065 {
1066 }
1067
1068 InterpolateAtCentroidCase::~InterpolateAtCentroidCase (void)
1069 {
1070 }
1071
1072 void InterpolateAtCentroidCase::init (void)
1073 {
1074 // test purpose and expectations
1075 if (m_type == TEST_CONSISTENCY)
1076 {
1077 m_testCtx.getLog()
1078 << tcu::TestLog::Message
1079 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid-qualified varying.\n"
1080 << " Draw a fan of narrow triangles (large number of pixels on the edges).\n"
1081 << " Set varyings 'barycentricsA' and 'barycentricsB' to contain barycentric coordinates.\n"
1082 << " Add centroid-qualifier for barycentricsB.\n"
1083 << " => interpolateAtCentroid(barycentricsA) ~= barycentricsB\n"
1084 << tcu::TestLog::EndMessage;
1085 }
1086 else if (m_type == TEST_ARRAY_ELEMENT)
1087 {
1088 m_testCtx.getLog()
1089 << tcu::TestLog::Message
1090 << "Testing interpolateAtCentroid with element of array as an argument."
1091 << tcu::TestLog::EndMessage;
1092 }
1093 else
1094 DE_ASSERT(false);
1095
1096 CentroidRenderCase::init();
1097 }
1098
1099 std::string InterpolateAtCentroidCase::genVertexSource (int numTargetSamples) const
1100 {
1101 DE_UNREF(numTargetSamples);
1102
1103 std::ostringstream buf;
1104
1105 if (m_type == TEST_CONSISTENCY)
1106 buf << "${GLSL_VERSION_DECL}\n"
1107 "in highp vec4 a_position;\n"
1108 "in highp vec4 a_barycentricsA;\n"
1109 "in highp vec4 a_barycentricsB;\n"
1110 "out highp vec3 v_barycentricsA;\n"
1111 "centroid out highp vec3 v_barycentricsB;\n"
1112 "void main (void)\n"
1113 "{\n"
1114 " gl_Position = a_position;\n"
1115 " v_barycentricsA = a_barycentricsA.xyz;\n"
1116 " v_barycentricsB = a_barycentricsB.xyz;\n"
1117 "}\n";
1118 else if (m_type == TEST_ARRAY_ELEMENT)
1119 buf << "${GLSL_VERSION_DECL}\n"
1120 "in highp vec4 a_position;\n"
1121 "in highp vec4 a_barycentricsA;\n"
1122 "in highp vec4 a_barycentricsB;\n"
1123 "out highp vec3[2] v_barycentrics;\n"
1124 "void main (void)\n"
1125 "{\n"
1126 " gl_Position = a_position;\n"
1127 " v_barycentrics[0] = a_barycentricsA.xyz;\n"
1128 " v_barycentrics[1] = a_barycentricsB.xyz;\n"
1129 "}\n";
1130 else
1131 DE_ASSERT(false);
1132
1133 return specializeShader(buf.str(), m_context.getRenderContext().getType());
1134 }
1135
1136 std::string InterpolateAtCentroidCase::genFragmentSource (int numTargetSamples) const
1137 {
1138 DE_UNREF(numTargetSamples);
1139
1140 std::ostringstream buf;
1141
1142 if (m_type == TEST_CONSISTENCY)
1143 buf << "${GLSL_VERSION_DECL}\n"
1144 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1145 "in highp vec3 v_barycentricsA;\n"
1146 "centroid in highp vec3 v_barycentricsB;\n"
1147 "layout(location = 0) out highp vec4 fragColor;\n"
1148 "void main (void)\n"
1149 "{\n"
1150 " const highp float threshold = 0.0005;\n"
1151 "\n"
1152 " highp vec3 centroidASampled = interpolateAtCentroid(v_barycentricsA);\n"
1153 " bool valuesEqual = all(lessThan(abs(centroidASampled - v_barycentricsB), vec3(threshold)));\n"
1154 " bool centroidAIsInvalid = any(greaterThan(centroidASampled, vec3(1.0))) ||\n"
1155 " any(lessThan(centroidASampled, vec3(0.0)));\n"
1156 " bool centroidBIsInvalid = any(greaterThan(v_barycentricsB, vec3(1.0))) ||\n"
1157 " any(lessThan(v_barycentricsB, vec3(0.0)));\n"
1158 "\n"
1159 " if (valuesEqual && !centroidAIsInvalid && !centroidBIsInvalid)\n"
1160 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1161 " else if (centroidAIsInvalid || centroidBIsInvalid)\n"
1162 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1163 " else\n"
1164 " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1165 "}\n";
1166 else if (m_type == TEST_ARRAY_ELEMENT)
1167 buf << "${GLSL_VERSION_DECL}\n"
1168 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1169 "in highp vec3[2] v_barycentrics;\n"
1170 "layout(location = 0) out mediump vec4 fragColor;\n"
1171 "void main (void)\n"
1172 "{\n"
1173 " const highp float threshold = 0.0005;\n"
1174 "\n"
1175 " highp vec3 centroidInterpolated = interpolateAtCentroid(v_barycentrics[1]);\n"
1176 " bool centroidIsInvalid = any(greaterThan(centroidInterpolated, vec3(1.0))) ||\n"
1177 " any(lessThan(centroidInterpolated, vec3(0.0)));\n"
1178 "\n"
1179 " if (!centroidIsInvalid)\n"
1180 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1181 " else\n"
1182 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1183 "}\n";
1184 else
1185 DE_ASSERT(false);
1186
1187 return specializeShader(buf.str(), m_context.getRenderContext().getType());
1188 }
1189
1190 bool InterpolateAtCentroidCase::verifyImage (const tcu::Surface& resultImage)
1191 {
1192 return verifyGreenImage(resultImage, m_testCtx.getLog());
1193 }
1194
1195 class InterpolateAtOffsetCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
1196 {
1197 public:
1198 enum TestType
1199 {
1200 TEST_QUALIFIER_NONE = 0,
1201 TEST_QUALIFIER_CENTROID,
1202 TEST_QUALIFIER_SAMPLE,
1203 TEST_ARRAY_ELEMENT,
1204
1205 TEST_LAST
1206 };
1207 InterpolateAtOffsetCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType testType);
1208 virtual ~InterpolateAtOffsetCase (void);
1209
1210 void init (void);
1211 private:
1212 enum
1213 {
1214 RENDER_SIZE = 32
1215 };
1216
1217 std::string genVertexSource (int numTargetSamples) const;
1218 std::string genFragmentSource (int numTargetSamples) const;
1219 bool verifyImage (const tcu::Surface& resultImage);
1220
1221 const TestType m_testType;
1222 };
1223
1224 InterpolateAtOffsetCase::InterpolateAtOffsetCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType testType)
1225 : MultisampleShaderRenderUtil::MultisampleRenderCase (context, name, description, numSamples, target, RENDER_SIZE)
1226 , m_testType (testType)
1227 {
1228 DE_ASSERT(testType < TEST_LAST);
1229 }
1230
1231 InterpolateAtOffsetCase::~InterpolateAtOffsetCase (void)
1232 {
1233 }
1234
1235 void InterpolateAtOffsetCase::init (void)
1236 {
1237 // requirements
1238 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
1239 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
1240
1241 // test purpose and expectations
1242 m_testCtx.getLog()
1243 << tcu::TestLog::Message
1244 << "Verifying that interpolateAtOffset returns correct values.\n"
1245 << " Interpolate varying containing screen space location.\n"
1246 << " => interpolateAtOffset(varying, offset) should be \"varying value at the pixel center\" + offset"
1247 << tcu::TestLog::EndMessage;
1248
1249 MultisampleShaderRenderUtil::MultisampleRenderCase::init();
1250 }
1251
1252 std::string InterpolateAtOffsetCase::genVertexSource (int numTargetSamples) const
1253 {
1254 DE_UNREF(numTargetSamples);
1255
1256 std::ostringstream buf;
1257 buf << "${GLSL_VERSION_DECL}\n"
1258 << "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1259 << "in highp vec4 a_position;\n";
1260
1261 if (m_testType == TEST_QUALIFIER_NONE || m_testType == TEST_QUALIFIER_CENTROID || m_testType == TEST_QUALIFIER_SAMPLE)
1262 {
1263 const char* const qualifier = (m_testType == TEST_QUALIFIER_CENTROID) ? ("centroid ") : (m_testType == TEST_QUALIFIER_SAMPLE) ? ("sample ") : ("");
1264 buf << qualifier << "out highp vec2 v_screenPosition;\n"
1265 << qualifier << "out highp vec2 v_offset;\n";
1266 }
1267 else if (m_testType == TEST_ARRAY_ELEMENT)
1268 {
1269 buf << "out highp vec2[2] v_screenPosition;\n"
1270 << "out highp vec2 v_offset;\n";
1271 }
1272 else
1273 DE_ASSERT(false);
1274
1275 buf << "void main (void)\n"
1276 << "{\n"
1277 << " gl_Position = a_position;\n";
1278
1279 if (m_testType != TEST_ARRAY_ELEMENT)
1280 buf << " v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n";
1281 else
1282 buf << " v_screenPosition[0] = a_position.xy; // not used\n"
1283 " v_screenPosition[1] = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n";
1284
1285 buf << " v_offset = a_position.xy * 0.5f;\n"
1286 << "}\n";
1287
1288 return specializeShader(buf.str(), m_context.getRenderContext().getType());
1289 }
1290
1291 std::string InterpolateAtOffsetCase::genFragmentSource (int numTargetSamples) const
1292 {
1293 DE_UNREF(numTargetSamples);
1294
1295 const char* const arrayIndexing = (m_testType == TEST_ARRAY_ELEMENT) ? ("[1]") : ("");
1296 std::ostringstream buf;
1297
1298 buf << "${GLSL_VERSION_DECL}\n"
1299 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}";
1300
1301 if (m_testType == TEST_QUALIFIER_NONE || m_testType == TEST_QUALIFIER_CENTROID || m_testType == TEST_QUALIFIER_SAMPLE)
1302 {
1303 const char* const qualifier = (m_testType == TEST_QUALIFIER_CENTROID) ? ("centroid ") : (m_testType == TEST_QUALIFIER_SAMPLE) ? ("sample ") : ("");
1304 buf << qualifier << "in highp vec2 v_screenPosition;\n"
1305 << qualifier << "in highp vec2 v_offset;\n";
1306 }
1307 else if (m_testType == TEST_ARRAY_ELEMENT)
1308 {
1309 buf << "in highp vec2[2] v_screenPosition;\n"
1310 << "in highp vec2 v_offset;\n";
1311 }
1312 else
1313 DE_ASSERT(false);
1314
1315 buf << "layout(location = 0) out mediump vec4 fragColor;\n"
1316 "void main (void)\n"
1317 "{\n"
1318 " const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
1319 "\n"
1320 " highp vec2 pixelCenter = floor(v_screenPosition" << arrayIndexing << ") + vec2(0.5, 0.5);\n"
1321 " highp vec2 offsetValue = interpolateAtOffset(v_screenPosition" << arrayIndexing << ", v_offset);\n"
1322 " highp vec2 refValue = pixelCenter + v_offset;\n"
1323 "\n"
1324 " bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n"
1325 " if (valuesEqual)\n"
1326 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1327 " else\n"
1328 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1329 "}\n";
1330
1331 return specializeShader(buf.str(), m_context.getRenderContext().getType());
1332 }
1333
1334 bool InterpolateAtOffsetCase::verifyImage (const tcu::Surface& resultImage)
1335 {
1336 return verifyGreenImage(resultImage, m_testCtx.getLog());
1337 }
1338
1339 class InterpolateAtSamplePositionCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
1340 {
1341 public:
1342 InterpolateAtSamplePositionCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target);
1343 virtual ~InterpolateAtSamplePositionCase (void);
1344
1345 void init (void);
1346 private:
1347 enum
1348 {
1349 RENDER_SIZE = 32
1350 };
1351
1352 std::string genVertexSource (int numTargetSamples) const;
1353 std::string genFragmentSource (int numTargetSamples) const;
1354 bool verifyImage (const tcu::Surface& resultImage);
1355 };
1356
1357 InterpolateAtSamplePositionCase::InterpolateAtSamplePositionCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target)
1358 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE)
1359 {
1360 }
1361
1362 InterpolateAtSamplePositionCase::~InterpolateAtSamplePositionCase (void)
1363 {
1364 }
1365
1366 void InterpolateAtSamplePositionCase::init (void)
1367 {
1368 // requirements
1369 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
1370 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
1371 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables"))
1372 TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_variables extension");
1373
1374 // test purpose and expectations
1375 m_testCtx.getLog()
1376 << tcu::TestLog::Message
1377 << "Verifying that interpolateAtOffset with the offset of current sample position returns consistent values.\n"
1378 << " Interpolate varying containing screen space location.\n"
1379 << " => interpolateAtOffset(varying, currentOffset) = varying"
1380 << tcu::TestLog::EndMessage;
1381
1382 MultisampleShaderRenderUtil::MultisampleRenderCase::init();
1383 }
1384
1385 std::string InterpolateAtSamplePositionCase::genVertexSource (int numTargetSamples) const
1386 {
1387 DE_UNREF(numTargetSamples);
1388
1389 std::ostringstream buf;
1390
1391 buf << "${GLSL_VERSION_DECL}\n"
1392 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1393 "in highp vec4 a_position;\n"
1394 "sample out highp vec2 v_screenPosition;\n"
1395 "void main (void)\n"
1396 "{\n"
1397 " gl_Position = a_position;\n"
1398 " v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n"
1399 "}\n";
1400
1401 return specializeShader(buf.str(), m_context.getRenderContext().getType());
1402 }
1403
1404 std::string InterpolateAtSamplePositionCase::genFragmentSource (int numTargetSamples) const
1405 {
1406 DE_UNREF(numTargetSamples);
1407
1408 std::ostringstream buf;
1409
1410 buf << "${GLSL_VERSION_DECL}\n"
1411 "${GLSL_EXT_SAMPLE_VARIABLES}"
1412 "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1413 "sample in highp vec2 v_screenPosition;\n"
1414 "layout(location = 0) out mediump vec4 fragColor;\n"
1415 "void main (void)\n"
1416 "{\n"
1417 " const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
1418 "\n"
1419 " highp vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n"
1420 " highp vec2 offsetValue = interpolateAtOffset(v_screenPosition, offset);\n"
1421 " highp vec2 refValue = v_screenPosition;\n"
1422 "\n"
1423 " bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n"
1424 " if (valuesEqual)\n"
1425 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1426 " else\n"
1427 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1428 "}\n";
1429
1430 return specializeShader(buf.str(), m_context.getRenderContext().getType());
1431 }
1432
1433 bool InterpolateAtSamplePositionCase::verifyImage (const tcu::Surface& resultImage)
1434 {
1435 return verifyGreenImage(resultImage, m_testCtx.getLog());
1436 }
1437
1438 class NegativeCompileInterpolationCase : public TestCase
1439 {
1440 public:
1441 enum CaseType
1442 {
1443 CASE_VEC4_IDENTITY_SWIZZLE = 0,
1444 CASE_VEC4_CROP_SWIZZLE,
1445 CASE_VEC4_MIXED_SWIZZLE,
1446 CASE_INTERPOLATE_IVEC4,
1447 CASE_INTERPOLATE_UVEC4,
1448 CASE_INTERPOLATE_ARRAY,
1449 CASE_INTERPOLATE_STRUCT,
1450 CASE_INTERPOLATE_STRUCT_MEMBER,
1451 CASE_INTERPOLATE_LOCAL,
1452 CASE_INTERPOLATE_GLOBAL,
1453 CASE_INTERPOLATE_CONSTANT,
1454
1455 CASE_LAST
1456 };
1457 enum InterpolatorType
1458 {
1459 INTERPOLATE_AT_SAMPLE = 0,
1460 INTERPOLATE_AT_CENTROID,
1461 INTERPOLATE_AT_OFFSET,
1462
1463 INTERPOLATE_LAST
1464 };
1465
1466 NegativeCompileInterpolationCase (Context& context, const char* name, const char* description, CaseType caseType, InterpolatorType interpolator);
1467
1468 private:
1469 void init (void);
1470 IterateResult iterate (void);
1471
1472 std::string genShaderSource (void) const;
1473
1474 const CaseType m_caseType;
1475 const InterpolatorType m_interpolation;
1476 };
1477
1478 NegativeCompileInterpolationCase::NegativeCompileInterpolationCase (Context& context, const char* name, const char* description, CaseType caseType, InterpolatorType interpolator)
1479 : TestCase (context, name, description)
1480 , m_caseType (caseType)
1481 , m_interpolation (interpolator)
1482 {
1483 DE_ASSERT(m_caseType < CASE_LAST);
1484 DE_ASSERT(m_interpolation < INTERPOLATE_LAST);
1485 }
1486
1487 void NegativeCompileInterpolationCase::init (void)
1488 {
1489 if (!checkSupport(m_context) && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
1490 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension");
1491
1492 if(!glu::isContextTypeES(m_context.getRenderContext().getType()))
1493 {
1494 if(m_caseType == CASE_VEC4_IDENTITY_SWIZZLE
1495 || m_caseType == CASE_VEC4_CROP_SWIZZLE
1496 || m_caseType == CASE_VEC4_MIXED_SWIZZLE
1497 || m_caseType == CASE_INTERPOLATE_IVEC4
1498 || m_caseType == CASE_INTERPOLATE_UVEC4
1499 || m_caseType == CASE_INTERPOLATE_STRUCT_MEMBER)
1500 TCU_THROW(NotSupportedError, "Test requires a GLES context");
1501 }
1502
1503 m_testCtx.getLog() << tcu::TestLog::Message << "Trying to compile illegal shader, expecting compile to fail." << tcu::TestLog::EndMessage;
1504 }
1505
1506 NegativeCompileInterpolationCase::IterateResult NegativeCompileInterpolationCase::iterate (void)
1507 {
1508 const std::string source = genShaderSource();
1509 glu::Shader shader (m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
1510 const char* const sourceStrPtr = source.c_str();
1511
1512 m_testCtx.getLog() << tcu::TestLog::Message
1513 << "Fragment shader source:"
1514 << tcu::TestLog::EndMessage
1515 << tcu::TestLog::KernelSource(source);
1516
1517 shader.setSources(1, &sourceStrPtr, DE_NULL);
1518 shader.compile();
1519
1520 m_testCtx.getLog() << tcu::TestLog::Message
1521 << "Info log:"
1522 << tcu::TestLog::EndMessage
1523 << tcu::TestLog::KernelSource(shader.getInfoLog());
1524
1525 if (shader.getCompileStatus())
1526 {
1527 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Illegal shader compiled successfully." << tcu::TestLog::EndMessage;
1528 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected compile status");
1529 }
1530 else
1531 {
1532 m_testCtx.getLog() << tcu::TestLog::Message << "Compile failed as expected." << tcu::TestLog::EndMessage;
1533 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1534 }
1535 return STOP;
1536 }
1537
1538 std::string NegativeCompileInterpolationCase::genShaderSource (void) const
1539 {
1540 std::ostringstream buf;
1541 std::string interpolation;
1542 const char* interpolationTemplate;
1543 const char* description;
1544 const char* globalDeclarations = "";
1545 const char* localDeclarations = "";
1546 const char* interpolationTarget = "";
1547 const char* postSelector = "";
1548
1549 switch (m_caseType)
1550 {
1551 case CASE_VEC4_IDENTITY_SWIZZLE:
1552 globalDeclarations = "in highp vec4 v_var;\n";
1553 interpolationTarget = "v_var.xyzw";
1554 description = "component selection is illegal";
1555 break;
1556
1557 case CASE_VEC4_CROP_SWIZZLE:
1558 globalDeclarations = "in highp vec4 v_var;\n";
1559 interpolationTarget = "v_var.xy";
1560 postSelector = ".x";
1561 description = "component selection is illegal";
1562 break;
1563
1564 case CASE_VEC4_MIXED_SWIZZLE:
1565 globalDeclarations = "in highp vec4 v_var;\n";
1566 interpolationTarget = "v_var.yzxw";
1567 description = "component selection is illegal";
1568 break;
1569
1570 case CASE_INTERPOLATE_IVEC4:
1571 globalDeclarations = "flat in highp ivec4 v_var;\n";
1572 interpolationTarget = "v_var";
1573 description = "no overload for ivec";
1574 break;
1575
1576 case CASE_INTERPOLATE_UVEC4:
1577 globalDeclarations = "flat in highp uvec4 v_var;\n";
1578 interpolationTarget = "v_var";
1579 description = "no overload for uvec";
1580 break;
1581
1582 case CASE_INTERPOLATE_ARRAY:
1583 globalDeclarations = "in highp float v_var[2];\n";
1584 interpolationTarget = "v_var";
1585 postSelector = "[1]";
1586 description = "no overload for arrays";
1587 break;
1588
1589 case CASE_INTERPOLATE_STRUCT:
1590 case CASE_INTERPOLATE_STRUCT_MEMBER:
1591 globalDeclarations = "struct S\n"
1592 "{\n"
1593 " highp float a;\n"
1594 " highp float b;\n"
1595 "};\n"
1596 "in S v_var;\n";
1597
1598 interpolationTarget = (m_caseType == CASE_INTERPOLATE_STRUCT) ? ("v_var") : ("v_var.a");
1599 postSelector = (m_caseType == CASE_INTERPOLATE_STRUCT) ? (".a") : ("");
1600 description = (m_caseType == CASE_INTERPOLATE_STRUCT) ? ("no overload for this type") : ("<interpolant> is not an input variable (just a member of)");
1601 break;
1602
1603 case CASE_INTERPOLATE_LOCAL:
1604 localDeclarations = " highp vec4 local_var = gl_FragCoord;\n";
1605 interpolationTarget = "local_var";
1606 description = "<interpolant> is not an input variable";
1607 break;
1608
1609 case CASE_INTERPOLATE_GLOBAL:
1610 globalDeclarations = "highp vec4 global_var;\n";
1611 localDeclarations = " global_var = gl_FragCoord;\n";
1612 interpolationTarget = "global_var";
1613 description = "<interpolant> is not an input variable";
1614 break;
1615
1616 case CASE_INTERPOLATE_CONSTANT:
1617 globalDeclarations = "const highp vec4 const_var = vec4(0.2);\n";
1618 interpolationTarget = "const_var";
1619 description = "<interpolant> is not an input variable";
1620 break;
1621
1622 default:
1623 DE_ASSERT(false);
1624 return "";
1625 }
1626
1627 switch (m_interpolation)
1628 {
1629 case INTERPOLATE_AT_SAMPLE:
1630 interpolationTemplate = "interpolateAtSample(${TARGET}, 0)${POST_SELECTOR}";
1631 break;
1632
1633 case INTERPOLATE_AT_CENTROID:
1634 interpolationTemplate = "interpolateAtCentroid(${TARGET})${POST_SELECTOR}";
1635 break;
1636
1637 case INTERPOLATE_AT_OFFSET:
1638 interpolationTemplate = "interpolateAtOffset(${TARGET}, vec2(0.2, 0.2))${POST_SELECTOR}";
1639 break;
1640
1641 default:
1642 DE_ASSERT(false);
1643 return "";
1644 }
1645
1646 {
1647 std::map<std::string, std::string> args;
1648 args["TARGET"] = interpolationTarget;
1649 args["POST_SELECTOR"] = postSelector;
1650
1651 interpolation = tcu::StringTemplate(interpolationTemplate).specialize(args);
1652 }
1653
1654 buf << glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType())) << "\n"
1655 << "${GLSL_EXT_SHADER_MULTISAMPLE_INTERPOLATION}"
1656 << globalDeclarations
1657 << "layout(location = 0) out mediump vec4 fragColor;\n"
1658 "void main (void)\n"
1659 "{\n"
1660 << localDeclarations
1661 << " fragColor = vec4(" << interpolation << "); // " << description << "\n"
1662 "}\n";
1663
1664 return specializeShader(buf.str(), m_context.getRenderContext().getType());
1665 }
1666
1667 } // anonymous
1668
1669 ShaderMultisampleInterpolationTests::ShaderMultisampleInterpolationTests (Context& context)
1670 : TestCaseGroup(context, "multisample_interpolation", "Test multisample interpolation")
1671 {
1672 }
1673
1674 ShaderMultisampleInterpolationTests::~ShaderMultisampleInterpolationTests (void)
1675 {
1676 }
1677
1678 void ShaderMultisampleInterpolationTests::init (void)
1679 {
1680 using namespace MultisampleShaderRenderUtil;
1681
1682 static const struct RenderTarget
1683 {
1684 const char* name;
1685 const char* desc;
1686 int numSamples;
1687 MultisampleRenderCase::RenderTarget target;
1688 } targets[] =
1689 {
1690 { "default_framebuffer", "Test with default framebuffer", 0, MultisampleRenderCase::TARGET_DEFAULT },
1691 { "singlesample_texture", "Test with singlesample texture", 0, MultisampleRenderCase::TARGET_TEXTURE },
1692 { "multisample_texture_1", "Test with multisample texture", 1, MultisampleRenderCase::TARGET_TEXTURE },
1693 { "multisample_texture_2", "Test with multisample texture", 2, MultisampleRenderCase::TARGET_TEXTURE },
1694 { "multisample_texture_4", "Test with multisample texture", 4, MultisampleRenderCase::TARGET_TEXTURE },
1695 { "multisample_texture_8", "Test with multisample texture", 8, MultisampleRenderCase::TARGET_TEXTURE },
1696 { "multisample_texture_16", "Test with multisample texture", 16, MultisampleRenderCase::TARGET_TEXTURE },
1697 { "singlesample_rbo", "Test with singlesample rbo", 0, MultisampleRenderCase::TARGET_RENDERBUFFER },
1698 { "multisample_rbo_1", "Test with multisample rbo", 1, MultisampleRenderCase::TARGET_RENDERBUFFER },
1699 { "multisample_rbo_2", "Test with multisample rbo", 2, MultisampleRenderCase::TARGET_RENDERBUFFER },
1700 { "multisample_rbo_4", "Test with multisample rbo", 4, MultisampleRenderCase::TARGET_RENDERBUFFER },
1701 { "multisample_rbo_8", "Test with multisample rbo", 8, MultisampleRenderCase::TARGET_RENDERBUFFER },
1702 { "multisample_rbo_16", "Test with multisample rbo", 16, MultisampleRenderCase::TARGET_RENDERBUFFER },
1703 };
1704
1705 static const struct
1706 {
1707 const char* name;
1708 const char* description;
1709 NegativeCompileInterpolationCase::CaseType caseType;
1710 } negativeCompileCases[] =
1711 {
1712 { "vec4_identity_swizzle", "use identity swizzle", NegativeCompileInterpolationCase::CASE_VEC4_IDENTITY_SWIZZLE },
1713 { "vec4_crop_swizzle", "use cropped identity swizzle", NegativeCompileInterpolationCase::CASE_VEC4_CROP_SWIZZLE },
1714 { "vec4_mixed_swizzle", "use swizzle", NegativeCompileInterpolationCase::CASE_VEC4_MIXED_SWIZZLE },
1715 { "interpolate_ivec4", "interpolate integer variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_IVEC4 },
1716 { "interpolate_uvec4", "interpolate integer variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_UVEC4 },
1717 { "interpolate_array", "interpolate whole array", NegativeCompileInterpolationCase::CASE_INTERPOLATE_ARRAY },
1718 { "interpolate_struct", "interpolate whole struct", NegativeCompileInterpolationCase::CASE_INTERPOLATE_STRUCT },
1719 { "interpolate_struct_member", "interpolate struct member", NegativeCompileInterpolationCase::CASE_INTERPOLATE_STRUCT_MEMBER },
1720 { "interpolate_local", "interpolate local variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_LOCAL },
1721 { "interpolate_global", "interpolate global variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_GLOBAL },
1722 { "interpolate_constant", "interpolate constant variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_CONSTANT },
1723 };
1724
1725 // .sample_qualifier
1726 {
1727 tcu::TestCaseGroup* const sampleQualifierGroup = new tcu::TestCaseGroup(m_testCtx, "sample_qualifier", "Test sample qualifier");
1728 addChild(sampleQualifierGroup);
1729
1730 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1731 sampleQualifierGroup->addChild(new SampleQualifierRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
1732 }
1733
1734 // .interpolate_at_sample
1735 {
1736 tcu::TestCaseGroup* const interpolateAtSampleGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_sample", "Test interpolateAtSample");
1737 addChild(interpolateAtSampleGroup);
1738
1739 // .static_sample_number
1740 {
1741 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "static_sample_number", "Test interpolateAtSample sample number");
1742 interpolateAtSampleGroup->addChild(group);
1743
1744 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1745 group->addChild(new InterpolateAtSampleRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtSampleRenderCase::INDEXING_STATIC));
1746 }
1747
1748 // .dynamic_sample_number
1749 {
1750 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "dynamic_sample_number", "Test interpolateAtSample sample number");
1751 interpolateAtSampleGroup->addChild(group);
1752
1753 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1754 group->addChild(new InterpolateAtSampleRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtSampleRenderCase::INDEXING_DYNAMIC));
1755 }
1756
1757 // .non_multisample_buffer
1758 {
1759 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "non_multisample_buffer", "Test interpolateAtSample with non-multisample buffers");
1760 interpolateAtSampleGroup->addChild(group);
1761
1762 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1763 if (targets[targetNdx].numSamples == 0)
1764 group->addChild(new SingleSampleInterpolateAtSampleCase(m_context, std::string("sample_0_").append(targets[targetNdx].name).c_str(), targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SingleSampleInterpolateAtSampleCase::SAMPLE_0));
1765
1766 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1767 if (targets[targetNdx].numSamples == 0)
1768 group->addChild(new SingleSampleInterpolateAtSampleCase(m_context, std::string("sample_n_").append(targets[targetNdx].name).c_str(), targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SingleSampleInterpolateAtSampleCase::SAMPLE_N));
1769 }
1770
1771 // .centroid_qualifier
1772 {
1773 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "centroid_qualified", "Test interpolateAtSample with centroid qualified varying");
1774 interpolateAtSampleGroup->addChild(group);
1775
1776 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1777 group->addChild(new CentroidQualifierAtSampleCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
1778 }
1779
1780 // .at_sample_id
1781 {
1782 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "at_sample_id", "Test interpolateAtSample at current sample id");
1783 interpolateAtSampleGroup->addChild(group);
1784
1785 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1786 group->addChild(new InterpolateAtSampleIDCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
1787 }
1788
1789 // .negative
1790 {
1791 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtSample negative tests");
1792 interpolateAtSampleGroup->addChild(group);
1793
1794 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx)
1795 group->addChild(new NegativeCompileInterpolationCase(m_context,
1796 negativeCompileCases[ndx].name,
1797 negativeCompileCases[ndx].description,
1798 negativeCompileCases[ndx].caseType,
1799 NegativeCompileInterpolationCase::INTERPOLATE_AT_SAMPLE));
1800 }
1801 }
1802
1803 // .interpolate_at_centroid
1804 {
1805 tcu::TestCaseGroup* const methodGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_centroid", "Test interpolateAtCentroid");
1806 addChild(methodGroup);
1807
1808 // .consistency
1809 {
1810 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "consistency", "Test interpolateAtCentroid return value is consistent to centroid qualified value");
1811 methodGroup->addChild(group);
1812
1813 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1814 group->addChild(new InterpolateAtCentroidCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtCentroidCase::TEST_CONSISTENCY));
1815 }
1816
1817 // .array_element
1818 {
1819 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "array_element", "Test interpolateAtCentroid with array element");
1820 methodGroup->addChild(group);
1821
1822 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1823 group->addChild(new InterpolateAtCentroidCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtCentroidCase::TEST_ARRAY_ELEMENT));
1824 }
1825
1826 // .negative
1827 {
1828 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtCentroid negative tests");
1829 methodGroup->addChild(group);
1830
1831 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx)
1832 group->addChild(new NegativeCompileInterpolationCase(m_context,
1833 negativeCompileCases[ndx].name,
1834 negativeCompileCases[ndx].description,
1835 negativeCompileCases[ndx].caseType,
1836 NegativeCompileInterpolationCase::INTERPOLATE_AT_CENTROID));
1837 }
1838 }
1839
1840 // .interpolate_at_offset
1841 {
1842 static const struct TestConfig
1843 {
1844 const char* name;
1845 InterpolateAtOffsetCase::TestType type;
1846 } configs[] =
1847 {
1848 { "no_qualifiers", InterpolateAtOffsetCase::TEST_QUALIFIER_NONE },
1849 { "centroid_qualifier", InterpolateAtOffsetCase::TEST_QUALIFIER_CENTROID },
1850 { "sample_qualifier", InterpolateAtOffsetCase::TEST_QUALIFIER_SAMPLE },
1851 };
1852
1853 tcu::TestCaseGroup* const methodGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_offset", "Test interpolateAtOffset");
1854 addChild(methodGroup);
1855
1856 // .no_qualifiers
1857 // .centroid_qualifier
1858 // .sample_qualifier
1859 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(configs); ++configNdx)
1860 {
1861 tcu::TestCaseGroup* const qualifierGroup = new tcu::TestCaseGroup(m_testCtx, configs[configNdx].name, "Test interpolateAtOffset with qualified/non-qualified varying");
1862 methodGroup->addChild(qualifierGroup);
1863
1864 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1865 qualifierGroup->addChild(new InterpolateAtOffsetCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, configs[configNdx].type));
1866 }
1867
1868 // .at_sample_position
1869 {
1870 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "at_sample_position", "Test interpolateAtOffset at sample position");
1871 methodGroup->addChild(group);
1872
1873 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1874 group->addChild(new InterpolateAtSamplePositionCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
1875 }
1876
1877 // .array_element
1878 {
1879 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "array_element", "Test interpolateAtOffset with array element");
1880 methodGroup->addChild(group);
1881
1882 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
1883 group->addChild(new InterpolateAtOffsetCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtOffsetCase::TEST_ARRAY_ELEMENT));
1884 }
1885
1886 // .negative
1887 {
1888 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtOffset negative tests");
1889 methodGroup->addChild(group);
1890
1891 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx)
1892 group->addChild(new NegativeCompileInterpolationCase(m_context,
1893 negativeCompileCases[ndx].name,
1894 negativeCompileCases[ndx].description,
1895 negativeCompileCases[ndx].caseType,
1896 NegativeCompileInterpolationCase::INTERPOLATE_AT_OFFSET));
1897 }
1898 }
1899 }
1900
1901 } // Functional
1902 } // gles31
1903 } // deqp
1904