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