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