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