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