xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fShaderMultisampleInterpolationTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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