1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22 */ /*-------------------------------------------------------------------*/
23
24#include "es31cProgramInterfaceQueryTests.hpp"
25#include "glwEnums.hpp"
26#include "glwFunctions.hpp"
27#include <cstdarg>
28#include <map>
29#include <set>
30
31namespace glcts
32{
33
34using namespace glw;
35
36namespace
37{
38
39class PIQBase : public glcts::SubcaseBase
40{
41
42public:
43	virtual ~PIQBase()
44	{
45	}
46
47	virtual std::string PassCriteria()
48	{
49		return "All called functions return expected values.";
50	}
51
52	virtual std::string Purpose()
53	{
54		return "Verify that the set of tested functions glGetProgram* return\n"
55			   "expected results when used to get data from program\n"
56			   "made of " +
57			   ShadersDesc() + "." + PurposeExt();
58	}
59
60	virtual std::string Method()
61	{
62		return "Create a program using " + ShadersDesc() +
63			   "\n"
64			   "then use set of tested functions to get an information about it and\n"
65			   "verify that information with the expected data" +
66			   Expectations();
67	}
68
69	virtual long Cleanup()
70	{
71		glUseProgram(0);
72		return NO_ERROR;
73	}
74
75	virtual long Setup()
76	{
77		return NO_ERROR;
78	}
79
80protected:
81	void LinkProgram(GLuint program)
82	{
83		glLinkProgram(program);
84		GLsizei length;
85		GLchar  log[1024];
86		glGetProgramInfoLog(program, sizeof(log), &length, log);
87		if (length > 1)
88		{
89			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
90												<< log << tcu::TestLog::EndMessage;
91		}
92	}
93
94	GLuint CreateProgram(const char* src_vs, const char* src_fs, bool link)
95	{
96		const GLuint p = glCreateProgram();
97
98		if (src_vs)
99		{
100			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
101			glAttachShader(p, sh);
102			glDeleteShader(sh);
103			glShaderSource(sh, 1, &src_vs, NULL);
104			glCompileShader(sh);
105		}
106		if (src_fs)
107		{
108			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
109			glAttachShader(p, sh);
110			glDeleteShader(sh);
111			glShaderSource(sh, 1, &src_fs, NULL);
112			glCompileShader(sh);
113		}
114		if (link)
115		{
116			LinkProgram(p);
117		}
118		return p;
119	}
120
121	virtual std::string ShadersDesc()
122	{
123		return "";
124	}
125
126	virtual std::string Expectations()
127	{
128		return ".";
129	}
130
131	virtual std::string PurposeExt()
132	{
133		return "";
134	}
135
136	virtual inline void ExpectError(GLenum expected, long& error)
137	{
138		if (error != NO_ERROR)
139			return;
140		GLenum tmp = glGetError();
141		if (tmp == expected)
142		{
143			m_context.getTestContext().getLog()
144				<< tcu::TestLog::Message << "Found expected error" << tcu::TestLog::EndMessage;
145			error = NO_ERROR; // Error is expected
146		}
147		else
148		{
149			error = ERROR;
150			m_context.getTestContext().getLog() << tcu::TestLog::Message << expected
151												<< " error was expected, found: " << tmp << tcu::TestLog::EndMessage;
152		}
153	}
154
155	virtual inline void VerifyGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, int expected,
156													long& error)
157	{
158		GLint res;
159		glGetProgramInterfaceiv(program, programInterface, pname, &res);
160		if (res != expected)
161		{
162			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
163												<< expected << tcu::TestLog::EndMessage;
164			error = ERROR;
165		}
166	}
167
168	virtual inline void VerifyGetProgramResourceIndex(GLuint program, GLenum programInterface, const std::string& name,
169													  GLuint expected, long& error)
170	{
171		GLuint res = glGetProgramResourceIndex(program, programInterface, name.c_str());
172		if (res != expected)
173		{
174			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
175												<< expected << tcu::TestLog::EndMessage;
176			error = ERROR;
177		}
178	}
179
180	virtual inline void VerifyGetProgramResourceIndex(GLuint program, GLenum		 programInterface,
181													  std::map<std::string, GLuint>& indices, const std::string& name,
182													  long& error)
183	{
184		GLuint res = glGetProgramResourceIndex(program, programInterface, name.c_str());
185		if (res == GL_INVALID_INDEX)
186		{
187			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res
188												<< ", expected number other than -1" << tcu::TestLog::EndMessage;
189			error = ERROR;
190			return;
191		}
192		std::map<std::string, GLuint>::iterator it = indices.begin();
193		while (it != indices.end())
194		{
195			if (it->second == res)
196			{
197				m_context.getTestContext().getLog()
198					<< tcu::TestLog::Message << "ERROR: Duplicated value found: " << res << tcu::TestLog::EndMessage;
199				error = ERROR;
200				return;
201			}
202			++it;
203		}
204		indices[name] = res;
205	}
206
207	virtual inline void VerifyGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index,
208													 const std::string& expected, long& error)
209	{
210		GLchar  name[1024] = { '\0' };
211		GLsizei len;
212		glGetProgramResourceName(program, programInterface, index, 1024, &len, name);
213		if (len <= 0 || len > 1023 || name[len - 1] == '\0')
214		{
215			m_context.getTestContext().getLog()
216				<< tcu::TestLog::Message
217				<< "ERROR: Length in glGetProgramResourceName should not count null terminator!"
218				<< tcu::TestLog::EndMessage;
219			error = ERROR;
220		}
221		else if (name != expected || name[len] != '\0')
222		{
223			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << name << ", expected "
224												<< expected << tcu::TestLog::EndMessage;
225			error = ERROR;
226		}
227	}
228
229	virtual inline void VerifyGetProgramResourceLocation(GLuint program, GLenum programInterface,
230														 const std::string& name, GLint expected, long& error)
231	{
232		GLint res = glGetProgramResourceLocation(program, programInterface, name.c_str());
233		if (res != expected)
234		{
235			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
236												<< expected << tcu::TestLog::EndMessage;
237			error = ERROR;
238		}
239	}
240
241	virtual inline void VerifyGetProgramResourceLocation(GLuint program, GLenum		   programInterface,
242														 std::map<std::string, GLint>& locations,
243														 const std::string& name, long& error)
244	{
245		GLint res = glGetProgramResourceLocation(program, programInterface, name.c_str());
246		if (res < 0)
247		{
248			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res
249												<< ", expected not less than 0" << tcu::TestLog::EndMessage;
250			error = ERROR;
251			return;
252		}
253		std::map<std::string, GLint>::iterator it = locations.begin();
254		while (it != locations.end())
255		{
256			if (it->second == res)
257			{
258				m_context.getTestContext().getLog()
259					<< tcu::TestLog::Message << "ERROR: Duplicated value found: " << res << tcu::TestLog::EndMessage;
260				error = ERROR;
261				return;
262			}
263			++it;
264		}
265		locations[name] = res;
266	}
267
268	virtual inline void VerifyGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index,
269												   GLsizei propCount, const GLenum props[], GLsizei expectedLength,
270												   const GLint expected[], long& error)
271	{
272		const GLsizei bufSize = 1000;
273		GLsizei		  length;
274		GLint		  params[bufSize];
275		glGetProgramResourceiv(program, programInterface, index, propCount, props, bufSize, &length, params);
276		if (length != expectedLength || length <= 0)
277		{
278			error = ERROR;
279			m_context.getTestContext().getLog()
280				<< tcu::TestLog::Message << "ERROR: Got length " << length << ", expected " << expectedLength
281				<< "\nCALL: glGetProgramResourceiv, with " << programInterface << ", " << index
282				<< tcu::TestLog::EndMessage;
283			return;
284		}
285		for (int i = 0; i < length; ++i)
286		{
287			if (params[i] != expected[i])
288			{
289				error = ERROR;
290				m_context.getTestContext().getLog()
291					<< tcu::TestLog::Message << "ERROR: Got " << params[i] << ", expected " << expected[i]
292					<< " at: " << i << "\nCALL: glGetProgramResourceiv, with " << programInterface << ", " << index
293					<< tcu::TestLog::EndMessage;
294			}
295		}
296	}
297
298	virtual inline GLint GetProgramivRetValue(GLuint program, GLenum pname)
299	{
300		GLint ret;
301		glGetProgramiv(program, pname, &ret);
302		return ret;
303	}
304
305	static const GLenum interfaces[];
306};
307
308const GLenum PIQBase::interfaces[] = { GL_PROGRAM_INPUT,
309									   GL_PROGRAM_OUTPUT,
310									   GL_UNIFORM,
311									   GL_UNIFORM_BLOCK,
312									   GL_BUFFER_VARIABLE,
313									   GL_SHADER_STORAGE_BLOCK,
314									   GL_ATOMIC_COUNTER_BUFFER,
315									   GL_TRANSFORM_FEEDBACK_VARYING };
316
317class NoShaders : public PIQBase
318{
319
320	virtual std::string Title()
321	{
322		return "No Shaders Test";
323	}
324
325	virtual std::string ShadersDesc()
326	{
327		return "no shaders";
328	}
329
330	virtual long Run()
331	{
332		const GLuint program = glCreateProgram();
333
334		long error = NO_ERROR;
335		int  size  = sizeof(PIQBase::interfaces) / sizeof(PIQBase::interfaces[0]);
336
337		for (int i = 0; i < size; ++i)
338		{
339			VerifyGetProgramInterfaceiv(program, PIQBase::interfaces[i], GL_ACTIVE_RESOURCES, 0, error);
340			if (PIQBase::interfaces[i] == GL_ATOMIC_COUNTER_BUFFER)
341				continue;
342			VerifyGetProgramInterfaceiv(program, PIQBase::interfaces[i], GL_MAX_NAME_LENGTH, 0, error);
343		}
344		VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
345		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
346		VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
347
348		for (int i = 0; i < size; ++i)
349		{
350			if (PIQBase::interfaces[i] == GL_ATOMIC_COUNTER_BUFFER)
351				continue;
352			VerifyGetProgramResourceIndex(program, PIQBase::interfaces[i], "", GL_INVALID_INDEX, error);
353		}
354
355		// can't test GetProgramResourceLocation* here since program has to be linked
356		// can't test GetProgramResourceiv, need valid index
357
358		glDeleteProgram(program);
359		return error;
360	}
361};
362
363class SimpleShaders : public PIQBase
364{
365
366public:
367	virtual std::string Title()
368	{
369		return "Simple Shaders Test";
370	}
371
372	virtual std::string ShadersDesc()
373	{
374		return "fallthrough fragment and vertex shaders";
375	}
376
377	virtual std::string VertexShader()
378	{
379		return "#version 310 es                      \n"
380			   "in vec4 position;                    \n"
381			   "void main(void)                      \n"
382			   "{                                    \n"
383			   "    gl_Position = position;          \n"
384			   "}";
385	}
386
387	virtual std::string FragmentShader()
388	{
389		return "#version 310 es                \n"
390			   "out mediump vec4 color;        \n"
391			   "void main() {                  \n"
392			   "    color = vec4(0, 1, 0, 1);  \n"
393			   "}";
394	}
395
396	virtual long Run()
397	{
398		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
399		glBindAttribLocation(program, 0, "position");
400		glLinkProgram(program);
401
402		long error = NO_ERROR;
403
404		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
405		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 9, error);
406		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 1, error);
407		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 6, error);
408
409		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "color", 0, error);
410		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position", 0, error);
411
412		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, 0, "color", error);
413		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, 0, "position", error);
414
415		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", 0, error);
416		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
417
418		GLenum props[] = { GL_NAME_LENGTH,
419						   GL_TYPE,
420						   GL_ARRAY_SIZE,
421						   GL_REFERENCED_BY_COMPUTE_SHADER,
422						   GL_REFERENCED_BY_FRAGMENT_SHADER,
423						   GL_REFERENCED_BY_VERTEX_SHADER,
424						   GL_LOCATION };
425		GLint expected[] = { 9, 35666, 1, 0, 0, 1, 0 };
426		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 7, props, 7, expected, error);
427
428		GLenum props2[] = { GL_NAME_LENGTH,
429							GL_TYPE,
430							GL_ARRAY_SIZE,
431							GL_REFERENCED_BY_COMPUTE_SHADER,
432							GL_REFERENCED_BY_FRAGMENT_SHADER,
433							GL_REFERENCED_BY_VERTEX_SHADER,
434							GL_LOCATION };
435		GLint expected2[] = { 6, 35666, 1, 0, 1, 0, 0 };
436		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 7, props2, 7, expected2, error);
437
438		glDeleteProgram(program);
439		return error;
440	}
441};
442
443class ComputeShaderTest : public PIQBase
444{
445public:
446	virtual std::string Title()
447	{
448		return "Compute Shader Test";
449	}
450
451	virtual std::string ShadersDesc()
452	{
453		return "compute shader";
454	}
455
456	virtual std::string ComputeShader()
457	{
458		return "layout(local_size_x = 1, local_size_y = 1) in; \n"
459			   "layout(std430) buffer Output {                 \n"
460			   "  mediump vec4 data[];                         \n"
461			   "} g_out;                                       \n"
462			   ""
463			   "void main() {                                   \n"
464			   "   g_out.data[0] = vec4(1.0, 2.0, 3.0, 4.0);    \n"
465			   "   g_out.data[100] = vec4(1.0, 2.0, 3.0, 4.0);  \n"
466			   "}";
467	}
468
469	GLuint CreateComputeProgram(const std::string& cs)
470	{
471		const GLuint p = glCreateProgram();
472
473		const char* const kGLSLVer = "#version 310 es\n";
474
475		if (!cs.empty())
476		{
477			const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
478			glAttachShader(p, sh);
479			glDeleteShader(sh);
480			const char* const src[2] = { kGLSLVer, cs.c_str() };
481			glShaderSource(sh, 2, src, NULL);
482			glCompileShader(sh);
483		}
484
485		return p;
486	}
487
488	bool CheckProgram(GLuint program, bool* compile_error = NULL)
489	{
490		GLint compile_status = GL_TRUE;
491		GLint status;
492		glGetProgramiv(program, GL_LINK_STATUS, &status);
493
494		if (status == GL_FALSE)
495		{
496			GLint attached_shaders;
497			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
498
499			if (attached_shaders > 0)
500			{
501				std::vector<GLuint> shaders(attached_shaders);
502				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
503
504				for (GLint i = 0; i < attached_shaders; ++i)
505				{
506					GLenum type;
507					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
508					switch (type)
509					{
510					case GL_VERTEX_SHADER:
511						m_context.getTestContext().getLog()
512							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
513						break;
514					case GL_TESS_CONTROL_SHADER:
515						m_context.getTestContext().getLog()
516							<< tcu::TestLog::Message << "*** Tessellation Control Shader ***"
517							<< tcu::TestLog::EndMessage;
518						break;
519					case GL_TESS_EVALUATION_SHADER:
520						m_context.getTestContext().getLog()
521							<< tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
522							<< tcu::TestLog::EndMessage;
523						break;
524					case GL_GEOMETRY_SHADER:
525						m_context.getTestContext().getLog()
526							<< tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
527						break;
528					case GL_FRAGMENT_SHADER:
529						m_context.getTestContext().getLog()
530							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
531						break;
532					case GL_COMPUTE_SHADER:
533						m_context.getTestContext().getLog()
534							<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
535						break;
536					default:
537						m_context.getTestContext().getLog()
538							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
539					}
540
541					GLint res;
542					glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &res);
543					if (res != GL_TRUE)
544						compile_status = res;
545
546					// shader source
547					GLint length;
548					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
549					if (length > 0)
550					{
551						std::vector<GLchar> source(length);
552						glGetShaderSource(shaders[i], length, NULL, &source[0]);
553						m_context.getTestContext().getLog()
554							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
555					}
556
557					// shader info log
558					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
559					if (length > 0)
560					{
561						std::vector<GLchar> log(length);
562						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
563						m_context.getTestContext().getLog()
564							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
565					}
566				}
567			}
568
569			// program info log
570			GLint length;
571			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
572			if (length > 0)
573			{
574				std::vector<GLchar> log(length);
575				glGetProgramInfoLog(program, length, NULL, &log[0]);
576				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
577			}
578		}
579
580		if (compile_error)
581			*compile_error = (compile_status == GL_TRUE ? false : true);
582		if (compile_status != GL_TRUE)
583			return false;
584		return status == GL_TRUE ? true : false;
585	}
586
587	virtual void inline VerifyCompute(GLuint program, long& error)
588	{
589		VerifyGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_MAX_NAME_LENGTH, 15, error);
590		VerifyGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_ACTIVE_RESOURCES, 1, error);
591		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, 1, error);
592		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, 7, error);
593		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 1, error);
594
595		std::map<std::string, GLuint> indicesSSB;
596		std::map<std::string, GLuint> indicesBV;
597		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "Output", error);
598		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "Output.data", error);
599
600		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["Output"], "Output", error);
601		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["Outputa.data"], "Output.data[0]", error);
602
603		GLenum props3[] = { GL_NAME_LENGTH,
604							GL_BUFFER_BINDING,
605							GL_NUM_ACTIVE_VARIABLES,
606							GL_REFERENCED_BY_COMPUTE_SHADER,
607							GL_REFERENCED_BY_FRAGMENT_SHADER,
608							GL_REFERENCED_BY_VERTEX_SHADER,
609							GL_ACTIVE_VARIABLES };
610		GLint expected3[] = { 7, 0, 1, 1, 0, 0, static_cast<GLint>(indicesBV["Outputa.data"]) };
611		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["Output"], 7, props3, 7, expected3,
612								   error);
613
614		GLenum props4[] = { GL_NAME_LENGTH,
615							GL_TYPE,
616							GL_ARRAY_SIZE,
617							GL_BLOCK_INDEX,
618							GL_IS_ROW_MAJOR,
619							GL_REFERENCED_BY_COMPUTE_SHADER,
620							GL_REFERENCED_BY_FRAGMENT_SHADER,
621							GL_REFERENCED_BY_VERTEX_SHADER,
622							GL_TOP_LEVEL_ARRAY_SIZE };
623		GLint expected4[] = { 15, 35666, 0, static_cast<GLint>(indicesSSB["Output"]), 0, 1, 0, 0, 1 };
624		VerifyGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["Outputa.data"], 9, props4, 9, expected4,
625								   error);
626	}
627
628	virtual long Run()
629	{
630		GLuint program = CreateComputeProgram(ComputeShader());
631		glLinkProgram(program);
632		if (!CheckProgram(program))
633		{
634			glDeleteProgram(program);
635			return ERROR;
636		}
637		glUseProgram(program);
638
639		long error = NO_ERROR;
640
641		VerifyCompute(program, error);
642
643		glDeleteProgram(program);
644		return error;
645	}
646};
647
648class InputTypes : public SimpleShaders
649{
650	virtual std::string Title()
651	{
652		return "Input Types Test";
653	}
654
655	virtual std::string ShadersDesc()
656	{
657		return "vertex shader with different `in` types and a fallthrough fragment shader";
658	}
659
660	virtual std::string VertexShader()
661	{
662		return "#version 310 es                      \n"
663			   "in mat4 a;                           \n"
664			   "in vec4 b;                           \n"
665			   "in float c;                          \n"
666			   "in mat2x3 d;                         \n"
667			   "in vec2 e;                           \n"
668			   "in uint f;                           \n"
669			   "in vec3 g;                           \n"
670			   "in int h;                            \n"
671			   "void main(void)                      \n"
672			   "{                                    \n"
673			   "   vec4 pos;                                                 \n"
674			   "   pos.w = float(h) + g.x + g.y + d[1].y;                    \n"
675			   "   pos.y = float(b.x) * c + c + d[0][0];                     \n"
676			   "   pos.x = a[0].x + a[1].y + a[2].z + a[3].w;                \n"
677			   "   pos.z = d[0][1] + float(e.x) * float(f) + d[1][0];        \n"
678			   "   gl_Position = pos;                                        \n"
679			   "}";
680	}
681
682	virtual long Run()
683	{
684		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
685		glBindAttribLocation(program, 0, "a");
686		glBindAttribLocation(program, 4, "b");
687		glBindAttribLocation(program, 5, "c");
688		glBindAttribLocation(program, 7, "d");
689		glBindAttribLocation(program, 11, "e");
690		glBindAttribLocation(program, 12, "f");
691		glBindAttribLocation(program, 13, "g");
692		glBindAttribLocation(program, 15, "h");
693		LinkProgram(program);
694
695		long error = NO_ERROR;
696
697		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 8, error);
698		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 2, error);
699
700		std::map<std::string, GLuint> indices;
701		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "a", error);
702		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "b", error);
703		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "c", error);
704		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "d", error);
705		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "e", error);
706		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "f", error);
707		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "g", error);
708		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "h", error);
709
710		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["a"], "a", error);
711		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["b"], "b", error);
712		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["c"], "c", error);
713		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["d"], "d", error);
714		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["e"], "e", error);
715		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["f"], "f", error);
716		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["g"], "g", error);
717		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["h"], "h", error);
718
719		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "a", 0, error);
720		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "b", 4, error);
721		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c", 5, error);
722		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d", 7, error);
723		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "e", 11, error);
724		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "f", 12, error);
725		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g", 13, error);
726		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "h", 15, error);
727
728		GLenum props[] = {
729			GL_NAME_LENGTH,
730			GL_TYPE,
731			GL_ARRAY_SIZE,
732			GL_REFERENCED_BY_COMPUTE_SHADER,
733			GL_REFERENCED_BY_FRAGMENT_SHADER,
734			GL_REFERENCED_BY_VERTEX_SHADER,
735			GL_LOCATION,
736		};
737		GLint expected[] = { 2, 35676, 1, 0, 0, 1, 0 };
738		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["a"], 7, props, 7, expected, error);
739		GLint expected2[] = { 2, 35666, 1, 0, 0, 1, 4 };
740		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["b"], 7, props, 7, expected2, error);
741		GLint expected3[] = { 2, 5126, 1, 0, 0, 1, 5 };
742		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["c"], 7, props, 7, expected3, error);
743		GLint expected4[] = { 2, 35685, 1, 0, 0, 1, 7 };
744		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["d"], 7, props, 7, expected4, error);
745		GLint expected5[] = { 2, 35664, 1, 0, 0, 1, 11 };
746		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["e"], 7, props, 7, expected5, error);
747		GLint expected6[] = { 2, 5125, 1, 0, 0, 1, 12 };
748		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["f"], 7, props, 7, expected6, error);
749		GLint expected7[] = { 2, 35665, 1, 0, 0, 1, 13 };
750		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["g"], 7, props, 7, expected7, error);
751		GLint expected8[] = { 2, 5124, 1, 0, 0, 1, 15 };
752		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["h"], 7, props, 7, expected8, error);
753
754		glDeleteProgram(program);
755		return error;
756	}
757};
758
759class InputBuiltIn : public SimpleShaders
760{
761
762	virtual std::string Title()
763	{
764		return "Input Built-ins Test";
765	}
766
767	virtual std::string ShadersDesc()
768	{
769		return "vertex shader using built-in variables and a fallthrough fragment shader";
770	}
771
772	virtual std::string Expectations()
773	{
774		return ".\n\n In this case we ask for information about built-in variables for the input interface.";
775	}
776
777	virtual std::string VertexShader()
778	{
779		return "#version 310 es                      \n"
780			   "void main(void)                      \n"
781			   "{                                    \n"
782			   "    gl_Position = (float(gl_VertexID) + float(gl_InstanceID)) * vec4(0.1);          \n"
783			   "}";
784	}
785
786	virtual long Run()
787	{
788		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
789		LinkProgram(program);
790
791		long error = NO_ERROR;
792
793		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 2, error);
794		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 14, error);
795
796		std::map<std::string, GLuint> indices;
797		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "gl_VertexID", error);
798		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "gl_InstanceID", error);
799
800		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["gl_VertexID"], "gl_VertexID", error);
801		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["gl_InstanceID"], "gl_InstanceID", error);
802
803		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "gl_VertexID", -1, error);
804		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "gl_InstanceID", -1, error);
805
806		GLenum props[] = { GL_NAME_LENGTH,
807						   GL_TYPE,
808						   GL_ARRAY_SIZE,
809						   GL_REFERENCED_BY_COMPUTE_SHADER,
810						   GL_REFERENCED_BY_FRAGMENT_SHADER,
811						   GL_REFERENCED_BY_VERTEX_SHADER,
812						   GL_LOCATION };
813		GLint expected[] = { 12, 5124, 1, 0, 0, 1, -1 };
814		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["gl_VertexID"], 7, props, 7, expected, error);
815		GLint expected2[] = { 14, 5124, 1, 0, 0, 1, -1 };
816		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["gl_InstanceID"], 7, props, 7, expected2, error);
817
818		glDeleteProgram(program);
819		return error;
820	}
821};
822
823class InputLayout : public SimpleShaders
824{
825	virtual std::string Title()
826	{
827		return "Input Layout Test";
828	}
829
830	virtual std::string ShadersDesc()
831	{
832		return "vertex shader with different `in` variables locations set through layout and a fallthrough fragment "
833			   "shader";
834	}
835
836	virtual std::string VertexShader()
837	{
838		return "#version 310 es                      \n"
839			   "layout(location = 4) in vec4 b;      \n"
840			   "layout(location = 7) in mat2x3 d;    \n"
841			   "layout(location = 5) in float c;     \n"
842			   "layout(location = 12) in uint f;     \n"
843			   "layout(location = 13) in vec3 g;     \n"
844			   "layout(location = 0) in mat4 a;      \n"
845			   "layout(location = 15) in int h;      \n"
846			   "layout(location = 11) in vec2 e;     \n"
847			   "void main(void)                      \n"
848			   "{                                    \n"
849			   "   vec4 pos;                                              \n"
850			   "   pos.w = float(h) + g.x + g.y + d[1][1];                \n"
851			   "   pos.y = float(b.x) * c + c + d[0][0];                  \n"
852			   "   pos.x = a[0].x + a[1].y + a[2].z + a[3].w;             \n"
853			   "   pos.z = d[0][1] + float(e.x) * float(f) + d[1][0];     \n"
854			   "   gl_Position = pos;                                     \n"
855			   "}";
856	}
857
858	virtual long Run()
859	{
860		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
861		LinkProgram(program);
862
863		long error = NO_ERROR;
864
865		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 8, error);
866		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 2, error);
867
868		std::map<std::string, GLuint> indices;
869		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "a", error);
870		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "b", error);
871		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "c", error);
872		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "d", error);
873		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "e", error);
874		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "f", error);
875		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "g", error);
876		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "h", error);
877
878		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["a"], "a", error);
879		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["b"], "b", error);
880		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["c"], "c", error);
881		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["d"], "d", error);
882		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["e"], "e", error);
883		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["f"], "f", error);
884		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["g"], "g", error);
885		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["h"], "h", error);
886
887		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "a", 0, error);
888		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "b", 4, error);
889		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c", 5, error);
890		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d", 7, error);
891		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "e", 11, error);
892		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "f", 12, error);
893		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g", 13, error);
894		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "h", 15, error);
895
896		GLenum props[] = { GL_NAME_LENGTH,
897						   GL_TYPE,
898						   GL_ARRAY_SIZE,
899						   GL_REFERENCED_BY_COMPUTE_SHADER,
900						   GL_REFERENCED_BY_FRAGMENT_SHADER,
901						   GL_REFERENCED_BY_VERTEX_SHADER,
902						   GL_LOCATION };
903		GLint expected[] = { 2, 35676, 1, 0, 0, 1, 0 };
904		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["a"], 7, props, 7, expected, error);
905		GLint expected2[] = { 2, 35666, 1, 0, 0, 1, 4 };
906		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["b"], 7, props, 7, expected2, error);
907		GLint expected3[] = { 2, 5126, 1, 0, 0, 1, 5 };
908		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["c"], 7, props, 7, expected3, error);
909		GLint expected4[] = { 2, 35685, 1, 0, 0, 1, 7 };
910		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["d"], 7, props, 7, expected4, error);
911		GLint expected5[] = { 2, 35664, 1, 0, 0, 1, 11 };
912		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["e"], 7, props, 7, expected5, error);
913		GLint expected6[] = { 2, 5125, 1, 0, 0, 1, 12 };
914		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["f"], 7, props, 7, expected6, error);
915		GLint expected7[] = { 2, 35665, 1, 0, 0, 1, 13 };
916		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["g"], 7, props, 7, expected7, error);
917		GLint expected8[] = { 2, 5124, 1, 0, 0, 1, 15 };
918		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["h"], 7, props, 7, expected8, error);
919
920		glDeleteProgram(program);
921		return error;
922	}
923};
924
925class OutputLayout : public SimpleShaders
926{
927	virtual std::string Title()
928	{
929		return "Output Layout Test";
930	}
931
932	virtual std::string ShadersDesc()
933	{
934		return "fragment shader with different `out` variables locations set through layout and a fallthrough vertex "
935			   "shader";
936	}
937
938	virtual std::string FragmentShader()
939	{
940		return "#version 310 es                \n"
941			   "layout(location = 2) out uint b;                    \n"
942			   "layout(location = 3) out mediump vec2 e;            \n"
943			   "layout(location = 0) out mediump vec3 a[2];         \n"
944			   "void main() {                  \n"
945			   "    b = 12u;                   \n"
946			   "    e = vec2(0, 1);            \n"
947			   "    a[1] = vec3(0, 1, 0);      \n"
948			   "    a[0] = vec3(0, 1, 0);      \n"
949			   "}";
950	}
951
952	virtual long Run()
953	{
954		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
955		glBindAttribLocation(program, 0, "position");
956		LinkProgram(program);
957
958		long error = NO_ERROR;
959
960		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 3, error);
961		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 5, error);
962
963		std::map<std::string, GLuint> indices;
964		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "a", error);
965		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "b", error);
966		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "e", error);
967
968		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["a"], "a[0]", error);
969		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["b"], "b", error);
970		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["e"], "e", error);
971
972		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
973		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a", 0, error);
974		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[1]", 1, error);
975		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "b", 2, error);
976		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "e", 3, error);
977
978		GLenum props[] = { GL_NAME_LENGTH,
979						   GL_TYPE,
980						   GL_ARRAY_SIZE,
981						   GL_REFERENCED_BY_COMPUTE_SHADER,
982						   GL_REFERENCED_BY_FRAGMENT_SHADER,
983						   GL_REFERENCED_BY_VERTEX_SHADER,
984						   GL_LOCATION };
985		GLint expected_a[] = { 5, 35665, 2, 0, 1, 0, 0 };
986		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["a"], 7, props, 7, expected_a, error);
987		GLint expected_b[] = { 2, 5125, 1, 0, 1, 0, 2 };
988		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["b"], 7, props, 7, expected_b, error);
989		GLint expected_e[] = { 2, 35664, 1, 0, 1, 0, 3 };
990		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["e"], 7, props, 7, expected_e, error);
991
992		glDeleteProgram(program);
993		return error;
994	}
995};
996
997class UniformSimple : public PIQBase
998{
999	virtual std::string Title()
1000	{
1001		return "Uniform Simple Test";
1002	}
1003
1004	virtual std::string ShadersDesc()
1005	{
1006		return "fallthrough fragment and vertex shaders with uniforms used";
1007	}
1008
1009	virtual std::string PurposeExt()
1010	{
1011		return "\n\n Purpose is to verify calls using GL_UNIFORM as an interface param.";
1012	}
1013
1014	virtual std::string VertexShader()
1015	{
1016		return "#version 310 es                      \n"
1017			   "in vec4 position;                    \n"
1018			   "uniform mediump vec4 repos;          \n"
1019			   "void main(void)                      \n"
1020			   "{                                    \n"
1021			   "    gl_Position = position + repos;  \n"
1022			   "}";
1023	}
1024
1025	virtual std::string FragmentShader()
1026	{
1027		return "#version 310 es                \n"
1028			   "uniform mediump vec4 recolor;  \n"
1029			   "out mediump vec4 color;        \n"
1030			   "void main() {                  \n"
1031			   "    color = vec4(0, 1, 0, 1) + recolor;  \n"
1032			   "}";
1033	}
1034
1035	virtual long Run()
1036	{
1037		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1038		glBindAttribLocation(program, 0, "position");
1039		LinkProgram(program);
1040
1041		long error = NO_ERROR;
1042
1043		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
1044									GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
1045		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, 8, error);
1046
1047		std::map<std::string, GLuint> indices;
1048		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "repos", error);
1049		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "recolor", error);
1050
1051		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["repos"], "repos", error);
1052		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["recolor"], "recolor", error);
1053
1054		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "repos", glGetUniformLocation(program, "repos"), error);
1055		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "recolor", glGetUniformLocation(program, "recolor"),
1056										 error);
1057
1058		GLenum props[] = { GL_NAME_LENGTH,
1059						   GL_TYPE,
1060						   GL_ARRAY_SIZE,
1061						   GL_OFFSET,
1062						   GL_BLOCK_INDEX,
1063						   GL_ARRAY_STRIDE,
1064						   GL_MATRIX_STRIDE,
1065						   GL_IS_ROW_MAJOR,
1066						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
1067						   GL_REFERENCED_BY_COMPUTE_SHADER,
1068						   GL_REFERENCED_BY_FRAGMENT_SHADER,
1069						   GL_REFERENCED_BY_VERTEX_SHADER,
1070						   GL_LOCATION };
1071		GLint expected[] = { 6, 35666, 1, -1, -1, -1, -1, 0, -1, 0, 0, 1, glGetUniformLocation(program, "repos") };
1072		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["repos"], 13, props, 13, expected, error);
1073
1074		GLint expected2[] = { 8, 35666, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "recolor") };
1075		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["recolor"], 13, props, 13, expected2, error);
1076
1077		glDeleteProgram(program);
1078		return error;
1079	}
1080};
1081
1082class UniformTypes : public PIQBase
1083{
1084	virtual std::string Title()
1085	{
1086		return "Uniform Types Test";
1087	}
1088
1089	virtual std::string ShadersDesc()
1090	{
1091		return "fallthrough fragment and vertex shaders with different uniform types used";
1092	}
1093
1094	virtual std::string PurposeExt()
1095	{
1096		return "\n\n Purpose is to verify calls using GL_UNIFORM as an interface param.\n";
1097	}
1098
1099	virtual std::string VertexShader()
1100	{
1101		return "#version 310 es                      \n"
1102			   "in vec4 position;                    \n"
1103			   "uniform mediump vec4 a;              \n"
1104			   "uniform ivec3 b;                     \n"
1105			   "uniform uvec2 c[3];                  \n"
1106			   "uniform mediump mat2 g[8];           \n"
1107			   "uniform mediump mat3x2 i;            \n"
1108			   "void main(void)                      \n"
1109			   "{                                    \n"
1110			   "    float tmp;                       \n"
1111			   "    tmp = g[0][1][1] * g[1][0][0] + g[2][1][0] - g[3][0][1]; \n"
1112			   "    tmp = tmp + g[4][0][0] * g[5][1][0] - g[6][1][1] + g[7][0][1]; \n"
1113			   "    tmp = tmp + a.z + +float(b.y) + float(c[0].x) - float(c[1].x) * float(c[2].y);   \n"
1114			   "    tmp = tmp + i[1][1];             \n"
1115			   "    gl_Position = position * tmp;    \n"
1116			   "}";
1117	}
1118
1119	virtual std::string FragmentShader()
1120	{
1121		return "#version 310 es                \n"
1122			   "struct U {                     \n"
1123			   "   bool a[3];                  \n"
1124			   "   mediump vec4 b;                     \n"
1125			   "   mediump mat3 c;                     \n"
1126			   "   mediump float d[2];                 \n"
1127			   "};                             \n"
1128			   "struct UU {                    \n"
1129			   "   U a;                        \n"
1130			   "   U b[2];                     \n"
1131			   "   uvec2 c;                    \n"
1132			   "};                             \n"
1133			   "uniform mediump mat4 d;                \n"
1134			   "uniform mediump mat3 e;                \n"
1135			   "uniform mediump float h;               \n"
1136			   "uniform int f;                 \n"
1137			   "uniform U j;                   \n"
1138			   "uniform UU k;                  \n"
1139			   "uniform UU l[3];               \n"
1140			   "out mediump vec4 color;                \n"
1141			   "void main() {                  \n"
1142			   "    mediump float tmp;                 \n"
1143			   "    tmp = h + float(f) + e[2][2];           \n"
1144			   "    tmp = tmp + d[0][0] + j.b.x;     \n"
1145			   "    tmp = tmp + k.b[0].c[0][0];      \n"
1146			   "    tmp = tmp + l[2].a.c[0][1];      \n"
1147			   "    tmp = tmp + l[2].b[1].d[0];      \n"
1148			   "    tmp = tmp + float(l[0].c.x);            \n"
1149			   "    color = vec4(0, 1, 0, 1) * tmp;  \n"
1150			   "}";
1151	}
1152
1153	virtual long Run()
1154	{
1155		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1156		glBindAttribLocation(program, 0, "position");
1157		LinkProgram(program);
1158
1159		long error = NO_ERROR;
1160
1161		// only active structure members
1162		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
1163									GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
1164		// l[2].b[1].d[0] and \0
1165		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, 15, error);
1166
1167		std::map<std::string, GLuint> indices;
1168		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "a", error);
1169		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "b", error);
1170		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "c", error);
1171		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "d", error);
1172		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "e", error);
1173		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "f", error);
1174		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "g", error);
1175		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "h", error);
1176		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "i", error);
1177		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "j.b", error);
1178		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "k.b[0].c", error);
1179		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[0].c", error);
1180		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[2].b[1].d[0]", error);
1181		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[2].a.c", error);
1182
1183		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["a"], "a", error);
1184		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["b"], "b", error);
1185		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["c"], "c[0]", error);
1186		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["d"], "d", error);
1187		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["e"], "e", error);
1188		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["f"], "f", error);
1189		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["g"], "g[0]", error);
1190		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["h"], "h", error);
1191		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["i"], "i", error);
1192		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["j.b"], "j.b", error);
1193		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["k.b[0].c"], "k.b[0].c", error);
1194		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[0].c"], "l[0].c", error);
1195		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[2].b[1].d[0]"], "l[2].b[1].d[0]", error);
1196		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[2].a.c"], "l[2].a.c", error);
1197
1198		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", glGetUniformLocation(program, "a"), error);
1199		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", glGetUniformLocation(program, "b"), error);
1200		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", glGetUniformLocation(program, "c"), error);
1201		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d", glGetUniformLocation(program, "d"), error);
1202		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "e", glGetUniformLocation(program, "e"), error);
1203		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "f", glGetUniformLocation(program, "f"), error);
1204		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "g", glGetUniformLocation(program, "g"), error);
1205		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "h", glGetUniformLocation(program, "h"), error);
1206		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "i", glGetUniformLocation(program, "i"), error);
1207		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "j.b", glGetUniformLocation(program, "j.b"), error);
1208		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "k.b[0].c", glGetUniformLocation(program, "k.b[0].c"),
1209										 error);
1210		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[0].c", glGetUniformLocation(program, "l[0].c"), error);
1211		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[2].b[1].d[0]",
1212										 glGetUniformLocation(program, "l[2].b[1].d[0]"), error);
1213		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[2].a.c", glGetUniformLocation(program, "l[2].a.c"),
1214										 error);
1215
1216		GLenum props[] = { GL_NAME_LENGTH,
1217						   GL_TYPE,
1218						   GL_ARRAY_SIZE,
1219						   GL_OFFSET,
1220						   GL_BLOCK_INDEX,
1221						   GL_ARRAY_STRIDE,
1222						   GL_MATRIX_STRIDE,
1223						   GL_IS_ROW_MAJOR,
1224						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
1225						   GL_REFERENCED_BY_COMPUTE_SHADER,
1226						   GL_REFERENCED_BY_FRAGMENT_SHADER,
1227						   GL_REFERENCED_BY_VERTEX_SHADER,
1228						   GL_LOCATION };
1229		GLint expected[] = { 2, 35666, 1, -1, -1, -1, -1, 0, -1, 0, 0, 1, glGetUniformLocation(program, "a") };
1230		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["a"], 13, props, 13, expected, error);
1231		GLint expected2[] = { 2, 35668, 1, -1, -1, -1, -1, 0, -1, 0, 0, 1, glGetUniformLocation(program, "b") };
1232		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["b"], 13, props, 13, expected2, error);
1233		GLint expected3[] = { 5, 36294, 3, -1, -1, -1, -1, 0, -1, 0, 0, 1, glGetUniformLocation(program, "c") };
1234		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["c"], 13, props, 13, expected3, error);
1235		GLint expected4[] = { 2, 35676, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "d") };
1236		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["d"], 13, props, 13, expected4, error);
1237		GLint expected5[] = { 2, 35675, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "e") };
1238		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["e"], 13, props, 13, expected5, error);
1239		GLint expected6[] = { 2, 5124, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "f") };
1240		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["f"], 13, props, 13, expected6, error);
1241		GLint expected7[] = { 5, 35674, 8, -1, -1, -1, -1, 0, -1, 0, 0, 1, glGetUniformLocation(program, "g") };
1242		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["g"], 13, props, 13, expected7, error);
1243		GLint expected8[] = { 2, 5126, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "h") };
1244		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["h"], 13, props, 13, expected8, error);
1245		GLint expected9[] = { 2, 35687, 1, -1, -1, -1, -1, 0, -1, 0, 0, 1, glGetUniformLocation(program, "i") };
1246		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["i"], 13, props, 13, expected9, error);
1247		GLint expected10[] = { 4, 35666, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "j.b") };
1248		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["j.b"], 13, props, 13, expected10, error);
1249		GLint expected11[] = { 9, 35675, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "k.b[0].c") };
1250		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["k.b[0].c"], 13, props, 13, expected11, error);
1251		GLint expected12[] = { 7, 36294, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "l[0].c") };
1252		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[0].c"], 13, props, 13, expected12, error);
1253		GLint expected13[] = {
1254			15, 5126, 2, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "l[2].b[1].d[0]")
1255		};
1256		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[2].b[1].d[0]"], 13, props, 13, expected13, error);
1257		GLint expected14[] = { 9, 35675, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, glGetUniformLocation(program, "l[2].a.c") };
1258		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[2].a.c"], 13, props, 13, expected14, error);
1259
1260		glDeleteProgram(program);
1261		return error;
1262	}
1263};
1264
1265class UniformBlockTypes : public PIQBase
1266{
1267	virtual std::string Title()
1268	{
1269		return "Uniform Block Types Test";
1270	}
1271
1272	virtual std::string ShadersDesc()
1273	{
1274		return "fallthrough fragment and vertex shaders with different types of uniform blocks used";
1275	}
1276
1277	virtual std::string PurposeExt()
1278	{
1279		return "\n\n Purpose is to verify calls using GL_UNIFORM_BLOCK as an interface param.\n";
1280	}
1281
1282	virtual std::string VertexShader()
1283	{
1284		return "#version 310 es                      \n"
1285			   "in vec4 position;                    \n"
1286			   ""
1287			   "uniform SimpleBlock {                \n"
1288			   "   mediump mat3x2 a;                         \n"
1289			   "   mediump mat4 b;                           \n"
1290			   "   vec4 c;                           \n"
1291			   "};                                   \n"
1292			   ""
1293			   "uniform NotSoSimpleBlockk {          \n"
1294			   "   ivec2 a[4];                       \n"
1295			   "   mediump mat3 b[2];                        \n"
1296			   "   mediump mat2 c;                           \n"
1297			   "} d;                                         \n"
1298			   ""
1299			   "void main(void)                                               \n"
1300			   "{                                                             \n"
1301			   "    mediump float tmp;                                        \n"
1302			   "    tmp =  a[0][1] * b[1][2] * c.x;                           \n"
1303			   "    tmp = tmp + float(d.a[2].y) + d.b[0][1][1] + d.c[1][1];   \n"
1304			   "    gl_Position = position * tmp;                             \n"
1305			   "}";
1306	}
1307
1308	virtual std::string FragmentShader()
1309	{
1310		return "#version 310 es                \n"
1311			   "struct U {                     \n"
1312			   "   bool a[3];                  \n"
1313			   "   mediump vec4 b;                     \n"
1314			   "   mediump mat3 c;                     \n"
1315			   "   mediump float d[2];                 \n"
1316			   "};                             \n"
1317			   "struct UU {                    \n"
1318			   "   U a;                        \n"
1319			   "   U b[2];                     \n"
1320			   "   uvec2 c;                    \n"
1321			   "};                             \n"
1322			   ""
1323			   "uniform TrickyBlock {                            \n"
1324			   "   UU a[3];                                      \n"
1325			   "   mediump mat4 b;                               \n"
1326			   "   uint c;                                       \n"
1327			   "} e[2];                                          \n"
1328			   ""
1329			   "out mediump vec4 color;                        \n"
1330			   "void main() {                                  \n"
1331			   "    mediump float tmp;                         \n"
1332			   "    tmp = e[0].a[2].b[0].d[1] * float(e[1].c); \n"
1333			   "    color = vec4(0, 1, 0, 1) * tmp;            \n"
1334			   "}";
1335	}
1336
1337	virtual long Run()
1338	{
1339		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1340		glBindAttribLocation(program, 0, "position");
1341		LinkProgram(program);
1342
1343		long error = NO_ERROR;
1344
1345		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
1346									GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
1347		VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, 4, error);
1348		VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NAME_LENGTH, 18, error);
1349
1350		std::map<std::string, GLuint> indicesUB;
1351		std::map<std::string, GLuint> indicesU;
1352		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "SimpleBlock", error);
1353		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "NotSoSimpleBlockk", error);
1354		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "TrickyBlock", error);
1355		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "TrickyBlock[1]", error);
1356		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
1357		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
1358		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "c", error);
1359		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.a[0]", error);
1360		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.c", error);
1361		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.b[0]", error);
1362		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "TrickyBlock.a[2].b[0].d", error);
1363
1364		glUniformBlockBinding(program, indicesUB["SimpleBlock"], 0);
1365		glUniformBlockBinding(program, indicesUB["NotSoSimpleBlockk"], 2);
1366		glUniformBlockBinding(program, indicesUB["TrickyBlock"], 3);
1367		glUniformBlockBinding(program, indicesUB["TrickyBlock[1]"], 4);
1368
1369		VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], "SimpleBlock", error);
1370		VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], "NotSoSimpleBlockk",
1371									 error);
1372		VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock"], "TrickyBlock[0]", error);
1373		VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock[1]"], "TrickyBlock[1]", error);
1374		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["a"], "a", error);
1375		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["b"], "b", error);
1376		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["c"], "c", error);
1377		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.a[0]"], "NotSoSimpleBlockk.a[0]",
1378									 error);
1379		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.c"], "NotSoSimpleBlockk.c",
1380									 error);
1381		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.b[0]"], "NotSoSimpleBlockk.b[0]",
1382									 error);
1383		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["TrickyBlock.a[2].b[0].d"],
1384									 "TrickyBlock.a[2].b[0].d[0]", error);
1385
1386		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", -1, error);
1387		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", -1, error);
1388		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", -1, error);
1389
1390		GLenum props[] = {
1391			GL_NAME_LENGTH,
1392			GL_BUFFER_BINDING,
1393			GL_REFERENCED_BY_COMPUTE_SHADER,
1394			GL_REFERENCED_BY_FRAGMENT_SHADER,
1395			GL_REFERENCED_BY_VERTEX_SHADER,
1396			GL_BUFFER_DATA_SIZE,
1397		};
1398		GLint size;
1399		glGetActiveUniformBlockiv(program, indicesUB["SimpleBlock"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
1400		GLint expected[] = { 12, 0, 0, 0, 1, size };
1401		VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], 6, props, 6, expected, error);
1402		glGetActiveUniformBlockiv(program, indicesUB["NotSoSimpleBlockk"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
1403		GLint expected2[] = { 18, 2, 0, 0, 1, size };
1404		VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], 6, props, 6, expected2,
1405								   error);
1406		glGetActiveUniformBlockiv(program, indicesUB["TrickyBlock"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
1407		GLint expected3[] = { 15, 3, 0, 1, 0, size };
1408		VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock"], 6, props, 6, expected3, error);
1409		GLint expected4[] = { 15, 4, 0, 1, 0, size };
1410		VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock[1]"], 6, props, 6, expected4,
1411								   error);
1412
1413		GLenum props2[] = { GL_NAME_LENGTH,
1414							GL_TYPE,
1415							GL_ARRAY_SIZE,
1416							GL_BLOCK_INDEX,
1417							GL_ARRAY_STRIDE,
1418							GL_IS_ROW_MAJOR,
1419							GL_ATOMIC_COUNTER_BUFFER_INDEX,
1420							GL_REFERENCED_BY_COMPUTE_SHADER,
1421							GL_REFERENCED_BY_FRAGMENT_SHADER,
1422							GL_REFERENCED_BY_VERTEX_SHADER,
1423							GL_LOCATION };
1424		GLint expected5[] = { 2, 35687, 1, static_cast<GLint>(indicesUB["SimpleBlock"]), 0, 0, -1, 0, 0, 1, -1 };
1425		VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 11, props2, 11, expected5, error);
1426		GLenum props3[] = { GL_NAME_LENGTH,
1427							GL_TYPE,
1428							GL_ARRAY_SIZE,
1429							GL_BLOCK_INDEX,
1430							GL_MATRIX_STRIDE,
1431							GL_IS_ROW_MAJOR,
1432							GL_ATOMIC_COUNTER_BUFFER_INDEX,
1433							GL_REFERENCED_BY_COMPUTE_SHADER,
1434							GL_REFERENCED_BY_FRAGMENT_SHADER,
1435							GL_REFERENCED_BY_VERTEX_SHADER,
1436							GL_LOCATION };
1437		GLint expected6[] = { 27, 5126, 2, static_cast<GLint>(indicesUB["TrickyBlock"]), 0, 0, -1, 0, 1, 0, -1 };
1438		VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["TrickyBlock.a[2].b[0].d"], 11, props3, 11, expected6,
1439								   error);
1440
1441		GLenum			 prop	= GL_ACTIVE_VARIABLES;
1442		const GLsizei	bufSize = 1000;
1443		GLsizei			 length;
1444		GLint			 param[bufSize];
1445		std::set<GLuint> exp;
1446		exp.insert(indicesU["a"]);
1447		exp.insert(indicesU["b"]);
1448		exp.insert(indicesU["c"]);
1449		glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], 1, &prop, bufSize, &length, param);
1450		for (int i = 0; i < length; ++i)
1451		{
1452			if (exp.find(param[i]) == exp.end())
1453			{
1454				m_context.getTestContext().getLog()
1455					<< tcu::TestLog::Message
1456					<< "Unexpected index found in active variables of SimpleBlock: " << param[i]
1457					<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
1458					<< tcu::TestLog::EndMessage;
1459				glDeleteProgram(program);
1460				return ERROR;
1461			}
1462			else if (length != 3)
1463			{
1464				m_context.getTestContext().getLog()
1465					<< tcu::TestLog::Message
1466					<< "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
1467					<< "Expected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
1468				glDeleteProgram(program);
1469				return ERROR;
1470			}
1471		}
1472		std::set<GLuint> exp2;
1473		exp2.insert(indicesU["NotSoSimpleBlockk.a[0]"]);
1474		exp2.insert(indicesU["NotSoSimpleBlockk.b[0]"]);
1475		exp2.insert(indicesU["NotSoSimpleBlockk.c"]);
1476		glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], 1, &prop, bufSize, &length,
1477							   param);
1478		for (int i = 0; i < length; ++i)
1479		{
1480			if (exp2.find(param[i]) == exp2.end())
1481			{
1482				m_context.getTestContext().getLog()
1483					<< tcu::TestLog::Message
1484					<< "Unexpected index found in active variables of NotSoSimpleBlockk: " << param[i]
1485					<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
1486					<< tcu::TestLog::EndMessage;
1487				glDeleteProgram(program);
1488				return ERROR;
1489			}
1490			else if (length != 3)
1491			{
1492				m_context.getTestContext().getLog()
1493					<< tcu::TestLog::Message
1494					<< "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
1495					<< "Expected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
1496				glDeleteProgram(program);
1497				return ERROR;
1498			}
1499		}
1500
1501		GLint res;
1502		glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &res);
1503		if (res < 3)
1504		{
1505			m_context.getTestContext().getLog()
1506				<< tcu::TestLog::Message << "Value of GL_MAX_NUM_ACTIVE_VARIABLES less than 3!"
1507				<< tcu::TestLog::EndMessage;
1508			glDeleteProgram(program);
1509			return ERROR;
1510		}
1511
1512		glDeleteProgram(program);
1513		return error;
1514	}
1515};
1516
1517class TransformFeedbackTypes : public SimpleShaders
1518{
1519	virtual std::string Title()
1520	{
1521		return "Transform Feedback Varying Types";
1522	}
1523
1524	virtual std::string ShadersDesc()
1525	{
1526		return "fallthrough fragment and vertex shaders with different types of out variables used";
1527	}
1528
1529	virtual std::string PurposeExt()
1530	{
1531		return "\n\n Purpose is to verify calls using GL_TRANSFORM_FEEDBACK_VARYING as an interface param.\n";
1532	}
1533
1534	virtual std::string VertexShader()
1535	{
1536		return "#version 310 es                      \n"
1537			   "in vec4 position;                    \n"
1538			   ""
1539			   "flat out highp vec4 a;               \n"
1540			   "out mediump float b[2];              \n"
1541			   "flat out highp uvec2 c;              \n"
1542			   "flat out highp uint d;               \n"
1543			   "out mediump vec3 e[2];               \n"
1544			   "flat out int f;                      \n"
1545			   ""
1546			   "void main(void)                      \n"
1547			   "{                                    \n"
1548			   "   vec4 pos;                         \n"
1549			   "   a = vec4(1);                      \n"
1550			   "   b[0] = 1.1;                       \n"
1551			   "   b[1] = 1.1;                       \n"
1552			   "   c = uvec2(1u);                    \n"
1553			   "   d = 1u;                           \n"
1554			   "   e[0] = vec3(1.1);                 \n"
1555			   "   e[1] = vec3(1.1);                 \n"
1556			   "   f = 1;                            \n"
1557			   "   gl_Position = position;           \n"
1558			   "}";
1559	}
1560
1561	virtual long Run()
1562	{
1563		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1564		glBindAttribLocation(program, 0, "position");
1565		const char* varyings[6] = { "a", "b[0]", "b[1]", "c", "d", "e" };
1566		glTransformFeedbackVaryings(program, 6, varyings, GL_INTERLEAVED_ATTRIBS);
1567		LinkProgram(program);
1568
1569		long error = NO_ERROR;
1570
1571		VerifyGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_ACTIVE_RESOURCES, 6, error);
1572		VerifyGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_MAX_NAME_LENGTH, 5, error);
1573
1574		std::map<std::string, GLuint> indices;
1575		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "a", error);
1576		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "b[0]", error);
1577		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "b[1]", error);
1578		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "c", error);
1579		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "d", error);
1580		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "e", error);
1581
1582		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["a"], "a", error);
1583		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[0]"], "b[0]", error);
1584		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[1]"], "b[1]", error);
1585		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["c"], "c", error);
1586		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["d"], "d", error);
1587		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["e"], "e", error);
1588
1589		GLenum props[]	= { GL_NAME_LENGTH, GL_TYPE, GL_ARRAY_SIZE };
1590		GLint  expected[] = { 2, 35666, 1 };
1591		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["a"], 3, props, 3, expected, error);
1592		GLint expected2[] = { 5, 5126, 1 };
1593		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[0]"], 3, props, 3, expected2,
1594								   error);
1595		GLint expected3[] = { 5, 5126, 1 };
1596		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[1]"], 3, props, 3, expected3,
1597								   error);
1598		GLint expected4[] = { 2, 36294, 1 };
1599		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["c"], 3, props, 3, expected4, error);
1600		GLint expected5[] = { 2, 5125, 1 };
1601		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["d"], 3, props, 3, expected5, error);
1602		GLint expected6[] = { 2, 35665, 2 };
1603		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["e"], 3, props, 3, expected6, error);
1604
1605		glDeleteProgram(program);
1606		return error;
1607	}
1608};
1609
1610class AtomicCounterSimple : public ComputeShaderTest
1611{
1612public:
1613	virtual std::string Title()
1614	{
1615		return "Atomic Counter Buffer Simple Test";
1616	}
1617
1618	virtual std::string ShadersDesc()
1619	{
1620		return "compute shader with atomic counters used";
1621	}
1622
1623	virtual std::string PurposeExt()
1624	{
1625		return "\n\n Purpose is to verify calls using GL_ATOMIC_COUNTER_BUFFER as an interface param.\n";
1626	}
1627
1628	virtual long Run()
1629	{
1630
1631		GLint max_buffer_bindings = 0;
1632		glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &max_buffer_bindings);
1633		if (max_buffer_bindings < 6)
1634		{
1635			OutputNotSupported("Test requires at least 6 atomic counter buffer binding points.");
1636			return NOT_SUPPORTED;
1637		}
1638
1639		const char* const glsl_cs = "layout(local_size_x = 1, local_size_y = 1) in;  \n"
1640									"layout(std430) buffer Output {                  \n"
1641									"   mediump vec4 data;                           \n"
1642									"} g_out;                                        \n"
1643									""
1644									"layout (binding = 1, offset = 0) uniform highp atomic_uint a;    \n"
1645									"layout (binding = 2, offset = 0) uniform highp atomic_uint b;    \n"
1646									"layout (binding = 2, offset = 4) uniform highp atomic_uint c;    \n"
1647									"layout (binding = 5, offset = 0) uniform highp atomic_uint d[3]; \n"
1648									"layout (binding = 5, offset = 12) uniform highp atomic_uint e;   \n"
1649									""
1650									"void main() {                                                         \n"
1651									"   uint x = atomicCounterIncrement(d[0]) + atomicCounterIncrement(a); \n"
1652									"   uint y = atomicCounterIncrement(d[1]) + atomicCounterIncrement(b); \n"
1653									"   uint z = atomicCounterIncrement(d[2]) + atomicCounterIncrement(c); \n"
1654									"   uint w = atomicCounterIncrement(e);                                \n"
1655									"   g_out.data = vec4(float(x), float(y), float(z), float(w));         \n"
1656									"}";
1657
1658		GLuint program = CreateComputeProgram(glsl_cs);
1659		glLinkProgram(program);
1660		if (!CheckProgram(program))
1661		{
1662			glDeleteProgram(program);
1663			return ERROR;
1664		}
1665		glUseProgram(program);
1666
1667		long error = NO_ERROR;
1668
1669		VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, 3, error);
1670		VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, 2, error);
1671
1672		std::map<std::string, GLuint> indicesU;
1673		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
1674		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
1675		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "c", error);
1676		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "d", error);
1677		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "e", error);
1678
1679		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["a"], "a", error);
1680		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["b"], "b", error);
1681		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["c"], "c", error);
1682		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["d"], "d[0]", error);
1683		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["e"], "e", error);
1684
1685		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", -1, error);
1686		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", -1, error);
1687		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", -1, error);
1688		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d", -1, error);
1689		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "e", -1, error);
1690		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[0]", -1, error);
1691		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[1]", -1, error);
1692		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[2]", -1, error);
1693
1694		GLenum		  prop	= GL_ATOMIC_COUNTER_BUFFER_INDEX;
1695		const GLsizei bufSize = 1000;
1696		GLsizei		  length;
1697		GLint		  res;
1698		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, &res);
1699
1700		GLenum props[] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES, GL_ACTIVE_VARIABLES };
1701		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, &res);
1702		GLint expected[] = { 1, 4, 1, static_cast<GLint>(indicesU["a"]) };
1703		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 4, props, 4, expected, error);
1704
1705		GLenum props2[] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES };
1706		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, bufSize, &length, &res);
1707		GLint expected2[] = { 2, 8, 2 };
1708		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected2, error);
1709		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["c"], 1, &prop, bufSize, &length, &res);
1710		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected2, error);
1711
1712		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["d"], 1, &prop, bufSize, &length, &res);
1713		GLint expected3[] = { 5, 16, 2 };
1714		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected3, error);
1715		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["e"], 1, &prop, bufSize, &length, &res);
1716		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected3, error);
1717
1718		GLenum			 prop2 = GL_ACTIVE_VARIABLES;
1719		GLint			 param[bufSize];
1720		std::set<GLuint> exp;
1721		exp.insert(indicesU["b"]);
1722		exp.insert(indicesU["c"]);
1723		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, bufSize, &length, &res);
1724		glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 1, &prop2, bufSize, &length, param);
1725		for (int i = 0; i < length; ++i)
1726		{
1727			if (exp.find(param[i]) == exp.end() || length != 2)
1728			{
1729				m_context.getTestContext().getLog()
1730					<< tcu::TestLog::Message << "Length: " << length
1731					<< "Unexpected index/length found in active variables of ATOMIC_COUNTER_BUFFER: " << param[i]
1732					<< tcu::TestLog::EndMessage;
1733				glDeleteProgram(program);
1734				return ERROR;
1735			}
1736		}
1737		std::set<GLuint> exp2;
1738		GLint			 param2[bufSize];
1739		exp2.insert(indicesU["d"]);
1740		exp2.insert(indicesU["e"]);
1741		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["d"], 1, &prop, bufSize, &length, &res);
1742		glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 1, &prop2, bufSize, &length, param2);
1743		for (int i = 0; i < length; ++i)
1744		{
1745			if (exp2.find(param2[i]) == exp2.end() || length != 2)
1746			{
1747				m_context.getTestContext().getLog()
1748					<< tcu::TestLog::Message << "Length: " << length
1749					<< "Unexpected index/length found in active variables of ATOMIC_COUNTER_BUFFER: " << param2[i]
1750					<< tcu::TestLog::EndMessage;
1751				glDeleteProgram(program);
1752				return ERROR;
1753			}
1754		}
1755
1756		glDeleteProgram(program);
1757		return error;
1758	}
1759};
1760
1761class AtomicCounterSimpleOneBuffer : public ComputeShaderTest
1762{
1763public:
1764	virtual std::string Title()
1765	{
1766		return "Atomic Counter Buffer Simple One Buffer Test";
1767	}
1768
1769	virtual std::string ShadersDesc()
1770	{
1771		return "compute shader with atomic counters used";
1772	}
1773
1774	virtual std::string PurposeExt()
1775	{
1776		return "\n\n Purpose is to verify calls using GL_ATOMIC_COUNTER_BUFFER as an interface param.\n";
1777	}
1778
1779	virtual long Run()
1780	{
1781
1782		GLint max_buffer_bindings = 0;
1783		glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &max_buffer_bindings);
1784		if (max_buffer_bindings < 3)
1785		{
1786			OutputNotSupported("Test requires at least 3 atomic counter buffer binding points.");
1787			return NOT_SUPPORTED;
1788		}
1789
1790		const char* const glsl_cs = "layout(local_size_x = 1, local_size_y = 1) in;  \n"
1791									"layout(std430) buffer Output {                  \n"
1792									"   mediump vec4 data;                           \n"
1793									"} g_out;                                        \n"
1794									""
1795									"layout (binding = 0, offset = 0) uniform highp atomic_uint a;    \n"
1796									"layout (binding = 0, offset = 4) uniform highp atomic_uint b[3]; \n"
1797									"layout (binding = 0, offset = 16) uniform highp atomic_uint c;   \n"
1798									""
1799									"void main() {                                                         \n"
1800									"   uint x = atomicCounterIncrement(b[0]) + atomicCounterIncrement(a); \n"
1801									"   uint y = atomicCounterIncrement(b[1]) + atomicCounterIncrement(a); \n"
1802									"   uint z = atomicCounterIncrement(b[2]) + atomicCounterIncrement(a); \n"
1803									"   uint w = atomicCounterIncrement(c);                                \n"
1804									"   g_out.data = vec4(float(x), float(y), float(z), float(w));         \n"
1805									"}";
1806
1807		GLuint program = CreateComputeProgram(glsl_cs);
1808		glLinkProgram(program);
1809		if (!CheckProgram(program))
1810		{
1811			glDeleteProgram(program);
1812			return ERROR;
1813		}
1814		glUseProgram(program);
1815
1816		long error = NO_ERROR;
1817
1818		VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, 1, error);
1819		VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, 3, error);
1820
1821		std::map<std::string, GLuint> indicesU;
1822		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
1823		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
1824		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "c", error);
1825
1826		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["a"], "a", error);
1827		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["b"], "b[0]", error);
1828		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["c"], "c", error);
1829
1830		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", -1, error);
1831		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", -1, error);
1832		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", -1, error);
1833		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b[0]", -1, error);
1834		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b[1]", -1, error);
1835		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b[2]", -1, error);
1836
1837		GLenum		  prop	= GL_ATOMIC_COUNTER_BUFFER_INDEX;
1838		const GLsizei bufSize = 1000;
1839		GLsizei		  length;
1840		GLint		  res;
1841
1842		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, &res);
1843		if (res != 0)
1844		{
1845			m_context.getTestContext().getLog()
1846				<< tcu::TestLog::Message << "Got buffer index " << res << ", expected 0." << tcu::TestLog::EndMessage;
1847			glDeleteProgram(program);
1848			return ERROR;
1849		}
1850
1851		GLenum props[]	= { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES };
1852		GLint  expected[] = { 0, 20, 3 };
1853		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props, 3, expected, error);
1854
1855		GLenum			 prop2 = GL_ACTIVE_VARIABLES;
1856		GLint			 param[bufSize];
1857		std::set<GLuint> exp;
1858		exp.insert(indicesU["a"]);
1859		exp.insert(indicesU["b"]);
1860		exp.insert(indicesU["c"]);
1861
1862		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, bufSize, &length, &res);
1863		if (res != 0)
1864		{
1865			m_context.getTestContext().getLog()
1866				<< tcu::TestLog::Message << "Got buffer index " << res << ", expected 0." << tcu::TestLog::EndMessage;
1867			glDeleteProgram(program);
1868			return ERROR;
1869		}
1870
1871		glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 1, &prop2, bufSize, &length, param);
1872		for (int i = 0; i < length; ++i)
1873		{
1874			if (exp.find(param[i]) == exp.end() || length != 3)
1875			{
1876				m_context.getTestContext().getLog()
1877					<< tcu::TestLog::Message << "Length: " << length
1878					<< "Unexpected index/length found in active variables of ATOMIC_COUNTER_BUFFER: " << param[i]
1879					<< tcu::TestLog::EndMessage;
1880				glDeleteProgram(program);
1881				return ERROR;
1882			}
1883		}
1884
1885		glDeleteProgram(program);
1886		return error;
1887	}
1888};
1889
1890class InvalidValueTest : public SimpleShaders
1891{
1892	virtual std::string Title()
1893	{
1894		return "Invalid Value Test";
1895	}
1896
1897	virtual std::string PassCriteria()
1898	{
1899		return "GL_INVALID_VALUE error is generated after every function call.";
1900	}
1901
1902	virtual std::string Purpose()
1903	{
1904		return "Verify that wrong use of functions generates GL_INVALID_VALUE as described in spec.";
1905	}
1906
1907	virtual std::string Method()
1908	{
1909		return "Call functions with invalid values and check if GL_INVALID_VALUE was generated.";
1910	}
1911
1912	virtual long Run()
1913	{
1914		long error = NO_ERROR;
1915
1916		GLint   res;
1917		GLsizei len		  = 0;
1918		GLchar  name[100] = { '\0' };
1919		GLenum  props[1]  = { GL_NAME_LENGTH };
1920
1921		m_context.getTestContext().getLog()
1922			<< tcu::TestLog::Message << "Case 1: <program> not a name of shader/program object"
1923			<< tcu::TestLog::EndMessage;
1924		glGetProgramInterfaceiv(1337u, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &res);
1925		ExpectError(GL_INVALID_VALUE, error);
1926		glGetProgramResourceIndex(31337u, GL_PROGRAM_INPUT, "pie");
1927		ExpectError(GL_INVALID_VALUE, error);
1928		glGetProgramResourceName(1337u, GL_PROGRAM_INPUT, 0, 1024, &len, name);
1929		ExpectError(GL_INVALID_VALUE, error);
1930		glGetProgramResourceiv(1337u, GL_PROGRAM_INPUT, 0, 1, props, 1024, &len, &res);
1931		ExpectError(GL_INVALID_VALUE, error);
1932		glGetProgramResourceLocation(1337u, GL_PROGRAM_INPUT, "pie");
1933		ExpectError(GL_INVALID_VALUE, error);
1934		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 1: finished" << tcu::TestLog::EndMessage;
1935
1936		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1937		glBindAttribLocation(program, 0, "position");
1938		LinkProgram(program);
1939
1940		m_context.getTestContext().getLog()
1941			<< tcu::TestLog::Message
1942			<< "Case 2: <index> is greater than the number of the active resources in GetProgramResourceName"
1943			<< tcu::TestLog::EndMessage;
1944		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 1: finished" << tcu::TestLog::EndMessage;
1945		glGetProgramResourceName(program, GL_PROGRAM_INPUT, 3000, 1024, &len, name);
1946		ExpectError(GL_INVALID_VALUE, error);
1947		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 2: finished" << tcu::TestLog::EndMessage;
1948
1949		m_context.getTestContext().getLog()
1950			<< tcu::TestLog::Message << "Case 3: <propCount> is zero in GetProgramResourceiv"
1951			<< tcu::TestLog::EndMessage;
1952		glGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 0, props, 1024, &len, &res);
1953		ExpectError(GL_INVALID_VALUE, error);
1954		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 3: finished" << tcu::TestLog::EndMessage;
1955
1956		std::string str = "position";
1957		glGetProgramResourceName(program, GL_PROGRAM_INPUT, 0, -100, NULL, const_cast<char*>(str.c_str()));
1958		ExpectError(GL_INVALID_VALUE, error);
1959		GLenum prop = GL_NAME_LENGTH;
1960		glGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 1, &prop, -100, &len, &res);
1961		ExpectError(GL_INVALID_VALUE, error);
1962
1963		glDeleteProgram(program);
1964		return error;
1965	}
1966};
1967
1968class InvalidEnumTest : public SimpleShaders
1969{
1970	virtual std::string Title()
1971	{
1972		return "Invalid Enum Test";
1973	}
1974
1975	virtual std::string PassCriteria()
1976	{
1977		return "GL_INVALID_ENUM error is generated after every function call.";
1978	}
1979
1980	virtual std::string Purpose()
1981	{
1982		return "Verify that wrong use of functions generates GL_INVALID_ENUM as described in spec.";
1983	}
1984
1985	virtual std::string Method()
1986	{
1987		return "Call functions with invalid enums and check if GL_INVALID_ENUM was generated.";
1988	}
1989
1990	// make sure at least one atomic counter resource is active
1991	virtual std::string FragmentShader()
1992	{
1993		return "#version 310 es                                        \n"
1994			   "layout (binding = 0, offset = 0) uniform highp atomic_uint a;\n"
1995			   "out mediump vec4 outColor;                             \n"
1996			   "void main(void) {                                      \n"
1997			   "   uint b = atomicCounterIncrement(a);                 \n"
1998			   "   outColor = vec4(float(b));                          \n"
1999			   "}                                                      \n";
2000	}
2001
2002	virtual long Run()
2003	{
2004		GLint max_buffers = 0, max_counters = 0;
2005		glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &max_buffers);
2006		glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &max_counters);
2007		if (max_buffers < 1 || max_counters < 1)
2008		{
2009			OutputNotSupported("Test requires at least 1 atomic counter.");
2010			return NOT_SUPPORTED;
2011		}
2012
2013		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2014		glBindAttribLocation(program, 0, "position");
2015		LinkProgram(program);
2016
2017		long error = NO_ERROR;
2018
2019		GLint   res;
2020		GLsizei len		  = 0;
2021		GLchar  name[100] = { '\0' };
2022		GLenum  props[1]  = { GL_TEXTURE_1D };
2023
2024		m_context.getTestContext().getLog()
2025			<< tcu::TestLog::Message << "Case 1: <programInterface> is ATOMIC_COUNTER_BUFFER in "
2026										"GetProgramResourceIndex or GetProgramResourceName"
2027			<< tcu::TestLog::EndMessage;
2028		glGetProgramResourceIndex(program, GL_ATOMIC_COUNTER_BUFFER, name);
2029		ExpectError(GL_INVALID_ENUM, error);
2030		glGetProgramResourceName(program, GL_ATOMIC_COUNTER_BUFFER, 0, 1024, &len, name);
2031		ExpectError(GL_INVALID_ENUM, error);
2032		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 1 finished" << tcu::TestLog::EndMessage;
2033
2034		m_context.getTestContext().getLog()
2035			<< tcu::TestLog::Message
2036			<< "Case 2: <props> is not a property name supported by the command GetProgramResourceiv"
2037			<< tcu::TestLog::EndMessage;
2038		glGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 1, props, 1024, &len, &res);
2039		ExpectError(GL_INVALID_ENUM, error);
2040		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 2 finished" << tcu::TestLog::EndMessage;
2041
2042		glGetProgramResourceLocation(program, GL_ATOMIC_COUNTER_BUFFER, "position");
2043		ExpectError(GL_INVALID_ENUM, error);
2044
2045		glDeleteProgram(program);
2046		return error;
2047	}
2048};
2049
2050class InvalidOperationTest : public SimpleShaders
2051{
2052	virtual std::string Title()
2053	{
2054		return "Invalid Operation Test";
2055	}
2056
2057	virtual std::string PassCriteria()
2058	{
2059		return "GL_INVALID_OPERATION error is generated after every function call.";
2060	}
2061
2062	virtual std::string Purpose()
2063	{
2064		return "Verify that wrong use of functions generates GL_INVALID_OPERATION as described in spec.";
2065	}
2066
2067	virtual std::string Method()
2068	{
2069		return "Perform invalid operation and check if GL_INVALID_OPERATION was generated.";
2070	}
2071
2072	virtual long Run()
2073	{
2074		long error = NO_ERROR;
2075
2076		GLuint program  = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2077		GLuint program2 = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2078		glBindAttribLocation(program, 0, "position");
2079		LinkProgram(program);
2080
2081		const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
2082		GLint		 res;
2083		GLsizei		 len	   = 0;
2084		GLchar		 name[100] = { '\0' };
2085		GLenum		 props[1]  = { GL_OFFSET };
2086
2087		m_context.getTestContext().getLog()
2088			<< tcu::TestLog::Message << "Case 1: <program> is the name of a shader object" << tcu::TestLog::EndMessage;
2089		glGetProgramInterfaceiv(sh, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &res);
2090		ExpectError(GL_INVALID_OPERATION, error);
2091		glGetProgramResourceIndex(sh, GL_PROGRAM_INPUT, "pie");
2092		ExpectError(GL_INVALID_OPERATION, error);
2093		glGetProgramResourceName(sh, GL_PROGRAM_INPUT, 0, 1024, &len, name);
2094		ExpectError(GL_INVALID_OPERATION, error);
2095		glGetProgramResourceiv(sh, GL_PROGRAM_INPUT, 0, 1, props, 1024, &len, &res);
2096		ExpectError(GL_INVALID_OPERATION, error);
2097		glGetProgramResourceLocation(sh, GL_PROGRAM_INPUT, "pie");
2098		ExpectError(GL_INVALID_OPERATION, error);
2099		glDeleteShader(sh);
2100		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 1 finished" << tcu::TestLog::EndMessage;
2101
2102		m_context.getTestContext().getLog()
2103			<< tcu::TestLog::Message << "Case 2: <pname> is not supported in GetProgramInterfaceiv"
2104			<< tcu::TestLog::EndMessage;
2105		glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &res);
2106		ExpectError(GL_INVALID_OPERATION, error);
2107		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 2 finished" << tcu::TestLog::EndMessage;
2108
2109		m_context.getTestContext().getLog()
2110			<< tcu::TestLog::Message << "Case 3: <props> is not supported in GetProgramResourceiv"
2111			<< tcu::TestLog::EndMessage;
2112		glGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 1, props, 1024, &len, &res);
2113		ExpectError(GL_INVALID_OPERATION, error);
2114		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 3 finished" << tcu::TestLog::EndMessage;
2115
2116		m_context.getTestContext().getLog()
2117			<< tcu::TestLog::Message << "Case 4: <program> has not been linked in GetProgramResourceLocation"
2118			<< tcu::TestLog::EndMessage;
2119		glGetProgramResourceLocation(program2, GL_PROGRAM_INPUT, "pie");
2120		ExpectError(GL_INVALID_OPERATION, error);
2121		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 4 finished" << tcu::TestLog::EndMessage;
2122
2123		glDeleteProgram(program);
2124		glDeleteProgram(program2);
2125		return error;
2126	}
2127};
2128
2129class ShaderStorageBlock : public ComputeShaderTest
2130{
2131	virtual std::string Title()
2132	{
2133		return "Shader Storage Block Test";
2134	}
2135
2136	virtual std::string ShadersDesc()
2137	{
2138		return "compute shader different types of storage blocks used";
2139	}
2140
2141	virtual std::string PurposeExt()
2142	{
2143		return "\n\n Purpose is to verify calls using GL_BUFFER_VARIABLE and GL_SHADER_STORAGE_BLOCK as an interface "
2144			   "params.\n";
2145	}
2146
2147	virtual std::string ComputeShader()
2148	{
2149		return "layout(local_size_x = 1, local_size_y = 1) in;  \n"
2150			   "layout(std430) buffer Output {                  \n"
2151			   "   mediump vec4 data;                           \n"
2152			   "} g_out;                                        \n"
2153			   ""
2154			   "struct U {                     \n"
2155			   "   bool a[3];                  \n"
2156			   "   mediump vec4 b;                     \n"
2157			   "   mediump mat3 c;                     \n"
2158			   "   mediump float d[2];                 \n"
2159			   "};                             \n"
2160			   "struct UU {                    \n"
2161			   "   U a;                        \n"
2162			   "   U b[2];                     \n"
2163			   "   uvec2 c;                    \n"
2164			   "};                             \n"
2165			   ""
2166			   "layout(binding=4) buffer TrickyBuffer {          \n"
2167			   "   UU a[3];                                      \n"
2168			   "   mediump mat4 b;                               \n"
2169			   "   uint c;                                       \n"
2170			   "} e[2];                                          \n"
2171			   ""
2172			   "layout(binding = 0) buffer SimpleBuffer {                \n"
2173			   "   mediump mat3x2 a;                                     \n"
2174			   "   mediump mat4 b;                                       \n"
2175			   "   mediump vec4 c;                                       \n"
2176			   "};                                                       \n"
2177			   ""
2178			   "layout(binding = 1) buffer NotSoSimpleBuffer {           \n"
2179			   "   ivec2 a[4];                                           \n"
2180			   "   mediump mat3 b[2];                                    \n"
2181			   "   mediump mat2 c;                                       \n"
2182			   "} d;                                                     \n"
2183			   ""
2184			   "void main() {                                    \n"
2185			   "    mediump float tmp;                           \n"
2186			   "    mediump float tmp2;                          \n"
2187			   "    tmp = e[0].a[0].b[0].d[0] * float(e[1].c);   \n"
2188			   "    tmp2 = a[0][0] * b[0][0] * c.x;                                \n"
2189			   "    tmp2 = tmp2 + float(d.a[0].y) + d.b[0][0][0] + d.c[0][0];      \n"
2190			   "    g_out.data = vec4(0, 1, 0, 1) * tmp * tmp2;                    \n"
2191			   "}";
2192	}
2193
2194	virtual long Run()
2195	{
2196		GLuint program = CreateComputeProgram(ComputeShader());
2197		glLinkProgram(program);
2198		if (!CheckProgram(program))
2199		{
2200			glDeleteProgram(program);
2201			return ERROR;
2202		}
2203		glUseProgram(program);
2204
2205		long error = NO_ERROR;
2206
2207		GLint res;
2208		VerifyGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_MAX_NAME_LENGTH, 28, error);
2209		glGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_ACTIVE_RESOURCES, &res);
2210		if (res < 7)
2211		{
2212			m_context.getTestContext().getLog()
2213				<< tcu::TestLog::Message
2214				<< "Error on: glGetProgramInterfaceiv, if: GL_BUFFER_VARIABLE, param: GL_ACTIVE_RESOURCES\n"
2215				<< "Expected value greater or equal to 7, got " << res << tcu::TestLog::EndMessage;
2216			glDeleteProgram(program);
2217			return ERROR;
2218		}
2219		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, 5, error);
2220		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, 18, error);
2221
2222		std::map<std::string, GLuint> indicesSSB;
2223		std::map<std::string, GLuint> indicesBV;
2224		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "SimpleBuffer", error);
2225		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "NotSoSimpleBuffer", error);
2226		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "TrickyBuffer", error);
2227		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "TrickyBuffer[1]", error);
2228		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "a", error);
2229		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "b", error);
2230		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "c", error);
2231		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "NotSoSimpleBuffer.a[0]", error);
2232		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "NotSoSimpleBuffer.c", error);
2233		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "NotSoSimpleBuffer.b[0]", error);
2234		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "TrickyBuffer.a[0].b[0].d", error);
2235		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "TrickyBuffer.b", error);
2236		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "TrickyBuffer.c", error);
2237
2238		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["SimpleBuffer"], "SimpleBuffer",
2239									 error);
2240		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["NotSoSimpleBuffer"],
2241									 "NotSoSimpleBuffer", error);
2242		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["TrickyBuffer"], "TrickyBuffer[0]",
2243									 error);
2244		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["TrickyBuffer[1]"], "TrickyBuffer[1]",
2245									 error);
2246		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["a"], "a", error);
2247		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["b"], "b", error);
2248		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["c"], "c", error);
2249		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["NotSoSimpleBuffer.a[0]"],
2250									 "NotSoSimpleBuffer.a[0]", error);
2251		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["NotSoSimpleBuffer.c"],
2252									 "NotSoSimpleBuffer.c", error);
2253		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["NotSoSimpleBuffer.b[0]"],
2254									 "NotSoSimpleBuffer.b[0]", error);
2255		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["TrickyBuffer.a[0].b[0].d"],
2256									 "TrickyBuffer.a[0].b[0].d[0]", error);
2257		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["TrickyBuffer.b"], "TrickyBuffer.b", error);
2258		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["TrickyBuffer.c"], "TrickyBuffer.c", error);
2259
2260		GLenum props[] = { GL_NAME_LENGTH,
2261						   GL_BUFFER_BINDING,
2262						   GL_NUM_ACTIVE_VARIABLES,
2263						   GL_REFERENCED_BY_COMPUTE_SHADER,
2264						   GL_REFERENCED_BY_FRAGMENT_SHADER,
2265						   GL_REFERENCED_BY_VERTEX_SHADER };
2266		GLint expected[] = { 13, 0, 3, 1, 0, 0 };
2267		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["SimpleBuffer"], 6, props, 6, expected,
2268								   error);
2269		GLenum props2[] = { GL_NAME_LENGTH, GL_BUFFER_BINDING, GL_REFERENCED_BY_COMPUTE_SHADER,
2270							GL_REFERENCED_BY_FRAGMENT_SHADER, GL_REFERENCED_BY_VERTEX_SHADER };
2271		GLint expected2[] = { 18, 1, 1, 0, 0 };
2272		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["NotSoSimpleBuffer"], 5, props2, 5,
2273								   expected2, error);
2274		GLint expected3[] = { 16, 4, 1, 0, 0 };
2275		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["TrickyBuffer"], 5, props2, 5,
2276								   expected3, error);
2277		GLint expected4[] = { 16, 5, 1, 0, 0 };
2278		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["TrickyBuffer[1]"], 5, props2, 5,
2279								   expected4, error);
2280
2281		GLenum props3[] = { GL_NAME_LENGTH,
2282							GL_TYPE,
2283							GL_ARRAY_SIZE,
2284							GL_BLOCK_INDEX,
2285							GL_ARRAY_STRIDE,
2286							GL_IS_ROW_MAJOR,
2287							GL_REFERENCED_BY_COMPUTE_SHADER,
2288							GL_REFERENCED_BY_FRAGMENT_SHADER,
2289							GL_REFERENCED_BY_VERTEX_SHADER,
2290							GL_TOP_LEVEL_ARRAY_SIZE,
2291							GL_TOP_LEVEL_ARRAY_STRIDE };
2292		GLint expected5[] = { 2, 35687, 1, static_cast<GLint>(indicesSSB["SimpleBuffer"]), 0, 0, 1, 0, 0, 1, 0 };
2293		VerifyGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["a"], 11, props3, 11, expected5, error);
2294		GLenum props4[] = { GL_NAME_LENGTH,
2295							GL_TYPE,
2296							GL_ARRAY_SIZE,
2297							GL_BLOCK_INDEX,
2298							GL_MATRIX_STRIDE,
2299							GL_IS_ROW_MAJOR,
2300							GL_REFERENCED_BY_COMPUTE_SHADER,
2301							GL_REFERENCED_BY_FRAGMENT_SHADER,
2302							GL_REFERENCED_BY_VERTEX_SHADER,
2303							GL_TOP_LEVEL_ARRAY_SIZE };
2304		GLint expected6[] = { 28, 5126, 2, static_cast<GLint>(indicesSSB["TrickyBuffer"]), 0, 0, 1, 0, 0, 3 };
2305		VerifyGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["TrickyBuffer.a[0].b[0].d"], 10, props4, 10,
2306								   expected6, error);
2307
2308		GLenum			 prop	= GL_ACTIVE_VARIABLES;
2309		const GLsizei	bufSize = 1000;
2310		GLsizei			 length;
2311		GLint			 param[bufSize];
2312		std::set<GLuint> exp;
2313		exp.insert(indicesBV["a"]);
2314		exp.insert(indicesBV["b"]);
2315		exp.insert(indicesBV["c"]);
2316		glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["SimpleBuffer"], 1, &prop, bufSize, &length,
2317							   param);
2318		for (int i = 0; i < length; ++i)
2319		{
2320			if (exp.find(param[i]) == exp.end())
2321			{
2322				m_context.getTestContext().getLog()
2323					<< tcu::TestLog::Message
2324					<< "Unexpected index found in active variables of SimpleBuffer: " << param[i]
2325					<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: "
2326					   "GL_SHADER_STORAGE_BLOCK"
2327					<< tcu::TestLog::EndMessage;
2328				glDeleteProgram(program);
2329				return ERROR;
2330			}
2331			else if (length != 3)
2332			{
2333				m_context.getTestContext().getLog()
2334					<< tcu::TestLog::Message
2335					<< "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_SHADER_STORAGE_BLOCK"
2336					<< "Expected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
2337				glDeleteProgram(program);
2338				return ERROR;
2339			}
2340		}
2341		std::set<GLuint> exp2;
2342		exp2.insert(indicesBV["NotSoSimpleBuffer.a[0]"]);
2343		exp2.insert(indicesBV["NotSoSimpleBuffer.b[0]"]);
2344		exp2.insert(indicesBV["NotSoSimpleBuffer.c"]);
2345		glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["NotSoSimpleBuffer"], 1, &prop, bufSize,
2346							   &length, param);
2347		for (int i = 0; i < length; ++i)
2348		{
2349			if (exp2.find(param[i]) == exp2.end())
2350			{
2351				m_context.getTestContext().getLog()
2352					<< tcu::TestLog::Message
2353					<< "Unexpected index found in active variables of NotSoSimpleBuffer: " << param[i]
2354					<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: "
2355					   "GL_SHADER_STORAGE_BLOCK"
2356					<< tcu::TestLog::EndMessage;
2357				glDeleteProgram(program);
2358				return ERROR;
2359			}
2360			else if (length != 3)
2361			{
2362				m_context.getTestContext().getLog()
2363					<< tcu::TestLog::Message
2364					<< "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_SHADER_STORAGE_BLOCK"
2365					<< param[i] << "\nExpected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
2366				glDeleteProgram(program);
2367				return ERROR;
2368			}
2369		}
2370
2371		glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &res);
2372		if (res < 3)
2373		{
2374			m_context.getTestContext().getLog()
2375				<< tcu::TestLog::Message << "Value of GL_MAX_NUM_ACTIVE_VARIABLES less than 3!\n"
2376				<< "Call: glGetProgramInterfaceiv, interface: GL_SHADER_STORAGE_BLOCK" << tcu::TestLog::EndMessage;
2377			return ERROR;
2378		}
2379
2380		glDeleteProgram(program);
2381		return error;
2382	}
2383};
2384
2385class NullLength : public SimpleShaders
2386{
2387
2388	virtual std::string Title()
2389	{
2390		return "NULL Length Test";
2391	}
2392
2393	virtual std::string PurposeExt()
2394	{
2395		return "\n\n Purpose is to verify that GetProgramResourceName with null length doesn't return length (doesn't "
2396			   "crash).\n";
2397	}
2398
2399	virtual std::string VertexShader()
2400	{
2401		return "#version 310 es                      \n"
2402			   "in vec4 position;                    \n"
2403			   "void main(void)                      \n"
2404			   "{                                    \n"
2405			   "    gl_Position = position;          \n"
2406			   "}";
2407	}
2408
2409	virtual std::string FragmentShader()
2410	{
2411		return "#version 310 es                \n"
2412			   "out mediump vec4 color;                \n"
2413			   "void main() {                  \n"
2414			   "    color = vec4(0, 1, 0, 1);  \n"
2415			   "}";
2416	}
2417
2418	virtual long Run()
2419	{
2420		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2421		glBindAttribLocation(program, 0, "position");
2422		LinkProgram(program);
2423
2424		GLchar name[1024] = { '\0' };
2425		GLuint index	  = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "color");
2426		GLenum prop		  = GL_ARRAY_SIZE;
2427		GLint  res;
2428		glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, 0, 1024, NULL, name);
2429		glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, 1, &prop, 1, NULL, &res);
2430
2431		std::string expected = "color";
2432		if (name != expected)
2433		{
2434			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Expected name: " << expected
2435												<< ", got: " << name << tcu::TestLog::EndMessage;
2436			glDeleteProgram(program);
2437			return ERROR;
2438		}
2439		else if (res != 1)
2440		{
2441			m_context.getTestContext().getLog()
2442				<< tcu::TestLog::Message << "Expected array_size: 1, got: " << res << tcu::TestLog::EndMessage;
2443			glDeleteProgram(program);
2444			return ERROR;
2445		}
2446
2447		glDeleteProgram(program);
2448		return NO_ERROR;
2449	}
2450};
2451
2452class ArraysOfArrays : public SimpleShaders
2453{
2454
2455	virtual std::string Title()
2456	{
2457		return "Arrays Of Arrays Test";
2458	}
2459
2460	virtual std::string ShadersDesc()
2461	{
2462		return "fallthrough fragment and vertex shaders with multi dimensional uniform array used";
2463	}
2464
2465	virtual std::string PurposeExt()
2466	{
2467		return "\n\n Purpose is to verify that feature works correctly with arrays_of_arrays feature.\n";
2468	}
2469
2470	virtual std::string VertexShader()
2471	{
2472		return "#version 310 es                      \n"
2473			   "in vec4 position;                    \n"
2474			   "uniform mediump vec4 a[3][4][5];             \n"
2475			   "void main(void)                      \n"
2476			   "{                                                 \n"
2477			   "    gl_Position = position + a[2][1][0];          \n"
2478			   "}";
2479	}
2480
2481	virtual std::string FragmentShader()
2482	{
2483		return "#version 310 es                \n"
2484			   "out mediump vec4 color;                \n"
2485			   "void main() {                  \n"
2486			   "    color = vec4(0, 1, 0, 1);  \n"
2487			   "}";
2488	}
2489
2490	virtual long Run()
2491	{
2492		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2493		glBindAttribLocation(program, 0, "position");
2494		LinkProgram(program);
2495
2496		long error = NO_ERROR;
2497
2498		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, 11, error);
2499
2500		std::map<std::string, GLuint> indices;
2501		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "a[2][1]", error);
2502		VerifyGetProgramResourceIndex(program, GL_UNIFORM, "a[2][1][0]", indices["a[2][1]"], error);
2503
2504		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["a[2][1]"], "a[2][1][0]", error);
2505
2506		GLenum props[] = { GL_NAME_LENGTH,
2507						   GL_TYPE,
2508						   GL_ARRAY_SIZE,
2509						   GL_OFFSET,
2510						   GL_BLOCK_INDEX,
2511						   GL_ARRAY_STRIDE,
2512						   GL_MATRIX_STRIDE,
2513						   GL_IS_ROW_MAJOR,
2514						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
2515						   GL_REFERENCED_BY_COMPUTE_SHADER,
2516						   GL_REFERENCED_BY_FRAGMENT_SHADER,
2517						   GL_REFERENCED_BY_VERTEX_SHADER,
2518						   GL_LOCATION };
2519		GLint expected[] = { 11, 35666, 5, -1, -1, -1, -1, 0, -1, 0, 0, 1, glGetUniformLocation(program, "a[2][1]") };
2520		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["a[2][1]"], 13, props, 13, expected, error);
2521
2522		glDeleteProgram(program);
2523		return error;
2524	}
2525};
2526
2527class TopLevelArray : public ComputeShaderTest
2528{
2529
2530	virtual std::string Title()
2531	{
2532		return "Top Level Array Test";
2533	}
2534
2535	virtual std::string ShadersDesc()
2536	{
2537		return "compute shader with multi dimensional array used inside storage block";
2538	}
2539
2540	virtual std::string PurposeExt()
2541	{
2542		return "\n\n Purpose is to verify that feature works correctly when querying for GL_TOP_LEVEL_ARRAY_SIZE\n"
2543			   " and GL_TOP_LEVEL_ARRAY_STRIDE.\n";
2544	}
2545
2546	virtual std::string ComputeShader()
2547	{
2548		return "layout(local_size_x = 1, local_size_y = 1) in; \n"
2549			   "layout(std430) buffer Outp {                   \n"
2550			   "   mediump vec4 d;                             \n"
2551			   "} g_out;                                       \n"
2552			   ""
2553			   "buffer Block {                       \n"
2554			   "   mediump vec4 a[5][4][3];          \n"
2555			   "};                                   \n"
2556			   ""
2557			   "void main(void)                      \n"
2558			   "{                                    \n"
2559			   "    g_out.d = a[0][0][0];            \n"
2560			   "}";
2561	}
2562
2563	virtual long Run()
2564	{
2565		GLuint program = CreateComputeProgram(ComputeShader());
2566		glLinkProgram(program);
2567		if (!CheckProgram(program))
2568		{
2569			glDeleteProgram(program);
2570			return ERROR;
2571		}
2572		glUseProgram(program);
2573
2574		long error = NO_ERROR;
2575
2576		VerifyGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_MAX_NAME_LENGTH, 11, error);
2577		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, 6, error);
2578		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, 2, error);
2579
2580		std::map<std::string, GLuint> indicesSSB;
2581		std::map<std::string, GLuint> indicesBV;
2582		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "a[0][0]", error);
2583		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "Block", error);
2584
2585		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["a[0][0]"], "a[0][0][0]", error);
2586		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["Block"], "Block", error);
2587
2588		GLenum props3[] = { GL_NAME_LENGTH,
2589							GL_TYPE,
2590							GL_ARRAY_SIZE,
2591							GL_BLOCK_INDEX,
2592							GL_IS_ROW_MAJOR,
2593							GL_REFERENCED_BY_COMPUTE_SHADER,
2594							GL_REFERENCED_BY_FRAGMENT_SHADER,
2595							GL_REFERENCED_BY_VERTEX_SHADER,
2596							GL_TOP_LEVEL_ARRAY_SIZE };
2597		GLint expected5[] = { 11, 35666, 3, static_cast<GLint>(indicesSSB["Block"]), 0, 1, 0, 0, 5 };
2598		VerifyGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["a[0][0]"], 9, props3, 9, expected5, error);
2599
2600		GLenum  prop = GL_TOP_LEVEL_ARRAY_STRIDE;
2601		GLsizei len;
2602		GLint   res;
2603		glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["a[0][0]"], 1, &prop, 1024, &len, &res);
2604		if (res <= 0)
2605		{
2606			m_context.getTestContext().getLog()
2607				<< tcu::TestLog::Message
2608				<< "Call: glGetProgramResourceiv, interface: GL_BUFFER_VARIABLE, param: GL_TOP_LEVEL_ARRAY_STRIDE\n"
2609				<< "Expected value greater than 0, got: " << res << tcu::TestLog::EndMessage;
2610			glDeleteProgram(program);
2611			return ERROR;
2612		}
2613
2614		glDeleteProgram(program);
2615		return error;
2616	}
2617};
2618
2619class SeparateProgramsVertex : public SimpleShaders
2620{
2621public:
2622	virtual std::string Title()
2623	{
2624		return "Separate Program Vertex Shader Test";
2625	}
2626
2627	virtual std::string ShadersDesc()
2628	{
2629		return "vertex shader as separate shader object";
2630	}
2631
2632	virtual std::string PurposeExt()
2633	{
2634		return "\n\n Purpose is to verify that feature works correctly when using separate_shader_objects "
2635			   "functionality.\n";
2636	}
2637
2638	virtual GLuint CreateShaderProgram(GLenum type, GLsizei count, const GLchar** strings)
2639	{
2640		GLuint program = glCreateShaderProgramv(type, count, strings);
2641		GLint  status  = GL_TRUE;
2642		glGetProgramiv(program, GL_LINK_STATUS, &status);
2643		if (status == GL_FALSE)
2644		{
2645			GLsizei length;
2646			GLchar  log[1024];
2647			glGetProgramInfoLog(program, sizeof(log), &length, log);
2648			if (length > 1)
2649			{
2650				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
2651													<< log << tcu::TestLog::EndMessage;
2652			}
2653		}
2654		return program;
2655	}
2656
2657	virtual long Run()
2658	{
2659		long error = NO_ERROR;
2660
2661		const char* srcVS = "#version 310 es                            \n"
2662							"layout(location = 0) in vec4 in_vertex;    \n"
2663							""
2664							"out mediump float r, g, b;                           \n"
2665							"out mediump vec4 iLikePie;                           \n"
2666							""
2667							"uniform mediump float u;                           \n"
2668							"uniform mediump vec4 v;                            \n"
2669							""
2670							"void main() {                     \n"
2671							"  gl_Position = in_vertex;        \n"
2672							"  r = u;                          \n"
2673							"  g = 0.0;                        \n"
2674							"  b = 0.0;                        \n"
2675							"  iLikePie = v;                   \n"
2676							"}";
2677
2678		const GLuint vs = CreateShaderProgram(GL_VERTEX_SHADER, 1, &srcVS);
2679
2680		VerifyGetProgramInterfaceiv(vs, GL_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
2681		VerifyGetProgramInterfaceiv(vs, GL_UNIFORM, GL_ACTIVE_RESOURCES, 2, error);
2682		VerifyGetProgramInterfaceiv(vs, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 10, error);
2683		VerifyGetProgramInterfaceiv(vs, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
2684		VerifyGetProgramInterfaceiv(vs, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 12, error);
2685		VerifyGetProgramInterfaceiv(vs, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 5, error);
2686
2687		std::map<std::string, GLuint> indicesU;
2688		std::map<std::string, GLuint> indicesI;
2689		std::map<std::string, GLuint> indicesO;
2690		VerifyGetProgramResourceIndex(vs, GL_UNIFORM, indicesU, "u", error);
2691		VerifyGetProgramResourceIndex(vs, GL_UNIFORM, indicesU, "v", error);
2692		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_INPUT, indicesI, "in_vertex", error);
2693		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "r", error);
2694		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "g", error);
2695		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "b", error);
2696		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "iLikePie", error);
2697		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "gl_Position", error);
2698
2699		VerifyGetProgramResourceName(vs, GL_UNIFORM, indicesU["u"], "u", error);
2700		VerifyGetProgramResourceName(vs, GL_UNIFORM, indicesU["v"], "v", error);
2701		VerifyGetProgramResourceName(vs, GL_PROGRAM_INPUT, indicesI["in_vertex"], "in_vertex", error);
2702		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["r"], "r", error);
2703		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["g"], "g", error);
2704		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["b"], "b", error);
2705		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["iLikePie"], "iLikePie", error);
2706		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["gl_Position"], "gl_Position", error);
2707
2708		VerifyGetProgramResourceLocation(vs, GL_UNIFORM, "u", glGetUniformLocation(vs, "u"), error);
2709		VerifyGetProgramResourceLocation(vs, GL_UNIFORM, "v", glGetUniformLocation(vs, "v"), error);
2710		VerifyGetProgramResourceLocation(vs, GL_PROGRAM_INPUT, "in_vertex", 0, error);
2711
2712		GLenum props[] = { GL_NAME_LENGTH,
2713						   GL_TYPE,
2714						   GL_ARRAY_SIZE,
2715						   GL_OFFSET,
2716						   GL_BLOCK_INDEX,
2717						   GL_ARRAY_STRIDE,
2718						   GL_MATRIX_STRIDE,
2719						   GL_IS_ROW_MAJOR,
2720						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
2721						   GL_REFERENCED_BY_COMPUTE_SHADER,
2722						   GL_REFERENCED_BY_FRAGMENT_SHADER,
2723						   GL_REFERENCED_BY_VERTEX_SHADER,
2724						   GL_LOCATION };
2725		GLint expected[] = { 2, 35666, 1, -1, -1, -1, -1, 0, -1, 0, 0, 1, glGetUniformLocation(vs, "v") };
2726		VerifyGetProgramResourceiv(vs, GL_UNIFORM, indicesU["v"], 13, props, 13, expected, error);
2727
2728		GLenum props2[] = { GL_NAME_LENGTH,
2729							GL_TYPE,
2730							GL_ARRAY_SIZE,
2731							GL_REFERENCED_BY_COMPUTE_SHADER,
2732							GL_REFERENCED_BY_FRAGMENT_SHADER,
2733							GL_REFERENCED_BY_VERTEX_SHADER,
2734							GL_LOCATION };
2735		GLint expected2[] = { 10, 35666, 1, 0, 0, 1, 0 };
2736		VerifyGetProgramResourceiv(vs, GL_PROGRAM_INPUT, indicesI["in_vertex"], 7, props2, 7, expected2, error);
2737
2738		GLenum props3[] = { GL_NAME_LENGTH,
2739							GL_TYPE,
2740							GL_ARRAY_SIZE,
2741							GL_REFERENCED_BY_COMPUTE_SHADER,
2742							GL_REFERENCED_BY_FRAGMENT_SHADER,
2743							GL_REFERENCED_BY_VERTEX_SHADER };
2744		GLint expected3[] = { 9, 35666, 1, 0, 0, 1 };
2745		VerifyGetProgramResourceiv(vs, GL_PROGRAM_OUTPUT, indicesO["iLikePie"], 6, props3, 6, expected3, error);
2746
2747		glDeleteProgram(vs);
2748		return error;
2749	}
2750};
2751
2752class SeparateProgramsFragment : public SeparateProgramsVertex
2753{
2754
2755	virtual std::string Title()
2756	{
2757		return "Separate Program Fragment Shader Test";
2758	}
2759
2760	virtual std::string ShadersDesc()
2761	{
2762		return "fragment shader as separate shader object";
2763	}
2764
2765	virtual long Run()
2766	{
2767		long error = NO_ERROR;
2768
2769		const char* srcTCS = "#version 310 es                                  \n"
2770							 "out mediump vec4 fs_color;                       \n"
2771							 ""
2772							 "layout(location = 1) uniform mediump vec4 x;     \n"
2773							 ""
2774							 "in mediump vec4 vs_color;                        \n"
2775							 "void main() {                                    \n"
2776							 "   fs_color = vs_color + x;                      \n"
2777							 "}";
2778
2779		const GLuint tcs = CreateShaderProgram(GL_FRAGMENT_SHADER, 1, &srcTCS);
2780
2781		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 9, error);
2782		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
2783		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 9, error);
2784		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 1, error);
2785		VerifyGetProgramInterfaceiv(tcs, GL_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
2786		VerifyGetProgramInterfaceiv(tcs, GL_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
2787
2788		std::map<std::string, GLuint> indicesI;
2789		std::map<std::string, GLuint> indicesO;
2790		std::map<std::string, GLuint> indicesU;
2791		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_INPUT, indicesI, "vs_color", error);
2792		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_OUTPUT, indicesO, "fs_color", error);
2793		VerifyGetProgramResourceIndex(tcs, GL_UNIFORM, indicesU, "x", error);
2794
2795		VerifyGetProgramResourceName(tcs, GL_PROGRAM_INPUT, indicesI["vs_color"], "vs_color", error);
2796		VerifyGetProgramResourceName(tcs, GL_PROGRAM_OUTPUT, indicesO["fs_color"], "fs_color", error);
2797		VerifyGetProgramResourceName(tcs, GL_UNIFORM, indicesU["x"], "x", error);
2798
2799		VerifyGetProgramResourceLocation(tcs, GL_UNIFORM, "x", 1, error);
2800
2801		GLenum props2[] = { GL_NAME_LENGTH,
2802							GL_TYPE,
2803							GL_ARRAY_SIZE,
2804							GL_REFERENCED_BY_COMPUTE_SHADER,
2805							GL_REFERENCED_BY_FRAGMENT_SHADER,
2806							GL_REFERENCED_BY_VERTEX_SHADER };
2807		GLint expected2[] = { 9, 35666, 1, 0, 1, 0 };
2808		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_INPUT, indicesI["vs_color"], 6, props2, 6, expected2, error);
2809		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_OUTPUT, indicesO["fs_color"], 6, props2, 6, expected2, error);
2810
2811		GLenum props[] = { GL_NAME_LENGTH,
2812						   GL_TYPE,
2813						   GL_ARRAY_SIZE,
2814						   GL_OFFSET,
2815						   GL_BLOCK_INDEX,
2816						   GL_ARRAY_STRIDE,
2817						   GL_MATRIX_STRIDE,
2818						   GL_IS_ROW_MAJOR,
2819						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
2820						   GL_REFERENCED_BY_COMPUTE_SHADER,
2821						   GL_REFERENCED_BY_FRAGMENT_SHADER,
2822						   GL_REFERENCED_BY_VERTEX_SHADER,
2823						   GL_LOCATION };
2824		GLint expected[] = { 2, 35666, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 1 };
2825		VerifyGetProgramResourceiv(tcs, GL_UNIFORM, indicesU["x"], 13, props, 13, expected, error);
2826
2827		glDeleteProgram(tcs);
2828		return error;
2829	}
2830};
2831
2832class UniformBlockAdvanced : public SimpleShaders
2833{
2834	virtual std::string Title()
2835	{
2836		return "Uniform Block Advanced Test";
2837	}
2838
2839	virtual std::string ShadersDesc()
2840	{
2841		return "fallthrough fragment and vertex shaders with different types of uniform blocks used";
2842	}
2843
2844	virtual std::string PurposeExt()
2845	{
2846		return "\n\n Purpose is to verify calls using GL_UNIFORM_BLOCK as an interface param and\n"
2847			   "verify results of querying offset, strides and row order.\n";
2848	}
2849
2850	virtual std::string VertexShader()
2851	{
2852		return "#version 310 es                      \n"
2853			   "in vec4 position;                    \n"
2854			   ""
2855			   "layout(row_major) uniform SimpleBlock {   \n"
2856			   "   mat4 a;                                \n"
2857			   "   vec4 b[10];                            \n"
2858			   "};                                        \n"
2859			   ""
2860			   "void main(void)                      \n"
2861			   "{                                    \n"
2862			   "    float tmp;                       \n"
2863			   "    tmp = a[0][0] + b[0].x;          \n"
2864			   "    gl_Position = position * tmp;    \n"
2865			   "}";
2866	}
2867
2868	virtual long Run()
2869	{
2870		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2871		glBindAttribLocation(program, 0, "position");
2872		LinkProgram(program);
2873
2874		long error = NO_ERROR;
2875
2876		std::map<std::string, GLuint> indicesU;
2877		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
2878		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
2879
2880		GLenum props[]	= { GL_IS_ROW_MAJOR };
2881		GLint  expected[] = { 1 };
2882		VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, props, 1, expected, error);
2883
2884		GLenum  prop = GL_MATRIX_STRIDE;
2885		GLsizei len;
2886		GLint   res;
2887		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, 1024, &len, &res);
2888		if (res < 1)
2889		{
2890			m_context.getTestContext().getLog()
2891				<< tcu::TestLog::Message
2892				<< "ERROR: glGetProgramResourceiv, interface GL_UNIFORM, prop GL_MATRIX_STRIDE\n"
2893				<< "Expected value greater than 0, got " << res << tcu::TestLog::EndMessage;
2894		}
2895		prop = GL_OFFSET;
2896		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, 1024, &len, &res);
2897		if (res < 0)
2898		{
2899			m_context.getTestContext().getLog()
2900				<< tcu::TestLog::Message << "ERROR: glGetProgramResourceiv, interface GL_UNIFORM, prop GL_OFFSET\n"
2901				<< "Expected value not less than 0, got " << res << tcu::TestLog::EndMessage;
2902		}
2903		prop = GL_ARRAY_STRIDE;
2904		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, 1024, &len, &res);
2905		if (res < 1)
2906		{
2907			m_context.getTestContext().getLog()
2908				<< tcu::TestLog::Message
2909				<< "ERROR: glGetProgramResourceiv, interface GL_UNIFORM, prop GL_ARRAY_STRIDE\n"
2910				<< "Expected value greater than 0, got " << res << tcu::TestLog::EndMessage;
2911		}
2912
2913		glDeleteProgram(program);
2914		return error;
2915	}
2916};
2917
2918class ArrayNames : public SimpleShaders
2919{
2920
2921	virtual std::string Title()
2922	{
2923		return "Array Names Test";
2924	}
2925
2926	virtual std::string ShadersDesc()
2927	{
2928		return "fallthrough fragment shader and a vertex shader with array of vec4 uniform used";
2929	}
2930
2931	virtual std::string PurposeExt()
2932	{
2933		return "\n\n Purpose is to verify that GetProgramResourceLocation match "
2934			   "name strings correctly.\n";
2935	}
2936
2937	virtual std::string VertexShader()
2938	{
2939		return "#version 310 es                      \n"
2940			   "in vec4 position;                    \n"
2941			   ""
2942			   "uniform mediump vec4 a[2];           \n"
2943			   ""
2944			   "void main(void)                            \n"
2945			   "{                                          \n"
2946			   "    gl_Position = position + a[0] + a[1];  \n"
2947			   "}";
2948	}
2949
2950	virtual long Run()
2951	{
2952		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2953		glBindAttribLocation(program, 0, "position");
2954		LinkProgram(program);
2955
2956		long error = NO_ERROR;
2957
2958		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", glGetUniformLocation(program, "a"), error);
2959		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[0]", glGetUniformLocation(program, "a"), error);
2960		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[1]", glGetUniformLocation(program, "a[1]"), error);
2961		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[2]", -1, error);
2962		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[0 + 0]", -1, error);
2963		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[0+0]", -1, error);
2964		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[ 0]", -1, error);
2965		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[0 ]", -1, error);
2966		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[\n0]", -1, error);
2967		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[\t0]", -1, error);
2968		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[01]", -1, error);
2969		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[00]", -1, error);
2970
2971		glDeleteProgram(program);
2972		return error;
2973	}
2974};
2975
2976class BuffLength : public SimpleShaders
2977{
2978
2979	virtual std::string Title()
2980	{
2981		return "Buff Length Test";
2982	}
2983
2984	virtual std::string ShadersDesc()
2985	{
2986		return "fallthrough fragment shader and vertex with uniform of vec4 type used";
2987	}
2988
2989	virtual std::string PurposeExt()
2990	{
2991		return "\n\n Purpose is to verify that bufsize of GetProgramResourceName and "
2992			   "GetProgramResourceiv is respected.\n";
2993	}
2994
2995	virtual std::string VertexShader()
2996	{
2997		return "#version 310 es                      \n"
2998			   "in vec4 position;                    \n"
2999			   ""
3000			   "uniform mediump vec4 someLongName;         \n"
3001			   ""
3002			   "void main(void)                            \n"
3003			   "{                                          \n"
3004			   "    gl_Position = position + someLongName; \n"
3005			   "}";
3006	}
3007
3008	virtual long Run()
3009	{
3010		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3011		glBindAttribLocation(program, 0, "position");
3012		LinkProgram(program);
3013
3014		long error = NO_ERROR;
3015
3016		GLuint  index = glGetProgramResourceIndex(program, GL_UNIFORM, "someLongName");
3017		GLsizei length;
3018		GLchar  buff[3] = { 'a', 'b', 'c' };
3019		glGetProgramResourceName(program, GL_UNIFORM, index, 0, NULL, NULL);
3020		glGetProgramResourceName(program, GL_UNIFORM, index, 0, NULL, buff);
3021		if (buff[0] != 'a' || buff[1] != 'b' || buff[2] != 'c')
3022		{
3023			m_context.getTestContext().getLog()
3024				<< tcu::TestLog::Message << "ERROR: buff has changed" << tcu::TestLog::EndMessage;
3025			error = ERROR;
3026		}
3027		glGetProgramResourceName(program, GL_UNIFORM, index, 2, &length, buff);
3028		if (buff[0] != 's' || buff[1] != '\0' || buff[2] != 'c')
3029		{
3030			m_context.getTestContext().getLog()
3031				<< tcu::TestLog::Message << "ERROR: buff different then expected" << tcu::TestLog::EndMessage;
3032			error = ERROR;
3033		}
3034		if (length != 1)
3035		{
3036			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: incorrect length, expected 1, got "
3037												<< length << tcu::TestLog::EndMessage;
3038			error = ERROR;
3039		}
3040
3041		GLint  params[3] = { 1, 2, 3 };
3042		GLenum props[]   = { GL_NAME_LENGTH,
3043						   GL_TYPE,
3044						   GL_ARRAY_SIZE,
3045						   GL_OFFSET,
3046						   GL_BLOCK_INDEX,
3047						   GL_ARRAY_STRIDE,
3048						   GL_MATRIX_STRIDE,
3049						   GL_IS_ROW_MAJOR,
3050						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
3051						   GL_REFERENCED_BY_COMPUTE_SHADER,
3052						   GL_REFERENCED_BY_FRAGMENT_SHADER,
3053						   GL_REFERENCED_BY_VERTEX_SHADER,
3054						   GL_LOCATION };
3055		glGetProgramResourceiv(program, GL_UNIFORM, index, 13, props, 0, NULL, NULL);
3056		glGetProgramResourceiv(program, GL_UNIFORM, index, 13, props, 0, NULL, params);
3057		if (params[0] != 1 || params[1] != 2 || params[2] != 3)
3058		{
3059			m_context.getTestContext().getLog()
3060				<< tcu::TestLog::Message << "ERROR: params has changed" << tcu::TestLog::EndMessage;
3061			error = ERROR;
3062		}
3063		glGetProgramResourceiv(program, GL_UNIFORM, index, 13, props, 2, &length, params);
3064		if (params[0] != 13 || params[1] != 35666 || params[2] != 3)
3065		{
3066			m_context.getTestContext().getLog()
3067				<< tcu::TestLog::Message << "ERROR: params has incorrect values" << tcu::TestLog::EndMessage;
3068			error = ERROR;
3069		}
3070		if (length != 2)
3071		{
3072			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: incorrect length, expected 2, got "
3073												<< length << tcu::TestLog::EndMessage;
3074			error = ERROR;
3075		}
3076
3077		glDeleteProgram(program);
3078		return error;
3079	}
3080};
3081
3082class NoLocations : public SimpleShaders
3083{
3084
3085	virtual std::string Title()
3086	{
3087		return "No Locations Test";
3088	}
3089
3090	virtual std::string ShadersDesc()
3091	{
3092		return "fragment and vertex shaders with no locations set";
3093	}
3094
3095	virtual std::string VertexShader()
3096	{
3097		return "#version 310 es                      \n"
3098			   "in vec4 a;                           \n"
3099			   "in vec4 b;                           \n"
3100			   "in vec4 c;                           \n"
3101			   "in vec4 d;                           \n"
3102			   "void main(void)                      \n"
3103			   "{                                    \n"
3104			   "    gl_Position = a + b + c + d;     \n"
3105			   "}";
3106	}
3107
3108	// fragment shader outputs need an explicit location per spec
3109	virtual std::string FragmentShader()
3110	{
3111		return "#version 310 es                \n"
3112			   "layout (location=0) out mediump vec4 a;            \n"
3113			   "layout (location=1) out mediump vec4 b;            \n"
3114			   "layout (location=2) out mediump vec4 c;            \n"
3115			   "layout (location=3) out mediump vec4 d[1];         \n"
3116			   "void main() {                  \n"
3117			   "    a = vec4(0, 1, 0, 1);      \n"
3118			   "    b = vec4(0, 1, 0, 1);      \n"
3119			   "    c = vec4(0, 1, 0, 1);      \n"
3120			   "    d[0] = vec4(0, 1, 0, 1);   \n"
3121			   "}";
3122	}
3123
3124	virtual long Run()
3125	{
3126		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3127		glBindAttribLocation(program, 0, "position");
3128		glLinkProgram(program);
3129
3130		long error = NO_ERROR;
3131
3132		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 4, error);
3133		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 2, error);
3134		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 4, error);
3135		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 5, error);
3136
3137		std::map<std::string, GLuint> indicesI;
3138		std::map<std::string, GLuint> indicesO;
3139		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indicesI, "a", error);
3140		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indicesI, "b", error);
3141		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indicesI, "c", error);
3142		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indicesI, "d", error);
3143		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indicesO, "a", error);
3144		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indicesO, "b", error);
3145		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indicesO, "c", error);
3146		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indicesO, "d[0]", error);
3147
3148		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indicesI["a"], "a", error);
3149		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indicesI["b"], "b", error);
3150		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indicesI["c"], "c", error);
3151		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indicesI["d"], "d", error);
3152		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indicesO["a"], "a", error);
3153		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indicesO["b"], "b", error);
3154		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indicesO["c"], "c", error);
3155		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indicesO["d[0]"], "d[0]", error);
3156
3157		std::map<std::string, GLint> locationsI;
3158		std::map<std::string, GLint> locationsO;
3159		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, locationsI, "a", error);
3160		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, locationsI, "b", error);
3161		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, locationsI, "c", error);
3162		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, locationsI, "d", error);
3163		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, locationsO, "a", error);
3164		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, locationsO, "b", error);
3165		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, locationsO, "c", error);
3166		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, locationsO, "d[0]", error);
3167
3168		GLenum props[] = { GL_NAME_LENGTH,
3169						   GL_TYPE,
3170						   GL_ARRAY_SIZE,
3171						   GL_REFERENCED_BY_COMPUTE_SHADER,
3172						   GL_REFERENCED_BY_FRAGMENT_SHADER,
3173						   GL_REFERENCED_BY_VERTEX_SHADER };
3174		GLint expected[] = { 2, 35666, 1, 0, 0, 1 };
3175		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indicesI["a"], 6, props, 6, expected, error);
3176		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indicesI["b"], 6, props, 6, expected, error);
3177		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indicesI["d"], 6, props, 6, expected, error);
3178		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indicesI["c"], 6, props, 6, expected, error);
3179		GLint expected3[] = { 2, 35666, 1, 0, 1, 0 };
3180		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indicesO["a"], 6, props, 6, expected3, error);
3181		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indicesO["b"], 6, props, 6, expected3, error);
3182		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indicesO["c"], 6, props, 6, expected3, error);
3183		GLint expected4[] = { 5, 35666, 1, 0, 1, 0 };
3184		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indicesO["d[0]"], 6, props, 6, expected4, error);
3185
3186		glDeleteProgram(program);
3187		return error;
3188	}
3189};
3190
3191class OutputBuiltIn : public SimpleShaders
3192{
3193
3194	virtual std::string Title()
3195	{
3196		return "Output Built-ins Test";
3197	}
3198
3199	virtual std::string ShadersDesc()
3200	{
3201		return "fragment shader using built-in variables and a fallthrough vertex shader";
3202	}
3203
3204	virtual std::string Expectations()
3205	{
3206		return ".\n\n In this case we ask for information about built-in variables for the output interface.";
3207	}
3208
3209	virtual std::string FragmentShader()
3210	{
3211		return "#version 310 es                            \n"
3212			   "void main(void)                            \n"
3213			   "{                                          \n"
3214			   "    gl_FragDepth = 0.1;                    \n"
3215			   "}";
3216	}
3217
3218	virtual long Run()
3219	{
3220		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), true);
3221
3222		long error = NO_ERROR;
3223
3224		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 1, error);
3225		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 13, error);
3226
3227		std::map<std::string, GLuint> indices;
3228		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "gl_FragDepth", error);
3229
3230		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["gl_FragDepth"], "gl_FragDepth", error);
3231
3232		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "gl_FragDepth", -1, error);
3233
3234		GLenum props[] = { GL_NAME_LENGTH,
3235						   GL_TYPE,
3236						   GL_ARRAY_SIZE,
3237						   GL_REFERENCED_BY_COMPUTE_SHADER,
3238						   GL_REFERENCED_BY_FRAGMENT_SHADER,
3239						   GL_REFERENCED_BY_VERTEX_SHADER,
3240						   GL_LOCATION };
3241		GLint expected[] = { 13, 5126, 1, 0, 1, 0, -1 };
3242		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["gl_FragDepth"], DE_LENGTH_OF_ARRAY(props),
3243								   props, DE_LENGTH_OF_ARRAY(expected), expected, error);
3244
3245		glDeleteProgram(program);
3246		return error;
3247	}
3248};
3249
3250class QueryNotUsed : public SimpleShaders
3251{
3252
3253	virtual std::string Title()
3254	{
3255		return "Query Not Used Test";
3256	}
3257
3258	virtual std::string PassCriteria()
3259	{
3260		return "Data from queries matches the not used program.";
3261	}
3262
3263	virtual std::string Purpose()
3264	{
3265		return "Verify that program parameter works correctly and proper program is queried when different program is "
3266			   "used.";
3267	}
3268
3269	virtual std::string Method()
3270	{
3271		return "Create 2 programs, use one of them and query the other, verify the results.";
3272	}
3273
3274	virtual std::string VertexShader2()
3275	{
3276		return "#version 310 es                      \n"
3277			   "in mediump vec4 p;                   \n"
3278			   "void main(void)                      \n"
3279			   "{                                    \n"
3280			   "    gl_Position = p;                 \n"
3281			   "}";
3282	}
3283
3284	virtual std::string FragmentShader2()
3285	{
3286		return "#version 310 es                \n"
3287			   "out mediump vec4 c;            \n"
3288			   "void main() {                  \n"
3289			   "    c = vec4(0., 1., 0., 1.);  \n"
3290			   "}";
3291	}
3292
3293	virtual long Run()
3294	{
3295		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3296		LinkProgram(program);
3297
3298		GLuint program2 = CreateProgram(VertexShader2().c_str(), FragmentShader2().c_str(), false);
3299		LinkProgram(program2);
3300		glUseProgram(program2);
3301
3302		long error = NO_ERROR;
3303
3304		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
3305		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 9, error);
3306		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 1, error);
3307		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 6, error);
3308
3309		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "color", 0, error);
3310		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position", 0, error);
3311
3312		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, 0, "color", error);
3313		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, 0, "position", error);
3314
3315		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", 0, error);
3316		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
3317
3318		GLenum props[] = { GL_NAME_LENGTH,
3319						   GL_TYPE,
3320						   GL_ARRAY_SIZE,
3321						   GL_REFERENCED_BY_COMPUTE_SHADER,
3322						   GL_REFERENCED_BY_FRAGMENT_SHADER,
3323						   GL_REFERENCED_BY_VERTEX_SHADER,
3324						   GL_LOCATION };
3325		GLint expected[] = { 9, 35666, 1, 0, 0, 1, 0 };
3326		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, DE_LENGTH_OF_ARRAY(props), props,
3327								   DE_LENGTH_OF_ARRAY(expected), expected, error);
3328
3329		GLenum props2[] = { GL_NAME_LENGTH,
3330							GL_TYPE,
3331							GL_ARRAY_SIZE,
3332							GL_REFERENCED_BY_COMPUTE_SHADER,
3333							GL_REFERENCED_BY_FRAGMENT_SHADER,
3334							GL_REFERENCED_BY_VERTEX_SHADER,
3335							GL_LOCATION };
3336		GLint expected2[] = { 6, 35666, 1, 0, 1, 0, 0 };
3337		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 7, props2, 7, expected2, error);
3338
3339		glDeleteProgram(program);
3340		glDeleteProgram(program2);
3341		return error;
3342	}
3343};
3344
3345class RelinkFailure : public SimpleShaders
3346{
3347
3348	virtual std::string Title()
3349	{
3350		return "Relink Failure Test";
3351	}
3352
3353	virtual std::string PassCriteria()
3354	{
3355		return "INVALID_OPERATION is generated when asking for locations after failed link.";
3356	}
3357
3358	virtual std::string Purpose()
3359	{
3360		return "Verify that queries behave correctly after failed relink of a program.";
3361	}
3362
3363	virtual std::string Method()
3364	{
3365		return "Create a program, use it, relink with failure and then verify that INVALID_OPERATION is returned when "
3366			   "asking for locations.";
3367	}
3368
3369	virtual std::string VertexShader()
3370	{
3371		return "#version 310 es                               \n"
3372			   "in mediump vec4 position;                     \n"
3373			   "in mediump vec3 pos;                          \n"
3374			   "void main(void)                               \n"
3375			   "{                                             \n"
3376			   "    gl_Position = position + vec4(pos, 1.);   \n"
3377			   "}";
3378	}
3379
3380	virtual long Run()
3381	{
3382		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3383		glBindAttribLocation(program, 0, "position");
3384		glBindAttribLocation(program, 1, "pos");
3385		LinkProgram(program);
3386
3387		long error = NO_ERROR;
3388
3389		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "pos", 1, error);
3390		glUseProgram(program);
3391
3392		tcu::Vec4 v[4] = { tcu::Vec4(-1, 1, 0, 1), tcu::Vec4(-1, -1, 0, 1), tcu::Vec4(1, 1, 0, 1),
3393						   tcu::Vec4(1, -1, 0, 1) };
3394		GLuint vao, vbuf;
3395		glGenVertexArrays(1, &vao);
3396		glBindVertexArray(vao);
3397		glGenBuffers(1, &vbuf);
3398		glBindBuffer(GL_ARRAY_BUFFER, vbuf);
3399		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
3400		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), 0);
3401		glEnableVertexAttribArray(0);
3402		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3403
3404		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3405		glDisableVertexAttribArray(0);
3406		glDeleteVertexArrays(1, &vao);
3407		glBindBuffer(GL_ARRAY_BUFFER, 0);
3408		glDeleteBuffers(1, &vbuf);
3409
3410		glBindAttribLocation(program, 0, "pos");
3411		glBindAttribLocation(program, 0, "position");
3412		const char* varyings[2] = { "q", "z" };
3413		glTransformFeedbackVaryings(program, 2, varyings, GL_INTERLEAVED_ATTRIBS);
3414		LinkProgram(program);
3415
3416		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", -1, error);
3417		ExpectError(GL_INVALID_OPERATION, error);
3418		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "pos", -1, error);
3419		ExpectError(GL_INVALID_OPERATION, error);
3420		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", -1, error);
3421		ExpectError(GL_INVALID_OPERATION, error);
3422
3423		glDeleteProgram(program);
3424		return error;
3425	}
3426};
3427
3428class LinkFailure : public SimpleShaders
3429{
3430
3431	virtual std::string Title()
3432	{
3433		return "Link Failure Test";
3434	}
3435
3436	virtual std::string PassCriteria()
3437	{
3438		return "INVALID_OPERATION is generated when asking for locations after failed link.";
3439	}
3440
3441	virtual std::string Purpose()
3442	{
3443		return "Verify that queries behave correctly after failed relink of a program with changed sources.";
3444	}
3445
3446	virtual std::string Method()
3447	{
3448		return "Create a program, use it, relink with failure using different sources and then \n"
3449			   "verify that INVALID_OPERATION is returned when asking for locations.";
3450	}
3451
3452	virtual const char* VertexShader_prop()
3453	{
3454		return "#version 310 es                      \n"
3455			   "in mediump vec4 posit;               \n"
3456			   "in mediump vec4 p;                   \n"
3457			   "void main(void)                      \n"
3458			   "{                                    \n"
3459			   "    gl_Position = p + posit;         \n"
3460			   "}";
3461	}
3462
3463	virtual const char* FragmentShader_prop()
3464	{
3465		return "#version 310 es                    \n"
3466			   "out mediump vec4 color;            \n"
3467			   "void main() {                      \n"
3468			   "    color = vec4(0., 1., 0., 1.);  \n"
3469			   "}";
3470	}
3471
3472	virtual const char* VertexShader_fail()
3473	{
3474		return "#version 310 es                      \n"
3475			   "in mediump vec4 position;            \n"
3476			   "void main(void)                      \n"
3477			   "{                                    \n"
3478			   "    gl_Position = position;          \n"
3479			   "}";
3480	}
3481
3482	virtual long Run()
3483	{
3484		const GLuint program = glCreateProgram();
3485		const char*  src_vs  = VertexShader_prop();
3486		const char*  src_fs  = FragmentShader_prop();
3487		const char*  src_vsh = VertexShader_fail();
3488
3489		GLuint sh1 = glCreateShader(GL_VERTEX_SHADER);
3490		glAttachShader(program, sh1);
3491		glDeleteShader(sh1);
3492		glShaderSource(sh1, 1, &src_vs, NULL);
3493		glCompileShader(sh1);
3494
3495		GLuint sh2 = glCreateShader(GL_FRAGMENT_SHADER);
3496		glAttachShader(program, sh2);
3497		glDeleteShader(sh2);
3498		glShaderSource(sh2, 1, &src_fs, NULL);
3499		glCompileShader(sh2);
3500
3501		glBindAttribLocation(program, 0, "p");
3502		glBindAttribLocation(program, 1, "posit");
3503		LinkProgram(program);
3504
3505		long error = NO_ERROR;
3506
3507		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "posit", 1, error);
3508		glUseProgram(program);
3509
3510		tcu::Vec4 v[4] = { tcu::Vec4(-1, 1, 0, 1), tcu::Vec4(-1, -1, 0, 1), tcu::Vec4(1, 1, 0, 1),
3511						   tcu::Vec4(1, -1, 0, 1) };
3512		GLuint vao, vbuf;
3513		glGenVertexArrays(1, &vao);
3514		glBindVertexArray(vao);
3515		glGenBuffers(1, &vbuf);
3516		glBindBuffer(GL_ARRAY_BUFFER, vbuf);
3517		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
3518		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), 0);
3519		glEnableVertexAttribArray(0);
3520		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3521
3522		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3523		glDisableVertexAttribArray(0);
3524		glDeleteVertexArrays(1, &vao);
3525		glBindBuffer(GL_ARRAY_BUFFER, 0);
3526		glDeleteBuffers(1, &vbuf);
3527
3528		glDetachShader(program, sh1);
3529		GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
3530		glAttachShader(program, vsh);
3531		glDeleteShader(vsh);
3532		glShaderSource(vsh, 1, &src_vsh, NULL);
3533		glCompileShader(vsh);
3534		const char* varyings[2] = { "q", "z" };
3535		glTransformFeedbackVaryings(program, 2, varyings, GL_INTERLEAVED_ATTRIBS);
3536		LinkProgram(program);
3537
3538		GLint res;
3539		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", -1, error);
3540		ExpectError(GL_INVALID_OPERATION, error);
3541		glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &res);
3542		if (res != 0 && res != 1)
3543		{
3544			m_context.getTestContext().getLog()
3545				<< tcu::TestLog::Message << "Error, expected 0 or 1 active resources, got: " << res
3546				<< tcu::TestLog::EndMessage;
3547			error = ERROR;
3548		}
3549		glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, &res);
3550		if (res != 0 && res != 9)
3551		{
3552			m_context.getTestContext().getLog()
3553				<< tcu::TestLog::Message << "Error, expected 1 or 9 GL_MAX_NAME_LENGTH, got: " << res
3554				<< tcu::TestLog::EndMessage;
3555			error = ERROR;
3556		}
3557		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", -1, error);
3558		ExpectError(GL_INVALID_OPERATION, error);
3559
3560		glDeleteProgram(program);
3561		return error;
3562	}
3563};
3564}
3565
3566ProgramInterfaceQueryTests::ProgramInterfaceQueryTests(glcts::Context& context)
3567	: TestCaseGroup(context, "program_interface_query", "")
3568{
3569}
3570
3571ProgramInterfaceQueryTests::~ProgramInterfaceQueryTests(void)
3572{
3573}
3574
3575void ProgramInterfaceQueryTests::init()
3576{
3577	using namespace glcts;
3578	addChild(new TestSubcase(m_context, "empty-shaders", TestSubcase::Create<NoShaders>));
3579	addChild(new TestSubcase(m_context, "simple-shaders", TestSubcase::Create<SimpleShaders>));
3580	addChild(new TestSubcase(m_context, "input-types", TestSubcase::Create<InputTypes>));
3581	addChild(new TestSubcase(m_context, "input-built-in", TestSubcase::Create<InputBuiltIn>));
3582	addChild(new TestSubcase(m_context, "input-layout", TestSubcase::Create<InputLayout>));
3583	addChild(new TestSubcase(m_context, "output-layout", TestSubcase::Create<OutputLayout>));
3584	addChild(new TestSubcase(m_context, "output-built-in", TestSubcase::Create<OutputBuiltIn>));
3585	addChild(new TestSubcase(m_context, "uniform-simple", TestSubcase::Create<UniformSimple>));
3586	addChild(new TestSubcase(m_context, "uniform-types", TestSubcase::Create<UniformTypes>));
3587	addChild(new TestSubcase(m_context, "uniform-block-types", TestSubcase::Create<UniformBlockTypes>));
3588	addChild(new TestSubcase(m_context, "transform-feedback-types", TestSubcase::Create<TransformFeedbackTypes>));
3589	addChild(new TestSubcase(m_context, "atomic-counters", TestSubcase::Create<AtomicCounterSimple>));
3590	addChild(
3591		new TestSubcase(m_context, "atomic-counters-one-buffer", TestSubcase::Create<AtomicCounterSimpleOneBuffer>));
3592	addChild(new TestSubcase(m_context, "ssb-types", TestSubcase::Create<ShaderStorageBlock>));
3593	addChild(new TestSubcase(m_context, "null-length", TestSubcase::Create<NullLength>));
3594	addChild(new TestSubcase(m_context, "arrays-of-arrays", TestSubcase::Create<ArraysOfArrays>));
3595	addChild(new TestSubcase(m_context, "top-level-array", TestSubcase::Create<TopLevelArray>));
3596	addChild(new TestSubcase(m_context, "separate-programs-vertex", TestSubcase::Create<SeparateProgramsVertex>));
3597	addChild(new TestSubcase(m_context, "separate-programs-fragment", TestSubcase::Create<SeparateProgramsFragment>));
3598	addChild(new TestSubcase(m_context, "uniform-block", TestSubcase::Create<UniformBlockAdvanced>));
3599	addChild(new TestSubcase(m_context, "array-names", TestSubcase::Create<ArrayNames>));
3600	addChild(new TestSubcase(m_context, "buff-length", TestSubcase::Create<BuffLength>));
3601	addChild(new TestSubcase(m_context, "no-locations", TestSubcase::Create<NoLocations>));
3602	addChild(new TestSubcase(m_context, "query-not-used", TestSubcase::Create<QueryNotUsed>));
3603	addChild(new TestSubcase(m_context, "relink-failure", TestSubcase::Create<RelinkFailure>));
3604	addChild(new TestSubcase(m_context, "link-failure", TestSubcase::Create<LinkFailure>));
3605	addChild(new TestSubcase(m_context, "compute-shader", TestSubcase::Create<ComputeShaderTest>));
3606	addChild(new TestSubcase(m_context, "invalid-value", TestSubcase::Create<InvalidValueTest>));
3607	addChild(new TestSubcase(m_context, "invalid-operation", TestSubcase::Create<InvalidOperationTest>));
3608	addChild(new TestSubcase(m_context, "invalid-enum", TestSubcase::Create<InvalidEnumTest>));
3609}
3610}
3611