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