1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Sample variable tests
22 *//*--------------------------------------------------------------------*/
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"
51 virtual bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const = 0;
52 virtual void logInfo (tcu::TestLog& log) const = 0;
55 class ColorVerifier : public Verifier
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))
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)
70 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
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)));
76 void logInfo (tcu::TestLog& log) const
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;
87 const tcu::RGBA m_color;
88 const tcu::IVec3 m_threshold;
91 class FullBlueSomeGreenVerifier : public Verifier
94 FullBlueSomeGreenVerifier (void)
98 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
102 // Values from 0.0 and 1.0 are accurate
104 if (testColor.getRed() != 0)
106 if (testColor.getGreen() == 0)
108 if (testColor.getBlue() != 255)
113 void logInfo (tcu::TestLog& log) const
115 log << tcu::TestLog::Message << "Expecting color c = (0.0, x, 1.0), x > 0.0" << tcu::TestLog::EndMessage;
119 class NoRedVerifier : public Verifier
126 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
129 return testColor.getRed() == 0;
132 void logInfo (tcu::TestLog& log) const
134 log << tcu::TestLog::Message << "Expecting zero-valued red channel." << tcu::TestLog::EndMessage;
138 class SampleAverageVerifier : public Verifier
141 SampleAverageVerifier (int _numSamples);
143 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const;
144 void logInfo (tcu::TestLog& log) const;
146 const int m_numSamples;
147 const bool m_isStatisticallySignificant;
148 float m_distanceThreshold;
151 SampleAverageVerifier::SampleAverageVerifier (int _numSamples)
152 : m_numSamples (_numSamples)
153 , m_isStatisticallySignificant (_numSamples >= 4)
154 , m_distanceThreshold (0.0f)
156 // approximate Bates distribution as normal
157 const float variance = (1.0f / (12.0f * m_numSamples));
158 const float standardDeviation = deFloatSqrt(variance);
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;
166 bool SampleAverageVerifier::verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
169 DE_ASSERT(m_isStatisticallySignificant);
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));
174 return distanceFromCenter.x() < m_distanceThreshold && distanceFromCenter.y() < m_distanceThreshold;
177 void SampleAverageVerifier::logInfo (tcu::TestLog& log) const
179 log << tcu::TestLog::Message << "Expecting average sample position to be near the pixel center. Maximum per-axis distance " << m_distanceThreshold << tcu::TestLog::EndMessage;
182 class PartialDiscardVerifier : public Verifier
185 PartialDiscardVerifier (void)
189 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const
193 return (testColor.getGreen() != 0) && (testColor.getGreen() != 255);
196 void logInfo (tcu::TestLog& log) const
198 log << tcu::TestLog::Message << "Expecting color non-zero and non-saturated green channel" << tcu::TestLog::EndMessage;
202 static bool verifyImageWithVerifier (const tcu::Surface& resultImage, tcu::TestLog& log, const Verifier& verifier, bool logOnSuccess = true)
204 tcu::Surface errorMask (resultImage.getWidth(), resultImage.getHeight());
207 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
211 log << tcu::TestLog::Message << "Verifying image." << tcu::TestLog::EndMessage;
212 verifier.logInfo(log);
215 for (int y = 0; y < resultImage.getHeight(); ++y)
216 for (int x = 0; x < resultImage.getWidth(); ++x)
218 const tcu::RGBA color = resultImage.getPixel(x, y);
220 // verify color value is valid for this pixel position
221 if (!verifier.verify(color, tcu::IVec2(x,y)))
224 errorMask.setPixel(x, y, tcu::RGBA::red);
230 // describe the verification logic if we haven't already
232 verifier.logInfo(log);
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;
240 else if (logOnSuccess)
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;
251 class MultisampleRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
254 MultisampleRenderCase (Context& context, const char* name, const char* desc, int numSamples, RenderTarget target, int renderSize, int flags = 0);
255 virtual ~MultisampleRenderCase (void);
257 virtual void init (void);
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)
264 DE_ASSERT(target < TARGET_LAST);
267 MultisampleRenderCase::~MultisampleRenderCase (void)
269 MultisampleRenderCase::deinit();
272 void MultisampleRenderCase::init (void)
274 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables"))
275 throw tcu::NotSupportedError("Test requires GL_OES_sample_variables extension");
277 MultisampleShaderRenderUtil::MultisampleRenderCase::init();
280 class NumSamplesCase : public MultisampleRenderCase
283 NumSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
284 ~NumSamplesCase (void);
286 std::string genFragmentSource (int numTargetSamples) const;
287 bool verifyImage (const tcu::Surface& resultImage);
296 NumSamplesCase::NumSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target)
297 : MultisampleRenderCase(context, name, desc, sampleCount, target, RENDER_SIZE)
301 NumSamplesCase::~NumSamplesCase (void)
305 std::string NumSamplesCase::genFragmentSource (int numTargetSamples) const
307 std::ostringstream buf;
309 buf << "#version 310 es\n"
310 "#extension GL_OES_sample_variables : require\n"
311 "layout(location = 0) out mediump vec4 fragColor;\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"
322 bool NumSamplesCase::verifyImage (const tcu::Surface& resultImage)
324 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier());
327 class MaxSamplesCase : public MultisampleRenderCase
330 MaxSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
331 ~MaxSamplesCase (void);
335 std::string genFragmentSource (int numTargetSamples) const;
336 bool verifyImage (const tcu::Surface& resultImage);
344 MaxSamplesCase::MaxSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target)
345 : MultisampleRenderCase(context, name, desc, sampleCount, target, RENDER_SIZE)
349 MaxSamplesCase::~MaxSamplesCase (void)
353 void MaxSamplesCase::preDraw (void)
355 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
356 deInt32 maxSamples = -1;
360 gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
361 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_MAX_SAMPLES");
363 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_SAMPLES = " << maxSamples << tcu::TestLog::EndMessage;
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");
372 gl.uniform1i(maxSampleLoc, maxSamples);
373 GLU_EXPECT_NO_ERROR(gl.getError(), "set u_maxSamples uniform");
375 m_testCtx.getLog() << tcu::TestLog::Message << "Set u_maxSamples = " << maxSamples << tcu::TestLog::EndMessage;
379 std::string MaxSamplesCase::genFragmentSource (int numTargetSamples) const
381 DE_UNREF(numTargetSamples);
383 std::ostringstream buf;
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"
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"
399 bool MaxSamplesCase::verifyImage (const tcu::Surface& resultImage)
401 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier());
404 class SampleIDCase : public MultisampleRenderCase
407 SampleIDCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
408 ~SampleIDCase (void);
413 std::string genFragmentSource (int numTargetSamples) const;
414 bool verifyImage (const tcu::Surface& resultImage);
415 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers);
421 enum VerificationMode
423 VERIFY_USING_SAMPLES,
424 VERIFY_USING_SELECTION,
427 const VerificationMode m_vericationMode;
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))
436 SampleIDCase::~SampleIDCase (void)
440 void SampleIDCase::init (void)
442 // log the test method and expectations
443 if (m_vericationMode == VERIFY_USING_SAMPLES)
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)
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;
459 MultisampleRenderCase::init();
462 std::string SampleIDCase::genFragmentSource (int numTargetSamples) const
464 DE_ASSERT(numTargetSamples != 0);
466 std::ostringstream buf;
468 if (m_vericationMode == VERIFY_USING_SAMPLES)
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"
476 " highp float normalizedSample = float(gl_SampleID) / float(" << numTargetSamples << ");\n"
477 " fragColor = vec4(0.0, normalizedSample, 1.0, 1.0);\n"
480 else if (m_vericationMode == VERIFY_USING_SELECTION)
482 if (numTargetSamples == 1)
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"
490 " if (gl_SampleID == 0)\n"
491 " fragColor = vec4(0.0, 1.0, 1.0, 1.0);\n"
493 " fragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
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"
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"
509 " if (gl_SampleID == selectedID)\n"
510 " fragColor = vec4(0.0, 1.0, 1.0, 1.0);\n"
512 " fragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
522 bool SampleIDCase::verifyImage (const tcu::Surface& resultImage)
524 if (m_vericationMode == VERIFY_USING_SAMPLES)
530 else if (m_vericationMode == VERIFY_USING_SELECTION)
532 // should result in full blue and some green everywhere
533 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), FullBlueSomeGreenVerifier());
542 bool SampleIDCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
544 // Verify all sample buffers
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;
555 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample buffers" << tcu::TestLog::EndMessage;
556 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
558 // sample id should be sample index
559 const int threshold = 255 / 4 / m_numTargetSamples + 1;
560 const float sampleIdColor = sampleNdx / (float)m_numTargetSamples;
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);
567 m_testCtx.getLog() << tcu::TestLog::Message << "Sample buffer verification failed" << tcu::TestLog::EndMessage;
572 class SamplePosDistributionCase : public MultisampleRenderCase
575 SamplePosDistributionCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
576 ~SamplePosDistributionCase (void);
585 std::string genFragmentSource (int numTargetSamples) const;
586 bool verifyImage (const tcu::Surface& resultImage);
587 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers);
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)
595 SamplePosDistributionCase::~SamplePosDistributionCase (void)
599 void SamplePosDistributionCase::init (void)
601 // log the test method and expectations
602 if (m_renderTarget == TARGET_TEXTURE)
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;
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;
626 MultisampleRenderCase::init();
629 std::string SamplePosDistributionCase::genFragmentSource (int numTargetSamples) const
631 DE_ASSERT(numTargetSamples != 0);
632 DE_UNREF(numTargetSamples);
634 const bool multisampleTarget = (m_numRequestedSamples > 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1);
635 std::ostringstream buf;
637 if (multisampleTarget)
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"
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"
648 " fragColor = vec4(0.0, gl_SamplePosition.x, gl_SamplePosition.y, 1.0);\n"
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"
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"
662 " fragColor = vec4(0.0, gl_SamplePosition.x, gl_SamplePosition.y, 1.0);\n"
669 bool SamplePosDistributionCase::verifyImage (const tcu::Surface& resultImage)
671 const int sampleCount = (m_renderTarget == TARGET_DEFAULT) ? (m_context.getRenderTarget().getNumSamples()) : (m_numRequestedSamples);
672 SampleAverageVerifier verifier (sampleCount);
674 // check there is nothing in the error channel
675 if (!verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier()))
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");
685 bool SamplePosDistributionCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
687 const int width = resultBuffers[0].getWidth();
688 const int height = resultBuffers[0].getHeight();
690 bool distibutionError = false;
692 // Check sample range, uniqueness, and distribution, log layers
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;
704 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position range" << tcu::TestLog::EndMessage;
705 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
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);
716 m_testCtx.getLog() << tcu::TestLog::Message << "Sample position verification failed." << tcu::TestLog::EndMessage;
722 bool uniquenessOk = true;
723 tcu::Surface errorMask (width, height);
724 std::vector<tcu::Vec2> samplePositions (resultBuffers.size());
726 const int printFloodLimit = 5;
728 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
730 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position uniqueness." << tcu::TestLog::EndMessage;
732 for (int y = 0; y < height; ++y)
733 for (int x = 0; x < width; ++x)
735 bool samplePosNotUnique = false;
737 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
739 const tcu::RGBA color = resultBuffers[sampleNdx].getPixel(x, y);
740 samplePositions[sampleNdx] = tcu::Vec2(color.getGreen() / 255.0f, color.getBlue() / 255.0f);
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)
747 if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB])
749 if (++printCount <= printFloodLimit)
752 << tcu::TestLog::Message
753 << "Pixel (" << x << ", " << y << "): Samples " << sampleNdxA << " and " << sampleNdxB << " have the same position."
754 << tcu::TestLog::EndMessage;
757 samplePosNotUnique = true;
758 uniquenessOk = false;
759 errorMask.setPixel(x, y, tcu::RGBA::red);
767 if (printCount > printFloodLimit)
769 << tcu::TestLog::Message
771 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
772 << tcu::TestLog::EndMessage;
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;
784 // check distribution
786 const SampleAverageVerifier verifier (m_numTargetSamples);
787 tcu::Surface errorMask (width, height);
789 const int printFloodLimit = 5;
791 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
793 // don't bother with small sample counts
794 if (verifier.m_isStatisticallySignificant)
796 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position distribution is (nearly) unbiased." << tcu::TestLog::EndMessage;
797 verifier.logInfo(m_testCtx.getLog());
799 for (int y = 0; y < height; ++y)
800 for (int x = 0; x < width; ++x)
802 tcu::IVec3 colorSum(0, 0, 0);
806 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
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();
814 colorSum.x() /= m_numTargetSamples;
815 colorSum.y() /= m_numTargetSamples;
816 colorSum.z() /= m_numTargetSamples;
818 // verify average sample position
820 if (!verifier.verify(tcu::RGBA(colorSum.x(), colorSum.y(), colorSum.z(), 0), tcu::IVec2(x, y)))
822 if (++printCount <= printFloodLimit)
825 << tcu::TestLog::Message
826 << "Pixel (" << x << ", " << y << "): Sample distribution is biased."
827 << tcu::TestLog::EndMessage;
830 distibutionError = true;
831 errorMask.setPixel(x, y, tcu::RGBA::red);
835 // sub-verification result
836 if (distibutionError)
838 if (printCount > printFloodLimit)
840 << tcu::TestLog::Message
842 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
843 << tcu::TestLog::EndMessage;
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;
857 else if (distibutionError)
858 throw MultisampleShaderRenderUtil::QualityWarning("Bias detected, sample positions are not uniformly distributed within the pixel");
861 m_testCtx.getLog() << tcu::TestLog::Message << "Verification ok." << tcu::TestLog::EndMessage;
866 class SamplePosCorrectnessCase : public MultisampleRenderCase
869 SamplePosCorrectnessCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
870 ~SamplePosCorrectnessCase (void);
880 void postDraw (void);
882 std::string genVertexSource (int numTargetSamples) const;
883 std::string genFragmentSource (int numTargetSamples) const;
884 bool verifyImage (const tcu::Surface& resultImage);
886 bool m_useSampleQualifier;
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)
895 SamplePosCorrectnessCase::~SamplePosCorrectnessCase (void)
899 void SamplePosCorrectnessCase::init (void)
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");
906 // prefer to use the sample qualifier path
907 m_useSampleQualifier = m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation");
909 // log the test method and expectations
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;
917 MultisampleRenderCase::init();
920 void SamplePosCorrectnessCase::preDraw (void)
922 if (!m_useSampleQualifier)
924 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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");
931 m_testCtx.getLog() << tcu::TestLog::Message << "Enabling per-sample interpolation with GL_SAMPLE_SHADING." << tcu::TestLog::EndMessage;
935 void SamplePosCorrectnessCase::postDraw (void)
937 if (!m_useSampleQualifier)
939 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
941 gl.disable(GL_SAMPLE_SHADING);
942 gl.minSampleShading(1.0f);
943 GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio");
947 std::string SamplePosCorrectnessCase::genVertexSource (int numTargetSamples) const
949 DE_UNREF(numTargetSamples);
951 std::ostringstream buf;
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"
959 " gl_Position = a_position;\n"
960 " v_position = a_position;\n"
966 std::string SamplePosCorrectnessCase::genFragmentSource (int numTargetSamples) const
968 DE_UNREF(numTargetSamples);
970 std::ostringstream buf;
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"
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)
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"
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"
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"
999 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1001 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1007 bool SamplePosCorrectnessCase::verifyImage (const tcu::Surface& resultImage)
1009 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier());
1012 class SampleMaskBaseCase : public MultisampleRenderCase
1019 RUN_PER_TWO_SAMPLES,
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);
1028 virtual void init (void);
1029 virtual void preDraw (void);
1030 virtual void postDraw (void);
1031 virtual bool verifyImage (const tcu::Surface& resultImage);
1033 const ShaderRunMode m_runMode;
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)
1040 DE_ASSERT(runMode < RUN_LAST);
1043 SampleMaskBaseCase::~SampleMaskBaseCase (void)
1047 void SampleMaskBaseCase::init (void)
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");
1053 MultisampleRenderCase::init();
1056 void SampleMaskBaseCase::preDraw (void)
1058 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1060 if (m_runMode == RUN_PER_TWO_SAMPLES)
1062 gl.enable(GL_SAMPLE_SHADING);
1063 gl.minSampleShading(0.5f);
1064 GLU_EXPECT_NO_ERROR(gl.getError(), "enable sample shading");
1066 m_testCtx.getLog() << tcu::TestLog::Message << "Enabled GL_SAMPLE_SHADING, value = 0.5" << tcu::TestLog::EndMessage;
1070 void SampleMaskBaseCase::postDraw (void)
1072 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1074 if (m_runMode == RUN_PER_TWO_SAMPLES)
1076 gl.disable(GL_SAMPLE_SHADING);
1077 gl.minSampleShading(1.0f);
1078 GLU_EXPECT_NO_ERROR(gl.getError(), "disable sample shading");
1082 bool SampleMaskBaseCase::verifyImage (const tcu::Surface& resultImage)
1084 // shader does the verification
1085 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier());
1088 class SampleMaskCase : public SampleMaskBaseCase
1091 SampleMaskCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target);
1092 ~SampleMaskCase (void);
1095 void preDraw (void);
1096 void postDraw (void);
1104 std::string genFragmentSource (int numTargetSamples) const;
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)
1112 SampleMaskCase::~SampleMaskCase (void)
1116 void SampleMaskCase::init (void)
1118 // log the test method and expectations
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;
1126 SampleMaskBaseCase::init();
1129 void SampleMaskCase::preDraw (void)
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;
1138 gl.enable(GL_SAMPLE_MASK);
1139 gl.sampleMaski(0, effectiveMask);
1140 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask");
1142 m_testCtx.getLog() << tcu::TestLog::Message << "Setting sample mask " << tcu::Format::Hex<4>(effectiveMask) << tcu::TestLog::EndMessage;
1144 // set multisample case uniforms
1145 if (multisampleTarget)
1147 const int maskLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampleMask");
1149 throw tcu::TestError("Location of u_mask was -1");
1151 gl.uniform1ui(maskLoc, effectiveMask);
1152 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask uniform");
1156 SampleMaskBaseCase::preDraw();
1159 void SampleMaskCase::postDraw (void)
1161 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1162 const deUint32 fullMask = (1U << m_numTargetSamples) - 1;
1164 gl.disable(GL_SAMPLE_MASK);
1165 gl.sampleMaski(0, fullMask);
1166 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask");
1169 SampleMaskBaseCase::postDraw();
1172 std::string SampleMaskCase::genFragmentSource (int numTargetSamples) const
1174 DE_ASSERT(numTargetSamples != 0);
1176 const bool multisampleTarget = (m_numRequestedSamples > 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1);
1177 std::ostringstream buf;
1179 // test supports only one sample mask word
1180 if (numTargetSamples > 32)
1181 throw tcu::NotSupportedError("Sample count larger than 32 is not supported.");
1183 if (multisampleTarget)
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"
1191 " if ((uint(gl_SampleMaskIn[0]) & (~u_sampleMask)) != 0u)\n"
1192 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1194 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1199 // non-multisample targets don't get multisample operations like ANDing with mask
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"
1207 " if (gl_SampleMaskIn[0] != 1)\n"
1208 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1210 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1217 class SampleMaskCountCase : public SampleMaskBaseCase
1220 SampleMaskCountCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode);
1221 ~SampleMaskCountCase (void);
1224 void preDraw (void);
1225 void postDraw (void);
1233 std::string genFragmentSource (int numTargetSamples) const;
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)
1239 DE_ASSERT(runMode < RUN_LAST);
1242 SampleMaskCountCase::~SampleMaskCountCase (void)
1246 void SampleMaskCountCase::init (void)
1248 // log the test method and expectations
1249 if (m_runMode == RUN_PER_PIXEL)
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)
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)
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;
1273 SampleMaskBaseCase::init();
1276 void SampleMaskCountCase::preDraw (void)
1278 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1280 if (m_runMode == RUN_PER_PIXEL)
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;
1288 throw tcu::TestError("Location of u_maxBitCount was -1");
1290 throw tcu::TestError("Location of u_minBitCount was -1");
1292 gl.uniform1i(minLoc, minBitCount);
1293 gl.uniform1i(maxLoc, maxBitCount);
1294 GLU_EXPECT_NO_ERROR(gl.getError(), "set limits");
1296 m_testCtx.getLog() << tcu::TestLog::Message << "Setting minBitCount = " << minBitCount << ", maxBitCount = " << maxBitCount << tcu::TestLog::EndMessage;
1298 else if (m_runMode == RUN_PER_TWO_SAMPLES)
1300 const int maxLoc = gl.getUniformLocation(m_program->getProgram(), "u_maxBitCount");
1301 const int minLoc = gl.getUniformLocation(m_program->getProgram(), "u_minBitCount");
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);
1309 throw tcu::TestError("Location of u_maxBitCount was -1");
1311 throw tcu::TestError("Location of u_minBitCount was -1");
1313 gl.uniform1i(minLoc, minBitCount);
1314 gl.uniform1i(maxLoc, maxBitCount);
1315 GLU_EXPECT_NO_ERROR(gl.getError(), "set limits");
1317 m_testCtx.getLog() << tcu::TestLog::Message << "Setting minBitCount = " << minBitCount << ", maxBitCount = " << maxBitCount << tcu::TestLog::EndMessage;
1320 SampleMaskBaseCase::preDraw();
1323 void SampleMaskCountCase::postDraw (void)
1325 SampleMaskBaseCase::postDraw();
1328 std::string SampleMaskCountCase::genFragmentSource (int numTargetSamples) const
1330 DE_ASSERT(numTargetSamples != 0);
1332 std::ostringstream buf;
1334 // test supports only one sample mask word
1335 if (numTargetSamples > 32)
1336 throw tcu::NotSupportedError("Sample count larger than 32 is not supported.");
1338 // count the number of the bits in gl_SampleMask
1340 buf << "#version 310 es\n"
1341 "#extension GL_OES_sample_variables : require\n"
1342 "layout(location = 0) out mediump vec4 fragColor;\n";
1344 if (m_runMode != RUN_PER_SAMPLE)
1345 buf << "uniform highp int u_minBitCount;\n"
1346 "uniform highp int u_maxBitCount;\n";
1348 buf << "void main (void)\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"
1356 if (m_runMode == RUN_PER_SAMPLE)
1358 // check the validity here
1359 buf << " // force per-sample shading\n"
1360 " highp float blue = float(gl_SampleID);\n"
1362 " if (maskBitCount != 1)\n"
1363 " fragColor = vec4(1.0, 0.0, blue, 1.0);\n"
1365 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n"
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"
1374 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
1381 class SampleMaskUniqueCase : public SampleMaskBaseCase
1384 SampleMaskUniqueCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode);
1385 ~SampleMaskUniqueCase (void);
1395 std::string genFragmentSource (int numTargetSamples) const;
1396 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers);
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)
1402 DE_ASSERT(runMode == RUN_PER_SAMPLE);
1403 DE_ASSERT(target == TARGET_TEXTURE);
1406 SampleMaskUniqueCase::~SampleMaskUniqueCase (void)
1410 void SampleMaskUniqueCase::init (void)
1412 // log the test method and expectations
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;
1422 SampleMaskBaseCase::init();
1425 std::string SampleMaskUniqueCase::genFragmentSource (int numTargetSamples) const
1427 DE_ASSERT(numTargetSamples != 0);
1429 std::ostringstream buf;
1431 // test supports only one sample mask word
1432 if (numTargetSamples > 32)
1433 throw tcu::NotSupportedError("Sample count larger than 32 is not supported.");
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"
1441 " mediump int firstIndex = -1;\n"
1442 " for (int i = 0; i < 32; ++i)\n"
1444 " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n"
1446 " firstIndex = i;\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"
1456 " highp float encodedSampleId = float(firstIndex) / " << numTargetSamples <<".0;\n"
1458 " // force per-sample shading\n"
1459 " highp float blue = float(gl_SampleID);\n"
1461 " if (notUniqueError)\n"
1462 " fragColor = vec4(1.0, 0.0, blue, 1.0);\n"
1464 " fragColor = vec4(0.0, encodedSampleId, blue, 1.0);\n"
1470 bool SampleMaskUniqueCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
1472 const int width = resultBuffers[0].getWidth();
1473 const int height = resultBuffers[0].getHeight();
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;
1484 // check for earlier errors (in fragment shader)
1486 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying fragment shader invocation found only one set sample mask bit." << tcu::TestLog::EndMessage;
1488 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
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);
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;
1503 // verify index / index ranges
1505 if (m_numRequestedSamples == 0)
1507 // single sample target, expect index=0
1509 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample mask bit index is 0." << tcu::TestLog::EndMessage;
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);
1518 tcu::Surface errorMask (width, height);
1519 bool uniquenessOk = true;
1521 const int printFloodLimit = 5;
1522 std::vector<int> maskBitIndices (resultBuffers.size());
1524 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1526 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying per-invocation sample mask bit is unique." << tcu::TestLog::EndMessage;
1528 for (int y = 0; y < height; ++y)
1529 for (int x = 0; x < width; ++x)
1531 bool maskNdxNotUnique = false;
1534 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx)
1536 const tcu::RGBA color = resultBuffers[sampleNdx].getPixel(x, y);
1537 maskBitIndices[sampleNdx] = (int)deFloatRound(color.getGreen() / 255.0f * m_numTargetSamples);
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)
1544 if (maskBitIndices[sampleNdxA] == maskBitIndices[sampleNdxB])
1546 if (++printCount <= printFloodLimit)
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;
1554 maskNdxNotUnique = true;
1555 uniquenessOk = false;
1556 errorMask.setPixel(x, y, tcu::RGBA::red);
1564 if (printCount > printFloodLimit)
1566 << tcu::TestLog::Message
1568 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
1569 << tcu::TestLog::EndMessage;
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;
1584 class SampleMaskUniqueSetCase : public SampleMaskBaseCase
1587 SampleMaskUniqueSetCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode);
1588 ~SampleMaskUniqueSetCase (void);
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;
1605 void preTest (void);
1606 void postTest (void);
1608 std::vector<tcu::Surface> m_iterationSampleBuffers;
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)
1614 DE_ASSERT(runMode == RUN_PER_TWO_SAMPLES);
1615 DE_ASSERT(target == TARGET_TEXTURE);
1617 // high and low bits
1618 m_numIterations = 2;
1621 SampleMaskUniqueSetCase::~SampleMaskUniqueSetCase (void)
1625 void SampleMaskUniqueSetCase::init (void)
1627 // log the test method and expectations
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;
1638 SampleMaskBaseCase::init();
1641 void SampleMaskUniqueSetCase::deinit (void)
1643 m_iterationSampleBuffers.clear();
1646 void SampleMaskUniqueSetCase::preDraw (void)
1648 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1649 const int selectorLoc = gl.getUniformLocation(m_program->getProgram(), "u_bitSelector");
1651 gl.uniform1ui(selectorLoc, (deUint32)m_iteration);
1652 GLU_EXPECT_NO_ERROR(gl.getError(), "set u_bitSelector");
1654 m_testCtx.getLog() << tcu::TestLog::Message << "Setting u_bitSelector = " << m_iteration << tcu::TestLog::EndMessage;
1656 SampleMaskBaseCase::preDraw();
1659 void SampleMaskUniqueSetCase::postDraw (void)
1661 SampleMaskBaseCase::postDraw();
1664 std::string SampleMaskUniqueSetCase::genFragmentSource (int numTargetSamples) const
1666 DE_ASSERT(numTargetSamples != 0);
1668 std::ostringstream buf;
1670 // test supports only one sample mask word
1671 if (numTargetSamples > 32)
1672 throw tcu::NotSupportedError("Sample count larger than 32 is not supported.");
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"
1681 " highp int selectedBits;\n"
1682 " if (u_bitSelector == 0u)\n"
1683 " selectedBits = (gl_SampleMaskIn[0] & 0xFFFF);\n"
1685 " selectedBits = ((gl_SampleMaskIn[0] >> 16) & 0xFFFF);\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"
1692 " fragColor = vec4(float(redBits) / float(31), float(greenBits) / float(63), float(blueBits) / float(31), 1.0);\n"
1698 bool SampleMaskUniqueSetCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
1700 // we need results from all passes to do verification. Store results and verify later (at postTest).
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];
1709 std::string SampleMaskUniqueSetCase::getIterationDescription (int iteration) const
1712 return "Reading low bits";
1713 else if (iteration == 1)
1714 return "Reading high bits";
1720 void SampleMaskUniqueSetCase::preTest (void)
1722 m_iterationSampleBuffers.resize(m_numTargetSamples * 2);
1725 void SampleMaskUniqueSetCase::postTest (void)
1727 DE_ASSERT((m_iterationSampleBuffers.size() % 2) == 0);
1728 DE_ASSERT((int)m_iterationSampleBuffers.size() / 2 == m_numTargetSamples);
1730 const int width = m_iterationSampleBuffers[0].getWidth();
1731 const int height = m_iterationSampleBuffers[0].getHeight();
1733 std::vector<tcu::TextureLevel> sampleCoverage (m_numTargetSamples);
1734 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Verify", "Verify masks");
1736 // convert color layers to 32 bit coverage masks, 2 passes per coverage
1738 for (int sampleNdx = 0; sampleNdx < (int)sampleCoverage.size(); ++sampleNdx)
1740 sampleCoverage[sampleNdx].setStorage(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32), width, height);
1742 for (int y = 0; y < height; ++y)
1743 for (int x = 0; x < width; ++x)
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);
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);
1755 low = (deUint16)(redBits | (greenBits << 5) | (blueBits << 11));
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);
1762 high = (deUint16)(redBits | (greenBits << 5) | (blueBits << 11));
1765 sampleCoverage[sampleNdx].getAccess().setPixel(tcu::UVec4((((deUint32)high) << 16) | low, 0, 0, 0), x, y);
1771 if (m_numRequestedSamples == 0)
1773 // single sample target, expect mask = 0x01
1774 const int printFloodLimit = 5;
1777 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample mask is 0x00000001." << tcu::TestLog::EndMessage;
1779 for (int y = 0; y < height; ++y)
1780 for (int x = 0; x < width; ++x)
1782 deUint32 mask = sampleCoverage[0].getAccess().getPixelUint(x, y).x();
1787 if (++printCount <= printFloodLimit)
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;
1797 if (!allOk && printCount > printFloodLimit)
1800 << tcu::TestLog::Message
1802 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
1803 << tcu::TestLog::EndMessage;
1810 bool uniquenessOk = true;
1812 const int printFloodLimit = 5;
1814 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying invocation sample masks do not share bits." << tcu::TestLog::EndMessage;
1816 for (int y = 0; y < height; ++y)
1817 for (int x = 0; x < width; ++x)
1819 bool maskBitsNotUnique = false;
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)
1824 const deUint32 maskA = sampleCoverage[sampleNdxA].getAccess().getPixelUint(x, y).x();
1825 const deUint32 maskB = sampleCoverage[sampleNdxB].getAccess().getPixelUint(x, y).x();
1827 // equal mask == emitted by the same invocation
1833 maskBitsNotUnique = true;
1834 uniquenessOk = false;
1836 if (++printCount <= printFloodLimit)
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;
1855 if (printCount > printFloodLimit)
1857 << tcu::TestLog::Message
1859 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
1860 << tcu::TestLog::EndMessage;
1864 // check number of sample mask bit groups is valid ( == number of invocations )
1866 const deUint32 minNumInvocations = (deUint32)de::max(1, (m_numTargetSamples+1)/2);
1867 bool countOk = true;
1869 const int printFloodLimit = 5;
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;
1873 for (int y = 0; y < height; ++y)
1874 for (int x = 0; x < width; ++x)
1876 std::set<deUint32> masks;
1878 for (int maskNdx = 0; maskNdx < m_numTargetSamples; ++maskNdx)
1880 const deUint32 mask = sampleCoverage[maskNdx].getAccess().getPixelUint(x, y).x();
1884 if ((int)masks.size() < (int)minNumInvocations)
1886 if (++printCount <= printFloodLimit)
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;
1893 for (std::set<deUint32>::iterator it = masks.begin(); it != masks.end(); ++it)
1895 << tcu::TestLog::Message
1896 << "\tMask: " << tcu::Format::Hex<8>(*it) << "\n"
1897 << tcu::TestLog::EndMessage;
1908 if (printCount > printFloodLimit)
1910 << tcu::TestLog::Message
1912 << "Omitted " << (printCount-printFloodLimit) << " error descriptions."
1913 << tcu::TestLog::EndMessage;
1919 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
1922 class SampleMaskWriteCase : public SampleMaskBaseCase
1932 SampleMaskWriteCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode, TestMode testMode);
1933 ~SampleMaskWriteCase (void);
1936 void preDraw (void);
1937 void postDraw (void);
1945 std::string genFragmentSource (int numTargetSamples) const;
1946 bool verifyImage (const tcu::Surface& resultImage);
1948 const TestMode m_testMode;
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)
1955 DE_ASSERT(testMode < TEST_LAST);
1958 SampleMaskWriteCase::~SampleMaskWriteCase (void)
1962 void SampleMaskWriteCase::init (void)
1964 // log the test method and expectations
1965 if (m_testMode == TEST_DISCARD)
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)
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;
1983 SampleMaskBaseCase::init();
1986 void SampleMaskWriteCase::preDraw (void)
1988 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1990 if (m_testMode == TEST_INVERSE)
1992 // set mask to 0xAAAA.., set inverse mask bit coverage in shader
1994 const int maskLoc = gl.getUniformLocation(m_program->getProgram(), "u_mask");
1995 const deUint32 mask = (deUint32)0xAAAAAAAAUL;
1998 throw tcu::TestError("Location of u_mask was -1");
2000 gl.enable(GL_SAMPLE_MASK);
2001 gl.sampleMaski(0, mask);
2002 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask");
2004 gl.uniform1ui(maskLoc, mask);
2005 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask uniform");
2007 m_testCtx.getLog() << tcu::TestLog::Message << "Setting sample mask " << tcu::Format::Hex<4>(mask) << tcu::TestLog::EndMessage;
2010 SampleMaskBaseCase::preDraw();
2013 void SampleMaskWriteCase::postDraw (void)
2015 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2017 if (m_testMode == TEST_INVERSE)
2019 const deUint32 fullMask = (1U << m_numTargetSamples) - 1;
2021 gl.disable(GL_SAMPLE_MASK);
2022 gl.sampleMaski(0, fullMask);
2023 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask");
2026 SampleMaskBaseCase::postDraw();
2029 std::string SampleMaskWriteCase::genFragmentSource (int numTargetSamples) const
2031 DE_ASSERT(numTargetSamples != 0);
2032 DE_UNREF(numTargetSamples);
2034 std::ostringstream buf;
2036 if (m_testMode == TEST_DISCARD)
2038 // mask out every other coverage bit
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"
2045 " for (int i = 0; i < gl_SampleMask.length(); ++i)\n"
2046 " gl_SampleMask[i] = int(0xAAAAAAAA);\n"
2049 if (m_runMode == RUN_PER_SAMPLE)
2050 buf << " // force per-sample shading\n"
2051 " highp float blue = float(gl_SampleID);\n"
2053 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n"
2056 buf << " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2059 else if (m_testMode == TEST_INVERSE)
2061 // inverse every coverage bit
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"
2069 " gl_SampleMask[0] = int(~u_mask);\n"
2072 if (m_runMode == RUN_PER_SAMPLE)
2073 buf << " // force per-sample shading\n"
2074 " highp float blue = float(gl_SampleID);\n"
2076 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n"
2079 buf << " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
2088 bool SampleMaskWriteCase::verifyImage (const tcu::Surface& resultImage)
2090 const bool singleSampleTarget = m_numRequestedSamples == 0 && !(m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1);
2092 if (m_testMode == TEST_DISCARD)
2094 if (singleSampleTarget)
2096 // single sample case => multisample operations are not effective => don't discard anything
2098 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 1.0f, 0.0f)));
2100 else if (m_numTargetSamples == 1)
2102 // total discard, expect black
2103 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 0.0f, 0.0f)));
2107 // partial discard, expect something between black and green
2108 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), PartialDiscardVerifier());
2111 else if (m_testMode == TEST_INVERSE)
2113 if (singleSampleTarget)
2115 // single sample case => multisample operations are not effective => don't discard anything
2117 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 1.0f, 0.0f)));
2121 // total discard, expect black
2122 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 0.0f, 0.0f)));
2134 SampleVariableTests::SampleVariableTests (Context& context)
2135 : TestCaseGroup(context, "sample_variables", "Test sample variables")
2139 SampleVariableTests::~SampleVariableTests (void)
2143 void SampleVariableTests::init (void)
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");
2152 addChild(numSampleGroup);
2153 addChild(maxSampleGroup);
2154 addChild(sampleIDGroup);
2155 addChild(samplePosGroup);
2156 addChild(sampleMaskInGroup);
2157 addChild(sampleMaskGroup);
2159 static const struct RenderTarget
2164 MultisampleRenderCase::RenderTarget target;
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 },
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));
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));
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));
2203 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "correctness", "Test SamplePos correctness");
2204 samplePosGroup->addChild(group);
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));
2211 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "distribution", "Test SamplePos distribution");
2212 samplePosGroup->addChild(group);
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));
2223 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "sample_mask", "Test with GL_SAMPLE_MASK");
2224 sampleMaskInGroup->addChild(group);
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));
2229 // .bit_count_per_pixel
2231 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_pixel", "Test number of coverage bits");
2232 sampleMaskInGroup->addChild(group);
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));
2237 // .bit_count_per_sample
2239 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_sample", "Test number of coverage bits");
2240 sampleMaskInGroup->addChild(group);
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));
2245 // .bit_count_per_two_samples
2247 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_two_samples", "Test number of coverage bits");
2248 sampleMaskInGroup->addChild(group);
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));
2253 // .bits_unique_per_sample
2255 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bits_unique_per_sample", "Test coverage bits");
2256 sampleMaskInGroup->addChild(group);
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));
2262 // .bits_unique_per_two_samples
2264 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bits_unique_per_two_samples", "Test coverage bits");
2265 sampleMaskInGroup->addChild(group);
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));
2275 // .discard_half_per_pixel
2277 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_pixel", "Test coverage bits");
2278 sampleMaskGroup->addChild(group);
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));
2283 // .discard_half_per_sample
2285 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_sample", "Test coverage bits");
2286 sampleMaskGroup->addChild(group);
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));
2291 // .discard_half_per_two_samples
2293 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_two_samples", "Test coverage bits");
2294 sampleMaskGroup->addChild(group);
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));
2300 // .discard_half_per_two_samples
2302 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_pixel", "Test coverage bits");
2303 sampleMaskGroup->addChild(group);
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));
2308 // .inverse_per_sample
2310 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_sample", "Test coverage bits");
2311 sampleMaskGroup->addChild(group);
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));
2316 // .inverse_per_two_samples
2318 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_two_samples", "Test coverage bits");
2319 sampleMaskGroup->addChild(group);
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));