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