• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Multisample texture size tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fShaderTextureSizeTests.hpp"
25 #include "gluRenderContext.hpp"
26 #include "gluShaderProgram.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "gluContextInfo.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuStringTemplate.hpp"
33 #include "tcuSurface.hpp"
34 #include "tcuRenderTarget.hpp"
35 #include "deStringUtil.hpp"
36 
37 using namespace glw;
38 
39 namespace deqp
40 {
41 namespace gles31
42 {
43 namespace Functional
44 {
45 namespace
46 {
47 
48 static const char* const s_positionVertexShaderSource =	"#version 310 es\n"
49 														"in highp vec4 a_position;\n"
50 														"void main (void)\n"
51 														"{\n"
52 														"	gl_Position = a_position;\n"
53 														"}\n";
54 
55 class TextureSizeCase : public TestCase
56 {
57 public:
58 	enum TextureType
59 	{
60 		TEXTURE_FLOAT_2D = 0,
61 		TEXTURE_FLOAT_2D_ARRAY,
62 		TEXTURE_INT_2D,
63 		TEXTURE_INT_2D_ARRAY,
64 		TEXTURE_UINT_2D,
65 		TEXTURE_UINT_2D_ARRAY,
66 
67 		TEXTURE_LAST
68 	};
69 
70 							TextureSizeCase		(Context& context, const char* name, const char* desc, TextureType type, int samples);
71 							~TextureSizeCase	(void);
72 
73 private:
74 	void					init				(void);
75 	void					deinit				(void);
76 	IterateResult			iterate				(void);
77 
78 	std::string				genFragmentSource	(void);
79 	glw::GLenum				getTextureGLTarget	(void);
80 	glw::GLenum				getTextureGLInternalFormat (void);
81 
82 	void					createTexture		(const tcu::IVec3& size);
83 	void					deleteTexture		(void);
84 	void					runShader			(tcu::Surface& dst, const tcu::IVec3& size);
85 	bool					verifyImage			(const tcu::Surface& dst);
86 
87 	const TextureType		m_type;
88 	const int				m_numSamples;
89 	const bool				m_isArrayType;
90 
91 	glw::GLuint				m_texture;
92 	glw::GLuint				m_vbo;
93 	glu::ShaderProgram*		m_shader;
94 	std::vector<tcu::IVec3>	m_iterations;
95 	int						m_iteration;
96 
97 	bool					m_allIterationsPassed;
98 	bool					m_allCasesSkipped;
99 };
100 
TextureSizeCase(Context & context,const char * name,const char * desc,TextureType type,int samples)101 TextureSizeCase::TextureSizeCase (Context& context, const char* name, const char* desc, TextureType type, int samples)
102 	: TestCase				(context, name, desc)
103 	, m_type				(type)
104 	, m_numSamples			(samples)
105 	, m_isArrayType			(m_type == TEXTURE_FLOAT_2D_ARRAY || m_type == TEXTURE_INT_2D_ARRAY || m_type == TEXTURE_UINT_2D_ARRAY)
106 	, m_texture				(0)
107 	, m_vbo					(0)
108 	, m_shader				(DE_NULL)
109 	, m_iteration			(0)
110 	, m_allIterationsPassed	(true)
111 	, m_allCasesSkipped		(true)
112 {
113 	DE_ASSERT(type < TEXTURE_LAST);
114 }
115 
~TextureSizeCase(void)116 TextureSizeCase::~TextureSizeCase (void)
117 {
118 	deinit();
119 }
120 
init(void)121 void TextureSizeCase::init (void)
122 {
123 	static const tcu::IVec2 testSizes2D[] =
124 	{
125 		tcu::IVec2(1,	1),
126 		tcu::IVec2(1,	4),
127 		tcu::IVec2(4,	8),
128 		tcu::IVec2(21,	11),
129 		tcu::IVec2(107,	254),
130 		tcu::IVec2(-1,	3),
131 		tcu::IVec2(3,	-1),
132 	};
133 	static const tcu::IVec3 testSizes3D[] =
134 	{
135 		tcu::IVec3(1,	1,		1),
136 		tcu::IVec3(1,	4,		7),
137 		tcu::IVec3(4,	8,		12),
138 		tcu::IVec3(21,	11,		9),
139 		tcu::IVec3(107,	254,	2),
140 		tcu::IVec3(-1,	3,		3),
141 		tcu::IVec3(3,	-1,		3),
142 		tcu::IVec3(4,	4,		-1),
143 	};
144 	static const tcu::Vec4 fullscreenQuad[] =
145 	{
146 		tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
147 		tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
148 		tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
149 		tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)
150 	};
151 
152 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
153 
154 	// requirements
155 	if (m_isArrayType && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
156 		TCU_THROW(NotSupportedError, "Test requires OES_texture_storage_multisample_2d_array extension");
157 
158 	if (m_context.getRenderTarget().getWidth() < 1 || m_context.getRenderTarget().getHeight() < 1)
159 		TCU_THROW(NotSupportedError, "rendertarget size must be at least 1x1");
160 
161 	glw::GLint				maxTextureSize		= 0;
162 	glw::GLint				maxTextureLayers	= 0;
163 	glw::GLint				maxSamples			= 0;
164 
165 	gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
166 	gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxTextureLayers);
167 	gl.getInternalformativ(getTextureGLTarget(), getTextureGLInternalFormat(), GL_SAMPLES, 1, &maxSamples);
168 
169 	if (m_numSamples > maxSamples)
170 		TCU_THROW(NotSupportedError, "sample count is not supported");
171 
172 	// gen shade
173 
174 	m_shader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_positionVertexShaderSource) << glu::FragmentSource(genFragmentSource()));
175 	m_testCtx.getLog() << *m_shader;
176 	if (!m_shader->isOk())
177 		throw tcu::TestError("shader build failed");
178 
179 	// gen buffer
180 
181 	gl.genBuffers(1, &m_vbo);
182 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
183 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW);
184 
185 	// gen iterations
186 
187 	m_testCtx.getLog()
188 		<< tcu::TestLog::Message
189 		<< "GL_MAX_TEXTURE_SIZE = " << maxTextureSize << "\n"
190 		<< "GL_MAX_ARRAY_TEXTURE_LAYERS = " << maxTextureLayers
191 		<< tcu::TestLog::EndMessage;
192 
193 	if (!m_isArrayType)
194 	{
195 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testSizes2D); ++ndx)
196 		{
197 			if (testSizes2D[ndx].x() <= maxTextureSize && testSizes2D[ndx].y() <= maxTextureSize)
198 			{
199 				const int w = (testSizes2D[ndx].x() < 0) ? (maxTextureSize) : (testSizes2D[ndx].x());
200 				const int h = (testSizes2D[ndx].y() < 0) ? (maxTextureSize) : (testSizes2D[ndx].y());
201 
202 				m_iterations.push_back(tcu::IVec3(w, h, 0));
203 			}
204 		}
205 	}
206 	else
207 	{
208 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testSizes3D); ++ndx)
209 		{
210 			if (testSizes3D[ndx].x() <= maxTextureSize && testSizes3D[ndx].y() <= maxTextureSize && testSizes3D[ndx].z() <= maxTextureLayers)
211 			{
212 				const int w = (testSizes3D[ndx].x() < 0) ? (maxTextureSize)		: (testSizes3D[ndx].x());
213 				const int h = (testSizes3D[ndx].y() < 0) ? (maxTextureSize)		: (testSizes3D[ndx].y());
214 				const int d = (testSizes3D[ndx].z() < 0) ? (maxTextureLayers)	: (testSizes3D[ndx].z());
215 
216 				m_iterations.push_back(tcu::IVec3(w, h, d));
217 			}
218 		}
219 	}
220 }
221 
deinit(void)222 void TextureSizeCase::deinit (void)
223 {
224 	if (m_texture)
225 	{
226 		m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture);
227 		m_texture = 0;
228 	}
229 
230 	if (m_vbo)
231 	{
232 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_vbo);
233 		m_vbo = 0;
234 	}
235 
236 	if (m_shader)
237 	{
238 		delete m_shader;
239 		m_shader = DE_NULL;
240 	}
241 }
242 
iterate(void)243 TextureSizeCase::IterateResult TextureSizeCase::iterate (void)
244 {
245 	tcu::Surface	result		(1, 1);
246 	bool			skipTest	= false;
247 
248 	m_testCtx.getLog() << tcu::TestLog::Message << "\nIteration " << (m_iteration+1) << " / " << (int)m_iterations.size() << tcu::TestLog::EndMessage;
249 
250 	try
251 	{
252 		// set texture size
253 
254 		createTexture(m_iterations[m_iteration]);
255 
256 		// query texture size
257 
258 		runShader(result, m_iterations[m_iteration]);
259 	}
260 	catch (glu::OutOfMemoryError&)
261 	{
262 		m_testCtx.getLog() << tcu::TestLog::Message << "Got GL_OUT_OF_MEMORY, skipping this size" << tcu::TestLog::EndMessage;
263 
264 		skipTest = true;
265 	}
266 
267 	// free resources
268 
269 	deleteTexture();
270 
271 	// queried value was correct?
272 
273 	if (!skipTest)
274 	{
275 		m_allCasesSkipped = false;
276 
277 		if (!verifyImage(result))
278 			m_allIterationsPassed = false;
279 	}
280 
281 	// final result
282 
283 	if (++m_iteration < (int)m_iterations.size())
284 		return CONTINUE;
285 
286 	if (!m_allIterationsPassed)
287 	{
288 		m_testCtx.getLog() << tcu::TestLog::Message << "One or more test sizes failed." << tcu::TestLog::EndMessage;
289 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid texture size");
290 	}
291 	else if (m_allCasesSkipped)
292 	{
293 		m_testCtx.getLog() << tcu::TestLog::Message << "Could not test any texture size, texture creation failed." << tcu::TestLog::EndMessage;
294 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "All test texture creations failed");
295 	}
296 	else
297 	{
298 		m_testCtx.getLog() << tcu::TestLog::Message << "All texture sizes passed." << tcu::TestLog::EndMessage;
299 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
300 	}
301 
302 	return STOP;
303 }
304 
genFragmentSource(void)305 std::string TextureSizeCase::genFragmentSource (void)
306 {
307 	static const char* const templateSource =	"#version 310 es\n"
308 												"${EXTENSION_STATEMENT}"
309 												"layout(location = 0) out highp vec4 fragColor;\n"
310 												"uniform highp ${SAMPLERTYPE} u_sampler;\n"
311 												"uniform highp ${SIZETYPE} u_size;\n"
312 												"void main (void)\n"
313 												"{\n"
314 												"	const highp vec4 okColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
315 												"	const highp vec4 failColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
316 												"	fragColor = (textureSize(u_sampler) == u_size) ? (okColor) : (failColor);\n"
317 												"}\n";
318 
319 	std::map<std::string, std::string> args;
320 
321 	switch (m_type)
322 	{
323 		case TEXTURE_FLOAT_2D:			args["SAMPLERTYPE"] = "sampler2DMS";		break;
324 		case TEXTURE_FLOAT_2D_ARRAY:	args["SAMPLERTYPE"] = "sampler2DMSArray";	break;
325 		case TEXTURE_INT_2D:			args["SAMPLERTYPE"] = "isampler2DMS";		break;
326 		case TEXTURE_INT_2D_ARRAY:		args["SAMPLERTYPE"] = "isampler2DMSArray";	break;
327 		case TEXTURE_UINT_2D:			args["SAMPLERTYPE"] = "usampler2DMS";		break;
328 		case TEXTURE_UINT_2D_ARRAY:		args["SAMPLERTYPE"] = "usampler2DMSArray";	break;
329 		default:
330 			DE_ASSERT(DE_FALSE);
331 	}
332 
333 	if (!m_isArrayType)
334 		args["SIZETYPE"] = "ivec2";
335 	else
336 		args["SIZETYPE"] = "ivec3";
337 
338 	if (m_isArrayType)
339 		args["EXTENSION_STATEMENT"] = "#extension GL_OES_texture_storage_multisample_2d_array : require\n";
340 	else
341 		args["EXTENSION_STATEMENT"] = "";
342 
343 	return tcu::StringTemplate(templateSource).specialize(args);
344 }
345 
getTextureGLTarget(void)346 glw::GLenum TextureSizeCase::getTextureGLTarget (void)
347 {
348 	switch (m_type)
349 	{
350 		case TEXTURE_FLOAT_2D:			return GL_TEXTURE_2D_MULTISAMPLE;
351 		case TEXTURE_FLOAT_2D_ARRAY:	return GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
352 		case TEXTURE_INT_2D:			return GL_TEXTURE_2D_MULTISAMPLE;
353 		case TEXTURE_INT_2D_ARRAY:		return GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
354 		case TEXTURE_UINT_2D:			return GL_TEXTURE_2D_MULTISAMPLE;
355 		case TEXTURE_UINT_2D_ARRAY:		return GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
356 		default:
357 			DE_ASSERT(DE_FALSE);
358 			return 0;
359 	}
360 }
361 
getTextureGLInternalFormat(void)362 glw::GLenum TextureSizeCase::getTextureGLInternalFormat (void)
363 {
364 	switch (m_type)
365 	{
366 		case TEXTURE_FLOAT_2D:			return GL_RGBA8;
367 		case TEXTURE_FLOAT_2D_ARRAY:	return GL_RGBA8;
368 		case TEXTURE_INT_2D:			return GL_R8I;
369 		case TEXTURE_INT_2D_ARRAY:		return GL_R8I;
370 		case TEXTURE_UINT_2D:			return GL_R8UI;
371 		case TEXTURE_UINT_2D_ARRAY:		return GL_R8UI;
372 		default:
373 			DE_ASSERT(DE_FALSE);
374 			return 0;
375 	}
376 }
377 
createTexture(const tcu::IVec3 & size)378 void TextureSizeCase::createTexture (const tcu::IVec3& size)
379 {
380 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
381 
382 	if (!m_isArrayType)
383 		m_testCtx.getLog() << tcu::TestLog::Message << "Creating texture with size " << size.x() << "x" << size.y() << tcu::TestLog::EndMessage;
384 	else
385 		m_testCtx.getLog() << tcu::TestLog::Message << "Creating texture with size " << size.x() << "x" << size.y() << "x" << size.z() << tcu::TestLog::EndMessage;
386 
387 	gl.genTextures(1, &m_texture);
388 	gl.bindTexture(getTextureGLTarget(), m_texture);
389 	GLU_EXPECT_NO_ERROR(gl.getError(), "texture gen");
390 
391 	if (!m_isArrayType)
392 		gl.texStorage2DMultisample(getTextureGLTarget(), m_numSamples, getTextureGLInternalFormat(), size.x(), size.y(), GL_FALSE);
393 	else
394 		gl.texStorage3DMultisample(getTextureGLTarget(), m_numSamples, getTextureGLInternalFormat(), size.x(), size.y(), size.z(), GL_FALSE);
395 	GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage");
396 }
397 
deleteTexture(void)398 void TextureSizeCase::deleteTexture (void)
399 {
400 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
401 
402 	if (m_texture)
403 	{
404 		gl.deleteTextures(1, &m_texture);
405 		m_texture = 0;
406 
407 		GLU_EXPECT_NO_ERROR(gl.getError(), "texture delete");
408 	}
409 }
410 
runShader(tcu::Surface & dst,const tcu::IVec3 & size)411 void TextureSizeCase::runShader (tcu::Surface& dst, const tcu::IVec3& size)
412 {
413 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
414 	const int				positionLoc			= gl.getAttribLocation(m_shader->getProgram(), "a_position");
415 	const int				shaderSamplerLoc	= gl.getUniformLocation(m_shader->getProgram(), "u_sampler");
416 	const int				shaderSizeLoc		= gl.getUniformLocation(m_shader->getProgram(), "u_size");
417 
418 	m_testCtx.getLog() << tcu::TestLog::Message << "Running the verification shader." << tcu::TestLog::EndMessage;
419 
420 	GLU_EXPECT_NO_ERROR(gl.getError(), "preclear");
421 	gl.viewport(0, 0, 1, 1);
422 	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
423 	gl.clear(GL_COLOR_BUFFER_BIT);
424 	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
425 
426 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
427 	gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
428 	gl.enableVertexAttribArray(positionLoc);
429 	GLU_EXPECT_NO_ERROR(gl.getError(), "vertexAttrib");
430 
431 	gl.useProgram(m_shader->getProgram());
432 	gl.uniform1i(shaderSamplerLoc, 0);
433 	if (m_isArrayType)
434 		gl.uniform3iv(shaderSizeLoc, 1, size.getPtr());
435 	else
436 		gl.uniform2iv(shaderSizeLoc, 1, size.getPtr());
437 	GLU_EXPECT_NO_ERROR(gl.getError(), "setup program");
438 
439 	gl.bindTexture(getTextureGLTarget(), m_texture);
440 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindtex");
441 
442 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
443 	GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
444 
445 	gl.disableVertexAttribArray(positionLoc);
446 	gl.useProgram(0);
447 	GLU_EXPECT_NO_ERROR(gl.getError(), "cleanup");
448 
449 	gl.finish();
450 	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
451 	GLU_EXPECT_NO_ERROR(gl.getError(), "readPixels");
452 }
453 
verifyImage(const tcu::Surface & dst)454 bool TextureSizeCase::verifyImage (const tcu::Surface& dst)
455 {
456 	DE_ASSERT(dst.getWidth() == 1 && dst.getHeight() == 1);
457 
458 	const int		colorThresholdRed	= 1 << (8 - m_context.getRenderTarget().getPixelFormat().redBits);
459 	const int		colorThresholdGreen	= 1 << (8 - m_context.getRenderTarget().getPixelFormat().greenBits);
460 	const int		colorThresholdBlue	= 1 << (8 - m_context.getRenderTarget().getPixelFormat().blueBits);
461 	const tcu::RGBA	color				= dst.getPixel(0,0);
462 
463 	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying image." << tcu::TestLog::EndMessage;
464 
465 	// green
466 	if (color.getRed() < colorThresholdRed && color.getGreen() > 255 - colorThresholdGreen && color.getBlue() < colorThresholdBlue)
467 	{
468 		m_testCtx.getLog() << tcu::TestLog::Message << "Result ok." << tcu::TestLog::EndMessage;
469 		return true;
470 	}
471 	// red
472 	else if (color.getRed() > 255 - colorThresholdRed && color.getGreen() < colorThresholdGreen && color.getBlue() < colorThresholdBlue)
473 	{
474 		m_testCtx.getLog() << tcu::TestLog::Message << "Image size incorrect." << tcu::TestLog::EndMessage;
475 		return false;
476 	}
477 
478 	m_testCtx.getLog() << tcu::TestLog::Message << "Expected either green or red pixel, got " << color << tcu::TestLog::EndMessage;
479 	return false;
480 }
481 
482 } // anonymous
483 
ShaderTextureSizeTests(Context & context)484 ShaderTextureSizeTests::ShaderTextureSizeTests (Context& context)
485 	: TestCaseGroup(context, "texture_size", "Texture size tests")
486 {
487 }
488 
~ShaderTextureSizeTests(void)489 ShaderTextureSizeTests::~ShaderTextureSizeTests (void)
490 {
491 }
492 
init(void)493 void ShaderTextureSizeTests::init (void)
494 {
495 	static const struct SamplerType
496 	{
497 		TextureSizeCase::TextureType	type;
498 		const char*						name;
499 	} samplerTypes[] =
500 	{
501 		{ TextureSizeCase::TEXTURE_FLOAT_2D,		"texture_2d"			},
502 		{ TextureSizeCase::TEXTURE_FLOAT_2D_ARRAY,	"texture_2d_array"		},
503 		{ TextureSizeCase::TEXTURE_INT_2D,			"texture_int_2d"		},
504 		{ TextureSizeCase::TEXTURE_INT_2D_ARRAY,	"texture_int_2d_array"	},
505 		{ TextureSizeCase::TEXTURE_UINT_2D,			"texture_uint_2d"		},
506 		{ TextureSizeCase::TEXTURE_UINT_2D_ARRAY,	"texture_uint_2d_array"	},
507 	};
508 
509 	static const int sampleCounts[] = { 1, 4 };
510 
511 	for (int samplerTypeNdx = 0; samplerTypeNdx < DE_LENGTH_OF_ARRAY(samplerTypes); ++samplerTypeNdx)
512 	{
513 		for (int sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); ++sampleCountNdx)
514 		{
515 			const std::string name = std::string() + "samples_" + de::toString(sampleCounts[sampleCountNdx]) + "_" + samplerTypes[samplerTypeNdx].name;
516 			const std::string desc = std::string() + "samples count = " + de::toString(sampleCounts[sampleCountNdx]) + ", type = " + samplerTypes[samplerTypeNdx].name;
517 
518 			addChild(new TextureSizeCase(m_context, name.c_str(), desc.c_str(), samplerTypes[samplerTypeNdx].type, sampleCounts[sampleCountNdx]));
519 		}
520 	}
521 }
522 
523 } // Functional
524 } // gles31
525 } // deqp
526