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