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 shading tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fSampleShadingTests.hpp"
     25 #include "es31fMultisampleShaderRenderCase.hpp"
     26 #include "tcuRenderTarget.hpp"
     27 #include "tcuSurface.hpp"
     28 #include "glsStateQueryUtil.hpp"
     29 #include "gluCallLogWrapper.hpp"
     30 #include "gluContextInfo.hpp"
     31 #include "gluShaderProgram.hpp"
     32 #include "gluRenderContext.hpp"
     33 #include "gluPixelTransfer.hpp"
     34 #include "glwFunctions.hpp"
     35 #include "glwEnums.hpp"
     36 #include "deStringUtil.hpp"
     37 #include "deRandom.hpp"
     38 
     39 #include <map>
     40 
     41 namespace deqp
     42 {
     43 namespace gles31
     44 {
     45 namespace Functional
     46 {
     47 namespace
     48 {
     49 
     50 using namespace gls::StateQueryUtil;
     51 
     52 class SampleShadingStateCase : public TestCase
     53 {
     54 public:
     55 						SampleShadingStateCase	(Context& ctx, const char* name, const char* desc, QueryType);
     56 
     57 	void				init					(void);
     58 	IterateResult		iterate					(void);
     59 
     60 private:
     61 	const QueryType		m_verifier;
     62 };
     63 
     64 SampleShadingStateCase::SampleShadingStateCase (Context& ctx, const char* name, const char* desc, QueryType type)
     65 	: TestCase		(ctx, name, desc)
     66 	, m_verifier	(type)
     67 {
     68 }
     69 
     70 void SampleShadingStateCase::init (void)
     71 {
     72 	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
     73 		throw tcu::NotSupportedError("Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
     74 }
     75 
     76 SampleShadingStateCase::IterateResult SampleShadingStateCase::iterate (void)
     77 {
     78 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
     79 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
     80 	gl.enableLogging(true);
     81 
     82 	// initial
     83 	{
     84 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying initial value" << tcu::TestLog::EndMessage;
     85 		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, false, m_verifier);
     86 	}
     87 
     88 	// true and false too
     89 	{
     90 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying random values" << tcu::TestLog::EndMessage;
     91 
     92 		gl.glEnable(GL_SAMPLE_SHADING);
     93 		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, true, m_verifier);
     94 
     95 		gl.glDisable(GL_SAMPLE_SHADING);
     96 		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, false, m_verifier);
     97 	}
     98 
     99 	result.setTestContextResult(m_testCtx);
    100 	return STOP;
    101 }
    102 
    103 class MinSampleShadingValueCase : public TestCase
    104 {
    105 public:
    106 						MinSampleShadingValueCase	(Context& ctx, const char* name, const char* desc, QueryType);
    107 
    108 	void				init						(void);
    109 	IterateResult		iterate						(void);
    110 
    111 private:
    112 	const QueryType		m_verifier;
    113 };
    114 
    115 MinSampleShadingValueCase::MinSampleShadingValueCase (Context& ctx, const char* name, const char* desc, QueryType type)
    116 	: TestCase		(ctx, name, desc)
    117 	, m_verifier	(type)
    118 {
    119 }
    120 
    121 void MinSampleShadingValueCase::init (void)
    122 {
    123 	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
    124 		throw tcu::NotSupportedError("Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
    125 }
    126 
    127 MinSampleShadingValueCase::IterateResult MinSampleShadingValueCase::iterate (void)
    128 {
    129 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    130 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
    131 
    132 	gl.enableLogging(true);
    133 
    134 	// initial
    135 	{
    136 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying initial value" << tcu::TestLog::EndMessage;
    137 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, m_verifier);
    138 	}
    139 
    140 	// special values
    141 	{
    142 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying special values" << tcu::TestLog::EndMessage;
    143 
    144 		gl.glMinSampleShading(0.0f);
    145 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, m_verifier);
    146 
    147 		gl.glMinSampleShading(1.0f);
    148 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, m_verifier);
    149 
    150 		gl.glMinSampleShading(0.5f);
    151 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.5, m_verifier);
    152 	}
    153 
    154 	// random values
    155 	{
    156 		const int	numRandomTests	= 10;
    157 		de::Random	rnd				(0xde123);
    158 
    159 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying random values" << tcu::TestLog::EndMessage;
    160 
    161 		for (int randNdx = 0; randNdx < numRandomTests; ++randNdx)
    162 		{
    163 			const float value = rnd.getFloat();
    164 
    165 			gl.glMinSampleShading(value);
    166 			verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, value, m_verifier);
    167 		}
    168 	}
    169 
    170 	result.setTestContextResult(m_testCtx);
    171 	return STOP;
    172 }
    173 
    174 class MinSampleShadingValueClampingCase : public TestCase
    175 {
    176 public:
    177 						MinSampleShadingValueClampingCase	(Context& ctx, const char* name, const char* desc);
    178 
    179 	void				init								(void);
    180 	IterateResult		iterate								(void);
    181 };
    182 
    183 MinSampleShadingValueClampingCase::MinSampleShadingValueClampingCase (Context& ctx, const char* name, const char* desc)
    184 	: TestCase(ctx, name, desc)
    185 {
    186 }
    187 
    188 void MinSampleShadingValueClampingCase::init (void)
    189 {
    190 	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
    191 		throw tcu::NotSupportedError("Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
    192 }
    193 
    194 MinSampleShadingValueClampingCase::IterateResult MinSampleShadingValueClampingCase::iterate (void)
    195 {
    196 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    197 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
    198 	gl.enableLogging(true);
    199 
    200 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    201 
    202 	// special values
    203 	{
    204 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying clamped values. Value is clamped when specified." << tcu::TestLog::EndMessage;
    205 
    206 		gl.glMinSampleShading(-0.5f);
    207 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
    208 
    209 		gl.glMinSampleShading(-1.0f);
    210 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
    211 
    212 		gl.glMinSampleShading(-1.5f);
    213 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
    214 
    215 		gl.glMinSampleShading(1.5f);
    216 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
    217 
    218 		gl.glMinSampleShading(2.0f);
    219 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
    220 
    221 		gl.glMinSampleShading(2.5f);
    222 		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
    223 	}
    224 
    225 	result.setTestContextResult(m_testCtx);
    226 	return STOP;
    227 }
    228 
    229 class SampleShadingRenderingCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
    230 {
    231 public:
    232 	enum TestType
    233 	{
    234 		TEST_DISCARD = 0,
    235 		TEST_COLOR,
    236 
    237 		TEST_LAST
    238 	};
    239 						SampleShadingRenderingCase	(Context& ctx, const char* name, const char* desc, RenderTarget target, int numSamples, TestType type);
    240 						~SampleShadingRenderingCase	(void);
    241 
    242 	void				init						(void);
    243 private:
    244 	void				setShadingValue				(int sampleCount);
    245 
    246 	void				preDraw						(void);
    247 	void				postDraw					(void);
    248 	std::string			getIterationDescription		(int iteration) const;
    249 
    250 	bool				verifyImage					(const tcu::Surface& resultImage);
    251 
    252 	std::string			genFragmentSource			(int numSamples) const;
    253 
    254 	enum
    255 	{
    256 		RENDER_SIZE = 128
    257 	};
    258 
    259 	const TestType		m_type;
    260 };
    261 
    262 SampleShadingRenderingCase::SampleShadingRenderingCase (Context& ctx, const char* name, const char* desc, RenderTarget target, int numSamples, TestType type)
    263 	: MultisampleShaderRenderUtil::MultisampleRenderCase	(ctx, name, desc, numSamples, target, RENDER_SIZE)
    264 	, m_type												(type)
    265 {
    266 	DE_ASSERT(type < TEST_LAST);
    267 }
    268 
    269 SampleShadingRenderingCase::~SampleShadingRenderingCase (void)
    270 {
    271 	deinit();
    272 }
    273 
    274 void SampleShadingRenderingCase::init (void)
    275 {
    276 	// requirements
    277 
    278 	if (!contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
    279 		throw tcu::NotSupportedError("Test requires GL_OES_sample_shading extension or a context version 3.2 or higher.");
    280 	if (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1)
    281 		throw tcu::NotSupportedError("Multisampled default framebuffer required");
    282 
    283 	// test purpose and expectations
    284 	m_testCtx.getLog()
    285 		<< tcu::TestLog::Message
    286 		<< "Verifying that a varying is given at least N different values for different samples within a single pixel.\n"
    287 		<< "	Render high-frequency function, map result to black/white. Modify N with glMinSampleShading().\n"
    288 		<< "	=> Resulting image should contain N+1 shades of gray.\n"
    289 		<< tcu::TestLog::EndMessage;
    290 
    291 	// setup resources
    292 
    293 	MultisampleShaderRenderUtil::MultisampleRenderCase::init();
    294 
    295 	// set iterations
    296 
    297 	m_numIterations = m_numTargetSamples + 1;
    298 }
    299 
    300 void SampleShadingRenderingCase::setShadingValue (int sampleCount)
    301 {
    302 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    303 
    304 	if (sampleCount == 0)
    305 	{
    306 		gl.disable(GL_SAMPLE_SHADING);
    307 		gl.minSampleShading(1.0f);
    308 		GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio");
    309 	}
    310 	else
    311 	{
    312 		// Minimum number of samples is max(ceil(<mss> * <samples>),1). Decrease mss with epsilon to prevent
    313 		// ceiling to a too large sample count.
    314 		const float epsilon	= 0.25f / (float)m_numTargetSamples;
    315 		const float ratio	= ((float)sampleCount / (float)m_numTargetSamples) - epsilon;
    316 
    317 		gl.enable(GL_SAMPLE_SHADING);
    318 		gl.minSampleShading(ratio);
    319 		GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio");
    320 
    321 		m_testCtx.getLog()
    322 			<< tcu::TestLog::Message
    323 			<< "Setting MIN_SAMPLE_SHADING_VALUE = " << ratio << "\n"
    324 			<< "Requested sample count: shadingValue * numSamples = " << ratio << " * " << m_numTargetSamples << " = " << (ratio * (float)m_numTargetSamples) << "\n"
    325 			<< "Minimum sample count: ceil(shadingValue * numSamples) = ceil(" << (ratio * (float)m_numTargetSamples) << ") = " << sampleCount
    326 			<< tcu::TestLog::EndMessage;
    327 
    328 		// can't fail with reasonable values of numSamples
    329 		DE_ASSERT(deFloatCeil(ratio * (float)m_numTargetSamples) == float(sampleCount));
    330 	}
    331 }
    332 
    333 void SampleShadingRenderingCase::preDraw (void)
    334 {
    335 	setShadingValue(m_iteration);
    336 }
    337 
    338 void SampleShadingRenderingCase::postDraw (void)
    339 {
    340 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    341 
    342 	gl.disable(GL_SAMPLE_SHADING);
    343 	gl.minSampleShading(1.0f);
    344 }
    345 
    346 std::string	SampleShadingRenderingCase::getIterationDescription (int iteration) const
    347 {
    348 	if (iteration == 0)
    349 		return "Disabled SAMPLE_SHADING";
    350 	else
    351 		return "Samples per pixel: " + de::toString(iteration);
    352 }
    353 
    354 bool SampleShadingRenderingCase::verifyImage (const tcu::Surface& resultImage)
    355 {
    356 	const int				numShadesRequired	= (m_iteration == 0) ? (2) : (m_iteration + 1);
    357 	const int				rareThreshold		= 100;
    358 	int						rareCount			= 0;
    359 	std::map<deUint32, int>	shadeFrequency;
    360 
    361 	// we should now have n+1 different shades of white, n = num samples
    362 
    363 	m_testCtx.getLog()
    364 		<< tcu::TestLog::Image("ResultImage", "Result Image", resultImage.getAccess())
    365 		<< tcu::TestLog::Message
    366 		<< "Verifying image has (at least) " << numShadesRequired << " different shades.\n"
    367 		<< "Excluding pixels with no full coverage (pixels on the shared edge of the triangle pair)."
    368 		<< tcu::TestLog::EndMessage;
    369 
    370 	for (int y = 0; y < RENDER_SIZE; ++y)
    371 	for (int x = 0; x < RENDER_SIZE; ++x)
    372 	{
    373 		const tcu::RGBA	color	= resultImage.getPixel(x, y);
    374 		const deUint32	packed	= ((deUint32)color.getRed()) + ((deUint32)color.getGreen() << 8) + ((deUint32)color.getGreen() << 16);
    375 
    376 		// on the triangle edge, skip
    377 		if (x == y)
    378 			continue;
    379 
    380 		if (shadeFrequency.find(packed) == shadeFrequency.end())
    381 			shadeFrequency[packed] = 1;
    382 		else
    383 			shadeFrequency[packed] = shadeFrequency[packed] + 1;
    384 	}
    385 
    386 	for (std::map<deUint32, int>::const_iterator it = shadeFrequency.begin(); it != shadeFrequency.end(); ++it)
    387 		if (it->second < rareThreshold)
    388 			rareCount++;
    389 
    390 	m_testCtx.getLog()
    391 		<< tcu::TestLog::Message
    392 		<< "Found " << (int)shadeFrequency.size() << " different shades.\n"
    393 		<< "\tRare (less than " << rareThreshold << " pixels): " << rareCount << "\n"
    394 		<< "\tCommon: " << (int)shadeFrequency.size() - rareCount << "\n"
    395 		<< tcu::TestLog::EndMessage;
    396 
    397 	if ((int)shadeFrequency.size() < numShadesRequired)
    398 	{
    399 		m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage;
    400 		return false;
    401 	}
    402 	return true;
    403 }
    404 
    405 std::string SampleShadingRenderingCase::genFragmentSource (int numSamples) const
    406 {
    407 	DE_UNREF(numSamples);
    408 	const glu::GLSLVersion	version	= contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2))
    409 									? glu::GLSL_VERSION_320_ES
    410 									: glu::GLSL_VERSION_310_ES;
    411 	std::ostringstream		buf;
    412 
    413 	buf <<	glu::getGLSLVersionDeclaration(version) << "\n"
    414 			"in highp vec4 v_position;\n"
    415 			"layout(location = 0) out mediump vec4 fragColor;\n"
    416 			"void main (void)\n"
    417 			"{\n"
    418 			"	highp float field = dot(v_position.xy, v_position.xy) + dot(21.0 * v_position.xx, sin(3.1 * v_position.xy));\n"
    419 			"	fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
    420 			"\n"
    421 			"	if (fract(field) > 0.5)\n";
    422 
    423 	if (m_type == TEST_DISCARD)
    424 		buf <<	"		discard;\n";
    425 	else if (m_type == TEST_COLOR)
    426 		buf <<	"		fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n";
    427 	else
    428 		DE_ASSERT(false);
    429 
    430 	buf <<	"}";
    431 
    432 	return buf.str();
    433 }
    434 
    435 } // anonymous
    436 
    437 SampleShadingTests::SampleShadingTests (Context& context)
    438 	: TestCaseGroup(context, "sample_shading", "Test sample shading")
    439 {
    440 }
    441 
    442 SampleShadingTests::~SampleShadingTests (void)
    443 {
    444 }
    445 
    446 void SampleShadingTests::init (void)
    447 {
    448 	tcu::TestCaseGroup* const stateQueryGroup = new tcu::TestCaseGroup(m_testCtx, "state_query", "State query tests.");
    449 	tcu::TestCaseGroup* const minSamplesGroup = new tcu::TestCaseGroup(m_testCtx, "min_sample_shading", "Min sample shading tests.");
    450 
    451 	addChild(stateQueryGroup);
    452 	addChild(minSamplesGroup);
    453 
    454 	// .state query
    455 	{
    456 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_is_enabled",				"test SAMPLE_SHADING",						QUERY_ISENABLED));
    457 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_boolean",				"test SAMPLE_SHADING",						QUERY_BOOLEAN));
    458 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_integer",				"test SAMPLE_SHADING",						QUERY_INTEGER));
    459 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_float",					"test SAMPLE_SHADING",						QUERY_FLOAT));
    460 		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_integer64",				"test SAMPLE_SHADING",						QUERY_INTEGER64));
    461 		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_boolean",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_BOOLEAN));
    462 		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_integer",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_INTEGER));
    463 		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_float",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_FLOAT));
    464 		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_integer64",	"test MIN_SAMPLE_SHADING_VALUE",			QUERY_INTEGER64));
    465 		stateQueryGroup->addChild(new MinSampleShadingValueClampingCase	(m_context, "min_sample_shading_value_clamping",		"test MIN_SAMPLE_SHADING_VALUE clamping"));
    466 	}
    467 
    468 	// .min_sample_count
    469 	{
    470 		static const struct Target
    471 		{
    472 			SampleShadingRenderingCase::RenderTarget	target;
    473 			int											numSamples;
    474 			const char*									name;
    475 		} targets[] =
    476 		{
    477 			{ SampleShadingRenderingCase::TARGET_DEFAULT,			0,	"default_framebuffer"					},
    478 			{ SampleShadingRenderingCase::TARGET_TEXTURE,			2,	"multisample_texture_samples_2"			},
    479 			{ SampleShadingRenderingCase::TARGET_TEXTURE,			4,	"multisample_texture_samples_4"			},
    480 			{ SampleShadingRenderingCase::TARGET_TEXTURE,			8,	"multisample_texture_samples_8"			},
    481 			{ SampleShadingRenderingCase::TARGET_TEXTURE,			16,	"multisample_texture_samples_16"		},
    482 			{ SampleShadingRenderingCase::TARGET_RENDERBUFFER,		2,	"multisample_renderbuffer_samples_2"	},
    483 			{ SampleShadingRenderingCase::TARGET_RENDERBUFFER,		4,	"multisample_renderbuffer_samples_4"	},
    484 			{ SampleShadingRenderingCase::TARGET_RENDERBUFFER,		8,	"multisample_renderbuffer_samples_8"	},
    485 			{ SampleShadingRenderingCase::TARGET_RENDERBUFFER,		16,	"multisample_renderbuffer_samples_16"	},
    486 		};
    487 
    488 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(targets); ++ndx)
    489 		{
    490 			minSamplesGroup->addChild(new SampleShadingRenderingCase(m_context, (std::string(targets[ndx].name) + "_color").c_str(),	"Test multiple samples per pixel with color",	targets[ndx].target, targets[ndx].numSamples, SampleShadingRenderingCase::TEST_COLOR));
    491 			minSamplesGroup->addChild(new SampleShadingRenderingCase(m_context, (std::string(targets[ndx].name) + "_discard").c_str(),	"Test multiple samples per pixel with",			targets[ndx].target, targets[ndx].numSamples, SampleShadingRenderingCase::TEST_DISCARD));
    492 		}
    493 	}
    494 }
    495 
    496 } // Functional
    497 } // gles31
    498 } // deqp
    499