1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "glcShaderMultisampleInterpolationTests.hpp"
25 #include "deMath.h"
26 #include "deRandom.hpp"
27 #include "deStringUtil.hpp"
28 #include "gluContextInfo.hpp"
29 #include "gluDrawUtil.hpp"
30 #include "gluPixelTransfer.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "glw.h"
33 #include "glwFunctions.hpp"
34 #include "tcuCommandLine.hpp"
35 #include "tcuStringTemplate.hpp"
36 #include "tcuSurface.hpp"
37 #include "tcuTestLog.hpp"
38 
39 namespace tcu
40 {
operator <(tcu::Vec4 const & k1,tcu::Vec4 const & k2)41 static bool operator<(tcu::Vec4 const &k1, tcu::Vec4 const &k2)
42 {
43     if (k1.y() < k2.y())
44     {
45         return true;
46     }
47     else if (k1.y() == k2.y())
48     {
49         return k1.x() < k2.x();
50     }
51     else
52     {
53         return false;
54     }
55 }
56 } // namespace tcu
57 
58 namespace deqp
59 {
60 
61 using std::string;
62 using std::vector;
63 using tcu::TestLog;
64 
specializeVersion(std::string const & source,glu::GLSLVersion version,std::string const & sampler="",std::string const & outType="",std::string const & qualifier="",std::string const & assignment="",std::string const & condition="")65 static std::string specializeVersion(std::string const &source, glu::GLSLVersion version,
66                                      std::string const &sampler = "", std::string const &outType = "",
67                                      std::string const &qualifier = "", std::string const &assignment = "",
68                                      std::string const &condition = "")
69 {
70     DE_ASSERT(version == glu::GLSL_VERSION_310_ES || version >= glu::GLSL_VERSION_440);
71     std::map<std::string, std::string> args;
72     args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(version);
73     args["SAMPLER"]      = sampler;
74     args["OUT_TYPE"]     = outType;
75     args["QUALIFIER"]    = qualifier;
76     args["ASSIGNMENT"]   = assignment;
77     args["CONDITION"]    = condition;
78     if (version == glu::GLSL_VERSION_310_ES)
79     {
80         args["OES_SMI_EN"] = "#extension GL_OES_shader_multisample_interpolation : enable\n";
81         args["OES_SMI_RQ"] = "#extension GL_OES_shader_multisample_interpolation : require\n";
82         args["OES_SMI_CH"] = "#if !GL_OES_shader_multisample_interpolation\n"
83                              "    this is broken\n"
84                              "#endif\n";
85         args["OES_SV_EN"]  = "#extension GL_OES_sample_variables : enable\n";
86     }
87     else
88     {
89         args["OES_SMI_EN"] = "";
90         args["OES_SMI_RQ"] = "";
91         args["OES_SMI_CH"] = "";
92         args["OES_SV_EN"]  = "";
93     }
94     return tcu::StringTemplate(source.c_str()).specialize(args);
95 }
96 
97 class ShaderMultisampleInterpolationApiCase : public TestCase
98 {
99 public:
100     ShaderMultisampleInterpolationApiCase(Context &context, const char *name, const char *description,
101                                           glu::GLSLVersion glslVersion);
102     ~ShaderMultisampleInterpolationApiCase();
103 
104     IterateResult iterate();
105 
106 protected:
107     glu::GLSLVersion m_glslVersion;
108 };
109 
ShaderMultisampleInterpolationApiCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)110 ShaderMultisampleInterpolationApiCase::ShaderMultisampleInterpolationApiCase(Context &context, const char *name,
111                                                                              const char *description,
112                                                                              glu::GLSLVersion glslVersion)
113     : TestCase(context, name, description)
114     , m_glslVersion(glslVersion)
115 {
116     DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440);
117 }
118 
~ShaderMultisampleInterpolationApiCase()119 ShaderMultisampleInterpolationApiCase::~ShaderMultisampleInterpolationApiCase()
120 {
121 }
122 
iterate()123 ShaderMultisampleInterpolationApiCase::IterateResult ShaderMultisampleInterpolationApiCase::iterate()
124 {
125     TestLog &log             = m_testCtx.getLog();
126     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
127     bool isOk                = true;
128 
129     if (m_glslVersion == glu::GLSL_VERSION_310_ES &&
130         !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
131     {
132         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_shader_multisample_interpolation");
133         return STOP;
134     }
135 
136     static char const *vss = "${VERSION_DECL}\n"
137                              "${OES_SMI_RQ}"
138                              "in highp vec4 a_position;\n"
139                              "in highp vec4 a_color;\n"
140                              "sample out highp vec4 v_color;\n"
141                              "void main()\n"
142                              "{\n"
143                              "    gl_Position = a_position;\n"
144                              "}\n";
145 
146     {
147         static char const *fss = "${VERSION_DECL}\n"
148                                  "${OES_SMI_RQ}"
149                                  "sample in highp vec4 v_color;\n"
150                                  "out highp vec4 o_color;\n"
151                                  "void main()\n"
152                                  "{\n"
153                                  "    o_color = v_color;\n"
154                                  "}\n";
155 
156         glu::ShaderProgram program(m_context.getRenderContext(),
157                                    glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(),
158                                                            specializeVersion(fss, m_glslVersion).c_str()));
159         log << program;
160         if (!program.isOk())
161         {
162             TCU_FAIL("Compile failed");
163         }
164     }
165 
166     {
167         static char const *fss = "${VERSION_DECL}\n"
168                                  "${OES_SMI_EN}"
169                                  "sample in highp vec4 v_color;\n"
170                                  "out highp vec4 o_color;\n"
171                                  "void main()\n"
172                                  "{\n"
173                                  "${OES_SMI_CH}"
174                                  "    o_color = v_color;\n"
175                                  "}\n";
176 
177         glu::ShaderProgram program(m_context.getRenderContext(),
178                                    glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(),
179                                                            specializeVersion(fss, m_glslVersion).c_str()));
180         log << program;
181         if (!program.isOk())
182         {
183             TCU_FAIL("Compile failed");
184         }
185     }
186 
187     GLfloat minFragmentInterpolationOffset = 0.0f;
188     gl.getFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET, &minFragmentInterpolationOffset);
189     if (minFragmentInterpolationOffset > -0.5f)
190     {
191         isOk = false;
192     }
193 
194     GLint fragmentInterpolationOffsetBits = 0;
195     gl.getIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS, &fragmentInterpolationOffsetBits);
196     if (fragmentInterpolationOffsetBits < 4)
197     {
198         isOk = false;
199     }
200     GLfloat ULP = 1.0f / powf(2, static_cast<float>(fragmentInterpolationOffsetBits));
201 
202     GLfloat maxFragmentInterpolationOffset = 0.0f;
203     gl.getFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET, &maxFragmentInterpolationOffset);
204     if (maxFragmentInterpolationOffset < 0.5f - ULP)
205     {
206         isOk = false;
207     }
208 
209     m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
210     return STOP;
211 }
212 
213 class ShaderMultisampleInterpolationBaseCase : public TestCase
214 {
215 public:
216     ShaderMultisampleInterpolationBaseCase(Context &context, const char *name, const char *description,
217                                            glu::GLSLVersion glslVersion, char const *qualifier, char const *assignment,
218                                            char const *condition, bool unique, GLenum internalFormat,
219                                            tcu::TextureFormat const &texFormat, const char *m_sampler,
220                                            const char *m_outType, GLfloat min, GLfloat max, GLint samples);
221     ~ShaderMultisampleInterpolationBaseCase();
222 
223     IterateResult iterate();
224 
225 protected:
226     glu::GLSLVersion m_glslVersion;
227     std::string m_qualifier;
228     std::string m_assignment;
229     std::string m_condition;
230     bool m_unique;
231     GLenum m_internalFormat;
232     tcu::TextureFormat m_texFormat;
233     std::string m_sampler;
234     std::string m_outType;
235     GLfloat m_min;
236     GLfloat m_max;
237     GLint m_samples;
238 
239     enum
240     {
241         WIDTH  = 8,
242         HEIGHT = 8,
243     };
244 
245     int countUniquePixels(tcu::ConstPixelBufferAccess const &pixels);
246     int countUniquePixels(const std::vector<tcu::Vec4> &pixels);
247 };
248 
ShaderMultisampleInterpolationBaseCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion,char const * qualifier,char const * assignment,char const * condition,bool unique,GLenum internalFormat,tcu::TextureFormat const & texFormat,const char * sampler,const char * outType,GLfloat min,GLfloat max,GLint samples)249 ShaderMultisampleInterpolationBaseCase::ShaderMultisampleInterpolationBaseCase(
250     Context &context, const char *name, const char *description, glu::GLSLVersion glslVersion, char const *qualifier,
251     char const *assignment, char const *condition, bool unique, GLenum internalFormat,
252     tcu::TextureFormat const &texFormat, const char *sampler, const char *outType, GLfloat min, GLfloat max,
253     GLint samples)
254     : TestCase(context, name, description)
255     , m_glslVersion(glslVersion)
256     , m_qualifier(qualifier)
257     , m_assignment(assignment)
258     , m_condition(condition)
259     , m_unique(unique)
260     , m_internalFormat(internalFormat)
261     , m_texFormat(texFormat)
262     , m_sampler(sampler)
263     , m_outType(outType)
264     , m_min(min)
265     , m_max(max)
266     , m_samples(samples)
267 {
268     DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440);
269 }
270 
~ShaderMultisampleInterpolationBaseCase()271 ShaderMultisampleInterpolationBaseCase::~ShaderMultisampleInterpolationBaseCase()
272 {
273 }
274 
iterate()275 ShaderMultisampleInterpolationBaseCase::IterateResult ShaderMultisampleInterpolationBaseCase::iterate()
276 {
277     TestLog &log             = m_testCtx.getLog();
278     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
279     bool isOk                = true;
280     bool supportsRgba32f     = false;
281 
282     if (m_glslVersion == glu::GLSL_VERSION_310_ES &&
283         !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"))
284     {
285         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_shader_multisample_interpolation");
286         return STOP;
287     }
288 
289     supportsRgba32f = isContextTypeGLCore(m_context.getRenderContext().getType()) ?
290                           true :
291                           (m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float") ||
292                            m_context.getContextInfo().isExtensionSupported("GL_ARB_color_buffer_float"));
293 
294     if (m_internalFormat == GL_RGBA32F && !supportsRgba32f)
295     {
296         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Internalformat rgba32f not supported");
297         return STOP;
298     }
299 
300     GLint maxSamples;
301     if (((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)) ||
302         ((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RG)) ||
303         ((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::R)) ||
304         ((m_texFormat.type == tcu::TextureFormat::HALF_FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)))
305     {
306         gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, m_internalFormat, GL_SAMPLES, 1, &maxSamples);
307         if (m_samples > maxSamples)
308         {
309             m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
310                                     "Test sample count greater than samples that the format supports");
311             return STOP;
312         }
313     }
314     else if (m_texFormat.type == tcu::TextureFormat::SIGNED_INT8 ||
315              m_texFormat.type == tcu::TextureFormat::UNSIGNED_INT8)
316     {
317         gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &maxSamples);
318         if (m_samples > maxSamples)
319         {
320             m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count greater than MAX_INTEGER_SAMPLES");
321             return STOP;
322         }
323     }
324     else
325     {
326         gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
327         if (m_samples > maxSamples)
328         {
329             m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count greater than MAX_SAMPLES");
330             return STOP;
331         }
332     }
333 
334     // Create a multisample texture, or a regular texture if samples is zero.
335     GLuint tex;
336     gl.genTextures(1, &tex);
337     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
338     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, m_internalFormat, WIDTH, HEIGHT, GL_FALSE);
339 
340     // Create a framebuffer with the texture attached.
341     GLuint fboMs;
342     gl.genFramebuffers(1, &fboMs);
343     gl.bindFramebuffer(GL_FRAMEBUFFER, fboMs);
344     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
345     gl.viewport(0, 0, WIDTH, HEIGHT);
346 
347     static uint16_t const quadIndices[] = {0, 1, 2, 2, 1, 3};
348 
349     {
350         // Draw with one of the fragment input qualifiers and with one of the
351         // interpolate functions. Cross-check the result in the shader and
352         // output the final interpolated value.
353 
354         static char const *vss = "${VERSION_DECL}\n"
355                                  "${OES_SMI_RQ}"
356                                  "layout(location = 0) in highp vec2 a_position;\n"
357                                  "layout(location = 1) in highp vec4 a_color;\n"
358                                  "out highp vec4 v_colorBase;\n"
359                                  "${QUALIFIER} out highp vec4 v_color;\n"
360                                  "void main()\n"
361                                  "{\n"
362                                  "    v_colorBase = a_color;\n"
363                                  "    v_color = a_color;\n"
364                                  "    gl_Position = vec4(a_position, 0.0, 1.0);\n"
365                                  "}\n";
366 
367         static char const *fss = "${VERSION_DECL}\n"
368                                  "${OES_SMI_RQ}"
369                                  "${OES_SV_EN}"
370                                  "in highp vec4 v_colorBase;\n"
371                                  "${QUALIFIER} in highp vec4 v_color;\n"
372                                  "layout(location = 0) out highp ${OUT_TYPE} o_color;\n"
373                                  "void main()\n"
374                                  "{\n"
375                                  "    highp vec4 temp = ${ASSIGNMENT};\n"
376                                  "    bool condition = ${CONDITION};\n"
377                                  "    o_color = ${OUT_TYPE}(temp.x, temp.y, condition, 1);\n"
378                                  "}\n";
379 
380         glu::ShaderProgram program(
381             m_context.getRenderContext(),
382             glu::makeVtxFragSources(
383                 specializeVersion(vss, m_glslVersion, m_sampler, m_outType, m_qualifier, m_assignment, m_condition)
384                     .c_str(),
385                 specializeVersion(fss, m_glslVersion, m_sampler, m_outType, m_qualifier, m_assignment, m_condition)
386                     .c_str()));
387         log << program;
388         if (!program.isOk())
389         {
390             TCU_FAIL("Compile failed");
391         }
392 
393         static float const position[] = {
394             -1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
395         };
396 
397         const float color[] = {
398             m_min, m_min, 0.0f, 1.0f, m_min, m_max, 0.0f, 1.0f, m_max, m_min, 0.0f, 1.0f, m_max, m_max, 0.0f, 1.0f,
399         };
400 
401         gl.useProgram(program.getProgram());
402 
403         glu::VertexArrayBinding vertexArrays[] = {
404             glu::va::Float("a_position", 2, 4, 0, &position[0]),
405             glu::va::Float("a_color", 4, 4, 0, &color[0]),
406         };
407         glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
408                   &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
409 
410         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
411     }
412 
413     gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
414     gl.deleteFramebuffers(1, &fboMs);
415 
416     GLsizei width = WIDTH * m_samples;
417 
418     GLuint rbo;
419     gl.genRenderbuffers(1, &rbo);
420     gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
421     gl.renderbufferStorage(GL_RENDERBUFFER, m_internalFormat, width, HEIGHT);
422 
423     GLuint fbo;
424     gl.genFramebuffers(1, &fbo);
425     gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
426     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
427     gl.viewport(0, 0, width, HEIGHT);
428 
429     {
430         // Resolve the mutli-sample texture into a render-buffer sized such that
431         // the width can hold all samples of a pixel.
432 
433         static char const *vss = "${VERSION_DECL}\n"
434                                  "in highp vec2 a_position;\n"
435                                  "void main(void)\n"
436                                  "{\n"
437                                  "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
438                                  "}\n";
439 
440         static char const *fss = "${VERSION_DECL}\n"
441                                  "uniform highp ${SAMPLER}MS u_texMS;\n"
442                                  "uniform int u_samples;\n"
443                                  "layout(location = 0) out highp ${OUT_TYPE} o_color;\n"
444                                  "void main(void)\n"
445                                  "{\n"
446                                  "    ivec2 coord = ivec2(int(gl_FragCoord.x) / u_samples, gl_FragCoord.y);\n"
447                                  "    int sampleId = int(gl_FragCoord.x) % u_samples;\n"
448                                  "    o_color = texelFetch(u_texMS, coord, sampleId);\n"
449                                  "}\n";
450 
451         glu::ShaderProgram program(
452             m_context.getRenderContext(),
453             glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion, m_sampler, m_outType).c_str(),
454                                     specializeVersion(fss, m_glslVersion, m_sampler, m_outType).c_str()));
455         log << program;
456         if (!program.isOk())
457         {
458             TCU_FAIL("Compile failed");
459         }
460 
461         static float const position[] = {
462             -1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
463         };
464 
465         gl.useProgram(program.getProgram());
466         gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_samples"), m_samples);
467         gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_texMS"), 0);
468 
469         glu::VertexArrayBinding vertexArrays[] = {
470             glu::va::Float("a_position", 2, 4, 0, &position[0]),
471         };
472         glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
473                   &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
474 
475         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
476     }
477 
478     // Verify the results.
479     tcu::TextureLevel results(m_texFormat, width, HEIGHT);
480     tcu::PixelBufferAccess pixels = results.getAccess();
481     std::vector<tcu::Vec4> result(pixels.getHeight() * pixels.getWidth());
482     int uniquePixels;
483 
484     if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8)
485     {
486         std::vector<GLint> data(pixels.getHeight() * pixels.getWidth() * 4);
487         gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_INT, &data[0]);
488         for (unsigned int i = 0; i < data.size(); i += 4)
489         {
490             result[i / 4] =
491                 tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]);
492         }
493         uniquePixels = countUniquePixels(result);
494     }
495     else if (pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8)
496     {
497         std::vector<GLuint> data(pixels.getHeight() * pixels.getWidth() * 4);
498         gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data[0]);
499         for (unsigned int i = 0; i < data.size(); i += 4)
500         {
501             result[i / 4] =
502                 tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]);
503         }
504         uniquePixels = countUniquePixels(result);
505     }
506     else
507     {
508         glu::readPixels(m_context.getRenderContext(), 0, 0, pixels);
509         uniquePixels = countUniquePixels(pixels);
510     }
511 
512     int expectedUnique = WIDTH * HEIGHT * ((m_unique) ? m_samples : 1);
513     if (uniquePixels < expectedUnique)
514     {
515         // There are duplicate pixel values meaning interpolation didn't work as expected.
516         isOk = false;
517     }
518     for (int y = 0; y < pixels.getHeight(); ++y)
519     {
520         for (int x = 0; x < pixels.getWidth(); ++x)
521         {
522             tcu::Vec4 pixel;
523             if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8 ||
524                 pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8)
525             {
526                 pixel = result[y * WIDTH + x];
527             }
528             else
529             {
530                 pixel = pixels.getPixel(x, y);
531             }
532             if (pixel.z() != 1)
533             {
534                 // The ${CONDITION} check in the shader failed.
535                 isOk = false;
536             }
537         }
538     }
539 
540     gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
541     gl.deleteFramebuffers(1, &fbo);
542 
543     gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
544     gl.deleteRenderbuffers(1, &rbo);
545 
546     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
547     gl.deleteTextures(1, &tex);
548 
549     m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
550     return STOP;
551 }
552 
countUniquePixels(tcu::ConstPixelBufferAccess const & pixels)553 int ShaderMultisampleInterpolationBaseCase::countUniquePixels(tcu::ConstPixelBufferAccess const &pixels)
554 {
555     std::set<tcu::Vec4> uniquePixels;
556 
557     for (int y = 0; y < pixels.getHeight(); ++y)
558     {
559         for (int x = 0; x < pixels.getWidth(); ++x)
560         {
561             uniquePixels.insert(pixels.getPixel(x, y));
562         }
563     }
564 
565     return (int)uniquePixels.size();
566 }
567 
countUniquePixels(const std::vector<tcu::Vec4> & pixels)568 int ShaderMultisampleInterpolationBaseCase::countUniquePixels(const std::vector<tcu::Vec4> &pixels)
569 {
570     std::set<tcu::Vec4> uniquePixels;
571 
572     for (unsigned int i = 0; i < pixels.size(); ++i)
573     {
574         uniquePixels.insert(pixels[i]);
575     }
576 
577     return (int)uniquePixels.size();
578 }
579 
ShaderMultisampleInterpolationTests(Context & context,glu::GLSLVersion glslVersion)580 ShaderMultisampleInterpolationTests::ShaderMultisampleInterpolationTests(Context &context, glu::GLSLVersion glslVersion)
581     : TestCaseGroup(context, "shader_multisample_interpolation", "Shader Multisample Interpolation tests")
582     , m_glslVersion(glslVersion)
583 {
584 }
585 
~ShaderMultisampleInterpolationTests()586 ShaderMultisampleInterpolationTests::~ShaderMultisampleInterpolationTests()
587 {
588 }
589 
init()590 void ShaderMultisampleInterpolationTests::init()
591 {
592     struct Sample
593     {
594         char const *name;
595         GLint samples;
596     } samples[] = {
597         {"samples_1", 1},
598         {"samples_2", 2},
599         {"samples_4", 4},
600     };
601 
602     // shader_multisample_interpolation.api
603     tcu::TestCaseGroup *apiGroup = new tcu::TestCaseGroup(m_testCtx, "api", "API verification");
604     apiGroup->addChild(new ShaderMultisampleInterpolationApiCase(m_context, "api", "API verification", m_glslVersion));
605     addChild(apiGroup);
606 
607     struct Case
608     {
609         char const *name;
610         char const *qualifier;
611         char const *assignment;
612         char const *condition;
613         bool unique;
614     } cases[] = {
615         {"base", "", "v_color", "true", false},
616         {"sample", "sample", "v_color", "true", true},
617         {"centroid", "centroid", "v_color", "true", false},
618         {"interpolate_at_sample", "", "interpolateAtSample(v_colorBase, gl_SampleID)", "true", true},
619         {"interpolate_at_sample_check", "sample", "interpolateAtSample(v_colorBase, gl_SampleID)", "temp == v_color",
620          true},
621         {"interpolate_at_centroid", "", "interpolateAtCentroid(v_colorBase)", "true", false},
622         {"interpolate_at_centroid_check", "centroid", "interpolateAtCentroid(v_colorBase)", "temp == v_color", false},
623         {"interpolate_at_offset", "", "interpolateAtOffset(v_colorBase, gl_SamplePosition - 0.5)", "true", true},
624         {"interpolate_at_offset_check", "sample", "interpolateAtOffset(v_colorBase, gl_SamplePosition - 0.5)",
625          "temp == v_color", true},
626     };
627 
628     // shader_multisample_interpolation.render
629     tcu::TestCaseGroup *renderGroup = new tcu::TestCaseGroup(m_testCtx, "render", "Rendering tests");
630     addChild(renderGroup);
631     for (int caseId = 0; caseId < DE_LENGTH_OF_ARRAY(cases); ++caseId)
632     {
633         tcu::TestCaseGroup *group = new tcu::TestCaseGroup(m_testCtx, cases[caseId].name, "");
634         renderGroup->addChild(group);
635         struct Format
636         {
637             char const *name;
638             GLenum internalFormat;
639             tcu::TextureFormat textureFormat;
640             char const *sampler;
641             char const *outType;
642             GLfloat min;
643             GLfloat max;
644         } formats[] = {
645             {"rgba8", GL_RGBA8, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
646              "sampler2D", "vec4", 0.0f, 1.0f},
647             {"rgba8i", GL_RGBA8I, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8),
648              "isampler2D", "ivec4", -128.0f, 127.0f},
649             {"rgba8ui", GL_RGBA8UI, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8),
650              "usampler2D", "uvec4", 0.0f, 255.0f},
651             {"rgba32f", GL_RGBA32F, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT),
652              "sampler2D", "vec4", 0.0f, 1.0f},
653         };
654         for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); ++format)
655         {
656             tcu::TestCaseGroup *formatGroup = new tcu::TestCaseGroup(m_testCtx, formats[format].name, "");
657             group->addChild(formatGroup);
658 
659             for (int sample = 0; sample < DE_LENGTH_OF_ARRAY(samples); ++sample)
660             {
661                 formatGroup->addChild(new ShaderMultisampleInterpolationBaseCase(
662                     m_context, samples[sample].name, "", m_glslVersion, cases[caseId].qualifier,
663                     cases[caseId].assignment, cases[caseId].condition, cases[caseId].unique,
664                     formats[format].internalFormat, formats[format].textureFormat, formats[format].sampler,
665                     formats[format].outType, formats[format].min, formats[format].max, samples[sample].samples));
666             }
667         }
668     }
669 }
670 
671 } // namespace deqp
672