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 "gl4cProgramInterfaceQueryTests.hpp"
25 #include "glwEnums.hpp"
26 #include "glwFunctions.hpp"
27 #include <cstdarg>
28 #include <map>
29 #include <set>
30 
31 namespace gl4cts
32 {
33 
34 using namespace glw;
35 
36 namespace
37 {
38 
39 class PIQBase : public deqp::SubcaseBase
40 {
41 
42 public:
PassCriteria()43 	virtual std::string PassCriteria()
44 	{
45 		return "All called functions return expected values.";
46 	}
47 
Purpose()48 	virtual std::string Purpose()
49 	{
50 		return "Verify that the set of tested functions glGetProgram* return\n"
51 			   "expected results when used to get data from program\n"
52 			   "made of " +
53 			   ShadersDesc() + "." + PurposeExt();
54 	}
55 
Method()56 	virtual std::string Method()
57 	{
58 		return "Create a program using " + ShadersDesc() +
59 			   "\n"
60 			   "then use set of tested functions to get an information about it and\n"
61 			   "verify that information with the expected data" +
62 			   Expectations();
63 	}
64 
Cleanup()65 	virtual long Cleanup()
66 	{
67 		glUseProgram(0);
68 		return NO_ERROR;
69 	}
70 
Setup()71 	virtual long Setup()
72 	{
73 		return NO_ERROR;
74 	}
75 
~PIQBase()76 	virtual ~PIQBase()
77 	{
78 	}
79 
80 protected:
LinkProgram(GLuint program)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 
CreateProgram(const char* src_vs, const char* src_fs, bool link)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 
CreateProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs, const char* src_fs, bool link)121 	GLuint CreateProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
122 						 const char* src_fs, bool link)
123 	{
124 		const GLuint p = glCreateProgram();
125 
126 		if (src_vs)
127 		{
128 			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
129 			glAttachShader(p, sh);
130 			glDeleteShader(sh);
131 			glShaderSource(sh, 1, &src_vs, NULL);
132 			glCompileShader(sh);
133 		}
134 		if (src_tcs)
135 		{
136 			GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
137 			glAttachShader(p, sh);
138 			glDeleteShader(sh);
139 			glShaderSource(sh, 1, &src_tcs, NULL);
140 			glCompileShader(sh);
141 		}
142 		if (src_tes)
143 		{
144 			GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
145 			glAttachShader(p, sh);
146 			glDeleteShader(sh);
147 			glShaderSource(sh, 1, &src_tes, NULL);
148 			glCompileShader(sh);
149 		}
150 		if (src_gs)
151 		{
152 			GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
153 			glAttachShader(p, sh);
154 			glDeleteShader(sh);
155 			glShaderSource(sh, 1, &src_gs, NULL);
156 			glCompileShader(sh);
157 		}
158 		if (src_fs)
159 		{
160 			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
161 			glAttachShader(p, sh);
162 			glDeleteShader(sh);
163 			glShaderSource(sh, 1, &src_fs, NULL);
164 			glCompileShader(sh);
165 		}
166 		if (link)
167 		{
168 			LinkProgram(p);
169 		}
170 		return p;
171 	}
172 
ShadersDesc()173 	virtual std::string ShadersDesc()
174 	{
175 		return "";
176 	}
177 
Expectations()178 	virtual std::string Expectations()
179 	{
180 		return ".";
181 	}
182 
PurposeExt()183 	virtual std::string PurposeExt()
184 	{
185 		return "";
186 	}
187 
ExpectError(GLenum expected, long& error)188 	virtual inline void ExpectError(GLenum expected, long& error)
189 	{
190 		if (error != NO_ERROR)
191 			return;
192 		GLenum tmp = glGetError();
193 		if (tmp == expected)
194 		{
195 			m_context.getTestContext().getLog()
196 				<< tcu::TestLog::Message << "Found expected error" << tcu::TestLog::EndMessage;
197 			error = NO_ERROR; // Error is expected
198 		}
199 		else
200 		{
201 			error = ERROR;
202 			m_context.getTestContext().getLog() << tcu::TestLog::Message << expected
203 												<< " error was expected, found: " << tmp << tcu::TestLog::EndMessage;
204 		}
205 	}
206 
VerifyGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, int expected, long& error)207 	virtual inline void VerifyGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, int expected,
208 													long& error)
209 	{
210 		GLint res;
211 		glGetProgramInterfaceiv(program, programInterface, pname, &res);
212 		if (res != expected)
213 		{
214 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
215 												<< expected << tcu::TestLog::EndMessage;
216 			error = ERROR;
217 		}
218 	}
219 
VerifyGetProgramResourceIndex(GLuint program, GLenum programInterface, const std::string& name, GLuint expected, long& error)220 	virtual inline void VerifyGetProgramResourceIndex(GLuint program, GLenum programInterface, const std::string& name,
221 													  GLuint expected, long& error)
222 	{
223 		GLuint res = glGetProgramResourceIndex(program, programInterface, name.c_str());
224 		if (res != expected)
225 		{
226 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
227 												<< expected << tcu::TestLog::EndMessage;
228 			error = ERROR;
229 		}
230 	}
231 
VerifyGetProgramResourceIndex(GLuint program, GLenum programInterface, std::map<std::string, GLuint>& indices, const std::string& name, long& error)232 	virtual inline void VerifyGetProgramResourceIndex(GLuint program, GLenum		 programInterface,
233 													  std::map<std::string, GLuint>& indices, const std::string& name,
234 													  long& error)
235 	{
236 		GLuint res = glGetProgramResourceIndex(program, programInterface, name.c_str());
237 		if (res == GL_INVALID_INDEX)
238 		{
239 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res
240 												<< ", expected number other than -1" << tcu::TestLog::EndMessage;
241 			error = ERROR;
242 			return;
243 		}
244 		std::map<std::string, GLuint>::iterator it = indices.begin();
245 		while (it != indices.end())
246 		{
247 			if (it->second == res)
248 			{
249 				m_context.getTestContext().getLog()
250 					<< tcu::TestLog::Message << "ERROR: Duplicated value found: " << res << tcu::TestLog::EndMessage;
251 				error = ERROR;
252 				return;
253 			}
254 			++it;
255 		}
256 		indices[name] = res;
257 	}
258 
VerifyGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, const std::string& expected, long& error)259 	virtual inline void VerifyGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index,
260 													 const std::string& expected, long& error)
261 	{
262 		GLchar  name[1024] = { '\0' };
263 		GLsizei len;
264 		glGetProgramResourceName(program, programInterface, index, 1024, &len, name);
265 		if (len <= 0 || len > 1023 || name[len - 1] == '\0')
266 		{
267 			m_context.getTestContext().getLog()
268 				<< tcu::TestLog::Message
269 				<< "ERROR: Length in glGetProgramResourceName should not count null terminator!"
270 				<< tcu::TestLog::EndMessage;
271 			error = ERROR;
272 		}
273 		else if (name != expected || name[len] != '\0')
274 		{
275 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << name << ", expected "
276 												<< expected << tcu::TestLog::EndMessage;
277 			error = ERROR;
278 		}
279 	}
280 
VerifyGetProgramResourceLocation(GLuint program, GLenum programInterface, const std::string& name, GLint expected, long& error)281 	virtual inline void VerifyGetProgramResourceLocation(GLuint program, GLenum programInterface,
282 														 const std::string& name, GLint expected, long& error)
283 	{
284 		GLint res = glGetProgramResourceLocation(program, programInterface, name.c_str());
285 		if (res != expected)
286 		{
287 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
288 												<< expected << tcu::TestLog::EndMessage;
289 			error = ERROR;
290 		}
291 	}
292 
VerifyGetProgramResourceLocation(GLuint program, GLenum programInterface, std::map<std::string, GLint>& locations, const std::string& name, long& error)293 	virtual inline void VerifyGetProgramResourceLocation(GLuint program, GLenum		   programInterface,
294 														 std::map<std::string, GLint>& locations,
295 														 const std::string& name, long& error)
296 	{
297 		GLint res = glGetProgramResourceLocation(program, programInterface, name.c_str());
298 		if (res < 0)
299 		{
300 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res
301 												<< ", expected not less than 0" << tcu::TestLog::EndMessage;
302 			error = ERROR;
303 			return;
304 		}
305 		std::map<std::string, GLint>::iterator it = locations.begin();
306 		while (it != locations.end())
307 		{
308 			if (it->second == res)
309 			{
310 				m_context.getTestContext().getLog()
311 					<< tcu::TestLog::Message << "ERROR: Duplicated value found: " << res << tcu::TestLog::EndMessage;
312 				error = ERROR;
313 				return;
314 			}
315 			++it;
316 		}
317 		locations[name] = res;
318 	}
319 
VerifyGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum props[], GLsizei expectedLength, const GLint expected[], long& error)320 	virtual inline void VerifyGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index,
321 												   GLsizei propCount, const GLenum props[], GLsizei expectedLength,
322 												   const GLint expected[], long& error)
323 	{
324 		const GLsizei bufSize = 1000;
325 		GLsizei		  length;
326 		GLint		  params[bufSize];
327 		glGetProgramResourceiv(program, programInterface, index, propCount, props, bufSize, &length, params);
328 		if (length != expectedLength || length <= 0)
329 		{
330 			error = ERROR;
331 			m_context.getTestContext().getLog()
332 				<< tcu::TestLog::Message << "ERROR: Got length " << length << ", expected " << expectedLength
333 				<< "\nCALL: glGetProgramResourceiv, with " << programInterface << ", " << index
334 				<< tcu::TestLog::EndMessage;
335 			return;
336 		}
337 		for (int i = 0; i < length; ++i)
338 		{
339 			if (params[i] != expected[i])
340 			{
341 				error = ERROR;
342 				m_context.getTestContext().getLog()
343 					<< tcu::TestLog::Message << "ERROR: Got " << params[i] << ", expected " << expected[i]
344 					<< " at: " << i << "\nCALL: glGetProgramResourceiv, with " << programInterface << ", " << index
345 					<< tcu::TestLog::EndMessage;
346 			}
347 		}
348 	}
349 
VerifyGetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const std::string& name, GLint expected, long& error)350 	virtual inline void VerifyGetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
351 															  const std::string& name, GLint expected, long& error)
352 	{
353 		GLint res = glGetProgramResourceLocationIndex(program, programInterface, name.c_str());
354 		if (res != expected)
355 		{
356 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
357 												<< expected << "\nCALL: glGetProgramResourceLocationIndex, with "
358 												<< programInterface << ", " << name << tcu::TestLog::EndMessage;
359 			error = ERROR;
360 		}
361 	}
362 
GetProgramivRetValue(GLuint program, GLenum pname)363 	virtual inline GLint GetProgramivRetValue(GLuint program, GLenum pname)
364 	{
365 		GLint ret;
366 		glGetProgramiv(program, pname, &ret);
367 		return ret;
368 	}
369 
370 	static const GLenum interfaces[];
371 };
372 
373 const GLenum PIQBase::interfaces[] = { GL_PROGRAM_INPUT,
374 									   GL_PROGRAM_OUTPUT,
375 									   GL_UNIFORM,
376 									   GL_UNIFORM_BLOCK,
377 									   GL_BUFFER_VARIABLE,
378 									   GL_SHADER_STORAGE_BLOCK,
379 									   GL_VERTEX_SUBROUTINE,
380 									   GL_TESS_CONTROL_SUBROUTINE,
381 									   GL_TESS_EVALUATION_SUBROUTINE,
382 									   GL_GEOMETRY_SUBROUTINE,
383 									   GL_FRAGMENT_SUBROUTINE,
384 									   GL_COMPUTE_SUBROUTINE,
385 									   GL_VERTEX_SUBROUTINE_UNIFORM,
386 									   GL_TESS_CONTROL_SUBROUTINE_UNIFORM,
387 									   GL_TESS_EVALUATION_SUBROUTINE_UNIFORM,
388 									   GL_GEOMETRY_SUBROUTINE_UNIFORM,
389 									   GL_FRAGMENT_SUBROUTINE_UNIFORM,
390 									   GL_COMPUTE_SUBROUTINE_UNIFORM,
391 									   GL_TRANSFORM_FEEDBACK_VARYING };
392 
393 class NoShaders : public PIQBase
394 {
395 
Title()396 	virtual std::string Title()
397 	{
398 		return "No Shaders Test";
399 	}
400 
ShadersDesc()401 	virtual std::string ShadersDesc()
402 	{
403 		return "no shaders";
404 	}
405 
Run()406 	virtual long Run()
407 	{
408 		const GLuint program = glCreateProgram();
409 
410 		long error = NO_ERROR;
411 		int  size  = sizeof(PIQBase::interfaces) / sizeof(PIQBase::interfaces[0]);
412 
413 		for (int i = 0; i < size; ++i)
414 		{
415 			VerifyGetProgramInterfaceiv(program, PIQBase::interfaces[i], GL_ACTIVE_RESOURCES, 0, error);
416 			if (PIQBase::interfaces[i] == GL_ATOMIC_COUNTER_BUFFER)
417 				continue;
418 			VerifyGetProgramInterfaceiv(program, PIQBase::interfaces[i], GL_MAX_NAME_LENGTH, 0, error);
419 		}
420 		VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
421 		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
422 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
423 		VerifyGetProgramInterfaceiv(program, GL_COMPUTE_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0,
424 									error);
425 		VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0,
426 									error);
427 		VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0,
428 									error);
429 		VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES,
430 									0, error);
431 		VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0,
432 									error);
433 		VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0, error);
434 
435 		for (int i = 0; i < size; ++i)
436 		{
437 			if (PIQBase::interfaces[i] == GL_ATOMIC_COUNTER_BUFFER)
438 				continue;
439 			VerifyGetProgramResourceIndex(program, PIQBase::interfaces[i], "", GL_INVALID_INDEX, error);
440 		}
441 
442 		// can't test GetProgramResourceLocation* here since program has to be linked
443 		// can't test GetProgramResourceiv, need valid index
444 
445 		glDeleteProgram(program);
446 		return error;
447 	}
448 };
449 
450 class SimpleShaders : public PIQBase
451 {
452 
453 public:
Title()454 	virtual std::string Title()
455 	{
456 		return "Simple Shaders Test";
457 	}
458 
ShadersDesc()459 	virtual std::string ShadersDesc()
460 	{
461 		return "fallthrough fragment and vertex shaders";
462 	}
463 
VertexShader()464 	virtual std::string VertexShader()
465 	{
466 		return "#version 430                         \n"
467 			   "in vec4 position;                    \n"
468 			   "void main(void)                      \n"
469 			   "{                                    \n"
470 			   "    gl_Position = position;          \n"
471 			   "}";
472 	}
473 
FragmentShader()474 	virtual std::string FragmentShader()
475 	{
476 		return "#version 430                   \n"
477 			   "out vec4 color;                \n"
478 			   "void main() {                  \n"
479 			   "    color = vec4(0, 1, 0, 1);  \n"
480 			   "}";
481 	}
482 
Run()483 	virtual long Run()
484 	{
485 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
486 		glBindAttribLocation(program, 0, "position");
487 		glBindFragDataLocation(program, 0, "color");
488 		LinkProgram(program);
489 
490 		long error = NO_ERROR;
491 
492 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
493 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 9, error);
494 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 1, error);
495 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 6, error);
496 
497 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "color", 0, error);
498 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position", 0, error);
499 
500 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, 0, "color", error);
501 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, 0, "position", error);
502 
503 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", 0, error);
504 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
505 
506 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "color", 0, error);
507 
508 		GLenum props[] = { GL_NAME_LENGTH,
509 						   GL_TYPE,
510 						   GL_ARRAY_SIZE,
511 						   GL_REFERENCED_BY_COMPUTE_SHADER,
512 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
513 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
514 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
515 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
516 						   GL_REFERENCED_BY_VERTEX_SHADER,
517 						   GL_LOCATION,
518 						   GL_IS_PER_PATCH };
519 		GLint expected[] = { 9, GL_FLOAT_VEC4, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
520 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 11, props, 11, expected, error);
521 
522 		GLenum props2[] = { GL_NAME_LENGTH,
523 							GL_TYPE,
524 							GL_ARRAY_SIZE,
525 							GL_REFERENCED_BY_COMPUTE_SHADER,
526 							GL_REFERENCED_BY_FRAGMENT_SHADER,
527 							GL_REFERENCED_BY_GEOMETRY_SHADER,
528 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
529 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
530 							GL_REFERENCED_BY_VERTEX_SHADER,
531 							GL_LOCATION,
532 							GL_IS_PER_PATCH,
533 							GL_LOCATION_INDEX };
534 		GLint expected2[] = { 6, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
535 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 12, props2, 12, expected2, error);
536 
537 		glDeleteProgram(program);
538 		return error;
539 	}
540 };
541 
542 class InputTypes : public SimpleShaders
543 {
Title()544 	virtual std::string Title()
545 	{
546 		return "Input Types Test";
547 	}
548 
ShadersDesc()549 	virtual std::string ShadersDesc()
550 	{
551 		return "vertex shader with different `in` types and a fallthrough fragment shader";
552 	}
553 
VertexShader()554 	virtual std::string VertexShader()
555 	{
556 		return "#version 430                         \n"
557 			   "in mat4 a;                           \n"
558 			   "in ivec4 b;                          \n"
559 			   "in float c[2];                       \n"
560 			   "in mat2x3 d[2];                      \n"
561 			   "in uvec2 e;                          \n"
562 			   "in uint f;                           \n"
563 			   "in vec3 g[2];                        \n"
564 			   "in int h;                            \n"
565 			   "void main(void)                      \n"
566 			   "{                                    \n"
567 			   "   vec4 pos;                                           \n"
568 			   "   pos.w = h + g[0].x + g[1].y + d[1][1].y;            \n"
569 			   "   pos.y = b.x * c[0] + c[1] + d[0][0].x;              \n"
570 			   "   pos.x = a[0].x + a[1].y + a[2].z + a[3].w;          \n"
571 			   "   pos.z = d[0][1].z + e.x * f + d[1][0].z;            \n"
572 			   "   gl_Position = pos;                                  \n"
573 			   "}";
574 	}
575 
Run()576 	virtual long Run()
577 	{
578 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
579 		glBindAttribLocation(program, 0, "a");
580 		glBindAttribLocation(program, 4, "b");
581 		glBindAttribLocation(program, 5, "c");
582 		glBindAttribLocation(program, 7, "d");
583 		glBindAttribLocation(program, 11, "e");
584 		glBindAttribLocation(program, 12, "f");
585 		glBindAttribLocation(program, 13, "g");
586 		glBindAttribLocation(program, 15, "h");
587 		glBindFragDataLocation(program, 0, "color");
588 		LinkProgram(program);
589 
590 		long error = NO_ERROR;
591 
592 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 8, error);
593 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 5, error);
594 
595 		std::map<std::string, GLuint> indices;
596 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "a", error);
597 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "b", error);
598 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "c[0]", error);
599 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "d", error);
600 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "e", error);
601 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "f", error);
602 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "g", error);
603 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "h", error);
604 
605 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["a"], "a", error);
606 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["b"], "b", error);
607 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["c[0]"], "c[0]", error);
608 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["d"], "d[0]", error);
609 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["e"], "e", error);
610 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["f"], "f", error);
611 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["g"], "g[0]", error);
612 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["h"], "h", error);
613 
614 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "a", 0, error);
615 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "b", 4, error);
616 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c[0]", 5, error);
617 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c", 5, error);
618 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c[1]", 6, error);
619 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d[0]", 7, error);
620 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d", 7, error);
621 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "e", 11, error);
622 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "f", 12, error);
623 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g[0]", 13, error);
624 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g", 13, error);
625 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g[1]", 14, error);
626 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "h", 15, error);
627 
628 		GLenum props[] = { GL_NAME_LENGTH,
629 						   GL_TYPE,
630 						   GL_ARRAY_SIZE,
631 						   GL_REFERENCED_BY_COMPUTE_SHADER,
632 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
633 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
634 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
635 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
636 						   GL_REFERENCED_BY_VERTEX_SHADER,
637 						   GL_LOCATION,
638 						   GL_IS_PER_PATCH };
639 		GLint expected[] = { 2, GL_FLOAT_MAT4, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
640 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["a"], 11, props, 11, expected, error);
641 		GLint expected2[] = { 2, GL_INT_VEC4, 1, 0, 0, 0, 0, 0, 1, 4, 0 };
642 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["b"], 11, props, 11, expected2, error);
643 		GLint expected3[] = { 5, GL_FLOAT, 2, 0, 0, 0, 0, 0, 1, 5, 0 };
644 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["c[0]"], 11, props, 11, expected3, error);
645 		GLint expected4[] = { 5, GL_FLOAT_MAT2x3, 2, 0, 0, 0, 0, 0, 1, 7, 0 };
646 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["d"], 11, props, 11, expected4, error);
647 		GLint expected5[] = { 2, GL_UNSIGNED_INT_VEC2, 1, 0, 0, 0, 0, 0, 1, 11, 0 };
648 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["e"], 11, props, 11, expected5, error);
649 		GLint expected6[] = { 2, GL_UNSIGNED_INT, 1, 0, 0, 0, 0, 0, 1, 12, 0 };
650 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["f"], 11, props, 11, expected6, error);
651 		GLint expected7[] = { 5, GL_FLOAT_VEC3, 2, 0, 0, 0, 0, 0, 1, 13, 0 };
652 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["g"], 11, props, 11, expected7, error);
653 		GLint expected8[] = { 2, GL_INT, 1, 0, 0, 0, 0, 0, 1, 15, 0 };
654 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["h"], 11, props, 11, expected8, error);
655 
656 		glDeleteProgram(program);
657 		return error;
658 	}
659 };
660 
661 class OutputTypes : public SimpleShaders
662 {
Title()663 	virtual std::string Title()
664 	{
665 		return "Output Types Test";
666 	}
667 
ShadersDesc()668 	virtual std::string ShadersDesc()
669 	{
670 		return "fragment shader with different `out` types and a fallthrough vertex shader";
671 	}
672 
FragmentShader()673 	virtual std::string FragmentShader()
674 	{
675 		return "#version 430                   \n"
676 			   "out vec3 a[2];                 \n"
677 			   "out uint b;                    \n"
678 			   "out float c[2];                \n"
679 			   "out int d[2];                  \n"
680 			   "out vec2 e;                    \n"
681 			   "void main() {                  \n"
682 			   "    c[1] = -0.6;               \n"
683 			   "    d[0] = 0;                  \n"
684 			   "    b = 12u;                   \n"
685 			   "    c[0] = 1.1;                \n"
686 			   "    e = vec2(0, 1);            \n"
687 			   "    d[1] = -19;                \n"
688 			   "    a[1] = vec3(0, 1, 0);      \n"
689 			   "    a[0] = vec3(0, 1, 0);      \n"
690 			   "}";
691 	}
692 
Run()693 	virtual long Run()
694 	{
695 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
696 		glBindAttribLocation(program, 0, "position");
697 		glBindFragDataLocation(program, 0, "a");
698 		glBindFragDataLocation(program, 2, "b");
699 		glBindFragDataLocation(program, 3, "c");
700 		glBindFragDataLocation(program, 5, "d");
701 		glBindFragDataLocation(program, 7, "e");
702 		LinkProgram(program);
703 
704 		long error = NO_ERROR;
705 
706 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 5, error);
707 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 5, error);
708 
709 		std::map<std::string, GLuint> indices;
710 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "a", error);
711 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "b", error);
712 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "c[0]", error);
713 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "d", error);
714 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "e", error);
715 
716 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["a"], "a[0]", error);
717 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["b"], "b", error);
718 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["c[0]"], "c[0]", error);
719 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["d"], "d[0]", error);
720 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["e"], "e", error);
721 
722 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
723 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a", 0, error);
724 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[1]", 1, error);
725 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "b", 2, error);
726 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c[0]", 3, error);
727 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c", 3, error);
728 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c[1]", 4, error);
729 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d[0]", 5, error);
730 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d", 5, error);
731 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d[1]", 6, error);
732 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "e", 7, error);
733 
734 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
735 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "a", 0, error);
736 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "b", 0, error);
737 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "c[0]", 0, error);
738 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "c", 0, error);
739 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "d[0]", 0, error);
740 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "d", 0, error);
741 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "e", 0, error);
742 
743 		GLenum props[] = { GL_NAME_LENGTH,
744 						   GL_TYPE,
745 						   GL_ARRAY_SIZE,
746 						   GL_REFERENCED_BY_COMPUTE_SHADER,
747 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
748 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
749 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
750 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
751 						   GL_REFERENCED_BY_VERTEX_SHADER,
752 						   GL_LOCATION,
753 						   GL_IS_PER_PATCH,
754 						   GL_LOCATION_INDEX };
755 		GLint expected[] = { 5, GL_FLOAT_VEC3, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
756 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["a"], 12, props, 12, expected, error);
757 		GLint expected2[] = { 2, GL_UNSIGNED_INT, 1, 0, 1, 0, 0, 0, 0, 2, 0, 0 };
758 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["b"], 12, props, 12, expected2, error);
759 		GLint expected3[] = { 5, GL_FLOAT, 2, 0, 1, 0, 0, 0, 0, 3, 0, 0 };
760 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["c[0]"], 12, props, 12, expected3, error);
761 		GLint expected4[] = { 5, GL_INT, 2, 0, 1, 0, 0, 0, 0, 5, 0, 0 };
762 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["d"], 12, props, 12, expected4, error);
763 		GLint expected5[] = { 2, GL_FLOAT_VEC2, 1, 0, 1, 0, 0, 0, 0, 7, 0, 0 };
764 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["e"], 12, props, 12, expected5, error);
765 
766 		glDeleteProgram(program);
767 		return error;
768 	}
769 };
770 
771 class OutputLocationIndex : public SimpleShaders
772 {
Title()773 	virtual std::string Title()
774 	{
775 		return "Output Location Index Test";
776 	}
777 
ShadersDesc()778 	virtual std::string ShadersDesc()
779 	{
780 		return "fragment shader with `out` location index different from 0 and a fallthrough vertex shader";
781 	}
782 
Run()783 	virtual long Run()
784 	{
785 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
786 		glBindAttribLocation(program, 0, "position");
787 		glBindFragDataLocationIndexed(program, 0, 1, "color");
788 		LinkProgram(program);
789 
790 		long error = NO_ERROR;
791 
792 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
793 
794 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "color", 1, error);
795 
796 		GLenum props[] = { GL_NAME_LENGTH,
797 						   GL_TYPE,
798 						   GL_ARRAY_SIZE,
799 						   GL_REFERENCED_BY_COMPUTE_SHADER,
800 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
801 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
802 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
803 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
804 						   GL_REFERENCED_BY_VERTEX_SHADER,
805 						   GL_LOCATION,
806 						   GL_IS_PER_PATCH,
807 						   GL_LOCATION_INDEX };
808 		GLint expected[] = { 6, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
809 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 12, props, 12, expected, error);
810 
811 		glDeleteProgram(program);
812 		return error;
813 	}
814 };
815 
816 class InputBuiltIn : public SimpleShaders
817 {
818 
Title()819 	virtual std::string Title()
820 	{
821 		return "Input Built-ins Test";
822 	}
823 
ShadersDesc()824 	virtual std::string ShadersDesc()
825 	{
826 		return "vertex shader using built-in variables and a fallthrough fragment shader";
827 	}
828 
Expectations()829 	virtual std::string Expectations()
830 	{
831 		return ".\n\n In this case we ask for information about built-in variables for the input interface.";
832 	}
833 
VertexShader()834 	virtual std::string VertexShader()
835 	{
836 		return "#version 430                         \n"
837 			   "void main(void)                      \n"
838 			   "{                                    \n"
839 			   "    gl_Position = (gl_VertexID + gl_InstanceID) * vec4(0.1);          \n"
840 			   "}";
841 	}
842 
Run()843 	virtual long Run()
844 	{
845 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
846 		glBindFragDataLocation(program, 0, "color");
847 		LinkProgram(program);
848 
849 		long error = NO_ERROR;
850 
851 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 2, error);
852 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 14, error);
853 
854 		std::map<std::string, GLuint> indices;
855 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "gl_VertexID", error);
856 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "gl_InstanceID", error);
857 
858 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["gl_VertexID"], "gl_VertexID", error);
859 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["gl_InstanceID"], "gl_InstanceID", error);
860 
861 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "gl_VertexID", -1, error);
862 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "gl_InstanceID", -1, error);
863 
864 		GLenum props[] = { GL_NAME_LENGTH,
865 						   GL_TYPE,
866 						   GL_ARRAY_SIZE,
867 						   GL_REFERENCED_BY_COMPUTE_SHADER,
868 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
869 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
870 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
871 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
872 						   GL_REFERENCED_BY_VERTEX_SHADER,
873 						   GL_LOCATION,
874 						   GL_IS_PER_PATCH };
875 		GLint expected[] = { 12, GL_INT, 1, 0, 0, 0, 0, 0, 1, -1, 0 };
876 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["gl_VertexID"], 11, props, 11, expected, error);
877 		GLint expected2[] = { 14, GL_INT, 1, 0, 0, 0, 0, 0, 1, -1, 0 };
878 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["gl_InstanceID"], 11, props, 11, expected2,
879 								   error);
880 
881 		glDeleteProgram(program);
882 		return error;
883 	}
884 };
885 
886 class OutputBuiltIn : public SimpleShaders
887 {
888 
Title()889 	virtual std::string Title()
890 	{
891 		return "Output Built-ins Test";
892 	}
893 
ShadersDesc()894 	virtual std::string ShadersDesc()
895 	{
896 		return "fragment shader using built-in variables and a fallthrough vertex shader";
897 	}
898 
Expectations()899 	virtual std::string Expectations()
900 	{
901 		return ".\n\n In this case we ask for information about built-in variables for the output interface.";
902 	}
903 
FragmentShader()904 	virtual std::string FragmentShader()
905 	{
906 		return "#version 430                               \n"
907 			   "void main(void)                            \n"
908 			   "{                                          \n"
909 			   "    gl_FragDepth = 0.1;                    \n"
910 			   "    gl_SampleMask[0] = 1;                  \n"
911 			   "}";
912 	}
913 
Run()914 	virtual long Run()
915 	{
916 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), true);
917 
918 		long error = NO_ERROR;
919 
920 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 2, error);
921 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 17, error);
922 
923 		std::map<std::string, GLuint> indices;
924 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "gl_FragDepth", error);
925 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "gl_SampleMask[0]", error);
926 
927 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["gl_FragDepth"], "gl_FragDepth", error);
928 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["gl_SampleMask[0]"], "gl_SampleMask[0]",
929 									 error);
930 
931 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "gl_FragDepth", -1, error);
932 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "gl_SampleMask", -1, error);
933 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "gl_SampleMask[0]", -1, error);
934 
935 		// spec is not clear what to require here
936 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "gl_FragDepth", -1, error);
937 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "gl_SampleMask", -1, error);
938 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "gl_SampleMask[0]", -1, error);
939 
940 		GLenum props[] = { GL_NAME_LENGTH,
941 						   GL_TYPE,
942 						   GL_ARRAY_SIZE,
943 						   GL_REFERENCED_BY_COMPUTE_SHADER,
944 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
945 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
946 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
947 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
948 						   GL_REFERENCED_BY_VERTEX_SHADER,
949 						   GL_LOCATION,
950 						   GL_IS_PER_PATCH,
951 						   GL_LOCATION_INDEX };
952 		GLint expected[] = { 13, GL_FLOAT, 1, 0, 1, 0, 0, 0, 0, -1, 0, -1 };
953 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["gl_FragDepth"], 12, props, 12, expected, error);
954 		GLint expected2[] = { 17, GL_INT, 1, 0, 1, 0, 0, 0, 0, -1, 0, -1 };
955 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["gl_SampleMask[0]"], 12, props, 12, expected2,
956 								   error);
957 
958 		glDeleteProgram(program);
959 		return error;
960 	}
961 };
962 
963 class InputLayout : public SimpleShaders
964 {
Title()965 	virtual std::string Title()
966 	{
967 		return "Input Layout Test";
968 	}
969 
ShadersDesc()970 	virtual std::string ShadersDesc()
971 	{
972 		return "vertex shader with different `in` variables locations set through layout and a fallthrough fragment "
973 			   "shader";
974 	}
975 
VertexShader()976 	virtual std::string VertexShader()
977 	{
978 		return "#version 430                         \n"
979 			   "layout(location = 4) in ivec4 b;     \n"
980 			   "layout(location = 7) in mat2x3 d[2]; \n"
981 			   "layout(location = 5) in float c[2];  \n"
982 			   "layout(location = 12) in uint f;     \n"
983 			   "layout(location = 13) in vec3 g[2];  \n"
984 			   "layout(location = 0) in mat4 a;      \n"
985 			   "layout(location = 15) in int h;      \n"
986 			   "layout(location = 11) in uvec2 e;    \n"
987 			   "void main(void)                      \n"
988 			   "{                                    \n"
989 			   "   vec4 pos;                                           \n"
990 			   "   pos.w = h + g[0].x + g[1].y + d[1][1].y;            \n"
991 			   "   pos.y = b.x * c[0] + c[1] + d[0][0].x;              \n"
992 			   "   pos.x = a[0].x + a[1].y + a[2].z + a[3].w;          \n"
993 			   "   pos.z = d[0][1].z + e.x * f + d[1][0].z;            \n"
994 			   "   gl_Position = pos;                                  \n"
995 			   "}";
996 	}
997 
Run()998 	virtual long Run()
999 	{
1000 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1001 		glBindFragDataLocation(program, 0, "color");
1002 		LinkProgram(program);
1003 
1004 		long error = NO_ERROR;
1005 
1006 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 8, error);
1007 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 5, error);
1008 
1009 		std::map<std::string, GLuint> indices;
1010 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "a", error);
1011 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "b", error);
1012 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "c[0]", error);
1013 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "d", error);
1014 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "e", error);
1015 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "f", error);
1016 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "g", error);
1017 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "h", error);
1018 
1019 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["a"], "a", error);
1020 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["b"], "b", error);
1021 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["c[0]"], "c[0]", error);
1022 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["d"], "d[0]", error);
1023 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["e"], "e", error);
1024 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["f"], "f", error);
1025 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["g"], "g[0]", error);
1026 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["h"], "h", error);
1027 
1028 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "a", 0, error);
1029 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "b", 4, error);
1030 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c[0]", 5, error);
1031 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c", 5, error);
1032 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c[1]", 6, error);
1033 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d[0]", 7, error);
1034 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d", 7, error);
1035 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "e", 11, error);
1036 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "f", 12, error);
1037 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g[0]", 13, error);
1038 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g", 13, error);
1039 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g[1]", 14, error);
1040 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "h", 15, error);
1041 
1042 		GLenum props[] = { GL_NAME_LENGTH,
1043 						   GL_TYPE,
1044 						   GL_ARRAY_SIZE,
1045 						   GL_REFERENCED_BY_COMPUTE_SHADER,
1046 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
1047 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
1048 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
1049 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
1050 						   GL_REFERENCED_BY_VERTEX_SHADER,
1051 						   GL_LOCATION,
1052 						   GL_IS_PER_PATCH };
1053 		GLint expected[] = { 2, GL_FLOAT_MAT4, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
1054 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["a"], 11, props, 11, expected, error);
1055 		GLint expected2[] = { 2, GL_INT_VEC4, 1, 0, 0, 0, 0, 0, 1, 4, 0 };
1056 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["b"], 11, props, 11, expected2, error);
1057 		GLint expected3[] = { 5, GL_FLOAT, 2, 0, 0, 0, 0, 0, 1, 5, 0 };
1058 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["c[0]"], 11, props, 11, expected3, error);
1059 		GLint expected4[] = { 5, GL_FLOAT_MAT2x3, 2, 0, 0, 0, 0, 0, 1, 7, 0 };
1060 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["d"], 11, props, 11, expected4, error);
1061 		GLint expected5[] = { 2, GL_UNSIGNED_INT_VEC2, 1, 0, 0, 0, 0, 0, 1, 11, 0 };
1062 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["e"], 11, props, 11, expected5, error);
1063 		GLint expected6[] = { 2, GL_UNSIGNED_INT, 1, 0, 0, 0, 0, 0, 1, 12, 0 };
1064 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["f"], 11, props, 11, expected6, error);
1065 		GLint expected7[] = { 5, GL_FLOAT_VEC3, 2, 0, 0, 0, 0, 0, 1, 13, 0 };
1066 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["g"], 11, props, 11, expected7, error);
1067 		GLint expected8[] = { 2, GL_INT, 1, 0, 0, 0, 0, 0, 1, 15, 0 };
1068 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["h"], 11, props, 11, expected8, error);
1069 
1070 		glDeleteProgram(program);
1071 		return error;
1072 	}
1073 };
1074 
1075 class OutputLayout : public SimpleShaders
1076 {
Title()1077 	virtual std::string Title()
1078 	{
1079 		return "Output Layout Test";
1080 	}
1081 
ShadersDesc()1082 	virtual std::string ShadersDesc()
1083 	{
1084 		return "fragment shader with different `out` variables locations set through layout and a fallthrough vertex "
1085 			   "shader";
1086 	}
1087 
FragmentShader()1088 	virtual std::string FragmentShader()
1089 	{
1090 		return "#version 430                   \n"
1091 			   "layout(location = 2) out uint b;                    \n"
1092 			   "layout(location = 7) out vec2 e;                    \n"
1093 			   "layout(location = 3) out float c[2];                \n"
1094 			   "layout(location = 5) out int d[2];                  \n"
1095 			   "layout(location = 0) out vec3 a[2];                 \n"
1096 			   "void main() {                  \n"
1097 			   "    c[1] = -0.6;               \n"
1098 			   "    d[0] = 0;                  \n"
1099 			   "    b = 12u;                   \n"
1100 			   "    c[0] = 1.1;                \n"
1101 			   "    e = vec2(0, 1);            \n"
1102 			   "    d[1] = -19;                \n"
1103 			   "    a[1] = vec3(0, 1, 0);      \n"
1104 			   "    a[0] = vec3(0, 1, 0);      \n"
1105 			   "}";
1106 	}
1107 
Run()1108 	virtual long Run()
1109 	{
1110 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1111 		glBindAttribLocation(program, 0, "position");
1112 		LinkProgram(program);
1113 
1114 		long error = NO_ERROR;
1115 
1116 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 5, error);
1117 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 5, error);
1118 
1119 		std::map<std::string, GLuint> indices;
1120 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "a", error);
1121 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "b", error);
1122 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "c[0]", error);
1123 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "d", error);
1124 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "e", error);
1125 
1126 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["a"], "a[0]", error);
1127 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["b"], "b", error);
1128 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["c[0]"], "c[0]", error);
1129 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["d"], "d[0]", error);
1130 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["e"], "e", error);
1131 
1132 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
1133 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a", 0, error);
1134 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[1]", 1, error);
1135 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "b", 2, error);
1136 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c[0]", 3, error);
1137 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c", 3, error);
1138 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c[1]", 4, error);
1139 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d[0]", 5, error);
1140 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d", 5, error);
1141 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d[1]", 6, error);
1142 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "e", 7, error);
1143 
1144 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
1145 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "a", 0, error);
1146 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "b", 0, error);
1147 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "c[0]", 0, error);
1148 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "c", 0, error);
1149 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "d[0]", 0, error);
1150 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "d", 0, error);
1151 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "e", 0, error);
1152 
1153 		GLenum props[] = { GL_NAME_LENGTH,
1154 						   GL_TYPE,
1155 						   GL_ARRAY_SIZE,
1156 						   GL_REFERENCED_BY_COMPUTE_SHADER,
1157 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
1158 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
1159 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
1160 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
1161 						   GL_REFERENCED_BY_VERTEX_SHADER,
1162 						   GL_LOCATION,
1163 						   GL_IS_PER_PATCH,
1164 						   GL_LOCATION_INDEX };
1165 		GLint expected[] = { 5, GL_FLOAT_VEC3, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
1166 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["a"], 12, props, 12, expected, error);
1167 		GLint expected2[] = { 2, GL_UNSIGNED_INT, 1, 0, 1, 0, 0, 0, 0, 2, 0, 0 };
1168 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["b"], 12, props, 12, expected2, error);
1169 		GLint expected3[] = { 5, GL_FLOAT, 2, 0, 1, 0, 0, 0, 0, 3, 0, 0 };
1170 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["c[0]"], 12, props, 12, expected3, error);
1171 		GLint expected4[] = { 5, GL_INT, 2, 0, 1, 0, 0, 0, 0, 5, 0, 0 };
1172 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["d"], 12, props, 12, expected4, error);
1173 		GLint expected5[] = { 2, GL_FLOAT_VEC2, 1, 0, 1, 0, 0, 0, 0, 7, 0, 0 };
1174 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["e"], 12, props, 12, expected5, error);
1175 
1176 		glDeleteProgram(program);
1177 		return error;
1178 	}
1179 };
1180 
1181 class OutputLayoutIndex : public SimpleShaders
1182 {
Title()1183 	virtual std::string Title()
1184 	{
1185 		return "Output Layout Index Test";
1186 	}
1187 
ShadersDesc()1188 	virtual std::string ShadersDesc()
1189 	{
1190 		return "fragment shader with different `out` variables fragment color index\n"
1191 			   "locations set through layout and a fallthrough vertex shader";
1192 	}
1193 
FragmentShader()1194 	virtual std::string FragmentShader()
1195 	{
1196 		return "#version 430                   \n"
1197 			   "layout(location = 0, index = 1) out vec4 color;                \n"
1198 			   "void main() {                  \n"
1199 			   "    color = vec4(0, 1, 0, 1);  \n"
1200 			   "}";
1201 	}
1202 
Run()1203 	virtual long Run()
1204 	{
1205 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1206 		glBindAttribLocation(program, 0, "position");
1207 		LinkProgram(program);
1208 
1209 		long error = NO_ERROR;
1210 
1211 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
1212 
1213 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "color", 1, error);
1214 
1215 		GLenum props[] = { GL_NAME_LENGTH,
1216 						   GL_TYPE,
1217 						   GL_ARRAY_SIZE,
1218 						   GL_REFERENCED_BY_COMPUTE_SHADER,
1219 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
1220 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
1221 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
1222 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
1223 						   GL_REFERENCED_BY_VERTEX_SHADER,
1224 						   GL_LOCATION,
1225 						   GL_IS_PER_PATCH,
1226 						   GL_LOCATION_INDEX };
1227 		GLint expected[] = { 6, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
1228 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 12, props, 12, expected, error);
1229 
1230 		glDeleteProgram(program);
1231 		return error;
1232 	}
1233 };
1234 
1235 class UniformSimple : public PIQBase
1236 {
Title()1237 	virtual std::string Title()
1238 	{
1239 		return "Uniform Simple Test";
1240 	}
1241 
ShadersDesc()1242 	virtual std::string ShadersDesc()
1243 	{
1244 		return "fallthrough fragment and vertex shaders with uniforms used";
1245 	}
1246 
PurposeExt()1247 	virtual std::string PurposeExt()
1248 	{
1249 		return "\n\n Purpose is to verify calls using GL_UNIFORM as an interface param.";
1250 	}
1251 
VertexShader()1252 	virtual std::string VertexShader()
1253 	{
1254 		return "#version 430                         \n"
1255 			   "in vec4 position;                    \n"
1256 			   "uniform vec4 repos;                  \n"
1257 			   "void main(void)                      \n"
1258 			   "{                                    \n"
1259 			   "    gl_Position = position + repos;  \n"
1260 			   "}";
1261 	}
1262 
FragmentShader()1263 	virtual std::string FragmentShader()
1264 	{
1265 		return "#version 430                   \n"
1266 			   "uniform vec4 recolor;          \n"
1267 			   "out vec4 color;                \n"
1268 			   "void main() {                  \n"
1269 			   "    color = vec4(0, 1, 0, 1) + recolor;  \n"
1270 			   "}";
1271 	}
1272 
Run()1273 	virtual long Run()
1274 	{
1275 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1276 		glBindAttribLocation(program, 0, "position");
1277 		glBindFragDataLocation(program, 0, "color");
1278 		LinkProgram(program);
1279 
1280 		long error = NO_ERROR;
1281 
1282 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
1283 									GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
1284 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, 8, error);
1285 
1286 		std::map<std::string, GLuint> indices;
1287 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "repos", error);
1288 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "recolor", error);
1289 
1290 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["repos"], "repos", error);
1291 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["recolor"], "recolor", error);
1292 
1293 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "repos", glGetUniformLocation(program, "repos"), error);
1294 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "recolor", glGetUniformLocation(program, "recolor"),
1295 										 error);
1296 
1297 		GLenum props[] = { GL_NAME_LENGTH,
1298 						   GL_TYPE,
1299 						   GL_ARRAY_SIZE,
1300 						   GL_OFFSET,
1301 						   GL_BLOCK_INDEX,
1302 						   GL_ARRAY_STRIDE,
1303 						   GL_MATRIX_STRIDE,
1304 						   GL_IS_ROW_MAJOR,
1305 						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
1306 						   GL_REFERENCED_BY_COMPUTE_SHADER,
1307 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
1308 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
1309 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
1310 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
1311 						   GL_REFERENCED_BY_VERTEX_SHADER,
1312 						   GL_LOCATION };
1313 		GLint expected[] = {
1314 			6, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "repos")
1315 		};
1316 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["repos"], 16, props, 16, expected, error);
1317 
1318 		GLint expected2[] = {
1319 			8, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "recolor")
1320 		};
1321 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["recolor"], 16, props, 16, expected2, error);
1322 
1323 		glDeleteProgram(program);
1324 		return error;
1325 	}
1326 };
1327 
1328 class UniformTypes : public PIQBase
1329 {
Title()1330 	virtual std::string Title()
1331 	{
1332 		return "Uniform Types Test";
1333 	}
1334 
ShadersDesc()1335 	virtual std::string ShadersDesc()
1336 	{
1337 		return "fallthrough fragment and vertex shaders with different uniform types used";
1338 	}
1339 
PurposeExt()1340 	virtual std::string PurposeExt()
1341 	{
1342 		return "\n\n Purpose is to verify calls using GL_UNIFORM as an interface param.\n";
1343 	}
1344 
VertexShader()1345 	virtual std::string VertexShader()
1346 	{
1347 		return "#version 430                         \n"
1348 			   "in vec4 position;                    \n"
1349 			   "uniform vec4 a;                      \n"
1350 			   "uniform ivec3 b;                     \n"
1351 			   "uniform uvec2 c[3];                  \n"
1352 			   "uniform mat2 g[8];                   \n"
1353 			   "uniform mat3x2 i;                    \n"
1354 			   "void main(void)                      \n"
1355 			   "{                                    \n"
1356 			   "    float tmp;                       \n"
1357 			   "    tmp =  g[0][1][1] + a.z + b.y + c[0].x;   \n"
1358 			   "    tmp += g[1][1][1] + c[1].x;      \n"
1359 			   "    tmp += g[2][1][1] + c[2].x;      \n"
1360 			   "    for (int i = 3; i < 8; ++i)      \n"
1361 			   "        tmp += g[i][1][1];           \n"
1362 			   "    tmp = tmp + i[1][1];             \n"
1363 			   "    gl_Position = position * tmp;    \n"
1364 			   "}";
1365 	}
1366 
FragmentShader()1367 	virtual std::string FragmentShader()
1368 	{
1369 		return "#version 430                   \n"
1370 			   "struct U {                     \n"
1371 			   "   bool a[3];                  \n"
1372 			   "   vec4 b;                     \n"
1373 			   "   mat3 c;                     \n"
1374 			   "   float d[2];                 \n"
1375 			   "};                             \n"
1376 			   "struct UU {                    \n"
1377 			   "   U a;                        \n"
1378 			   "   U b[2];                     \n"
1379 			   "   uvec2 c;                    \n"
1380 			   "};                             \n"
1381 			   "uniform mat4 d;                \n"
1382 			   "uniform mat3 e;                \n"
1383 			   "uniform float h;               \n"
1384 			   "uniform int f;                 \n"
1385 			   "uniform U j;                   \n"
1386 			   "uniform UU k;                  \n"
1387 			   "uniform UU l[3];               \n"
1388 			   "out vec4 color;                \n"
1389 			   "void main() {                  \n"
1390 			   "    float tmp;                 \n"
1391 			   "    tmp = h + f + e[2][2];           \n"
1392 			   "    tmp = tmp + d[0][0] + j.b.x;     \n"
1393 			   "    tmp = tmp + k.b[0].c[0][0];      \n"
1394 			   "    tmp = tmp + l[2].a.c[0][1];      \n"
1395 			   "    tmp = tmp + l[2].b[1].d[0];      \n"
1396 			   "    tmp = tmp + l[2].b[1].d[1];      \n"
1397 			   "    tmp = tmp + l[0].c.x;            \n"
1398 			   "    color = vec4(0, 1, 0, 1) * tmp;  \n"
1399 			   "}";
1400 	}
1401 
Run()1402 	virtual long Run()
1403 	{
1404 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1405 		glBindAttribLocation(program, 0, "position");
1406 		glBindFragDataLocation(program, 0, "color");
1407 		LinkProgram(program);
1408 
1409 		long error = NO_ERROR;
1410 
1411 		// only active structure members
1412 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
1413 									GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
1414 		// l[2].b[1].d[0] and \0
1415 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, 15, error);
1416 
1417 		std::map<std::string, GLuint> indices;
1418 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "a", error);
1419 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "b", error);
1420 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "c", error);
1421 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "d", error);
1422 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "e", error);
1423 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "f", error);
1424 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "g", error);
1425 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "h", error);
1426 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "i", error);
1427 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "j.b", error);
1428 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "k.b[0].c", error);
1429 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[0].c", error);
1430 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[2].b[1].d[0]", error);
1431 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[2].a.c", error);
1432 
1433 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["a"], "a", error);
1434 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["b"], "b", error);
1435 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["c"], "c[0]", error);
1436 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["d"], "d", error);
1437 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["e"], "e", error);
1438 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["f"], "f", error);
1439 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["g"], "g[0]", error);
1440 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["h"], "h", error);
1441 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["i"], "i", error);
1442 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["j.b"], "j.b", error);
1443 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["k.b[0].c"], "k.b[0].c", error);
1444 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[0].c"], "l[0].c", error);
1445 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[2].b[1].d[0]"], "l[2].b[1].d[0]", error);
1446 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[2].a.c"], "l[2].a.c", error);
1447 
1448 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", glGetUniformLocation(program, "a"), error);
1449 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", glGetUniformLocation(program, "b"), error);
1450 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", glGetUniformLocation(program, "c"), error);
1451 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d", glGetUniformLocation(program, "d"), error);
1452 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "e", glGetUniformLocation(program, "e"), error);
1453 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "f", glGetUniformLocation(program, "f"), error);
1454 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "g", glGetUniformLocation(program, "g"), error);
1455 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "h", glGetUniformLocation(program, "h"), error);
1456 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "i", glGetUniformLocation(program, "i"), error);
1457 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "j.b", glGetUniformLocation(program, "j.b"), error);
1458 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "k.b[0].c", glGetUniformLocation(program, "k.b[0].c"),
1459 										 error);
1460 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[0].c", glGetUniformLocation(program, "l[0].c"), error);
1461 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[2].b[1].d[0]",
1462 										 glGetUniformLocation(program, "l[2].b[1].d[0]"), error);
1463 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[2].a.c", glGetUniformLocation(program, "l[2].a.c"),
1464 										 error);
1465 
1466 		GLenum props[] = { GL_NAME_LENGTH,
1467 						   GL_TYPE,
1468 						   GL_ARRAY_SIZE,
1469 						   GL_OFFSET,
1470 						   GL_BLOCK_INDEX,
1471 						   GL_ARRAY_STRIDE,
1472 						   GL_MATRIX_STRIDE,
1473 						   GL_IS_ROW_MAJOR,
1474 						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
1475 						   GL_REFERENCED_BY_COMPUTE_SHADER,
1476 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
1477 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
1478 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
1479 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
1480 						   GL_REFERENCED_BY_VERTEX_SHADER,
1481 						   GL_LOCATION };
1482 		GLint expected[] = {
1483 			2, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "a")
1484 		};
1485 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["a"], 16, props, 16, expected, error);
1486 		GLint expected2[] = { 2,  GL_INT_VEC3, 1, -1, -1, -1, -1, 0,
1487 							  -1, 0,		   0, 0,  0,  0,  1,  glGetUniformLocation(program, "b") };
1488 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["b"], 16, props, 16, expected2, error);
1489 		GLint expected3[] = {
1490 			5, GL_UNSIGNED_INT_VEC2, 3, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "c")
1491 		};
1492 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["c"], 16, props, 16, expected3, error);
1493 		GLint expected4[] = {
1494 			2, GL_FLOAT_MAT4, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "d")
1495 		};
1496 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["d"], 16, props, 16, expected4, error);
1497 		GLint expected5[] = {
1498 			2, GL_FLOAT_MAT3, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "e")
1499 		};
1500 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["e"], 16, props, 16, expected5, error);
1501 		GLint expected6[] = {
1502 			2, GL_INT, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "f")
1503 		};
1504 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["f"], 16, props, 16, expected6, error);
1505 		GLint expected7[] = {
1506 			5, GL_FLOAT_MAT2, 8, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "g")
1507 		};
1508 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["g"], 16, props, 16, expected7, error);
1509 		GLint expected8[] = { 2,  GL_FLOAT, 1, -1, -1, -1, -1, 0,
1510 							  -1, 0,		1, 0,  0,  0,  0,  glGetUniformLocation(program, "h") };
1511 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["h"], 16, props, 16, expected8, error);
1512 		GLint expected9[] = {
1513 			2, GL_FLOAT_MAT3x2, 1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "i")
1514 		};
1515 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["i"], 16, props, 16, expected9, error);
1516 		GLint expected10[] = {
1517 			4, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "j.b")
1518 		};
1519 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["j.b"], 16, props, 16, expected10, error);
1520 		GLint expected11[] = {
1521 			9, GL_FLOAT_MAT3, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "k.b[0].c")
1522 		};
1523 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["k.b[0].c"], 16, props, 16, expected11, error);
1524 		GLint expected12[] = { 7,  GL_UNSIGNED_INT_VEC2,
1525 							   1,  -1,
1526 							   -1, -1,
1527 							   -1, 0,
1528 							   -1, 0,
1529 							   1,  0,
1530 							   0,  0,
1531 							   0,  glGetUniformLocation(program, "l[0].c") };
1532 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[0].c"], 16, props, 16, expected12, error);
1533 		GLint expected13[] = { 15, GL_FLOAT, 2, -1, -1, -1, -1, 0,
1534 							   -1, 0,		 1, 0,  0,  0,  0,  glGetUniformLocation(program, "l[2].b[1].d[0]") };
1535 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[2].b[1].d[0]"], 16, props, 16, expected13, error);
1536 		GLint expected14[] = {
1537 			9, GL_FLOAT_MAT3, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "l[2].a.c")
1538 		};
1539 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[2].a.c"], 16, props, 16, expected14, error);
1540 
1541 		glDeleteProgram(program);
1542 		return error;
1543 	}
1544 };
1545 
1546 class UniformBlockTypes : public PIQBase
1547 {
Title()1548 	virtual std::string Title()
1549 	{
1550 		return "Uniform Block Types Test";
1551 	}
1552 
ShadersDesc()1553 	virtual std::string ShadersDesc()
1554 	{
1555 		return "fallthrough fragment and vertex shaders with different types of uniform blocks used";
1556 	}
1557 
PurposeExt()1558 	virtual std::string PurposeExt()
1559 	{
1560 		return "\n\n Purpose is to verify calls using GL_UNIFORM_BLOCK as an interface param.\n";
1561 	}
1562 
VertexShader()1563 	virtual std::string VertexShader()
1564 	{
1565 		return "#version 430                         \n"
1566 			   "in vec4 position;                    \n"
1567 			   ""
1568 			   "uniform SimpleBlock {                \n"
1569 			   "   mat3x2 a;                         \n"
1570 			   "   mat4 b;                           \n"
1571 			   "   vec4 c;                           \n"
1572 			   "};                                   \n"
1573 			   ""
1574 			   "uniform NotSoSimpleBlockk {          \n"
1575 			   "   ivec2 a[4];                       \n"
1576 			   "   mat3 b[2];                        \n"
1577 			   "   mat2 c;                           \n"
1578 			   "} d;                                 \n"
1579 			   ""
1580 			   "void main(void)                      \n"
1581 			   "{                                    \n"
1582 			   "    float tmp;                       \n"
1583 			   "    tmp =  a[0][1] * b[1][2] * c.x;  \n"
1584 			   "    tmp = tmp + d.a[2].y + d.b[0][1][1] + d.c[1][1];             \n"
1585 			   "    gl_Position = position * tmp;    \n"
1586 			   "}";
1587 	}
1588 
FragmentShader()1589 	virtual std::string FragmentShader()
1590 	{
1591 		return "#version 430                   \n"
1592 			   "struct U {                     \n"
1593 			   "   bool a[3];                  \n"
1594 			   "   vec4 b;                     \n"
1595 			   "   mat3 c;                     \n"
1596 			   "   float d[2];                 \n"
1597 			   "};                             \n"
1598 			   "struct UU {                    \n"
1599 			   "   U a;                        \n"
1600 			   "   U b[2];                     \n"
1601 			   "   uvec2 c;                    \n"
1602 			   "};                             \n"
1603 			   ""
1604 			   "uniform TrickyBlock {                            \n"
1605 			   "   UU a[3];                                      \n"
1606 			   "   mat4 b;                                       \n"
1607 			   "   uint c;                                       \n"
1608 			   "} e[2];                                          \n"
1609 			   ""
1610 			   "out vec4 color;                                \n"
1611 			   "void main() {                                  \n"
1612 			   "    float tmp;                                 \n"
1613 			   "    tmp = e[0].a[2].b[0].d[1];                 \n"
1614 			   "    color = vec4(0, 1, 0, 1) * tmp;            \n"
1615 			   "}";
1616 	}
1617 
Run()1618 	virtual long Run()
1619 	{
1620 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1621 		glBindAttribLocation(program, 0, "position");
1622 		glBindFragDataLocation(program, 0, "color");
1623 		LinkProgram(program);
1624 
1625 		long error = NO_ERROR;
1626 
1627 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
1628 									GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
1629 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, 4, error);
1630 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NAME_LENGTH, 18, error);
1631 
1632 		std::map<std::string, GLuint> indicesUB;
1633 		std::map<std::string, GLuint> indicesU;
1634 		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "SimpleBlock", error);
1635 		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "NotSoSimpleBlockk", error);
1636 		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "TrickyBlock", error);
1637 		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "TrickyBlock[1]", error);
1638 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
1639 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
1640 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "c", error);
1641 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.a[0]", error);
1642 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.c", error);
1643 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.b[0]", error);
1644 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "TrickyBlock.a[2].b[0].d", error);
1645 
1646 		glUniformBlockBinding(program, indicesUB["SimpleBlock"], 0);
1647 		glUniformBlockBinding(program, indicesUB["NotSoSimpleBlockk"], 2);
1648 		glUniformBlockBinding(program, indicesUB["TrickyBlock"], 3);
1649 		glUniformBlockBinding(program, indicesUB["TrickyBlock[1]"], 4);
1650 
1651 		VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], "SimpleBlock", error);
1652 		VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], "NotSoSimpleBlockk",
1653 									 error);
1654 		VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock"], "TrickyBlock[0]", error);
1655 		VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock[1]"], "TrickyBlock[1]", error);
1656 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["a"], "a", error);
1657 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["b"], "b", error);
1658 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["c"], "c", error);
1659 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.a[0]"], "NotSoSimpleBlockk.a[0]",
1660 									 error);
1661 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.c"], "NotSoSimpleBlockk.c",
1662 									 error);
1663 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.b[0]"], "NotSoSimpleBlockk.b[0]",
1664 									 error);
1665 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["TrickyBlock.a[2].b[0].d"],
1666 									 "TrickyBlock.a[2].b[0].d[0]", error);
1667 
1668 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", -1, error);
1669 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", -1, error);
1670 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", -1, error);
1671 
1672 		GLenum props[] = {
1673 			GL_NAME_LENGTH,
1674 			GL_BUFFER_BINDING,
1675 			GL_REFERENCED_BY_COMPUTE_SHADER,
1676 			GL_REFERENCED_BY_FRAGMENT_SHADER,
1677 			GL_REFERENCED_BY_GEOMETRY_SHADER,
1678 			GL_REFERENCED_BY_TESS_CONTROL_SHADER,
1679 			GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
1680 			GL_REFERENCED_BY_VERTEX_SHADER,
1681 			GL_BUFFER_DATA_SIZE,
1682 		};
1683 		GLint size;
1684 		glGetActiveUniformBlockiv(program, indicesUB["SimpleBlock"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
1685 		GLint expected[] = { 12, 0, 0, 0, 0, 0, 0, 1, size };
1686 		VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], 9, props, 9, expected, error);
1687 		glGetActiveUniformBlockiv(program, indicesUB["NotSoSimpleBlockk"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
1688 		GLint expected2[] = { 18, 2, 0, 0, 0, 0, 0, 1, size };
1689 		VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], 9, props, 9, expected2,
1690 								   error);
1691 		glGetActiveUniformBlockiv(program, indicesUB["TrickyBlock"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
1692 		GLint expected3[] = { 15, 3, 0, 1, 0, 0, 0, 0, size };
1693 		VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock"], 9, props, 9, expected3, error);
1694 		GLint expected4[] = { 15, 4, 0, 0, 0, 0, 0, 0, size };
1695 		VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock[1]"], 9, props, 9, expected4,
1696 								   error);
1697 
1698 		GLenum props2[] = { GL_NAME_LENGTH,
1699 							GL_TYPE,
1700 							GL_ARRAY_SIZE,
1701 							GL_BLOCK_INDEX,
1702 							GL_ARRAY_STRIDE,
1703 							GL_IS_ROW_MAJOR,
1704 							GL_ATOMIC_COUNTER_BUFFER_INDEX,
1705 							GL_REFERENCED_BY_COMPUTE_SHADER,
1706 							GL_REFERENCED_BY_FRAGMENT_SHADER,
1707 							GL_REFERENCED_BY_GEOMETRY_SHADER,
1708 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
1709 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
1710 							GL_REFERENCED_BY_VERTEX_SHADER,
1711 							GL_LOCATION };
1712 		GLint expected5[] = {
1713 			2, GL_FLOAT_MAT3x2, 1, static_cast<GLint>(indicesUB["SimpleBlock"]), 0, 0, -1, 0, 0, 0, 0, 0, 1, -1
1714 		};
1715 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 14, props2, 14, expected5, error);
1716 		GLenum props3[] = { GL_NAME_LENGTH,
1717 							GL_TYPE,
1718 							GL_ARRAY_SIZE,
1719 							GL_BLOCK_INDEX,
1720 							GL_MATRIX_STRIDE,
1721 							GL_IS_ROW_MAJOR,
1722 							GL_ATOMIC_COUNTER_BUFFER_INDEX,
1723 							GL_REFERENCED_BY_COMPUTE_SHADER,
1724 							GL_REFERENCED_BY_FRAGMENT_SHADER,
1725 							GL_REFERENCED_BY_GEOMETRY_SHADER,
1726 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
1727 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
1728 							GL_REFERENCED_BY_VERTEX_SHADER,
1729 							GL_LOCATION };
1730 		GLint expected6[] = { 27, GL_FLOAT, 2, static_cast<GLint>(indicesUB["TrickyBlock"]), 0, 0, -1, 0, 1, 0, 0,
1731 							  0,  0,		-1 };
1732 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["TrickyBlock.a[2].b[0].d"], 14, props3, 14, expected6,
1733 								   error);
1734 
1735 		GLenum			 prop	= GL_ACTIVE_VARIABLES;
1736 		const GLsizei	bufSize = 1000;
1737 		GLsizei			 length;
1738 		GLint			 param[bufSize];
1739 		std::set<GLuint> exp;
1740 		exp.insert(indicesU["a"]);
1741 		exp.insert(indicesU["b"]);
1742 		exp.insert(indicesU["c"]);
1743 		glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], 1, &prop, bufSize, &length, param);
1744 		for (int i = 0; i < length; ++i)
1745 		{
1746 			if (exp.find(param[i]) == exp.end())
1747 			{
1748 				m_context.getTestContext().getLog()
1749 					<< tcu::TestLog::Message
1750 					<< "Unexpected index found in active variables of SimpleBlock: " << param[i]
1751 					<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
1752 					<< tcu::TestLog::EndMessage;
1753 				glDeleteProgram(program);
1754 				return ERROR;
1755 			}
1756 			else if (length != 3)
1757 			{
1758 				m_context.getTestContext().getLog()
1759 					<< tcu::TestLog::Message
1760 					<< "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK\n"
1761 					<< "Expected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
1762 				glDeleteProgram(program);
1763 				return ERROR;
1764 			}
1765 		}
1766 		std::set<GLuint> exp2;
1767 		exp2.insert(indicesU["NotSoSimpleBlockk.a[0]"]);
1768 		exp2.insert(indicesU["NotSoSimpleBlockk.b[0]"]);
1769 		exp2.insert(indicesU["NotSoSimpleBlockk.c"]);
1770 		glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], 1, &prop, bufSize, &length,
1771 							   param);
1772 		for (int i = 0; i < length; ++i)
1773 		{
1774 			if (exp2.find(param[i]) == exp2.end())
1775 			{
1776 				m_context.getTestContext().getLog()
1777 					<< tcu::TestLog::Message
1778 					<< "Unexpected index found in active variables of NotSoSimpleBlockk: " << param[i]
1779 					<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
1780 					<< tcu::TestLog::EndMessage;
1781 				glDeleteProgram(program);
1782 				return ERROR;
1783 			}
1784 			else if (length != 3)
1785 			{
1786 				m_context.getTestContext().getLog()
1787 					<< tcu::TestLog::Message
1788 					<< "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
1789 					<< "\nExpected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
1790 				glDeleteProgram(program);
1791 				return ERROR;
1792 			}
1793 		}
1794 
1795 		GLint res;
1796 		glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &res);
1797 		if (res < 3)
1798 		{
1799 			m_context.getTestContext().getLog()
1800 				<< tcu::TestLog::Message << "Value of GL_MAX_NUM_ACTIVE_VARIABLES less than 3!"
1801 				<< tcu::TestLog::EndMessage;
1802 			glDeleteProgram(program);
1803 			return ERROR;
1804 		}
1805 
1806 		glDeleteProgram(program);
1807 		return error;
1808 	}
1809 };
1810 
1811 class TransformFeedbackTypes : public SimpleShaders
1812 {
Title()1813 	virtual std::string Title()
1814 	{
1815 		return "Transform Feedback Varying Types";
1816 	}
1817 
ShadersDesc()1818 	virtual std::string ShadersDesc()
1819 	{
1820 		return "fallthrough fragment and vertex shaders with different types of out variables used";
1821 	}
1822 
PurposeExt()1823 	virtual std::string PurposeExt()
1824 	{
1825 		return "\n\n Purpose is to verify calls using GL_TRANSFORM_FEEDBACK_VARYING as an interface param.\n";
1826 	}
1827 
VertexShader()1828 	virtual std::string VertexShader()
1829 	{
1830 		return "#version 430                         \n"
1831 			   "in vec4 position;                    \n"
1832 			   ""
1833 			   "flat out ivec4 a;                    \n"
1834 			   "out float b[2];                      \n"
1835 			   "flat out uvec2 c;                    \n"
1836 			   "flat out uint d;                     \n"
1837 			   "out vec3 e[2];                       \n"
1838 			   "flat out int f;                      \n"
1839 			   ""
1840 			   "void main(void)                      \n"
1841 			   "{                                    \n"
1842 			   "   vec4 pos;                         \n"
1843 			   "   a = ivec4(1);                     \n"
1844 			   "   b[0] = 1.1;                       \n"
1845 			   "   b[1] = 1.1;                       \n"
1846 			   "   c = uvec2(1u);                    \n"
1847 			   "   d = 1u;                           \n"
1848 			   "   e[0] = vec3(1.1);                 \n"
1849 			   "   e[1] = vec3(1.1);                 \n"
1850 			   "   f = 1;                            \n"
1851 			   "   gl_Position = position;           \n"
1852 			   "}";
1853 	}
1854 
Run()1855 	virtual long Run()
1856 	{
1857 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1858 		glBindAttribLocation(program, 0, "position");
1859 		const char* varyings[6] = { "a", "b[0]", "b[1]", "c", "d", "e" };
1860 		glTransformFeedbackVaryings(program, 6, varyings, GL_INTERLEAVED_ATTRIBS);
1861 		LinkProgram(program);
1862 
1863 		long error = NO_ERROR;
1864 
1865 		VerifyGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_ACTIVE_RESOURCES, 6, error);
1866 		VerifyGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_MAX_NAME_LENGTH, 5, error);
1867 
1868 		std::map<std::string, GLuint> indices;
1869 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "a", error);
1870 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "b[0]", error);
1871 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "b[1]", error);
1872 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "c", error);
1873 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "d", error);
1874 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "e", error);
1875 
1876 		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["a"], "a", error);
1877 		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[0]"], "b[0]", error);
1878 		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[1]"], "b[1]", error);
1879 		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["c"], "c", error);
1880 		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["d"], "d", error);
1881 		VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["e"], "e", error);
1882 
1883 		GLenum props[]	= { GL_NAME_LENGTH, GL_TYPE, GL_ARRAY_SIZE };
1884 		GLint  expected[] = { 2, GL_INT_VEC4, 1 };
1885 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["a"], 3, props, 3, expected, error);
1886 		GLint expected2[] = { 5, GL_FLOAT, 1 };
1887 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[0]"], 3, props, 3, expected2,
1888 								   error);
1889 		GLint expected3[] = { 5, GL_FLOAT, 1 };
1890 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[1]"], 3, props, 3, expected3,
1891 								   error);
1892 		GLint expected4[] = { 2, GL_UNSIGNED_INT_VEC2, 1 };
1893 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["c"], 3, props, 3, expected4, error);
1894 		GLint expected5[] = { 2, GL_UNSIGNED_INT, 1 };
1895 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["d"], 3, props, 3, expected5, error);
1896 		GLint expected6[] = { 2, GL_FLOAT_VEC3, 2 };
1897 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["e"], 3, props, 3, expected6, error);
1898 
1899 		glDeleteProgram(program);
1900 		return error;
1901 	}
1902 };
1903 
1904 class AtomicCounterSimple : public SimpleShaders
1905 {
1906 public:
Title()1907 	virtual std::string Title()
1908 	{
1909 		return "Atomic Counter Buffer Simple Test";
1910 	}
1911 
ShadersDesc()1912 	virtual std::string ShadersDesc()
1913 	{
1914 		return "fallthrough fragment and vertex shaders with atomic counters used";
1915 	}
1916 
PurposeExt()1917 	virtual std::string PurposeExt()
1918 	{
1919 		return "\n\n Purpose is to verify calls using GL_ATOMIC_COUNTER_BUFFER as an interface param.\n";
1920 	}
1921 
FragmentShader()1922 	virtual std::string FragmentShader()
1923 	{
1924 		return "#version 430                   \n"
1925 			   "out vec4 color;                \n"
1926 			   ""
1927 			   "layout (binding = 1, offset = 0) uniform atomic_uint a;    \n"
1928 			   "layout (binding = 2, offset = 0) uniform atomic_uint b;    \n"
1929 			   "layout (binding = 2, offset = 4) uniform atomic_uint c;    \n"
1930 			   "layout (binding = 5, offset = 0) uniform atomic_uint d[3]; \n"
1931 			   "layout (binding = 5, offset = 12) uniform atomic_uint e;   \n"
1932 			   ""
1933 			   "void main() {                                                         \n"
1934 			   "   uint x = atomicCounterIncrement(d[0]) + atomicCounterIncrement(a); \n"
1935 			   "   uint y = atomicCounterIncrement(d[1]) + atomicCounterIncrement(b); \n"
1936 			   "   uint z = atomicCounterIncrement(d[2]) + atomicCounterIncrement(c); \n"
1937 			   "   uint w = atomicCounterIncrement(e);                                \n"
1938 			   "   color = vec4(float(x), float(y), float(z), float(w));              \n"
1939 			   "}";
1940 	}
1941 
Run()1942 	virtual long Run()
1943 	{
1944 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
1945 		glBindAttribLocation(program, 0, "position");
1946 		glBindFragDataLocation(program, 0, "color");
1947 		LinkProgram(program);
1948 
1949 		long error = NO_ERROR;
1950 
1951 		VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, 3, error);
1952 		VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, 2, error);
1953 
1954 		std::map<std::string, GLuint> indicesU;
1955 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
1956 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
1957 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "c", error);
1958 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "d", error);
1959 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "e", error);
1960 
1961 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["a"], "a", error);
1962 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["b"], "b", error);
1963 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["c"], "c", error);
1964 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["d"], "d[0]", error);
1965 		VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["e"], "e", error);
1966 
1967 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", -1, error);
1968 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", -1, error);
1969 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", -1, error);
1970 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d", -1, error);
1971 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "e", -1, error);
1972 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[0]", -1, error);
1973 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[1]", -1, error);
1974 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[2]", -1, error);
1975 
1976 		GLenum		  prop	= GL_ATOMIC_COUNTER_BUFFER_INDEX;
1977 		const GLsizei bufSize = 1000;
1978 		GLsizei		  length;
1979 		GLint		  res;
1980 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, &res);
1981 
1982 		GLenum props[] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES, GL_ACTIVE_VARIABLES };
1983 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, &res);
1984 		GLint expected[] = { 1, 4, 1, static_cast<GLint>(indicesU["a"]) };
1985 		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 4, props, 4, expected, error);
1986 
1987 		GLenum props2[] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES };
1988 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, bufSize, &length, &res);
1989 		GLint expected2[] = { 2, 8, 2 };
1990 		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected2, error);
1991 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["c"], 1, &prop, bufSize, &length, &res);
1992 		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected2, error);
1993 
1994 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["d"], 1, &prop, bufSize, &length, &res);
1995 		GLint expected3[] = { 5, 16, 2 };
1996 		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected3, error);
1997 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["e"], 1, &prop, bufSize, &length, &res);
1998 		VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected3, error);
1999 
2000 		GLenum			 prop2 = GL_ACTIVE_VARIABLES;
2001 		GLint			 param[bufSize];
2002 		std::set<GLuint> exp;
2003 		exp.insert(indicesU["b"]);
2004 		exp.insert(indicesU["c"]);
2005 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, bufSize, &length, &res);
2006 		glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 1, &prop2, bufSize, &length, param);
2007 		for (int i = 0; i < length; ++i)
2008 		{
2009 			if (exp.find(param[i]) == exp.end() || length != 2)
2010 			{
2011 				m_context.getTestContext().getLog()
2012 					<< tcu::TestLog::Message << "Length: " << length
2013 					<< "\nUnexpected index/length found in active variables of ATOMIC_COUNTER_BUFFER: " << param[i]
2014 					<< tcu::TestLog::EndMessage;
2015 				glDeleteProgram(program);
2016 				return ERROR;
2017 			}
2018 		}
2019 		m_context.getTestContext().getLog()
2020 			<< tcu::TestLog::Message << "GL_ACTIVE_VARIABLES ok for 1st ATOMIC_COUNTER_BUFFER"
2021 			<< tcu::TestLog::EndMessage;
2022 		std::set<GLuint> exp2;
2023 		GLint			 param2[bufSize];
2024 		exp2.insert(indicesU["d"]);
2025 		exp2.insert(indicesU["e"]);
2026 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["d"], 1, &prop, bufSize, &length, &res);
2027 		glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 1, &prop2, bufSize, &length, param2);
2028 		for (int i = 0; i < length; ++i)
2029 		{
2030 			if (exp2.find(param2[i]) == exp2.end() || length != 2)
2031 			{
2032 				m_context.getTestContext().getLog()
2033 					<< tcu::TestLog::Message << "Length: " << length
2034 					<< "\nUnexpected index/length found in active variables of ATOMIC_COUNTER_BUFFER: " << param2[i]
2035 					<< tcu::TestLog::EndMessage;
2036 				glDeleteProgram(program);
2037 				return ERROR;
2038 			}
2039 		}
2040 
2041 		glDeleteProgram(program);
2042 		return error;
2043 	}
2044 };
2045 
2046 class SubroutinesBase : public SimpleShaders
2047 {
2048 protected:
ShadersDesc()2049 	virtual std::string ShadersDesc()
2050 	{
2051 		return "fallthrough vertex, geometry, tesselation and fragment shaders with subroutines used";
2052 	}
2053 
VertexShader()2054 	virtual std::string VertexShader()
2055 	{
2056 		return "#version 430                         \n"
2057 			   "in vec4 position;                    \n"
2058 			   ""
2059 			   "subroutine vec4 a_t();               \n"
2060 			   "subroutine uniform a_t a;            \n"
2061 			   "subroutine(a_t) vec4 x() {           \n"
2062 			   "   return vec4(1);                   \n"
2063 			   "}                                    \n"
2064 			   "subroutine(a_t) vec4 y() {           \n"
2065 			   "   return vec4(0);                   \n"
2066 			   "}                                    \n"
2067 			   "void main(void)                      \n"
2068 			   "{                                    \n"
2069 			   "   gl_Position = a();                \n"
2070 			   "}";
2071 	}
2072 
TessControlShader()2073 	virtual std::string TessControlShader()
2074 	{
2075 		return "#version 430                                                  \n"
2076 			   "layout(vertices = 3) out;                                     \n"
2077 			   ""
2078 			   "subroutine vec4 a_t();               \n"
2079 			   "subroutine uniform a_t a;            \n"
2080 			   "subroutine(a_t) vec4 x() {           \n"
2081 			   "   return vec4(1);                   \n"
2082 			   "}                                    \n"
2083 			   ""
2084 			   "void main() {                                                                   \n"
2085 			   "   gl_out[gl_InvocationID].gl_Position = a();                                   \n"
2086 			   "   gl_TessLevelInner[0] = 1.0;                                                  \n"
2087 			   "   gl_TessLevelInner[1] = 1.0;                                                  \n"
2088 			   "   gl_TessLevelOuter[0] = 1.0;                                                  \n"
2089 			   "   gl_TessLevelOuter[1] = 1.0;                                                  \n"
2090 			   "   gl_TessLevelOuter[2] = 1.0;                                                  \n"
2091 			   "}";
2092 	}
2093 
TessEvalShader()2094 	virtual std::string TessEvalShader()
2095 	{
2096 		return "#version 430                                                  \n"
2097 			   "layout(triangles, equal_spacing) in;                          \n"
2098 			   ""
2099 			   "subroutine vec4 a_t();               \n"
2100 			   "subroutine uniform a_t a;            \n"
2101 			   "subroutine(a_t) vec4 x() {           \n"
2102 			   "   return vec4(1);                   \n"
2103 			   "}                                    \n"
2104 			   ""
2105 			   "void main() {                                \n"
2106 			   "   vec4 p0 = gl_in[0].gl_Position;           \n"
2107 			   "   vec4 p1 = gl_in[1].gl_Position;           \n"
2108 			   "   vec4 p2 = gl_in[2].gl_Position;           \n"
2109 			   "   vec3 p = gl_TessCoord.xyz;                \n"
2110 			   "   gl_Position = a();                        \n"
2111 			   "}";
2112 	}
2113 
GeometryShader()2114 	virtual std::string GeometryShader()
2115 	{
2116 		return "#version 430                                                  \n"
2117 			   "layout(triangles) in;                                         \n"
2118 			   "layout(triangle_strip, max_vertices = 4) out;                 \n"
2119 			   ""
2120 			   "subroutine vec4 a_t();               \n"
2121 			   "subroutine uniform a_t a;            \n"
2122 			   "subroutine(a_t) vec4 x() {           \n"
2123 			   "   return vec4(1);                   \n"
2124 			   "}                                    \n"
2125 			   ""
2126 			   "void main() {                              \n"
2127 			   "   gl_Position = vec4(-1, 1, 0, 1);        \n"
2128 			   "   EmitVertex();                           \n"
2129 			   "   gl_Position = vec4(-1, -1, 0, 1);       \n"
2130 			   "   EmitVertex();                           \n"
2131 			   "   gl_Position = vec4(1, 1, 0, 1);         \n"
2132 			   "   EmitVertex();                           \n"
2133 			   "   gl_Position = a();                      \n"
2134 			   "   EmitVertex();                           \n"
2135 			   "   EndPrimitive();                         \n"
2136 			   "}";
2137 	}
2138 
FragmentShader()2139 	virtual std::string FragmentShader()
2140 	{
2141 		return "#version 430                   \n"
2142 			   "out vec4 color;                \n"
2143 			   ""
2144 			   "subroutine vec4 a_t();               \n"
2145 			   "subroutine uniform a_t a;            \n"
2146 			   "subroutine(a_t) vec4 x() {           \n"
2147 			   "   return vec4(1);                   \n"
2148 			   "}                                    \n"
2149 			   ""
2150 			   "void main() {                             \n"
2151 			   "   color = a();                           \n"
2152 			   "}";
2153 	}
2154 
VerifyVS(GLuint program, long& error)2155 	virtual void inline VerifyVS(GLuint program, long& error)
2156 	{
2157 		VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE, GL_ACTIVE_RESOURCES, 2, error);
2158 		VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
2159 
2160 		VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
2161 		VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
2162 		VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 2, error);
2163 
2164 		std::map<std::string, GLuint> indicesS;
2165 		VerifyGetProgramResourceIndex(program, GL_VERTEX_SUBROUTINE, indicesS, "x", error);
2166 		VerifyGetProgramResourceIndex(program, GL_VERTEX_SUBROUTINE, indicesS, "y", error);
2167 		std::map<std::string, GLuint> indicesU;
2168 		VerifyGetProgramResourceIndex(program, GL_VERTEX_SUBROUTINE_UNIFORM, indicesU, "a", error);
2169 
2170 		VerifyGetProgramResourceName(program, GL_VERTEX_SUBROUTINE, indicesS["x"], "x", error);
2171 		VerifyGetProgramResourceName(program, GL_VERTEX_SUBROUTINE, indicesS["y"], "y", error);
2172 		VerifyGetProgramResourceName(program, GL_VERTEX_SUBROUTINE_UNIFORM, indicesU["a"], "a", error);
2173 
2174 		VerifyGetProgramResourceLocation(program, GL_VERTEX_SUBROUTINE_UNIFORM, "a",
2175 										 glGetSubroutineUniformLocation(program, GL_VERTEX_SHADER, "a"), error);
2176 
2177 		GLenum propsS[]	= { GL_NAME_LENGTH };
2178 		GLint  expectedS[] = { 2 };
2179 		VerifyGetProgramResourceiv(program, GL_VERTEX_SUBROUTINE, indicesS["x"], 1, propsS, 1, expectedS, error);
2180 		VerifyGetProgramResourceiv(program, GL_VERTEX_SUBROUTINE, indicesS["y"], 1, propsS, 1, expectedS, error);
2181 
2182 		GLenum propsU[]	= { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION };
2183 		GLint  expectedU[] = { 2, 1, 2, glGetSubroutineUniformLocation(program, GL_VERTEX_SHADER, "a") };
2184 		VerifyGetProgramResourceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, indicesU["a"], 4, propsU, 4, expectedU,
2185 								   error);
2186 
2187 		GLenum			 prop	= GL_COMPATIBLE_SUBROUTINES;
2188 		const GLsizei	bufSize = 1000;
2189 		GLint			 param[bufSize];
2190 		GLsizei			 length;
2191 		std::set<GLuint> exp;
2192 		exp.insert(indicesS["x"]);
2193 		exp.insert(indicesS["y"]);
2194 		glGetProgramResourceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, param);
2195 		for (int i = 0; i < length; ++i)
2196 		{
2197 			if (exp.find(param[i]) == exp.end() || length != 2)
2198 			{
2199 				m_context.getTestContext().getLog()
2200 					<< tcu::TestLog::Message << "Length: " << length
2201 					<< "\nUnexpected index/length found in active variables of GL_VERTEX_SUBROUTINE_UNIFORM: "
2202 					<< param[i] << tcu::TestLog::EndMessage;
2203 				error = ERROR;
2204 			}
2205 		}
2206 	}
2207 
VerifyTCS(GLuint program, long& error)2208 	virtual void inline VerifyTCS(GLuint program, long& error)
2209 	{
2210 		VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE, GL_ACTIVE_RESOURCES, 1, error);
2211 		VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
2212 
2213 		VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
2214 		VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
2215 		VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 1,
2216 									error);
2217 
2218 		std::map<std::string, GLuint> indicesTS;
2219 		VerifyGetProgramResourceIndex(program, GL_TESS_CONTROL_SUBROUTINE, indicesTS, "x", error);
2220 		std::map<std::string, GLuint> indicesTU;
2221 		VerifyGetProgramResourceIndex(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, indicesTU, "a", error);
2222 
2223 		VerifyGetProgramResourceName(program, GL_TESS_CONTROL_SUBROUTINE, indicesTS["x"], "x", error);
2224 		VerifyGetProgramResourceName(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
2225 
2226 		VerifyGetProgramResourceLocation(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, "a",
2227 										 glGetSubroutineUniformLocation(program, GL_TESS_CONTROL_SHADER, "a"), error);
2228 
2229 		GLenum propsS[]	= { GL_NAME_LENGTH };
2230 		GLint  expectedS[] = { 2 };
2231 		VerifyGetProgramResourceiv(program, GL_TESS_CONTROL_SUBROUTINE, static_cast<GLint>(indicesTS["x"]), 1, propsS,
2232 								   1, expectedS, error);
2233 
2234 		GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION,
2235 							GL_COMPATIBLE_SUBROUTINES };
2236 		GLint expectedU[] = { 2, 1, 1, glGetSubroutineUniformLocation(program, GL_TESS_CONTROL_SHADER, "a"),
2237 							  static_cast<GLint>(indicesTS["x"]) };
2238 		VerifyGetProgramResourceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, indicesTU["a"], 5, propsU, 5, expectedU,
2239 								   error);
2240 	}
2241 };
2242 
2243 class SubroutinesVertex : public SubroutinesBase
2244 {
Title()2245 	virtual std::string Title()
2246 	{
2247 		return "Vertex Shader Subroutines Test";
2248 	}
2249 
PurposeExt()2250 	virtual std::string PurposeExt()
2251 	{
2252 		return "\n\n Purpose is to verify calls using *VERTEX_SUBROUTINE* as an interface params.\n";
2253 	}
2254 
Run()2255 	virtual long Run()
2256 	{
2257 		GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
2258 									   GeometryShader().c_str(), FragmentShader().c_str(), false);
2259 		glBindAttribLocation(program, 0, "position");
2260 		glBindFragDataLocation(program, 0, "color");
2261 		LinkProgram(program);
2262 		long error = NO_ERROR;
2263 
2264 		VerifyVS(program, error);
2265 
2266 		glDeleteProgram(program);
2267 		return error;
2268 	}
2269 };
2270 
2271 class SubroutinesTessControl : public SubroutinesBase
2272 {
Title()2273 	virtual std::string Title()
2274 	{
2275 		return "Tess Control Subroutines Test";
2276 	}
2277 
PurposeExt()2278 	virtual std::string PurposeExt()
2279 	{
2280 		return "\n\n Purpose is to verify calls using *TESS_CONTROL_SUBROUTINE* as an interface params.\n";
2281 	}
2282 
Run()2283 	virtual long Run()
2284 	{
2285 		GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
2286 									   GeometryShader().c_str(), FragmentShader().c_str(), false);
2287 		glBindAttribLocation(program, 0, "position");
2288 		glBindFragDataLocation(program, 0, "color");
2289 		LinkProgram(program);
2290 		long error = NO_ERROR;
2291 
2292 		VerifyTCS(program, error);
2293 
2294 		glDeleteProgram(program);
2295 		return error;
2296 	}
2297 };
2298 
2299 class SubroutinesTessEval : public SubroutinesBase
2300 {
Title()2301 	virtual std::string Title()
2302 	{
2303 		return "Tess Evaluation Subroutines Test";
2304 	}
2305 
PurposeExt()2306 	virtual std::string PurposeExt()
2307 	{
2308 		return "\n\n Purpose is to verify calls using *TESS_EVALUATION_SUBROUTINE* as an interface params.\n";
2309 	}
2310 
VerifyTES(GLuint program, long& error)2311 	virtual void inline VerifyTES(GLuint program, long& error)
2312 	{
2313 		VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE, GL_ACTIVE_RESOURCES, 1, error);
2314 		VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
2315 
2316 		VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
2317 		VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
2318 		VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES,
2319 									1, error);
2320 
2321 		std::map<std::string, GLuint> indicesTS;
2322 		VerifyGetProgramResourceIndex(program, GL_TESS_EVALUATION_SUBROUTINE, indicesTS, "x", error);
2323 		std::map<std::string, GLuint> indicesTU;
2324 		VerifyGetProgramResourceIndex(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, indicesTU, "a", error);
2325 
2326 		VerifyGetProgramResourceName(program, GL_TESS_EVALUATION_SUBROUTINE, indicesTS["x"], "x", error);
2327 		VerifyGetProgramResourceName(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
2328 
2329 		VerifyGetProgramResourceLocation(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, "a",
2330 										 glGetSubroutineUniformLocation(program, GL_TESS_EVALUATION_SHADER, "a"),
2331 										 error);
2332 
2333 		GLenum propsS[]	= { GL_NAME_LENGTH };
2334 		GLint  expectedS[] = { 2 };
2335 		VerifyGetProgramResourceiv(program, GL_TESS_EVALUATION_SUBROUTINE, indicesTS["x"], 1, propsS, 1, expectedS,
2336 								   error);
2337 
2338 		GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION,
2339 							GL_COMPATIBLE_SUBROUTINES };
2340 		GLint expectedU[] = { 2, 1, 1, glGetSubroutineUniformLocation(program, GL_TESS_EVALUATION_SHADER, "a"),
2341 							  static_cast<GLint>(indicesTS["x"]) };
2342 		VerifyGetProgramResourceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, indicesTU["a"], 5, propsU, 5,
2343 								   expectedU, error);
2344 	}
2345 
Run()2346 	virtual long Run()
2347 	{
2348 		GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
2349 									   GeometryShader().c_str(), FragmentShader().c_str(), false);
2350 		glBindAttribLocation(program, 0, "position");
2351 		glBindFragDataLocation(program, 0, "color");
2352 		LinkProgram(program);
2353 		long error = NO_ERROR;
2354 
2355 		VerifyTES(program, error);
2356 
2357 		glDeleteProgram(program);
2358 		return error;
2359 	}
2360 };
2361 
2362 class SubroutinesGeometry : public SubroutinesBase
2363 {
Title()2364 	virtual std::string Title()
2365 	{
2366 		return "Geometry Shader Subroutines Test";
2367 	}
2368 
PurposeExt()2369 	virtual std::string PurposeExt()
2370 	{
2371 		return "\n\n Purpose is to verify calls using *GEOMETRY_SUBROUTINE* as an interface params.\n";
2372 	}
2373 
VerifyGEO(GLuint program, long& error)2374 	virtual void inline VerifyGEO(GLuint program, long& error)
2375 	{
2376 		VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE, GL_ACTIVE_RESOURCES, 1, error);
2377 		VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
2378 
2379 		VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
2380 		VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
2381 		VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 1,
2382 									error);
2383 
2384 		std::map<std::string, GLuint> indicesTS;
2385 		VerifyGetProgramResourceIndex(program, GL_GEOMETRY_SUBROUTINE, indicesTS, "x", error);
2386 		std::map<std::string, GLuint> indicesTU;
2387 		VerifyGetProgramResourceIndex(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, indicesTU, "a", error);
2388 
2389 		VerifyGetProgramResourceName(program, GL_GEOMETRY_SUBROUTINE, indicesTS["x"], "x", error);
2390 		VerifyGetProgramResourceName(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
2391 
2392 		VerifyGetProgramResourceLocation(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, "a",
2393 										 glGetSubroutineUniformLocation(program, GL_GEOMETRY_SHADER, "a"), error);
2394 
2395 		GLenum propsS[]	= { GL_NAME_LENGTH };
2396 		GLint  expectedS[] = { 2 };
2397 		VerifyGetProgramResourceiv(program, GL_GEOMETRY_SUBROUTINE, indicesTS["x"], 1, propsS, 1, expectedS, error);
2398 
2399 		GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION,
2400 							GL_COMPATIBLE_SUBROUTINES };
2401 		GLint expectedU[] = { 2, 1, 1, glGetSubroutineUniformLocation(program, GL_GEOMETRY_SHADER, "a"),
2402 							  static_cast<GLint>(indicesTS["x"]) };
2403 		VerifyGetProgramResourceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, indicesTU["a"], 5, propsU, 5, expectedU,
2404 								   error);
2405 	}
2406 
Run()2407 	virtual long Run()
2408 	{
2409 		GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
2410 									   GeometryShader().c_str(), FragmentShader().c_str(), false);
2411 		glBindAttribLocation(program, 0, "position");
2412 		glBindFragDataLocation(program, 0, "color");
2413 		LinkProgram(program);
2414 		long error = NO_ERROR;
2415 
2416 		VerifyGEO(program, error);
2417 
2418 		glDeleteProgram(program);
2419 		return error;
2420 	}
2421 };
2422 
2423 class SubroutinesFragment : public SubroutinesBase
2424 {
Title()2425 	virtual std::string Title()
2426 	{
2427 		return "Fragment Shader Subroutines Test";
2428 	}
2429 
PurposeExt()2430 	virtual std::string PurposeExt()
2431 	{
2432 		return "\n\n Purpose is to verify calls using *FRAGMENT_SUBROUTINE* as an interface params.\n";
2433 	}
2434 
VerifyFS(GLuint program, long& error)2435 	virtual void inline VerifyFS(GLuint program, long& error)
2436 	{
2437 		VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE, GL_ACTIVE_RESOURCES, 1, error);
2438 		VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
2439 
2440 		VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
2441 		VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
2442 		VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 1,
2443 									error);
2444 
2445 		std::map<std::string, GLuint> indicesTS;
2446 		VerifyGetProgramResourceIndex(program, GL_FRAGMENT_SUBROUTINE, indicesTS, "x", error);
2447 		std::map<std::string, GLuint> indicesTU;
2448 		VerifyGetProgramResourceIndex(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, indicesTU, "a", error);
2449 
2450 		VerifyGetProgramResourceName(program, GL_FRAGMENT_SUBROUTINE, indicesTS["x"], "x", error);
2451 		VerifyGetProgramResourceName(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
2452 
2453 		VerifyGetProgramResourceLocation(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, "a",
2454 										 glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "a"), error);
2455 
2456 		GLenum propsS[]	= { GL_NAME_LENGTH };
2457 		GLint  expectedS[] = { 2 };
2458 		VerifyGetProgramResourceiv(program, GL_FRAGMENT_SUBROUTINE, indicesTS["x"], 1, propsS, 1, expectedS, error);
2459 
2460 		GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION,
2461 							GL_COMPATIBLE_SUBROUTINES };
2462 		GLint expectedU[] = { 2, 1, 1, glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "a"),
2463 							  static_cast<GLint>(indicesTS["x"]) };
2464 		VerifyGetProgramResourceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, indicesTU["a"], 5, propsU, 5, expectedU,
2465 								   error);
2466 	}
2467 
Run()2468 	virtual long Run()
2469 	{
2470 		GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
2471 									   GeometryShader().c_str(), FragmentShader().c_str(), false);
2472 		glBindAttribLocation(program, 0, "position");
2473 		glBindFragDataLocation(program, 0, "color");
2474 		LinkProgram(program);
2475 		long error = NO_ERROR;
2476 
2477 		VerifyFS(program, error);
2478 
2479 		glDeleteProgram(program);
2480 		return error;
2481 	}
2482 };
2483 
2484 class SoubroutinesCompute : public PIQBase
2485 {
Title()2486 	virtual std::string Title()
2487 	{
2488 		return "Compute Shader Subroutines Test";
2489 	}
2490 
ShadersDesc()2491 	virtual std::string ShadersDesc()
2492 	{
2493 		return "compute shader with subroutines used";
2494 	}
2495 
PurposeExt()2496 	virtual std::string PurposeExt()
2497 	{
2498 		return "\n\n Purpose is to verify calls using *COMPUTE_SUBROUTINE* as an interface params.\n";
2499 	}
2500 
ComputeShader()2501 	virtual std::string ComputeShader()
2502 	{
2503 		return "layout(local_size_x = 1, local_size_y = 1) in; \n"
2504 
2505 			   "layout(std430) buffer Output {                 \n"
2506 			   "  vec4 data;                                   \n"
2507 			   "} g_out;                                       \n"
2508 			   ""
2509 			   "subroutine vec4 a_t();               \n"
2510 			   "subroutine uniform a_t a;            \n"
2511 			   "subroutine(a_t) vec4 ax() {          \n"
2512 			   "   return vec4(1);                   \n"
2513 			   "}                                    \n"
2514 			   "subroutine(a_t) vec4 ay() {          \n"
2515 			   "   return vec4(0);                   \n"
2516 			   "}                                    \n"
2517 			   ""
2518 			   "subroutine vec4 b_t();               \n"
2519 			   "subroutine uniform b_t b[3];         \n"
2520 			   "subroutine(b_t) vec4 bx() {          \n"
2521 			   "   return vec4(1);                   \n"
2522 			   "}                                    \n"
2523 			   "subroutine(b_t) vec4 by() {          \n"
2524 			   "   return vec4(0);                   \n"
2525 			   "}                                    \n"
2526 			   "subroutine(b_t) vec4 bz() {          \n"
2527 			   "   return vec4(-1);                   \n"
2528 			   "}                                    \n"
2529 			   ""
2530 			   "void main() {                                    \n"
2531 			   "   g_out.data = a() + b[0]() + b[1]() + b[2]();  \n"
2532 			   "}";
2533 	}
2534 
CreateComputeProgram(const std::string& cs)2535 	GLuint CreateComputeProgram(const std::string& cs)
2536 	{
2537 		const GLuint p = glCreateProgram();
2538 
2539 		const char* const kGLSLVer = "#version 430 core\n";
2540 
2541 		if (!cs.empty())
2542 		{
2543 			const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
2544 			glAttachShader(p, sh);
2545 			glDeleteShader(sh);
2546 			const char* const src[2] = { kGLSLVer, cs.c_str() };
2547 			glShaderSource(sh, 2, src, NULL);
2548 			glCompileShader(sh);
2549 		}
2550 
2551 		return p;
2552 	}
2553 
CheckProgram(GLuint program, bool* compile_error = NULL)2554 	bool CheckProgram(GLuint program, bool* compile_error = NULL)
2555 	{
2556 		GLint compile_status = GL_TRUE;
2557 		GLint status;
2558 		glGetProgramiv(program, GL_LINK_STATUS, &status);
2559 
2560 		if (status == GL_FALSE)
2561 		{
2562 			GLint attached_shaders;
2563 			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
2564 
2565 			if (attached_shaders > 0)
2566 			{
2567 				std::vector<GLuint> shaders(attached_shaders);
2568 				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
2569 
2570 				for (GLint i = 0; i < attached_shaders; ++i)
2571 				{
2572 					GLenum type;
2573 					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
2574 					switch (type)
2575 					{
2576 					case GL_VERTEX_SHADER:
2577 						m_context.getTestContext().getLog()
2578 							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
2579 						break;
2580 					case GL_TESS_CONTROL_SHADER:
2581 						m_context.getTestContext().getLog()
2582 							<< tcu::TestLog::Message << "*** Tessellation Control Shader ***"
2583 							<< tcu::TestLog::EndMessage;
2584 						break;
2585 					case GL_TESS_EVALUATION_SHADER:
2586 						m_context.getTestContext().getLog()
2587 							<< tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
2588 							<< tcu::TestLog::EndMessage;
2589 						break;
2590 					case GL_GEOMETRY_SHADER:
2591 						m_context.getTestContext().getLog()
2592 							<< tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
2593 						break;
2594 					case GL_FRAGMENT_SHADER:
2595 						m_context.getTestContext().getLog()
2596 							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
2597 						break;
2598 					case GL_COMPUTE_SHADER:
2599 						m_context.getTestContext().getLog()
2600 							<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
2601 						break;
2602 					default:
2603 						m_context.getTestContext().getLog()
2604 							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
2605 					}
2606 
2607 					GLint res;
2608 					glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &res);
2609 					if (res != GL_TRUE)
2610 						compile_status = res;
2611 
2612 					// shader source
2613 					GLint length;
2614 					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
2615 					if (length > 0)
2616 					{
2617 						std::vector<GLchar> source(length);
2618 						glGetShaderSource(shaders[i], length, NULL, &source[0]);
2619 						m_context.getTestContext().getLog()
2620 							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
2621 					}
2622 
2623 					// shader info log
2624 					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
2625 					if (length > 0)
2626 					{
2627 						std::vector<GLchar> log(length);
2628 						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
2629 						m_context.getTestContext().getLog()
2630 							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
2631 					}
2632 				}
2633 			}
2634 
2635 			// program info log
2636 			GLint length;
2637 			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
2638 			if (length > 0)
2639 			{
2640 				std::vector<GLchar> log(length);
2641 				glGetProgramInfoLog(program, length, NULL, &log[0]);
2642 				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
2643 			}
2644 		}
2645 
2646 		if (compile_error)
2647 			*compile_error = (compile_status == GL_TRUE ? false : true);
2648 		if (compile_status != GL_TRUE)
2649 			return false;
2650 		return status == GL_TRUE ? true : false;
2651 	}
2652 
VerifyCompute(GLuint program, long& error)2653 	virtual void inline VerifyCompute(GLuint program, long& error)
2654 	{
2655 		VerifyGetProgramInterfaceiv(program, GL_COMPUTE_SUBROUTINE, GL_ACTIVE_RESOURCES, 5, error);
2656 		VerifyGetProgramInterfaceiv(program, GL_COMPUTE_SUBROUTINE, GL_MAX_NAME_LENGTH, 3, error);
2657 
2658 		GLint res;
2659 		glGetProgramStageiv(program, GL_COMPUTE_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &res);
2660 		VerifyGetProgramInterfaceiv(program, GL_COMPUTE_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, res, error);
2661 		VerifyGetProgramInterfaceiv(program, GL_COMPUTE_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 5, error);
2662 		VerifyGetProgramInterfaceiv(program, GL_COMPUTE_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 3,
2663 									error);
2664 
2665 		std::map<std::string, GLuint> indicesTS;
2666 		VerifyGetProgramResourceIndex(program, GL_COMPUTE_SUBROUTINE, indicesTS, "ax", error);
2667 		VerifyGetProgramResourceIndex(program, GL_COMPUTE_SUBROUTINE, indicesTS, "ay", error);
2668 		VerifyGetProgramResourceIndex(program, GL_COMPUTE_SUBROUTINE, indicesTS, "bx", error);
2669 		VerifyGetProgramResourceIndex(program, GL_COMPUTE_SUBROUTINE, indicesTS, "by", error);
2670 		VerifyGetProgramResourceIndex(program, GL_COMPUTE_SUBROUTINE, indicesTS, "bz", error);
2671 		std::map<std::string, GLuint> indicesTU;
2672 		VerifyGetProgramResourceIndex(program, GL_COMPUTE_SUBROUTINE_UNIFORM, indicesTU, "a", error);
2673 		VerifyGetProgramResourceIndex(program, GL_COMPUTE_SUBROUTINE_UNIFORM, indicesTU, "b[0]", error);
2674 
2675 		VerifyGetProgramResourceName(program, GL_COMPUTE_SUBROUTINE, indicesTS["ax"], "ax", error);
2676 		VerifyGetProgramResourceName(program, GL_COMPUTE_SUBROUTINE, indicesTS["ay"], "ay", error);
2677 		VerifyGetProgramResourceName(program, GL_COMPUTE_SUBROUTINE, indicesTS["bx"], "bx", error);
2678 		VerifyGetProgramResourceName(program, GL_COMPUTE_SUBROUTINE, indicesTS["by"], "by", error);
2679 		VerifyGetProgramResourceName(program, GL_COMPUTE_SUBROUTINE, indicesTS["bz"], "bz", error);
2680 		VerifyGetProgramResourceName(program, GL_COMPUTE_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
2681 		VerifyGetProgramResourceName(program, GL_COMPUTE_SUBROUTINE_UNIFORM, indicesTU["b[0]"], "b[0]", error);
2682 
2683 		VerifyGetProgramResourceLocation(program, GL_COMPUTE_SUBROUTINE_UNIFORM, "a",
2684 										 glGetSubroutineUniformLocation(program, GL_COMPUTE_SHADER, "a"), error);
2685 		VerifyGetProgramResourceLocation(program, GL_COMPUTE_SUBROUTINE_UNIFORM, "b",
2686 										 glGetSubroutineUniformLocation(program, GL_COMPUTE_SHADER, "b"), error);
2687 
2688 		GLenum propsS[]	= { GL_NAME_LENGTH };
2689 		GLint  expectedS[] = { 3 };
2690 		VerifyGetProgramResourceiv(program, GL_COMPUTE_SUBROUTINE, indicesTS["ax"], 1, propsS, 1, expectedS, error);
2691 		VerifyGetProgramResourceiv(program, GL_COMPUTE_SUBROUTINE, indicesTS["ay"], 1, propsS, 1, expectedS, error);
2692 		VerifyGetProgramResourceiv(program, GL_COMPUTE_SUBROUTINE, indicesTS["bx"], 1, propsS, 1, expectedS, error);
2693 		VerifyGetProgramResourceiv(program, GL_COMPUTE_SUBROUTINE, indicesTS["by"], 1, propsS, 1, expectedS, error);
2694 		VerifyGetProgramResourceiv(program, GL_COMPUTE_SUBROUTINE, indicesTS["bz"], 1, propsS, 1, expectedS, error);
2695 
2696 		GLenum propsU[]	= { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION };
2697 		GLint  expectedU[] = { 2, 1, 2, glGetSubroutineUniformLocation(program, GL_COMPUTE_SHADER, "a") };
2698 		VerifyGetProgramResourceiv(program, GL_COMPUTE_SUBROUTINE_UNIFORM, indicesTU["a"], 4, propsU, 4, expectedU,
2699 								   error);
2700 		GLint expectedU2[] = { 5, 3, 3, glGetSubroutineUniformLocation(program, GL_COMPUTE_SHADER, "b") };
2701 		VerifyGetProgramResourceiv(program, GL_COMPUTE_SUBROUTINE_UNIFORM, indicesTU["b[0]"], 4, propsU, 4, expectedU2,
2702 								   error);
2703 	}
2704 
Run()2705 	virtual long Run()
2706 	{
2707 		GLuint program = CreateComputeProgram(ComputeShader());
2708 		glLinkProgram(program);
2709 		if (!CheckProgram(program))
2710 		{
2711 			glDeleteProgram(program);
2712 			return ERROR;
2713 		}
2714 		glUseProgram(program);
2715 
2716 		long error = NO_ERROR;
2717 
2718 		VerifyCompute(program, error);
2719 
2720 		glDeleteProgram(program);
2721 		return error;
2722 	}
2723 };
2724 
2725 class InvalidValueTest : public SimpleShaders
2726 {
Title()2727 	virtual std::string Title()
2728 	{
2729 		return "Invalid Value Test";
2730 	}
2731 
PassCriteria()2732 	virtual std::string PassCriteria()
2733 	{
2734 		return "GL_INVALID_VALUE error is generated after every function call.";
2735 	}
2736 
Purpose()2737 	virtual std::string Purpose()
2738 	{
2739 		return "Verify that wrong use of functions generates GL_INVALID_VALUE as described in spec.";
2740 	}
2741 
Method()2742 	virtual std::string Method()
2743 	{
2744 		return "Call functions with invalid values and check if GL_INVALID_VALUE was generated.";
2745 	}
2746 
Run()2747 	virtual long Run()
2748 	{
2749 		long error = NO_ERROR;
2750 
2751 		GLint   res = 0;
2752 		GLsizei len = 0;
2753 		GLchar  name[100] = { '\0' };
2754 		GLenum  props[1]  = { GL_NAME_LENGTH };
2755 
2756 		m_context.getTestContext().getLog()
2757 			<< tcu::TestLog::Message << "Case 1: <program> not a name of shader/program object"
2758 			<< tcu::TestLog::EndMessage;
2759 		glGetProgramInterfaceiv(1337u, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &res);
2760 		ExpectError(GL_INVALID_VALUE, error);
2761 		glGetProgramResourceIndex(31337u, GL_PROGRAM_INPUT, "pie");
2762 		ExpectError(GL_INVALID_VALUE, error);
2763 		glGetProgramResourceName(1337u, GL_PROGRAM_INPUT, 0, 1024, &len, name);
2764 		ExpectError(GL_INVALID_VALUE, error);
2765 		glGetProgramResourceiv(1337u, GL_PROGRAM_INPUT, 0, 1, props, 1024, &len, &res);
2766 		ExpectError(GL_INVALID_VALUE, error);
2767 		glGetProgramResourceLocation(1337u, GL_PROGRAM_INPUT, "pie");
2768 		ExpectError(GL_INVALID_VALUE, error);
2769 		glGetProgramResourceLocationIndex(1337u, GL_PROGRAM_OUTPUT, "pie");
2770 		ExpectError(GL_INVALID_VALUE, error);
2771 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 1 finished" << tcu::TestLog::EndMessage;
2772 
2773 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2774 		glBindAttribLocation(program, 0, "position");
2775 		glBindFragDataLocation(program, 0, "color");
2776 		LinkProgram(program);
2777 
2778 		m_context.getTestContext().getLog()
2779 			<< tcu::TestLog::Message
2780 			<< "Case 2: <index> is greater than the number of the active resources in GetProgramResourceName"
2781 			<< tcu::TestLog::EndMessage;
2782 		glGetProgramResourceName(program, GL_PROGRAM_INPUT, 3000, 1024, &len, name);
2783 		ExpectError(GL_INVALID_VALUE, error);
2784 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 2 finished" << tcu::TestLog::EndMessage;
2785 
2786 		m_context.getTestContext().getLog()
2787 			<< tcu::TestLog::Message << "Case 3: <propCount> is zero in GetProgramResourceiv"
2788 			<< tcu::TestLog::EndMessage;
2789 		glGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 0, props, 1024, &len, &res);
2790 		ExpectError(GL_INVALID_VALUE, error);
2791 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 3 finished" << tcu::TestLog::EndMessage;
2792 
2793 		std::string str = "position";
2794 		glGetProgramResourceName(program, GL_PROGRAM_INPUT, 0, -100, NULL, const_cast<char*>(str.c_str()));
2795 		ExpectError(GL_INVALID_VALUE, error);
2796 		GLenum prop = GL_NAME_LENGTH;
2797 		glGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 1, &prop, -100, &len, &res);
2798 		ExpectError(GL_INVALID_VALUE, error);
2799 
2800 		glDeleteProgram(program);
2801 		return error;
2802 	}
2803 };
2804 
2805 class InvalidEnumTest : public AtomicCounterSimple
2806 {
Title()2807 	virtual std::string Title()
2808 	{
2809 		return "Invalid Enum Test";
2810 	}
2811 
PassCriteria()2812 	virtual std::string PassCriteria()
2813 	{
2814 		return "GL_INVALID_ENUM error is generated after every function call.";
2815 	}
2816 
Purpose()2817 	virtual std::string Purpose()
2818 	{
2819 		return "Verify that wrong use of functions generates GL_INVALID_ENUM as described in spec.";
2820 	}
2821 
Method()2822 	virtual std::string Method()
2823 	{
2824 		return "Call functions with invalid enums and check if GL_INVALID_ENUM was generated.";
2825 	}
2826 
Run()2827 	virtual long Run()
2828 	{
2829 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2830 		glBindAttribLocation(program, 0, "position");
2831 		glBindFragDataLocation(program, 0, "color");
2832 		LinkProgram(program);
2833 
2834 		long error = NO_ERROR;
2835 
2836 		GLint   res = 0;
2837 		GLsizei len = 0;
2838 		GLchar  name[100] = { '\0' };
2839 		GLenum  props[1]  = { GL_TEXTURE_1D };
2840 
2841 		m_context.getTestContext().getLog()
2842 			<< tcu::TestLog::Message << "Case 1: <programInterface> is ATOMIC_COUNTER_BUFFER "
2843 			<< "in GetProgramResourceIndex or GetProgramResourceName" << tcu::TestLog::EndMessage;
2844 		glGetProgramResourceIndex(program, GL_ATOMIC_COUNTER_BUFFER, name);
2845 		ExpectError(GL_INVALID_ENUM, error);
2846 		glGetProgramResourceName(program, GL_ATOMIC_COUNTER_BUFFER, 0, 1024, &len, name);
2847 		ExpectError(GL_INVALID_ENUM, error);
2848 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 1 finished" << tcu::TestLog::EndMessage;
2849 
2850 		m_context.getTestContext().getLog()
2851 			<< tcu::TestLog::Message << "Case 2: <props> is not a property name supported by "
2852 			<< "the command GetProgramResourceiv" << tcu::TestLog::EndMessage;
2853 		glGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 1, props, 1024, &len, &res);
2854 		ExpectError(GL_INVALID_ENUM, error);
2855 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 2 finished" << tcu::TestLog::EndMessage;
2856 
2857 		glGetProgramResourceLocation(program, GL_ATOMIC_COUNTER_BUFFER, "position");
2858 		ExpectError(GL_INVALID_ENUM, error);
2859 
2860 		glDeleteProgram(program);
2861 		return error;
2862 	}
2863 };
2864 
2865 class InvalidOperationTest : public SimpleShaders
2866 {
Title()2867 	virtual std::string Title()
2868 	{
2869 		return "Invalid Operation Test";
2870 	}
2871 
PassCriteria()2872 	virtual std::string PassCriteria()
2873 	{
2874 		return "GL_INVALID_OPERATION error is generated after every function call.";
2875 	}
2876 
Purpose()2877 	virtual std::string Purpose()
2878 	{
2879 		return "Verify that wrong use of functions generates GL_INVALID_OPERATION as described in spec.";
2880 	}
2881 
Method()2882 	virtual std::string Method()
2883 	{
2884 		return "Perform invalid operation and check if GL_INVALID_OPERATION was generated.";
2885 	}
2886 
Run()2887 	virtual long Run()
2888 	{
2889 		long error = NO_ERROR;
2890 
2891 		GLuint program  = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2892 		GLuint program2 = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
2893 		glBindAttribLocation(program, 0, "position");
2894 		glBindFragDataLocation(program, 0, "color");
2895 		LinkProgram(program);
2896 
2897 		const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
2898 		GLint		 res = 0;
2899 		GLsizei		 len = 0;
2900 		GLchar		 name[100] = { '\0' };
2901 		GLenum		 props[1]  = { GL_OFFSET };
2902 
2903 		m_context.getTestContext().getLog()
2904 			<< tcu::TestLog::Message << "Case 1: <program> is the name of a shader object" << tcu::TestLog::EndMessage;
2905 		glGetProgramInterfaceiv(sh, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &res);
2906 		ExpectError(GL_INVALID_OPERATION, error);
2907 		glGetProgramResourceIndex(sh, GL_PROGRAM_INPUT, "pie");
2908 		ExpectError(GL_INVALID_OPERATION, error);
2909 		glGetProgramResourceName(sh, GL_PROGRAM_INPUT, 0, 1024, &len, name);
2910 		ExpectError(GL_INVALID_OPERATION, error);
2911 		glGetProgramResourceiv(sh, GL_PROGRAM_INPUT, 0, 1, props, 1024, &len, &res);
2912 		ExpectError(GL_INVALID_OPERATION, error);
2913 		glGetProgramResourceLocation(sh, GL_PROGRAM_INPUT, "pie");
2914 		ExpectError(GL_INVALID_OPERATION, error);
2915 		glGetProgramResourceLocationIndex(sh, GL_PROGRAM_OUTPUT, "pie");
2916 		ExpectError(GL_INVALID_OPERATION, error);
2917 		glDeleteShader(sh);
2918 		m_context.getTestContext().getLog()
2919 			<< tcu::TestLog::Message << "Case 1 finished\n"
2920 			<< "Case 2: <pname> is not supported in GetProgramInterfacei" << tcu::TestLog::EndMessage;
2921 
2922 		glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &res);
2923 		ExpectError(GL_INVALID_OPERATION, error);
2924 		m_context.getTestContext().getLog()
2925 			<< tcu::TestLog::Message << "Case 2 finished\n"
2926 			<< "Case 3: <props> is not supported in GetProgramResourceiv" << tcu::TestLog::EndMessage;
2927 
2928 		glGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 1, props, 1024, &len, &res);
2929 		ExpectError(GL_INVALID_OPERATION, error);
2930 		m_context.getTestContext().getLog()
2931 			<< tcu::TestLog::Message << "Case 3 finished\n"
2932 			<< "Case 4: <program> has not been linked in GetProgramResourceLocation/GetProgramResourceLocationIndex"
2933 			<< tcu::TestLog::EndMessage;
2934 
2935 		glGetProgramResourceLocation(program2, GL_PROGRAM_INPUT, "pie");
2936 		ExpectError(GL_INVALID_OPERATION, error);
2937 		glGetProgramResourceLocationIndex(program2, GL_PROGRAM_OUTPUT, "pie");
2938 		ExpectError(GL_INVALID_OPERATION, error);
2939 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Case 4 finished\n" << tcu::TestLog::EndMessage;
2940 
2941 		glDeleteProgram(program);
2942 		glDeleteProgram(program2);
2943 		return error;
2944 	}
2945 };
2946 
2947 class ShaderStorageBlock : public SimpleShaders
2948 {
Title()2949 	virtual std::string Title()
2950 	{
2951 		return "Shader Storage Block Test";
2952 	}
2953 
ShadersDesc()2954 	virtual std::string ShadersDesc()
2955 	{
2956 		return "fallthrough fragment and vertex shaders with different types of storage blocks used";
2957 	}
2958 
PurposeExt()2959 	virtual std::string PurposeExt()
2960 	{
2961 		return "\n\n Purpose is to verify calls using GL_BUFFER_VARIABLE and GL_SHADER_STORAGE_BLOCK as an interface "
2962 			   "params.\n";
2963 	}
2964 
FragmentShader()2965 	virtual std::string FragmentShader()
2966 	{
2967 		return "#version 430                   \n"
2968 			   ""
2969 			   "struct U {                     \n"
2970 			   "   bool a[3];                  \n"
2971 			   "   mediump vec4 b;             \n"
2972 			   "   mediump mat3 c;             \n"
2973 			   "   mediump float d[2];         \n"
2974 			   "};                             \n"
2975 			   ""
2976 			   "struct UU {                    \n"
2977 			   "   U a;                        \n"
2978 			   "   U b[2];                     \n"
2979 			   "   uvec2 c;                    \n"
2980 			   "};                             \n"
2981 			   ""
2982 			   "layout(binding=4) buffer TrickyBuffer {          \n"
2983 			   "   UU a[3];                                      \n"
2984 			   "   mediump mat4 b;                               \n"
2985 			   "   uint c;                                       \n"
2986 			   "} e[2];                                          \n"
2987 			   ""
2988 			   "layout(binding = 0) buffer SimpleBuffer {        \n"
2989 			   "   mediump mat3x2 a;                             \n"
2990 			   "   mediump mat4 b;                               \n"
2991 			   "   mediump vec4 c;                               \n"
2992 			   "};                                               \n"
2993 			   ""
2994 			   "layout(binding = 1) buffer NotSoSimpleBuffer {   \n"
2995 			   "   ivec2 a[4];                                   \n"
2996 			   "   mediump mat3 b[2];                            \n"
2997 			   "   mediump mat2 c;                               \n"
2998 			   "} d;                                             \n"
2999 			   ""
3000 			   "out mediump vec4 color;                          \n"
3001 			   ""
3002 			   "void main() {                                    \n"
3003 			   "    mediump float tmp;                           \n"
3004 			   "    mediump float tmp2;                          \n"
3005 			   "    tmp = e[0].a[0].b[0].d[0] * float(e[1].c);   \n"
3006 			   "    tmp2 = a[0][0] * b[0][0] * c.x;                                \n"
3007 			   "    tmp2 = tmp2 + float(d.a[0].y) + d.b[0][0][0] + d.c[0][0];      \n"
3008 			   "    color = vec4(0, 1, 0, 1) * tmp * tmp2;                         \n"
3009 			   "}";
3010 	}
3011 
Run()3012 	virtual long Run()
3013 	{
3014 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3015 		glBindAttribLocation(program, 0, "position");
3016 		glBindFragDataLocation(program, 0, "color");
3017 		LinkProgram(program);
3018 
3019 		long error = NO_ERROR;
3020 
3021 		GLint res;
3022 		VerifyGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_MAX_NAME_LENGTH, 28, error);
3023 		glGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_ACTIVE_RESOURCES, &res);
3024 		if (res < 7)
3025 		{
3026 			m_context.getTestContext().getLog()
3027 				<< tcu::TestLog::Message
3028 				<< "Error on: glGetProgramInterfaceiv, if: GL_BUFFER_VARIABLE, param: GL_ACTIVE_RESOURCES\n"
3029 				<< "Expected value greater or equal to 7, got " << res << tcu::TestLog::EndMessage;
3030 			error = ERROR;
3031 		}
3032 		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, 4, error);
3033 		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, 18, error);
3034 
3035 		std::map<std::string, GLuint> indicesSSB;
3036 		std::map<std::string, GLuint> indicesBV;
3037 		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "SimpleBuffer", error);
3038 		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "NotSoSimpleBuffer", error);
3039 		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "TrickyBuffer", error);
3040 		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "TrickyBuffer[1]", error);
3041 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "a", error);
3042 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "b", error);
3043 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "c", error);
3044 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "NotSoSimpleBuffer.a[0]", error);
3045 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "NotSoSimpleBuffer.c", error);
3046 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "NotSoSimpleBuffer.b[0]", error);
3047 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "TrickyBuffer.a[0].b[0].d", error);
3048 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "TrickyBuffer.b", error);
3049 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "TrickyBuffer.c", error);
3050 
3051 		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["SimpleBuffer"], "SimpleBuffer",
3052 									 error);
3053 		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["NotSoSimpleBuffer"],
3054 									 "NotSoSimpleBuffer", error);
3055 		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["TrickyBuffer"], "TrickyBuffer[0]",
3056 									 error);
3057 		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["TrickyBuffer[1]"], "TrickyBuffer[1]",
3058 									 error);
3059 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["a"], "a", error);
3060 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["b"], "b", error);
3061 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["c"], "c", error);
3062 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["NotSoSimpleBuffer.a[0]"],
3063 									 "NotSoSimpleBuffer.a[0]", error);
3064 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["NotSoSimpleBuffer.c"],
3065 									 "NotSoSimpleBuffer.c", error);
3066 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["NotSoSimpleBuffer.b[0]"],
3067 									 "NotSoSimpleBuffer.b[0]", error);
3068 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["TrickyBuffer.a[0].b[0].d"],
3069 									 "TrickyBuffer.a[0].b[0].d[0]", error);
3070 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["TrickyBuffer.b"], "TrickyBuffer.b", error);
3071 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["TrickyBuffer.c"], "TrickyBuffer.c", error);
3072 
3073 		GLenum props[] = { GL_NAME_LENGTH,
3074 						   GL_BUFFER_BINDING,
3075 						   GL_NUM_ACTIVE_VARIABLES,
3076 						   GL_REFERENCED_BY_COMPUTE_SHADER,
3077 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
3078 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
3079 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3080 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3081 						   GL_REFERENCED_BY_VERTEX_SHADER };
3082 		GLint expected[] = { 13, 0, 3, 0, 1, 0, 0, 0, 0 };
3083 		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["SimpleBuffer"], 9, props, 9, expected,
3084 								   error);
3085 
3086 		GLenum props2[] = { GL_NAME_LENGTH,
3087 							GL_BUFFER_BINDING,
3088 							GL_REFERENCED_BY_COMPUTE_SHADER,
3089 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3090 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3091 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3092 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3093 							GL_REFERENCED_BY_VERTEX_SHADER };
3094 		GLint expected2[] = { 18, 1, 0, 1, 0, 0, 0, 0 };
3095 		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["NotSoSimpleBuffer"], 8, props2, 8,
3096 								   expected2, error);
3097 		GLint expected3[] = { 16, 4, 0, 1, 0, 0, 0, 0 };
3098 		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["TrickyBuffer"], 8, props2, 8,
3099 								   expected3, error);
3100 		GLint expected4[] = { 16, 5, 0, 1, 0, 0, 0, 0 };
3101 		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["TrickyBuffer[1]"], 8, props2, 8,
3102 								   expected4, error);
3103 
3104 		GLenum props3[] = { GL_NAME_LENGTH,
3105 							GL_TYPE,
3106 							GL_ARRAY_SIZE,
3107 							GL_BLOCK_INDEX,
3108 							GL_ARRAY_STRIDE,
3109 							GL_IS_ROW_MAJOR,
3110 							GL_REFERENCED_BY_COMPUTE_SHADER,
3111 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3112 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3113 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3114 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3115 							GL_REFERENCED_BY_VERTEX_SHADER,
3116 							GL_TOP_LEVEL_ARRAY_SIZE,
3117 							GL_TOP_LEVEL_ARRAY_STRIDE };
3118 		GLint expected5[] = {
3119 			2, GL_FLOAT_MAT3x2, 1, static_cast<GLint>(indicesSSB["SimpleBuffer"]), 0, 0, 0, 1, 0, 0, 0, 0, 1, 0
3120 		};
3121 		VerifyGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["a"], 14, props3, 14, expected5, error);
3122 
3123 		GLenum props4[] = { GL_NAME_LENGTH,
3124 							GL_TYPE,
3125 							GL_ARRAY_SIZE,
3126 							GL_BLOCK_INDEX,
3127 							GL_MATRIX_STRIDE,
3128 							GL_IS_ROW_MAJOR,
3129 							GL_REFERENCED_BY_COMPUTE_SHADER,
3130 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3131 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3132 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3133 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3134 							GL_REFERENCED_BY_VERTEX_SHADER,
3135 							GL_TOP_LEVEL_ARRAY_SIZE };
3136 		GLint expected6[] = {
3137 			28, GL_FLOAT, 2, static_cast<GLint>(indicesSSB["TrickyBuffer"]), 0, 0, 0, 1, 0, 0, 0, 0, 3
3138 		};
3139 		VerifyGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["TrickyBuffer.a[0].b[0].d"], 13, props4, 13,
3140 								   expected6, error);
3141 
3142 		GLenum			 prop	= GL_ACTIVE_VARIABLES;
3143 		const GLsizei	bufSize = 1000;
3144 		GLsizei			 length;
3145 		GLint			 param[bufSize];
3146 		std::set<GLuint> exp;
3147 		exp.insert(indicesBV["a"]);
3148 		exp.insert(indicesBV["b"]);
3149 		exp.insert(indicesBV["c"]);
3150 		glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["SimpleBuffer"], 1, &prop, bufSize, &length,
3151 							   param);
3152 		for (int i = 0; i < length; ++i)
3153 		{
3154 			if (exp.find(param[i]) == exp.end())
3155 			{
3156 				m_context.getTestContext().getLog()
3157 					<< tcu::TestLog::Message
3158 					<< "Unexpected index found in active variables of SimpleBuffer: " << param[i]
3159 					<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: "
3160 					   "GL_SHADER_STORAGE_BLOCK"
3161 					<< tcu::TestLog::EndMessage;
3162 				glDeleteProgram(program);
3163 				return ERROR;
3164 			}
3165 			else if (length != 3)
3166 			{
3167 				m_context.getTestContext().getLog()
3168 					<< tcu::TestLog::Message << "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES "
3169 												"interface: GL_SHADER_STORAGE_BLOCK\n"
3170 					<< "Expected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
3171 				glDeleteProgram(program);
3172 				return ERROR;
3173 			}
3174 		}
3175 		std::set<GLuint> exp2;
3176 		exp2.insert(indicesBV["NotSoSimpleBuffer.a[0]"]);
3177 		exp2.insert(indicesBV["NotSoSimpleBuffer.b[0]"]);
3178 		exp2.insert(indicesBV["NotSoSimpleBuffer.c"]);
3179 		glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["NotSoSimpleBuffer"], 1, &prop, bufSize,
3180 							   &length, param);
3181 		for (int i = 0; i < length; ++i)
3182 		{
3183 			if (exp2.find(param[i]) == exp2.end())
3184 			{
3185 				m_context.getTestContext().getLog()
3186 					<< tcu::TestLog::Message
3187 					<< "Unexpected index found in active variables of NotSoSimpleBuffer: " << param[i]
3188 					<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: "
3189 					   "GL_SHADER_STORAGE_BLOCK"
3190 					<< tcu::TestLog::EndMessage;
3191 				glDeleteProgram(program);
3192 				return ERROR;
3193 			}
3194 			else if (length != 3)
3195 			{
3196 				m_context.getTestContext().getLog()
3197 					<< tcu::TestLog::Message << "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES "
3198 												"interface: GL_SHADER_STORAGE_BLOCK\n"
3199 					<< "Expected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
3200 				glDeleteProgram(program);
3201 				return ERROR;
3202 			}
3203 		}
3204 
3205 		glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &res);
3206 		if (res < 3)
3207 		{
3208 			m_context.getTestContext().getLog()
3209 				<< tcu::TestLog::Message << "Value of GL_MAX_NUM_ACTIVE_VARIABLES less than 3!\n"
3210 				<< "Call: glGetProgramInterfaceiv, interface: GL_SHADER_STORAGE_BLOCK" << tcu::TestLog::EndMessage;
3211 			return ERROR;
3212 		}
3213 
3214 		glDeleteProgram(program);
3215 		return error;
3216 	}
3217 };
3218 
3219 class UniformBlockArray : public SimpleShaders
3220 {
Title()3221 	virtual std::string Title()
3222 	{
3223 		return "Uniform Block Array Test";
3224 	}
3225 
ShadersDesc()3226 	virtual std::string ShadersDesc()
3227 	{
3228 		return "verify BLOCK_INDEX property when an interface block is declared as an array of block instances";
3229 	}
3230 
PurposeExt()3231 	virtual std::string PurposeExt()
3232 	{
3233 		return "\n\n Purpose is to verify calls using GL_BLOCK_INDEX as an interface param.\n";
3234 	}
3235 
VertexShader()3236 	virtual std::string VertexShader()
3237 	{
3238 		return "#version 430                    \n"
3239 			   "void main(void)                 \n"
3240 			   "{                               \n"
3241 			   "    gl_Position = vec4(1.0);    \n"
3242 			   "}";
3243 	}
3244 
FragmentShader()3245 	virtual std::string FragmentShader()
3246 	{
3247 		return "#version 430                   \n"
3248 			   "uniform TestBlock {            \n"
3249 			   "   mediump vec4 color;         \n"
3250 			   "} blockInstance[4];            \n"
3251 			   ""
3252 			   "out mediump vec4 color;                                      \n"
3253 			   "void main() {                                                \n"
3254 			   "    color = blockInstance[2].color + blockInstance[3].color; \n"
3255 			   "}";
3256 	}
3257 
Run()3258 	virtual long Run()
3259 	{
3260 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3261 		LinkProgram(program);
3262 
3263 		long error = NO_ERROR;
3264 
3265 		std::map<std::string, GLuint> indicesUB;
3266 		VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "TestBlock", error);
3267 
3268 		std::map<std::string, GLuint> indicesU;
3269 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "TestBlock.color", error);
3270 
3271 		GLenum props[]	= { GL_BLOCK_INDEX };
3272 		GLint  expected[] = { static_cast<GLint>(indicesUB["TestBlock"]) };
3273 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["TestBlock.color"], 1, props, 1, expected, error);
3274 
3275 		glDeleteProgram(program);
3276 		return error;
3277 	}
3278 };
3279 
3280 class TransformFeedbackBuiltin : public SimpleShaders
3281 {
Title()3282 	virtual std::string Title()
3283 	{
3284 		return "Transform Feedback Built-in Variables";
3285 	}
3286 
ShadersDesc()3287 	virtual std::string ShadersDesc()
3288 	{
3289 		return "fallthrough fragment and vertex shaders with different types of out variables used";
3290 	}
3291 
PurposeExt()3292 	virtual std::string PurposeExt()
3293 	{
3294 		return "\n\n Purpose is to verify calls using GL_TRANSFORM_FEEDBACK_VARYING as an interface param with"
3295 			   " built-in variables (gl_NextBuffer, gl_SkipComponents) used.\n";
3296 	}
3297 
VertexShader()3298 	virtual std::string VertexShader()
3299 	{
3300 		return "#version 430                         \n"
3301 			   "in vec4 position;                    \n"
3302 			   ""
3303 			   "out ivec4 a;                         \n"
3304 			   "out uvec2 c;                         \n"
3305 			   "out uint d;                          \n"
3306 			   "out int f;                           \n"
3307 			   "out uint e;                          \n"
3308 			   "out int g;                           \n"
3309 			   ""
3310 			   "void main(void)                      \n"
3311 			   "{                                    \n"
3312 			   "   vec4 pos;                         \n"
3313 			   "   a = ivec4(1);                     \n"
3314 			   "   c = uvec2(1u);                    \n"
3315 			   "   d = 1u;                           \n"
3316 			   "   f = 1;                            \n"
3317 			   "   e = 1u;                           \n"
3318 			   "   g = 1;                            \n"
3319 			   "   gl_Position = position;           \n"
3320 			   "}";
3321 	}
3322 
Run()3323 	virtual long Run()
3324 	{
3325 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3326 		glBindAttribLocation(program, 0, "position");
3327 		glBindFragDataLocation(program, 0, "color");
3328 		const char* varyings[11] = { "a", "gl_NextBuffer",		"c", "gl_SkipComponents1", "d", "gl_SkipComponents2",
3329 									 "f", "gl_SkipComponents3", "e", "gl_SkipComponents4", "g" };
3330 		glTransformFeedbackVaryings(program, 11, varyings, GL_INTERLEAVED_ATTRIBS);
3331 		LinkProgram(program);
3332 
3333 		long error = NO_ERROR;
3334 
3335 		VerifyGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_ACTIVE_RESOURCES, 11, error);
3336 		VerifyGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_MAX_NAME_LENGTH, 19, error);
3337 
3338 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "gl_NextBuffer", GL_INVALID_INDEX, error);
3339 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "gl_SkipComponents1", GL_INVALID_INDEX,
3340 									  error);
3341 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "gl_SkipComponents2", GL_INVALID_INDEX,
3342 									  error);
3343 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "gl_SkipComponents3", GL_INVALID_INDEX,
3344 									  error);
3345 		VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "gl_SkipComponents4", GL_INVALID_INDEX,
3346 									  error);
3347 
3348 		std::map<std::string, GLuint> indices;
3349 		for (int i = 0; i < 11; i++)
3350 		{
3351 			GLsizei length;
3352 			GLchar  name[1024] = { '\0' };
3353 			glGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, i, 1024, &length, name);
3354 			indices[name] = i;
3355 		}
3356 
3357 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Indices of builtins:\n"
3358 											<< indices["gl_NextBuffer"] << ", " << indices["gl_SkipComponents1"] << ", "
3359 											<< indices["gl_SkipComponents2"] << ", " << indices["gl_SkipComponents3"]
3360 											<< ", " << indices["gl_SkipComponents4"] << tcu::TestLog::EndMessage;
3361 
3362 		GLenum props[]	= { GL_NAME_LENGTH, GL_TYPE, GL_ARRAY_SIZE };
3363 		GLint  expected[] = { 14, GL_NONE, 0 };
3364 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["gl_NextBuffer"], 3, props, 3,
3365 								   expected, error);
3366 		GLint expected2[] = { 19, GL_NONE, 1 };
3367 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["gl_SkipComponents1"], 3, props, 3,
3368 								   expected2, error);
3369 		GLint expected3[] = { 19, GL_NONE, 2 };
3370 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["gl_SkipComponents2"], 3, props, 3,
3371 								   expected3, error);
3372 		GLint expected4[] = { 19, GL_NONE, 3 };
3373 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["gl_SkipComponents3"], 3, props, 3,
3374 								   expected4, error);
3375 		GLint expected5[] = { 19, GL_NONE, 4 };
3376 		VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["gl_SkipComponents4"], 3, props, 3,
3377 								   expected5, error);
3378 
3379 		glDeleteProgram(program);
3380 		return error;
3381 	}
3382 };
3383 
3384 class NullLength : public SimpleShaders
3385 {
3386 
Title()3387 	virtual std::string Title()
3388 	{
3389 		return "NULL Length Test";
3390 	}
3391 
PurposeExt()3392 	virtual std::string PurposeExt()
3393 	{
3394 		return "\n\n Purpose is to verify that GetProgramResourceName with null length doesn't return length (doesn't "
3395 			   "crash).\n";
3396 	}
3397 
VertexShader()3398 	virtual std::string VertexShader()
3399 	{
3400 		return "#version 430                         \n"
3401 			   "in vec4 position;                    \n"
3402 			   "void main(void)                      \n"
3403 			   "{                                    \n"
3404 			   "    gl_Position = position;          \n"
3405 			   "}";
3406 	}
3407 
FragmentShader()3408 	virtual std::string FragmentShader()
3409 	{
3410 		return "#version 430                   \n"
3411 			   "out vec4 color;                \n"
3412 			   "void main() {                  \n"
3413 			   "    color = vec4(0, 1, 0, 1);  \n"
3414 			   "}";
3415 	}
3416 
Run()3417 	virtual long Run()
3418 	{
3419 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3420 		glBindAttribLocation(program, 0, "position");
3421 		glBindFragDataLocation(program, 0, "color");
3422 		LinkProgram(program);
3423 
3424 		GLchar name[1024] = { '\0' };
3425 		GLuint index	  = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "color");
3426 		GLenum prop		  = GL_ARRAY_SIZE;
3427 		GLint  res;
3428 		glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, 0, 1024, NULL, name);
3429 		glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, 1, &prop, 1, NULL, &res);
3430 
3431 		std::string expected = "color";
3432 		if (name != expected)
3433 		{
3434 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Expected name: " << expected
3435 												<< ", got: " << name << tcu::TestLog::EndMessage;
3436 			glDeleteProgram(program);
3437 			return ERROR;
3438 		}
3439 		else if (res != 1)
3440 		{
3441 			m_context.getTestContext().getLog()
3442 				<< tcu::TestLog::Message << "Expected array_size: 1, got: " << res << tcu::TestLog::EndMessage;
3443 			glDeleteProgram(program);
3444 			return ERROR;
3445 		}
3446 
3447 		glDeleteProgram(program);
3448 		return NO_ERROR;
3449 	}
3450 };
3451 
3452 class ArraysOfArrays : public SimpleShaders
3453 {
3454 
Title()3455 	virtual std::string Title()
3456 	{
3457 		return "Arrays Of Arrays Test";
3458 	}
3459 
ShadersDesc()3460 	virtual std::string ShadersDesc()
3461 	{
3462 		return "fallthrough fragment and vertex shaders with multi dimensional uniform array used";
3463 	}
3464 
PurposeExt()3465 	virtual std::string PurposeExt()
3466 	{
3467 		return "\n\n Purpose is to verify that feature works correctly with arrays_of_arrays extension.\n";
3468 	}
3469 
VertexShader()3470 	virtual std::string VertexShader()
3471 	{
3472 		return "#version 430                         \n"
3473 			   "in vec4 position;                    \n"
3474 			   "uniform vec4 a[3][4][5];             \n"
3475 			   "void main(void)                      \n"
3476 			   "{                                    \n"
3477 			   "    gl_Position = position;          \n"
3478 			   "    for (int i = 0; i < 5; ++i)      \n"
3479 			   "        gl_Position += a[2][1][i];   \n"
3480 			   "}";
3481 	}
3482 
FragmentShader()3483 	virtual std::string FragmentShader()
3484 	{
3485 		return "#version 430                   \n"
3486 			   "out vec4 color;                \n"
3487 			   "void main() {                  \n"
3488 			   "    color = vec4(0, 1, 0, 1);  \n"
3489 			   "}";
3490 	}
3491 
Run()3492 	virtual long Run()
3493 	{
3494 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3495 		glBindAttribLocation(program, 0, "position");
3496 		glBindFragDataLocation(program, 0, "color");
3497 		LinkProgram(program);
3498 
3499 		long error = NO_ERROR;
3500 
3501 		VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, 11, error);
3502 
3503 		std::map<std::string, GLuint> indices;
3504 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "a[2][1]", error);
3505 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, "a[2][1][0]", indices["a[2][1]"], error);
3506 
3507 		VerifyGetProgramResourceName(program, GL_UNIFORM, indices["a[2][1]"], "a[2][1][0]", error);
3508 
3509 		GLenum props[] = { GL_NAME_LENGTH,
3510 						   GL_TYPE,
3511 						   GL_ARRAY_SIZE,
3512 						   GL_OFFSET,
3513 						   GL_BLOCK_INDEX,
3514 						   GL_ARRAY_STRIDE,
3515 						   GL_MATRIX_STRIDE,
3516 						   GL_IS_ROW_MAJOR,
3517 						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
3518 						   GL_REFERENCED_BY_COMPUTE_SHADER,
3519 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
3520 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
3521 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3522 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3523 						   GL_REFERENCED_BY_VERTEX_SHADER,
3524 						   GL_LOCATION };
3525 		GLint expected[] = {
3526 			11, GL_FLOAT_VEC4, 5, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "a[2][1]")
3527 		};
3528 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["a[2][1]"], 16, props, 16, expected, error);
3529 
3530 		glDeleteProgram(program);
3531 		return error;
3532 	}
3533 };
3534 
3535 class TopLevelArray : public SimpleShaders
3536 {
3537 
Title()3538 	virtual std::string Title()
3539 	{
3540 		return "Top Level Array Test";
3541 	}
3542 
ShadersDesc()3543 	virtual std::string ShadersDesc()
3544 	{
3545 		return "fallthrough fragment and vertex shaders with multi dimensional array used inside storage block";
3546 	}
3547 
PurposeExt()3548 	virtual std::string PurposeExt()
3549 	{
3550 		return "\n\n Purpose is to verify that feature works correctly when querying for GL_TOP_LEVEL_ARRAY_SIZE\n"
3551 			   " and GL_TOP_LEVEL_ARRAY_STRIDE extension.\n";
3552 	}
3553 
FragmentShader()3554 	virtual std::string FragmentShader()
3555 	{
3556 		return "#version 430                   \n"
3557 			   "buffer Block {                       \n"
3558 			   "   vec4 a[5][4][3];                  \n"
3559 			   "};                                   \n"
3560 			   "out vec4 color;                             \n"
3561 			   "void main() {                               \n"
3562 			   "    color = vec4(0, 1, 0, 1) + a[0][0][0];  \n"
3563 			   "}";
3564 	}
3565 
Run()3566 	virtual long Run()
3567 	{
3568 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
3569 		glBindAttribLocation(program, 0, "position");
3570 		glBindFragDataLocation(program, 0, "color");
3571 		LinkProgram(program);
3572 
3573 		long error = NO_ERROR;
3574 
3575 		VerifyGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_MAX_NAME_LENGTH, 11, error);
3576 		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, 6, error);
3577 		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, 1, error);
3578 
3579 		std::map<std::string, GLuint> indicesSSB;
3580 		std::map<std::string, GLuint> indicesBV;
3581 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "a[0][0]", error);
3582 		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "Block", error);
3583 
3584 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["a[0][0]"], "a[0][0][0]", error);
3585 		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["Block"], "Block", error);
3586 
3587 		GLenum props3[] = { GL_NAME_LENGTH,
3588 							GL_TYPE,
3589 							GL_ARRAY_SIZE,
3590 							GL_BLOCK_INDEX,
3591 							GL_IS_ROW_MAJOR,
3592 							GL_REFERENCED_BY_COMPUTE_SHADER,
3593 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3594 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3595 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3596 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3597 							GL_REFERENCED_BY_VERTEX_SHADER,
3598 							GL_TOP_LEVEL_ARRAY_SIZE };
3599 		GLint expected5[] = { 11, GL_FLOAT_VEC4, 3, static_cast<GLint>(indicesSSB["Block"]), 0, 0, 1, 0, 0, 0, 0, 5 };
3600 		VerifyGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["a[0][0]"], 12, props3, 12, expected5, error);
3601 
3602 		GLenum  prop = GL_TOP_LEVEL_ARRAY_STRIDE;
3603 		GLsizei len;
3604 		GLint   res;
3605 		glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["a[0][0]"], 1, &prop, 1024, &len, &res);
3606 		if (res <= 0)
3607 		{
3608 			m_context.getTestContext().getLog()
3609 				<< tcu::TestLog::Message
3610 				<< "Call: glGetProgramResourceiv, interface: GL_BUFFER_VARIABLE, param: GL_TOP_LEVEL_ARRAY_STRIDE\n"
3611 				<< "Expected value greater than 0, got: " << res << tcu::TestLog::EndMessage;
3612 			glDeleteProgram(program);
3613 			return ERROR;
3614 		}
3615 
3616 		glDeleteProgram(program);
3617 		return error;
3618 	}
3619 };
3620 
3621 class SeparateProgramsVertex : public SimpleShaders
3622 {
3623 public:
Title()3624 	virtual std::string Title()
3625 	{
3626 		return "Separate Program Vertex Shader Test";
3627 	}
3628 
ShadersDesc()3629 	virtual std::string ShadersDesc()
3630 	{
3631 		return "vertex shader as separate shader object";
3632 	}
3633 
PurposeExt()3634 	virtual std::string PurposeExt()
3635 	{
3636 		return "\n\n Purpose is to verify that feature works correctly when using separate_shader_objects "
3637 			   "functionality.\n";
3638 	}
3639 
CreateShaderProgram(GLenum type, GLsizei count, const GLchar** strings)3640 	virtual GLuint CreateShaderProgram(GLenum type, GLsizei count, const GLchar** strings)
3641 	{
3642 		GLuint program = glCreateShaderProgramv(type, count, strings);
3643 		GLint  status  = GL_TRUE;
3644 		glGetProgramiv(program, GL_LINK_STATUS, &status);
3645 		if (status == GL_FALSE)
3646 		{
3647 			GLsizei length;
3648 			GLchar  log[1024];
3649 			glGetProgramInfoLog(program, sizeof(log), &length, log);
3650 			if (length > 1)
3651 			{
3652 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
3653 													<< log << tcu::TestLog::EndMessage;
3654 			}
3655 		}
3656 		return program;
3657 	}
3658 
Run()3659 	virtual long Run()
3660 	{
3661 		long error = NO_ERROR;
3662 
3663 		const char* srcVS = "#version 430 core                          \n"
3664 							"layout(location = 0) in vec4 in_vertex;    \n"
3665 							""
3666 							"out Color {                                \n"
3667 							"  float r, g, b;                           \n"
3668 							"  vec4 iLikePie;                           \n"
3669 							"} vs_color;                                \n"
3670 							"out gl_PerVertex {                         \n"
3671 							"  vec4 gl_Position;                        \n"
3672 							"};                                         \n"
3673 							""
3674 							"uniform float u;                           \n"
3675 							"uniform vec4 v;                            \n"
3676 							""
3677 							"void main() {                              \n"
3678 							"  gl_Position = in_vertex;                 \n"
3679 							"  vs_color.r = u;                          \n"
3680 							"  vs_color.g = 0.0;                        \n"
3681 							"  vs_color.b = 0.0;                        \n"
3682 							"  vs_color.iLikePie = v;                   \n"
3683 							"}";
3684 
3685 		const GLuint vs = CreateShaderProgram(GL_VERTEX_SHADER, 1, &srcVS);
3686 
3687 		VerifyGetProgramInterfaceiv(vs, GL_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
3688 		VerifyGetProgramInterfaceiv(vs, GL_UNIFORM, GL_ACTIVE_RESOURCES, 2, error);
3689 		VerifyGetProgramInterfaceiv(vs, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 10, error);
3690 		VerifyGetProgramInterfaceiv(vs, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
3691 		VerifyGetProgramInterfaceiv(vs, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 15, error);
3692 		VerifyGetProgramInterfaceiv(vs, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 5, error);
3693 
3694 		std::map<std::string, GLuint> indicesU;
3695 		std::map<std::string, GLuint> indicesI;
3696 		std::map<std::string, GLuint> indicesO;
3697 		VerifyGetProgramResourceIndex(vs, GL_UNIFORM, indicesU, "u", error);
3698 		VerifyGetProgramResourceIndex(vs, GL_UNIFORM, indicesU, "v", error);
3699 		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_INPUT, indicesI, "in_vertex", error);
3700 		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "Color.r", error);
3701 		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "Color.g", error);
3702 		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "Color.b", error);
3703 		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "Color.iLikePie", error);
3704 		VerifyGetProgramResourceIndex(vs, GL_PROGRAM_OUTPUT, indicesO, "gl_Position", error);
3705 
3706 		VerifyGetProgramResourceName(vs, GL_UNIFORM, indicesU["u"], "u", error);
3707 		VerifyGetProgramResourceName(vs, GL_UNIFORM, indicesU["v"], "v", error);
3708 		VerifyGetProgramResourceName(vs, GL_PROGRAM_INPUT, indicesI["in_vertex"], "in_vertex", error);
3709 		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["Color.r"], "Color.r", error);
3710 		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["Color.g"], "Color.g", error);
3711 		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["Color.b"], "Color.b", error);
3712 		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["Color.iLikePie"], "Color.iLikePie", error);
3713 		VerifyGetProgramResourceName(vs, GL_PROGRAM_OUTPUT, indicesO["gl_Position"], "gl_Position", error);
3714 
3715 		VerifyGetProgramResourceLocation(vs, GL_UNIFORM, "u", glGetUniformLocation(vs, "u"), error);
3716 		VerifyGetProgramResourceLocation(vs, GL_UNIFORM, "v", glGetUniformLocation(vs, "v"), error);
3717 		VerifyGetProgramResourceLocation(vs, GL_PROGRAM_INPUT, "in_vertex", 0, error);
3718 
3719 		VerifyGetProgramResourceLocationIndex(vs, GL_PROGRAM_OUTPUT, "Color.r", -1, error);
3720 		VerifyGetProgramResourceLocationIndex(vs, GL_PROGRAM_OUTPUT, "Color.g", -1, error);
3721 		VerifyGetProgramResourceLocationIndex(vs, GL_PROGRAM_OUTPUT, "Color.b", -1, error);
3722 		VerifyGetProgramResourceLocationIndex(vs, GL_PROGRAM_OUTPUT, "Color.iLikePie", -1, error);
3723 		VerifyGetProgramResourceLocationIndex(vs, GL_PROGRAM_OUTPUT, "gl_Position", -1, error);
3724 
3725 		GLenum props[] = { GL_NAME_LENGTH,
3726 						   GL_TYPE,
3727 						   GL_ARRAY_SIZE,
3728 						   GL_OFFSET,
3729 						   GL_BLOCK_INDEX,
3730 						   GL_ARRAY_STRIDE,
3731 						   GL_MATRIX_STRIDE,
3732 						   GL_IS_ROW_MAJOR,
3733 						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
3734 						   GL_REFERENCED_BY_COMPUTE_SHADER,
3735 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
3736 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
3737 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3738 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3739 						   GL_REFERENCED_BY_VERTEX_SHADER,
3740 						   GL_LOCATION };
3741 		GLint expected[] = {
3742 			2, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(vs, "v")
3743 		};
3744 		VerifyGetProgramResourceiv(vs, GL_UNIFORM, indicesU["v"], 16, props, 16, expected, error);
3745 
3746 		GLenum props2[] = { GL_NAME_LENGTH,
3747 							GL_TYPE,
3748 							GL_ARRAY_SIZE,
3749 							GL_REFERENCED_BY_COMPUTE_SHADER,
3750 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3751 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3752 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3753 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3754 							GL_REFERENCED_BY_VERTEX_SHADER,
3755 							GL_LOCATION,
3756 							GL_IS_PER_PATCH };
3757 		GLint expected2[] = { 10, GL_FLOAT_VEC4, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
3758 		VerifyGetProgramResourceiv(vs, GL_PROGRAM_INPUT, indicesI["in_vertex"], 11, props2, 11, expected2, error);
3759 
3760 		GLenum props3[] = { GL_NAME_LENGTH,
3761 							GL_TYPE,
3762 							GL_ARRAY_SIZE,
3763 							GL_REFERENCED_BY_COMPUTE_SHADER,
3764 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3765 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3766 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3767 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3768 							GL_REFERENCED_BY_VERTEX_SHADER,
3769 							GL_IS_PER_PATCH,
3770 							GL_LOCATION_INDEX };
3771 		GLint expected3[] = { 15, GL_FLOAT_VEC4, 1, 0, 0, 0, 0, 0, 1, 0, -1 };
3772 		VerifyGetProgramResourceiv(vs, GL_PROGRAM_OUTPUT, indicesO["Color.iLikePie"], 11, props3, 11, expected3, error);
3773 
3774 		glDeleteProgram(vs);
3775 		return error;
3776 	}
3777 };
3778 
3779 class SeparateProgramsTessControl : public SeparateProgramsVertex
3780 {
3781 
Title()3782 	virtual std::string Title()
3783 	{
3784 		return "Separate Program Tess Control Shader Test";
3785 	}
3786 
ShadersDesc()3787 	virtual std::string ShadersDesc()
3788 	{
3789 		return "tess control shader as separate shader object";
3790 	}
3791 
PurposeExt()3792 	virtual std::string PurposeExt()
3793 	{
3794 		return "\n\n Purpose is to verify that feature works correctly when using separate_shader_objects "
3795 			   "functionality.\n";
3796 	}
3797 
Run()3798 	virtual long Run()
3799 	{
3800 		long error = NO_ERROR;
3801 
3802 		const char* srcTCS = "#version 430                                                  \n"
3803 							 "layout(vertices = 3) out;                                     \n"
3804 							 "layout(location = 0) patch out vec4 data;                     \n"
3805 							 "out gl_PerVertex {                                            \n"
3806 							 "   vec4 gl_Position;                                          \n"
3807 							 "   float gl_PointSize;                                        \n"
3808 							 "   float gl_ClipDistance[];                                   \n"
3809 							 "} gl_out[];                                                   \n"
3810 							 ""
3811 							 "in Color {                                 \n"
3812 							 "  float r, g, b;                           \n"
3813 							 "  vec4 iLikePie;                           \n"
3814 							 "} vs_color[];                              \n"
3815 							 ""
3816 							 "void main() {                                                                   \n"
3817 							 "   data = vec4(1);                                                              \n"
3818 							 "   gl_out[gl_InvocationID].gl_Position =                                        \n"
3819 							 "           vec4(vs_color[0].r, vs_color[0].g, vs_color[0].b, vs_color[0].iLikePie.x + "
3820 							 "float(gl_InvocationID));       \n"
3821 							 "   gl_TessLevelInner[0] = 1.0;                                                  \n"
3822 							 "   gl_TessLevelInner[1] = 1.0;                                                  \n"
3823 							 "   gl_TessLevelOuter[0] = 1.0;                                                  \n"
3824 							 "   gl_TessLevelOuter[1] = 1.0;                                                  \n"
3825 							 "   gl_TessLevelOuter[2] = 1.0;                                                  \n"
3826 							 "}";
3827 
3828 		const GLuint tcs = CreateShaderProgram(GL_TESS_CONTROL_SHADER, 1, &srcTCS);
3829 
3830 		// gl_InvocationID should be included
3831 		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 16, error);
3832 		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 5, error);
3833 
3834 		std::map<std::string, GLuint> indicesI;
3835 		std::map<std::string, GLuint> indicesO;
3836 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_OUTPUT, indicesO, "gl_PerVertex.gl_Position", error);
3837 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_OUTPUT, indicesO, "data", error);
3838 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_INPUT, indicesI, "Color.r", error);
3839 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_INPUT, indicesI, "Color.g", error);
3840 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_INPUT, indicesI, "Color.b", error);
3841 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_INPUT, indicesI, "Color.iLikePie", error);
3842 
3843 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_OUTPUT, indicesO["gl_PerVertex.gl_Position"],
3844 									 "gl_PerVertex.gl_Position", error);
3845 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_OUTPUT, indicesO["data"], "data", error);
3846 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_INPUT, indicesI["Color.r"], "Color.r", error);
3847 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_INPUT, indicesI["Color.g"], "Color.g", error);
3848 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_INPUT, indicesI["Color.b"], "Color.b", error);
3849 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_INPUT, indicesI["Color.iLikePie"], "Color.iLikePie", error);
3850 
3851 		GLenum props2[] = { GL_NAME_LENGTH,
3852 							GL_TYPE,
3853 							GL_ARRAY_SIZE,
3854 							GL_REFERENCED_BY_COMPUTE_SHADER,
3855 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3856 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3857 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3858 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3859 							GL_REFERENCED_BY_VERTEX_SHADER,
3860 							GL_IS_PER_PATCH };
3861 		GLint expected2[] = { 15, GL_FLOAT_VEC4, 1, 0, 0, 0, 1, 0, 0, 0 };
3862 		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_INPUT, indicesI["Color.iLikePie"], 10, props2, 10, expected2, error);
3863 
3864 		GLenum props3[] = { GL_NAME_LENGTH,
3865 							GL_TYPE,
3866 							GL_ARRAY_SIZE,
3867 							GL_REFERENCED_BY_COMPUTE_SHADER,
3868 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3869 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3870 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3871 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3872 							GL_REFERENCED_BY_VERTEX_SHADER,
3873 							GL_IS_PER_PATCH,
3874 							GL_LOCATION,
3875 							GL_LOCATION_INDEX };
3876 		GLint expected3[] = { 5, GL_FLOAT_VEC4, 1, 0, 0, 0, 1, 0, 0, 1, 0, -1 };
3877 		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_OUTPUT, indicesO["data"], 12, props3, 12, expected3, error);
3878 
3879 		glDeleteProgram(tcs);
3880 		return error;
3881 	}
3882 };
3883 
3884 class SeparateProgramsTessEval : public SeparateProgramsVertex
3885 {
3886 
Title()3887 	virtual std::string Title()
3888 	{
3889 		return "Separate Program Tess Eval Shader Test";
3890 	}
3891 
ShadersDesc()3892 	virtual std::string ShadersDesc()
3893 	{
3894 		return "tess eval shader as separate shader object";
3895 	}
3896 
Run()3897 	virtual long Run()
3898 	{
3899 		long error = NO_ERROR;
3900 
3901 		const char* srcTCS = "#version 430                                                  \n"
3902 							 "layout(quads, equal_spacing, ccw) in;                         \n"
3903 							 "out gl_PerVertex {                                            \n"
3904 							 "   vec4 gl_Position;                                          \n"
3905 							 "   float gl_PointSize;                                        \n"
3906 							 "   float gl_ClipDistance[];                                   \n"
3907 							 "};                                                            \n"
3908 							 ""
3909 							 "in gl_PerVertex {                   \n"
3910 							 "   vec4 gl_Position;                \n"
3911 							 "   float gl_PointSize;              \n"
3912 							 "   float gl_ClipDistance[];         \n"
3913 							 "} gl_in[];                          \n"
3914 							 ""
3915 							 "void main() {                                \n"
3916 							 "   vec4 p0 = gl_in[0].gl_Position;           \n"
3917 							 "   vec4 p1 = gl_in[1].gl_Position;           \n"
3918 							 "   vec4 p2 = gl_in[2].gl_Position;           \n"
3919 							 "   gl_Position = vec4(p0.x, p1.y, p2.z, p0.x);                 \n"
3920 							 "}";
3921 
3922 		const GLuint tcs = CreateShaderProgram(GL_TESS_EVALUATION_SHADER, 1, &srcTCS);
3923 
3924 		std::map<std::string, GLuint> indicesI;
3925 		std::map<std::string, GLuint> indicesO;
3926 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_INPUT, indicesI, "gl_PerVertex.gl_Position", error);
3927 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_OUTPUT, indicesO, "gl_Position", error);
3928 
3929 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_INPUT, indicesI["gl_PerVertex.gl_Position"],
3930 									 "gl_PerVertex.gl_Position", error);
3931 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_OUTPUT, indicesO["gl_Position"], "gl_Position", error);
3932 
3933 		GLenum props2[] = { GL_NAME_LENGTH,
3934 							GL_TYPE,
3935 							GL_ARRAY_SIZE,
3936 							GL_REFERENCED_BY_COMPUTE_SHADER,
3937 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3938 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3939 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3940 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3941 							GL_REFERENCED_BY_VERTEX_SHADER,
3942 							GL_IS_PER_PATCH };
3943 		GLint expected2[] = { 25, GL_FLOAT_VEC4, 1, 0, 0, 0, 0, 1, 0, 0 };
3944 		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_INPUT, indicesI["gl_PerVertex.gl_Position"], 10, props2, 10,
3945 								   expected2, error);
3946 
3947 		GLenum props3[] = { GL_NAME_LENGTH,
3948 							GL_TYPE,
3949 							GL_ARRAY_SIZE,
3950 							GL_REFERENCED_BY_COMPUTE_SHADER,
3951 							GL_REFERENCED_BY_FRAGMENT_SHADER,
3952 							GL_REFERENCED_BY_GEOMETRY_SHADER,
3953 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
3954 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
3955 							GL_REFERENCED_BY_VERTEX_SHADER,
3956 							GL_IS_PER_PATCH,
3957 							GL_LOCATION_INDEX };
3958 		GLint expected3[] = { 12, GL_FLOAT_VEC4, 1, 0, 0, 0, 0, 1, 0, 0, -1 };
3959 		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_OUTPUT, indicesO["gl_Position"], 11, props3, 11, expected3, error);
3960 
3961 		glDeleteProgram(tcs);
3962 		return error;
3963 	}
3964 };
3965 
3966 class SeparateProgramsGeometry : public SeparateProgramsVertex
3967 {
3968 
Title()3969 	virtual std::string Title()
3970 	{
3971 		return "Separate Program Geometry Shader Test";
3972 	}
3973 
ShadersDesc()3974 	virtual std::string ShadersDesc()
3975 	{
3976 		return "geometry shader as separate shader object";
3977 	}
3978 
Run()3979 	virtual long Run()
3980 	{
3981 		long error = NO_ERROR;
3982 
3983 		const char* srcTCS = "#version 430                                                  \n"
3984 							 "layout(triangles) in;                                         \n"
3985 							 "layout(triangle_strip, max_vertices = 4) out;                 \n"
3986 							 ""
3987 							 "out gl_PerVertex {                                            \n"
3988 							 "   vec4 gl_Position;                                          \n"
3989 							 "   float gl_PointSize;                                        \n"
3990 							 "   float gl_ClipDistance[];                                   \n"
3991 							 "};                                                            \n"
3992 							 ""
3993 							 "in gl_PerVertex {                                             \n"
3994 							 "   vec4 gl_Position;                                          \n"
3995 							 "   float gl_PointSize;                                        \n"
3996 							 "   float gl_ClipDistance[];                                   \n"
3997 							 "} gl_in[];                                                    \n"
3998 							 ""
3999 							 "void main() {                              \n"
4000 							 "   gl_Position = vec4(-1, 1, 0, 1);        \n"
4001 							 "   EmitVertex();                           \n"
4002 							 "   gl_Position = vec4(-1, -1, 0, 1);       \n"
4003 							 "   EmitVertex();                           \n"
4004 							 "   gl_Position = vec4(1, 1, 0, 1);         \n"
4005 							 "   EmitVertex();                           \n"
4006 							 "   gl_Position = gl_in[0].gl_Position;     \n"
4007 							 "   EmitVertex();                           \n"
4008 							 "   EndPrimitive();                         \n"
4009 							 "}";
4010 
4011 		const GLuint tcs = CreateShaderProgram(GL_GEOMETRY_SHADER, 1, &srcTCS);
4012 
4013 		std::map<std::string, GLuint> indicesI;
4014 		std::map<std::string, GLuint> indicesO;
4015 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_INPUT, indicesI, "gl_PerVertex.gl_Position", error);
4016 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_OUTPUT, indicesO, "gl_Position", error);
4017 
4018 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_INPUT, indicesI["gl_PerVertex.gl_Position"],
4019 									 "gl_PerVertex.gl_Position", error);
4020 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_OUTPUT, indicesO["gl_Position"], "gl_Position", error);
4021 
4022 		GLenum props2[] = { GL_NAME_LENGTH,
4023 							GL_TYPE,
4024 							GL_ARRAY_SIZE,
4025 							GL_REFERENCED_BY_COMPUTE_SHADER,
4026 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4027 							GL_REFERENCED_BY_GEOMETRY_SHADER,
4028 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
4029 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
4030 							GL_REFERENCED_BY_VERTEX_SHADER,
4031 							GL_IS_PER_PATCH };
4032 		GLint expected2[] = { 25, GL_FLOAT_VEC4, 1, 0, 0, 1, 0, 0, 0, 0 };
4033 		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_INPUT, indicesI["gl_PerVertex.gl_Position"], 10, props2, 10,
4034 								   expected2, error);
4035 
4036 		GLenum props3[] = { GL_NAME_LENGTH,
4037 							GL_TYPE,
4038 							GL_ARRAY_SIZE,
4039 							GL_REFERENCED_BY_COMPUTE_SHADER,
4040 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4041 							GL_REFERENCED_BY_GEOMETRY_SHADER,
4042 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
4043 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
4044 							GL_REFERENCED_BY_VERTEX_SHADER,
4045 							GL_IS_PER_PATCH,
4046 							GL_LOCATION_INDEX };
4047 		GLint expected3[] = { 12, GL_FLOAT_VEC4, 1, 0, 0, 1, 0, 0, 0, 0, -1 };
4048 		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_OUTPUT, indicesO["gl_Position"], 11, props3, 11, expected3, error);
4049 
4050 		glDeleteProgram(tcs);
4051 		return error;
4052 	}
4053 };
4054 
4055 class SeparateProgramsFragment : public SeparateProgramsVertex
4056 {
4057 
Title()4058 	virtual std::string Title()
4059 	{
4060 		return "Separate Program Fragment Shader Test";
4061 	}
4062 
ShadersDesc()4063 	virtual std::string ShadersDesc()
4064 	{
4065 		return "fragment shader as separate shader object";
4066 	}
4067 
Run()4068 	virtual long Run()
4069 	{
4070 		long error = NO_ERROR;
4071 
4072 		const char* srcTCS = "#version 430                                     \n"
4073 							 "out vec4 fs_color;                               \n"
4074 							 ""
4075 							 "layout(location = 1) uniform vec4 x;             \n"
4076 							 ""
4077 							 "layout(binding = 0) buffer SimpleBuffer {        \n"
4078 							 "   vec4 a;                                       \n"
4079 							 "};                                               \n"
4080 							 ""
4081 							 "in vec4 vs_color;                                \n"
4082 							 "void main() {                                    \n"
4083 							 "   fs_color = vs_color + x + a;                  \n"
4084 							 "}";
4085 
4086 		const GLuint tcs = CreateShaderProgram(GL_FRAGMENT_SHADER, 1, &srcTCS);
4087 
4088 		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 9, error);
4089 		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
4090 		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 9, error);
4091 		VerifyGetProgramInterfaceiv(tcs, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 1, error);
4092 		VerifyGetProgramInterfaceiv(tcs, GL_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
4093 		VerifyGetProgramInterfaceiv(tcs, GL_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
4094 		VerifyGetProgramInterfaceiv(tcs, GL_BUFFER_VARIABLE, GL_MAX_NAME_LENGTH, 2, error);
4095 		VerifyGetProgramInterfaceiv(tcs, GL_BUFFER_VARIABLE, GL_ACTIVE_RESOURCES, 1, error);
4096 		VerifyGetProgramInterfaceiv(tcs, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, 1, error);
4097 		VerifyGetProgramInterfaceiv(tcs, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, 13, error);
4098 		VerifyGetProgramInterfaceiv(tcs, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 1, error);
4099 
4100 		std::map<std::string, GLuint> indicesSSB;
4101 		std::map<std::string, GLuint> indicesBV;
4102 		std::map<std::string, GLuint> indicesI;
4103 		std::map<std::string, GLuint> indicesO;
4104 		std::map<std::string, GLuint> indicesU;
4105 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_INPUT, indicesI, "vs_color", error);
4106 		VerifyGetProgramResourceIndex(tcs, GL_PROGRAM_OUTPUT, indicesO, "fs_color", error);
4107 		VerifyGetProgramResourceIndex(tcs, GL_UNIFORM, indicesU, "x", error);
4108 		VerifyGetProgramResourceIndex(tcs, GL_SHADER_STORAGE_BLOCK, indicesSSB, "SimpleBuffer", error);
4109 		VerifyGetProgramResourceIndex(tcs, GL_BUFFER_VARIABLE, indicesBV, "a", error);
4110 
4111 		VerifyGetProgramResourceName(tcs, GL_SHADER_STORAGE_BLOCK, indicesSSB["SimpleBuffer"], "SimpleBuffer", error);
4112 		VerifyGetProgramResourceName(tcs, GL_BUFFER_VARIABLE, indicesBV["a"], "a", error);
4113 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_INPUT, indicesI["vs_color"], "vs_color", error);
4114 		VerifyGetProgramResourceName(tcs, GL_PROGRAM_OUTPUT, indicesO["fs_color"], "fs_color", error);
4115 		VerifyGetProgramResourceName(tcs, GL_UNIFORM, indicesU["x"], "x", error);
4116 
4117 		VerifyGetProgramResourceLocation(tcs, GL_UNIFORM, "x", 1, error);
4118 
4119 		GLenum props2[] = { GL_NAME_LENGTH,
4120 							GL_TYPE,
4121 							GL_ARRAY_SIZE,
4122 							GL_REFERENCED_BY_COMPUTE_SHADER,
4123 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4124 							GL_REFERENCED_BY_GEOMETRY_SHADER,
4125 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
4126 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
4127 							GL_REFERENCED_BY_VERTEX_SHADER,
4128 							GL_IS_PER_PATCH };
4129 		GLint expected2[] = { 9, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0 };
4130 		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_INPUT, indicesI["vs_color"], 10, props2, 10, expected2, error);
4131 
4132 		GLenum props3[] = { GL_NAME_LENGTH,
4133 							GL_TYPE,
4134 							GL_ARRAY_SIZE,
4135 							GL_REFERENCED_BY_COMPUTE_SHADER,
4136 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4137 							GL_REFERENCED_BY_GEOMETRY_SHADER,
4138 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
4139 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
4140 							GL_REFERENCED_BY_VERTEX_SHADER,
4141 							GL_IS_PER_PATCH,
4142 							GL_LOCATION_INDEX };
4143 		GLint expected3[] = { 9, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0, 0 };
4144 		VerifyGetProgramResourceiv(tcs, GL_PROGRAM_OUTPUT, indicesO["fs_color"], 11, props3, 11, expected3, error);
4145 
4146 		GLenum props5[] = { GL_NAME_LENGTH,
4147 							GL_TYPE,
4148 							GL_ARRAY_SIZE,
4149 							GL_OFFSET,
4150 							GL_BLOCK_INDEX,
4151 							GL_ARRAY_STRIDE,
4152 							GL_MATRIX_STRIDE,
4153 							GL_IS_ROW_MAJOR,
4154 							GL_ATOMIC_COUNTER_BUFFER_INDEX,
4155 							GL_REFERENCED_BY_COMPUTE_SHADER,
4156 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4157 							GL_REFERENCED_BY_VERTEX_SHADER,
4158 							GL_LOCATION };
4159 		GLint expected5[] = { 2, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 1 };
4160 		VerifyGetProgramResourceiv(tcs, GL_UNIFORM, indicesU["x"], 13, props5, 13, expected5, error);
4161 
4162 		GLenum props6[] = { GL_NAME_LENGTH,
4163 							GL_BUFFER_BINDING,
4164 							GL_NUM_ACTIVE_VARIABLES,
4165 							GL_REFERENCED_BY_COMPUTE_SHADER,
4166 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4167 							GL_REFERENCED_BY_VERTEX_SHADER,
4168 							GL_ACTIVE_VARIABLES };
4169 		GLint expected6[] = { 13, 0, 1, 0, 1, 0, static_cast<GLint>(indicesBV["a"]) };
4170 		VerifyGetProgramResourceiv(tcs, GL_SHADER_STORAGE_BLOCK, indicesSSB["SimpleBuffer"], 7, props6, 7, expected6,
4171 								   error);
4172 
4173 		GLenum props7[] = { GL_NAME_LENGTH,
4174 							GL_TYPE,
4175 							GL_ARRAY_SIZE,
4176 							GL_BLOCK_INDEX,
4177 							GL_ARRAY_STRIDE,
4178 							GL_IS_ROW_MAJOR,
4179 							GL_REFERENCED_BY_COMPUTE_SHADER,
4180 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4181 							GL_REFERENCED_BY_VERTEX_SHADER,
4182 							GL_TOP_LEVEL_ARRAY_SIZE,
4183 							GL_TOP_LEVEL_ARRAY_STRIDE };
4184 		GLint expected7[] = {
4185 			2, GL_FLOAT_VEC4, 1, static_cast<GLint>(indicesSSB["SimpleBuffer"]), 0, 0, 0, 1, 0, 1, 0
4186 		};
4187 		VerifyGetProgramResourceiv(tcs, GL_BUFFER_VARIABLE, indicesBV["a"], 11, props7, 11, expected7, error);
4188 
4189 		glDeleteProgram(tcs);
4190 		return error;
4191 	}
4192 };
4193 
4194 class UniformBlockAdvanced : public SimpleShaders
4195 {
Title()4196 	virtual std::string Title()
4197 	{
4198 		return "Uniform Block Advanced Test";
4199 	}
4200 
ShadersDesc()4201 	virtual std::string ShadersDesc()
4202 	{
4203 		return "fallthrough fragment and vertex shaders with different types of uniform blocks used";
4204 	}
4205 
PurposeExt()4206 	virtual std::string PurposeExt()
4207 	{
4208 		return "\n\n Purpose is to verify calls using GL_UNIFORM_BLOCK as an interface param and\n"
4209 			   "verify results of querying offset, strides and row order.\n";
4210 	}
4211 
VertexShader()4212 	virtual std::string VertexShader()
4213 	{
4214 		return "#version 430                         \n"
4215 			   "in vec4 position;                    \n"
4216 			   ""
4217 			   "layout(row_major) uniform SimpleBlock {   \n"
4218 			   "   mat4 a;                                \n"
4219 			   "   vec4 b[10];                            \n"
4220 			   "};                                        \n"
4221 			   "void main(void)                      \n"
4222 			   "{                                    \n"
4223 			   "    float tmp;                       \n"
4224 			   "    tmp = a[0][0] + b[0].x;          \n"
4225 			   "    gl_Position = position * tmp;    \n"
4226 			   "}";
4227 	}
4228 
Run()4229 	virtual long Run()
4230 	{
4231 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
4232 		glBindAttribLocation(program, 0, "position");
4233 		glBindFragDataLocation(program, 0, "color");
4234 		LinkProgram(program);
4235 
4236 		long error = NO_ERROR;
4237 
4238 		std::map<std::string, GLuint> indicesU;
4239 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
4240 		VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
4241 
4242 		GLenum props[]	= { GL_IS_ROW_MAJOR };
4243 		GLint  expected[] = { 1 };
4244 		VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, props, 1, expected, error);
4245 
4246 		GLenum  prop = GL_MATRIX_STRIDE;
4247 		GLsizei len;
4248 		GLint   res;
4249 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, 1024, &len, &res);
4250 		if (res < 1)
4251 		{
4252 			m_context.getTestContext().getLog()
4253 				<< tcu::TestLog::Message
4254 				<< "ERROR: glGetProgramResourceiv, interface GL_UNIFORM, prop GL_MATRIX_STRIDE\n"
4255 				<< "Expected value greater than 0, got " << res << tcu::TestLog::EndMessage;
4256 		}
4257 		prop = GL_OFFSET;
4258 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, 1024, &len, &res);
4259 		if (res < 0)
4260 		{
4261 			m_context.getTestContext().getLog()
4262 				<< tcu::TestLog::Message << "ERROR: glGetProgramResourceiv, interface GL_UNIFORM, prop GL_OFFSET\n"
4263 				<< "Expected value not less than 0, got " << res << tcu::TestLog::EndMessage;
4264 		}
4265 		prop = GL_ARRAY_STRIDE;
4266 		glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, 1024, &len, &res);
4267 		if (res < 1)
4268 		{
4269 			m_context.getTestContext().getLog()
4270 				<< tcu::TestLog::Message
4271 				<< "ERROR: glGetProgramResourceiv, interface GL_UNIFORM, prop GL_ARRAY_STRIDE\n"
4272 				<< "Expected value greater than 0, got " << res << tcu::TestLog::EndMessage;
4273 		}
4274 
4275 		glDeleteProgram(program);
4276 		return error;
4277 	}
4278 };
4279 
4280 class ArrayNames : public SimpleShaders
4281 {
4282 
Title()4283 	virtual std::string Title()
4284 	{
4285 		return "Array Names Test";
4286 	}
4287 
ShadersDesc()4288 	virtual std::string ShadersDesc()
4289 	{
4290 		return "fallthrough fragment shader and a vertex shader with array of vec4 uniform used";
4291 	}
4292 
PurposeExt()4293 	virtual std::string PurposeExt()
4294 	{
4295 		return "\n\n Purpose is to verify that GetProgramResourceLocation match "
4296 			   "name strings correctly.\n";
4297 	}
4298 
VertexShader()4299 	virtual std::string VertexShader()
4300 	{
4301 		return "#version 430                         \n"
4302 			   "in vec4 position;                    \n"
4303 			   ""
4304 			   "uniform vec4 a[2];           \n"
4305 			   ""
4306 			   "void main(void)                            \n"
4307 			   "{                                          \n"
4308 			   "    gl_Position = position + a[0] + a[1];  \n"
4309 			   "}";
4310 	}
4311 
Run()4312 	virtual long Run()
4313 	{
4314 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
4315 		glBindAttribLocation(program, 0, "position");
4316 		LinkProgram(program);
4317 
4318 		long error = NO_ERROR;
4319 
4320 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", glGetUniformLocation(program, "a"), error);
4321 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[0]", glGetUniformLocation(program, "a"), error);
4322 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[1]", glGetUniformLocation(program, "a[1]"), error);
4323 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[2]", -1, error);
4324 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[0 + 0]", -1, error);
4325 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[0+0]", -1, error);
4326 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[ 0]", -1, error);
4327 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[0 ]", -1, error);
4328 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[\n0]", -1, error);
4329 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[\t0]", -1, error);
4330 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[01]", -1, error);
4331 		VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a[00]", -1, error);
4332 
4333 		glDeleteProgram(program);
4334 		return error;
4335 	}
4336 };
4337 
4338 class BuffLength : public SimpleShaders
4339 {
4340 
Title()4341 	virtual std::string Title()
4342 	{
4343 		return "Buff Length Test";
4344 	}
4345 
ShadersDesc()4346 	virtual std::string ShadersDesc()
4347 	{
4348 		return "fallthrough fragment shader and vertex with uniform of vec4 type used";
4349 	}
4350 
PurposeExt()4351 	virtual std::string PurposeExt()
4352 	{
4353 		return "\n\n Purpose is to verify that bufsize of GetProgramResourceName and "
4354 			   "GetProgramResourceiv is respected.\n";
4355 	}
4356 
VertexShader()4357 	virtual std::string VertexShader()
4358 	{
4359 		return "#version 430                         \n"
4360 			   "in vec4 position;                    \n"
4361 			   ""
4362 			   "uniform vec4 someLongName;           \n"
4363 			   ""
4364 			   "void main(void)                            \n"
4365 			   "{                                          \n"
4366 			   "    gl_Position = position + someLongName; \n"
4367 			   "}";
4368 	}
4369 
Run()4370 	virtual long Run()
4371 	{
4372 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
4373 		glBindAttribLocation(program, 0, "position");
4374 		LinkProgram(program);
4375 
4376 		long error = NO_ERROR;
4377 
4378 		GLuint  index = glGetProgramResourceIndex(program, GL_UNIFORM, "someLongName");
4379 		GLsizei length;
4380 		GLchar  buff[3] = { 'a', 'b', 'c' };
4381 		glGetProgramResourceName(program, GL_UNIFORM, index, 0, NULL, NULL);
4382 		glGetProgramResourceName(program, GL_UNIFORM, index, 0, NULL, buff);
4383 		if (buff[0] != 'a' || buff[1] != 'b' || buff[2] != 'c')
4384 		{
4385 			m_context.getTestContext().getLog()
4386 				<< tcu::TestLog::Message << "ERROR: buff has changed" << tcu::TestLog::EndMessage;
4387 			error = ERROR;
4388 		}
4389 		glGetProgramResourceName(program, GL_UNIFORM, index, 2, &length, buff);
4390 		if (buff[0] != 's' || buff[1] != '\0' || buff[2] != 'c')
4391 		{
4392 			m_context.getTestContext().getLog()
4393 				<< tcu::TestLog::Message << "ERROR: buff different then expected" << tcu::TestLog::EndMessage;
4394 			error = ERROR;
4395 		}
4396 		if (length != 1)
4397 		{
4398 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: incorrect length, expected 1, got "
4399 												<< length << tcu::TestLog::EndMessage;
4400 			error = ERROR;
4401 		}
4402 
4403 		GLint  params[3] = { 1, 2, 3 };
4404 		GLenum props[]   = { GL_NAME_LENGTH,
4405 						   GL_TYPE,
4406 						   GL_ARRAY_SIZE,
4407 						   GL_OFFSET,
4408 						   GL_BLOCK_INDEX,
4409 						   GL_ARRAY_STRIDE,
4410 						   GL_MATRIX_STRIDE,
4411 						   GL_IS_ROW_MAJOR,
4412 						   GL_ATOMIC_COUNTER_BUFFER_INDEX,
4413 						   GL_REFERENCED_BY_COMPUTE_SHADER,
4414 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
4415 						   GL_REFERENCED_BY_VERTEX_SHADER,
4416 						   GL_LOCATION };
4417 		glGetProgramResourceiv(program, GL_UNIFORM, index, 13, props, 0, NULL, NULL);
4418 		glGetProgramResourceiv(program, GL_UNIFORM, index, 13, props, 0, NULL, params);
4419 		if (params[0] != 1 || params[1] != 2 || params[2] != 3)
4420 		{
4421 			m_context.getTestContext().getLog()
4422 				<< tcu::TestLog::Message << "ERROR: params has changed" << tcu::TestLog::EndMessage;
4423 			error = ERROR;
4424 		}
4425 		glGetProgramResourceiv(program, GL_UNIFORM, index, 13, props, 2, &length, params);
4426 		if (params[0] != 13 || params[1] != GL_FLOAT_VEC4 || params[2] != 3)
4427 		{
4428 			m_context.getTestContext().getLog()
4429 				<< tcu::TestLog::Message << "ERROR: params has incorrect values" << tcu::TestLog::EndMessage;
4430 			error = ERROR;
4431 		}
4432 		if (length != 2)
4433 		{
4434 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: incorrect length, expected 2, got "
4435 												<< length << tcu::TestLog::EndMessage;
4436 			error = ERROR;
4437 		}
4438 
4439 		glDeleteProgram(program);
4440 		return error;
4441 	}
4442 };
4443 
4444 class NoLocations : public SimpleShaders
4445 {
4446 
Title()4447 	virtual std::string Title()
4448 	{
4449 		return "No Locations Test";
4450 	}
4451 
ShadersDesc()4452 	virtual std::string ShadersDesc()
4453 	{
4454 		return "fragment and vertex shaders with no locations set";
4455 	}
4456 
VertexShader()4457 	virtual std::string VertexShader()
4458 	{
4459 		return "#version 430                         \n"
4460 			   "in vec4 a;                           \n"
4461 			   "in vec4 b;                           \n"
4462 			   "in vec4 c[1];                        \n"
4463 			   "in vec4 d;                           \n"
4464 			   "void main(void)                      \n"
4465 			   "{                                    \n"
4466 			   "    gl_Position = a + b + c[0] + d;  \n"
4467 			   "}";
4468 	}
4469 
FragmentShader()4470 	virtual std::string FragmentShader()
4471 	{
4472 		return "#version 430                   \n"
4473 			   "out vec4 a;                    \n"
4474 			   "out vec4 b;                    \n"
4475 			   "out vec4 c;                    \n"
4476 			   "out vec4 d[1];                 \n"
4477 			   "void main() {                  \n"
4478 			   "    a = vec4(0, 1, 0, 1);      \n"
4479 			   "    b = vec4(0, 1, 0, 1);      \n"
4480 			   "    c = vec4(0, 1, 0, 1);      \n"
4481 			   "    d[0] = vec4(0, 1, 0, 1);   \n"
4482 			   "}";
4483 	}
4484 
Run()4485 	virtual long Run()
4486 	{
4487 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
4488 		glBindAttribLocation(program, 0, "position");
4489 		glLinkProgram(program);
4490 
4491 		long error = NO_ERROR;
4492 
4493 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 4, error);
4494 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 5, error);
4495 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 4, error);
4496 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 5, error);
4497 
4498 		std::map<std::string, GLuint> indicesI;
4499 		std::map<std::string, GLuint> indicesO;
4500 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indicesI, "a", error);
4501 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indicesI, "b", error);
4502 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indicesI, "c", error);
4503 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indicesI, "d", error);
4504 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indicesO, "a", error);
4505 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indicesO, "b", error);
4506 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indicesO, "c", error);
4507 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indicesO, "d[0]", error);
4508 
4509 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indicesI["a"], "a", error);
4510 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indicesI["b"], "b", error);
4511 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indicesI["c"], "c[0]", error);
4512 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indicesI["d"], "d", error);
4513 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indicesO["a"], "a", error);
4514 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indicesO["b"], "b", error);
4515 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indicesO["c"], "c", error);
4516 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indicesO["d[0]"], "d[0]", error);
4517 
4518 		std::map<std::string, GLint> locationsI;
4519 		std::map<std::string, GLint> locationsO;
4520 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, locationsI, "a", error);
4521 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, locationsI, "b", error);
4522 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, locationsI, "c", error);
4523 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, locationsI, "d", error);
4524 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, locationsO, "a", error);
4525 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, locationsO, "b", error);
4526 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, locationsO, "c", error);
4527 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, locationsO, "d[0]", error);
4528 
4529 		GLenum props[] = { GL_NAME_LENGTH,
4530 						   GL_TYPE,
4531 						   GL_ARRAY_SIZE,
4532 						   GL_REFERENCED_BY_COMPUTE_SHADER,
4533 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
4534 						   GL_REFERENCED_BY_VERTEX_SHADER };
4535 		GLint expected[] = { 2, GL_FLOAT_VEC4, 1, 0, 0, 1 };
4536 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indicesI["a"], 6, props, 6, expected, error);
4537 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indicesI["b"], 6, props, 6, expected, error);
4538 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indicesI["d"], 6, props, 6, expected, error);
4539 		GLint expected2[] = { 5, GL_FLOAT_VEC4, 1, 0, 0, 1 };
4540 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indicesI["c"], 6, props, 6, expected2, error);
4541 		GLint expected3[] = { 2, GL_FLOAT_VEC4, 1, 0, 1, 0 };
4542 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indicesO["a"], 6, props, 6, expected3, error);
4543 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indicesO["b"], 6, props, 6, expected3, error);
4544 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indicesO["c"], 6, props, 6, expected3, error);
4545 		GLint expected4[] = { 5, GL_FLOAT_VEC4, 1, 0, 1, 0 };
4546 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indicesO["d[0]"], 6, props, 6, expected4, error);
4547 
4548 		glDeleteProgram(program);
4549 		return error;
4550 	}
4551 };
4552 
4553 class ComputeShaderTest : public PIQBase
4554 {
Title()4555 	virtual std::string Title()
4556 	{
4557 		return "Compute Shader Test";
4558 	}
4559 
ShadersDesc()4560 	virtual std::string ShadersDesc()
4561 	{
4562 		return "compute shader";
4563 	}
4564 
ComputeShader()4565 	virtual std::string ComputeShader()
4566 	{
4567 		return "layout(local_size_x = 1, local_size_y = 1) in; \n"
4568 			   "layout(std430) buffer Output {                 \n"
4569 			   "   vec4 data[];                                \n"
4570 			   "} g_out;                                       \n"
4571 			   ""
4572 			   "void main() {                                   \n"
4573 			   "   g_out.data[0] = vec4(1.0, 2.0, 3.0, 4.0);    \n"
4574 			   "   g_out.data[100] = vec4(1.0, 2.0, 3.0, 4.0);  \n"
4575 			   "}";
4576 	}
4577 
CreateComputeProgram(const std::string& cs)4578 	GLuint CreateComputeProgram(const std::string& cs)
4579 	{
4580 		const GLuint p = glCreateProgram();
4581 
4582 		const char* const kGLSLVer = "#version 430  core \n";
4583 
4584 		if (!cs.empty())
4585 		{
4586 			const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
4587 			glAttachShader(p, sh);
4588 			glDeleteShader(sh);
4589 			const char* const src[2] = { kGLSLVer, cs.c_str() };
4590 			glShaderSource(sh, 2, src, NULL);
4591 			glCompileShader(sh);
4592 		}
4593 
4594 		return p;
4595 	}
4596 
CheckProgram(GLuint program, bool* compile_error = NULL)4597 	bool CheckProgram(GLuint program, bool* compile_error = NULL)
4598 	{
4599 		GLint compile_status = GL_TRUE;
4600 		GLint status;
4601 		glGetProgramiv(program, GL_LINK_STATUS, &status);
4602 
4603 		if (status == GL_FALSE)
4604 		{
4605 			GLint attached_shaders;
4606 			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
4607 
4608 			if (attached_shaders > 0)
4609 			{
4610 				std::vector<GLuint> shaders(attached_shaders);
4611 				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
4612 
4613 				for (GLint i = 0; i < attached_shaders; ++i)
4614 				{
4615 					GLenum type;
4616 					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
4617 					switch (type)
4618 					{
4619 					case GL_VERTEX_SHADER:
4620 						m_context.getTestContext().getLog()
4621 							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
4622 						break;
4623 					case GL_TESS_CONTROL_SHADER:
4624 						m_context.getTestContext().getLog()
4625 							<< tcu::TestLog::Message << "*** Tessellation Control Shader ***"
4626 							<< tcu::TestLog::EndMessage;
4627 						break;
4628 					case GL_TESS_EVALUATION_SHADER:
4629 						m_context.getTestContext().getLog()
4630 							<< tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
4631 							<< tcu::TestLog::EndMessage;
4632 						break;
4633 					case GL_GEOMETRY_SHADER:
4634 						m_context.getTestContext().getLog()
4635 							<< tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
4636 						break;
4637 					case GL_FRAGMENT_SHADER:
4638 						m_context.getTestContext().getLog()
4639 							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
4640 						break;
4641 					case GL_COMPUTE_SHADER:
4642 						m_context.getTestContext().getLog()
4643 							<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
4644 						break;
4645 					default:
4646 						m_context.getTestContext().getLog()
4647 							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
4648 					}
4649 
4650 					GLint res;
4651 					glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &res);
4652 					if (res != GL_TRUE)
4653 						compile_status = res;
4654 
4655 					// shader source
4656 					GLint length;
4657 					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
4658 					if (length > 0)
4659 					{
4660 						std::vector<GLchar> source(length);
4661 						glGetShaderSource(shaders[i], length, NULL, &source[0]);
4662 						m_context.getTestContext().getLog()
4663 							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
4664 					}
4665 
4666 					// shader info log
4667 					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
4668 					if (length > 0)
4669 					{
4670 						std::vector<GLchar> log(length);
4671 						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
4672 						m_context.getTestContext().getLog()
4673 							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
4674 					}
4675 				}
4676 			}
4677 
4678 			// program info log
4679 			GLint length;
4680 			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
4681 			if (length > 0)
4682 			{
4683 				std::vector<GLchar> log(length);
4684 				glGetProgramInfoLog(program, length, NULL, &log[0]);
4685 				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
4686 			}
4687 		}
4688 
4689 		if (compile_error)
4690 			*compile_error = (compile_status == GL_TRUE ? false : true);
4691 		if (compile_status != GL_TRUE)
4692 			return false;
4693 		return status == GL_TRUE ? true : false;
4694 	}
4695 
VerifyCompute(GLuint program, long& error)4696 	virtual void inline VerifyCompute(GLuint program, long& error)
4697 	{
4698 		VerifyGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_MAX_NAME_LENGTH, 15, error);
4699 		VerifyGetProgramInterfaceiv(program, GL_BUFFER_VARIABLE, GL_ACTIVE_RESOURCES, 1, error);
4700 		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, 1, error);
4701 		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, 7, error);
4702 		VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 1, error);
4703 
4704 		std::map<std::string, GLuint> indicesSSB;
4705 		std::map<std::string, GLuint> indicesBV;
4706 		VerifyGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, indicesSSB, "Output", error);
4707 		VerifyGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, indicesBV, "Output.data", error);
4708 
4709 		VerifyGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["Output"], "Output", error);
4710 		VerifyGetProgramResourceName(program, GL_BUFFER_VARIABLE, indicesBV["Outputa.data"], "Output.data[0]", error);
4711 
4712 		GLenum props3[] = { GL_NAME_LENGTH,
4713 							GL_BUFFER_BINDING,
4714 							GL_NUM_ACTIVE_VARIABLES,
4715 							GL_REFERENCED_BY_COMPUTE_SHADER,
4716 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4717 							GL_REFERENCED_BY_VERTEX_SHADER,
4718 							GL_ACTIVE_VARIABLES };
4719 		GLint expected3[] = { 7, 0, 1, 1, 0, 0, static_cast<GLint>(indicesBV["Outputa.data"]) };
4720 		VerifyGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, indicesSSB["Output"], 7, props3, 7, expected3,
4721 								   error);
4722 
4723 		GLenum props4[] = { GL_NAME_LENGTH,
4724 							GL_TYPE,
4725 							GL_ARRAY_SIZE,
4726 							GL_BLOCK_INDEX,
4727 							GL_IS_ROW_MAJOR,
4728 							GL_REFERENCED_BY_COMPUTE_SHADER,
4729 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4730 							GL_REFERENCED_BY_VERTEX_SHADER,
4731 							GL_TOP_LEVEL_ARRAY_SIZE };
4732 		GLint expected4[] = { 15, GL_FLOAT_VEC4, 0, static_cast<GLint>(indicesSSB["Output"]), 0, 1, 0, 0, 1 };
4733 		VerifyGetProgramResourceiv(program, GL_BUFFER_VARIABLE, indicesBV["Outputa.data"], 9, props4, 9, expected4,
4734 								   error);
4735 	}
4736 
Run()4737 	virtual long Run()
4738 	{
4739 		GLuint program = CreateComputeProgram(ComputeShader());
4740 		glLinkProgram(program);
4741 		if (!CheckProgram(program))
4742 		{
4743 			glDeleteProgram(program);
4744 			return ERROR;
4745 		}
4746 		glUseProgram(program);
4747 
4748 		long error = NO_ERROR;
4749 
4750 		VerifyCompute(program, error);
4751 
4752 		glDeleteProgram(program);
4753 		return error;
4754 	}
4755 };
4756 
4757 class QueryNotUsed : public SimpleShaders
4758 {
4759 
Title()4760 	virtual std::string Title()
4761 	{
4762 		return "Query Not Used Test";
4763 	}
4764 
PassCriteria()4765 	virtual std::string PassCriteria()
4766 	{
4767 		return "Data from queries matches the not used program.";
4768 	}
4769 
Purpose()4770 	virtual std::string Purpose()
4771 	{
4772 		return "Verify that program parameter works correctly and proper program is queried when different program is "
4773 			   "used.";
4774 	}
4775 
Method()4776 	virtual std::string Method()
4777 	{
4778 		return "Create 2 programs, use one of them and query the other, verify the results.";
4779 	}
4780 
VertexShader2()4781 	virtual std::string VertexShader2()
4782 	{
4783 		return "#version 430                         \n"
4784 			   "in vec4 p;                           \n"
4785 			   "void main(void)                      \n"
4786 			   "{                                    \n"
4787 			   "    gl_Position = p;                 \n"
4788 			   "}";
4789 	}
4790 
FragmentShader2()4791 	virtual std::string FragmentShader2()
4792 	{
4793 		return "#version 430                   \n"
4794 			   "out vec4 c;                    \n"
4795 			   "void main() {                  \n"
4796 			   "    c = vec4(0, 1, 0, 1);      \n"
4797 			   "}";
4798 	}
4799 
Run()4800 	virtual long Run()
4801 	{
4802 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
4803 		glBindAttribLocation(program, 0, "position");
4804 		glBindFragDataLocation(program, 0, "color");
4805 		LinkProgram(program);
4806 
4807 		GLuint program2 = CreateProgram(VertexShader2().c_str(), FragmentShader2().c_str(), false);
4808 		glBindAttribLocation(program, 0, "p");
4809 		glBindFragDataLocation(program, 0, "c");
4810 		LinkProgram(program2);
4811 		glUseProgram(program2);
4812 
4813 		long error = NO_ERROR;
4814 
4815 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
4816 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 9, error);
4817 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 1, error);
4818 		VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 6, error);
4819 
4820 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "color", 0, error);
4821 		VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position", 0, error);
4822 
4823 		VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, 0, "color", error);
4824 		VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, 0, "position", error);
4825 
4826 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", 0, error);
4827 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
4828 
4829 		VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "color", 0, error);
4830 
4831 		GLenum props[] = { GL_NAME_LENGTH,
4832 						   GL_TYPE,
4833 						   GL_ARRAY_SIZE,
4834 						   GL_REFERENCED_BY_COMPUTE_SHADER,
4835 						   GL_REFERENCED_BY_FRAGMENT_SHADER,
4836 						   GL_REFERENCED_BY_GEOMETRY_SHADER,
4837 						   GL_REFERENCED_BY_TESS_CONTROL_SHADER,
4838 						   GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
4839 						   GL_REFERENCED_BY_VERTEX_SHADER,
4840 						   GL_LOCATION,
4841 						   GL_IS_PER_PATCH };
4842 		GLint expected[] = { 9, GL_FLOAT_VEC4, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
4843 		VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 11, props, 11, expected, error);
4844 
4845 		GLenum props2[] = { GL_NAME_LENGTH,
4846 							GL_TYPE,
4847 							GL_ARRAY_SIZE,
4848 							GL_REFERENCED_BY_COMPUTE_SHADER,
4849 							GL_REFERENCED_BY_FRAGMENT_SHADER,
4850 							GL_REFERENCED_BY_GEOMETRY_SHADER,
4851 							GL_REFERENCED_BY_TESS_CONTROL_SHADER,
4852 							GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
4853 							GL_REFERENCED_BY_VERTEX_SHADER,
4854 							GL_LOCATION,
4855 							GL_IS_PER_PATCH,
4856 							GL_LOCATION_INDEX };
4857 		GLint expected2[] = { 6, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
4858 		VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 12, props2, 12, expected2, error);
4859 
4860 		glDeleteProgram(program);
4861 		glDeleteProgram(program2);
4862 		return error;
4863 	}
4864 };
4865 
4866 class RelinkFailure : public SimpleShaders
4867 {
4868 
Title()4869 	virtual std::string Title()
4870 	{
4871 		return "Relink Failure Test";
4872 	}
4873 
PassCriteria()4874 	virtual std::string PassCriteria()
4875 	{
4876 		return "INVALID_OPERATION is generated when asking for locations after failed link.";
4877 	}
4878 
Purpose()4879 	virtual std::string Purpose()
4880 	{
4881 		return "Verify that queries behave correctly after failed relink of a program.";
4882 	}
4883 
Method()4884 	virtual std::string Method()
4885 	{
4886 		return "Create a program, use it, relink with failure and then verify that INVALID_OPERATION is returned when "
4887 			   "asking for locations.";
4888 	}
4889 
VertexShader()4890 	virtual std::string VertexShader()
4891 	{
4892 		return "#version 430                                  \n"
4893 			   "in vec4 position;                             \n"
4894 			   "in vec3 pos;                                  \n"
4895 			   "void main(void)                               \n"
4896 			   "{                                             \n"
4897 			   "    gl_Position = position + vec4(pos, 1);    \n"
4898 			   "}";
4899 	}
4900 
Run()4901 	virtual long Run()
4902 	{
4903 		GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
4904 		glBindAttribLocation(program, 0, "position");
4905 		glBindAttribLocation(program, 1, "pos");
4906 		glBindFragDataLocation(program, 0, "color");
4907 		LinkProgram(program);
4908 
4909 		long error = NO_ERROR;
4910 
4911 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "pos", 1, error);
4912 		glUseProgram(program);
4913 
4914 		tcu::Vec4 v[4] = { tcu::Vec4(-1, 1, 0, 1), tcu::Vec4(-1, -1, 0, 1), tcu::Vec4(1, 1, 0, 1),
4915 						   tcu::Vec4(1, -1, 0, 1) };
4916 		GLuint vao, vbuf;
4917 		glGenVertexArrays(1, &vao);
4918 		glBindVertexArray(vao);
4919 		glGenBuffers(1, &vbuf);
4920 		glBindBuffer(GL_ARRAY_BUFFER, vbuf);
4921 		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
4922 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), 0);
4923 		glEnableVertexAttribArray(0);
4924 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4925 
4926 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4927 		glDisableVertexAttribArray(0);
4928 		glDeleteVertexArrays(1, &vao);
4929 		glBindBuffer(GL_ARRAY_BUFFER, 0);
4930 		glDeleteBuffers(1, &vbuf);
4931 
4932 		glBindAttribLocation(program, 0, "pos");
4933 		glBindAttribLocation(program, 0, "position");
4934 		const char* varyings[2] = { "q", "z" };
4935 		glTransformFeedbackVaryings(program, 2, varyings, GL_INTERLEAVED_ATTRIBS);
4936 		LinkProgram(program);
4937 
4938 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", -1, error);
4939 		ExpectError(GL_INVALID_OPERATION, error);
4940 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "pos", -1, error);
4941 		ExpectError(GL_INVALID_OPERATION, error);
4942 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", -1, error);
4943 		ExpectError(GL_INVALID_OPERATION, error);
4944 
4945 		glDeleteProgram(program);
4946 		return error;
4947 	}
4948 };
4949 
4950 class LinkFailure : public SimpleShaders
4951 {
4952 
Title()4953 	virtual std::string Title()
4954 	{
4955 		return "Link Failure Test";
4956 	}
4957 
PassCriteria()4958 	virtual std::string PassCriteria()
4959 	{
4960 		return "INVALID_OPERATION is generated when asking for locations after failed link.";
4961 	}
4962 
Purpose()4963 	virtual std::string Purpose()
4964 	{
4965 		return "Verify that queries behave correctly after failed relink of a program with changed sources.";
4966 	}
4967 
Method()4968 	virtual std::string Method()
4969 	{
4970 		return "Create a program, use it, relink with failure using different sources and then \n"
4971 			   "verify that INVALID_OPERATION is returned when asking for locations.";
4972 	}
4973 
VertexShader_prop()4974 	virtual const char* VertexShader_prop()
4975 	{
4976 		return "#version 430                         \n"
4977 			   "in vec4 posit;                       \n"
4978 			   "in vec4 p;                           \n"
4979 			   "void main(void)                      \n"
4980 			   "{                                    \n"
4981 			   "    gl_Position = p + posit;         \n"
4982 			   "}";
4983 	}
4984 
FragmentShader_prop()4985 	virtual const char* FragmentShader_prop()
4986 	{
4987 		return "#version 430                   \n"
4988 			   "out vec4 color;                \n"
4989 			   "void main() {                  \n"
4990 			   "    color = vec4(0, 1, 0, 1);  \n"
4991 			   "}";
4992 	}
4993 
VertexShader_fail()4994 	virtual const char* VertexShader_fail()
4995 	{
4996 		return "#version 430                         \n"
4997 			   "in vec4 position;                    \n"
4998 			   "void main(void)                      \n"
4999 			   "{                                    \n"
5000 			   "    gl_Position = position;          \n"
5001 			   "}";
5002 	}
5003 
Run()5004 	virtual long Run()
5005 	{
5006 		const GLuint program = glCreateProgram();
5007 		const char*  src_vs  = VertexShader_prop();
5008 		const char*  src_fs  = FragmentShader_prop();
5009 		const char*  src_vsh = VertexShader_fail();
5010 
5011 		GLuint sh1 = glCreateShader(GL_VERTEX_SHADER);
5012 		glAttachShader(program, sh1);
5013 		glDeleteShader(sh1);
5014 		glShaderSource(sh1, 1, &src_vs, NULL);
5015 		glCompileShader(sh1);
5016 
5017 		GLuint sh2 = glCreateShader(GL_FRAGMENT_SHADER);
5018 		glAttachShader(program, sh2);
5019 		glDeleteShader(sh2);
5020 		glShaderSource(sh2, 1, &src_fs, NULL);
5021 		glCompileShader(sh2);
5022 
5023 		glBindAttribLocation(program, 0, "p");
5024 		glBindAttribLocation(program, 1, "posit");
5025 		glBindFragDataLocation(program, 0, "color");
5026 		LinkProgram(program);
5027 
5028 		long error = NO_ERROR;
5029 
5030 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "posit", 1, error);
5031 		glUseProgram(program);
5032 
5033 		tcu::Vec4 v[4] = { tcu::Vec4(-1, 1, 0, 1), tcu::Vec4(-1, -1, 0, 1), tcu::Vec4(1, 1, 0, 1),
5034 						   tcu::Vec4(1, -1, 0, 1) };
5035 		GLuint vao, vbuf;
5036 		glGenVertexArrays(1, &vao);
5037 		glBindVertexArray(vao);
5038 		glGenBuffers(1, &vbuf);
5039 		glBindBuffer(GL_ARRAY_BUFFER, vbuf);
5040 		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
5041 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), 0);
5042 		glEnableVertexAttribArray(0);
5043 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5044 
5045 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5046 		glDisableVertexAttribArray(0);
5047 		glDeleteVertexArrays(1, &vao);
5048 		glBindBuffer(GL_ARRAY_BUFFER, 0);
5049 		glDeleteBuffers(1, &vbuf);
5050 
5051 		glDetachShader(program, sh1);
5052 		GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
5053 		glAttachShader(program, vsh);
5054 		glDeleteShader(vsh);
5055 		glShaderSource(vsh, 1, &src_vsh, NULL);
5056 		glCompileShader(vsh);
5057 		const char* varyings[2] = { "q", "z" };
5058 		glTransformFeedbackVaryings(program, 2, varyings, GL_INTERLEAVED_ATTRIBS);
5059 		LinkProgram(program);
5060 
5061 		GLint res;
5062 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", -1, error);
5063 		ExpectError(GL_INVALID_OPERATION, error);
5064 		glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &res);
5065 		if (res != 0 && res != 1)
5066 		{
5067 			m_context.getTestContext().getLog()
5068 				<< tcu::TestLog::Message << "Error, expected 0 or 1 active resources, got: " << res
5069 				<< tcu::TestLog::EndMessage;
5070 			error = ERROR;
5071 		}
5072 		glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, &res);
5073 		if (res != 0 && res != 9)
5074 		{
5075 			m_context.getTestContext().getLog()
5076 				<< tcu::TestLog::Message << "Error, expected 1 or 9 GL_MAX_NAME_LENGTH, got: " << res
5077 				<< tcu::TestLog::EndMessage;
5078 			error = ERROR;
5079 		}
5080 		VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", -1, error);
5081 		ExpectError(GL_INVALID_OPERATION, error);
5082 
5083 		glDeleteProgram(program);
5084 		return error;
5085 	}
5086 };
5087 
5088 } // anonymous namespace
5089 
ProgramInterfaceQueryTests(deqp::Context& context)5090 ProgramInterfaceQueryTests::ProgramInterfaceQueryTests(deqp::Context& context)
5091 	: TestCaseGroup(context, "program_interface_query", "")
5092 {
5093 }
5094 
~ProgramInterfaceQueryTests(void)5095 ProgramInterfaceQueryTests::~ProgramInterfaceQueryTests(void)
5096 {
5097 }
5098 
init()5099 void ProgramInterfaceQueryTests::init()
5100 {
5101 	using namespace deqp;
5102 	addChild(new TestSubcase(m_context, "empty-shaders", TestSubcase::Create<NoShaders>));
5103 	addChild(new TestSubcase(m_context, "simple-shaders", TestSubcase::Create<SimpleShaders>));
5104 	addChild(new TestSubcase(m_context, "input-types", TestSubcase::Create<InputTypes>));
5105 	addChild(new TestSubcase(m_context, "input-built-in", TestSubcase::Create<InputBuiltIn>));
5106 	addChild(new TestSubcase(m_context, "input-layout", TestSubcase::Create<InputLayout>));
5107 	addChild(new TestSubcase(m_context, "output-types", TestSubcase::Create<OutputTypes>));
5108 	addChild(new TestSubcase(m_context, "output-location-index", TestSubcase::Create<OutputLocationIndex>));
5109 	addChild(new TestSubcase(m_context, "output-built-in", TestSubcase::Create<OutputBuiltIn>));
5110 	addChild(new TestSubcase(m_context, "output-layout", TestSubcase::Create<OutputLayout>));
5111 	addChild(new TestSubcase(m_context, "output-layout-index", TestSubcase::Create<OutputLayoutIndex>));
5112 	addChild(new TestSubcase(m_context, "uniform-simple", TestSubcase::Create<UniformSimple>));
5113 	addChild(new TestSubcase(m_context, "uniform-types", TestSubcase::Create<UniformTypes>));
5114 	addChild(new TestSubcase(m_context, "uniform-block-types", TestSubcase::Create<UniformBlockTypes>));
5115 	addChild(new TestSubcase(m_context, "transform-feedback-types", TestSubcase::Create<TransformFeedbackTypes>));
5116 	addChild(new TestSubcase(m_context, "atomic-counters", TestSubcase::Create<AtomicCounterSimple>));
5117 	addChild(new TestSubcase(m_context, "subroutines-vertex", TestSubcase::Create<SubroutinesVertex>));
5118 	addChild(new TestSubcase(m_context, "subroutines-tess-control", TestSubcase::Create<SubroutinesTessControl>));
5119 	addChild(new TestSubcase(m_context, "subroutines-tess-eval", TestSubcase::Create<SubroutinesTessEval>));
5120 	addChild(new TestSubcase(m_context, "subroutines-geometry", TestSubcase::Create<SubroutinesGeometry>));
5121 	addChild(new TestSubcase(m_context, "subroutines-fragment", TestSubcase::Create<SubroutinesFragment>));
5122 	addChild(new TestSubcase(m_context, "subroutines-compute", TestSubcase::Create<SoubroutinesCompute>));
5123 	addChild(new TestSubcase(m_context, "ssb-types", TestSubcase::Create<ShaderStorageBlock>));
5124 	addChild(new TestSubcase(m_context, "transform-feedback-built-in", TestSubcase::Create<TransformFeedbackBuiltin>));
5125 	addChild(new TestSubcase(m_context, "null-length", TestSubcase::Create<NullLength>));
5126 	addChild(new TestSubcase(m_context, "arrays-of-arrays", TestSubcase::Create<ArraysOfArrays>));
5127 	addChild(new TestSubcase(m_context, "top-level-array", TestSubcase::Create<TopLevelArray>));
5128 	addChild(new TestSubcase(m_context, "separate-programs-vertex", TestSubcase::Create<SeparateProgramsVertex>));
5129 	addChild(
5130 		new TestSubcase(m_context, "separate-programs-tess-control", TestSubcase::Create<SeparateProgramsTessControl>));
5131 	addChild(new TestSubcase(m_context, "separate-programs-tess-eval", TestSubcase::Create<SeparateProgramsTessEval>));
5132 	addChild(new TestSubcase(m_context, "separate-programs-geometry", TestSubcase::Create<SeparateProgramsGeometry>));
5133 	addChild(new TestSubcase(m_context, "separate-programs-fragment", TestSubcase::Create<SeparateProgramsFragment>));
5134 	addChild(new TestSubcase(m_context, "uniform-block", TestSubcase::Create<UniformBlockAdvanced>));
5135 	addChild(new TestSubcase(m_context, "uniform-block-array", TestSubcase::Create<UniformBlockArray>));
5136 	addChild(new TestSubcase(m_context, "array-names", TestSubcase::Create<ArrayNames>));
5137 	addChild(new TestSubcase(m_context, "buff-length", TestSubcase::Create<BuffLength>));
5138 	addChild(new TestSubcase(m_context, "no-locations", TestSubcase::Create<NoLocations>));
5139 	addChild(new TestSubcase(m_context, "query-not-used", TestSubcase::Create<QueryNotUsed>));
5140 	addChild(new TestSubcase(m_context, "relink-failure", TestSubcase::Create<RelinkFailure>));
5141 	addChild(new TestSubcase(m_context, "link-failure", TestSubcase::Create<LinkFailure>));
5142 	addChild(new TestSubcase(m_context, "compute-shader", TestSubcase::Create<ComputeShaderTest>));
5143 	addChild(new TestSubcase(m_context, "invalid-value", TestSubcase::Create<InvalidValueTest>));
5144 	addChild(new TestSubcase(m_context, "invalid-operation", TestSubcase::Create<InvalidOperationTest>));
5145 	addChild(new TestSubcase(m_context, "invalid-enum", TestSubcase::Create<InvalidEnumTest>));
5146 }
5147 
5148 } // gl4cts namespace
5149