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