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 Basic Layout Binding Tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fLayoutBindingTests.hpp"
25 
26 #include "gluShaderProgram.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "gluContextInfo.hpp"
30 
31 #include "glwFunctions.hpp"
32 #include "glwEnums.hpp"
33 
34 #include "tcuSurface.hpp"
35 #include "tcuTestLog.hpp"
36 #include "tcuTexture.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuStringTemplate.hpp"
40 #include "tcuRenderTarget.hpp"
41 
42 #include "deString.h"
43 #include "deStringUtil.hpp"
44 #include "deRandom.hpp"
45 
46 using tcu::TestLog;
47 using tcu::Vec2;
48 using tcu::Vec3;
49 using tcu::Vec4;
50 
51 namespace deqp
52 {
53 namespace gles31
54 {
55 namespace Functional
56 {
57 namespace
58 {
59 
60 enum TestType
61 {
62 	TESTTYPE_BINDING_SINGLE = 0,
63 	TESTTYPE_BINDING_MAX,
64 	TESTTYPE_BINDING_MULTIPLE,
65 	TESTTYPE_BINDING_ARRAY,
66 	TESTTYPE_BINDING_MAX_ARRAY,
67 
68 	TESTTYPE_BINDING_LAST,
69 };
70 
71 enum ShaderType
72 {
73 	SHADERTYPE_VERTEX = 0,
74 	SHADERTYPE_FRAGMENT,
75 	SHADERTYPE_TESS_CONTROL,
76 	SHADERTYPE_TESS_EVALUATION,
77 	SHADERTYPE_ALL,
78 
79 	SHADERTYPE_LAST,
80 };
81 
82 enum
83 {
84 	MAX_UNIFORM_MULTIPLE_INSTANCES	= 7,
85 	MAX_UNIFORM_ARRAY_SIZE			= 7,
86 };
87 
generateVertexShader(ShaderType shaderType,const std::string & shaderUniformDeclarations,const std::string & shaderBody)88 std::string generateVertexShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody)
89 {
90 	static const char* const s_simpleVertexShaderSource	=	"#version 310 es\n"
91 															"in highp vec4 a_position;\n"
92 															"void main (void)\n"
93 															"{\n"
94 															"	gl_Position = a_position;\n"
95 															"}\n";
96 
97 	switch (shaderType)
98 	{
99 		case SHADERTYPE_VERTEX:
100 		case SHADERTYPE_ALL:
101 		{
102 			std::ostringstream vertexShaderSource;
103 			vertexShaderSource	<<	"#version 310 es\n"
104 								<<	"in highp vec4 a_position;\n"
105 								<<	"out highp vec4 v_color;\n"
106 								<<	"uniform highp int u_arrayNdx;\n\n"
107 								<<	shaderUniformDeclarations << "\n"
108 								<<	"void main (void)\n"
109 								<<	"{\n"
110 								<<	"	highp vec4 color;\n\n"
111 								<<	shaderBody << "\n"
112 								<<	"	v_color = color;\n"
113 								<<	"	gl_Position = a_position;\n"
114 								<<	"}\n";
115 
116 			return vertexShaderSource.str();
117 		}
118 
119 		case SHADERTYPE_FRAGMENT:
120 		case SHADERTYPE_TESS_CONTROL:
121 		case SHADERTYPE_TESS_EVALUATION:
122 			return s_simpleVertexShaderSource;
123 
124 		default:
125 			DE_ASSERT(false);
126 			return "";
127 	}
128 }
129 
generateFragmentShader(ShaderType shaderType,const std::string & shaderUniformDeclarations,const std::string & shaderBody)130 std::string generateFragmentShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody)
131 {
132 	static const char* const s_simpleFragmentShaderSource = "#version 310 es\n"
133 															"in highp vec4 v_color;\n"
134 															"layout(location = 0) out highp vec4 fragColor;\n"
135 															"void main (void)\n"
136 															"{\n"
137 															"	fragColor = v_color;\n"
138 															"}\n";
139 
140 	switch (shaderType)
141 	{
142 		case SHADERTYPE_VERTEX:
143 		case SHADERTYPE_TESS_CONTROL:
144 		case SHADERTYPE_TESS_EVALUATION:
145 			return s_simpleFragmentShaderSource;
146 
147 		case SHADERTYPE_FRAGMENT:
148 		{
149 			std::ostringstream fragmentShaderSource;
150 			fragmentShaderSource	<<	"#version 310 es\n"
151 									<<	"layout(location = 0) out highp vec4 fragColor;\n"
152 									<<	"uniform highp int u_arrayNdx;\n\n"
153 									<<	shaderUniformDeclarations << "\n"
154 									<<	"void main (void)\n"
155 									<<	"{\n"
156 									<<	"	highp vec4 color;\n\n"
157 									<<	shaderBody << "\n"
158 									<<	"	fragColor = color;\n"
159 									<<	"}\n";
160 
161 			return fragmentShaderSource.str();
162 		}
163 		case SHADERTYPE_ALL:
164 		{
165 			std::ostringstream fragmentShaderSource;
166 			fragmentShaderSource	<<	"#version 310 es\n"
167 									<<	"in highp vec4 v_color;\n"
168 									<<	"layout(location = 0) out highp vec4 fragColor;\n"
169 									<<	"uniform highp int u_arrayNdx;\n\n"
170 									<<	shaderUniformDeclarations << "\n"
171 									<<	"void main (void)\n"
172 									<<	"{\n"
173 									<<	"	if (v_color.x > 2.0) discard;\n"
174 									<<	"	highp vec4 color;\n\n"
175 									<<	shaderBody << "\n"
176 									<<	"	fragColor = color;\n"
177 									<<	"}\n";
178 
179 			return fragmentShaderSource.str();
180 		}
181 
182 		default:
183 			DE_ASSERT(false);
184 			return "";
185 	}
186 }
187 
generateTessControlShader(ShaderType shaderType,const std::string & shaderUniformDeclarations,const std::string & shaderBody)188 std::string generateTessControlShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody)
189 {
190 	static const char* const s_simpleTessContorlShaderSource =	"#version 310 es\n"
191 																"#extension GL_EXT_tessellation_shader : require\n"
192 																"layout (vertices=3) out;\n"
193 																"\n"
194 																"void main (void)\n"
195 																"{\n"
196 																"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
197 																"}\n";
198 
199 	switch (shaderType)
200 	{
201 		case SHADERTYPE_VERTEX:
202 		case SHADERTYPE_FRAGMENT:
203 		case SHADERTYPE_TESS_EVALUATION:
204 			return s_simpleTessContorlShaderSource;
205 
206 		case SHADERTYPE_TESS_CONTROL:
207 		case SHADERTYPE_ALL:
208 		{
209 			std::ostringstream tessControlShaderSource;
210 			tessControlShaderSource <<	"#version 310 es\n"
211 									<<	"#extension GL_EXT_tessellation_shader : require\n"
212 									<<	"layout (vertices=3) out;\n"
213 									<<	"\n"
214 									<<	"uniform highp int u_arrayNdx;\n\n"
215 									<<	shaderUniformDeclarations << "\n"
216 									<<	"void main (void)\n"
217 									<<	"{\n"
218 									<<	"	highp vec4 color;\n\n"
219 									<<	shaderBody << "\n"
220 									<<	"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
221 									<<	"}\n";
222 
223 			return tessControlShaderSource.str();
224 		}
225 
226 		default:
227 			DE_ASSERT(false);
228 			return "";
229 	}
230 }
231 
generateTessEvaluationShader(ShaderType shaderType,const std::string & shaderUniformDeclarations,const std::string & shaderBody)232 std::string generateTessEvaluationShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody)
233 {
234 	static const char* const s_simpleTessEvaluationShaderSource =	"#version 310 es\n"
235 																	"#extension GL_EXT_tessellation_shader : require\n"
236 																	"layout (triangles) in;\n"
237 																	"\n"
238 																	"void main (void)\n"
239 																	"{\n"
240 																	"	gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"
241 																	"}\n";
242 
243 	switch (shaderType)
244 	{
245 		case SHADERTYPE_VERTEX:
246 		case SHADERTYPE_FRAGMENT:
247 		case SHADERTYPE_TESS_CONTROL:
248 			return s_simpleTessEvaluationShaderSource;
249 
250 		case SHADERTYPE_TESS_EVALUATION:
251 		case SHADERTYPE_ALL:
252 		{
253 			std::ostringstream tessEvaluationShaderSource;
254 			tessEvaluationShaderSource	<< "#version 310 es\n"
255 										<< "#extension GL_EXT_tessellation_shader : require\n"
256 										<< "layout (triangles) in;\n"
257 										<< "\n"
258 										<< "uniform highp int u_arrayNdx;\n\n"
259 										<< shaderUniformDeclarations << "\n"
260 										<< "out mediump vec4 v_color;\n"
261 										<< "void main (void)\n"
262 										<< "{\n"
263 										<< "	highp vec4 color;\n\n"
264 										<<	shaderBody << "\n"
265 										<< "	v_color = color;\n"
266 										<< "	gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"
267 										<< "}\n";
268 
269 			return tessEvaluationShaderSource.str();
270 		}
271 
272 		default:
273 			DE_ASSERT(false);
274 			return "";
275 	}
276 }
277 
getUniformName(const std::string & name,int declNdx)278 std::string getUniformName (const std::string& name, int declNdx)
279 {
280 	return name + de::toString(declNdx);
281 }
282 
getUniformName(const std::string & name,int declNdx,int arrNdx)283 std::string getUniformName (const std::string& name, int declNdx, int arrNdx)
284 {
285 	return name + de::toString(declNdx) + "[" + de::toString(arrNdx) + "]";
286 }
287 
getRandomColor(de::Random & rnd)288 Vec4 getRandomColor (de::Random& rnd)
289 {
290 	const float r = rnd.getFloat(0.2f, 0.9f);
291 	const float g = rnd.getFloat(0.2f, 0.9f);
292 	const float b = rnd.getFloat(0.2f, 0.9f);
293 	return Vec4(r, g, b, 1.0f);
294 }
295 
296 class LayoutBindingRenderCase : public TestCase
297 {
298 public:
299 	enum
300 	{
301 		MAX_TEST_RENDER_WIDTH	= 256,
302 		MAX_TEST_RENDER_HEIGHT	= 256,
303 		TEST_TEXTURE_SIZE	= 1,
304 	};
305 
306 										LayoutBindingRenderCase			(Context&			context,
307 																		 const char*		name,
308 																		 const char*		desc,
309 																		 ShaderType			shaderType,
310 																		 TestType			testType,
311 																		 glw::GLenum		maxBindingPointEnum,
312 																		 glw::GLenum		maxVertexUnitsEnum,
313 																		 glw::GLenum		maxFragmentUnitsEnum,
314 																		 glw::GLenum		maxCombinedUnitsEnum,
315 																		 const std::string& uniformName);
316 	virtual								~LayoutBindingRenderCase		(void);
317 
318 	virtual void						init							(void);
319 	virtual void						deinit							(void);
320 
getRenderWidth(void) const321 	int									getRenderWidth					(void) const { return de::min((int)MAX_TEST_RENDER_WIDTH, m_context.getRenderTarget().getWidth()); }
getRenderHeight(void) const322 	int									getRenderHeight					(void) const { return de::min((int)MAX_TEST_RENDER_HEIGHT, m_context.getRenderTarget().getHeight()); }
323 protected:
324 	virtual glu::ShaderProgram*			generateShaders					(void) const = 0;
325 
326 	void								initRenderState					(void);
327 	bool								drawAndVerifyResult				(const Vec4& expectedColor);
328 	void								setTestResult					(bool queryTestPassed, bool imageTestPassed);
329 
330 	const glu::ShaderProgram*			m_program;
331 	const ShaderType					m_shaderType;
332 	const TestType						m_testType;
333 	const std::string					m_uniformName;
334 
335 	const glw::GLenum					m_maxBindingPointEnum;
336 	const glw::GLenum					m_maxVertexUnitsEnum;
337 	const glw::GLenum					m_maxFragmentUnitsEnum;
338 	const glw::GLenum					m_maxCombinedUnitsEnum;
339 
340 	glw::GLuint							m_vertexBuffer;
341 	glw::GLuint							m_indexBuffer;
342 	glw::GLint							m_shaderProgramLoc;
343 	glw::GLint							m_shaderProgramPosLoc;
344 	glw::GLint							m_shaderProgramArrayNdxLoc;
345 	glw::GLint							m_numBindings;
346 
347 	std::vector<glw::GLint>				m_bindings;
348 
349 private:
350 	void								initBindingPoints				(int minBindingPoint, int numBindingPoints);
351 };
352 
LayoutBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,glw::GLenum maxBindingPointEnum,glw::GLenum maxVertexUnitsEnum,glw::GLenum maxFragmentUnitsEnum,glw::GLenum maxCombinedUnitsEnum,const std::string & uniformName)353 LayoutBindingRenderCase::LayoutBindingRenderCase (Context&				context,
354 												  const char*			name,
355 												  const char*			desc,
356 												  ShaderType			shaderType,
357 												  TestType				testType,
358 												  glw::GLenum			maxBindingPointEnum,
359 												  glw::GLenum			maxVertexUnitsEnum,
360 												  glw::GLenum			maxFragmentUnitsEnum,
361 												  glw::GLenum			maxCombinedUnitsEnum,
362 												  const std::string&	uniformName)
363 	: TestCase						(context, name, desc)
364 	, m_program						(DE_NULL)
365 	, m_shaderType					(shaderType)
366 	, m_testType					(testType)
367 	, m_uniformName					(uniformName)
368 	, m_maxBindingPointEnum			(maxBindingPointEnum)
369 	, m_maxVertexUnitsEnum			(maxVertexUnitsEnum)
370 	, m_maxFragmentUnitsEnum		(maxFragmentUnitsEnum)
371 	, m_maxCombinedUnitsEnum		(maxCombinedUnitsEnum)
372 	, m_vertexBuffer				(0)
373 	, m_indexBuffer					(0)
374 	, m_shaderProgramLoc			(0)
375 	, m_shaderProgramPosLoc			(0)
376 	, m_shaderProgramArrayNdxLoc	(0)
377 	, m_numBindings					(0)
378 {
379 }
380 
~LayoutBindingRenderCase(void)381 LayoutBindingRenderCase::~LayoutBindingRenderCase (void)
382 {
383 	deinit();
384 }
385 
init(void)386 void LayoutBindingRenderCase::init (void)
387 {
388 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
389 
390 	{
391 		de::Random				rnd					(deStringHash(getName()) ^ 0xff23a4);
392 		glw::GLint				numBindingPoints	= 0;	// Number of available binding points
393 		glw::GLint				maxVertexUnits		= 0;	// Available uniforms in the vertex shader
394 		glw::GLint				maxFragmentUnits	= 0;	// Available uniforms in the fragment shader
395 		glw::GLint				maxCombinedUnits	= 0;	// Available uniforms in all the shader stages combined
396 		glw::GLint				maxUnits			= 0;	// Maximum available uniforms for this test
397 
398 		gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits);
399 		gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits);
400 		gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits);
401 		gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints);
402 		GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed");
403 
404 		m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits << tcu::TestLog::EndMessage;
405 		m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits << tcu::TestLog::EndMessage;
406 		m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits << tcu::TestLog::EndMessage;
407 		m_testCtx.getLog() << tcu::TestLog::Message << "Maximum binding point for uniform type: " << numBindingPoints-1 << tcu::TestLog::EndMessage;
408 
409 		// Select maximum number of uniforms used for the test
410 		switch (m_shaderType)
411 		{
412 			case SHADERTYPE_VERTEX:
413 				maxUnits = maxVertexUnits;
414 				break;
415 
416 			case SHADERTYPE_FRAGMENT:
417 				maxUnits = maxFragmentUnits;
418 				break;
419 
420 			case SHADERTYPE_ALL:
421 				maxUnits = maxCombinedUnits/2;
422 				break;
423 
424 			default:
425 				DE_ASSERT(false);
426 		}
427 
428 		// Select the number of uniforms (= bindings) used for this test
429 		switch (m_testType)
430 		{
431 			case TESTTYPE_BINDING_SINGLE:
432 			case TESTTYPE_BINDING_MAX:
433 				m_numBindings = 1;
434 				break;
435 
436 			case TESTTYPE_BINDING_MULTIPLE:
437 				if (maxUnits < 2)
438 					throw tcu::NotSupportedError("Not enough uniforms available for test");
439 				m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_MULTIPLE_INSTANCES, maxUnits));
440 				break;
441 
442 			case TESTTYPE_BINDING_ARRAY:
443 			case TESTTYPE_BINDING_MAX_ARRAY:
444 				if (maxUnits < 2)
445 					throw tcu::NotSupportedError("Not enough uniforms available for test");
446 				m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits));
447 				break;
448 
449 			default:
450 				DE_ASSERT(false);
451 		}
452 
453 		// Check that we have enough uniforms in different shaders to perform the tests
454 		if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_ALL)) && (maxVertexUnits < m_numBindings) )
455 			throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test");
456 		if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_ALL)) && (maxFragmentUnits < m_numBindings) )
457 			throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test");
458 		if ( (m_shaderType == SHADERTYPE_ALL) && (maxCombinedUnits < m_numBindings*2) )
459 			throw tcu::NotSupportedError("Not enough uniforms available for test");
460 
461 		// Check that we have enough binding points to perform the tests
462 		if (numBindingPoints < m_numBindings)
463 			throw tcu::NotSupportedError("Not enough binding points available for test");
464 
465 		// Initialize the binding points i.e. populate the two binding point vectors
466 		initBindingPoints(0, numBindingPoints);
467 	}
468 
469 	// Generate the shader program - note: this must be done after deciding the binding points
470 	DE_ASSERT(!m_program);
471 	m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shaders" << tcu::TestLog::EndMessage;
472 	m_program = generateShaders();
473 	m_testCtx.getLog() << *m_program;
474 
475 	if (!m_program->isOk())
476 		throw tcu::TestError("Shader compile failed");
477 
478 	// Setup vertex and index buffers
479 	{
480 		// Get attribute and uniform locations
481 		const deUint32	program	= m_program->getProgram();
482 
483 		m_shaderProgramPosLoc		= gl.getAttribLocation(program, "a_position");
484 		m_shaderProgramArrayNdxLoc	= gl.getUniformLocation(program, "u_arrayNdx");
485 		m_vertexBuffer				= 0;
486 		m_indexBuffer				= 0;
487 
488 		// Setup buffers so that we render one quad covering the whole viewport
489 		const Vec3 vertices[] =
490 		{
491 			Vec3(-1.0f, -1.0f, +1.0f),
492 			Vec3(+1.0f, -1.0f, +1.0f),
493 			Vec3(+1.0f, +1.0f, +1.0f),
494 			Vec3(-1.0f, +1.0f, +1.0f),
495 		};
496 
497 		const deUint16 indices[] =
498 		{
499 			0, 1, 2,
500 			0, 2, 3,
501 		};
502 
503 		TCU_CHECK((m_shaderProgramPosLoc >= 0) && (m_shaderProgramArrayNdxLoc >= 0));
504 
505 		// Generate and bind index buffer
506 		gl.genBuffers(1, &m_indexBuffer);
507 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
508 		gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (DE_LENGTH_OF_ARRAY(indices)*(glw::GLsizeiptr)sizeof(indices[0])), &indices[0], GL_STATIC_DRAW);
509 		GLU_EXPECT_NO_ERROR(gl.getError(), "Index buffer setup failed");
510 
511 		// Generate and bind vertex buffer
512 		gl.genBuffers(1, &m_vertexBuffer);
513 		gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
514 		gl.bufferData(GL_ARRAY_BUFFER, (DE_LENGTH_OF_ARRAY(vertices)*(glw::GLsizeiptr)sizeof(vertices[0])), &vertices[0], GL_STATIC_DRAW);
515 		gl.enableVertexAttribArray(m_shaderProgramPosLoc);
516 		gl.vertexAttribPointer(m_shaderProgramPosLoc, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
517 		GLU_EXPECT_NO_ERROR(gl.getError(), "Vertex buffer setup failed");
518 	}
519 }
520 
deinit(void)521 void LayoutBindingRenderCase::deinit (void)
522 {
523 	if (m_program)
524 	{
525 		delete m_program;
526 		m_program = DE_NULL;
527 	}
528 
529 	if (m_shaderProgramPosLoc)
530 		m_context.getRenderContext().getFunctions().disableVertexAttribArray(m_shaderProgramPosLoc);
531 
532 	if (m_vertexBuffer)
533 	{
534 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_vertexBuffer);
535 		m_context.getRenderContext().getFunctions().bindBuffer(GL_ARRAY_BUFFER, 0);
536 	}
537 
538 	if (m_indexBuffer)
539 	{
540 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBuffer);
541 		m_context.getRenderContext().getFunctions().bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
542 	}
543 }
544 
initBindingPoints(int minBindingPoint,int numBindingPoints)545 void LayoutBindingRenderCase::initBindingPoints (int minBindingPoint, int numBindingPoints)
546 {
547 	de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
548 
549 	switch (m_testType)
550 	{
551 		case TESTTYPE_BINDING_SINGLE:
552 		{
553 			const int bpoint = rnd.getInt(minBindingPoint, numBindingPoints-1);
554 			m_bindings.push_back(bpoint);
555 			break;
556 		}
557 
558 		case TESTTYPE_BINDING_MAX:
559 			m_bindings.push_back(numBindingPoints-1);
560 			break;
561 
562 		case TESTTYPE_BINDING_MULTIPLE:
563 		{
564 			// Choose multiple unique binding points from the low and high end of available binding points
565 			std::vector<deUint32> lowBindingPoints;
566 			std::vector<deUint32> highBindingPoints;
567 
568 			for (int bpoint = 0; bpoint < numBindingPoints/2; ++bpoint)
569 				lowBindingPoints.push_back(bpoint);
570 			for (int bpoint = numBindingPoints/2; bpoint < numBindingPoints; ++bpoint)
571 				highBindingPoints.push_back(bpoint);
572 
573 			rnd.shuffle(lowBindingPoints.begin(), lowBindingPoints.end());
574 			rnd.shuffle(highBindingPoints.begin(), highBindingPoints.end());
575 
576 			for (int ndx = 0; ndx < m_numBindings; ++ndx)
577 			{
578 				if (ndx%2 == 0)
579 				{
580 					const int bpoint = lowBindingPoints.back();
581 					lowBindingPoints.pop_back();
582 					m_bindings.push_back(bpoint);
583 				}
584 				else
585 				{
586 					const int bpoint = highBindingPoints.back();
587 					highBindingPoints.pop_back();
588 					m_bindings.push_back(bpoint);
589 				}
590 
591 			}
592 			break;
593 		}
594 
595 		case TESTTYPE_BINDING_ARRAY:
596 		{
597 			const glw::GLint binding = rnd.getInt(minBindingPoint, numBindingPoints-m_numBindings);
598 			for (int ndx = 0; ndx < m_numBindings; ++ndx)
599 				m_bindings.push_back(binding+ndx);
600 			break;
601 		}
602 
603 		case TESTTYPE_BINDING_MAX_ARRAY:
604 		{
605 			const glw::GLint binding = numBindingPoints-m_numBindings;
606 			for (int ndx = 0; ndx < m_numBindings; ++ndx)
607 				m_bindings.push_back(binding+ndx);
608 			break;
609 		}
610 
611 		default:
612 			DE_ASSERT(false);
613 	}
614 }
615 
initRenderState(void)616 void LayoutBindingRenderCase::initRenderState (void)
617 {
618 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
619 
620 	gl.useProgram(m_program->getProgram());
621 	gl.viewport(0, 0, getRenderWidth(), getRenderHeight());
622 	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
623 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set render state");
624 }
625 
drawAndVerifyResult(const Vec4 & expectedColor)626 bool LayoutBindingRenderCase::drawAndVerifyResult (const Vec4& expectedColor)
627 {
628 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
629 	tcu::Surface			reference			(getRenderWidth(), getRenderHeight());
630 
631 	// the point of these test is to check layout_binding. For this purpose, we can use quite
632 	// large thresholds.
633 	const tcu::RGBA			surfaceThreshold	= m_context.getRenderContext().getRenderTarget().getPixelFormat().getColorThreshold();
634 	const tcu::RGBA			compareThreshold	= tcu::RGBA(de::clamp(2 * surfaceThreshold.getRed(),   0, 255),
635 															de::clamp(2 * surfaceThreshold.getGreen(), 0, 255),
636 															de::clamp(2 * surfaceThreshold.getBlue(),  0, 255),
637 															de::clamp(2 * surfaceThreshold.getAlpha(), 0, 255));
638 
639 	gl.clear(GL_COLOR_BUFFER_BIT);
640 
641 	// Draw
642 	gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL);
643 	GLU_EXPECT_NO_ERROR(gl.getError(), "Drawing failed");
644 
645 	// Verify
646 	tcu::Surface result(getRenderWidth(), getRenderHeight());
647 	m_testCtx.getLog() << TestLog::Message << "Reading pixels" << TestLog::EndMessage;
648 	glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
649 	GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
650 
651 	tcu::clear(reference.getAccess(), expectedColor);
652 	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output image, fragment output color is " << expectedColor << tcu::TestLog::EndMessage;
653 
654 	return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Render result", "Result verification", reference, result, compareThreshold, tcu::COMPARE_LOG_RESULT);
655 }
656 
setTestResult(bool queryTestPassed,bool imageTestPassed)657 void LayoutBindingRenderCase::setTestResult (bool queryTestPassed, bool imageTestPassed)
658 {
659 	if (queryTestPassed && imageTestPassed)
660 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
661 	else if (!queryTestPassed && !imageTestPassed)
662 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more binding point queries and image comparisons failed");
663 	else if (!queryTestPassed)
664 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more binding point queries failed");
665 	else
666 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more image comparisons failed");
667 }
668 
669 class LayoutBindingNegativeCase : public TestCase
670 {
671 public:
672 	enum ErrorType
673 	{
674 		ERRORTYPE_OVER_MAX_UNITS = 0,
675 		ERRORTYPE_LESS_THAN_ZERO,
676 		ERRORTYPE_CONTRADICTORY,
677 
678 		ERRORTYPE_LAST,
679 	};
680 
681 										LayoutBindingNegativeCase		(Context&			context,
682 																		 const char*		name,
683 																		 const char*		desc,
684 																		 ShaderType			shaderType,
685 																		 TestType			testType,
686 																		 ErrorType			errorType,
687 																		 glw::GLenum		maxBindingPointEnum,
688 																		 glw::GLenum		maxVertexUnitsEnum,
689 																		 glw::GLenum		maxFragmentUnitsEnum,
690 																		 glw::GLenum		maxTessCtrlUnitsEnum,
691 																		 glw::GLenum		maxTessEvalUnitsEnum,
692 																		 glw::GLenum		maxCombinedUnitsEnum,
693 																		 const std::string& uniformName);
694 	virtual								~LayoutBindingNegativeCase		(void);
695 
696 	virtual void						init							(void);
697 	virtual void						deinit							(void);
698 	virtual IterateResult				iterate							(void);
699 
700 protected:
701 	virtual glu::ShaderProgram*			generateShaders					(void) const = 0;
702 
703 	const glu::ShaderProgram*			m_program;
704 	const ShaderType					m_shaderType;
705 	const TestType						m_testType;
706 	const ErrorType						m_errorType;
707 	const glw::GLenum					m_maxBindingPointEnum;
708 	const glw::GLenum					m_maxVertexUnitsEnum;
709 	const glw::GLenum					m_maxFragmentUnitsEnum;
710 	const glw::GLenum					m_maxTessCtrlUnitsEnum;
711 	const glw::GLenum					m_maxTessEvalUnitsEnum;
712 	const glw::GLenum					m_maxCombinedUnitsEnum;
713 	const std::string					m_uniformName;
714 	glw::GLint							m_numBindings;
715 	std::vector<glw::GLint>				m_vertexShaderBinding;
716 	std::vector<glw::GLint>				m_fragmentShaderBinding;
717 	std::vector<glw::GLint>				m_tessCtrlShaderBinding;
718 	std::vector<glw::GLint>				m_tessEvalShaderBinding;
719 	bool								m_tessSupport;
720 
721 private:
722 	void								initBindingPoints				(int minBindingPoint, int numBindingPoints);
723 };
724 
LayoutBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType,glw::GLenum maxBindingPointEnum,glw::GLenum maxVertexUnitsEnum,glw::GLenum maxTessCtrlUnitsEnum,glw::GLenum maxTessEvalUnitsEnum,glw::GLenum maxFragmentUnitsEnum,glw::GLenum maxCombinedUnitsEnum,const std::string & uniformName)725 LayoutBindingNegativeCase::LayoutBindingNegativeCase (Context&				context,
726 													  const char*			name,
727 													  const char*			desc,
728 													  ShaderType			shaderType,
729 													  TestType				testType,
730 													  ErrorType				errorType,
731 													  glw::GLenum			maxBindingPointEnum,
732 													  glw::GLenum			maxVertexUnitsEnum,
733 													  glw::GLenum			maxTessCtrlUnitsEnum,
734 													  glw::GLenum			maxTessEvalUnitsEnum,
735 													  glw::GLenum			maxFragmentUnitsEnum,
736 													  glw::GLenum			maxCombinedUnitsEnum,
737 													  const std::string&	uniformName)
738 	: TestCase					(context, name, desc)
739 	, m_program					(DE_NULL)
740 	, m_shaderType				(shaderType)
741 	, m_testType				(testType)
742 	, m_errorType				(errorType)
743 	, m_maxBindingPointEnum		(maxBindingPointEnum)
744 	, m_maxVertexUnitsEnum		(maxVertexUnitsEnum)
745 	, m_maxFragmentUnitsEnum	(maxFragmentUnitsEnum)
746 	, m_maxTessCtrlUnitsEnum	(maxTessCtrlUnitsEnum)
747 	, m_maxTessEvalUnitsEnum	(maxTessEvalUnitsEnum)
748 	, m_maxCombinedUnitsEnum	(maxCombinedUnitsEnum)
749 	, m_uniformName				(uniformName)
750 	, m_numBindings				(0)
751 	, m_tessSupport				(false)
752 {
753 }
754 
~LayoutBindingNegativeCase(void)755 LayoutBindingNegativeCase::~LayoutBindingNegativeCase (void)
756 {
757 	deinit();
758 }
759 
init(void)760 void LayoutBindingNegativeCase::init (void)
761 {
762 	// Decide appropriate binding points for the vertex and fragment shaders
763 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
764 	de::Random				rnd					(deStringHash(getName()) ^ 0xff23a4);
765 	glw::GLint				numBindingPoints	= 0;	// Number of binding points
766 	glw::GLint				maxVertexUnits		= 0;	// Available uniforms in the vertex shader
767 	glw::GLint				maxFragmentUnits	= 0;	// Available uniforms in the fragment shader
768 	glw::GLint				maxCombinedUnits	= 0;	// Available uniforms in all the shader stages combined
769 	glw::GLint				maxTessCtrlUnits	= 0;	// Available uniforms in tessellation control shader
770 	glw::GLint				maxTessEvalUnits	= 0;	// Available uniforms in tessellation evaluation shader
771 	glw::GLint				maxUnits			= 0;	// Maximum available uniforms for this test
772 
773 	m_tessSupport = m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader")
774 					|| contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
775 
776 	if (!m_tessSupport && (m_shaderType == SHADERTYPE_TESS_EVALUATION || m_shaderType == SHADERTYPE_TESS_CONTROL))
777 		TCU_THROW(NotSupportedError, "Tesselation shaders not supported");
778 
779 	int numShaderStages = m_tessSupport ? 4 : 2;
780 
781 	gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits);
782 	gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits);
783 
784 	if (m_tessSupport)
785 	{
786 		gl.getIntegerv(m_maxTessCtrlUnitsEnum, &maxTessCtrlUnits);
787 		gl.getIntegerv(m_maxTessEvalUnitsEnum, &maxTessEvalUnits);
788 	}
789 
790 	gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits);
791 	gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints);
792 	GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed");
793 
794 	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits << tcu::TestLog::EndMessage;
795 	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits << tcu::TestLog::EndMessage;
796 
797 	if (m_tessSupport)
798 	{
799 		m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the tessellation control shader: " << maxTessCtrlUnits << tcu::TestLog::EndMessage;
800 		m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the tessellation evaluation shader: " << maxTessCtrlUnits << tcu::TestLog::EndMessage;
801 	}
802 
803 	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits << tcu::TestLog::EndMessage;
804 	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum binding point for uniform type: " << numBindingPoints-1 << tcu::TestLog::EndMessage;
805 
806 	// Select maximum number of uniforms used for the test
807 	switch (m_shaderType)
808 	{
809 		case SHADERTYPE_VERTEX:
810 			maxUnits = maxVertexUnits;
811 			break;
812 
813 		case SHADERTYPE_FRAGMENT:
814 			maxUnits = maxFragmentUnits;
815 			break;
816 
817 		case SHADERTYPE_ALL:
818 			maxUnits = de::min(de::min(de::min(maxVertexUnits, maxFragmentUnits), de::min(maxTessCtrlUnits, maxTessEvalUnits)), maxCombinedUnits/numShaderStages);
819 			break;
820 
821 		case SHADERTYPE_TESS_CONTROL:
822 			maxUnits = maxTessCtrlUnits;
823 			break;
824 
825 		case SHADERTYPE_TESS_EVALUATION:
826 			maxUnits = maxTessEvalUnits;
827 			break;
828 
829 		default:
830 			DE_ASSERT(false);
831 	}
832 
833 	// Select the number of uniforms (= bindings) used for this test
834 	switch (m_testType)
835 	{
836 		case TESTTYPE_BINDING_SINGLE:
837 		case TESTTYPE_BINDING_MAX:
838 			m_numBindings = 1;
839 			break;
840 
841 		case TESTTYPE_BINDING_MULTIPLE:
842 		case TESTTYPE_BINDING_ARRAY:
843 		case TESTTYPE_BINDING_MAX_ARRAY:
844 			if (m_errorType == ERRORTYPE_CONTRADICTORY)
845 			{
846 				// leave room for contradictory case
847 				if (maxUnits < 3)
848 					TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
849 				m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits-1));
850 			}
851 			else
852 			{
853 				if (maxUnits < 2)
854 					TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
855 				m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits));
856 			}
857 			break;
858 
859 		default:
860 			DE_ASSERT(false);
861 	}
862 
863 	// Check that we have enough uniforms in different shaders to perform the tests
864 	if (((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_ALL)) && (maxVertexUnits < m_numBindings) )
865 		TCU_THROW(NotSupportedError, "Vertex shader: not enough uniforms available for test");
866 
867 	if (((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_ALL)) && (maxFragmentUnits < m_numBindings) )
868 		TCU_THROW(NotSupportedError, "Fragment shader: not enough uniforms available for test");
869 
870 	if (m_tessSupport && ((m_shaderType == SHADERTYPE_TESS_CONTROL) || (m_shaderType == SHADERTYPE_ALL)) && (maxTessCtrlUnits < m_numBindings) )
871 		TCU_THROW(NotSupportedError, "Tessellation control shader: not enough uniforms available for test");
872 
873 	if (m_tessSupport && ((m_shaderType == SHADERTYPE_TESS_EVALUATION) || (m_shaderType == SHADERTYPE_ALL)) && (maxTessEvalUnits < m_numBindings) )
874 		TCU_THROW(NotSupportedError, "Tessellation evaluation shader: not enough uniforms available for test");
875 
876 	if ((m_shaderType == SHADERTYPE_ALL) && (maxCombinedUnits < m_numBindings*numShaderStages) )
877 		TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
878 
879 	// Check that we have enough binding points to perform the tests
880 	if (numBindingPoints < m_numBindings)
881 		TCU_THROW(NotSupportedError, "Not enough binding points available for test");
882 
883 	if (m_errorType == ERRORTYPE_CONTRADICTORY && numBindingPoints == m_numBindings)
884 		TCU_THROW(NotSupportedError, "Not enough binding points available for test");
885 
886 	// Initialize the binding points i.e. populate the two binding point vectors
887 	initBindingPoints(0, numBindingPoints);
888 
889 	// Generate the shader program - note: this must be done after deciding the binding points
890 	DE_ASSERT(!m_program);
891 	m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shaders" << tcu::TestLog::EndMessage;
892 	m_program = generateShaders();
893 	m_testCtx.getLog() << *m_program;
894 }
895 
deinit(void)896 void LayoutBindingNegativeCase::deinit (void)
897 {
898 	if (m_program)
899 	{
900 		delete m_program;
901 		m_program = DE_NULL;
902 	}
903 }
904 
iterate(void)905 TestCase::IterateResult LayoutBindingNegativeCase::iterate (void)
906 {
907 	bool pass = false;
908 	std::string failMessage;
909 
910 	switch (m_errorType)
911 	{
912 		case ERRORTYPE_CONTRADICTORY:		// Contradictory binding points should cause a link-time error
913 			if (!(m_program->getProgramInfo()).linkOk)
914 				pass = true;
915 			failMessage = "Test failed - expected a link-time error";
916 			break;
917 
918 		case ERRORTYPE_LESS_THAN_ZERO:		// Out of bounds binding points should cause a compile-time error
919 		case ERRORTYPE_OVER_MAX_UNITS:
920 			if (m_tessSupport)
921 			{
922 				if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk
923 					|| !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk)
924 					|| !(m_program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_CONTROL).compileOk)
925 					|| !(m_program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_EVALUATION)).compileOk)
926 					pass = true;
927 			}
928 			else
929 			{
930 				if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk
931 					|| !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk))
932 					pass = true;
933 			}
934 
935 			failMessage = "Test failed - expected a compile-time error";
936 			break;
937 
938 		default:
939 			DE_ASSERT(false);
940 	}
941 
942 	if (pass)
943 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
944 	else
945 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, failMessage.c_str());
946 
947 	return STOP;
948 }
949 
initBindingPoints(int minBindingPoint,int numBindingPoints)950 void LayoutBindingNegativeCase::initBindingPoints (int minBindingPoint, int numBindingPoints)
951 {
952 	de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
953 
954 	switch (m_errorType)
955 	{
956 		case ERRORTYPE_OVER_MAX_UNITS:	// Select a binding point that is 1 over the maximum
957 		{
958 			m_vertexShaderBinding.push_back(numBindingPoints+1-m_numBindings);
959 			m_fragmentShaderBinding.push_back(numBindingPoints+1-m_numBindings);
960 			m_tessCtrlShaderBinding.push_back(numBindingPoints+1-m_numBindings);
961 			m_tessEvalShaderBinding.push_back(numBindingPoints+1-m_numBindings);
962 			break;
963 		}
964 
965 		case ERRORTYPE_LESS_THAN_ZERO:	// Select a random negative binding point
966 		{
967 			const glw::GLint binding = -rnd.getInt(1, m_numBindings);
968 			m_vertexShaderBinding.push_back(binding);
969 			m_fragmentShaderBinding.push_back(binding);
970 			m_tessCtrlShaderBinding.push_back(binding);
971 			m_tessEvalShaderBinding.push_back(binding);
972 			break;
973 		}
974 
975 		case ERRORTYPE_CONTRADICTORY:	// Select two valid, but contradictory binding points
976 		{
977 			m_vertexShaderBinding.push_back(minBindingPoint);
978 			m_fragmentShaderBinding.push_back((minBindingPoint+1)%numBindingPoints);
979 			m_tessCtrlShaderBinding.push_back((minBindingPoint+2)%numBindingPoints);
980 			m_tessEvalShaderBinding.push_back((minBindingPoint+3)%numBindingPoints);
981 
982 			DE_ASSERT(m_vertexShaderBinding.back()		!= m_fragmentShaderBinding.back());
983 			DE_ASSERT(m_fragmentShaderBinding.back()	!= m_tessEvalShaderBinding.back());
984 			DE_ASSERT(m_tessEvalShaderBinding.back()	!= m_tessCtrlShaderBinding.back());
985 			DE_ASSERT(m_tessCtrlShaderBinding.back()	!= m_vertexShaderBinding.back());
986 			DE_ASSERT(m_vertexShaderBinding.back()		!= m_tessEvalShaderBinding.back());
987 			DE_ASSERT(m_tessCtrlShaderBinding.back()	!= m_fragmentShaderBinding.back());
988 			break;
989 		}
990 
991 		default:
992 			DE_ASSERT(false);
993 	}
994 
995 	// In case we are testing with multiple uniforms populate the rest of the binding points
996 	for (int ndx = 1; ndx < m_numBindings; ++ndx)
997 	{
998 		m_vertexShaderBinding.push_back(m_vertexShaderBinding.front()+ndx);
999 		m_fragmentShaderBinding.push_back(m_fragmentShaderBinding.front()+ndx);
1000 		m_tessCtrlShaderBinding.push_back(m_tessCtrlShaderBinding.front()+ndx);
1001 		m_tessEvalShaderBinding.push_back(m_tessCtrlShaderBinding.front()+ndx);
1002 	}
1003 }
1004 
1005 class SamplerBindingRenderCase : public LayoutBindingRenderCase
1006 {
1007 public:
1008 									SamplerBindingRenderCase		(Context& context, const char* name, const char* desc, ShaderType shaderType, TestType testType, glw::GLenum samplerType, glw::GLenum textureType);
1009 									~SamplerBindingRenderCase		(void);
1010 
1011 	void							init							(void);
1012 	void							deinit							(void);
1013 	IterateResult					iterate							(void);
1014 
1015 private:
1016 	glu::ShaderProgram*				generateShaders					(void) const;
1017 	glu::DataType					getSamplerTexCoordType			(void) const;
1018 	void							initializeTexture				(glw::GLint bindingPoint, glw::GLint textureName, const Vec4& color) const;
1019 
1020 	const glw::GLenum				m_samplerType;
1021 	const glw::GLenum				m_textureType;
1022 
1023 	std::vector<glw::GLuint>		m_textures;
1024 	std::vector<Vec4>				m_textureColors;
1025 };
1026 
1027 
SamplerBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,glw::GLenum samplerType,glw::GLenum textureType)1028 SamplerBindingRenderCase::SamplerBindingRenderCase (Context&		context,
1029 													const char*		name,
1030 													const char*		desc,
1031 													ShaderType		shaderType,
1032 													TestType		testType,
1033 													glw::GLenum		samplerType,
1034 													glw::GLenum		textureType)
1035 	: LayoutBindingRenderCase	(context, name, desc, shaderType, testType, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, "u_sampler")
1036 	, m_samplerType				(samplerType)
1037 	, m_textureType				(textureType)
1038 {
1039 }
1040 
~SamplerBindingRenderCase(void)1041 SamplerBindingRenderCase::~SamplerBindingRenderCase (void)
1042 {
1043 	deinit();
1044 }
1045 
init(void)1046 void SamplerBindingRenderCase::init (void)
1047 {
1048 	LayoutBindingRenderCase::init();
1049 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
1050 	de::Random				rnd		(deStringHash(getName()) ^ 0xff23a4);
1051 
1052 
1053 	// Initialize texture resources
1054 	m_textures = std::vector<glw::GLuint>(m_numBindings,  0);
1055 
1056 	// Texture colors
1057 	for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1058 		m_textureColors.push_back(getRandomColor(rnd));
1059 
1060 	// Textures
1061 	gl.genTextures((glw::GLsizei)m_textures.size(), &m_textures[0]);
1062 
1063 	for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1064 		initializeTexture(m_bindings[texNdx], m_textures[texNdx], m_textureColors[texNdx]);
1065 
1066 	gl.activeTexture(GL_TEXTURE0);
1067 }
1068 
deinit(void)1069 void SamplerBindingRenderCase::deinit(void)
1070 {
1071 	LayoutBindingRenderCase::deinit();
1072 
1073 	// Clean up texture data
1074 	for (int i = 0; i < (int)m_textures.size(); ++i)
1075 	{
1076 		if (m_textures[i])
1077 		{
1078 			m_context.getRenderContext().getFunctions().deleteTextures(1, &m_textures[i]);
1079 			m_context.getRenderContext().getFunctions().bindTexture(m_textureType, 0);
1080 		}
1081 	}
1082 }
1083 
iterate(void)1084 TestCase::IterateResult SamplerBindingRenderCase::iterate (void)
1085 {
1086 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
1087 	const int				iterations		= m_numBindings;
1088 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1089 	bool					imageTestPassed	= true;
1090 	bool					queryTestPassed	= true;
1091 
1092 	// Set the viewport and enable the shader program
1093 	initRenderState();
1094 
1095 	for (int iterNdx = 0; iterNdx < iterations; ++iterNdx)
1096 	{
1097 		// Set the uniform value indicating the current array index
1098 		gl.uniform1i(m_shaderProgramArrayNdxLoc, iterNdx);
1099 
1100 		// Query binding point
1101 		const std::string	name	= arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx);
1102 		const glw::GLint	binding = m_bindings[iterNdx];
1103 		glw::GLint			val		= -1;
1104 
1105 		gl.getUniformiv(m_program->getProgram(), gl.getUniformLocation(m_program->getProgram(), name.c_str()), &val);
1106 		m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage;
1107 		GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed");
1108 
1109 		// Draw and verify
1110 		if (val != binding)
1111 			queryTestPassed = false;
1112 		if (!drawAndVerifyResult(m_textureColors[iterNdx]))
1113 			imageTestPassed = false;
1114 	}
1115 
1116 	setTestResult(queryTestPassed, imageTestPassed);
1117 	return STOP;
1118 }
1119 
generateShaders(void) const1120 glu::ShaderProgram* SamplerBindingRenderCase::generateShaders (void) const
1121 {
1122 	std::ostringstream		shaderUniformDecl;
1123 	std::ostringstream		shaderBody;
1124 
1125 	const std::string		texCoordType	= glu::getDataTypeName(getSamplerTexCoordType());
1126 	const std::string		samplerType		= glu::getDataTypeName(glu::getDataTypeFromGLType(m_samplerType));
1127 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY) ? true : false;
1128 	const int				numDeclarations =  arrayInstance ? 1 : m_numBindings;
1129 
1130 	// Generate the uniform declarations for the vertex and fragment shaders
1131 	for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1132 	{
1133 		shaderUniformDecl << "layout(binding = " << m_bindings[declNdx] << ") uniform highp " << samplerType << " "
1134 			<< (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1135 	}
1136 
1137 	// Generate the shader body for the vertex and fragment shaders
1138 	for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx)
1139 	{
1140 		shaderBody	<< "	" << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n"
1141 					<< "	{\n"
1142 					<< "		color = texture(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0.5));\n"
1143 					<< "	}\n";
1144 	}
1145 
1146 	shaderBody	<< "	else\n"
1147 				<< "	{\n"
1148 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1149 				<< "	}\n";
1150 
1151 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
1152 					<< glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))
1153 					<< glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())));
1154 }
1155 
initializeTexture(glw::GLint bindingPoint,glw::GLint textureName,const Vec4 & color) const1156 void SamplerBindingRenderCase::initializeTexture (glw::GLint bindingPoint, glw::GLint textureName, const Vec4& color) const
1157 {
1158 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1159 
1160 	gl.activeTexture(GL_TEXTURE0 + bindingPoint);
1161 	gl.bindTexture(m_textureType, textureName);
1162 	gl.texParameteri(m_textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1163 
1164 	switch (m_textureType)
1165 	{
1166 		case GL_TEXTURE_2D:
1167 		{
1168 			tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1169 			tcu::clear(level.getAccess(), color);
1170 			glu::texImage2D(m_context.getRenderContext(), m_textureType, 0, GL_RGBA8, level.getAccess());
1171 			break;
1172 		}
1173 
1174 		case GL_TEXTURE_3D:
1175 		{
1176 			tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1177 			tcu::clear(level.getAccess(), color);
1178 			glu::texImage3D(m_context.getRenderContext(), m_textureType, 0, GL_RGBA8, level.getAccess());
1179 			break;
1180 		}
1181 
1182 		default:
1183 			DE_ASSERT(false);
1184 	}
1185 
1186 	GLU_EXPECT_NO_ERROR(gl.getError(), "Texture initialization failed");
1187 }
1188 
getSamplerTexCoordType(void) const1189 glu::DataType SamplerBindingRenderCase::getSamplerTexCoordType (void) const
1190 {
1191 	switch (m_samplerType)
1192 	{
1193 		case GL_SAMPLER_2D:
1194 			return glu::TYPE_FLOAT_VEC2;
1195 
1196 		case GL_SAMPLER_3D:
1197 			return glu::TYPE_FLOAT_VEC3;
1198 
1199 		default:
1200 			DE_ASSERT(false);
1201 			return glu::TYPE_INVALID;
1202 	}
1203 }
1204 
1205 
1206 class SamplerBindingNegativeCase : public LayoutBindingNegativeCase
1207 {
1208 public:
1209 									SamplerBindingNegativeCase		(Context&		context,
1210 																	 const char*	name,
1211 																	 const char*	desc,
1212 																	 ShaderType		shaderType,
1213 																	 TestType		testType,
1214 																	 ErrorType		errorType,
1215 																	 glw::GLenum	samplerType);
1216 									~SamplerBindingNegativeCase		(void);
1217 
1218 private:
1219 	glu::ShaderProgram*				generateShaders					(void) const;
1220 	glu::DataType					getSamplerTexCoordType			(void) const;
1221 
1222 	const glw::GLenum				m_samplerType;
1223 };
1224 
SamplerBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType,glw::GLenum samplerType)1225 SamplerBindingNegativeCase::SamplerBindingNegativeCase (Context&		context,
1226 														const char*		name,
1227 														const char*		desc,
1228 														ShaderType		shaderType,
1229 														TestType		testType,
1230 														ErrorType		errorType,
1231 														glw::GLenum		samplerType)
1232 	: LayoutBindingNegativeCase		(context,
1233 									 name,
1234 									 desc,
1235 									 shaderType,
1236 									 testType,
1237 									 errorType,
1238 									 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
1239 									 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
1240 									 GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,
1241 									 GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,
1242 									 GL_MAX_TEXTURE_IMAGE_UNITS,
1243 									 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
1244 									 "u_sampler")
1245 	, m_samplerType					(samplerType)
1246 {
1247 }
1248 
~SamplerBindingNegativeCase(void)1249 SamplerBindingNegativeCase::~SamplerBindingNegativeCase (void)
1250 {
1251 	LayoutBindingNegativeCase::deinit();
1252 }
1253 
generateShaders(void) const1254 glu::ShaderProgram*	SamplerBindingNegativeCase::generateShaders	(void) const
1255 {
1256 	std::ostringstream		vertexUniformDecl;
1257 	std::ostringstream		fragmentUniformDecl;
1258 	std::ostringstream		tessCtrlUniformDecl;
1259 	std::ostringstream		tessEvalUniformDecl;
1260 	std::ostringstream		shaderBody;
1261 
1262 	const std::string		texCoordType	= glu::getDataTypeName(getSamplerTexCoordType());
1263 	const std::string		samplerType		= glu::getDataTypeName(glu::getDataTypeFromGLType(m_samplerType));
1264 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1265 	const int				numDeclarations = arrayInstance ? 1 : m_numBindings;
1266 
1267 	// Generate the uniform declarations for the vertex and fragment shaders
1268 	for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1269 	{
1270 		vertexUniformDecl << "layout(binding = " << m_vertexShaderBinding[declNdx] << ") uniform highp " << samplerType
1271 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1272 		fragmentUniformDecl << "layout(binding = " << m_fragmentShaderBinding[declNdx] << ") uniform highp " << samplerType
1273 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1274 		tessCtrlUniformDecl << "layout(binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform highp " << samplerType
1275 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1276 		tessEvalUniformDecl << "layout(binding = " << m_tessEvalShaderBinding[declNdx] << ") uniform highp " << samplerType
1277 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1278 	}
1279 
1280 	// Generate the shader body for the vertex and fragment shaders
1281 	for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx)
1282 	{
1283 		shaderBody	<< "	" << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n"
1284 					<< "	{\n"
1285 					<< "		color = texture(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0.5));\n"
1286 					<< "	}\n";
1287 	}
1288 
1289 	shaderBody	<< "	else\n"
1290 				<< "	{\n"
1291 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1292 				<< "	}\n";
1293 
1294 	glu::ProgramSources sources = glu::ProgramSources()
1295 				<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
1296 				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
1297 
1298 	if (m_tessSupport)
1299 		sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
1300 				<< glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
1301 
1302 	return new glu::ShaderProgram(m_context.getRenderContext(), sources);
1303 
1304 }
1305 
getSamplerTexCoordType(void) const1306 glu::DataType SamplerBindingNegativeCase::getSamplerTexCoordType(void) const
1307 {
1308 	switch (m_samplerType)
1309 	{
1310 		case GL_SAMPLER_2D:
1311 			return glu::TYPE_FLOAT_VEC2;
1312 
1313 		case GL_SAMPLER_3D:
1314 			return glu::TYPE_FLOAT_VEC3;
1315 
1316 		default:
1317 			DE_ASSERT(false);
1318 			return glu::TYPE_INVALID;
1319 	}
1320 }
1321 
1322 class ImageBindingRenderCase : public LayoutBindingRenderCase
1323 {
1324 public:
1325 											ImageBindingRenderCase			(Context&		context,
1326 																			 const char*	name,
1327 																			 const char*	desc,
1328 																			 ShaderType		shaderType,
1329 																			 TestType		testType,
1330 																			 glw::GLenum	imageType,
1331 																			 glw::GLenum	textureType);
1332 											~ImageBindingRenderCase			(void);
1333 
1334 	void									init							(void);
1335 	void									deinit							(void);
1336 	IterateResult							iterate							(void);
1337 
1338 private:
1339 	glu::ShaderProgram*						generateShaders					(void) const;
1340 	void									initializeImage					(glw::GLint imageBindingPoint, glw::GLint textureBindingPoint, glw::GLint textureName, const Vec4& color) const;
1341 	glu::DataType							getImageTexCoordType			(void) const;
1342 
1343 	const glw::GLenum						m_imageType;
1344 	const glw::GLenum						m_textureType;
1345 
1346 	std::vector<glw::GLuint>				m_textures;
1347 	std::vector<Vec4>						m_textureColors;
1348 };
1349 
1350 
ImageBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,glw::GLenum imageType,glw::GLenum textureType)1351 ImageBindingRenderCase::ImageBindingRenderCase (Context&		context,
1352 												const char*		name,
1353 												const char*		desc,
1354 												ShaderType		shaderType,
1355 												TestType		testType,
1356 												glw::GLenum		imageType,
1357 												glw::GLenum		textureType)
1358 	: LayoutBindingRenderCase		(context, name, desc, shaderType, testType, GL_MAX_IMAGE_UNITS, GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS, GL_MAX_COMBINED_IMAGE_UNIFORMS, "u_image")
1359 	, m_imageType					(imageType)
1360 	, m_textureType					(textureType)
1361 {
1362 }
1363 
~ImageBindingRenderCase(void)1364 ImageBindingRenderCase::~ImageBindingRenderCase (void)
1365 {
1366 	deinit();
1367 }
1368 
init(void)1369 void ImageBindingRenderCase::init (void)
1370 {
1371 	LayoutBindingRenderCase::init();
1372 
1373 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
1374 	de::Random				rnd		(deStringHash(getName()) ^ 0xff23a4);
1375 
1376 	// Initialize image / texture resources
1377 	m_textures = std::vector<glw::GLuint>(m_numBindings,  0);
1378 
1379 	// Texture colors
1380 	for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1381 		m_textureColors.push_back(getRandomColor(rnd));
1382 
1383 	// Image textures
1384 	gl.genTextures(m_numBindings, &m_textures[0]);
1385 
1386 	for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1387 		initializeImage(m_bindings[texNdx], texNdx, m_textures[texNdx], m_textureColors[texNdx]);
1388 }
1389 
deinit(void)1390 void ImageBindingRenderCase::deinit (void)
1391 {
1392 	LayoutBindingRenderCase::deinit();
1393 
1394 	// Clean up texture data
1395 	for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1396 	{
1397 		if (m_textures[texNdx])
1398 		{
1399 			m_context.getRenderContext().getFunctions().deleteTextures(1, &m_textures[texNdx]);
1400 			m_context.getRenderContext().getFunctions().bindTexture(m_textureType, 0);
1401 		}
1402 	}
1403 }
1404 
iterate(void)1405 TestCase::IterateResult ImageBindingRenderCase::iterate	(void)
1406 {
1407 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
1408 	const int				iterations		= m_numBindings;
1409 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1410 	bool					queryTestPassed	= true;
1411 	bool					imageTestPassed = true;
1412 
1413 	// Set the viewport and enable the shader program
1414 	initRenderState();
1415 
1416 	for (int iterNdx = 0; iterNdx < iterations; ++iterNdx)
1417 	{
1418 		// Set the uniform value indicating the current array index
1419 		gl.uniform1i(m_shaderProgramArrayNdxLoc, iterNdx);
1420 
1421 		const std::string	name	= (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx));
1422 		const glw::GLint	binding = m_bindings[iterNdx];
1423 		glw::GLint			val		= -1;
1424 
1425 		gl.getUniformiv(m_program->getProgram(), gl.getUniformLocation(m_program->getProgram(), name.c_str()), &val);
1426 		m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage;
1427 		GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed");
1428 
1429 		// Draw and verify
1430 		if (val != binding)
1431 			queryTestPassed = false;
1432 		if (!drawAndVerifyResult(m_textureColors[iterNdx]))
1433 			imageTestPassed = false;
1434 	}
1435 
1436 	setTestResult(queryTestPassed, imageTestPassed);
1437 	return STOP;
1438 }
1439 
initializeImage(glw::GLint imageBindingPoint,glw::GLint textureBindingPoint,glw::GLint textureName,const Vec4 & color) const1440 void ImageBindingRenderCase::initializeImage (glw::GLint imageBindingPoint, glw::GLint textureBindingPoint, glw::GLint textureName, const Vec4& color) const
1441 {
1442 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1443 
1444 	gl.activeTexture(GL_TEXTURE0 + textureBindingPoint);
1445 	gl.bindTexture(m_textureType, textureName);
1446 	gl.texParameteri(m_textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1447 
1448 	switch (m_textureType)
1449 	{
1450 		case GL_TEXTURE_2D:
1451 		{
1452 			tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1453 			tcu::clear(level.getAccess(), color);
1454 			gl.texStorage2D(m_textureType, 1, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1455 			gl.texSubImage2D(m_textureType, 0, 0, 0, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, level.getAccess().getDataPtr());
1456 			break;
1457 		}
1458 
1459 		case GL_TEXTURE_3D:
1460 		{
1461 			tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1462 			tcu::clear(level.getAccess(), color);
1463 			gl.texStorage3D(m_textureType, 1, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1464 			gl.texSubImage3D(m_textureType, 0, 0, 0, 0, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, level.getAccess().getDataPtr());
1465 			break;
1466 		}
1467 
1468 		default:
1469 			DE_ASSERT(false);
1470 	}
1471 
1472 	gl.bindTexture(m_textureType, 0);
1473 	gl.bindImageTexture(imageBindingPoint, textureName, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA8);
1474 	GLU_EXPECT_NO_ERROR(gl.getError(), "Image initialization failed");
1475 }
1476 
generateShaders(void) const1477 glu::ShaderProgram* ImageBindingRenderCase::generateShaders (void) const
1478 {
1479 	std::ostringstream		shaderUniformDecl;
1480 	std::ostringstream		shaderBody;
1481 
1482 	const std::string		texCoordType	= glu::getDataTypeName(getImageTexCoordType());
1483 	const std::string		imageType		= glu::getDataTypeName(glu::getDataTypeFromGLType(m_imageType));
1484 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY) ? true : false;
1485 	const int				numDeclarations = (arrayInstance ? 1 : m_numBindings);
1486 
1487 	// Generate the uniform declarations for the vertex and fragment shaders
1488 	for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1489 	{
1490 		shaderUniformDecl << "layout(rgba8, binding = " << m_bindings[declNdx] << ") uniform readonly highp " << imageType
1491 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1492 	}
1493 
1494 	// Generate the shader body for the vertex and fragment shaders
1495 	for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx)
1496 	{
1497 		shaderBody	<< "	" << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n"
1498 					<< "	{\n"
1499 					<< "		color = imageLoad(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0));\n"
1500 					<< "	}\n";
1501 	}
1502 
1503 	shaderBody	<< "	else\n"
1504 				<< "	{\n"
1505 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1506 				<< "	}\n";
1507 
1508 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
1509 					<< glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))
1510 					<< glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())));
1511 }
1512 
getImageTexCoordType(void) const1513 glu::DataType ImageBindingRenderCase::getImageTexCoordType(void) const
1514 {
1515 	switch (m_imageType)
1516 	{
1517 		case GL_IMAGE_2D:
1518 			return glu::TYPE_INT_VEC2;
1519 
1520 		case GL_IMAGE_3D:
1521 			return glu::TYPE_INT_VEC3;
1522 
1523 		default:
1524 			DE_ASSERT(false);
1525 			return glu::TYPE_INVALID;
1526 	}
1527 }
1528 
1529 
1530 class ImageBindingNegativeCase : public LayoutBindingNegativeCase
1531 {
1532 public:
1533 											ImageBindingNegativeCase		(Context&		context,
1534 																			 const char*	name,
1535 																			 const char*	desc,
1536 																			 ShaderType		shaderType,
1537 																			 TestType		testType,
1538 																			 ErrorType		errorType,
1539 																			 glw::GLenum	imageType);
1540 											~ImageBindingNegativeCase		(void);
1541 
1542 private:
1543 	glu::ShaderProgram*						generateShaders					(void) const;
1544 	glu::DataType							getImageTexCoordType			(void) const;
1545 
1546 	const glw::GLenum						m_imageType;
1547 };
1548 
ImageBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType,glw::GLenum imageType)1549 ImageBindingNegativeCase::ImageBindingNegativeCase (Context&		context,
1550 													const char*		name,
1551 													const char*		desc,
1552 													ShaderType		shaderType,
1553 													TestType		testType,
1554 													ErrorType		errorType,
1555 													glw::GLenum		imageType)
1556 	: LayoutBindingNegativeCase		(context,
1557 									 name,
1558 									 desc,
1559 									 shaderType,
1560 									 testType,
1561 									 errorType,
1562 									 GL_MAX_IMAGE_UNITS,
1563 									 GL_MAX_VERTEX_IMAGE_UNIFORMS,
1564 									 GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS,
1565 									 GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS,
1566 									 GL_MAX_FRAGMENT_IMAGE_UNIFORMS,
1567 									 GL_MAX_COMBINED_IMAGE_UNIFORMS,
1568 									 "u_image")
1569 	, m_imageType					(imageType)
1570 {
1571 }
1572 
~ImageBindingNegativeCase(void)1573 ImageBindingNegativeCase::~ImageBindingNegativeCase (void)
1574 {
1575 	deinit();
1576 }
1577 
generateShaders(void) const1578 glu::ShaderProgram* ImageBindingNegativeCase::generateShaders (void) const
1579 {
1580 	std::ostringstream		vertexUniformDecl;
1581 	std::ostringstream		fragmentUniformDecl;
1582 	std::ostringstream		tessCtrlUniformDecl;
1583 	std::ostringstream		tessEvalUniformDecl;
1584 	std::ostringstream		shaderBody;
1585 
1586 	const std::string		texCoordType	= glu::getDataTypeName(getImageTexCoordType());
1587 	const std::string		imageType		= glu::getDataTypeName(glu::getDataTypeFromGLType(m_imageType));
1588 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1589 	const int				numDeclarations = (arrayInstance ? 1 : m_numBindings);
1590 
1591 	// Generate the uniform declarations for the vertex and fragment shaders
1592 	for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1593 	{
1594 		vertexUniformDecl << "layout(rgba8, binding = " << m_vertexShaderBinding[declNdx] << ") uniform readonly highp " << imageType
1595 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1596 		fragmentUniformDecl << "layout(rgba8, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform readonly highp " << imageType
1597 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1598 		tessCtrlUniformDecl << "layout(rgba8, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform readonly highp " << imageType
1599 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1600 		tessEvalUniformDecl << "layout(rgba8, binding = " << m_tessEvalShaderBinding[declNdx] << ") uniform readonly highp " << imageType
1601 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
1602 	}
1603 
1604 	// Generate the shader body for the vertex and fragment shaders
1605 	for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx)
1606 	{
1607 		shaderBody	<< "	" << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n"
1608 					<< "	{\n"
1609 					<< "		color = imageLoad(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0));\n"
1610 					<< "	}\n";
1611 	}
1612 
1613 	shaderBody	<< "	else\n"
1614 				<< "	{\n"
1615 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1616 				<< "	}\n";
1617 
1618 	glu::ProgramSources sources = glu::ProgramSources()
1619 				<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
1620 				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
1621 
1622 	if (m_tessSupport)
1623 		sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
1624 				<< glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
1625 
1626 	return new glu::ShaderProgram(m_context.getRenderContext(), sources);
1627 }
1628 
getImageTexCoordType(void) const1629 glu::DataType ImageBindingNegativeCase::getImageTexCoordType(void) const
1630 {
1631 	switch (m_imageType)
1632 	{
1633 		case GL_IMAGE_2D:
1634 			return glu::TYPE_INT_VEC2;
1635 
1636 		case GL_IMAGE_3D:
1637 			return glu::TYPE_INT_VEC3;
1638 
1639 		default:
1640 			DE_ASSERT(false);
1641 			return glu::TYPE_INVALID;
1642 	}
1643 }
1644 
1645 
1646 class UBOBindingRenderCase : public LayoutBindingRenderCase
1647 {
1648 public:
1649 											UBOBindingRenderCase		(Context&		context,
1650 																		 const char*	name,
1651 																		 const char*	desc,
1652 																		 ShaderType		shaderType,
1653 																		 TestType		testType);
1654 											~UBOBindingRenderCase		(void);
1655 
1656 	void									init						(void);
1657 	void									deinit						(void);
1658 	IterateResult							iterate						(void);
1659 
1660 private:
1661 	glu::ShaderProgram*						generateShaders				(void) const;
1662 
1663 	std::vector<deUint32>					m_buffers;
1664 	std::vector<Vec4>						m_expectedColors;
1665 };
1666 
UBOBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType)1667 UBOBindingRenderCase::UBOBindingRenderCase (Context&		context,
1668 											const char*		name,
1669 											const char*		desc,
1670 											ShaderType		shaderType,
1671 											TestType		testType)
1672 	: LayoutBindingRenderCase (context, name, desc, shaderType, testType, GL_MAX_UNIFORM_BUFFER_BINDINGS, GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, GL_MAX_COMBINED_UNIFORM_BLOCKS, "ColorBlock")
1673 {
1674 }
1675 
~UBOBindingRenderCase(void)1676 UBOBindingRenderCase::~UBOBindingRenderCase (void)
1677 {
1678 	deinit();
1679 }
1680 
init(void)1681 void UBOBindingRenderCase::init (void)
1682 {
1683 	LayoutBindingRenderCase::init();
1684 
1685 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
1686 	de::Random				rnd		(deStringHash(getName()) ^ 0xff23a4);
1687 
1688 	// Initialize UBOs and related data
1689 	m_buffers = std::vector<glw::GLuint>(m_numBindings,  0);
1690 	gl.genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]);
1691 
1692 	for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1693 	{
1694 			m_expectedColors.push_back(getRandomColor(rnd));
1695 			m_expectedColors.push_back(getRandomColor(rnd));
1696 	}
1697 
1698 	for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1699 	{
1700 		gl.bindBuffer(GL_UNIFORM_BUFFER, m_buffers[bufNdx]);
1701 		gl.bufferData(GL_UNIFORM_BUFFER, 2*sizeof(Vec4), &(m_expectedColors[2*bufNdx]), GL_STATIC_DRAW);
1702 		gl.bindBufferBase(GL_UNIFORM_BUFFER, m_bindings[bufNdx], m_buffers[bufNdx]);
1703 	}
1704 
1705 	GLU_EXPECT_NO_ERROR(gl.getError(), "UBO setup failed");
1706 }
1707 
deinit(void)1708 void UBOBindingRenderCase::deinit (void)
1709 {
1710 	LayoutBindingRenderCase::deinit();
1711 
1712 	// Clean up UBO data
1713 	for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1714 	{
1715 		if (m_buffers[bufNdx])
1716 		{
1717 			m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffers[bufNdx]);
1718 			m_context.getRenderContext().getFunctions().bindBuffer(GL_UNIFORM_BUFFER, 0);
1719 		}
1720 	}
1721 }
1722 
iterate(void)1723 TestCase::IterateResult UBOBindingRenderCase::iterate (void)
1724 {
1725 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
1726 	const int				iterations		= m_numBindings;
1727 	const glw::GLenum		prop			= GL_BUFFER_BINDING;
1728 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1729 	bool					queryTestPassed	= true;
1730 	bool					imageTestPassed = true;
1731 
1732 	// Set the viewport and enable the shader program
1733 	initRenderState();
1734 
1735 	for (int iterNdx = 0; iterNdx < iterations; ++iterNdx)
1736 	{
1737 		// Query binding point
1738 		const std::string	name	= (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx));
1739 		const glw::GLint	binding = m_bindings[iterNdx];
1740 		glw::GLint			val		= -1;
1741 
1742 		gl.getProgramResourceiv(m_program->getProgram(), GL_UNIFORM_BLOCK, gl.getProgramResourceIndex(m_program->getProgram(), GL_UNIFORM_BLOCK, name.c_str() ), 1, &prop, 1, DE_NULL, &val);
1743 		m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage;
1744 		GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed");
1745 
1746 		if (val != binding)
1747 			queryTestPassed = false;
1748 
1749 		// Draw twice to render both colors within the UBO
1750 		for (int drawCycle = 0; drawCycle < 2; ++drawCycle)
1751 		{
1752 			// Set the uniform indicating the array index to be used and set the expected color
1753 			const int arrayNdx = iterNdx*2 + drawCycle;
1754 			gl.uniform1i(m_shaderProgramArrayNdxLoc, arrayNdx);
1755 
1756 			if (!drawAndVerifyResult(m_expectedColors[arrayNdx]))
1757 				imageTestPassed = false;
1758 		}
1759 	}
1760 
1761 	setTestResult(queryTestPassed, imageTestPassed);
1762 	return STOP;
1763 }
1764 
generateShaders(void) const1765 glu::ShaderProgram* UBOBindingRenderCase::generateShaders (void) const
1766 {
1767 	std::ostringstream		shaderUniformDecl;
1768 	std::ostringstream		shaderBody;
1769 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1770 	const int				numDeclarations = (arrayInstance ? 1 : m_numBindings);
1771 
1772 	// Generate the uniform declarations for the vertex and fragment shaders
1773 	for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1774 	{
1775 		shaderUniformDecl << "layout(std140, binding = " << m_bindings[declNdx] << ") uniform "
1776 			<< getUniformName(m_uniformName, declNdx) << "\n"
1777 			<< "{\n"
1778 			<< "	highp vec4 color1;\n"
1779 			<< "	highp vec4 color2;\n"
1780 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
1781 	}
1782 
1783 	// Generate the shader body for the vertex and fragment shaders
1784 	for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx)	// Multiply by two to cover cases for both colors for each UBO
1785 	{
1786 		const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2));
1787 		shaderBody	<< "	" << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n"
1788 					<< "	{\n"
1789 					<< "		color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n"
1790 					<< "	}\n";
1791 	}
1792 
1793 	shaderBody	<< "	else\n"
1794 				<< "	{\n"
1795 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1796 				<< "	}\n";
1797 
1798 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
1799 					<< glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))
1800 					<< glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())));
1801 }
1802 
1803 
1804 class UBOBindingNegativeCase : public LayoutBindingNegativeCase
1805 {
1806 public:
1807 											UBOBindingNegativeCase			(Context&		context,
1808 																			 const char*	name,
1809 																			 const char*	desc,
1810 																			 ShaderType		shaderType,
1811 																			 TestType		testType,
1812 																			 ErrorType		errorType);
1813 											~UBOBindingNegativeCase			(void);
1814 
1815 private:
1816 	glu::ShaderProgram*						generateShaders					(void) const;
1817 };
1818 
UBOBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType)1819 UBOBindingNegativeCase::UBOBindingNegativeCase (Context&		context,
1820 												const char*		name,
1821 												const char*		desc,
1822 												ShaderType		shaderType,
1823 												TestType		testType,
1824 												ErrorType		errorType)
1825 	: LayoutBindingNegativeCase(context,
1826 								name,
1827 								desc,
1828 								shaderType,
1829 								testType,
1830 								errorType,
1831 								GL_MAX_UNIFORM_BUFFER_BINDINGS,
1832 								GL_MAX_VERTEX_UNIFORM_BLOCKS,
1833 								GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,
1834 								GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,
1835 								GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
1836 								GL_MAX_COMBINED_UNIFORM_BLOCKS,
1837 								"ColorBlock")
1838 {
1839 }
1840 
~UBOBindingNegativeCase(void)1841 UBOBindingNegativeCase::~UBOBindingNegativeCase (void)
1842 {
1843 	deinit();
1844 }
1845 
generateShaders(void) const1846 glu::ShaderProgram* UBOBindingNegativeCase::generateShaders (void) const
1847 {
1848 	std::ostringstream		vertexUniformDecl;
1849 	std::ostringstream		fragmentUniformDecl;
1850 	std::ostringstream		tessCtrlUniformDecl;
1851 	std::ostringstream		tessEvalUniformDecl;
1852 	std::ostringstream		shaderBody;
1853 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1854 	const int				numDeclarations = (arrayInstance ? 1 : m_numBindings);
1855 
1856 	// Generate the uniform declarations for the vertex and fragment shaders
1857 	for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1858 	{
1859 		vertexUniformDecl << "layout(std140, binding = " << m_vertexShaderBinding[declNdx] << ") uniform "
1860 			<< getUniformName(m_uniformName, declNdx) << "\n"
1861 			<< "{\n"
1862 			<< "	highp vec4 color1;\n"
1863 			<< "	highp vec4 color2;\n"
1864 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
1865 
1866 		fragmentUniformDecl << "layout(std140, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform "
1867 			<< getUniformName(m_uniformName, declNdx) << "\n"
1868 			<< "{\n"
1869 			<< "	highp vec4 color1;\n"
1870 			<< "	highp vec4 color2;\n"
1871 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
1872 
1873 		tessCtrlUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform "
1874 			<< getUniformName(m_uniformName, declNdx) << "\n"
1875 			<< "{\n"
1876 			<< "	highp vec4 color1;\n"
1877 			<< "	highp vec4 color2;\n"
1878 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
1879 
1880 		tessEvalUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform "
1881 			<< getUniformName(m_uniformName, declNdx) << "\n"
1882 			<< "{\n"
1883 			<< "	highp vec4 color1;\n"
1884 			<< "	highp vec4 color2;\n"
1885 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
1886 	}
1887 
1888 	// Generate the shader body for the vertex and fragment shaders
1889 	for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx)	// Multiply by two to cover cases for both colors for each UBO
1890 	{
1891 		const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2));
1892 		shaderBody	<< "	" << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n"
1893 					<< "	{\n"
1894 					<< "		color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n"
1895 					<< "	}\n";
1896 	}
1897 
1898 	shaderBody	<< "	else\n"
1899 				<< "	{\n"
1900 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1901 				<< "	}\n";
1902 
1903 	glu::ProgramSources sources = glu::ProgramSources()
1904 				<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
1905 				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
1906 
1907 	if (m_tessSupport)
1908 		sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
1909 				<< glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
1910 
1911 	return new glu::ShaderProgram(m_context.getRenderContext(), sources);
1912 }
1913 
1914 
1915 class SSBOBindingRenderCase : public LayoutBindingRenderCase
1916 {
1917 public:
1918 											SSBOBindingRenderCase		(Context&		context,
1919 																		 const char*	name,
1920 																		 const char*	desc,
1921 																		 ShaderType		shaderType,
1922 																		 TestType		testType);
1923 											~SSBOBindingRenderCase		(void);
1924 
1925 	void									init						(void);
1926 	void									deinit						(void);
1927 	IterateResult							iterate						(void);
1928 
1929 private:
1930 	glu::ShaderProgram*						generateShaders				(void) const;
1931 
1932 	std::vector<glw::GLuint>				m_buffers;
1933 	std::vector<Vec4>						m_expectedColors;
1934 };
1935 
SSBOBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType)1936 SSBOBindingRenderCase::SSBOBindingRenderCase (Context&		context,
1937 											  const char*	name,
1938 											  const char*	desc,
1939 											  ShaderType	shaderType,
1940 											  TestType		testType)
1941 	: LayoutBindingRenderCase (context, name, desc, shaderType, testType, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, "ColorBuffer")
1942 {
1943 }
1944 
~SSBOBindingRenderCase(void)1945 SSBOBindingRenderCase::~SSBOBindingRenderCase (void)
1946 {
1947 	deinit();
1948 }
1949 
init(void)1950 void SSBOBindingRenderCase::init (void)
1951 {
1952 	LayoutBindingRenderCase::init();
1953 
1954 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
1955 	de::Random				rnd		(deStringHash(getName()) ^ 0xff23a4);
1956 
1957 	// Initialize SSBOs and related data
1958 	m_buffers = std::vector<glw::GLuint>(m_numBindings, 0);
1959 	gl.genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]);
1960 
1961 	for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1962 	{
1963 		m_expectedColors.push_back(getRandomColor(rnd));
1964 		m_expectedColors.push_back(getRandomColor(rnd));
1965 	}
1966 
1967 	for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1968 	{
1969 		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffers[bufNdx]);
1970 		gl.bufferData(GL_SHADER_STORAGE_BUFFER, 2*sizeof(Vec4), &(m_expectedColors[2*bufNdx]), GL_STATIC_DRAW);
1971 		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, m_bindings[bufNdx], m_buffers[bufNdx]);
1972 	}
1973 
1974 	GLU_EXPECT_NO_ERROR(gl.getError(), "SSBO setup failed");
1975 }
1976 
deinit(void)1977 void SSBOBindingRenderCase::deinit (void)
1978 {
1979 	LayoutBindingRenderCase::deinit();
1980 
1981 	// Clean up SSBO data
1982 	for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1983 	{
1984 		if (m_buffers[bufNdx])
1985 		{
1986 			m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffers[bufNdx]);
1987 			m_context.getRenderContext().getFunctions().bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1988 			m_buffers[bufNdx] = 0;
1989 		}
1990 	}
1991 }
1992 
iterate(void)1993 TestCase::IterateResult SSBOBindingRenderCase::iterate (void)
1994 {
1995 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
1996 	const int				iterations		= m_numBindings;
1997 	const glw::GLenum		prop			= GL_BUFFER_BINDING;
1998 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1999 	bool					queryTestPassed	= true;
2000 	bool					imageTestPassed = true;
2001 
2002 	initRenderState();
2003 
2004 	for (int iterNdx = 0; iterNdx < iterations; ++iterNdx)
2005 	{
2006 		// Query binding point
2007 		const std::string	name	= (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx));
2008 		const glw::GLint	binding = m_bindings[iterNdx];
2009 		glw::GLint			val		= -1;
2010 
2011 		gl.getProgramResourceiv(m_program->getProgram(), GL_SHADER_STORAGE_BLOCK, gl.getProgramResourceIndex(m_program->getProgram(), GL_SHADER_STORAGE_BLOCK, name.c_str() ), 1, &prop, 1, DE_NULL, &val);
2012 		m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage;
2013 		GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed");
2014 
2015 		if (val != binding)
2016 			queryTestPassed = false;
2017 
2018 		// Draw twice to render both colors within the SSBO
2019 		for (int drawCycle = 0; drawCycle < 2; ++drawCycle)
2020 		{
2021 			// Set the uniform indicating the array index to be used and set the expected color
2022 			const int arrayNdx = iterNdx*2 + drawCycle;
2023 			gl.uniform1i(m_shaderProgramArrayNdxLoc, arrayNdx);
2024 
2025 			if (!drawAndVerifyResult(m_expectedColors[arrayNdx]))
2026 				imageTestPassed = false;
2027 		}
2028 	}
2029 
2030 	setTestResult(queryTestPassed, imageTestPassed);
2031 	return STOP;
2032 }
2033 
generateShaders(void) const2034 glu::ShaderProgram* SSBOBindingRenderCase::generateShaders (void) const
2035 {
2036 	std::ostringstream		shaderUniformDecl;
2037 	std::ostringstream		shaderBody;
2038 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
2039 	const int				numDeclarations = (arrayInstance ? 1 : m_numBindings);
2040 
2041 	// Generate the uniform declarations for the vertex and fragment shaders
2042 	for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
2043 	{
2044 		shaderUniformDecl << "layout(std140, binding = " << m_bindings[declNdx] << ") buffer "
2045 			<< getUniformName(m_uniformName, declNdx) << "\n"
2046 			<< "{\n"
2047 			<< "	highp vec4 color1;\n"
2048 			<< "	highp vec4 color2;\n"
2049 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
2050 	}
2051 
2052 	// Generate the shader body for the vertex and fragment shaders
2053 	for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx)	// Multiply by two to cover cases for both colors for each UBO
2054 	{
2055 		const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2));
2056 		shaderBody	<< "	" << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n"
2057 					<< "	{\n"
2058 					<< "		color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n"
2059 					<< "	}\n";
2060 	}
2061 
2062 	shaderBody	<< "	else\n"
2063 				<< "	{\n"
2064 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
2065 				<< "	}\n";
2066 
2067 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
2068 					<< glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))
2069 					<< glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())));
2070 }
2071 
2072 
2073 class SSBOBindingNegativeCase : public LayoutBindingNegativeCase
2074 {
2075 public:
2076 											SSBOBindingNegativeCase			(Context&		context,
2077 																			 const char*	name,
2078 																			 const char*	desc,
2079 																			 ShaderType		shaderType,
2080 																			 TestType		testType,
2081 																			 ErrorType		errorType);
2082 											~SSBOBindingNegativeCase		(void);
2083 
2084 private:
2085 	glu::ShaderProgram*						generateShaders					(void) const;
2086 };
2087 
SSBOBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType)2088 SSBOBindingNegativeCase::SSBOBindingNegativeCase (Context& context,
2089 												  const char* name,
2090 												  const char* desc,
2091 												  ShaderType shaderType,
2092 												  TestType testType,
2093 												  ErrorType errorType)
2094 	: LayoutBindingNegativeCase(context,
2095 								name,
2096 								desc,
2097 								shaderType,
2098 								testType,
2099 								errorType,
2100 								GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
2101 								GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,
2102 								GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS,
2103 								GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS,
2104 								GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS,
2105 								GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS,
2106 								"ColorBuffer")
2107 {
2108 }
2109 
~SSBOBindingNegativeCase(void)2110 SSBOBindingNegativeCase::~SSBOBindingNegativeCase (void)
2111 {
2112 	deinit();
2113 }
2114 
generateShaders(void) const2115 glu::ShaderProgram* SSBOBindingNegativeCase::generateShaders (void) const
2116 {
2117 	std::ostringstream		vertexUniformDecl;
2118 	std::ostringstream		fragmentUniformDecl;
2119 	std::ostringstream		tessCtrlUniformDecl;
2120 	std::ostringstream		tessEvalUniformDecl;
2121 	std::ostringstream		shaderBody;
2122 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
2123 	const int				numDeclarations = (arrayInstance ? 1 : m_numBindings);
2124 
2125 	// Generate the uniform declarations for the vertex and fragment shaders
2126 	for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
2127 	{
2128 		vertexUniformDecl << "layout(std140, binding = " << m_vertexShaderBinding[declNdx] << ") buffer "
2129 			<< getUniformName(m_uniformName, declNdx) << "\n"
2130 			<< "{\n"
2131 			<< "	highp vec4 color1;\n"
2132 			<< "	highp vec4 color2;\n"
2133 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
2134 
2135 		fragmentUniformDecl << "layout(std140, binding = " << m_fragmentShaderBinding[declNdx] << ") buffer "
2136 			<< getUniformName(m_uniformName, declNdx) << "\n"
2137 			<< "{\n"
2138 			<< "	highp vec4 color1;\n"
2139 			<< "	highp vec4 color2;\n"
2140 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
2141 
2142 		tessCtrlUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") buffer "
2143 			<< getUniformName(m_uniformName, declNdx) << "\n"
2144 			<< "{\n"
2145 			<< "	highp vec4 color1;\n"
2146 			<< "	highp vec4 color2;\n"
2147 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
2148 
2149 		tessEvalUniformDecl << "layout(std140, binding = " << m_tessEvalShaderBinding[declNdx] << ") buffer "
2150 			<< getUniformName(m_uniformName, declNdx) << "\n"
2151 			<< "{\n"
2152 			<< "	highp vec4 color1;\n"
2153 			<< "	highp vec4 color2;\n"
2154 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
2155 	}
2156 
2157 	// Generate the shader body for the vertex and fragment shaders
2158 	for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx)	// Multiply by two to cover cases for both colors for each UBO
2159 	{
2160 		const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2));
2161 		shaderBody	<< "	" << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n"
2162 					<< "	{\n"
2163 					<< "		color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n"
2164 					<< "	}\n";
2165 	}
2166 
2167 	shaderBody	<< "	else\n"
2168 				<< "	{\n"
2169 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
2170 				<< "	}\n";
2171 
2172 	glu::ProgramSources sources = glu::ProgramSources()
2173 				<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
2174 				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
2175 
2176 	if (m_tessSupport)
2177 		sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
2178 				<< glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
2179 
2180 	return new glu::ShaderProgram(m_context.getRenderContext(), sources);
2181 }
2182 
2183 
2184 } // Anonymous
2185 
LayoutBindingTests(Context & context)2186 LayoutBindingTests::LayoutBindingTests (Context& context)
2187 	: TestCaseGroup (context, "layout_binding", "Layout binding tests")
2188 {
2189 }
2190 
~LayoutBindingTests(void)2191 LayoutBindingTests::~LayoutBindingTests (void)
2192 {
2193 }
2194 
init(void)2195 void LayoutBindingTests::init (void)
2196 {
2197 	// Render test groups
2198 	tcu::TestCaseGroup* const samplerBindingTestGroup			= new tcu::TestCaseGroup(m_testCtx, "sampler",		"Test sampler layout binding");
2199 	tcu::TestCaseGroup* const sampler2dBindingTestGroup			= new tcu::TestCaseGroup(m_testCtx, "sampler2d",	"Test sampler2d layout binding");
2200 	tcu::TestCaseGroup* const sampler3dBindingTestGroup			= new tcu::TestCaseGroup(m_testCtx, "sampler3d",	"Test sampler3d layout binding");
2201 
2202 	tcu::TestCaseGroup* const imageBindingTestGroup				= new tcu::TestCaseGroup(m_testCtx, "image",		"Test image layout binding");
2203 	tcu::TestCaseGroup* const image2dBindingTestGroup			= new tcu::TestCaseGroup(m_testCtx, "image2d",		"Test image2d layout binding");
2204 	tcu::TestCaseGroup* const image3dBindingTestGroup			= new tcu::TestCaseGroup(m_testCtx, "image3d",		"Test image3d layout binding");
2205 
2206 	tcu::TestCaseGroup* const UBOBindingTestGroup				= new tcu::TestCaseGroup(m_testCtx, "ubo",			"Test UBO layout binding");
2207 	tcu::TestCaseGroup* const SSBOBindingTestGroup				= new tcu::TestCaseGroup(m_testCtx, "ssbo",			"Test SSBO layout binding");
2208 
2209 	// Negative test groups
2210 	tcu::TestCaseGroup* const negativeBindingTestGroup			= new tcu::TestCaseGroup(m_testCtx, "negative",		"Test layout binding with invalid bindings");
2211 
2212 	tcu::TestCaseGroup* const negativeSamplerBindingTestGroup	= new tcu::TestCaseGroup(m_testCtx, "sampler",		"Test sampler layout binding with invalid bindings");
2213 	tcu::TestCaseGroup* const negativeSampler2dBindingTestGroup	= new tcu::TestCaseGroup(m_testCtx, "sampler2d",	"Test sampler2d layout binding with invalid bindings");
2214 	tcu::TestCaseGroup* const negativeSampler3dBindingTestGroup	= new tcu::TestCaseGroup(m_testCtx, "sampler3d",	"Test sampler3d layout binding with invalid bindings");
2215 
2216 	tcu::TestCaseGroup* const negativeImageBindingTestGroup		= new tcu::TestCaseGroup(m_testCtx, "image",		"Test image layout binding with invalid bindings");
2217 	tcu::TestCaseGroup* const negativeImage2dBindingTestGroup	= new tcu::TestCaseGroup(m_testCtx, "image2d",		"Test image2d layout binding with invalid bindings");
2218 	tcu::TestCaseGroup* const negativeImage3dBindingTestGroup	= new tcu::TestCaseGroup(m_testCtx, "image3d",		"Test image3d layout binding with invalid bindings");
2219 
2220 	tcu::TestCaseGroup* const negativeUBOBindingTestGroup		= new tcu::TestCaseGroup(m_testCtx, "ubo",			"Test UBO layout binding with invalid bindings");
2221 	tcu::TestCaseGroup* const negativeSSBOBindingTestGroup		= new tcu::TestCaseGroup(m_testCtx, "ssbo",			"Test SSBO layout binding with invalid bindings");
2222 
2223 	static const struct RenderTestType
2224 	{
2225 		ShaderType				shaderType;
2226 		TestType				testType;
2227 		std::string				name;
2228 		std::string				descPostfix;
2229 	} s_renderTestTypes[] =
2230 	{
2231 		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_SINGLE,		"vertex_binding_single",		"a single instance" },
2232 		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_MAX,			"vertex_binding_max",			"maximum binding point"	},
2233 		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_MULTIPLE,		"vertex_binding_multiple",		"multiple instances"},
2234 		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_ARRAY,			"vertex_binding_array",			"an array instance" },
2235 		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_MAX_ARRAY,		"vertex_binding_max_array",		"an array instance with maximum binding point" },
2236 
2237 		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_SINGLE,		"fragment_binding_single",		"a single instance" },
2238 		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_MAX,			"fragment_binding_max",			"maximum binding point"	},
2239 		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_MULTIPLE,		"fragment_binding_multiple",	"multiple instances"},
2240 		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_ARRAY,			"fragment_binding_array",		"an array instance" },
2241 		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_MAX_ARRAY,		"fragment_binding_max_array",	"an array instance with maximum binding point" },
2242 	};
2243 
2244 	static const struct NegativeTestType
2245 	{
2246 		ShaderType								shaderType;
2247 		TestType								testType;
2248 		LayoutBindingNegativeCase::ErrorType	errorType;
2249 		std::string								name;
2250 		std::string								descPostfix;
2251 	} s_negativeTestTypes[] =
2252 	{
2253 		{ SHADERTYPE_VERTEX,			TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"vertex_binding_over_max",					"over maximum binding point"   },
2254 		{ SHADERTYPE_FRAGMENT,			TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"fragment_binding_over_max",				"over maximum binding point"   },
2255 		{ SHADERTYPE_TESS_CONTROL,		TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"tess_control_binding_over_max",			"over maximum binding point"   },
2256 		{ SHADERTYPE_TESS_EVALUATION,	TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"tess_evaluation_binding_over_max",			"over maximum binding point"   },
2257 		{ SHADERTYPE_VERTEX,			TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"vertex_binding_neg",						"negative binding point"	   },
2258 		{ SHADERTYPE_FRAGMENT,			TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"fragment_binding_neg",						"negative binding point"	   },
2259 		{ SHADERTYPE_TESS_CONTROL,		TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"tess_control_binding_neg",					"negative binding point"	   },
2260 		{ SHADERTYPE_TESS_EVALUATION,	TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"tess_evaluation_binding_neg",				"negative binding point"	   },
2261 
2262 		{ SHADERTYPE_VERTEX,			TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"vertex_binding_over_max_array",			"over maximum binding point"   },
2263 		{ SHADERTYPE_FRAGMENT,			TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"fragment_binding_over_max_array",			"over maximum binding point"   },
2264 		{ SHADERTYPE_TESS_CONTROL,		TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"tess_control_binding_over_max_array",		"over maximum binding point"   },
2265 		{ SHADERTYPE_TESS_EVALUATION,	TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"tess_evaluation_binding_over_max_array",	"over maximum binding point"   },
2266 		{ SHADERTYPE_VERTEX,			TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"vertex_binding_neg_array",					"negative binding point"	   },
2267 		{ SHADERTYPE_FRAGMENT,			TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"fragment_binding_neg_array",				"negative binding point"	   },
2268 		{ SHADERTYPE_TESS_CONTROL,		TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"tess_control_binding_neg_array",			"negative binding point"	   },
2269 		{ SHADERTYPE_TESS_EVALUATION,	TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"tess_evaluation_binding_neg_array",		"negative binding point"	   },
2270 
2271 		{ SHADERTYPE_ALL,				TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY,		"binding_contradictory",					"contradictory binding points" },
2272 		{ SHADERTYPE_ALL,				TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY,		"binding_contradictory_array",				"contradictory binding points" },
2273 	};
2274 
2275 	// Render tests
2276 	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_renderTestTypes); ++testNdx)
2277 	{
2278 		const RenderTestType& test = s_renderTestTypes[testNdx];
2279 
2280 		// Render sampler binding tests
2281 		sampler2dBindingTestGroup->addChild(new SamplerBindingRenderCase(m_context, test.name.c_str(), ("Sampler2D layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType, GL_SAMPLER_2D, GL_TEXTURE_2D));
2282 		sampler3dBindingTestGroup->addChild(new SamplerBindingRenderCase(m_context, test.name.c_str(), ("Sampler3D layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType, GL_SAMPLER_3D, GL_TEXTURE_3D));
2283 
2284 		// Render image binding tests
2285 		image2dBindingTestGroup->addChild(new ImageBindingRenderCase(m_context, test.name.c_str(), ("Image2D layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType, GL_IMAGE_2D, GL_TEXTURE_2D));
2286 		image3dBindingTestGroup->addChild(new ImageBindingRenderCase(m_context, test.name.c_str(), ("Image3D layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType, GL_IMAGE_3D, GL_TEXTURE_3D));
2287 
2288 		// Render UBO binding tests
2289 		UBOBindingTestGroup->addChild(new UBOBindingRenderCase(m_context, test.name.c_str(), ("UBO layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType));
2290 
2291 		// Render SSBO binding tests
2292 		SSBOBindingTestGroup->addChild(new SSBOBindingRenderCase(m_context, test.name.c_str(), ("SSBO layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType));
2293 	}
2294 
2295 	// Negative binding tests
2296 	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_negativeTestTypes); ++testNdx)
2297 	{
2298 		const NegativeTestType& test = s_negativeTestTypes[testNdx];
2299 
2300 		// Negative sampler binding tests
2301 		negativeSampler2dBindingTestGroup->addChild(new SamplerBindingNegativeCase(m_context, test.name.c_str(), ("Invalid sampler2d layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType, GL_SAMPLER_2D));
2302 		negativeSampler3dBindingTestGroup->addChild(new SamplerBindingNegativeCase(m_context, test.name.c_str(), ("Invalid sampler3d layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType, GL_SAMPLER_3D));
2303 
2304 		// Negative image binding tests
2305 		negativeImage2dBindingTestGroup->addChild(new ImageBindingNegativeCase(m_context, test.name.c_str(), ("Invalid image2d layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType, GL_IMAGE_2D));
2306 		negativeImage3dBindingTestGroup->addChild(new ImageBindingNegativeCase(m_context, test.name.c_str(), ("Invalid image3d layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType, GL_IMAGE_3D));
2307 
2308 		// Negative UBO binding tests
2309 		negativeUBOBindingTestGroup->addChild(new UBOBindingNegativeCase(m_context, test.name.c_str(), ("Invalid UBO layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType));
2310 
2311 		// Negative SSBO binding tests
2312 		negativeSSBOBindingTestGroup->addChild(new SSBOBindingNegativeCase(m_context, test.name.c_str(), ("Invalid SSBO layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType));
2313 	}
2314 
2315 	samplerBindingTestGroup->addChild(sampler2dBindingTestGroup);
2316 	samplerBindingTestGroup->addChild(sampler3dBindingTestGroup);
2317 
2318 	imageBindingTestGroup->addChild(image2dBindingTestGroup);
2319 	imageBindingTestGroup->addChild(image3dBindingTestGroup);
2320 
2321 	negativeSamplerBindingTestGroup->addChild(negativeSampler2dBindingTestGroup);
2322 	negativeSamplerBindingTestGroup->addChild(negativeSampler3dBindingTestGroup);
2323 
2324 	negativeImageBindingTestGroup->addChild(negativeImage2dBindingTestGroup);
2325 	negativeImageBindingTestGroup->addChild(negativeImage3dBindingTestGroup);
2326 
2327 	negativeBindingTestGroup->addChild(negativeSamplerBindingTestGroup);
2328 	negativeBindingTestGroup->addChild(negativeUBOBindingTestGroup);
2329 	negativeBindingTestGroup->addChild(negativeSSBOBindingTestGroup);
2330 	negativeBindingTestGroup->addChild(negativeImageBindingTestGroup);
2331 
2332 	addChild(samplerBindingTestGroup);
2333 	addChild(UBOBindingTestGroup);
2334 	addChild(SSBOBindingTestGroup);
2335 	addChild(imageBindingTestGroup);
2336 	addChild(negativeBindingTestGroup);
2337 }
2338 
2339 } // Functional
2340 } // gles31
2341 } // deqp
2342