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