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 Sample variable tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fSampleVariableTests.hpp"
25 #include "es31fMultisampleShaderRenderCase.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuTextureUtil.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "tcuFormatUtil.hpp"
32 #include "tcuStringTemplate.hpp"
33 #include "gluContextInfo.hpp"
34 #include "gluShaderProgram.hpp"
35 #include "gluRenderContext.hpp"
36 #include "glwFunctions.hpp"
37 #include "glwEnums.hpp"
38 #include "deStringUtil.hpp"
39
40 namespace deqp
41 {
42
43 using std::map;
44 using std::string;
45
46 namespace gles31
47 {
48 namespace Functional
49 {
50 namespace
51 {
52
53 class Verifier
54 {
55 public:
56 virtual bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const = 0;
57 virtual void logInfo (tcu::TestLog& log) const = 0;
58 };
59
60 class ColorVerifier : public Verifier
61 {
62 public:
ColorVerifier(const tcu::Vec3 & _color,int _threshold=8)63 ColorVerifier (const tcu::Vec3& _color, int _threshold = 8)
64 : m_color (tcu::Vec4(_color.x(), _color.y(), _color.z(), 1.0f))
65 , m_threshold (tcu::IVec3(_threshold))
66 {
67 }
68
ColorVerifier(const tcu::Vec3 & _color,tcu::IVec3 _threshold)69 ColorVerifier (const tcu::Vec3& _color, tcu::IVec3 _threshold)
70 : m_color (tcu::Vec4(_color.x(), _color.y(), _color.z(), 1.0f))
71 , m_threshold (_threshold)
72 {
73 }
74
verify(const tcu::RGBA & testColor,const tcu::IVec2 & position) const75 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
76 {
77 DE_UNREF(position);
78 return !tcu::boolAny(tcu::greaterThan(tcu::abs(m_color.toIVec().swizzle(0, 1, 2) - testColor.toIVec().swizzle(0, 1, 2)), tcu::IVec3(m_threshold)));
79 }
80
logInfo(tcu::TestLog & log) const81 void logInfo (tcu::TestLog& log) const
82 {
83 // full threshold? print * for clarity
84 log << tcu::TestLog::Message
85 << "Expecting unicolored image, color = RGB("
86 << ((m_threshold[0] >= 255) ? ("*") : (de::toString(m_color.getRed()))) << ", "
87 << ((m_threshold[1] >= 255) ? ("*") : (de::toString(m_color.getGreen()))) << ", "
88 << ((m_threshold[2] >= 255) ? ("*") : (de::toString(m_color.getBlue()))) << ")"
89 << tcu::TestLog::EndMessage;
90 }
91
92 const tcu::RGBA m_color;
93 const tcu::IVec3 m_threshold;
94 };
95
96 class FullBlueSomeGreenVerifier : public Verifier
97 {
98 public:
FullBlueSomeGreenVerifier(void)99 FullBlueSomeGreenVerifier (void)
100 {
101 }
102
verify(const tcu::RGBA & testColor,const tcu::IVec2 & position) const103 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
104 {
105 DE_UNREF(position);
106
107 // Values from 0.0 and 1.0 are accurate
108
109 if (testColor.getRed() != 0)
110 return false;
111 if (testColor.getGreen() == 0)
112 return false;
113 if (testColor.getBlue() != 255)
114 return false;
115 return true;
116 }
117
logInfo(tcu::TestLog & log) const118 void logInfo (tcu::TestLog& log) const
119 {
120 log << tcu::TestLog::Message << "Expecting color c = (0.0, x, 1.0), x > 0.0" << tcu::TestLog::EndMessage;
121 }
122 };
123
124 class NoRedVerifier : public Verifier
125 {
126 public:
NoRedVerifier(void)127 NoRedVerifier (void)
128 {
129 }
130
verify(const tcu::RGBA & testColor,const tcu::IVec2 & position) const131 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
132 {
133 DE_UNREF(position);
134 return testColor.getRed() == 0;
135 }
136
logInfo(tcu::TestLog & log) const137 void logInfo (tcu::TestLog& log) const
138 {
139 log << tcu::TestLog::Message << "Expecting zero-valued red channel." << tcu::TestLog::EndMessage;
140 }
141 };
142
143 class SampleAverageVerifier : public Verifier
144 {
145 public:
146 SampleAverageVerifier (int _numSamples);
147
148 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const;
149 void logInfo (tcu::TestLog& log) const;
150
151 const int m_numSamples;
152 const bool m_isStatisticallySignificant;
153 float m_distanceThreshold;
154 };
155
SampleAverageVerifier(int _numSamples)156 SampleAverageVerifier::SampleAverageVerifier (int _numSamples)
157 : m_numSamples (_numSamples)
158 , m_isStatisticallySignificant (_numSamples >= 4)
159 , m_distanceThreshold (0.0f)
160 {
161 // approximate Bates distribution as normal
162 const float variance = (1.0f / (12.0f * (float)m_numSamples));
163 const float standardDeviation = deFloatSqrt(variance);
164
165 // 95% of means of sample positions are within 2 standard deviations if
166 // they were randomly assigned. Sample patterns are expected to be more
167 // uniform than a random pattern.
168 m_distanceThreshold = 2 * standardDeviation;
169 }
170
verify(const tcu::RGBA & testColor,const tcu::IVec2 & position) const171 bool SampleAverageVerifier::verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
172 {
173 DE_UNREF(position);
174 DE_ASSERT(m_isStatisticallySignificant);
175
176 const tcu::Vec2 avgPosition ((float)testColor.getGreen() / 255.0f, (float)testColor.getBlue() / 255.0f);
177 const tcu::Vec2 distanceFromCenter = tcu::abs(avgPosition - tcu::Vec2(0.5f, 0.5f));
178
179 return distanceFromCenter.x() < m_distanceThreshold && distanceFromCenter.y() < m_distanceThreshold;
180 }
181
logInfo(tcu::TestLog & log) const182 void SampleAverageVerifier::logInfo (tcu::TestLog& log) const
183 {
184 log << tcu::TestLog::Message << "Expecting average sample position to be near the pixel center. Maximum per-axis distance " << m_distanceThreshold << tcu::TestLog::EndMessage;
185 }
186
187 class PartialDiscardVerifier : public Verifier
188 {
189 public:
PartialDiscardVerifier(void)190 PartialDiscardVerifier (void)
191 {
192 }
193
verify(const tcu::RGBA & testColor,const tcu::IVec2 & position) const194 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
195 {
196 DE_UNREF(position);
197
198 return (testColor.getGreen() != 0) && (testColor.getGreen() != 255);
199 }
200
logInfo(tcu::TestLog & log) const201 void logInfo (tcu::TestLog& log) const
202 {
203 log << tcu::TestLog::Message << "Expecting color non-zero and non-saturated green channel" << tcu::TestLog::EndMessage;
204 }
205 };
206
verifyImageWithVerifier(const tcu::Surface & resultImage,tcu::TestLog & log,const Verifier & verifier,bool logOnSuccess=true)207 static bool verifyImageWithVerifier (const tcu::Surface& resultImage, tcu::TestLog& log, const Verifier& verifier, bool logOnSuccess = true)
208 {
209 tcu::Surface errorMask (resultImage.getWidth(), resultImage.getHeight());
210 bool error = false;
211
212 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
213
214 if (logOnSuccess)
215 {
216 log << tcu::TestLog::Message << "Verifying image." << tcu::TestLog::EndMessage;
217 verifier.logInfo(log);
218 }
219
220 for (int y = 0; y < resultImage.getHeight(); ++y)
221 for (int x = 0; x < resultImage.getWidth(); ++x)
222 {
223 const tcu::RGBA color = resultImage.getPixel(x, y);
224
225 // verify color value is valid for this pixel position
226 if (!verifier.verify(color, tcu::IVec2(x,y)))
227 {
228 error = true;
229 errorMask.setPixel(x, y, tcu::RGBA::red());
230 }
231 }
232
233 if (error)
234 {
235 // describe the verification logic if we haven't already
236 if (!logOnSuccess)
237 verifier.logInfo(log);
238
239 log << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage
240 << tcu::TestLog::ImageSet("Verification", "Image Verification")
241 << tcu::TestLog::Image("Result", "Result image", resultImage.getAccess())
242 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask.getAccess())
243 << tcu::TestLog::EndImageSet;
244 }
245 else if (logOnSuccess)
246 {
247 log << tcu::TestLog::Message << "Image verification passed." << tcu::TestLog::EndMessage
248 << tcu::TestLog::ImageSet("Verification", "Image Verification")
249 << tcu::TestLog::Image("Result", "Result image", resultImage.getAccess())
250 << tcu::TestLog::EndImageSet;
251 }
252
253 return !error;
254 }
255
256 class MultisampleRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
257 {
258 public:
259 MultisampleRenderCase (Context& context, const char* name, const char* desc, int numSamples, RenderTarget target, int renderSize, int flags = 0);
260 virtual ~MultisampleRenderCase (void);
261
262 virtual void init (void);
263
264 };
265
MultisampleRenderCase(Context & context,const char * name,const char * desc,int numSamples,RenderTarget target,int renderSize,int flags)266 MultisampleRenderCase::MultisampleRenderCase (Context& context, const char* name, const char* desc, int numSamples, RenderTarget target, int renderSize, int flags)
267 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, desc, numSamples, target, renderSize, flags)
268 {
269 DE_ASSERT(target < TARGET_LAST);
270 }
271
~MultisampleRenderCase(void)272 MultisampleRenderCase::~MultisampleRenderCase (void)
273 {
274 MultisampleRenderCase::deinit();
275 }
276
init(void)277 void MultisampleRenderCase::init (void)
278 {
279 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
280 if (!isES32 && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables"))
281 TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_variables extension or a context version 3.2 or higher.");
282
283 MultisampleShaderRenderUtil::MultisampleRenderCase::init();
284 }
285
286 class NumSamplesCase : public MultisampleRenderCase
287 {
288 public:
289 NumSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
290 ~NumSamplesCase (void);
291
292 std::string genFragmentSource (int numTargetSamples) const;
293 bool verifyImage (const tcu::Surface& resultImage);
294
295 private:
296 enum
297 {
298 RENDER_SIZE = 64
299 };
300 };
301
NumSamplesCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target)302 NumSamplesCase::NumSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target)
303 : MultisampleRenderCase(context, name, desc, sampleCount, target, RENDER_SIZE)
304 {
305 }
306
~NumSamplesCase(void)307 NumSamplesCase::~NumSamplesCase (void)
308 {
309 }
310
genFragmentSource(int numTargetSamples) const311 std::string NumSamplesCase::genFragmentSource (int numTargetSamples) const
312 {
313 std::ostringstream buf;
314 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
315 map<string, string> args;
316 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
317 args["GLSL_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
318
319 buf << "${GLSL_VERSION_DECL}\n"
320 "${GLSL_EXTENSION}\n"
321 "layout(location = 0) out mediump vec4 fragColor;\n"
322 "void main (void)\n"
323 "{\n"
324 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
325 " if (gl_NumSamples == " << numTargetSamples << ")\n"
326 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
327 "}\n";
328
329 return tcu::StringTemplate(buf.str()).specialize(args);
330 }
331
verifyImage(const tcu::Surface & resultImage)332 bool NumSamplesCase::verifyImage (const tcu::Surface& resultImage)
333 {
334 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier());
335 }
336
337 class MaxSamplesCase : public MultisampleRenderCase
338 {
339 public:
340 MaxSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
341 ~MaxSamplesCase (void);
342
343 private:
344 void preDraw (void);
345 std::string genFragmentSource (int numTargetSamples) const;
346 bool verifyImage (const tcu::Surface& resultImage);
347
348 enum
349 {
350 RENDER_SIZE = 64
351 };
352 };
353
MaxSamplesCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target)354 MaxSamplesCase::MaxSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target)
355 : MultisampleRenderCase(context, name, desc, sampleCount, target, RENDER_SIZE)
356 {
357 }
358
~MaxSamplesCase(void)359 MaxSamplesCase::~MaxSamplesCase (void)
360 {
361 }
362
preDraw(void)363 void MaxSamplesCase::preDraw (void)
364 {
365 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
366 deInt32 maxSamples = -1;
367
368 // query samples
369 {
370 gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
371 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_MAX_SAMPLES");
372
373 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_SAMPLES = " << maxSamples << tcu::TestLog::EndMessage;
374 }
375
376 // set samples
377 {
378 const int maxSampleLoc = gl.getUniformLocation(m_program->getProgram(), "u_maxSamples");
379 if (maxSampleLoc == -1)
380 throw tcu::TestError("Location of u_maxSamples was -1");
381
382 gl.uniform1i(maxSampleLoc, maxSamples);
383 GLU_EXPECT_NO_ERROR(gl.getError(), "set u_maxSamples uniform");
384
385 m_testCtx.getLog() << tcu::TestLog::Message << "Set u_maxSamples = " << maxSamples << tcu::TestLog::EndMessage;
386 }
387 }
388
genFragmentSource(int numTargetSamples) const389 std::string MaxSamplesCase::genFragmentSource (int numTargetSamples) const
390 {
391 DE_UNREF(numTargetSamples);
392
393 std::ostringstream buf;
394 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
395 map<string, string> args;
396 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
397 args["GLSL_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
398
399 buf << "${GLSL_VERSION_DECL}\n"
400 "${GLSL_EXTENSION}\n"
401 "layout(location = 0) out mediump vec4 fragColor;\n"
402 "uniform mediump int u_maxSamples;\n"
403 "void main (void)\n"
404 "{\n"
405 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
406 " if (gl_MaxSamples == u_maxSamples)\n"
407 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
408 "}\n";
409
410 return tcu::StringTemplate(buf.str()).specialize(args);
411 }
412
verifyImage(const tcu::Surface & resultImage)413 bool MaxSamplesCase::verifyImage (const tcu::Surface& resultImage)
414 {
415 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier());
416 }
417
418 class SampleIDCase : public MultisampleRenderCase
419 {
420 public:
421 SampleIDCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
422 ~SampleIDCase (void);
423
424 void init (void);
425
426 private:
427 std::string genFragmentSource (int numTargetSamples) const;
428 bool verifyImage (const tcu::Surface& resultImage);
429 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers);
430
431 enum
432 {
433 RENDER_SIZE = 64
434 };
435 enum VerificationMode
436 {
437 VERIFY_USING_SAMPLES,
438 VERIFY_USING_SELECTION,
439 };
440
441 const VerificationMode m_vericationMode;
442 };
443
SampleIDCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target)444 SampleIDCase::SampleIDCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target)
445 : MultisampleRenderCase (context, name, desc, sampleCount, target, RENDER_SIZE, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS)
446 , m_vericationMode ((target == TARGET_TEXTURE) ? (VERIFY_USING_SAMPLES) : (VERIFY_USING_SELECTION))
447 {
448 }
449
~SampleIDCase(void)450 SampleIDCase::~SampleIDCase (void)
451 {
452 }
453
init(void)454 void SampleIDCase::init (void)
455 {
456 // log the test method and expectations
457 if (m_vericationMode == VERIFY_USING_SAMPLES)
458 m_testCtx.getLog()
459 << tcu::TestLog::Message
460 << "Writing gl_SampleID to the green channel of the texture and verifying texture values, expecting:\n"
461 << " 1) 0 with non-multisample targets.\n"
462 << " 2) value N at sample index N of a multisample texture\n"
463 << tcu::TestLog::EndMessage;
464 else if (m_vericationMode == VERIFY_USING_SELECTION)
465 m_testCtx.getLog()
466 << tcu::TestLog::Message
467 << "Selecting a single sample id for each pixel and writing color only if gl_SampleID == selected.\n"
468 << "Expecting all output pixels to be partially (multisample) or fully (singlesample) colored.\n"
469 << tcu::TestLog::EndMessage;
470 else
471 DE_ASSERT(false);
472
473 MultisampleRenderCase::init();
474 }
475
genFragmentSource(int numTargetSamples) const476 std::string SampleIDCase::genFragmentSource (int numTargetSamples) const
477 {
478 DE_ASSERT(numTargetSamples != 0);
479
480 std::ostringstream buf;
481 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
482 map<string, string> args;
483 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
484 args["GLSL_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
485
486 if (m_vericationMode == VERIFY_USING_SAMPLES)
487 {
488 // encode the id to the output, and then verify it during sampling
489 buf << "${GLSL_VERSION_DECL}\n"
490 "${GLSL_EXTENSION}\n"
491 "layout(location = 0) out mediump vec4 fragColor;\n"
492 "void main (void)\n"
493 "{\n"
494 " highp float normalizedSample = float(gl_SampleID) / float(" << numTargetSamples << ");\n"
495 " fragColor = vec4(0.0, normalizedSample, 1.0, 1.0);\n"
496 "}\n";
497 }
498 else if (m_vericationMode == VERIFY_USING_SELECTION)
499 {
500 if (numTargetSamples == 1)
501 {
502 // single sample, just verify value is 0
503 buf << "${GLSL_VERSION_DECL}\n"
504 "${GLSL_EXTENSION}\n"
505 "layout(location = 0) out mediump vec4 fragColor;\n"
506 "void main (void)\n"
507 "{\n"
508 " if (gl_SampleID == 0)\n"
509 " fragColor = vec4(0.0, 1.0, 1.0, 1.0);\n"
510 " else\n"
511 " fragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
512 "}\n";
513 }
514 else
515 {
516 // select only one sample per PIXEL
517 buf << "${GLSL_VERSION_DECL}\n"
518 "${GLSL_EXTENSION}\n"
519 "in highp vec4 v_position;\n"
520 "layout(location = 0) out mediump vec4 fragColor;\n"
521 "void main (void)\n"
522 "{\n"
523 " highp vec2 relPosition = (v_position.xy + vec2(1.0, 1.0)) / 2.0;\n"
524 " highp ivec2 pixelPos = ivec2(floor(relPosition * " << (int)RENDER_SIZE << ".0));\n"
525 " highp int selectedID = abs(pixelPos.x + 17 * pixelPos.y) % " << numTargetSamples << ";\n"
526 "\n"
527 " if (gl_SampleID == selectedID)\n"
528 " fragColor = vec4(0.0, 1.0, 1.0, 1.0);\n"
529 " else\n"
530 " fragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
531 "}\n";
532 }
533 }
534 else
535 DE_ASSERT(false);
536
537 return tcu::StringTemplate(buf.str()).specialize(args);
538 }
539
verifyImage(const tcu::Surface & resultImage)540 bool SampleIDCase::verifyImage (const tcu::Surface& resultImage)
541 {
542 if (m_vericationMode == VERIFY_USING_SAMPLES)
543 {
544 // never happens
545 DE_ASSERT(false);
546 return false;
547 }
548 else if (m_vericationMode == VERIFY_USING_SELECTION)
549 {
550 // should result in full blue and some green everywhere
551 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), FullBlueSomeGreenVerifier());
552 }
553 else
554 {
555 DE_ASSERT(false);
556 return false;
557 }
558 }
559
verifySampleBuffers(const std::vector<tcu::Surface> & resultBuffers)560 bool SampleIDCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
561 {
562 // Verify all sample buffers
563 bool allOk = true;
564
565 // Log layers
566 {
567 m_testCtx.getLog() << tcu::TestLog::ImageSet("SampleBuffers", "Image sample buffers");
568 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
569 m_testCtx.getLog() << tcu::TestLog::Image("Buffer" + de::toString(sampleNdx), "Sample " + de::toString(sampleNdx), resultBuffers[sampleNdx].getAccess());
570 m_testCtx.getLog() << tcu::TestLog::EndImageSet;
571 }
572
573 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample buffers" << tcu::TestLog::EndMessage;
574 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
575 {
576 // sample id should be sample index
577 const int threshold = 255 / 4 / m_numTargetSamples + 1;
578 const float sampleIdColor = (float)sampleNdx / (float)m_numTargetSamples;
579
580 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample " << (sampleNdx+1) << "/" << (int)resultBuffers.size() << tcu::TestLog::EndMessage;
581 allOk &= verifyImageWithVerifier(resultBuffers[sampleNdx], m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, sampleIdColor, 1.0f), tcu::IVec3(1, threshold, 1)), false);
582 }
583
584 if (!allOk)
585 m_testCtx.getLog() << tcu::TestLog::Message << "Sample buffer verification failed" << tcu::TestLog::EndMessage;
586
587 return allOk;
588 }
589
590 class SamplePosDistributionCase : public MultisampleRenderCase
591 {
592 public:
593 SamplePosDistributionCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
594 ~SamplePosDistributionCase (void);
595
596 void init (void);
597 private:
598 enum
599 {
600 RENDER_SIZE = 64
601 };
602
603 std::string genFragmentSource (int numTargetSamples) const;
604 bool verifyImage (const tcu::Surface& resultImage);
605 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers);
606 };
607
SamplePosDistributionCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target)608 SamplePosDistributionCase::SamplePosDistributionCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target)
609 : MultisampleRenderCase(context, name, desc, sampleCount, target, RENDER_SIZE, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS)
610 {
611 }
612
~SamplePosDistributionCase(void)613 SamplePosDistributionCase::~SamplePosDistributionCase (void)
614 {
615 }
616
init(void)617 void SamplePosDistributionCase::init (void)
618 {
619 // log the test method and expectations
620 if (m_renderTarget == TARGET_TEXTURE)
621 {
622 m_testCtx.getLog()
623 << tcu::TestLog::Message
624 << "Verifying gl_SamplePosition value:\n"
625 << " 1) With non-multisample targets: Expect the center of the pixel.\n"
626 << " 2) With multisample targets:\n"
627 << " a) Expect legal sample position.\n"
628 << " b) Sample position is unique within the set of all sample positions of a pixel.\n"
629 << " c) Sample position distribution is uniform or almost uniform.\n"
630 << tcu::TestLog::EndMessage;
631 }
632 else
633 {
634 m_testCtx.getLog()
635 << tcu::TestLog::Message
636 << "Verifying gl_SamplePosition value:\n"
637 << " 1) With non-multisample targets: Expect the center of the pixel.\n"
638 << " 2) With multisample targets:\n"
639 << " a) Expect legal sample position.\n"
640 << " b) Sample position distribution is uniform or almost uniform.\n"
641 << tcu::TestLog::EndMessage;
642 }
643
644 MultisampleRenderCase::init();
645 }
646
genFragmentSource(int numTargetSamples) const647 std::string SamplePosDistributionCase::genFragmentSource (int numTargetSamples) const
648 {
649 DE_ASSERT(numTargetSamples != 0);
650 DE_UNREF(numTargetSamples);
651
652 const bool multisampleTarget = (m_numRequestedSamples > 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1);
653 std::ostringstream buf;
654 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
655 map<string, string> args;
656 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
657 args["GLSL_EXTENSION"] = isES32 ? "\n" : "#extension GL_OES_sample_variables : require\n";
658
659 if (multisampleTarget)
660 {
661 // encode the position to the output, use red channel as error channel
662 buf << "${GLSL_VERSION_DECL}\n"
663 "${GLSL_EXTENSION}\n"
664 "layout(location = 0) out mediump vec4 fragColor;\n"
665 "void main (void)\n"
666 "{\n"
667 " if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n"
668 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
669 " else\n"
670 " fragColor = vec4(0.0, gl_SamplePosition.x, gl_SamplePosition.y, 1.0);\n"
671 "}\n";
672 }
673 else
674 {
675 // verify value is ok
676 buf << "${GLSL_VERSION_DECL}\n"
677 "${GLSL_EXTENSION}\n"
678 "layout(location = 0) out mediump vec4 fragColor;\n"
679 "void main (void)\n"
680 "{\n"
681 " if (gl_SamplePosition.x != 0.5 || gl_SamplePosition.y != 0.5)\n"
682 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
683 " else\n"
684 " fragColor = vec4(0.0, gl_SamplePosition.x, gl_SamplePosition.y, 1.0);\n"
685 "}\n";
686 }
687
688 return tcu::StringTemplate(buf.str()).specialize(args);
689 }
690
verifyImage(const tcu::Surface & resultImage)691 bool SamplePosDistributionCase::verifyImage (const tcu::Surface& resultImage)
692 {
693 const int sampleCount = (m_renderTarget == TARGET_DEFAULT) ? (m_context.getRenderTarget().getNumSamples()) : (m_numRequestedSamples);
694 SampleAverageVerifier verifier (sampleCount);
695
696 // check there is nothing in the error channel
697 if (!verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier()))
698 return false;
699
700 // position average should be around 0.5, 0.5
701 if (verifier.m_isStatisticallySignificant && !verifyImageWithVerifier(resultImage, m_testCtx.getLog(), verifier))
702 throw MultisampleShaderRenderUtil::QualityWarning("Bias detected, sample positions are not uniformly distributed within the pixel");
703
704 return true;
705 }
706
verifySampleBuffers(const std::vector<tcu::Surface> & resultBuffers)707 bool SamplePosDistributionCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
708 {
709 const int width = resultBuffers[0].getWidth();
710 const int height = resultBuffers[0].getHeight();
711 bool allOk = true;
712 bool distibutionError = false;
713
714 // Check sample range, uniqueness, and distribution, log layers
715 {
716 m_testCtx.getLog() << tcu::TestLog::ImageSet("SampleBuffers", "Image sample buffers");
717 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
718 m_testCtx.getLog() << tcu::TestLog::Image("Buffer" + de::toString(sampleNdx), "Sample " + de::toString(sampleNdx), resultBuffers[sampleNdx].getAccess());
719 m_testCtx.getLog() << tcu::TestLog::EndImageSet;
720 }
721
722 // verify range
723 {
724 bool rangeOk = true;
725
726 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position range" << tcu::TestLog::EndMessage;
727 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
728 {
729 // shader does the check, just check the shader error output (red)
730 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample " << (sampleNdx+1) << "/" << (int)resultBuffers.size() << tcu::TestLog::EndMessage;
731 rangeOk &= verifyImageWithVerifier(resultBuffers[sampleNdx], m_testCtx.getLog(), NoRedVerifier(), false);
732 }
733
734 if (!rangeOk)
735 {
736 allOk = false;
737
738 m_testCtx.getLog() << tcu::TestLog::Message << "Sample position verification failed." << tcu::TestLog::EndMessage;
739 }
740 }
741
742 // Verify uniqueness
743 {
744 bool uniquenessOk = true;
745 tcu::Surface errorMask (width, height);
746 std::vector<tcu::Vec2> samplePositions (resultBuffers.size());
747 int printCount = 0;
748 const int printFloodLimit = 5;
749
750 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
751
752 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position uniqueness." << tcu::TestLog::EndMessage;
753
754 for (int y = 0; y < height; ++y)
755 for (int x = 0; x < width; ++x)
756 {
757 bool samplePosNotUnique = false;
758
759 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
760 {
761 const tcu::RGBA color = resultBuffers[sampleNdx].getPixel(x, y);
762 samplePositions[sampleNdx] = tcu::Vec2((float)color.getGreen() / 255.0f, (float)color.getBlue() / 255.0f);
763 }
764
765 // Just check there are no two samples with same positions
766 for (int sampleNdxA = 0; sampleNdxA < (int)resultBuffers.size() && (!samplePosNotUnique || printCount < printFloodLimit); ++sampleNdxA)
767 for (int sampleNdxB = sampleNdxA+1; sampleNdxB < (int)resultBuffers.size() && (!samplePosNotUnique || printCount < printFloodLimit); ++sampleNdxB)
768 {
769 if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB])
770 {
771 if (++printCount <= printFloodLimit)
772 {
773 m_testCtx.getLog()
774 << tcu::TestLog::Message
775 << "Pixel (" << x << ", " << y << "): Samples " << sampleNdxA << " and " << sampleNdxB << " have the same position."
776 << tcu::TestLog::EndMessage;
777 }
778
779 samplePosNotUnique = true;
780 uniquenessOk = false;
781 errorMask.setPixel(x, y, tcu::RGBA::red());
782 }
783 }
784 }
785
786 // end result
787 if (!uniquenessOk)
788 {
789 if (printCount > printFloodLimit)
790 m_testCtx.getLog()
791 << tcu::TestLog::Message
792 << "...\n"
793 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
794 << tcu::TestLog::EndMessage;
795
796 m_testCtx.getLog()
797 << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage
798 << tcu::TestLog::ImageSet("Verification", "Image Verification")
799 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask.getAccess())
800 << tcu::TestLog::EndImageSet;
801
802 allOk = false;
803 }
804 }
805
806 // check distribution
807 {
808 const SampleAverageVerifier verifier (m_numTargetSamples);
809 tcu::Surface errorMask (width, height);
810 int printCount = 0;
811 const int printFloodLimit = 5;
812
813 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
814
815 // don't bother with small sample counts
816 if (verifier.m_isStatisticallySignificant)
817 {
818 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position distribution is (nearly) unbiased." << tcu::TestLog::EndMessage;
819 verifier.logInfo(m_testCtx.getLog());
820
821 for (int y = 0; y < height; ++y)
822 for (int x = 0; x < width; ++x)
823 {
824 tcu::IVec3 colorSum(0, 0, 0);
825
826 // color average
827
828 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
829 {
830 const tcu::RGBA color = resultBuffers[sampleNdx].getPixel(x, y);
831 colorSum.x() += color.getRed();
832 colorSum.y() += color.getBlue();
833 colorSum.z() += color.getGreen();
834 }
835
836 colorSum.x() /= m_numTargetSamples;
837 colorSum.y() /= m_numTargetSamples;
838 colorSum.z() /= m_numTargetSamples;
839
840 // verify average sample position
841
842 if (!verifier.verify(tcu::RGBA(colorSum.x(), colorSum.y(), colorSum.z(), 0), tcu::IVec2(x, y)))
843 {
844 if (++printCount <= printFloodLimit)
845 {
846 m_testCtx.getLog()
847 << tcu::TestLog::Message
848 << "Pixel (" << x << ", " << y << "): Sample distribution is biased."
849 << tcu::TestLog::EndMessage;
850 }
851
852 distibutionError = true;
853 errorMask.setPixel(x, y, tcu::RGBA::red());
854 }
855 }
856
857 // sub-verification result
858 if (distibutionError)
859 {
860 if (printCount > printFloodLimit)
861 m_testCtx.getLog()
862 << tcu::TestLog::Message
863 << "...\n"
864 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
865 << tcu::TestLog::EndMessage;
866
867 m_testCtx.getLog()
868 << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage
869 << tcu::TestLog::ImageSet("Verification", "Image Verification")
870 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask.getAccess())
871 << tcu::TestLog::EndImageSet;
872 }
873 }
874 }
875
876 // results
877 if (!allOk)
878 return false;
879 else if (distibutionError)
880 throw MultisampleShaderRenderUtil::QualityWarning("Bias detected, sample positions are not uniformly distributed within the pixel");
881 else
882 {
883 m_testCtx.getLog() << tcu::TestLog::Message << "Verification ok." << tcu::TestLog::EndMessage;
884 return true;
885 }
886 }
887
888 class SamplePosCorrectnessCase : public MultisampleRenderCase
889 {
890 public:
891 SamplePosCorrectnessCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
892 ~SamplePosCorrectnessCase (void);
893
894 void init (void);
895 private:
896 enum
897 {
898 RENDER_SIZE = 32
899 };
900
901 void preDraw (void);
902 void postDraw (void);
903
904 std::string genVertexSource (int numTargetSamples) const;
905 std::string genFragmentSource (int numTargetSamples) const;
906 bool verifyImage (const tcu::Surface& resultImage);
907
908 bool m_useSampleQualifier;
909 };
910
SamplePosCorrectnessCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target)911 SamplePosCorrectnessCase::SamplePosCorrectnessCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target)
912 : MultisampleRenderCase (context, name, desc, sampleCount, target, RENDER_SIZE)
913 , m_useSampleQualifier (false)
914 {
915 }
916
~SamplePosCorrectnessCase(void)917 SamplePosCorrectnessCase::~SamplePosCorrectnessCase (void)
918 {
919 }
920
init(void)921 void SamplePosCorrectnessCase::init (void)
922 {
923 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
924 // requirements: per-invocation interpolation required
925 if (!isES32 && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") &&
926 !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
927 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation or GL_OES_sample_shading extension or a context version 3.2 or higher.");
928
929 // prefer to use the sample qualifier path
930 m_useSampleQualifier = m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation");
931
932 // log the test method and expectations
933 m_testCtx.getLog()
934 << tcu::TestLog::Message
935 << "Verifying gl_SamplePosition correctness:\n"
936 << " 1) Varying values should be sampled at the sample position.\n"
937 << " => fract(screenSpacePosition) == gl_SamplePosition\n"
938 << tcu::TestLog::EndMessage;
939
940 MultisampleRenderCase::init();
941 }
942
preDraw(void)943 void SamplePosCorrectnessCase::preDraw (void)
944 {
945 if (!m_useSampleQualifier)
946 {
947 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
948
949 // use GL_OES_sample_shading to set per fragment sample invocation interpolation
950 gl.enable(GL_SAMPLE_SHADING);
951 gl.minSampleShading(1.0f);
952 GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio");
953
954 m_testCtx.getLog() << tcu::TestLog::Message << "Enabling per-sample interpolation with GL_SAMPLE_SHADING." << tcu::TestLog::EndMessage;
955 }
956 }
957
postDraw(void)958 void SamplePosCorrectnessCase::postDraw (void)
959 {
960 if (!m_useSampleQualifier)
961 {
962 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
963
964 gl.disable(GL_SAMPLE_SHADING);
965 gl.minSampleShading(1.0f);
966 GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio");
967 }
968 }
969
genVertexSource(int numTargetSamples) const970 std::string SamplePosCorrectnessCase::genVertexSource (int numTargetSamples) const
971 {
972 DE_UNREF(numTargetSamples);
973
974 std::ostringstream buf;
975 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
976 map<string, string> args;
977 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
978 args["GLSL_EXTENSION"] = isES32 ? "" : m_useSampleQualifier ? "#extension GL_OES_shader_multisample_interpolation : require" : "";
979
980 buf << "${GLSL_VERSION_DECL}\n"
981 "${GLSL_EXTENSION}\n"
982 << "in highp vec4 a_position;\n"
983 << ((m_useSampleQualifier) ? ("sample ") : ("")) << "out highp vec4 v_position;\n"
984 "void main (void)\n"
985 "{\n"
986 " gl_Position = a_position;\n"
987 " v_position = a_position;\n"
988 "}\n";
989
990 return tcu::StringTemplate(buf.str()).specialize(args);
991 }
992
genFragmentSource(int numTargetSamples) const993 std::string SamplePosCorrectnessCase::genFragmentSource (int numTargetSamples) const
994 {
995 DE_UNREF(numTargetSamples);
996
997 std::ostringstream buf;
998 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
999 map<string, string> args;
1000 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
1001 args["GLSL_SAMPLE_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
1002 args["GLSL_MULTISAMPLE_EXTENSION"] = isES32 ? "" : m_useSampleQualifier ? "#extension GL_OES_shader_multisample_interpolation : require" : "";
1003
1004 // encode the position to the output, use red channel as error channel
1005 buf << "${GLSL_VERSION_DECL}\n"
1006 "${GLSL_SAMPLE_EXTENSION}\n"
1007 "${GLSL_MULTISAMPLE_EXTENSION}\n"
1008 << ((m_useSampleQualifier) ? ("sample ") : ("")) << "in highp vec4 v_position;\n"
1009 "layout(location = 0) out mediump vec4 fragColor;\n"
1010 "void main (void)\n"
1011 "{\n"
1012 " const highp float maxDistance = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE)
1013 "\n"
1014 " highp vec2 screenSpacePosition = (v_position.xy + vec2(1.0, 1.0)) / 2.0 * " << (int)RENDER_SIZE << ".0;\n"
1015 " highp ivec2 nearbyPixel = ivec2(floor(screenSpacePosition));\n"
1016 " bool allOk = false;\n"
1017 "\n"
1018 " // sample at edge + inaccuaries may cause us to round to any neighboring pixel\n"
1019 " // check all neighbors for any match\n"
1020 " for (highp int dy = -1; dy <= 1; ++dy)\n"
1021 " for (highp int dx = -1; dx <= 1; ++dx)\n"
1022 " {\n"
1023 " highp ivec2 currentPixel = nearbyPixel + ivec2(dx, dy);\n"
1024 " highp vec2 candidateSamplingPos = vec2(currentPixel) + gl_SamplePosition.xy;\n"
1025 " highp vec2 positionDiff = abs(candidateSamplingPos - screenSpacePosition);\n"
1026 " if (positionDiff.x < maxDistance && positionDiff.y < maxDistance)\n"
1027 " allOk = true;\n"
1028 " }\n"
1029 "\n"
1030 " if (allOk)\n"
1031 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1032 " else\n"
1033 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1034 "}\n";
1035
1036 return tcu::StringTemplate(buf.str()).specialize(args);
1037 }
1038
verifyImage(const tcu::Surface & resultImage)1039 bool SamplePosCorrectnessCase::verifyImage (const tcu::Surface& resultImage)
1040 {
1041 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier());
1042 }
1043
1044 class SampleMaskBaseCase : public MultisampleRenderCase
1045 {
1046 public:
1047 enum ShaderRunMode
1048 {
1049 RUN_PER_PIXEL = 0,
1050 RUN_PER_SAMPLE,
1051 RUN_PER_TWO_SAMPLES,
1052
1053 RUN_LAST
1054 };
1055
1056 SampleMaskBaseCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, int renderSize, ShaderRunMode runMode, int flags = 0);
1057 virtual ~SampleMaskBaseCase (void);
1058
1059 protected:
1060 virtual void init (void);
1061 virtual void preDraw (void);
1062 virtual void postDraw (void);
1063 virtual bool verifyImage (const tcu::Surface& resultImage);
1064
1065 const ShaderRunMode m_runMode;
1066 };
1067
SampleMaskBaseCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target,int renderSize,ShaderRunMode runMode,int flags)1068 SampleMaskBaseCase::SampleMaskBaseCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, int renderSize, ShaderRunMode runMode, int flags)
1069 : MultisampleRenderCase (context, name, desc, sampleCount, target, renderSize, flags)
1070 , m_runMode (runMode)
1071 {
1072 DE_ASSERT(runMode < RUN_LAST);
1073 }
1074
~SampleMaskBaseCase(void)1075 SampleMaskBaseCase::~SampleMaskBaseCase (void)
1076 {
1077 }
1078
init(void)1079 void SampleMaskBaseCase::init (void)
1080 {
1081 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1082 // required extra extension
1083 if (m_runMode == RUN_PER_TWO_SAMPLES && !isES32 && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
1084 TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
1085
1086 MultisampleRenderCase::init();
1087 }
1088
preDraw(void)1089 void SampleMaskBaseCase::preDraw (void)
1090 {
1091 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1092
1093 if (m_runMode == RUN_PER_TWO_SAMPLES)
1094 {
1095 gl.enable(GL_SAMPLE_SHADING);
1096 gl.minSampleShading(0.5f);
1097 GLU_EXPECT_NO_ERROR(gl.getError(), "enable sample shading");
1098
1099 m_testCtx.getLog() << tcu::TestLog::Message << "Enabled GL_SAMPLE_SHADING, value = 0.5" << tcu::TestLog::EndMessage;
1100 }
1101 }
1102
postDraw(void)1103 void SampleMaskBaseCase::postDraw (void)
1104 {
1105 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1106
1107 if (m_runMode == RUN_PER_TWO_SAMPLES)
1108 {
1109 gl.disable(GL_SAMPLE_SHADING);
1110 gl.minSampleShading(1.0f);
1111 GLU_EXPECT_NO_ERROR(gl.getError(), "disable sample shading");
1112 }
1113 }
1114
verifyImage(const tcu::Surface & resultImage)1115 bool SampleMaskBaseCase::verifyImage (const tcu::Surface& resultImage)
1116 {
1117 // shader does the verification
1118 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier());
1119 }
1120
1121 class SampleMaskCase : public SampleMaskBaseCase
1122 {
1123 public:
1124 SampleMaskCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
1125 ~SampleMaskCase (void);
1126
1127 void init (void);
1128 void preDraw (void);
1129 void postDraw (void);
1130
1131 private:
1132 enum
1133 {
1134 RENDER_SIZE = 64
1135 };
1136
1137 std::string genFragmentSource (int numTargetSamples) const;
1138 };
1139
SampleMaskCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target)1140 SampleMaskCase::SampleMaskCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target)
1141 : SampleMaskBaseCase(context, name, desc, sampleCount, target, RENDER_SIZE, RUN_PER_PIXEL)
1142 {
1143 }
1144
~SampleMaskCase(void)1145 SampleMaskCase::~SampleMaskCase (void)
1146 {
1147 }
1148
init(void)1149 void SampleMaskCase::init (void)
1150 {
1151 // log the test method and expectations
1152 m_testCtx.getLog()
1153 << tcu::TestLog::Message
1154 << "Verifying gl_SampleMaskIn value with SAMPLE_MASK state. gl_SampleMaskIn does not contain any bits set that are have been killed by SAMPLE_MASK state. Expecting:\n"
1155 << " 1) With multisample targets: gl_SampleMaskIn AND ~(SAMPLE_MASK) should be zero.\n"
1156 << " 2) With non-multisample targets: SAMPLE_MASK state is only ANDed as a multisample operation. gl_SampleMaskIn should only have its last bit set regardless of SAMPLE_MASK state.\n"
1157 << tcu::TestLog::EndMessage;
1158
1159 SampleMaskBaseCase::init();
1160 }
1161
preDraw(void)1162 void SampleMaskCase::preDraw (void)
1163 {
1164 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1165 const bool multisampleTarget = (m_numRequestedSamples > 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1);
1166 const deUint32 fullMask = (deUint32)0xAAAAAAAAUL;
1167 const deUint32 maskMask = (1U << m_numTargetSamples) - 1;
1168 const deUint32 effectiveMask = fullMask & maskMask;
1169
1170 // set test mask
1171 gl.enable(GL_SAMPLE_MASK);
1172 gl.sampleMaski(0, effectiveMask);
1173 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask");
1174
1175 m_testCtx.getLog() << tcu::TestLog::Message << "Setting sample mask " << tcu::Format::Hex<4>(effectiveMask) << tcu::TestLog::EndMessage;
1176
1177 // set multisample case uniforms
1178 if (multisampleTarget)
1179 {
1180 const int maskLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampleMask");
1181 if (maskLoc == -1)
1182 throw tcu::TestError("Location of u_mask was -1");
1183
1184 gl.uniform1ui(maskLoc, effectiveMask);
1185 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask uniform");
1186 }
1187
1188 // base class logic
1189 SampleMaskBaseCase::preDraw();
1190 }
1191
postDraw(void)1192 void SampleMaskCase::postDraw (void)
1193 {
1194 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1195 const deUint32 fullMask = (1U << m_numTargetSamples) - 1;
1196
1197 gl.disable(GL_SAMPLE_MASK);
1198 gl.sampleMaski(0, fullMask);
1199 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask");
1200
1201 // base class logic
1202 SampleMaskBaseCase::postDraw();
1203 }
1204
genFragmentSource(int numTargetSamples) const1205 std::string SampleMaskCase::genFragmentSource (int numTargetSamples) const
1206 {
1207 DE_ASSERT(numTargetSamples != 0);
1208
1209 const bool multisampleTarget = (m_numRequestedSamples > 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1);
1210 std::ostringstream buf;
1211 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1212 map<string, string> args;
1213 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
1214 args["GLSL_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
1215
1216 // test supports only one sample mask word
1217 if (numTargetSamples > 32)
1218 TCU_THROW(NotSupportedError, "Sample count larger than 32 is not supported.");
1219
1220 if (multisampleTarget)
1221 {
1222 buf << "${GLSL_VERSION_DECL}\n"
1223 "${GLSL_EXTENSION}\n"
1224 "layout(location = 0) out mediump vec4 fragColor;\n"
1225 "uniform highp uint u_sampleMask;\n"
1226 "void main (void)\n"
1227 "{\n"
1228 " if ((uint(gl_SampleMaskIn[0]) & (~u_sampleMask)) != 0u)\n"
1229 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1230 " else\n"
1231 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1232 "}\n";
1233 }
1234 else
1235 {
1236 // non-multisample targets don't get multisample operations like ANDing with mask
1237
1238 buf << "${GLSL_VERSION_DECL}\n"
1239 "${GLSL_EXTENSION}\n"
1240 "layout(location = 0) out mediump vec4 fragColor;\n"
1241 "uniform highp uint u_sampleMask;\n"
1242 "void main (void)\n"
1243 "{\n"
1244 " if (gl_SampleMaskIn[0] != 1)\n"
1245 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1246 " else\n"
1247 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1248 "}\n";
1249 }
1250
1251 return tcu::StringTemplate(buf.str()).specialize(args);
1252 }
1253
1254 class SampleMaskCountCase : public SampleMaskBaseCase
1255 {
1256 public:
1257 SampleMaskCountCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode);
1258 ~SampleMaskCountCase (void);
1259
1260 void init (void);
1261 void preDraw (void);
1262 void postDraw (void);
1263
1264 private:
1265 enum
1266 {
1267 RENDER_SIZE = 64
1268 };
1269
1270 std::string genFragmentSource (int numTargetSamples) const;
1271 };
1272
SampleMaskCountCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target,ShaderRunMode runMode)1273 SampleMaskCountCase::SampleMaskCountCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode)
1274 : SampleMaskBaseCase(context, name, desc, sampleCount, target, RENDER_SIZE, runMode)
1275 {
1276 DE_ASSERT(runMode < RUN_LAST);
1277 }
1278
~SampleMaskCountCase(void)1279 SampleMaskCountCase::~SampleMaskCountCase (void)
1280 {
1281 }
1282
init(void)1283 void SampleMaskCountCase::init (void)
1284 {
1285 // log the test method and expectations
1286 if (m_runMode == RUN_PER_PIXEL)
1287 m_testCtx.getLog()
1288 << tcu::TestLog::Message
1289 << "Verifying gl_SampleMaskIn.\n"
1290 << " Fragment shader may be invoked [1, numSamples] times.\n"
1291 << " => gl_SampleMaskIn should have the number of bits set in range [1, numSamples]\n"
1292 << tcu::TestLog::EndMessage;
1293 else if (m_runMode == RUN_PER_SAMPLE)
1294 m_testCtx.getLog()
1295 << tcu::TestLog::Message
1296 << "Verifying gl_SampleMaskIn.\n"
1297 << " Fragment will be invoked numSamples times.\n"
1298 << " => gl_SampleMaskIn should have only one bit set.\n"
1299 << tcu::TestLog::EndMessage;
1300 else if (m_runMode == RUN_PER_TWO_SAMPLES)
1301 m_testCtx.getLog()
1302 << tcu::TestLog::Message
1303 << "Verifying gl_SampleMaskIn.\n"
1304 << " Fragment shader may be invoked [ceil(numSamples/2), numSamples] times.\n"
1305 << " => gl_SampleMaskIn should have the number of bits set in range [1, numSamples - ceil(numSamples/2) + 1]:\n"
1306 << tcu::TestLog::EndMessage;
1307 else
1308 DE_ASSERT(false);
1309
1310 SampleMaskBaseCase::init();
1311 }
1312
preDraw(void)1313 void SampleMaskCountCase::preDraw (void)
1314 {
1315 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1316
1317 if (m_runMode == RUN_PER_PIXEL)
1318 {
1319 const int maxLoc = gl.getUniformLocation(m_program->getProgram(), "u_maxBitCount");
1320 const int minLoc = gl.getUniformLocation(m_program->getProgram(), "u_minBitCount");
1321 const int minBitCount = 1;
1322 const int maxBitCount = m_numTargetSamples;
1323
1324 if (maxLoc == -1)
1325 throw tcu::TestError("Location of u_maxBitCount was -1");
1326 if (minLoc == -1)
1327 throw tcu::TestError("Location of u_minBitCount was -1");
1328
1329 gl.uniform1i(minLoc, minBitCount);
1330 gl.uniform1i(maxLoc, maxBitCount);
1331 GLU_EXPECT_NO_ERROR(gl.getError(), "set limits");
1332
1333 m_testCtx.getLog() << tcu::TestLog::Message << "Setting minBitCount = " << minBitCount << ", maxBitCount = " << maxBitCount << tcu::TestLog::EndMessage;
1334 }
1335 else if (m_runMode == RUN_PER_TWO_SAMPLES)
1336 {
1337 const int maxLoc = gl.getUniformLocation(m_program->getProgram(), "u_maxBitCount");
1338 const int minLoc = gl.getUniformLocation(m_program->getProgram(), "u_minBitCount");
1339
1340 // Worst case: all but one shader invocations get one sample, one shader invocation the rest of the samples
1341 const int minInvocationCount = ((m_numTargetSamples + 1) / 2);
1342 const int minBitCount = 1;
1343 const int maxBitCount = (m_numTargetSamples <= 2) ? (1) : (m_numTargetSamples - ((minInvocationCount-1) * minBitCount));
1344
1345 if (maxLoc == -1)
1346 throw tcu::TestError("Location of u_maxBitCount was -1");
1347 if (minLoc == -1)
1348 throw tcu::TestError("Location of u_minBitCount was -1");
1349
1350 gl.uniform1i(minLoc, minBitCount);
1351 gl.uniform1i(maxLoc, maxBitCount);
1352 GLU_EXPECT_NO_ERROR(gl.getError(), "set limits");
1353
1354 m_testCtx.getLog() << tcu::TestLog::Message << "Setting minBitCount = " << minBitCount << ", maxBitCount = " << maxBitCount << tcu::TestLog::EndMessage;
1355 }
1356
1357 SampleMaskBaseCase::preDraw();
1358 }
1359
postDraw(void)1360 void SampleMaskCountCase::postDraw (void)
1361 {
1362 SampleMaskBaseCase::postDraw();
1363 }
1364
genFragmentSource(int numTargetSamples) const1365 std::string SampleMaskCountCase::genFragmentSource (int numTargetSamples) const
1366 {
1367 DE_ASSERT(numTargetSamples != 0);
1368
1369 std::ostringstream buf;
1370 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1371 map<string, string> args;
1372 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
1373 args["GLSL_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
1374
1375 // test supports only one sample mask word
1376 if (numTargetSamples > 32)
1377 TCU_THROW(NotSupportedError, "Sample count larger than 32 is not supported.");
1378
1379 // count the number of the bits in gl_SampleMask
1380
1381 buf << "${GLSL_VERSION_DECL}\n"
1382 "${GLSL_EXTENSION}\n"
1383 "layout(location = 0) out mediump vec4 fragColor;\n";
1384
1385 if (m_runMode != RUN_PER_SAMPLE)
1386 buf << "uniform highp int u_minBitCount;\n"
1387 "uniform highp int u_maxBitCount;\n";
1388
1389 buf << "void main (void)\n"
1390 "{\n"
1391 " mediump int maskBitCount = 0;\n"
1392 " for (int i = 0; i < 32; ++i)\n"
1393 " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n"
1394 " ++maskBitCount;\n"
1395 "\n";
1396
1397 if (m_runMode == RUN_PER_SAMPLE)
1398 {
1399 // check the validity here
1400 buf << " // force per-sample shading\n"
1401 " highp float blue = float(gl_SampleID);\n"
1402 "\n"
1403 " if (maskBitCount != 1)\n"
1404 " fragColor = vec4(1.0, 0.0, blue, 1.0);\n"
1405 " else\n"
1406 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n"
1407 "}\n";
1408 }
1409 else
1410 {
1411 // check the validity here
1412 buf << " if (maskBitCount < u_minBitCount || maskBitCount > u_maxBitCount)\n"
1413 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1414 " else\n"
1415 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1416 "}\n";
1417 }
1418
1419 return tcu::StringTemplate(buf.str()).specialize(args);
1420 }
1421
1422 class SampleMaskUniqueCase : public SampleMaskBaseCase
1423 {
1424 public:
1425 SampleMaskUniqueCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode);
1426 ~SampleMaskUniqueCase (void);
1427
1428 void init (void);
1429
1430 private:
1431 enum
1432 {
1433 RENDER_SIZE = 64
1434 };
1435
1436 std::string genFragmentSource (int numTargetSamples) const;
1437 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers);
1438 };
1439
SampleMaskUniqueCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target,ShaderRunMode runMode)1440 SampleMaskUniqueCase::SampleMaskUniqueCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode)
1441 : SampleMaskBaseCase(context, name, desc, sampleCount, target, RENDER_SIZE, runMode, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS)
1442 {
1443 DE_ASSERT(runMode == RUN_PER_SAMPLE);
1444 DE_ASSERT(target == TARGET_TEXTURE);
1445 }
1446
~SampleMaskUniqueCase(void)1447 SampleMaskUniqueCase::~SampleMaskUniqueCase (void)
1448 {
1449 }
1450
init(void)1451 void SampleMaskUniqueCase::init (void)
1452 {
1453 // log the test method and expectations
1454 m_testCtx.getLog()
1455 << tcu::TestLog::Message
1456 << "Verifying gl_SampleMaskIn.\n"
1457 << " Fragment will be invoked numSamples times.\n"
1458 << " => gl_SampleMaskIn should have only one bit set\n"
1459 << " => and that bit index should be unique within other fragment shader invocations of that pixel.\n"
1460 << " Writing sampleMask bit index to green channel in render shader. Verifying uniqueness in sampler shader.\n"
1461 << tcu::TestLog::EndMessage;
1462
1463 SampleMaskBaseCase::init();
1464 }
1465
genFragmentSource(int numTargetSamples) const1466 std::string SampleMaskUniqueCase::genFragmentSource (int numTargetSamples) const
1467 {
1468 DE_ASSERT(numTargetSamples != 0);
1469
1470 std::ostringstream buf;
1471 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1472 map<string, string> args;
1473 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
1474 args["GLSL_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
1475
1476 // test supports only one sample mask word
1477 if (numTargetSamples > 32)
1478 TCU_THROW(NotSupportedError, "Sample count larger than 32 is not supported.");
1479
1480 // find our sampleID by searching for unique bit.
1481 buf << "${GLSL_VERSION_DECL}\n"
1482 "${GLSL_EXTENSION}\n"
1483 "layout(location = 0) out mediump vec4 fragColor;\n"
1484 "void main (void)\n"
1485 "{\n"
1486 " mediump int firstIndex = -1;\n"
1487 " for (int i = 0; i < 32; ++i)\n"
1488 " {\n"
1489 " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n"
1490 " {\n"
1491 " firstIndex = i;\n"
1492 " break;\n"
1493 " }\n"
1494 " }\n"
1495 "\n"
1496 " bool notUniqueError = false;\n"
1497 " for (int i = firstIndex + 1; i < 32; ++i)\n"
1498 " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n"
1499 " notUniqueError = true;\n"
1500 "\n"
1501 " highp float encodedSampleId = float(firstIndex) / " << numTargetSamples <<".0;\n"
1502 "\n"
1503 " // force per-sample shading\n"
1504 " highp float blue = float(gl_SampleID);\n"
1505 "\n"
1506 " if (notUniqueError)\n"
1507 " fragColor = vec4(1.0, 0.0, blue, 1.0);\n"
1508 " else\n"
1509 " fragColor = vec4(0.0, encodedSampleId, blue, 1.0);\n"
1510 "}\n";
1511
1512 return tcu::StringTemplate(buf.str()).specialize(args);
1513 }
1514
verifySampleBuffers(const std::vector<tcu::Surface> & resultBuffers)1515 bool SampleMaskUniqueCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
1516 {
1517 const int width = resultBuffers[0].getWidth();
1518 const int height = resultBuffers[0].getHeight();
1519 bool allOk = true;
1520
1521 // Log samples
1522 {
1523 m_testCtx.getLog() << tcu::TestLog::ImageSet("SampleBuffers", "Image sample buffers");
1524 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
1525 m_testCtx.getLog() << tcu::TestLog::Image("Buffer" + de::toString(sampleNdx), "Sample " + de::toString(sampleNdx), resultBuffers[sampleNdx].getAccess());
1526 m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1527 }
1528
1529 // check for earlier errors (in fragment shader)
1530 {
1531 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying fragment shader invocation found only one set sample mask bit." << tcu::TestLog::EndMessage;
1532
1533 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
1534 {
1535 // shader does the check, just check the shader error output (red)
1536 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample " << (sampleNdx+1) << "/" << (int)resultBuffers.size() << tcu::TestLog::EndMessage;
1537 allOk &= verifyImageWithVerifier(resultBuffers[sampleNdx], m_testCtx.getLog(), NoRedVerifier(), false);
1538 }
1539
1540 if (!allOk)
1541 {
1542 // can't check the uniqueness if the masks don't work at all
1543 m_testCtx.getLog() << tcu::TestLog::Message << "Could not get mask information from the rendered image, cannot continue verification." << tcu::TestLog::EndMessage;
1544 return false;
1545 }
1546 }
1547
1548 // verify index / index ranges
1549
1550 if (m_numRequestedSamples == 0)
1551 {
1552 // single sample target, expect index=0
1553
1554 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample mask bit index is 0." << tcu::TestLog::EndMessage;
1555
1556 // only check the mask index
1557 allOk &= verifyImageWithVerifier(resultBuffers[0], m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::IVec3(255, 8, 255)), false);
1558 }
1559 else
1560 {
1561 // check uniqueness
1562
1563 tcu::Surface errorMask (width, height);
1564 bool uniquenessOk = true;
1565 int printCount = 0;
1566 const int printFloodLimit = 5;
1567 std::vector<int> maskBitIndices (resultBuffers.size());
1568
1569 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1570
1571 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying per-invocation sample mask bit is unique." << tcu::TestLog::EndMessage;
1572
1573 for (int y = 0; y < height; ++y)
1574 for (int x = 0; x < width; ++x)
1575 {
1576 bool maskNdxNotUnique = false;
1577
1578 // decode index
1579 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
1580 {
1581 const tcu::RGBA color = resultBuffers[sampleNdx].getPixel(x, y);
1582 maskBitIndices[sampleNdx] = (int)deFloatRound((float)color.getGreen() / 255.0f * (float)m_numTargetSamples);
1583 }
1584
1585 // just check there are no two invocations with the same bit index
1586 for (int sampleNdxA = 0; sampleNdxA < (int)resultBuffers.size() && (!maskNdxNotUnique || printCount < printFloodLimit); ++sampleNdxA)
1587 for (int sampleNdxB = sampleNdxA+1; sampleNdxB < (int)resultBuffers.size() && (!maskNdxNotUnique || printCount < printFloodLimit); ++sampleNdxB)
1588 {
1589 if (maskBitIndices[sampleNdxA] == maskBitIndices[sampleNdxB])
1590 {
1591 if (++printCount <= printFloodLimit)
1592 {
1593 m_testCtx.getLog()
1594 << tcu::TestLog::Message
1595 << "Pixel (" << x << ", " << y << "): Samples " << sampleNdxA << " and " << sampleNdxB << " have the same sample mask. (Single bit at index " << maskBitIndices[sampleNdxA] << ")"
1596 << tcu::TestLog::EndMessage;
1597 }
1598
1599 maskNdxNotUnique = true;
1600 uniquenessOk = false;
1601 errorMask.setPixel(x, y, tcu::RGBA::red());
1602 }
1603 }
1604 }
1605
1606 // end result
1607 if (!uniquenessOk)
1608 {
1609 if (printCount > printFloodLimit)
1610 m_testCtx.getLog()
1611 << tcu::TestLog::Message
1612 << "...\n"
1613 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
1614 << tcu::TestLog::EndMessage;
1615
1616 m_testCtx.getLog()
1617 << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage
1618 << tcu::TestLog::ImageSet("Verification", "Image Verification")
1619 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask.getAccess())
1620 << tcu::TestLog::EndImageSet;
1621
1622 allOk = false;
1623 }
1624 }
1625
1626 return allOk;
1627 }
1628
1629 class SampleMaskUniqueSetCase : public SampleMaskBaseCase
1630 {
1631 public:
1632 SampleMaskUniqueSetCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode);
1633 ~SampleMaskUniqueSetCase (void);
1634
1635 void init (void);
1636 void deinit (void);
1637
1638 private:
1639 enum
1640 {
1641 RENDER_SIZE = 64
1642 };
1643
1644 void preDraw (void);
1645 void postDraw (void);
1646 std::string genFragmentSource (int numTargetSamples) const;
1647 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers);
1648 std::string getIterationDescription (int iteration) const;
1649
1650 void preTest (void);
1651 void postTest (void);
1652
1653 std::vector<tcu::Surface> m_iterationSampleBuffers;
1654 };
1655
SampleMaskUniqueSetCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target,ShaderRunMode runMode)1656 SampleMaskUniqueSetCase::SampleMaskUniqueSetCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode)
1657 : SampleMaskBaseCase(context, name, desc, sampleCount, target, RENDER_SIZE, runMode, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS)
1658 {
1659 DE_ASSERT(runMode == RUN_PER_TWO_SAMPLES);
1660 DE_ASSERT(target == TARGET_TEXTURE);
1661
1662 // high and low bits
1663 m_numIterations = 2;
1664 }
1665
~SampleMaskUniqueSetCase(void)1666 SampleMaskUniqueSetCase::~SampleMaskUniqueSetCase (void)
1667 {
1668 }
1669
init(void)1670 void SampleMaskUniqueSetCase::init (void)
1671 {
1672 // log the test method and expectations
1673 m_testCtx.getLog()
1674 << tcu::TestLog::Message
1675 << "Verifying gl_SampleMaskIn.\n"
1676 << " Fragment shader may be invoked [ceil(numSamples/2), numSamples] times.\n"
1677 << " => Each invocation should have unique bit set\n"
1678 << " Writing highest and lowest bit index to color channels in render shader. Verifying:\n"
1679 << " 1) no other invocation contains these bits in sampler shader.\n"
1680 << " 2) number of invocations is at least ceil(numSamples/2).\n"
1681 << tcu::TestLog::EndMessage;
1682
1683 SampleMaskBaseCase::init();
1684 }
1685
deinit(void)1686 void SampleMaskUniqueSetCase::deinit (void)
1687 {
1688 m_iterationSampleBuffers.clear();
1689 }
1690
preDraw(void)1691 void SampleMaskUniqueSetCase::preDraw (void)
1692 {
1693 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1694 const int selectorLoc = gl.getUniformLocation(m_program->getProgram(), "u_bitSelector");
1695
1696 gl.uniform1ui(selectorLoc, (deUint32)m_iteration);
1697 GLU_EXPECT_NO_ERROR(gl.getError(), "set u_bitSelector");
1698
1699 m_testCtx.getLog() << tcu::TestLog::Message << "Setting u_bitSelector = " << m_iteration << tcu::TestLog::EndMessage;
1700
1701 SampleMaskBaseCase::preDraw();
1702 }
1703
postDraw(void)1704 void SampleMaskUniqueSetCase::postDraw (void)
1705 {
1706 SampleMaskBaseCase::postDraw();
1707 }
1708
genFragmentSource(int numTargetSamples) const1709 std::string SampleMaskUniqueSetCase::genFragmentSource (int numTargetSamples) const
1710 {
1711 DE_ASSERT(numTargetSamples != 0);
1712
1713 std::ostringstream buf;
1714 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
1715 map<string, string> args;
1716 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
1717 args["GLSL_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
1718
1719 // test supports only one sample mask word
1720 if (numTargetSamples > 32)
1721 TCU_THROW(NotSupportedError, "Sample count larger than 32 is not supported.");
1722
1723 // output min and max sample id
1724 buf << "${GLSL_VERSION_DECL}\n"
1725 "${GLSL_EXTENSION}\n"
1726 "uniform highp uint u_bitSelector;\n"
1727 "layout(location = 0) out mediump vec4 fragColor;\n"
1728 "void main (void)\n"
1729 "{\n"
1730 " highp int selectedBits;\n"
1731 " if (u_bitSelector == 0u)\n"
1732 " selectedBits = (gl_SampleMaskIn[0] & 0xFFFF);\n"
1733 " else\n"
1734 " selectedBits = ((gl_SampleMaskIn[0] >> 16) & 0xFFFF);\n"
1735 "\n"
1736 " // encode bits to color\n"
1737 " highp int redBits = selectedBits & 31;\n"
1738 " highp int greenBits = (selectedBits >> 5) & 63;\n"
1739 " highp int blueBits = (selectedBits >> 11) & 31;\n"
1740 "\n"
1741 " fragColor = vec4(float(redBits) / float(31), float(greenBits) / float(63), float(blueBits) / float(31), 1.0);\n"
1742 "}\n";
1743
1744 return tcu::StringTemplate(buf.str()).specialize(args);
1745 }
1746
verifySampleBuffers(const std::vector<tcu::Surface> & resultBuffers)1747 bool SampleMaskUniqueSetCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
1748 {
1749 // we need results from all passes to do verification. Store results and verify later (at postTest).
1750
1751 DE_ASSERT(m_numTargetSamples == (int)resultBuffers.size());
1752 for (int ndx = 0; ndx < m_numTargetSamples; ++ndx)
1753 m_iterationSampleBuffers[m_iteration * m_numTargetSamples + ndx] = resultBuffers[ndx];
1754
1755 return true;
1756 }
1757
getIterationDescription(int iteration) const1758 std::string SampleMaskUniqueSetCase::getIterationDescription (int iteration) const
1759 {
1760 if (iteration == 0)
1761 return "Reading low bits";
1762 else if (iteration == 1)
1763 return "Reading high bits";
1764 else
1765 DE_ASSERT(false);
1766 return "";
1767 }
1768
preTest(void)1769 void SampleMaskUniqueSetCase::preTest (void)
1770 {
1771 m_iterationSampleBuffers.resize(m_numTargetSamples * 2);
1772 }
1773
postTest(void)1774 void SampleMaskUniqueSetCase::postTest (void)
1775 {
1776 DE_ASSERT((m_iterationSampleBuffers.size() % 2) == 0);
1777 DE_ASSERT((int)m_iterationSampleBuffers.size() / 2 == m_numTargetSamples);
1778
1779 const int width = m_iterationSampleBuffers[0].getWidth();
1780 const int height = m_iterationSampleBuffers[0].getHeight();
1781 bool allOk = true;
1782 std::vector<tcu::TextureLevel> sampleCoverage (m_numTargetSamples);
1783 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Verify", "Verify masks");
1784
1785 // convert color layers to 32 bit coverage masks, 2 passes per coverage
1786
1787 for (int sampleNdx = 0; sampleNdx < (int)sampleCoverage.size(); ++sampleNdx)
1788 {
1789 sampleCoverage[sampleNdx].setStorage(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32), width, height);
1790
1791 for (int y = 0; y < height; ++y)
1792 for (int x = 0; x < width; ++x)
1793 {
1794 const tcu::RGBA lowColor = m_iterationSampleBuffers[sampleNdx].getPixel(x, y);
1795 const tcu::RGBA highColor = m_iterationSampleBuffers[sampleNdx + (int)sampleCoverage.size()].getPixel(x, y);
1796 deUint16 low;
1797 deUint16 high;
1798
1799 {
1800 int redBits = (int)deFloatRound((float)lowColor.getRed() / 255.0f * 31);
1801 int greenBits = (int)deFloatRound((float)lowColor.getGreen() / 255.0f * 63);
1802 int blueBits = (int)deFloatRound((float)lowColor.getBlue() / 255.0f * 31);
1803
1804 low = (deUint16)(redBits | (greenBits << 5) | (blueBits << 11));
1805 }
1806 {
1807 int redBits = (int)deFloatRound((float)highColor.getRed() / 255.0f * 31);
1808 int greenBits = (int)deFloatRound((float)highColor.getGreen() / 255.0f * 63);
1809 int blueBits = (int)deFloatRound((float)highColor.getBlue() / 255.0f * 31);
1810
1811 high = (deUint16)(redBits | (greenBits << 5) | (blueBits << 11));
1812 }
1813
1814 sampleCoverage[sampleNdx].getAccess().setPixel(tcu::UVec4((((deUint32)high) << 16) | low, 0, 0, 0), x, y);
1815 }
1816 }
1817
1818 // verify masks
1819
1820 if (m_numRequestedSamples == 0)
1821 {
1822 // single sample target, expect mask = 0x01
1823 const int printFloodLimit = 5;
1824 int printCount = 0;
1825
1826 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample mask is 0x00000001." << tcu::TestLog::EndMessage;
1827
1828 for (int y = 0; y < height; ++y)
1829 for (int x = 0; x < width; ++x)
1830 {
1831 deUint32 mask = sampleCoverage[0].getAccess().getPixelUint(x, y).x();
1832 if (mask != 0x01)
1833 {
1834 allOk = false;
1835
1836 if (++printCount <= printFloodLimit)
1837 {
1838 m_testCtx.getLog()
1839 << tcu::TestLog::Message
1840 << "Pixel (" << x << ", " << y << "): Invalid mask, got " << tcu::Format::Hex<8>(mask) << ", expected " << tcu::Format::Hex<8>(0x01) << "\n"
1841 << tcu::TestLog::EndMessage;
1842 }
1843 }
1844 }
1845
1846 if (!allOk && printCount > printFloodLimit)
1847 {
1848 m_testCtx.getLog()
1849 << tcu::TestLog::Message
1850 << "...\n"
1851 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
1852 << tcu::TestLog::EndMessage;
1853 }
1854 }
1855 else
1856 {
1857 // check uniqueness
1858 {
1859 bool uniquenessOk = true;
1860 int printCount = 0;
1861 const int printFloodLimit = 5;
1862
1863 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying invocation sample masks do not share bits." << tcu::TestLog::EndMessage;
1864
1865 for (int y = 0; y < height; ++y)
1866 for (int x = 0; x < width; ++x)
1867 {
1868 bool maskBitsNotUnique = false;
1869
1870 for (int sampleNdxA = 0; sampleNdxA < m_numTargetSamples && (!maskBitsNotUnique || printCount < printFloodLimit); ++sampleNdxA)
1871 for (int sampleNdxB = sampleNdxA+1; sampleNdxB < m_numTargetSamples && (!maskBitsNotUnique || printCount < printFloodLimit); ++sampleNdxB)
1872 {
1873 const deUint32 maskA = sampleCoverage[sampleNdxA].getAccess().getPixelUint(x, y).x();
1874 const deUint32 maskB = sampleCoverage[sampleNdxB].getAccess().getPixelUint(x, y).x();
1875
1876 // equal mask == emitted by the same invocation
1877 if (maskA != maskB)
1878 {
1879 // shares samples?
1880 if (maskA & maskB)
1881 {
1882 maskBitsNotUnique = true;
1883 uniquenessOk = false;
1884
1885 if (++printCount <= printFloodLimit)
1886 {
1887 m_testCtx.getLog()
1888 << tcu::TestLog::Message
1889 << "Pixel (" << x << ", " << y << "):\n"
1890 << "\tSamples " << sampleNdxA << " and " << sampleNdxB << " share mask bits\n"
1891 << "\tMask" << sampleNdxA << " = " << tcu::Format::Hex<8>(maskA) << "\n"
1892 << "\tMask" << sampleNdxB << " = " << tcu::Format::Hex<8>(maskB) << "\n"
1893 << tcu::TestLog::EndMessage;
1894 }
1895 }
1896 }
1897 }
1898 }
1899
1900 if (!uniquenessOk)
1901 {
1902 allOk = false;
1903
1904 if (printCount > printFloodLimit)
1905 m_testCtx.getLog()
1906 << tcu::TestLog::Message
1907 << "...\n"
1908 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
1909 << tcu::TestLog::EndMessage;
1910 }
1911 }
1912
1913 // check number of sample mask bit groups is valid ( == number of invocations )
1914 {
1915 const deUint32 minNumInvocations = (deUint32)de::max(1, (m_numTargetSamples+1)/2);
1916 bool countOk = true;
1917 int printCount = 0;
1918 const int printFloodLimit = 5;
1919
1920 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying cardinality of separate sample mask bit sets. Expecting equal to the number of invocations, (greater or equal to " << minNumInvocations << ")" << tcu::TestLog::EndMessage;
1921
1922 for (int y = 0; y < height; ++y)
1923 for (int x = 0; x < width; ++x)
1924 {
1925 std::set<deUint32> masks;
1926
1927 for (int maskNdx = 0; maskNdx < m_numTargetSamples; ++maskNdx)
1928 {
1929 const deUint32 mask = sampleCoverage[maskNdx].getAccess().getPixelUint(x, y).x();
1930 masks.insert(mask);
1931 }
1932
1933 if ((int)masks.size() < (int)minNumInvocations)
1934 {
1935 if (++printCount <= printFloodLimit)
1936 {
1937 m_testCtx.getLog()
1938 << tcu::TestLog::Message
1939 << "Pixel (" << x << ", " << y << "): Pixel invocations had only " << (int)masks.size() << " separate mask sets. Expected " << minNumInvocations << " or more. Found masks:"
1940 << tcu::TestLog::EndMessage;
1941
1942 for (std::set<deUint32>::iterator it = masks.begin(); it != masks.end(); ++it)
1943 m_testCtx.getLog()
1944 << tcu::TestLog::Message
1945 << "\tMask: " << tcu::Format::Hex<8>(*it) << "\n"
1946 << tcu::TestLog::EndMessage;
1947 }
1948
1949 countOk = false;
1950 }
1951 }
1952
1953 if (!countOk)
1954 {
1955 allOk = false;
1956
1957 if (printCount > printFloodLimit)
1958 m_testCtx.getLog()
1959 << tcu::TestLog::Message
1960 << "...\n"
1961 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
1962 << tcu::TestLog::EndMessage;
1963 }
1964 }
1965 }
1966
1967 if (!allOk)
1968 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
1969 }
1970
1971 class SampleMaskWriteCase : public SampleMaskBaseCase
1972 {
1973 public:
1974 enum TestMode
1975 {
1976 TEST_DISCARD = 0,
1977 TEST_INVERSE,
1978
1979 TEST_LAST
1980 };
1981 SampleMaskWriteCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode, TestMode testMode);
1982 ~SampleMaskWriteCase (void);
1983
1984 void init (void);
1985 void preDraw (void);
1986 void postDraw (void);
1987
1988 private:
1989 enum
1990 {
1991 RENDER_SIZE = 64
1992 };
1993
1994 std::string genFragmentSource (int numTargetSamples) const;
1995 bool verifyImage (const tcu::Surface& resultImage);
1996
1997 const TestMode m_testMode;
1998 };
1999
SampleMaskWriteCase(Context & context,const char * name,const char * desc,int sampleCount,RenderTarget target,ShaderRunMode runMode,TestMode testMode)2000 SampleMaskWriteCase::SampleMaskWriteCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode, TestMode testMode)
2001 : SampleMaskBaseCase (context, name, desc, sampleCount, target, RENDER_SIZE, runMode)
2002 , m_testMode (testMode)
2003 {
2004 DE_ASSERT(testMode < TEST_LAST);
2005 }
2006
~SampleMaskWriteCase(void)2007 SampleMaskWriteCase::~SampleMaskWriteCase (void)
2008 {
2009 }
2010
init(void)2011 void SampleMaskWriteCase::init (void)
2012 {
2013 // log the test method and expectations
2014 if (m_testMode == TEST_DISCARD)
2015 m_testCtx.getLog()
2016 << tcu::TestLog::Message
2017 << "Discarding half of the samples using gl_SampleMask, expecting:\n"
2018 << " 1) half intensity on multisample targets (numSamples > 1)\n"
2019 << " 2) full discard on multisample targets (numSamples == 1)\n"
2020 << " 3) full intensity (no discard) on singlesample targets. (Mask is only applied as a multisample operation.)\n"
2021 << tcu::TestLog::EndMessage;
2022 else if (m_testMode == TEST_INVERSE)
2023 m_testCtx.getLog()
2024 << tcu::TestLog::Message
2025 << "Discarding half of the samples using GL_SAMPLE_MASK, setting inverse mask in fragment shader using gl_SampleMask, expecting:\n"
2026 << " 1) full discard on multisample targets (mask & modifiedCoverge == 0)\n"
2027 << " 2) full intensity (no discard) on singlesample targets. (Mask and coverage is only applied as a multisample operation.)\n"
2028 << tcu::TestLog::EndMessage;
2029 else
2030 DE_ASSERT(false);
2031
2032 SampleMaskBaseCase::init();
2033 }
2034
preDraw(void)2035 void SampleMaskWriteCase::preDraw (void)
2036 {
2037 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2038
2039 if (m_testMode == TEST_INVERSE)
2040 {
2041 // set mask to 0xAAAA.., set inverse mask bit coverage in shader
2042
2043 const int maskLoc = gl.getUniformLocation(m_program->getProgram(), "u_mask");
2044 const deUint32 mask = (deUint32)0xAAAAAAAAUL;
2045
2046 if (maskLoc == -1)
2047 throw tcu::TestError("Location of u_mask was -1");
2048
2049 gl.enable(GL_SAMPLE_MASK);
2050 gl.sampleMaski(0, mask);
2051 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask");
2052
2053 gl.uniform1ui(maskLoc, mask);
2054 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask uniform");
2055
2056 m_testCtx.getLog() << tcu::TestLog::Message << "Setting sample mask " << tcu::Format::Hex<4>(mask) << tcu::TestLog::EndMessage;
2057 }
2058
2059 SampleMaskBaseCase::preDraw();
2060 }
2061
postDraw(void)2062 void SampleMaskWriteCase::postDraw (void)
2063 {
2064 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2065
2066 if (m_testMode == TEST_INVERSE)
2067 {
2068 const deUint32 fullMask = (1U << m_numTargetSamples) - 1;
2069
2070 gl.disable(GL_SAMPLE_MASK);
2071 gl.sampleMaski(0, fullMask);
2072 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask");
2073 }
2074
2075 SampleMaskBaseCase::postDraw();
2076 }
2077
genFragmentSource(int numTargetSamples) const2078 std::string SampleMaskWriteCase::genFragmentSource (int numTargetSamples) const
2079 {
2080 DE_ASSERT(numTargetSamples != 0);
2081 DE_UNREF(numTargetSamples);
2082
2083 std::ostringstream buf;
2084 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
2085 map<string, string> args;
2086 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
2087 args["GLSL_EXTENSION"] = isES32 ? "" : "#extension GL_OES_sample_variables : require";
2088
2089 if (m_testMode == TEST_DISCARD)
2090 {
2091 // mask out every other coverage bit
2092
2093 buf << "${GLSL_VERSION_DECL}\n"
2094 "${GLSL_EXTENSION}\n"
2095 "layout(location = 0) out mediump vec4 fragColor;\n"
2096 "void main (void)\n"
2097 "{\n"
2098 " for (int i = 0; i < gl_SampleMask.length(); ++i)\n"
2099 " gl_SampleMask[i] = int(0xAAAAAAAA);\n"
2100 "\n";
2101
2102 if (m_runMode == RUN_PER_SAMPLE)
2103 buf << " // force per-sample shading\n"
2104 " highp float blue = float(gl_SampleID);\n"
2105 "\n"
2106 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n"
2107 "}\n";
2108 else
2109 buf << " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2110 "}\n";
2111 }
2112 else if (m_testMode == TEST_INVERSE)
2113 {
2114 // inverse every coverage bit
2115
2116 buf << "${GLSL_VERSION_DECL}\n"
2117 "${GLSL_EXTENSION}\n"
2118 "layout(location = 0) out mediump vec4 fragColor;\n"
2119 "uniform highp uint u_mask;\n"
2120 "void main (void)\n"
2121 "{\n"
2122 " gl_SampleMask[0] = int(~u_mask);\n"
2123 "\n";
2124
2125 if (m_runMode == RUN_PER_SAMPLE)
2126 buf << " // force per-sample shading\n"
2127 " highp float blue = float(gl_SampleID);\n"
2128 "\n"
2129 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n"
2130 "}\n";
2131 else
2132 buf << " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2133 "}\n";
2134 }
2135 else
2136 DE_ASSERT(false);
2137
2138 return tcu::StringTemplate(buf.str()).specialize(args);
2139 }
2140
verifyImage(const tcu::Surface & resultImage)2141 bool SampleMaskWriteCase::verifyImage (const tcu::Surface& resultImage)
2142 {
2143 const bool singleSampleTarget = m_numRequestedSamples == 0 && !(m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1);
2144
2145 if (m_testMode == TEST_DISCARD)
2146 {
2147 if (singleSampleTarget)
2148 {
2149 // single sample case => multisample operations are not effective => don't discard anything
2150 // expect green
2151 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 1.0f, 0.0f)));
2152 }
2153 else if (m_numTargetSamples == 1)
2154 {
2155 // total discard, expect black
2156 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 0.0f, 0.0f)));
2157 }
2158 else
2159 {
2160 // partial discard, expect something between black and green
2161 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), PartialDiscardVerifier());
2162 }
2163 }
2164 else if (m_testMode == TEST_INVERSE)
2165 {
2166 if (singleSampleTarget)
2167 {
2168 // single sample case => multisample operations are not effective => don't discard anything
2169 // expect green
2170 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 1.0f, 0.0f)));
2171 }
2172 else
2173 {
2174 // total discard, expect black
2175 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 0.0f, 0.0f)));
2176 }
2177 }
2178 else
2179 {
2180 DE_ASSERT(false);
2181 return false;
2182 }
2183 }
2184
2185 } // anonymous
2186
SampleVariableTests(Context & context)2187 SampleVariableTests::SampleVariableTests (Context& context)
2188 : TestCaseGroup(context, "sample_variables", "Test sample variables")
2189 {
2190 }
2191
~SampleVariableTests(void)2192 SampleVariableTests::~SampleVariableTests (void)
2193 {
2194 }
2195
init(void)2196 void SampleVariableTests::init (void)
2197 {
2198 tcu::TestCaseGroup* const numSampleGroup = new tcu::TestCaseGroup(m_testCtx, "num_samples", "Test NumSamples");
2199 tcu::TestCaseGroup* const maxSampleGroup = new tcu::TestCaseGroup(m_testCtx, "max_samples", "Test MaxSamples");
2200 tcu::TestCaseGroup* const sampleIDGroup = new tcu::TestCaseGroup(m_testCtx, "sample_id", "Test SampleID");
2201 tcu::TestCaseGroup* const samplePosGroup = new tcu::TestCaseGroup(m_testCtx, "sample_pos", "Test SamplePosition");
2202 tcu::TestCaseGroup* const sampleMaskInGroup = new tcu::TestCaseGroup(m_testCtx, "sample_mask_in", "Test SampleMaskIn");
2203 tcu::TestCaseGroup* const sampleMaskGroup = new tcu::TestCaseGroup(m_testCtx, "sample_mask", "Test SampleMask");
2204
2205 addChild(numSampleGroup);
2206 addChild(maxSampleGroup);
2207 addChild(sampleIDGroup);
2208 addChild(samplePosGroup);
2209 addChild(sampleMaskInGroup);
2210 addChild(sampleMaskGroup);
2211
2212 static const struct RenderTarget
2213 {
2214 const char* name;
2215 const char* desc;
2216 int numSamples;
2217 MultisampleRenderCase::RenderTarget target;
2218 } targets[] =
2219 {
2220 { "default_framebuffer", "Test with default framebuffer", 0, MultisampleRenderCase::TARGET_DEFAULT },
2221 { "singlesample_texture", "Test with singlesample texture", 0, MultisampleRenderCase::TARGET_TEXTURE },
2222 { "multisample_texture_1", "Test with multisample texture", 1, MultisampleRenderCase::TARGET_TEXTURE },
2223 { "multisample_texture_2", "Test with multisample texture", 2, MultisampleRenderCase::TARGET_TEXTURE },
2224 { "multisample_texture_4", "Test with multisample texture", 4, MultisampleRenderCase::TARGET_TEXTURE },
2225 { "multisample_texture_8", "Test with multisample texture", 8, MultisampleRenderCase::TARGET_TEXTURE },
2226 { "multisample_texture_16", "Test with multisample texture", 16, MultisampleRenderCase::TARGET_TEXTURE },
2227 { "singlesample_rbo", "Test with singlesample rbo", 0, MultisampleRenderCase::TARGET_RENDERBUFFER },
2228 { "multisample_rbo_1", "Test with multisample rbo", 1, MultisampleRenderCase::TARGET_RENDERBUFFER },
2229 { "multisample_rbo_2", "Test with multisample rbo", 2, MultisampleRenderCase::TARGET_RENDERBUFFER },
2230 { "multisample_rbo_4", "Test with multisample rbo", 4, MultisampleRenderCase::TARGET_RENDERBUFFER },
2231 { "multisample_rbo_8", "Test with multisample rbo", 8, MultisampleRenderCase::TARGET_RENDERBUFFER },
2232 { "multisample_rbo_16", "Test with multisample rbo", 16, MultisampleRenderCase::TARGET_RENDERBUFFER },
2233 };
2234
2235 // .num_samples
2236 {
2237 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2238 numSampleGroup->addChild(new NumSamplesCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
2239 }
2240
2241 // .max_samples
2242 {
2243 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2244 maxSampleGroup->addChild(new MaxSamplesCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
2245 }
2246
2247 // .sample_ID
2248 {
2249 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2250 sampleIDGroup->addChild(new SampleIDCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
2251 }
2252
2253 // .sample_pos
2254 {
2255 {
2256 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "correctness", "Test SamplePos correctness");
2257 samplePosGroup->addChild(group);
2258
2259 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2260 group->addChild(new SamplePosCorrectnessCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
2261 }
2262
2263 {
2264 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "distribution", "Test SamplePos distribution");
2265 samplePosGroup->addChild(group);
2266
2267 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2268 group->addChild(new SamplePosDistributionCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
2269 }
2270 }
2271
2272 // .sample_mask_in
2273 {
2274 // .sample_mask
2275 {
2276 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "sample_mask", "Test with GL_SAMPLE_MASK");
2277 sampleMaskInGroup->addChild(group);
2278
2279 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2280 group->addChild(new SampleMaskCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target));
2281 }
2282 // .bit_count_per_pixel
2283 {
2284 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_pixel", "Test number of coverage bits");
2285 sampleMaskInGroup->addChild(group);
2286
2287 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2288 group->addChild(new SampleMaskCountCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskCountCase::RUN_PER_PIXEL));
2289 }
2290 // .bit_count_per_sample
2291 {
2292 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_sample", "Test number of coverage bits");
2293 sampleMaskInGroup->addChild(group);
2294
2295 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2296 group->addChild(new SampleMaskCountCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskCountCase::RUN_PER_SAMPLE));
2297 }
2298 // .bit_count_per_two_samples
2299 {
2300 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_two_samples", "Test number of coverage bits");
2301 sampleMaskInGroup->addChild(group);
2302
2303 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2304 group->addChild(new SampleMaskCountCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskCountCase::RUN_PER_TWO_SAMPLES));
2305 }
2306 // .bits_unique_per_sample
2307 {
2308 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bits_unique_per_sample", "Test coverage bits");
2309 sampleMaskInGroup->addChild(group);
2310
2311 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2312 if (targets[targetNdx].target == MultisampleRenderCase::TARGET_TEXTURE)
2313 group->addChild(new SampleMaskUniqueCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskUniqueCase::RUN_PER_SAMPLE));
2314 }
2315 // .bits_unique_per_two_samples
2316 {
2317 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bits_unique_per_two_samples", "Test coverage bits");
2318 sampleMaskInGroup->addChild(group);
2319
2320 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2321 if (targets[targetNdx].target == MultisampleRenderCase::TARGET_TEXTURE)
2322 group->addChild(new SampleMaskUniqueSetCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskUniqueCase::RUN_PER_TWO_SAMPLES));
2323 }
2324 }
2325
2326 // .sample_mask
2327 {
2328 // .discard_half_per_pixel
2329 {
2330 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_pixel", "Test coverage bits");
2331 sampleMaskGroup->addChild(group);
2332
2333 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2334 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_PIXEL, SampleMaskWriteCase::TEST_DISCARD));
2335 }
2336 // .discard_half_per_sample
2337 {
2338 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_sample", "Test coverage bits");
2339 sampleMaskGroup->addChild(group);
2340
2341 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2342 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_SAMPLE, SampleMaskWriteCase::TEST_DISCARD));
2343 }
2344 // .discard_half_per_two_samples
2345 {
2346 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_two_samples", "Test coverage bits");
2347 sampleMaskGroup->addChild(group);
2348
2349 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2350 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_TWO_SAMPLES, SampleMaskWriteCase::TEST_DISCARD));
2351 }
2352
2353 // .discard_half_per_two_samples
2354 {
2355 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_pixel", "Test coverage bits");
2356 sampleMaskGroup->addChild(group);
2357
2358 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2359 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_PIXEL, SampleMaskWriteCase::TEST_INVERSE));
2360 }
2361 // .inverse_per_sample
2362 {
2363 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_sample", "Test coverage bits");
2364 sampleMaskGroup->addChild(group);
2365
2366 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2367 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_SAMPLE, SampleMaskWriteCase::TEST_INVERSE));
2368 }
2369 // .inverse_per_two_samples
2370 {
2371 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_two_samples", "Test coverage bits");
2372 sampleMaskGroup->addChild(group);
2373
2374 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2375 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_TWO_SAMPLES, SampleMaskWriteCase::TEST_INVERSE));
2376 }
2377 }
2378 }
2379
2380 } // Functional
2381 } // gles31
2382 } // deqp
2383