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/**
25 * \file  gl4cShaderSubroutineTests.cpp
26 * \brief Implements conformance tests for "Shader Subroutine" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29#include "gl4cShaderSubroutineTests.hpp"
30#include "gluContextInfo.hpp"
31#include "glwEnums.hpp"
32#include "glwFunctions.hpp"
33#include "tcuMatrix.hpp"
34#include <cmath>
35#include <cstring>
36#include <deMath.h>
37
38using namespace glw;
39
40namespace gl4cts
41{
42namespace ShaderSubroutine
43{
44/** Constructor.
45 *
46 * @param context CTS context.
47 **/
48Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context)
49{
50}
51
52/** Destructor
53 *
54 **/
55Utils::buffer::~buffer()
56{
57	if (0 != m_id)
58	{
59		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
60
61		gl.deleteBuffers(1, &m_id);
62		m_id = 0;
63	}
64}
65
66/** Execute BindBufferRange
67 *
68 * @param target <target> parameter
69 * @param index  <index> parameter
70 * @param offset <offset> parameter
71 * @param size   <size> parameter
72 **/
73void Utils::buffer::bindRange(glw::GLenum target, glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size)
74{
75	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
76
77	gl.bindBufferRange(target, index, m_id, offset, size);
78	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
79}
80
81/** Execute GenBuffer
82 *
83 **/
84void Utils::buffer::generate()
85{
86	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
87
88	gl.genBuffers(1, &m_id);
89	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
90}
91
92/** Execute BufferData
93 *
94 * @param target <target> parameter
95 * @param size   <size> parameter
96 * @param data   <data> parameter
97 * @param usage  <usage> parameter
98 **/
99void Utils::buffer::update(glw::GLenum target, glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage)
100{
101	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
102
103	gl.bindBuffer(target, m_id);
104	GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
105
106	gl.bufferData(target, size, data, usage);
107	GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData");
108}
109
110/** Constructor
111 *
112 * @param context CTS context
113 **/
114Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context)
115{
116	/* Nothing to be done here */
117}
118
119/** Destructor
120 *
121 **/
122Utils::framebuffer::~framebuffer()
123{
124	if (0 != m_id)
125	{
126		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
127
128		gl.deleteFramebuffers(1, &m_id);
129		m_id = 0;
130	}
131}
132
133/** Attach texture to specified attachment
134 *
135 * @param attachment Attachment
136 * @param texture_id Texture id
137 * @param width      Texture width
138 * @param height     Texture height
139 **/
140void Utils::framebuffer::attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width,
141									   glw::GLuint height)
142{
143	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
144
145	bind();
146
147	gl.bindTexture(GL_TEXTURE_2D, texture_id);
148	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
149
150	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture_id, 0 /* level */);
151
152	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
153
154	gl.viewport(0 /* x */, 0 /* y */, width, height);
155	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
156}
157
158/** Binds framebuffer to DRAW_FRAMEBUFFER
159 *
160 **/
161void Utils::framebuffer::bind()
162{
163	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
164
165	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_id);
166	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
167}
168
169/** Clear framebuffer
170 *
171 * @param mask <mask> parameter of glClear. Decides which shall be cleared
172 **/
173void Utils::framebuffer::clear(glw::GLenum mask)
174{
175	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
176
177	gl.clear(mask);
178	GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
179}
180
181/** Specifie clear color
182 *
183 * @param red   Red channel
184 * @param green Green channel
185 * @param blue  Blue channel
186 * @param alpha Alpha channel
187 **/
188void Utils::framebuffer::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
189{
190	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
191
192	gl.clearColor(red, green, blue, alpha);
193	GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
194}
195
196/** Generate framebuffer
197 *
198 **/
199void Utils::framebuffer::generate()
200{
201	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
202
203	gl.genFramebuffers(1, &m_id);
204	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
205}
206
207const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9;
208
209/** Constructor.
210 *
211 * @param context CTS context.
212 **/
213Utils::program::program(deqp::Context& context)
214	: m_compute_shader_id(0)
215	, m_fragment_shader_id(0)
216	, m_geometry_shader_id(0)
217	, m_program_object_id(0)
218	, m_tesselation_control_shader_id(0)
219	, m_tesselation_evaluation_shader_id(0)
220	, m_vertex_shader_id(0)
221	, m_context(context)
222{
223	/* Nothing to be done here */
224}
225
226/** Destructor
227 *
228 **/
229Utils::program::~program()
230{
231	remove();
232}
233
234/** Build program
235 *
236 * @param compute_shader_code                Compute shader source code
237 * @param fragment_shader_code               Fragment shader source code
238 * @param geometry_shader_code               Geometry shader source code
239 * @param tesselation_control_shader_code    Tesselation control shader source code
240 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
241 * @param vertex_shader_code                 Vertex shader source code
242 * @param varying_names                      Array of strings containing names of varyings to be captured with transfrom feedback
243 * @param n_varying_names                    Number of varyings to be captured with transfrom feedback
244 * @param is_separable                       Selects if monolithis or separable program should be built. Defaults to false
245 **/
246void Utils::program::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
247						   const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code,
248						   const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code,
249						   const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable)
250{
251	/* GL entry points */
252	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
253
254	/* Create shader objects and compile */
255	if (0 != compute_shader_code)
256	{
257		m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
258		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
259
260		compile(m_compute_shader_id, compute_shader_code);
261	}
262
263	if (0 != fragment_shader_code)
264	{
265		m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
266		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
267
268		compile(m_fragment_shader_id, fragment_shader_code);
269	}
270
271	if (0 != geometry_shader_code)
272	{
273		m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
274		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
275
276		compile(m_geometry_shader_id, geometry_shader_code);
277	}
278
279	if (0 != tesselation_control_shader_code)
280	{
281		m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
282		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
283
284		compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
285	}
286
287	if (0 != tesselation_evaluation_shader_code)
288	{
289		m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
290		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
291
292		compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
293	}
294
295	if (0 != vertex_shader_code)
296	{
297		m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
298		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
299
300		compile(m_vertex_shader_id, vertex_shader_code);
301	}
302
303	/* Create program object */
304	m_program_object_id = gl.createProgram();
305	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
306
307	/* Set up captyured varyings' names */
308	if (0 != n_varying_names)
309	{
310		gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
311		GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
312	}
313
314	/* Set separable parameter */
315	if (true == is_separable)
316	{
317		gl.programParameteri(m_program_object_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
318		GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri");
319	}
320
321	/* Link program */
322	link();
323}
324
325/** Compile shader
326 *
327 * @param shader_id   Shader object id
328 * @param shader_code Shader source code
329 **/
330void Utils::program::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const
331{
332	/* GL entry points */
333	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
334
335	/* Compilation status */
336	glw::GLint status = GL_FALSE;
337
338	/* Set source code */
339	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
340	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
341
342	/* Compile */
343	gl.compileShader(shader_id);
344	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
345
346	/* Get compilation status */
347	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
348	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
349
350	/* Log compilation error */
351	if (GL_TRUE != status)
352	{
353		glw::GLint				 length = 0;
354		std::vector<glw::GLchar> message;
355
356		/* Error log length */
357		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
358		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
359
360		/* Prepare storage */
361		message.resize(length);
362
363		/* Get error log */
364		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
365		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
366
367		/* Log */
368		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
369											<< &message[0] << "\nShader source\n"
370											<< shader_code << tcu::TestLog::EndMessage;
371
372		TCU_FAIL("Failed to compile shader");
373	}
374}
375
376/** Checks whether the tested driver supports GL_ARB_get_program_binary
377 *
378 *  @return true if the extension is supported and, also, at least one binary format.
379 **/
380bool Utils::program::isProgramBinarySupported() const
381{
382	glw::GLint n_program_binary_formats = 0;
383
384	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
385
386	if (m_context.getContextInfo().isExtensionSupported("GL_ARB_get_program_binary"))
387	{
388		gl.getIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &n_program_binary_formats);
389		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
390	}
391
392	return n_program_binary_formats > 0;
393}
394
395/** Create program from provided binary
396 *
397 * @param binary        Buffer with binary form of program
398 * @param binary_format Format of <binary> data
399 **/
400void Utils::program::createFromBinary(const std::vector<GLubyte>& binary, GLenum binary_format)
401{
402	/* GL entry points */
403	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
404
405	/* Create program object */
406	m_program_object_id = gl.createProgram();
407	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
408
409	gl.programBinary(m_program_object_id, binary_format, &binary[0], (GLsizei)binary.size());
410	GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramBinary");
411}
412
413/** Get binary form of program
414 *
415 * @param binary        Buffer for binary data
416 * @param binary_format Format of binary data
417 **/
418void Utils::program::getBinary(std::vector<GLubyte>& binary, GLenum& binary_format) const
419{
420	/* GL entry points */
421	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
422
423	/* Get binary size */
424	GLint length = 0;
425	gl.getProgramiv(m_program_object_id, GL_PROGRAM_BINARY_LENGTH, &length);
426	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
427
428	/* Allocate storage */
429	binary.resize(length);
430
431	/* Get binary */
432	gl.getProgramBinary(m_program_object_id, (GLsizei)binary.size(), &length, &binary_format, &binary[0]);
433	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramBinary");
434}
435
436/** Get subroutine index
437 *
438 * @param subroutine_name Subroutine name
439 *
440 * @return Index of subroutine
441 **/
442GLuint Utils::program::getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const
443{
444	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
445	GLuint				  index = -1;
446
447	index = gl.getSubroutineIndex(m_program_object_id, shader_stage, subroutine_name);
448	GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
449
450	if (GL_INVALID_INDEX == index)
451	{
452		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine: " << subroutine_name
453											<< " is not available" << tcu::TestLog::EndMessage;
454
455		TCU_FAIL("Subroutine is not available");
456	}
457
458	return index;
459}
460
461/** Get subroutine uniform location
462 *
463 * @param uniform_name Subroutine uniform name
464 *
465 * @return Location of subroutine uniform
466 **/
467GLint Utils::program::getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const
468{
469	const glw::Functions& gl	   = m_context.getRenderContext().getFunctions();
470	GLint				  location = -1;
471
472	location = gl.getSubroutineUniformLocation(m_program_object_id, shader_stage, uniform_name);
473	GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
474
475	if (-1 == location)
476	{
477		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine uniform: " << uniform_name
478											<< " is not available" << tcu::TestLog::EndMessage;
479
480		TCU_FAIL("Subroutine uniform is not available");
481	}
482
483	return location;
484}
485
486/** Get uniform location
487 *
488 * @param uniform_name Subroutine uniform name
489 *
490 * @return Location of uniform
491 **/
492GLint Utils::program::getUniformLocation(const glw::GLchar* uniform_name) const
493{
494	const glw::Functions& gl	   = m_context.getRenderContext().getFunctions();
495	GLint				  location = -1;
496
497	location = gl.getUniformLocation(m_program_object_id, uniform_name);
498	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
499
500	if (-1 == location)
501	{
502		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name
503											<< " is not available" << tcu::TestLog::EndMessage;
504
505		TCU_FAIL("Uniform is not available");
506	}
507
508	return location;
509}
510
511/** Attach shaders and link program
512 *
513 **/
514void Utils::program::link() const
515{
516	/* GL entry points */
517	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
518
519	/* Link status */
520	glw::GLint status = GL_FALSE;
521
522	/* Attach shaders */
523	if (0 != m_compute_shader_id)
524	{
525		gl.attachShader(m_program_object_id, m_compute_shader_id);
526		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
527	}
528
529	if (0 != m_fragment_shader_id)
530	{
531		gl.attachShader(m_program_object_id, m_fragment_shader_id);
532		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
533	}
534
535	if (0 != m_geometry_shader_id)
536	{
537		gl.attachShader(m_program_object_id, m_geometry_shader_id);
538		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
539	}
540
541	if (0 != m_tesselation_control_shader_id)
542	{
543		gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
544		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
545	}
546
547	if (0 != m_tesselation_evaluation_shader_id)
548	{
549		gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
550		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
551	}
552
553	if (0 != m_vertex_shader_id)
554	{
555		gl.attachShader(m_program_object_id, m_vertex_shader_id);
556		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
557	}
558
559	/* Link */
560	gl.linkProgram(m_program_object_id);
561	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
562
563	/* Get link status */
564	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
565	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
566
567	/* Log link error */
568	if (GL_TRUE != status)
569	{
570		glw::GLint				 length = 0;
571		std::vector<glw::GLchar> message;
572
573		/* Get error log length */
574		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
575		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
576
577		message.resize(length);
578
579		/* Get error log */
580		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
581		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
582
583		/* Log */
584		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
585											<< &message[0] << tcu::TestLog::EndMessage;
586
587		TCU_FAIL("Failed to link program");
588	}
589}
590
591/** Delete program object and all attached shaders
592 *
593 **/
594void Utils::program::remove()
595{
596	/* GL entry points */
597	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
598
599	/* Make sure program object is no longer used by GL */
600	gl.useProgram(0);
601
602	/* Clean program object */
603	if (0 != m_program_object_id)
604	{
605		gl.deleteProgram(m_program_object_id);
606		m_program_object_id = 0;
607	}
608
609	/* Clean shaders */
610	if (0 != m_compute_shader_id)
611	{
612		gl.deleteShader(m_compute_shader_id);
613		m_compute_shader_id = 0;
614	}
615
616	if (0 != m_fragment_shader_id)
617	{
618		gl.deleteShader(m_fragment_shader_id);
619		m_fragment_shader_id = 0;
620	}
621
622	if (0 != m_geometry_shader_id)
623	{
624		gl.deleteShader(m_geometry_shader_id);
625		m_geometry_shader_id = 0;
626	}
627
628	if (0 != m_tesselation_control_shader_id)
629	{
630		gl.deleteShader(m_tesselation_control_shader_id);
631		m_tesselation_control_shader_id = 0;
632	}
633
634	if (0 != m_tesselation_evaluation_shader_id)
635	{
636		gl.deleteShader(m_tesselation_evaluation_shader_id);
637		m_tesselation_evaluation_shader_id = 0;
638	}
639
640	if (0 != m_vertex_shader_id)
641	{
642		gl.deleteShader(m_vertex_shader_id);
643		m_vertex_shader_id = 0;
644	}
645}
646
647/** Execute UseProgram
648 *
649 **/
650void Utils::program::use() const
651{
652	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
653
654	gl.useProgram(m_program_object_id);
655	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
656}
657
658/** Constructor.
659 *
660 * @param context CTS context.
661 **/
662Utils::texture::texture(deqp::Context& context) : m_id(0), m_context(context)
663{
664	/* Nothing to done here */
665}
666
667/** Destructor
668 *
669 **/
670Utils::texture::~texture()
671{
672	if (0 != m_id)
673	{
674		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
675
676		gl.deleteTextures(1, &m_id);
677		m_id = 0;
678	}
679}
680
681/** Bind texture to GL_TEXTURE_2D
682 *
683 **/
684void Utils::texture::bind()
685{
686	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
687
688	gl.bindTexture(GL_TEXTURE_2D, m_id);
689	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
690}
691
692/** Create 2d texture
693 *
694 * @param width           Width of texture
695 * @param height          Height of texture
696 * @param internal_format Internal format of texture
697 **/
698void Utils::texture::create(glw::GLuint width, glw::GLuint height, glw::GLenum internal_format)
699{
700	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
701
702	gl.genTextures(1, &m_id);
703	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
704
705	bind();
706
707	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, internal_format, width, height);
708	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
709}
710
711/** Get contents of texture
712 *
713 * @param format   Format of image
714 * @param type     Type of image
715 * @param out_data Buffer for image
716 **/
717void Utils::texture::get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data)
718{
719	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
720
721	bind();
722
723	gl.getTexImage(GL_TEXTURE_2D, 0, format, type, out_data);
724	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
725}
726
727/** Update contents of texture
728 *
729 * @param width  Width of texture
730 * @param height Height of texture
731 * @param format Format of data
732 * @param type   Type of data
733 * @param data   Buffer with image
734 **/
735void Utils::texture::update(glw::GLuint width, glw::GLuint height, glw::GLenum format, glw::GLenum type,
736							glw::GLvoid* data)
737{
738	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
739
740	bind();
741
742	gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, width, height, format, type, data);
743	GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
744}
745
746/** Constructor.
747 *
748 * @param context CTS context.
749 **/
750Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
751{
752}
753
754/** Destructor
755 *
756 **/
757Utils::vertexArray::~vertexArray()
758{
759	if (0 != m_id)
760	{
761		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
762
763		gl.deleteVertexArrays(1, &m_id);
764
765		m_id = 0;
766	}
767}
768
769/** Execute BindVertexArray
770 *
771 **/
772void Utils::vertexArray::bind()
773{
774	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
775
776	gl.bindVertexArray(m_id);
777	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
778}
779
780/** Execute GenVertexArrays
781 *
782 **/
783void Utils::vertexArray::generate()
784{
785	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
786
787	gl.genVertexArrays(1, &m_id);
788	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
789}
790
791/** Builds a program object consisting of up to 5 shader stages
792 *  (vertex/tessellation control/tessellation evaluation/geometry/fragment).
793 *  The shaders are attached to the program object, then compiled. Finally,
794 *  the program object is linked.
795 *
796 *  XFB can be optionally configured for the program object.
797 *
798 *  Should an error be reported by GL implementation, a TestError
799 *  exception will be thrown.
800 *
801 *  @param gl             OpenGL functions from the active rendering context.
802 *  @param vs_body        Body to use for the vertex shader. Can be an empty string.
803 *  @param tc_body        Body to use for the tessellation control shader. Can be
804 *                        an empty string.
805 *  @param te_body        Body to use for the tessellation evaluation shader. Can be
806 *                        an empty string.
807 *  @param gs_body        Body to use for the geometry shader. Can be an empty string.
808 *  @param fs_body        Body to use for the fragment shader. Can be an empty string.
809 *  @param xfb_varyings   An array of names of varyings to use for XFB. Can be NULL.
810 *  @param n_xfb_varyings Amount of XFB varyings defined in @param xfb_varyings.Can be 0.
811 *  @param out_vs_id      Deref will be used to store GL id of a generated vertex shader.
812 *                        Can be NULL in which case no vertex shader will be used for the
813 *                        program object.
814 *  @param out_tc_id      Deref will be used to store GL id of a generated tess control shader.
815 *                        Can be NULL in which case no tess control shader will be used for the
816 *                        program object.
817 *  @param out_te_id      Deref will be used to store GL id of a generated tess evaluation shader.
818 *                        Can be NULL in which case no tess evaluation shader will be used for the
819 *                        program object.
820 *  @param out_gs_id      Deref will be used to store GL id of a generated geometry shader.
821 *                        Can be NULL in which case no geometry shader will be used for the
822 *                        program object.
823 *  @param out_fs_id      Deref will be used to store GL id of a generated fragment shader.
824 *                        Can be NULL in which case no fragment shader will be used for the
825 *                        program object.
826 *  @param out_po_id      Deref will be used to store GL id of a generated program object.
827 *                        Must not be NULL.
828 *
829 *  @return true if the program was built successfully, false otherwise.
830 *  */
831bool Utils::buildProgram(const glw::Functions& gl, const std::string& vs_body, const std::string& tc_body,
832						 const std::string& te_body, const std::string& gs_body, const std::string& fs_body,
833						 const glw::GLchar** xfb_varyings, const unsigned int& n_xfb_varyings, glw::GLuint* out_vs_id,
834						 glw::GLuint* out_tc_id, glw::GLuint* out_te_id, glw::GLuint* out_gs_id, glw::GLuint* out_fs_id,
835						 glw::GLuint* out_po_id)
836{
837	bool result = false;
838
839	/* Link the program object */
840	glw::GLint link_status = GL_FALSE;
841
842	/* Create objects, set up shader bodies and attach all requested shaders to the program object */
843	*out_po_id = gl.createProgram();
844	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
845
846	if (out_vs_id != DE_NULL)
847	{
848		const char* vs_body_raw_ptr = vs_body.c_str();
849
850		*out_vs_id = gl.createShader(GL_VERTEX_SHADER);
851		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
852
853		gl.attachShader(*out_po_id, *out_vs_id);
854		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
855
856		gl.shaderSource(*out_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
857		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
858	}
859
860	if (out_tc_id != DE_NULL)
861	{
862		const char* tc_body_raw_ptr = tc_body.c_str();
863
864		*out_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
865		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
866
867		gl.attachShader(*out_po_id, *out_tc_id);
868		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
869
870		gl.shaderSource(*out_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
871		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
872	}
873
874	if (out_te_id != DE_NULL)
875	{
876		const char* te_body_raw_ptr = te_body.c_str();
877
878		*out_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
879		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
880
881		gl.attachShader(*out_po_id, *out_te_id);
882		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
883
884		gl.shaderSource(*out_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
885		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
886	}
887
888	if (out_gs_id != DE_NULL)
889	{
890		const char* gs_body_raw_ptr = gs_body.c_str();
891
892		*out_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
893		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
894
895		gl.attachShader(*out_po_id, *out_gs_id);
896		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
897
898		gl.shaderSource(*out_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
899		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
900	}
901
902	if (out_fs_id != DE_NULL)
903	{
904		const char* fs_body_raw_ptr = fs_body.c_str();
905
906		*out_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
907		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
908
909		gl.attachShader(*out_po_id, *out_fs_id);
910		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
911
912		gl.shaderSource(*out_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
913		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
914	}
915
916	/* Compile all shaders */
917	const glw::GLuint so_ids[] = { (out_vs_id != DE_NULL) ? *out_vs_id : 0, (out_tc_id != DE_NULL) ? *out_tc_id : 0,
918								   (out_te_id != DE_NULL) ? *out_te_id : 0, (out_gs_id != DE_NULL) ? *out_gs_id : 0,
919								   (out_fs_id != DE_NULL) ? *out_fs_id : 0 };
920	const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
921
922	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
923	{
924		glw::GLuint so_id = so_ids[n_so_id];
925
926		if (so_id != 0)
927		{
928			glw::GLint compile_status = GL_FALSE;
929
930			gl.compileShader(so_id);
931			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
932
933			gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
934			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
935
936			if (compile_status != GL_TRUE)
937			{
938				goto end;
939			}
940		} /* if (so_id != 0) */
941	}	 /* for (all shader objects) */
942
943	/* Set up XFB */
944	if (xfb_varyings != NULL)
945	{
946		gl.transformFeedbackVaryings(*out_po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
947		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
948	}
949
950	gl.linkProgram(*out_po_id);
951	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
952
953	gl.getProgramiv(*out_po_id, GL_LINK_STATUS, &link_status);
954	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
955
956	if (link_status != GL_TRUE)
957	{
958		goto end;
959	}
960
961	/* All done */
962	result = true;
963
964end:
965	return result;
966}
967
968/** Retrieves base variable type for user-specified variable type
969 *  (eg. float for vec4)
970 *
971 *  @param variable_type Variable type to use for the query.
972 *
973 *  @return As per description.
974 **/
975Utils::_variable_type Utils::getBaseVariableType(const _variable_type& variable_type)
976{
977	_variable_type result = VARIABLE_TYPE_UNKNOWN;
978
979	switch (variable_type)
980	{
981	case VARIABLE_TYPE_BOOL:
982	case VARIABLE_TYPE_BVEC2:
983	case VARIABLE_TYPE_BVEC3:
984	case VARIABLE_TYPE_BVEC4:
985	{
986		result = VARIABLE_TYPE_BOOL;
987
988		break;
989	}
990
991	case VARIABLE_TYPE_DOUBLE:
992	case VARIABLE_TYPE_DVEC2:
993	case VARIABLE_TYPE_DVEC3:
994	case VARIABLE_TYPE_DVEC4:
995	{
996		result = VARIABLE_TYPE_DOUBLE;
997
998		break;
999	}
1000
1001	case VARIABLE_TYPE_FLOAT:
1002	case VARIABLE_TYPE_MAT2:
1003	case VARIABLE_TYPE_MAT2X3:
1004	case VARIABLE_TYPE_MAT2X4:
1005	case VARIABLE_TYPE_MAT3:
1006	case VARIABLE_TYPE_MAT3X2:
1007	case VARIABLE_TYPE_MAT3X4:
1008	case VARIABLE_TYPE_MAT4:
1009	case VARIABLE_TYPE_MAT4X2:
1010	case VARIABLE_TYPE_MAT4X3:
1011	case VARIABLE_TYPE_VEC2:
1012	case VARIABLE_TYPE_VEC3:
1013	case VARIABLE_TYPE_VEC4:
1014	{
1015		result = VARIABLE_TYPE_FLOAT;
1016
1017		break;
1018	}
1019
1020	case VARIABLE_TYPE_INT:
1021	case VARIABLE_TYPE_IVEC2:
1022	case VARIABLE_TYPE_IVEC3:
1023	case VARIABLE_TYPE_IVEC4:
1024	{
1025		result = VARIABLE_TYPE_INT;
1026
1027		break;
1028	}
1029
1030	case VARIABLE_TYPE_UINT:
1031	case VARIABLE_TYPE_UVEC2:
1032	case VARIABLE_TYPE_UVEC3:
1033	case VARIABLE_TYPE_UVEC4:
1034	{
1035		result = VARIABLE_TYPE_UINT;
1036
1037		break;
1038	}
1039
1040	default:
1041	{
1042		TCU_FAIL("Unrecognized variable type");
1043	}
1044	} /* switch (variable_type) */
1045
1046	return result;
1047}
1048
1049/** Retrieves size of a single component (in bytes) for user-specified
1050 *  variable type.
1051 *
1052 *  @param variable_type Variable type to use for the query.
1053 *
1054 *  @return As per description.
1055 **/
1056unsigned int Utils::getComponentSizeForVariableType(const _variable_type& variable_type)
1057{
1058	_variable_type base_variable_type = getBaseVariableType(variable_type);
1059	unsigned int   result			  = 0;
1060
1061	switch (base_variable_type)
1062	{
1063	case VARIABLE_TYPE_BOOL:
1064		result = sizeof(bool);
1065		break;
1066	case VARIABLE_TYPE_DOUBLE:
1067		result = sizeof(double);
1068		break;
1069	case VARIABLE_TYPE_FLOAT:
1070		result = sizeof(float);
1071		break;
1072	case VARIABLE_TYPE_INT:
1073		result = sizeof(int);
1074		break;
1075	case VARIABLE_TYPE_UINT:
1076		result = sizeof(unsigned int);
1077		break;
1078
1079	default:
1080	{
1081		TCU_FAIL("Unrecognized base variable type");
1082	}
1083	} /* switch (variable_type) */
1084
1085	return result;
1086}
1087
1088/** Retrieves a GLenum value corresponding to internal shader stage
1089 *  representation.
1090 *
1091 *  @param shader_stage Shader stage to user for the query.
1092 *
1093 *  @return Requested value or GL_NONE if the stage was not recognized.
1094 **/
1095glw::GLenum Utils::getGLenumForShaderStage(const _shader_stage& shader_stage)
1096{
1097	glw::GLenum result = GL_NONE;
1098
1099	switch (shader_stage)
1100	{
1101	case SHADER_STAGE_VERTEX:
1102		result = GL_VERTEX_SHADER;
1103		break;
1104	case SHADER_STAGE_TESSELLATION_CONTROL:
1105		result = GL_TESS_CONTROL_SHADER;
1106		break;
1107	case SHADER_STAGE_TESSELLATION_EVALUATION:
1108		result = GL_TESS_EVALUATION_SHADER;
1109		break;
1110	case SHADER_STAGE_GEOMETRY:
1111		result = GL_GEOMETRY_SHADER;
1112		break;
1113	case SHADER_STAGE_FRAGMENT:
1114		result = GL_FRAGMENT_SHADER;
1115		break;
1116
1117	default:
1118	{
1119		TCU_FAIL("Unrecognized shader stage requested");
1120	}
1121	} /* switch (shader_stage) */
1122
1123	return result;
1124}
1125
1126/** Retrieves number of components that user-specified variable type supports.
1127 *
1128 *  @param variable_type GLSL variable type to use for the query.
1129 *
1130 *  @return As per description.
1131 **/
1132unsigned int Utils::getNumberOfComponentsForVariableType(const _variable_type& variable_type)
1133{
1134	unsigned int result = 0;
1135
1136	switch (variable_type)
1137	{
1138	case VARIABLE_TYPE_BOOL:
1139	case VARIABLE_TYPE_DOUBLE:
1140	case VARIABLE_TYPE_FLOAT:
1141	case VARIABLE_TYPE_INT:
1142	case VARIABLE_TYPE_UINT:
1143	{
1144		result = 1;
1145
1146		break;
1147	}
1148
1149	case VARIABLE_TYPE_BVEC2:
1150	case VARIABLE_TYPE_DVEC2:
1151	case VARIABLE_TYPE_IVEC2:
1152	case VARIABLE_TYPE_UVEC2:
1153	case VARIABLE_TYPE_VEC2:
1154	{
1155		result = 2;
1156
1157		break;
1158	}
1159
1160	case VARIABLE_TYPE_BVEC3:
1161	case VARIABLE_TYPE_DVEC3:
1162	case VARIABLE_TYPE_IVEC3:
1163	case VARIABLE_TYPE_UVEC3:
1164	case VARIABLE_TYPE_VEC3:
1165	{
1166		result = 3;
1167
1168		break;
1169	}
1170
1171	case VARIABLE_TYPE_BVEC4:
1172	case VARIABLE_TYPE_DVEC4:
1173	case VARIABLE_TYPE_IVEC4:
1174	case VARIABLE_TYPE_MAT2:
1175	case VARIABLE_TYPE_UVEC4:
1176	case VARIABLE_TYPE_VEC4:
1177	{
1178		result = 4;
1179
1180		break;
1181	}
1182
1183	case VARIABLE_TYPE_MAT2X3:
1184	case VARIABLE_TYPE_MAT3X2:
1185	{
1186		result = 6;
1187
1188		break;
1189	}
1190
1191	case VARIABLE_TYPE_MAT2X4:
1192	case VARIABLE_TYPE_MAT4X2:
1193	{
1194		result = 8;
1195
1196		break;
1197	}
1198
1199	case VARIABLE_TYPE_MAT3:
1200	{
1201		result = 9;
1202
1203		break;
1204	}
1205
1206	case VARIABLE_TYPE_MAT3X4:
1207	case VARIABLE_TYPE_MAT4X3:
1208	{
1209		result = 12;
1210
1211		break;
1212	}
1213
1214	case VARIABLE_TYPE_MAT4:
1215	{
1216		result = 16;
1217
1218		break;
1219	}
1220
1221	default:
1222		break;
1223	} /* switch (variable_type) */
1224
1225	return result;
1226}
1227
1228/** Retrieves a literal defining user-specified shader stage enum.
1229 *
1230 *  @param shader_stage Shader stage to use for the query.
1231 *
1232 *  @return Requested string or "?" if the stage was not recognized.
1233 **/
1234std::string Utils::getShaderStageString(const _shader_stage& shader_stage)
1235{
1236	std::string result = "?";
1237
1238	switch (shader_stage)
1239	{
1240	case SHADER_STAGE_FRAGMENT:
1241		result = "Fragment Shader";
1242		break;
1243	case SHADER_STAGE_GEOMETRY:
1244		result = "Geometry Shader";
1245		break;
1246	case SHADER_STAGE_TESSELLATION_CONTROL:
1247		result = "Tessellation Control Shader";
1248		break;
1249	case SHADER_STAGE_TESSELLATION_EVALUATION:
1250		result = "Tessellation Evaluation Shader";
1251		break;
1252	case SHADER_STAGE_VERTEX:
1253		result = "Vertex Shader";
1254		break;
1255
1256	default:
1257	{
1258		TCU_FAIL("Unrecognized shader stage");
1259	}
1260	} /* switch (shader_stage) */
1261
1262	return result;
1263}
1264
1265/** Retrieves a literal defining user-specified shader stage enum.
1266 *
1267 *  @param shader_stage_glenum Shader stage to use for the query.
1268 *
1269 *  @return Requested string or "?" if the stage was not recognized.
1270 **/
1271std::string Utils::getShaderStageStringFromGLEnum(const glw::GLenum shader_stage_glenum)
1272{
1273	std::string result = "?";
1274
1275	switch (shader_stage_glenum)
1276	{
1277	case GL_FRAGMENT_SHADER:
1278		result = "Fragment Shader";
1279		break;
1280	case GL_GEOMETRY_SHADER:
1281		result = "Geometry Shader";
1282		break;
1283	case GL_TESS_CONTROL_SHADER:
1284		result = "Tessellation Control Shader";
1285		break;
1286	case GL_TESS_EVALUATION_SHADER:
1287		result = "Tessellation Evaluation Shader";
1288		break;
1289	case GL_VERTEX_SHADER:
1290		result = "Vertex Shader";
1291		break;
1292
1293	default:
1294	{
1295		TCU_FAIL("Unrecognized shader string");
1296	}
1297	} /* switch (shader_stage_glenum) */
1298
1299	return result;
1300}
1301
1302/** Returns string that represents program interface name
1303 *
1304 * @param program_interface Program interface
1305 *
1306 * @return String representation of known program interface
1307 **/
1308const GLchar* Utils::programInterfaceToStr(glw::GLenum program_interface)
1309{
1310	const GLchar* string = "Unknown program interface";
1311
1312	switch (program_interface)
1313	{
1314	case GL_VERTEX_SUBROUTINE:
1315		string = "GL_VERTEX_SUBROUTINE";
1316		break;
1317	case GL_VERTEX_SUBROUTINE_UNIFORM:
1318		string = "GL_VERTEX_SUBROUTINE_UNIFORM";
1319		break;
1320	default:
1321		TCU_FAIL("Not implemented");
1322		break;
1323	};
1324
1325	return string;
1326}
1327
1328/** Returns string that represents pname's name
1329 *
1330 * @param pname pname
1331 *
1332 * @return String representation of known pnames
1333 **/
1334const GLchar* Utils::pnameToStr(glw::GLenum pname)
1335{
1336	const GLchar* string = "Unknown pname";
1337
1338	switch (pname)
1339	{
1340	case GL_ACTIVE_SUBROUTINE_UNIFORMS:
1341		string = "GL_ACTIVE_SUBROUTINE_UNIFORMS";
1342		break;
1343	case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS:
1344		string = "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS";
1345		break;
1346	case GL_ACTIVE_SUBROUTINES:
1347		string = "GL_ACTIVE_SUBROUTINES";
1348		break;
1349	case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH:
1350		string = "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH";
1351		break;
1352	case GL_ACTIVE_SUBROUTINE_MAX_LENGTH:
1353		string = "GL_ACTIVE_SUBROUTINE_MAX_LENGTH";
1354		break;
1355	case GL_NUM_COMPATIBLE_SUBROUTINES:
1356		string = "GL_NUM_COMPATIBLE_SUBROUTINES";
1357		break;
1358	case GL_UNIFORM_SIZE:
1359		string = "GL_UNIFORM_SIZE";
1360		break;
1361	case GL_COMPATIBLE_SUBROUTINES:
1362		string = "GL_COMPATIBLE_SUBROUTINES";
1363		break;
1364	case GL_UNIFORM_NAME_LENGTH:
1365		string = "GL_UNIFORM_NAME_LENGTH";
1366		break;
1367	case GL_ACTIVE_RESOURCES:
1368		string = "GL_ACTIVE_RESOURCES";
1369		break;
1370	case GL_MAX_NAME_LENGTH:
1371		string = "GL_MAX_NAME_LENGTH";
1372		break;
1373	case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
1374		string = "GL_MAX_NUM_COMPATIBLE_SUBROUTINES";
1375		break;
1376	case GL_NAME_LENGTH:
1377		string = "GL_NAME_LENGTH";
1378		break;
1379	case GL_ARRAY_SIZE:
1380		string = "GL_ARRAY_SIZE";
1381		break;
1382	case GL_LOCATION:
1383		string = "GL_LOCATION";
1384		break;
1385	default:
1386		TCU_FAIL("Not implemented");
1387		break;
1388	};
1389
1390	return string;
1391}
1392
1393bool Utils::compare(const glw::GLfloat& left, const glw::GLfloat& right)
1394{
1395	static const glw::GLfloat m_epsilon = 0.00001f;
1396
1397	if (m_epsilon < std::abs(right - left))
1398	{
1399		return false;
1400	}
1401	else
1402	{
1403		return true;
1404	}
1405}
1406
1407/** Returns a variable type enum corresponding to user-specified base variable type
1408 *  and the number of components it should support.
1409 *
1410 *  @param base_variable_type Base variable type to use for the query.
1411 *  @param n_components       Number of components to consider for the query.
1412 *
1413 *  @return As per description.
1414 **/
1415Utils::_variable_type Utils::getVariableTypeFromProperties(const _variable_type& base_variable_type,
1416														   const unsigned int&   n_components)
1417{
1418	_variable_type result = VARIABLE_TYPE_UNKNOWN;
1419
1420	switch (base_variable_type)
1421	{
1422	case VARIABLE_TYPE_BOOL:
1423	{
1424		switch (n_components)
1425		{
1426		case 1:
1427			result = VARIABLE_TYPE_BOOL;
1428			break;
1429		case 2:
1430			result = VARIABLE_TYPE_BVEC2;
1431			break;
1432		case 3:
1433			result = VARIABLE_TYPE_BVEC3;
1434			break;
1435		case 4:
1436			result = VARIABLE_TYPE_BVEC4;
1437			break;
1438
1439		default:
1440		{
1441			TCU_FAIL("Unsupported number of components requested");
1442		}
1443		} /* switch (n_components) */
1444
1445		break;
1446	}
1447
1448	case VARIABLE_TYPE_DOUBLE:
1449	{
1450		switch (n_components)
1451		{
1452		case 1:
1453			result = VARIABLE_TYPE_DOUBLE;
1454			break;
1455		case 2:
1456			result = VARIABLE_TYPE_DVEC2;
1457			break;
1458		case 3:
1459			result = VARIABLE_TYPE_DVEC3;
1460			break;
1461		case 4:
1462			result = VARIABLE_TYPE_DVEC4;
1463			break;
1464
1465		default:
1466		{
1467			TCU_FAIL("Unsupported number of components requested");
1468		}
1469		} /* switch (n_components) */
1470
1471		break;
1472	}
1473
1474	case VARIABLE_TYPE_FLOAT:
1475	{
1476		switch (n_components)
1477		{
1478		case 1:
1479			result = VARIABLE_TYPE_FLOAT;
1480			break;
1481		case 2:
1482			result = VARIABLE_TYPE_VEC2;
1483			break;
1484		case 3:
1485			result = VARIABLE_TYPE_VEC3;
1486			break;
1487		case 4:
1488			result = VARIABLE_TYPE_VEC4;
1489			break;
1490
1491		default:
1492		{
1493			TCU_FAIL("Unsupported number of components requested");
1494		}
1495		} /* switch (n_components) */
1496
1497		break;
1498	}
1499
1500	case VARIABLE_TYPE_INT:
1501	{
1502		switch (n_components)
1503		{
1504		case 1:
1505			result = VARIABLE_TYPE_INT;
1506			break;
1507		case 2:
1508			result = VARIABLE_TYPE_IVEC2;
1509			break;
1510		case 3:
1511			result = VARIABLE_TYPE_IVEC3;
1512			break;
1513		case 4:
1514			result = VARIABLE_TYPE_IVEC4;
1515			break;
1516
1517		default:
1518		{
1519			TCU_FAIL("Unsupported number of components requested");
1520		}
1521		} /* switch (n_components) */
1522
1523		break;
1524	}
1525
1526	case VARIABLE_TYPE_UINT:
1527	{
1528		switch (n_components)
1529		{
1530		case 1:
1531			result = VARIABLE_TYPE_UINT;
1532			break;
1533		case 2:
1534			result = VARIABLE_TYPE_UVEC2;
1535			break;
1536		case 3:
1537			result = VARIABLE_TYPE_UVEC3;
1538			break;
1539		case 4:
1540			result = VARIABLE_TYPE_UVEC4;
1541			break;
1542
1543		default:
1544		{
1545			TCU_FAIL("Unsupported number of components requested");
1546		}
1547		} /* switch (n_components) */
1548
1549		break;
1550	}
1551
1552	default:
1553	{
1554		TCU_FAIL("Unrecognized base variable type");
1555	}
1556	} /* switch (base_variable_type) */
1557
1558	return result;
1559}
1560
1561/** Returns a GLSL literal corresponding to user-specified variable type.
1562 *
1563 *  @param variable_type Variable type to use for the query.
1564 *
1565 *  @return As per description or [?] if @param variable_type was not
1566 *          recognized.
1567 **/
1568std::string Utils::getVariableTypeGLSLString(const _variable_type& variable_type)
1569{
1570	std::string result = "[?]";
1571
1572	switch (variable_type)
1573	{
1574	case VARIABLE_TYPE_BOOL:
1575		result = "bool";
1576		break;
1577	case VARIABLE_TYPE_BVEC2:
1578		result = "bvec2";
1579		break;
1580	case VARIABLE_TYPE_BVEC3:
1581		result = "bvec3";
1582		break;
1583	case VARIABLE_TYPE_BVEC4:
1584		result = "bvec4";
1585		break;
1586	case VARIABLE_TYPE_DOUBLE:
1587		result = "double";
1588		break;
1589	case VARIABLE_TYPE_DVEC2:
1590		result = "dvec2";
1591		break;
1592	case VARIABLE_TYPE_DVEC3:
1593		result = "dvec3";
1594		break;
1595	case VARIABLE_TYPE_DVEC4:
1596		result = "dvec4";
1597		break;
1598	case VARIABLE_TYPE_FLOAT:
1599		result = "float";
1600		break;
1601	case VARIABLE_TYPE_INT:
1602		result = "int";
1603		break;
1604	case VARIABLE_TYPE_IVEC2:
1605		result = "ivec2";
1606		break;
1607	case VARIABLE_TYPE_IVEC3:
1608		result = "ivec3";
1609		break;
1610	case VARIABLE_TYPE_IVEC4:
1611		result = "ivec4";
1612		break;
1613	case VARIABLE_TYPE_MAT2:
1614		result = "mat2";
1615		break;
1616	case VARIABLE_TYPE_MAT2X3:
1617		result = "mat2x3";
1618		break;
1619	case VARIABLE_TYPE_MAT2X4:
1620		result = "mat2x4";
1621		break;
1622	case VARIABLE_TYPE_MAT3:
1623		result = "mat3";
1624		break;
1625	case VARIABLE_TYPE_MAT3X2:
1626		result = "mat3x2";
1627		break;
1628	case VARIABLE_TYPE_MAT3X4:
1629		result = "mat3x4";
1630		break;
1631	case VARIABLE_TYPE_MAT4:
1632		result = "mat4";
1633		break;
1634	case VARIABLE_TYPE_MAT4X2:
1635		result = "mat4x2";
1636		break;
1637	case VARIABLE_TYPE_MAT4X3:
1638		result = "mat4x3";
1639		break;
1640	case VARIABLE_TYPE_UINT:
1641		result = "uint";
1642		break;
1643	case VARIABLE_TYPE_UVEC2:
1644		result = "uvec2";
1645		break;
1646	case VARIABLE_TYPE_UVEC3:
1647		result = "uvec3";
1648		break;
1649	case VARIABLE_TYPE_UVEC4:
1650		result = "uvec4";
1651		break;
1652	case VARIABLE_TYPE_VEC2:
1653		result = "vec2";
1654		break;
1655	case VARIABLE_TYPE_VEC3:
1656		result = "vec3";
1657		break;
1658	case VARIABLE_TYPE_VEC4:
1659		result = "vec4";
1660		break;
1661
1662	default:
1663	{
1664		TCU_FAIL("Unrecognized variable type");
1665	}
1666	} /* switch (variable_type) */
1667
1668	return result;
1669}
1670
1671/** Constructor.
1672 *
1673 *  @param context Rendering context.
1674 *
1675 **/
1676APITest1::APITest1(deqp::Context& context)
1677	: TestCase(context, "min_maxes", "Verifies the implementation returns valid GL_MAX_SUBROUTINE* pnames "
1678									 "which meet the minimum maximum requirements enforced by the spec.")
1679	, m_has_test_passed(true)
1680{
1681	/* Left blank intentionally */
1682}
1683
1684/** Executes test iteration.
1685 *
1686 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1687 */
1688tcu::TestNode::IterateResult APITest1::iterate()
1689{
1690	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1691
1692	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
1693	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
1694	{
1695		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
1696	}
1697
1698	/* Iterate over all pnames */
1699	const struct
1700	{
1701		glw::GLenum pname;
1702		const char* pname_string;
1703		glw::GLint  min_value;
1704	} pnames[] = { { GL_MAX_SUBROUTINES, "GL_MAX_SUBROUTINES", 256 },
1705				   { GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS", 1024 } };
1706	const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
1707
1708	for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
1709	{
1710		glw::GLboolean	 bool_value   = GL_FALSE;
1711		glw::GLdouble	  double_value = 0.0;
1712		glw::GLfloat	   float_value  = 0.0f;
1713		glw::GLint		   int_value	= 0;
1714		glw::GLint64	   int64_value  = 0;
1715		const glw::GLint   min_value	= pnames[n_pname].min_value;
1716		const glw::GLenum& pname		= pnames[n_pname].pname;
1717		const char*		   pname_string = pnames[n_pname].pname_string;
1718
1719		/* Retrieve the pname values */
1720		gl.getBooleanv(pname, &bool_value);
1721		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() call failed.");
1722
1723		gl.getDoublev(pname, &double_value);
1724		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetDoublev() call failed.");
1725
1726		gl.getFloatv(pname, &float_value);
1727		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed.");
1728
1729		gl.getIntegerv(pname, &int_value);
1730		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
1731
1732		gl.getInteger64v(pname, &int64_value);
1733		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v() call failed.");
1734
1735		/* Make sure the value reported meets the min max requirement */
1736		if (int_value < min_value)
1737		{
1738			m_testCtx.getLog() << tcu::TestLog::Message << "GL implementation reports a value of [" << int_value
1739							   << "]"
1740								  " for property ["
1741							   << pname_string << "]"
1742												  ", whereas the min max for the property is ["
1743							   << min_value << "]." << tcu::TestLog::EndMessage;
1744
1745			m_has_test_passed = false;
1746		}
1747
1748		/* Verify the other getters reported valid values */
1749		const float epsilon = 1e-5f;
1750
1751		if (((int_value == 0) && (bool_value == GL_TRUE)) || ((int_value != 0) && (bool_value != GL_TRUE)))
1752		{
1753			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid boolean value [" << bool_value
1754							   << "]"
1755								  " reported for property ["
1756							   << pname_string << "]"
1757												  " (int value:["
1758							   << int_value << "])" << tcu::TestLog::EndMessage;
1759
1760			m_has_test_passed = false;
1761		}
1762
1763		if (de::abs(double_value - (double)int_value) > epsilon)
1764		{
1765			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid double value [" << double_value
1766							   << "]"
1767								  " reported for property ["
1768							   << pname_string << "]"
1769												  " (int value:["
1770							   << int_value << "])" << tcu::TestLog::EndMessage;
1771
1772			m_has_test_passed = false;
1773		}
1774
1775		if (de::abs(float_value - (float)int_value) > epsilon)
1776		{
1777			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid float value [" << float_value
1778							   << "]"
1779								  " reported for property ["
1780							   << pname_string << "]"
1781												  " (int value:["
1782							   << int_value << "])" << tcu::TestLog::EndMessage;
1783
1784			m_has_test_passed = false;
1785		}
1786
1787		if (int64_value != int_value)
1788		{
1789			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid 64-bit integer value [" << float_value
1790							   << "]"
1791								  " reported for property ["
1792							   << pname_string << "]"
1793												  " (int value:["
1794							   << int_value << "])" << tcu::TestLog::EndMessage;
1795
1796			m_has_test_passed = false;
1797		}
1798	} /* for (all pnames) */
1799
1800	if (m_has_test_passed)
1801	{
1802		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1803	}
1804	else
1805	{
1806		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1807	}
1808
1809	return STOP;
1810}
1811
1812/** Constructor.
1813 *
1814 *  @param context Rendering context.
1815 *
1816 **/
1817APITest2::APITest2(deqp::Context& context)
1818	: TestCase(context, "name_getters", "Verifies glGetActiveSubroutineName() and glGetActiveSubroutineUniformName() "
1819										"functions work correctly.")
1820	, m_buffer(DE_NULL)
1821	, m_has_test_passed(true)
1822	, m_po_id(0)
1823	, m_subroutine_name1("subroutine1")
1824	, m_subroutine_name2("subroutine2")
1825	, m_subroutine_uniform_name("data_provider")
1826	, m_vs_id(0)
1827{
1828	/* Left blank intentionally */
1829}
1830
1831/** Destroys all ES objects that may have been created during test initialization,
1832 *  as well as releases any buffers that may have been allocated during the process.
1833 */
1834void APITest2::deinit()
1835{
1836	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1837
1838	if (m_buffer != DE_NULL)
1839	{
1840		delete[] m_buffer;
1841
1842		m_buffer = DE_NULL;
1843	}
1844
1845	if (m_po_id != 0)
1846	{
1847		gl.deleteProgram(m_po_id);
1848
1849		m_po_id = 0;
1850	}
1851
1852	if (m_vs_id != 0)
1853	{
1854		gl.deleteShader(m_vs_id);
1855
1856		m_vs_id = 0;
1857	}
1858}
1859
1860/** Returns body of a vertex shader that should be used for the test.
1861 *
1862 *  @return As per description.
1863 **/
1864std::string APITest2::getVertexShaderBody()
1865{
1866	return "#version 400\n"
1867		   "\n"
1868		   "#extension GL_ARB_shader_subroutine : require\n"
1869		   "\n"
1870		   "subroutine int ExampleSubroutineType(int example_argument);\n"
1871		   "\n"
1872		   "subroutine(ExampleSubroutineType) int subroutine1(int example_argument)\n"
1873		   "{\n"
1874		   "    return 1;\n"
1875		   "}\n"
1876		   "\n"
1877		   "subroutine(ExampleSubroutineType) int subroutine2(int example_argument)\n"
1878		   "{\n"
1879		   "    return 2;\n"
1880		   "}\n"
1881		   "\n"
1882		   "subroutine uniform ExampleSubroutineType data_provider;\n"
1883		   "\n"
1884		   "void main()\n"
1885		   "{\n"
1886		   "    gl_Position = vec4(float(data_provider(0)), vec3(1) );\n"
1887		   "}\n";
1888}
1889
1890/** Initializes all ES objects required to run the test. */
1891void APITest2::initTest()
1892{
1893	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1894
1895	/* Generate program & shader objects */
1896	m_po_id = gl.createProgram();
1897	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1898
1899	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call(s) failed.");
1900
1901	/* Attach the shader to the program object */
1902	gl.attachShader(m_po_id, m_vs_id);
1903	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
1904
1905	/* Compile the shader */
1906	glw::GLint  compile_status  = GL_FALSE;
1907	std::string vs_body			= getVertexShaderBody();
1908	const char* vs_body_raw_ptr = vs_body.c_str();
1909
1910	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
1911	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1912
1913	gl.compileShader(m_vs_id);
1914	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1915
1916	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1917	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1918
1919	if (compile_status != GL_TRUE)
1920	{
1921		TCU_FAIL("Shader compilation failed.");
1922	}
1923
1924	/* Try to link the program object */
1925	glw::GLint link_status = GL_FALSE;
1926
1927	gl.linkProgram(m_po_id);
1928	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1929
1930	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1931	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
1932
1933	if (link_status != GL_TRUE)
1934	{
1935		TCU_FAIL("Program linking failed.");
1936	}
1937
1938	/* Perform a few sanity checks */
1939	glw::GLint n_active_subroutines			= 0;
1940	glw::GLint n_active_subroutine_uniforms = 0;
1941
1942	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
1943	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
1944	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call failed.");
1945
1946	if (n_active_subroutines != 2 /* subroutines declared in vertex shader */)
1947	{
1948		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid amount of active subroutines reported; expected: 2,"
1949													   " reported:"
1950						   << n_active_subroutines << tcu::TestLog::EndMessage;
1951
1952		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINES property value.");
1953	}
1954
1955	if (n_active_subroutine_uniforms != 1)
1956	{
1957		m_testCtx.getLog() << tcu::TestLog::Message
1958						   << "Invalid amount of active subroutine uniforms reported: expected: 1,"
1959							  " reported: "
1960						   << n_active_subroutine_uniforms << tcu::TestLog::EndMessage;
1961
1962		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORMS property value.");
1963	}
1964}
1965
1966/** Executes test iteration.
1967 *
1968 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1969 */
1970tcu::TestNode::IterateResult APITest2::iterate()
1971{
1972	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
1973	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
1974	{
1975		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
1976	}
1977
1978	/* Initialize a test program object */
1979	initTest();
1980
1981	/* Verify glGetActiveSubroutineName() works correctly */
1982	verifyGLGetActiveSubroutineNameFunctionality();
1983
1984	/* Verify glGetActiveSubroutineUniformName() works correctly */
1985	verifyGLGetActiveSubroutineUniformNameFunctionality();
1986
1987	/* Done */
1988	if (m_has_test_passed)
1989	{
1990		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1991	}
1992	else
1993	{
1994		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1995	}
1996
1997	return STOP;
1998}
1999
2000/** Verifies glGetActiveSubroutineName() behaves as per GL_ARB_shader_subroutine
2001 *  specification.
2002 **/
2003void APITest2::verifyGLGetActiveSubroutineNameFunctionality()
2004{
2005	GLsizei				  expected_length1 = (GLsizei)strlen(m_subroutine_name1) + 1;
2006	GLsizei				  expected_length2 = (GLsizei)strlen(m_subroutine_name1) + 1;
2007	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
2008	GLsizei				  reported_length  = 0;
2009
2010	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2011							   0,							 /* bufsize */
2012							   DE_NULL,						 /* length */
2013							   DE_NULL);					 /* name */
2014	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2015
2016	gl.getProgramInterfaceiv(m_po_id, GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, &reported_length);
2017	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2018
2019	if ((reported_length != expected_length1) && (reported_length != expected_length2))
2020	{
2021		m_testCtx.getLog() << tcu::TestLog::Message
2022						   << "Invalid active subroutine name length reported:" << reported_length
2023						   << ", instead of: " << expected_length1 << " or " << expected_length2
2024						   << tcu::TestLog::EndMessage;
2025
2026		TCU_FAIL("Incorrect length of active subroutine name");
2027	}
2028
2029	m_buffer = new glw::GLchar[reported_length];
2030
2031	memset(m_buffer, 0, reported_length);
2032
2033	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, reported_length, DE_NULL, /* length */
2034							   m_buffer);
2035	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2036
2037	if (strcmp(m_buffer, m_subroutine_name1) != 0 && strcmp(m_buffer, m_subroutine_name2) != 0)
2038	{
2039		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine name reported:[" << m_buffer
2040						   << "]"
2041							  " instead of:["
2042						   << m_subroutine_name1 << "]"
2043													" or:["
2044						   << m_subroutine_name2 << "]." << tcu::TestLog::EndMessage;
2045
2046		TCU_FAIL("Invalid active subroutine name reported.");
2047	}
2048
2049	delete[] m_buffer;
2050	m_buffer = DE_NULL;
2051}
2052
2053/** Verifies glGetActiveSubroutineUniformName() behaves as per GL_ARB_shader_subroutine
2054 *  specification.
2055 **/
2056void APITest2::verifyGLGetActiveSubroutineUniformNameFunctionality()
2057{
2058	GLsizei				  expected_length = (GLsizei)strlen(m_subroutine_uniform_name);
2059	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
2060	GLsizei				  reported_length = 0;
2061
2062	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2063									  0,							/* bufsize */
2064									  DE_NULL,						/* length */
2065									  DE_NULL);						/* name */
2066	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed.");
2067
2068	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2069									  0,							/* bufsize */
2070									  &reported_length, DE_NULL);   /* name */
2071	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed.");
2072
2073	// reported_length is the actual number of characters written into <name>
2074	// If <bufSize> is 0, reported_length should be 0
2075	if (reported_length != 0)
2076	{
2077		m_testCtx.getLog() << tcu::TestLog::Message
2078						   << "Invalid active subroutine uniform name length reported:" << reported_length
2079						   << ", instead of: " << 0 << tcu::TestLog::EndMessage;
2080
2081		TCU_FAIL("Incorrect length of active subroutine uniform name");
2082	}
2083
2084	m_buffer = new glw::GLchar[expected_length + 1];
2085
2086	memset(m_buffer, 0, expected_length + 1);
2087
2088	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, expected_length + 1, &reported_length, m_buffer);
2089	GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformName() call failed.");
2090
2091	if (reported_length != expected_length)
2092	{
2093		m_testCtx.getLog() << tcu::TestLog::Message
2094						   << "Invalid active subroutine uniform name length reported:" << reported_length
2095						   << ", instead of: " << expected_length << tcu::TestLog::EndMessage;
2096
2097		TCU_FAIL("Incorrect length of active subroutine uniform name");
2098	}
2099
2100	if (strcmp(m_buffer, m_subroutine_uniform_name) != 0)
2101	{
2102		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine uniform name reported:[" << m_buffer
2103						   << "]"
2104							  " instead of:["
2105						   << m_subroutine_uniform_name << "]" << tcu::TestLog::EndMessage;
2106
2107		TCU_FAIL("Invalid active subroutine uniform name reported.");
2108	}
2109
2110	delete[] m_buffer;
2111	m_buffer = DE_NULL;
2112}
2113
2114/** Constructor.
2115 *
2116 *  @param context Rendering context.
2117 *
2118 **/
2119FunctionalTest1_2::FunctionalTest1_2(deqp::Context& context)
2120	: TestCase(context, "two_subroutines_single_subroutine_uniform",
2121			   "Verifies the subroutines work correctly in a vertex shader for"
2122			   " bool/float/int/uint/double/*vec*/*mat* argument and return types")
2123	, m_has_test_passed(true)
2124	, m_po_id(0)
2125	, m_po_getter0_subroutine_index(GL_INVALID_INDEX)
2126	, m_po_getter1_subroutine_index(GL_INVALID_INDEX)
2127	, m_po_subroutine_uniform_index(-1)
2128	, m_xfb_bo_id(0)
2129	, m_vao_id(0)
2130	, m_vs_id(0)
2131{
2132	/* Left blank intentionally */
2133}
2134
2135/** Destroys all ES objects that may have been created during test initialization,
2136 *  as well as releases any buffers that may have been allocated during the process.
2137 */
2138void FunctionalTest1_2::deinit()
2139{
2140	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2141
2142	deinitTestIteration();
2143
2144	if (m_xfb_bo_id != 0)
2145	{
2146		gl.deleteBuffers(1, &m_xfb_bo_id);
2147
2148		m_xfb_bo_id = 0;
2149	}
2150
2151	if (m_vao_id != 0)
2152	{
2153		gl.deleteVertexArrays(1, &m_vao_id);
2154
2155		m_vao_id = 0;
2156	}
2157}
2158
2159/** Deinitializes GL objects that are iteration-specific */
2160void FunctionalTest1_2::deinitTestIteration()
2161{
2162	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2163
2164	if (m_po_id != 0)
2165	{
2166		gl.deleteProgram(m_po_id);
2167
2168		m_po_id = 0;
2169	}
2170
2171	if (m_vs_id != 0)
2172	{
2173		gl.deleteShader(m_vs_id);
2174
2175		m_vs_id = 0;
2176	}
2177}
2178
2179/** Executes a single test iteration using user-specified test case propertiesz.
2180 *
2181 *  @param test-case Test case descriptor.
2182 *
2183 *  @return true if the test iteration passed, false otherwise.
2184 **/
2185bool FunctionalTest1_2::executeTestIteration(const _test_case& test_case)
2186{
2187	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2188	bool				  result = true;
2189
2190	/* Build the test program */
2191	std::string		   empty_body;
2192	std::string		   vs_body		  = getVertexShaderBody(test_case.variable_type, test_case.array_size);
2193	const glw::GLchar* xfb_varyings[] = { "result" };
2194	const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
2195
2196	if (!Utils::buildProgram(gl, vs_body, empty_body, empty_body, empty_body, empty_body, xfb_varyings, n_xfb_varyings,
2197							 &m_vs_id, NULL, /* out_tc_id */
2198							 NULL,			 /* out_te_id */
2199							 NULL,			 /* out_gs_id */
2200							 NULL, &m_po_id))
2201	{
2202		TCU_FAIL("Test program failed to build.");
2203	}
2204
2205	/* Retrieve subroutine locations */
2206	m_po_getter0_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter0");
2207	m_po_getter1_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter1");
2208
2209	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
2210
2211	if (m_po_getter0_subroutine_index == GL_INVALID_INDEX || m_po_getter1_subroutine_index == GL_INVALID_INDEX)
2212	{
2213		TCU_FAIL("At least one subroutine is considered inactive which is invalid.");
2214	}
2215
2216	/* Retrieve subroutine uniform location */
2217	m_po_subroutine_uniform_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "colorGetterUniform");
2218
2219	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call failed.");
2220
2221	if (m_po_subroutine_uniform_index == -1)
2222	{
2223		TCU_FAIL("Subroutine uniform is considered inactive which is invalid.");
2224	}
2225
2226	/* Set up XFB BO storage */
2227	const Utils::_variable_type base_variable_type	= Utils::getBaseVariableType(test_case.variable_type);
2228	unsigned int				iteration_xfb_bo_size = Utils::getComponentSizeForVariableType(base_variable_type) *
2229										 Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
2230	unsigned int total_xfb_bo_size = 0;
2231
2232	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2233	{
2234		/* Boolean varyings are not supported by OpenGL. Instead, we use ints to output
2235		 * boolean values. */
2236		iteration_xfb_bo_size = static_cast<unsigned int>(iteration_xfb_bo_size * sizeof(int));
2237	}
2238
2239	total_xfb_bo_size = iteration_xfb_bo_size * 2 /* subroutines we will be testing */;
2240
2241	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, total_xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
2242	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2243
2244	/* Activate test program object */
2245	gl.useProgram(m_po_id);
2246	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2247
2248	/* Run two iterations. Each iteration should invoke different subroutine. */
2249	const glw::GLuint  subroutine_indices[] = { m_po_getter0_subroutine_index, m_po_getter1_subroutine_index };
2250	const unsigned int n_subroutine_indices = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
2251
2252	for (unsigned int n_subroutine_index = 0; n_subroutine_index < n_subroutine_indices; ++n_subroutine_index)
2253	{
2254		/* Configure which subroutine should be used for the draw call */
2255		glw::GLuint current_subroutine_index = subroutine_indices[n_subroutine_index];
2256
2257		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &current_subroutine_index);
2258		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
2259
2260		/* Update XFB binding so that we do not overwrite data XFBed in previous iterations */
2261		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2262						   m_xfb_bo_id, iteration_xfb_bo_size * n_subroutine_index, iteration_xfb_bo_size);
2263		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() call failed.");
2264
2265		/* Draw a single point */
2266		gl.beginTransformFeedback(GL_POINTS);
2267		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2268		{
2269			gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2270			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
2271		}
2272		gl.endTransformFeedback();
2273		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
2274	} /* for (all subroutine indices) */
2275
2276	/* Map the BO storage into process space */
2277	const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2278	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
2279
2280	result &= verifyXFBData(xfb_data_ptr, test_case.variable_type);
2281
2282	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2283	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffeR() call failed.");
2284
2285	return result;
2286}
2287
2288/** Retrieves body of a vertex shader that should be used to verify
2289 *  subroutine support, given user-specified test iteration properties.
2290 *
2291 *  @param variable_type GLSL type that should be used for argument and
2292 *                       return type definition in a subroutine. This setting
2293 *                       also affects type of the only output variable in the shader.
2294 *  @param array_size    1 if non-arrayed arguments/return types should be tested;
2295 *                       2 if arrayed arguments/return types should be tested.
2296 *
2297 *  @return Requested string.
2298 **/
2299std::string FunctionalTest1_2::getVertexShaderBody(const Utils::_variable_type& variable_type, unsigned int array_size)
2300{
2301	Utils::_variable_type base_variable_type		 = Utils::getBaseVariableType(variable_type);
2302	unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
2303	std::stringstream	 result_sstream;
2304	std::string			  variable_type_glsl = Utils::getVariableTypeGLSLString(variable_type);
2305	std::stringstream	 variable_type_glsl_array_sstream;
2306	std::stringstream	 variable_type_glsl_arrayed_sstream;
2307
2308	variable_type_glsl_arrayed_sstream << variable_type_glsl;
2309
2310	if (array_size > 1)
2311	{
2312		variable_type_glsl_array_sstream << "[" << array_size << "]";
2313		variable_type_glsl_arrayed_sstream << variable_type_glsl_array_sstream.str();
2314	}
2315
2316	/* Form pre-amble */
2317	result_sstream << "#version 400\n"
2318					  "\n"
2319					  "#extension GL_ARB_shader_subroutine : require\n";
2320
2321	if (variable_type == Utils::VARIABLE_TYPE_DOUBLE)
2322	{
2323		result_sstream << "#extension GL_ARB_gpu_shader_fp64 : require\n";
2324	}
2325
2326	/* Form subroutine type declaration */
2327	result_sstream << "\n"
2328					  "subroutine "
2329				   << variable_type_glsl_arrayed_sstream.str() << " colorGetter(in " << variable_type_glsl
2330				   << " in_value" << variable_type_glsl_array_sstream.str() << ");\n"
2331																			   "\n";
2332
2333	/* Declare getter functions */
2334	for (int n_getter = 0; n_getter < 2; ++n_getter)
2335	{
2336		result_sstream << "subroutine(colorGetter) " << variable_type_glsl_arrayed_sstream.str() << " getter"
2337					   << n_getter << "(in " << variable_type_glsl << " in_value"
2338					   << variable_type_glsl_array_sstream.str() << ")\n"
2339																	"{\n";
2340
2341		if (array_size > 1)
2342		{
2343			result_sstream << variable_type_glsl << " temp" << variable_type_glsl_array_sstream.str() << ";\n";
2344		}
2345
2346		if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2347		{
2348			if (array_size > 1)
2349			{
2350				for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2351				{
2352					result_sstream << "    temp[" << array_index << "]"
2353																	" = "
2354								   << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "")
2355								   << "(in_value[" << array_index << "]);\n";
2356				}
2357
2358				result_sstream << "    return temp;\n";
2359			}
2360			else
2361			{
2362				result_sstream << "    return "
2363							   << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "")
2364							   << "(in_value);\n";
2365			}
2366		} /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */
2367		else
2368		{
2369			if (array_size > 1)
2370			{
2371				for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2372				{
2373					result_sstream << "    temp[" << array_index << "]"
2374																	" = in_value["
2375								   << array_index << "] + " << (n_getter + 1) << ";\n";
2376				}
2377
2378				result_sstream << "    return temp;\n";
2379			}
2380			else
2381			{
2382				result_sstream << "    return (in_value + " << (n_getter + 1) << ");\n";
2383			}
2384		}
2385
2386		result_sstream << "}\n";
2387	} /* for (both getter functions) */
2388
2389	/* Declare subroutine uniform */
2390	result_sstream << "subroutine uniform colorGetter colorGetterUniform;\n"
2391					  "\n";
2392
2393	/* Declare output variable */
2394	result_sstream << "out ";
2395
2396	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2397	{
2398		Utils::_variable_type result_as_int_variable_type =
2399			Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components);
2400		std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type);
2401
2402		result_sstream << variable_type_glsl_as_int;
2403	}
2404	else
2405	{
2406		result_sstream << variable_type_glsl;
2407	}
2408
2409	result_sstream << " result;\n"
2410					  "\n";
2411
2412	/* Declare main(): prepare input argument for the subroutine function */
2413	result_sstream << "void main()\n"
2414					  "{\n"
2415					  "    "
2416				   << variable_type_glsl << " temp";
2417
2418	if (array_size > 1)
2419	{
2420		result_sstream << "[" << array_size << "]";
2421	};
2422
2423	result_sstream << ";\n";
2424
2425	for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2426	{
2427		result_sstream << "    temp";
2428
2429		if (array_size > 1)
2430		{
2431			result_sstream << "[" << array_index << "]";
2432		}
2433
2434		result_sstream << " = " << variable_type_glsl << "(";
2435
2436		if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2437		{
2438			result_sstream << "true";
2439		}
2440		else
2441		{
2442			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2443			{
2444				result_sstream << "3";
2445
2446				if (n_component != (n_variable_type_components - 1))
2447				{
2448					result_sstream << ", ";
2449				}
2450			} /* for (all components) */
2451		}
2452
2453		result_sstream << ");\n";
2454	} /* for (all array indices) */
2455
2456	/* Declare main(): call the subroutine. Verify the input and write the result
2457	 *                 to the output variable.
2458	 **/
2459	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2460	{
2461		Utils::_variable_type result_as_int_variable_type =
2462			Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components);
2463		std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type);
2464
2465		result_sstream << variable_type_glsl_arrayed_sstream.str() << " subroutine_result = colorGetterUniform(temp);\n"
2466																	  "result = ";
2467
2468		for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2469		{
2470			if (variable_type_glsl == "bool")
2471				result_sstream << "bool(subroutine_result";
2472			else
2473				result_sstream << "all(subroutine_result";
2474
2475			if (array_size > 1)
2476			{
2477				result_sstream << "[" << array_index << "]";
2478			}
2479
2480			result_sstream << ")";
2481
2482			if (array_index != (array_size - 1))
2483			{
2484				result_sstream << "&& ";
2485			}
2486		}
2487
2488		result_sstream << " == true ? " << variable_type_glsl_as_int << "(1) : " << variable_type_glsl_as_int << "(0);";
2489	}
2490	else
2491	{
2492		if (array_size > 1)
2493		{
2494			DE_ASSERT(array_size == 2);
2495
2496			result_sstream << variable_type_glsl << " subroutine_result" << variable_type_glsl_array_sstream.str()
2497						   << " = colorGetterUniform(temp);\n"
2498							  "\n"
2499							  "if (subroutine_result[0] == subroutine_result[1]) result = subroutine_result[0];\n"
2500							  "else\n"
2501							  "result = "
2502						   << variable_type_glsl << "(-1);\n";
2503		}
2504		else
2505		{
2506			result_sstream << "result = colorGetterUniform(temp);\n";
2507		}
2508	}
2509
2510	/* All done */
2511	result_sstream << "}\n";
2512
2513	return result_sstream.str();
2514}
2515
2516/** Initializes all GL objects required to run the test. */
2517void FunctionalTest1_2::initTest()
2518{
2519	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2520
2521	/* Generate buffer object to hold result XFB data */
2522	gl.genBuffers(1, &m_xfb_bo_id);
2523	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2524
2525	/* Set up XFB BO bindings */
2526	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
2527	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2528
2529	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
2530	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
2531
2532	/* Generate VAO to use for the draw calls */
2533	gl.genVertexArrays(1, &m_vao_id);
2534	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2535
2536	gl.bindVertexArray(m_vao_id);
2537	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2538}
2539
2540/** Executes test iteration.
2541 *
2542 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2543 */
2544tcu::TestNode::IterateResult FunctionalTest1_2::iterate()
2545{
2546	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
2547	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
2548	{
2549		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
2550	}
2551
2552	/* Initialize a test program object */
2553	initTest();
2554
2555	/* Construct test case descriptors: first, iIerate over all
2556	 * variable types we want to cover */
2557	const Utils::_variable_type variable_types[] = {
2558		Utils::VARIABLE_TYPE_BOOL,   Utils::VARIABLE_TYPE_BVEC2,  Utils::VARIABLE_TYPE_BVEC3,
2559		Utils::VARIABLE_TYPE_BVEC4,  Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT,
2560		Utils::VARIABLE_TYPE_INT,	Utils::VARIABLE_TYPE_IVEC2,  Utils::VARIABLE_TYPE_IVEC3,
2561		Utils::VARIABLE_TYPE_IVEC4,  Utils::VARIABLE_TYPE_MAT2,   Utils::VARIABLE_TYPE_MAT2X3,
2562		Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_MAT3,   Utils::VARIABLE_TYPE_MAT3X2,
2563		Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_MAT4,   Utils::VARIABLE_TYPE_MAT4X2,
2564		Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_UINT,   Utils::VARIABLE_TYPE_UVEC2,
2565		Utils::VARIABLE_TYPE_UVEC3,  Utils::VARIABLE_TYPE_UVEC4,  Utils::VARIABLE_TYPE_VEC2,
2566		Utils::VARIABLE_TYPE_VEC3,   Utils::VARIABLE_TYPE_VEC4
2567	};
2568	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
2569
2570	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
2571	{
2572		Utils::_variable_type current_variable_type = variable_types[n_variable_type];
2573
2574		/* We need to test both arrayed and non-arrayed arguments */
2575		for (unsigned int array_size = 1; array_size < 3; ++array_size)
2576		{
2577			/* Exclude double variables if the relevant extension is unavailable */
2578			if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64") &&
2579				current_variable_type == Utils::VARIABLE_TYPE_DOUBLE)
2580			{
2581				continue;
2582			}
2583
2584			/* Form the descriptor */
2585			_test_case test_case;
2586
2587			test_case.array_size	= array_size;
2588			test_case.variable_type = current_variable_type;
2589
2590			/* Store the test case descriptor */
2591			m_test_cases.push_back(test_case);
2592		} /* for (both arrayed and non-arrayed arguments) */
2593	}	 /* for (all variable types) */
2594
2595	/* Iterate over all test cases and execute the test */
2596	for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
2597		 ++test_case_iterator)
2598	{
2599		const _test_case& test_case = *test_case_iterator;
2600
2601		m_has_test_passed &= executeTestIteration(test_case);
2602
2603		/* Release GL objects that were created during the execution */
2604		deinitTestIteration();
2605	} /* for (all test cases) */
2606
2607	/* Done */
2608	if (m_has_test_passed)
2609	{
2610		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2611	}
2612	else
2613	{
2614		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2615	}
2616
2617	return STOP;
2618}
2619
2620/** Verifies data that has been XFBed out by the vertex shader.
2621 *
2622 *  @param xfb_data      Buffer holding the data.
2623 *  @param variable_type GLSL type used for the test iteration
2624 *                       that generated the data at @param xfb_data.
2625 *
2626 *  @return true if the data was found to be valid, false if it
2627 *               was detected to be incorrect.
2628 **/
2629bool FunctionalTest1_2::verifyXFBData(const void* xfb_data, const Utils::_variable_type& variable_type)
2630{
2631	const Utils::_variable_type base_variable_type		   = Utils::getBaseVariableType(variable_type);
2632	const float					epsilon					   = 1e-5f;
2633	const unsigned int			n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
2634	bool						result					   = true;
2635	const unsigned char*		traveller_ptr			   = (const unsigned char*)xfb_data;
2636
2637	/* Boolean arguments/return types are tested with a slightly different shader so we
2638	 * need to test them in a separate code-path.
2639	 */
2640	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2641	{
2642		/* 0 should be returned when getter0 is used, 1 otherwise */
2643		const unsigned int ref_values[] = { 0, 1 };
2644		const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]);
2645
2646		for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value)
2647		{
2648			const unsigned int ref_value = ref_values[n_ref_value];
2649
2650			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2651			{
2652				int* result_value_ptr = (int*)(traveller_ptr);
2653
2654				if (*result_value_ptr != (int)ref_value)
2655				{
2656					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2657																   "["
2658									   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2659									   << " argument/return types ("
2660										  "expected:["
2661									   << ref_value << "], found:[" << *result_value_ptr << "])"
2662									   << tcu::TestLog::EndMessage;
2663
2664					result = false;
2665					break;
2666				}
2667
2668				traveller_ptr += sizeof(int);
2669			} /* for (all components) */
2670		}	 /* for (all reference values) */
2671	}		  /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */
2672	else
2673	{
2674		/* 4 should be returned when getter0 is used, 5 otherwise */
2675		const unsigned int ref_values[] = { 4, 5 };
2676		const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]);
2677
2678		for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value)
2679		{
2680			const unsigned int ref_value = ref_values[n_ref_value];
2681
2682			DE_ASSERT(
2683				base_variable_type == Utils::VARIABLE_TYPE_DOUBLE || base_variable_type == Utils::VARIABLE_TYPE_FLOAT ||
2684				base_variable_type == Utils::VARIABLE_TYPE_INT || base_variable_type == Utils::VARIABLE_TYPE_UINT);
2685
2686			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2687			{
2688				const double* double_value_ptr = (double*)traveller_ptr;
2689				const float*  float_value_ptr  = (float*)traveller_ptr;
2690				const int*	int_value_ptr	= (int*)traveller_ptr;
2691
2692				switch (base_variable_type)
2693				{
2694				case Utils::VARIABLE_TYPE_DOUBLE:
2695				{
2696					if (de::abs(*double_value_ptr - (double)ref_value) > epsilon)
2697					{
2698						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2699																	   "["
2700										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2701										   << " argument/return types ("
2702											  "expected:["
2703										   << ref_value << "], found:[" << *double_value_ptr << "])"
2704										   << tcu::TestLog::EndMessage;
2705
2706						result = false;
2707					}
2708
2709					traveller_ptr += sizeof(double);
2710					break;
2711				}
2712
2713				case Utils::VARIABLE_TYPE_FLOAT:
2714				{
2715					if (de::abs(*float_value_ptr - (float)ref_value) > epsilon)
2716					{
2717						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2718																	   "["
2719										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2720										   << " argument/return types ("
2721											  "expected:["
2722										   << ref_value << "], found:[" << *float_value_ptr << "])"
2723										   << tcu::TestLog::EndMessage;
2724
2725						result = false;
2726					}
2727
2728					traveller_ptr += sizeof(float);
2729					break;
2730				}
2731
2732				case Utils::VARIABLE_TYPE_INT:
2733				case Utils::VARIABLE_TYPE_UINT:
2734				{
2735					if (*int_value_ptr != (int)ref_value)
2736					{
2737						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2738																	   "["
2739										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2740										   << " argument/return types ("
2741											  "expected:["
2742										   << ref_value << "], found:[" << *int_value_ptr << "])"
2743										   << tcu::TestLog::EndMessage;
2744
2745						result = false;
2746					}
2747
2748					traveller_ptr += sizeof(int);
2749					break;
2750				}
2751
2752				default:
2753					break;
2754				} /* switch (base_variable_type) */
2755			}	 /* for (all components) */
2756		}		  /* for (all reference values) */
2757	}
2758
2759	return result;
2760}
2761
2762/** Constructor
2763 *
2764 * @param context CTS context
2765 **/
2766FunctionalTest3_4::FunctionalTest3_4(deqp::Context& context)
2767	: TestCase(context, "four_subroutines_with_two_uniforms", "Verify Get* API and draw calls")
2768	, m_n_active_subroutine_uniforms(0)
2769	, m_n_active_subroutine_uniform_locations(0)
2770	, m_n_active_subroutines(0)
2771	, m_n_active_subroutine_uniform_name_length(0)
2772	, m_n_active_subroutine_name_length(0)
2773	, m_n_active_subroutine_uniform_size(0)
2774{
2775	/* Nothing to be done here */
2776}
2777
2778/** Execute test
2779 *
2780 * @return tcu::TestNode::STOP
2781 **/
2782tcu::TestNode::IterateResult FunctionalTest3_4::iterate()
2783{
2784	static const glw::GLchar* vertex_shader_code =
2785		"#version 400 core\n"
2786		"#extension GL_ARB_shader_subroutine : require\n"
2787		"\n"
2788		"precision highp float;\n"
2789		"\n"
2790		"// Sub routine type declaration\n"
2791		"subroutine vec4 routine_type(in vec4 iparam);\n"
2792		"\n"
2793		"// Sub routine definitions\n"
2794		"subroutine(routine_type) vec4 inverse_order(in vec4 iparam)\n"
2795		"{\n"
2796		"    return iparam.wzyx;\n"
2797		"}\n"
2798		"\n"
2799		"subroutine(routine_type) vec4 negate(in vec4 iparam)\n"
2800		"{\n"
2801		"    return -iparam;\n"
2802		"}\n"
2803		"\n"
2804		"subroutine(routine_type) vec4 inverse(in vec4 iparam)\n"
2805		"{\n"
2806		"    return 1 / iparam;\n"
2807		"}\n"
2808		"\n"
2809		"subroutine(routine_type) vec4 square(in vec4 iparam)\n"
2810		"{\n"
2811		"    return iparam * iparam;\n"
2812		"}\n"
2813		"\n"
2814		"// Sub routine uniforms\n"
2815		"subroutine uniform routine_type first_routine;\n"
2816		"subroutine uniform routine_type second_routine;\n"
2817		"\n"
2818		"// Input data\n"
2819		"uniform vec4 input_data;\n"
2820		"\n"
2821		"// Output\n"
2822		"out vec4 out_input_data;\n"
2823		"out vec4 out_result_from_first_routine;\n"
2824		"out vec4 out_result_from_second_routine;\n"
2825		"out vec4 out_result_from_combined_routines;\n"
2826		"out vec4 out_result_from_routines_combined_in_reveresed_order;\n"
2827		"\n"
2828		"void main()\n"
2829		"{\n"
2830		"    out_input_data                                       = input_data;\n"
2831		"    out_result_from_first_routine                        = first_routine(input_data);\n"
2832		"    out_result_from_second_routine                       = second_routine(input_data);\n"
2833		"    out_result_from_combined_routines                    = second_routine(first_routine(input_data));\n"
2834		"    out_result_from_routines_combined_in_reveresed_order = first_routine(second_routine(input_data));\n"
2835		"}\n"
2836		"\n";
2837
2838	static const GLchar* varying_names[] = {
2839		"out_input_data",
2840		"out_result_from_first_routine",
2841		"out_result_from_second_routine",
2842		"out_result_from_combined_routines",
2843		"out_result_from_routines_combined_in_reveresed_order",
2844	};
2845
2846	static const GLchar* subroutine_uniform_names[] = { "first_routine", "second_routine" };
2847
2848	static const GLchar* subroutine_names[] = { "inverse_order", "negate", "inverse", "square" };
2849
2850	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
2851	static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */;
2852
2853	static const GLuint inverse_order_routine_index = 0;
2854	static const GLuint negate_routine_index		= 1;
2855	static const GLuint inverse_routine_index		= 2;
2856	static const GLuint square_routine_index		= 3;
2857
2858	/* Test data */
2859	static const Utils::vec4<GLfloat> inverse_order_negate_data[5] = {
2860		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2861		Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),
2862		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),
2863	};
2864
2865	static const Utils::vec4<GLfloat> inverse_order_inverse_data[5] = {
2866		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2867		Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2868		Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2869	};
2870
2871	static const Utils::vec4<GLfloat> inverse_order_square_data[5] = {
2872		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2873		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),   Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2874		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2875	};
2876
2877	static const Utils::vec4<GLfloat> negate_inverse_data[5] = {
2878		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2879		Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2880		Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2881	};
2882
2883	static const Utils::vec4<GLfloat> negate_square_data[5] = {
2884		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),   Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2885		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),	 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2886		Utils::vec4<GLfloat>(-4.0f, -1.0f, -1.0f, -4.0f),
2887	};
2888
2889	static const Utils::vec4<GLfloat> inverse_square_data[5] = {
2890		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f),
2891		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),   Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f),
2892		Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f),
2893	};
2894
2895	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
2896	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
2897	{
2898		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
2899	}
2900
2901	m_n_active_subroutine_uniforms			  = 2;
2902	m_n_active_subroutine_uniform_locations   = 2;
2903	m_n_active_subroutines					  = 4;
2904	m_n_active_subroutine_uniform_name_length = 0;
2905	m_n_active_subroutine_name_length		  = 0;
2906	m_n_active_subroutine_uniform_size		  = 1;
2907
2908	/* GL objects */
2909	Utils::program	 program(m_context);
2910	Utils::buffer	  transform_feedback_buffer(m_context);
2911	Utils::vertexArray vao(m_context);
2912
2913	bool result = true;
2914
2915	/* Calculate max name lengths for subroutines and subroutine uniforms */
2916	for (GLint i = 0; i < m_n_active_subroutine_uniforms; ++i)
2917	{
2918		const GLsizei length = (GLsizei)strlen(subroutine_uniform_names[i]);
2919
2920		if (length > m_n_active_subroutine_uniform_name_length)
2921		{
2922			m_n_active_subroutine_uniform_name_length = length;
2923		}
2924	}
2925
2926	for (GLint i = 0; i < m_n_active_subroutines; ++i)
2927	{
2928		const GLsizei length = (GLsizei)strlen(subroutine_names[i]);
2929
2930		if (length > m_n_active_subroutine_name_length)
2931		{
2932			m_n_active_subroutine_name_length = length;
2933		}
2934	}
2935
2936	/* Init */
2937	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
2938				  n_varyings);
2939
2940	vao.generate();
2941	vao.bind();
2942
2943	transform_feedback_buffer.generate();
2944	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
2945									 GL_DYNAMIC_COPY);
2946	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
2947
2948	program.use();
2949
2950	/* Inspect Get* API */
2951	if ((false == inspectProgramStageiv(program.m_program_object_id)) ||
2952		(false == inspectActiveSubroutineUniformiv(program.m_program_object_id, subroutine_uniform_names)) ||
2953		(false == inspectActiveSubroutineUniformName(program.m_program_object_id, subroutine_uniform_names)) ||
2954		(false == inspectActiveSubroutineName(program.m_program_object_id, subroutine_names)) ||
2955		(false ==
2956		 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, false)))
2957	{
2958		result = false;
2959	}
2960
2961	/* Inspect GetProgram* API */
2962	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
2963	{
2964		if ((false == inspectProgramInterfaceiv(program.m_program_object_id)) ||
2965			(false ==
2966			 inspectProgramResourceiv(program.m_program_object_id, subroutine_names, subroutine_uniform_names)) ||
2967			(false ==
2968			 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, true)))
2969		{
2970			result = false;
2971		}
2972	}
2973
2974	/* Test shader execution */
2975	if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2976						   subroutine_names[negate_routine_index], subroutine_uniform_names, inverse_order_negate_data,
2977						   false)) ||
2978		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2979						   subroutine_names[inverse_routine_index], subroutine_uniform_names,
2980						   inverse_order_inverse_data, false)) ||
2981		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2982						   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_order_square_data,
2983						   false)) ||
2984		(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
2985						   subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data,
2986						   false)) ||
2987		(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
2988						   subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data,
2989						   false)) ||
2990		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index],
2991						   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data,
2992						   false)))
2993	{
2994		result = false;
2995	}
2996
2997	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
2998	{
2999		if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3000							   subroutine_names[negate_routine_index], subroutine_uniform_names,
3001							   inverse_order_negate_data, true)) ||
3002			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3003							   subroutine_names[inverse_routine_index], subroutine_uniform_names,
3004							   inverse_order_inverse_data, true)) ||
3005			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3006							   subroutine_names[square_routine_index], subroutine_uniform_names,
3007							   inverse_order_square_data, true)) ||
3008			(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
3009							   subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data,
3010							   true)) ||
3011			(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
3012							   subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data,
3013							   true)) ||
3014			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index],
3015							   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data,
3016							   true)))
3017		{
3018			result = false;
3019		}
3020	}
3021
3022	/* Done */
3023	if (true == result)
3024	{
3025		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3026	}
3027	else
3028	{
3029		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3030	}
3031
3032	return tcu::TestNode::STOP;
3033}
3034
3035/** Verify result of getProgramStageiv
3036 *
3037 * @param program_id Program object id
3038 * @param pname      <pname> parameter for getProgramStageiv
3039 * @param expected   Expected value
3040 *
3041 * @return true if result is equal to expected value, flase otherwise
3042 **/
3043bool FunctionalTest3_4::checkProgramStageiv(glw::GLuint program_id, glw::GLenum pname, glw::GLint expected) const
3044{
3045	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3046	GLint				  value = 0;
3047
3048	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, pname, &value);
3049	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3050
3051	if (expected != value)
3052	{
3053		m_context.getTestContext().getLog() << tcu::TestLog::Message
3054											<< "Error. Invalid result. Function: getProgramStageiv. "
3055											<< "pname: " << Utils::pnameToStr(pname) << ". "
3056											<< "Result: " << value << ". "
3057											<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3058
3059		return false;
3060	}
3061	else
3062	{
3063		return true;
3064	}
3065}
3066
3067/** Verify result of getProgramResourceiv
3068 *
3069 * @param program_id        Program object id
3070 * @param program_interface Program interface
3071 * @param pname             <pname> parameter for getProgramStageiv
3072 * @param resource_name     Resource name
3073 * @param expected          Expected value
3074 *
3075 * @return true if result is equal to expected value, false otherwise
3076 **/
3077bool FunctionalTest3_4::checkProgramResourceiv(GLuint program_id, GLenum program_interface, GLenum pname,
3078											   const glw::GLchar* resource_name, GLint expected) const
3079{
3080	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3081	GLuint				  index = gl.getProgramResourceIndex(program_id, program_interface, resource_name);
3082	GLint				  value = 0;
3083
3084	if (GL_INVALID_INDEX == index)
3085	{
3086		return false;
3087	}
3088
3089	gl.getProgramResourceiv(program_id, program_interface, index, 1, &pname, 1, 0, &value);
3090	GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceiv");
3091
3092	if (expected != value)
3093	{
3094		m_context.getTestContext().getLog()
3095			<< tcu::TestLog::Message << "Error. Invalid result. Function: getProgramResourceiv. "
3096			<< "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". "
3097			<< "Resource name: " << resource_name << ". "
3098			<< "Property: " << Utils::pnameToStr(pname) << ". "
3099			<< "Result: " << value << ". "
3100			<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3101
3102		return false;
3103	}
3104	else
3105	{
3106		return true;
3107	}
3108}
3109
3110/** Verify result of getProgramInterfaceiv
3111 *
3112 * @param program_id        Program object id
3113 * @param program_interface Program interface
3114 * @param pname             <pname> parameter for getProgramStageiv
3115 * @param expected          Expected value
3116 *
3117 * @return true if result is equal to expected value, flase otherwise
3118 **/
3119bool FunctionalTest3_4::checkProgramInterfaceiv(GLuint program_id, GLenum program_interface, GLenum pname,
3120												GLint expected) const
3121{
3122	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3123	GLint				  value = 0;
3124
3125	gl.getProgramInterfaceiv(program_id, program_interface, pname, &value);
3126	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInterfaceiv");
3127
3128	if (expected != value)
3129	{
3130		m_context.getTestContext().getLog()
3131			<< tcu::TestLog::Message << "Error. Invalid result. Function: getProgramInterfaceiv. "
3132			<< "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". "
3133			<< "pname: " << Utils::pnameToStr(pname) << ". "
3134			<< "Result: " << value << ". "
3135			<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3136
3137		return false;
3138	}
3139	else
3140	{
3141		return true;
3142	}
3143}
3144
3145/** Verify result of getActiveSubroutineUniformiv
3146 *
3147 * @param program_id Program object id
3148 * @param index      <index> parameter for getActiveSubroutineUniformiv
3149 * @param pname      <pname> parameter for getActiveSubroutineUniformiv
3150 * @param expected   Expected value
3151 *
3152 * @return true if result is equal to expected value, flase otherwise
3153 **/
3154bool FunctionalTest3_4::checkActiveSubroutineUniformiv(GLuint program_id, GLuint index, GLenum pname,
3155													   GLint expected) const
3156{
3157	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3158	GLint				  value = 0;
3159
3160	gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, index, pname, &value);
3161	GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv");
3162
3163	if (expected != value)
3164	{
3165		m_context.getTestContext().getLog() << tcu::TestLog::Message
3166											<< "Error. Invalid result. Function: getActiveSubroutineUniformiv. "
3167											<< "idnex: " << index << ". "
3168											<< "pname: " << Utils::pnameToStr(pname) << ". "
3169											<< "Result: " << value << ". "
3170											<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3171
3172		return false;
3173	}
3174	else
3175	{
3176		return true;
3177	}
3178}
3179
3180/** Returns index of program resource
3181 *
3182 * @param program_id        Program object id
3183 * @param program_interface Program interface
3184 * @param resource_name     Name of resource
3185 *
3186 * @return Index of specified resource
3187 **/
3188GLuint FunctionalTest3_4::getProgramResourceIndex(GLuint program_id, GLenum program_interface,
3189												  const glw::GLchar* resource_name) const
3190{
3191	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3192	GLuint				  index = gl.getProgramResourceIndex(program_id, program_interface, resource_name);
3193
3194	GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceIndex");
3195
3196	if (GL_INVALID_INDEX == index)
3197	{
3198		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Program resource is not available. "
3199											<< "Program interface: " << Utils::programInterfaceToStr(program_interface)
3200											<< ". "
3201											<< "Resource name: " << resource_name << "." << tcu::TestLog::EndMessage;
3202	}
3203
3204	return index;
3205}
3206
3207/** Get subroutine index
3208 *
3209 * @param program_id        Program object id
3210 * @param subroutine_name   Subroutine name
3211 * @param use_program_query If true getProgramResourceIndex is used, otherwise getSubroutineIndex
3212 *
3213 * @return Index of subroutine
3214 **/
3215GLuint FunctionalTest3_4::getSubroutineIndex(GLuint program_id, const glw::GLchar* subroutine_name,
3216											 bool use_program_query) const
3217{
3218	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3219	GLuint				  index = -1;
3220
3221	if (false == use_program_query)
3222	{
3223		index = gl.getSubroutineIndex(program_id, GL_VERTEX_SHADER, subroutine_name);
3224		GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
3225	}
3226	else
3227	{
3228		index = gl.getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE, subroutine_name);
3229		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex");
3230	}
3231
3232	if (GL_INVALID_INDEX == index)
3233	{
3234		TCU_FAIL("Subroutine is not available");
3235	}
3236
3237	return index;
3238}
3239
3240/** Get subroutine uniform location
3241 *
3242 * @param program_id        Program object id
3243 * @param uniform_name      Subroutine uniform name
3244 * @param use_program_query If true getProgramResourceLocation is used, otherwise getSubroutineUniformLocation
3245 *
3246 * @return Location of subroutine uniform
3247 **/
3248GLint FunctionalTest3_4::getSubroutineUniformLocation(GLuint program_id, const glw::GLchar* uniform_name,
3249													  bool use_program_query) const
3250{
3251	const glw::Functions& gl	   = m_context.getRenderContext().getFunctions();
3252	GLint				  location = -1;
3253
3254	if (false == use_program_query)
3255	{
3256		location = gl.getSubroutineUniformLocation(program_id, GL_VERTEX_SHADER, uniform_name);
3257		GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
3258	}
3259	else
3260	{
3261		location = gl.getProgramResourceLocation(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name);
3262		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceLocation");
3263	}
3264
3265	if (-1 == location)
3266	{
3267		TCU_FAIL("Subroutine uniform is not available");
3268	}
3269
3270	return location;
3271}
3272
3273/** Test if getProgramStageiv results are as expected
3274 *
3275 * @param program_id Program object id
3276 *
3277 * @result false in case of invalid result for any pname, true otherwise
3278 **/
3279bool FunctionalTest3_4::inspectProgramStageiv(glw::GLuint program_id) const
3280{
3281	bool result = true;
3282
3283	const inspectionDetails details[] = {
3284		{ GL_ACTIVE_SUBROUTINE_UNIFORMS, m_n_active_subroutine_uniforms },
3285		{ GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, m_n_active_subroutine_uniform_locations },
3286		{ GL_ACTIVE_SUBROUTINES, m_n_active_subroutines },
3287		{ GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH, m_n_active_subroutine_uniform_name_length + 1 },
3288		{ GL_ACTIVE_SUBROUTINE_MAX_LENGTH, m_n_active_subroutine_name_length + 1 }
3289	};
3290	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3291
3292	for (GLuint i = 0; i < n_details; ++i)
3293	{
3294		if (false == checkProgramStageiv(program_id, details[i].pname, details[i].expected_value))
3295		{
3296			result = false;
3297		}
3298	}
3299
3300	return result;
3301}
3302
3303/** Test if checkProgramInterfaceiv results are as expected
3304 *
3305 * @param program_id Program object id
3306 *
3307 * @result false in case of invalid result for any pname, true otherwise
3308 **/
3309bool FunctionalTest3_4::inspectProgramInterfaceiv(glw::GLuint program_id) const
3310{
3311	bool result = true;
3312
3313	const inspectionDetailsForProgramInterface details[] = {
3314		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, m_n_active_subroutine_uniforms },
3315		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, m_n_active_subroutine_uniform_name_length + 1 },
3316		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3317		{ GL_VERTEX_SUBROUTINE, GL_ACTIVE_RESOURCES, m_n_active_subroutines },
3318		{ GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, m_n_active_subroutine_name_length + 1 }
3319	};
3320	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3321
3322	for (GLuint i = 0; i < n_details; ++i)
3323	{
3324		if (false == checkProgramInterfaceiv(program_id, details[i].program_interface, details[i].pname,
3325											 details[i].expected_value))
3326		{
3327			result = false;
3328		}
3329	}
3330
3331	return result;
3332}
3333
3334/** Test if checkProgramResourceiv results are as expected
3335 *
3336 * @param program_id       Program object id
3337 * @param subroutine_names Array of subroutine names
3338 * @param uniform_names    Array of uniform names
3339 *
3340 * @result false in case of invalid result for any pname, true otherwise
3341 **/
3342bool FunctionalTest3_4::inspectProgramResourceiv(GLuint program_id, const GLchar** subroutine_names,
3343												 const GLchar** uniform_names) const
3344{
3345	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
3346	bool				  result = true;
3347
3348	for (GLint subroutine = 0; subroutine < m_n_active_subroutines; ++subroutine)
3349	{
3350		const GLchar* subroutine_name = subroutine_names[subroutine];
3351		const GLint   length		  = (GLint)strlen(subroutine_name) + 1;
3352
3353		if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE, GL_NAME_LENGTH, subroutine_name, length))
3354		{
3355			result = false;
3356		}
3357	}
3358
3359	inspectionDetails details[] = {
3360		{ GL_NAME_LENGTH, 0 },
3361		{ GL_ARRAY_SIZE, 1 },
3362		{ GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3363		{ GL_LOCATION, 0 },
3364	};
3365	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3366
3367	for (GLint uniform = 0; uniform < m_n_active_subroutine_uniforms; ++uniform)
3368	{
3369		const GLchar* uniform_name = uniform_names[uniform];
3370		const GLint   length	   = (GLint)strlen(uniform_name) + 1;
3371		const GLint   location	 = getSubroutineUniformLocation(program_id, uniform_name, true);
3372
3373		details[0].expected_value = length;
3374		details[3].expected_value = location;
3375
3376		for (GLuint i = 0; i < n_details; ++i)
3377		{
3378			if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, details[i].pname,
3379												uniform_name, details[i].expected_value))
3380			{
3381				result = false;
3382			}
3383		}
3384
3385		/* Check compatible subroutines */
3386		GLuint index = getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name);
3387
3388		if (GL_INVALID_INDEX != index)
3389		{
3390			std::vector<GLint> compatible_subroutines;
3391			GLint			   index_sum = 0;
3392			GLenum			   prop		 = GL_COMPATIBLE_SUBROUTINES;
3393
3394			compatible_subroutines.resize(m_n_active_subroutines);
3395
3396			gl.getProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, index, 1, &prop, m_n_active_subroutines,
3397									0, &compatible_subroutines[0]);
3398
3399			GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv");
3400
3401			/* Expected indices are 0, 1, 2, ... N */
3402			for (GLint i = 0; i < m_n_active_subroutines; ++i)
3403			{
3404				index_sum += compatible_subroutines[i];
3405			}
3406
3407			/* Sum of E1, ..., EN = (E1 + EN) * N / 2 */
3408			if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum)
3409			{
3410				tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3411
3412				message << "Error. Invalid result. Function: getProgramResourceiv. "
3413						<< "Program interface: GL_VERTEX_SUBROUTINE_UNIFORM. "
3414						<< "Resource name: " << uniform_name << ". "
3415						<< "Property: GL_COMPATIBLE_SUBROUTINES. "
3416						<< "Results: ";
3417
3418				for (GLint i = 1; i < m_n_active_subroutines; ++i)
3419				{
3420					message << compatible_subroutines[i];
3421				}
3422
3423				message << tcu::TestLog::EndMessage;
3424
3425				result = false;
3426			}
3427		}
3428	}
3429
3430	return result;
3431}
3432
3433/** Test if getActiveSubroutineUniformiv results are as expected
3434 *
3435 * @param program_id    Program object id
3436 * @param uniform_names Array of subroutine uniform names available in program
3437 *
3438 * @result false in case of invalid result for any pname, true otherwise
3439 **/
3440bool FunctionalTest3_4::inspectActiveSubroutineUniformiv(GLuint program_id, const GLchar** uniform_names) const
3441{
3442	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3443	bool				  result					   = true;
3444	GLint				  n_active_subroutine_uniforms = 0;
3445
3446	inspectionDetails details[] = {
3447		{ GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3448		{ GL_UNIFORM_SIZE, m_n_active_subroutine_uniform_size },
3449		{ GL_UNIFORM_NAME_LENGTH, 0 },
3450	};
3451	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3452
3453	/* Get amount of active subroutine uniforms */
3454	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3455	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3456
3457	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3458	{
3459		GLint name_length = (GLint)strlen(uniform_names[uniform]);
3460
3461		details[2].expected_value = name_length + 1;
3462
3463		/* Checks from "details" */
3464		for (GLuint i = 0; i < n_details; ++i)
3465		{
3466			if (false ==
3467				checkActiveSubroutineUniformiv(program_id, uniform, details[i].pname, details[i].expected_value))
3468			{
3469				result = false;
3470			}
3471		}
3472
3473		/* Check compatible subroutines */
3474		std::vector<GLint> compatible_subroutines;
3475		compatible_subroutines.resize(m_n_active_subroutines);
3476		GLint index_sum = 0;
3477
3478		gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, uniform, GL_COMPATIBLE_SUBROUTINES,
3479										&compatible_subroutines[0]);
3480		GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv");
3481
3482		/* Expected indices are 0, 1, 2, ... N */
3483		for (GLint i = 0; i < m_n_active_subroutines; ++i)
3484		{
3485			index_sum += compatible_subroutines[i];
3486		}
3487
3488		/* Sum of E1, ..., EN = (E1 + EN) * N / 2 */
3489		if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum)
3490		{
3491			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3492
3493			message << "Error. Invalid result. Function: getActiveSubroutineUniformiv. idnex: " << uniform
3494					<< ". pname: " << Utils::pnameToStr(GL_COMPATIBLE_SUBROUTINES) << ". Results: ";
3495
3496			for (GLint i = 1; i < m_n_active_subroutines; ++i)
3497			{
3498				message << compatible_subroutines[i];
3499			}
3500
3501			message << tcu::TestLog::EndMessage;
3502
3503			result = false;
3504		}
3505	}
3506
3507	return result;
3508}
3509
3510/** Test if getActiveSubroutineUniformName results are as expected
3511 *
3512 * @param program_id    Program object id
3513 * @param uniform_names Array of subroutine uniform names available in program
3514 *
3515 * @result false in case of invalid result, true otherwise
3516 **/
3517bool FunctionalTest3_4::inspectActiveSubroutineUniformName(GLuint program_id, const GLchar** uniform_names) const
3518{
3519	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3520	bool				  result					   = true;
3521	GLint				  n_active_subroutine_uniforms = 0;
3522	std::vector<GLchar>   active_uniform_name;
3523
3524	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3525	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3526
3527	active_uniform_name.resize(m_n_active_subroutine_uniform_name_length + 1);
3528
3529	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3530	{
3531		bool is_name_ok = false;
3532
3533		gl.getActiveSubroutineUniformName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_uniform_name.size(),
3534										  0 /* length */, &active_uniform_name[0]);
3535		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveSubroutineUniformName");
3536
3537		for (GLint name = 0; name < n_active_subroutine_uniforms; ++name)
3538		{
3539			if (0 == strcmp(uniform_names[name], &active_uniform_name[0]))
3540			{
3541				is_name_ok = true;
3542				break;
3543			}
3544		}
3545
3546		if (false == is_name_ok)
3547		{
3548			m_context.getTestContext().getLog()
3549				<< tcu::TestLog::Message
3550				<< "Error. Invalid result. Function: getActiveSubroutineUniformName. idnex: " << uniform
3551				<< ". Result: " << &active_uniform_name[0] << tcu::TestLog::EndMessage;
3552
3553			result = false;
3554			break;
3555		}
3556	}
3557
3558	return result;
3559}
3560
3561/** Test if getActiveSubroutineUniformName results are as expected
3562 *
3563 * @param program_id       Program object id
3564 * @param subroutine_names Array of subroutine names available in program
3565 *
3566 * @result false in case of invalid result, true otherwise
3567 **/
3568bool FunctionalTest3_4::inspectActiveSubroutineName(GLuint program_id, const GLchar** subroutine_names) const
3569{
3570	const glw::Functions& gl				   = m_context.getRenderContext().getFunctions();
3571	bool				  result			   = true;
3572	GLint				  n_active_subroutines = 0;
3573	std::vector<GLchar>   active_subroutine_name;
3574
3575	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
3576	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3577
3578	active_subroutine_name.resize(m_n_active_subroutine_name_length + 1);
3579
3580	for (GLint uniform = 0; uniform < n_active_subroutines; ++uniform)
3581	{
3582		bool is_name_ok = false;
3583
3584		gl.getActiveSubroutineName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_subroutine_name.size(),
3585								   0 /* length */, &active_subroutine_name[0]);
3586		GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineName");
3587
3588		for (GLint name = 0; name < n_active_subroutines; ++name)
3589		{
3590			if (0 == strcmp(subroutine_names[name], &active_subroutine_name[0]))
3591			{
3592				is_name_ok = true;
3593				break;
3594			}
3595		}
3596
3597		if (false == is_name_ok)
3598		{
3599			m_context.getTestContext().getLog()
3600				<< tcu::TestLog::Message
3601				<< "Error. Invalid result. Function: getActiveSubroutineName. idnex: " << uniform
3602				<< ". Result: " << &active_subroutine_name[0] << tcu::TestLog::EndMessage;
3603
3604			result = false;
3605			break;
3606		}
3607	}
3608
3609	return result;
3610}
3611
3612/** Test if it is possible to "bind" all subroutines uniforms with all subroutines
3613 *
3614 * @param program_id       Program object id
3615 * @param subroutine_names Array of subroutine names available in program
3616 * @param uniform_names    Array of subroutine uniform names available in program
3617 *
3618 * @result false in case of invalid result, true otherwise
3619 **/
3620bool FunctionalTest3_4::inspectSubroutineBinding(GLuint program_id, const GLchar** subroutine_names,
3621												 const GLchar** uniform_names, bool use_program_query) const
3622{
3623	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3624	bool				  result					   = true;
3625	GLint				  n_active_subroutines		   = 0;
3626	GLint				  n_active_subroutine_uniforms = 0;
3627	std::vector<GLuint>   subroutine_uniforms;
3628	GLuint				  queried_subroutine_index = 0;
3629
3630	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
3631	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3632
3633	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3634	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3635
3636	subroutine_uniforms.resize(n_active_subroutine_uniforms);
3637
3638	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3639	{
3640		GLuint uniform_location = getSubroutineUniformLocation(program_id, uniform_names[uniform], use_program_query);
3641
3642		for (GLint routine = 0; routine < n_active_subroutines; ++routine)
3643		{
3644			GLuint routine_index = getSubroutineIndex(program_id, subroutine_names[routine], use_program_query);
3645
3646			subroutine_uniforms[uniform] = routine_index;
3647
3648			gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_active_subroutine_uniforms, &subroutine_uniforms[0]);
3649			GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3650
3651			gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, uniform_location, &queried_subroutine_index);
3652			GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
3653
3654			if (queried_subroutine_index != routine_index)
3655			{
3656				m_context.getTestContext().getLog()
3657					<< tcu::TestLog::Message << "Error. Invalid result. Function: gl.getUniformSubroutineuiv."
3658					<< " Subroutine uniform: " << uniform << ", name: " << uniform_names[uniform]
3659					<< ", location: " << uniform_location << ". Subroutine: " << routine
3660					<< ", name: " << subroutine_names[routine] << ", index: " << routine_index
3661					<< ". Result: " << queried_subroutine_index << tcu::TestLog::EndMessage;
3662
3663				result = false;
3664			}
3665		}
3666	}
3667
3668	return result;
3669}
3670
3671/** Execute draw call and verify results
3672 *
3673 * @param program_id                   Program object id
3674 * @param first_routine_name           Name of subroutine that shall be used aas first_routine
3675 * @param second_routine_name          Name of subroutine that shall be used aas second_routine
3676 * @param uniform_names                Name of uniforms
3677 * @param expected_results             Test data. [0] is used as input data. All are used as expected_results
3678 * @param use_program_query            If true GetProgram* API will be used
3679 *
3680 * @return false in case of invalid result, true otherwise
3681 **/
3682bool FunctionalTest3_4::testDraw(GLuint program_id, const GLchar* first_routine_name, const GLchar* second_routine_name,
3683								 const GLchar** uniform_names, const Utils::vec4<GLfloat> expected_results[5],
3684								 bool use_program_query) const
3685{
3686	static const GLuint   n_varyings			 = 5;
3687	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3688	bool				  result				 = true;
3689	GLuint				  subroutine_uniforms[2] = { 0 };
3690
3691	/* Get subroutine uniform locations */
3692	GLint first_routine_location = getSubroutineUniformLocation(program_id, uniform_names[0], use_program_query);
3693
3694	GLint second_routine_location = getSubroutineUniformLocation(program_id, uniform_names[1], use_program_query);
3695
3696	/* Get subroutine indices */
3697	GLuint first_routine_index = getSubroutineIndex(program_id, first_routine_name, use_program_query);
3698
3699	GLuint second_routine_index = getSubroutineIndex(program_id, second_routine_name, use_program_query);
3700
3701	/* Map uniforms with subroutines */
3702	subroutine_uniforms[first_routine_location]  = first_routine_index;
3703	subroutine_uniforms[second_routine_location] = second_routine_index;
3704
3705	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 2 /* number of uniforms */, &subroutine_uniforms[0]);
3706	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3707
3708	/* Get location of input_data */
3709	GLint input_data_location = gl.getUniformLocation(program_id, "input_data");
3710	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
3711
3712	if (-1 == input_data_location)
3713	{
3714		TCU_FAIL("Uniform is not available");
3715	}
3716
3717	/* Set up input_data */
3718	gl.uniform4f(input_data_location, expected_results[0].m_x, expected_results[0].m_y, expected_results[0].m_z,
3719				 expected_results[0].m_w);
3720	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
3721
3722	/* Execute draw call with transform feedback */
3723	gl.beginTransformFeedback(GL_POINTS);
3724	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
3725
3726	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
3727	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
3728
3729	gl.endTransformFeedback();
3730	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
3731
3732	/* Verify results */
3733	GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3734	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3735
3736	Utils::vec4<GLfloat> results[5];
3737
3738	results[0].m_x = feedback_data[0];
3739	results[0].m_y = feedback_data[1];
3740	results[0].m_z = feedback_data[2];
3741	results[0].m_w = feedback_data[3];
3742
3743	results[1].m_x = feedback_data[4];
3744	results[1].m_y = feedback_data[5];
3745	results[1].m_z = feedback_data[6];
3746	results[1].m_w = feedback_data[7];
3747
3748	results[2].m_x = feedback_data[8];
3749	results[2].m_y = feedback_data[9];
3750	results[2].m_z = feedback_data[10];
3751	results[2].m_w = feedback_data[11];
3752
3753	results[3].m_x = feedback_data[12];
3754	results[3].m_y = feedback_data[13];
3755	results[3].m_z = feedback_data[14];
3756	results[3].m_w = feedback_data[15];
3757
3758	results[4].m_x = feedback_data[16];
3759	results[4].m_y = feedback_data[17];
3760	results[4].m_z = feedback_data[18];
3761	results[4].m_w = feedback_data[19];
3762
3763	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3764	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3765
3766	for (GLuint i = 0; i < n_varyings; ++i)
3767	{
3768		result = result && (results[i] == expected_results[i]);
3769	}
3770
3771	if (false == result)
3772	{
3773		m_context.getTestContext().getLog() << tcu::TestLog::Message
3774											<< "Error. Invalid result. First routine: " << first_routine_name
3775											<< ". Second routine: " << second_routine_name << tcu::TestLog::EndMessage;
3776
3777		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3778
3779		message << "Results:";
3780
3781		for (GLuint i = 0; i < n_varyings; ++i)
3782		{
3783			results[i].log(message);
3784		}
3785
3786		message << tcu::TestLog::EndMessage;
3787
3788		message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3789
3790		message << "Expected:";
3791
3792		for (GLuint i = 0; i < n_varyings; ++i)
3793		{
3794			expected_results[i].log(message);
3795		}
3796
3797		message << tcu::TestLog::EndMessage;
3798	}
3799
3800	return result;
3801}
3802
3803/** Constructor
3804 *
3805 * @param context CTS context
3806 **/
3807FunctionalTest5::FunctionalTest5(deqp::Context& context)
3808	: TestCase(context, "eight_subroutines_four_uniforms", "Verify multiple subroutine sets")
3809{
3810}
3811
3812/** Execute test
3813 *
3814 * @return tcu::TestNode::STOP
3815 **/
3816tcu::TestNode::IterateResult FunctionalTest5::iterate()
3817{
3818	static const GLchar* vertex_shader_code =
3819		"#version 400 core\n"
3820		"#extension GL_ARB_shader_subroutine : require\n"
3821		"\n"
3822		"precision highp float;\n"
3823		"\n"
3824		"// Subroutine types\n"
3825		"subroutine vec4  routine_type_1(in vec4 left, in vec4 right);\n"
3826		"subroutine vec4  routine_type_2(in vec4 iparam);\n"
3827		"subroutine vec4  routine_type_3(in vec4 a,    in vec4 b,    in vec4 c);\n"
3828		"subroutine bvec4 routine_type_4(in vec4 left, in vec4 right);\n"
3829		"\n"
3830		"// Subroutine definitions\n"
3831		"// 1st type\n"
3832		"subroutine(routine_type_1) vec4 add(in vec4 left, in vec4 right)\n"
3833		"{\n"
3834		"    return left + right;\n"
3835		"}\n"
3836		"\n"
3837		"subroutine(routine_type_1) vec4 subtract(in vec4 left, in vec4 right)\n"
3838		"{\n"
3839		"    return left - right;\n"
3840		"}\n"
3841		"\n"
3842		"// 2nd type\n"
3843		"subroutine(routine_type_2) vec4 square(in vec4 iparam)\n"
3844		"{\n"
3845		"    return iparam * iparam;\n"
3846		"}\n"
3847		"\n"
3848		"subroutine(routine_type_2) vec4 square_root(in vec4 iparam)\n"
3849		"{\n"
3850		"    return sqrt(iparam);\n"
3851		"}\n"
3852		"\n"
3853		"// 3rd type\n"
3854		"subroutine(routine_type_3) vec4 do_fma(in vec4 a, in vec4 b, in vec4 c)\n"
3855		"{\n"
3856		"    return fma(a, b, c);\n"
3857		"}\n"
3858		"\n"
3859		"subroutine(routine_type_3) vec4 blend(in vec4 a, in vec4 b, in vec4 c)\n"
3860		"{\n"
3861		"    return c * a + (vec4(1) - c) * b;\n"
3862		"}\n"
3863		"\n"
3864		"// 4th type\n"
3865		"subroutine(routine_type_4) bvec4 are_equal(in vec4 left, in vec4 right)\n"
3866		"{\n"
3867		"    return equal(left, right);\n"
3868		"}\n"
3869		"\n"
3870		"subroutine(routine_type_4) bvec4 are_greater(in vec4 left, in vec4 right)\n"
3871		"{\n"
3872		"    return greaterThan(left, right);\n"
3873		"}\n"
3874		"\n"
3875		"// Sub routine uniforms\n"
3876		"subroutine uniform routine_type_1 first_routine;\n"
3877		"subroutine uniform routine_type_2 second_routine;\n"
3878		"subroutine uniform routine_type_3 third_routine;\n"
3879		"subroutine uniform routine_type_4 fourth_routine;\n"
3880		"\n"
3881		"// Input data\n"
3882		"uniform vec4 first_input;\n"
3883		"uniform vec4 second_input;\n"
3884		"uniform vec4 third_input;\n"
3885		"\n"
3886		"// Output\n"
3887		"out  vec4 out_result_from_first_routine;\n"
3888		"out  vec4 out_result_from_second_routine;\n"
3889		"out  vec4 out_result_from_third_routine;\n"
3890		"out uvec4 out_result_from_fourth_routine;\n"
3891		"\n"
3892		"void main()\n"
3893		"{\n"
3894		"    out_result_from_first_routine  =       first_routine (first_input, second_input);\n"
3895		"    out_result_from_second_routine =       second_routine(first_input);\n"
3896		"    out_result_from_third_routine  =       third_routine (first_input, second_input, third_input);\n"
3897		"    out_result_from_fourth_routine = uvec4(fourth_routine(first_input, second_input));\n"
3898		"}\n"
3899		"\n";
3900
3901	static const GLchar* subroutine_names[4][2] = {
3902		{ "add", "subtract" }, { "square", "square_root" }, { "do_fma", "blend" }, { "are_equal", "are_greater" }
3903	};
3904
3905	static const GLchar* subroutine_uniform_names[4][1] = {
3906		{ "first_routine" }, { "second_routine" }, { "third_routine" }, { "fourth_routine" }
3907	};
3908
3909	static const GLuint n_subroutine_types	 = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
3910	static const GLuint n_subroutines_per_type = sizeof(subroutine_names[0]) / sizeof(subroutine_names[0][0]);
3911	static const GLuint n_subroutine_uniforms_per_type =
3912		sizeof(subroutine_uniform_names[0]) / sizeof(subroutine_uniform_names[0][0]);
3913
3914	static const GLchar* uniform_names[] = { "first_input", "second_input", "third_input" };
3915	static const GLuint  n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
3916
3917	static const GLchar* varying_names[] = { "out_result_from_first_routine", "out_result_from_second_routine",
3918											 "out_result_from_third_routine", "out_result_from_fourth_routine" };
3919	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
3920	static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */;
3921
3922	/* Test data */
3923	static const Utils::vec4<GLfloat> input_data[3] = { Utils::vec4<GLfloat>(1.0f, 4.0f, 9.0f, 16.0f),
3924														Utils::vec4<GLfloat>(16.0f, 9.0f, 4.0f, 1.0f),
3925														Utils::vec4<GLfloat>(0.25f, 0.5f, 0.75f, 1.0f) };
3926
3927	static const Utils::vec4<GLfloat> expected_result_from_first_routine[2] = {
3928		Utils::vec4<GLfloat>(17.0f, 13.0f, 13.0f, 17.0f), Utils::vec4<GLfloat>(-15.0f, -5.0f, 5.0f, 15.0f)
3929	};
3930
3931	static const Utils::vec4<GLfloat> expected_result_from_second_routine[2] = {
3932		Utils::vec4<GLfloat>(1.0f, 16.0f, 81.0f, 256.0f), Utils::vec4<GLfloat>(1.0f, 2.0f, 3.0f, 4.0f)
3933	};
3934
3935	static const Utils::vec4<GLfloat> expected_result_from_third_routine[2] = {
3936		Utils::vec4<GLfloat>(16.25f, 36.5f, 36.75f, 17.0f), Utils::vec4<GLfloat>(12.25f, 6.5f, 7.75f, 16.0f)
3937	};
3938
3939	static const Utils::vec4<GLuint> expected_result_from_fourth_routine[2] = { Utils::vec4<GLuint>(0, 0, 0, 0),
3940																				Utils::vec4<GLuint>(0, 0, 1, 1) };
3941
3942	/* All combinations of subroutines */
3943	static const GLuint subroutine_combinations[][4] = {
3944		{ 0, 0, 0, 0 }, { 0, 0, 0, 1 }, { 0, 0, 1, 0 }, { 0, 0, 1, 1 }, { 0, 1, 0, 0 }, { 0, 1, 0, 1 },
3945		{ 0, 1, 1, 0 }, { 0, 1, 1, 1 }, { 1, 0, 0, 0 }, { 1, 0, 0, 1 }, { 1, 0, 1, 0 }, { 1, 0, 1, 1 },
3946		{ 1, 1, 0, 0 }, { 1, 1, 0, 1 }, { 1, 1, 1, 0 }, { 1, 1, 1, 1 }
3947	};
3948	static const GLuint n_subroutine_combinations =
3949		sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]);
3950
3951	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
3952	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
3953	{
3954		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
3955	}
3956
3957	/* Result */
3958	bool result = true;
3959
3960	/* GL objects */
3961	Utils::program	 program(m_context);
3962	Utils::buffer	  transform_feedback_buffer(m_context);
3963	Utils::vertexArray vao(m_context);
3964
3965	/* Init GL objects */
3966	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
3967				  n_varyings);
3968
3969	program.use();
3970
3971	vao.generate();
3972	vao.bind();
3973
3974	transform_feedback_buffer.generate();
3975	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
3976									 GL_DYNAMIC_COPY);
3977	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
3978
3979	/* Get subroutine uniform locations and subroutine indices */
3980	for (GLuint type = 0; type < n_subroutine_types; ++type)
3981	{
3982		for (GLuint uniform = 0; uniform < n_subroutine_uniforms_per_type; ++uniform)
3983		{
3984			m_subroutine_uniform_locations[type][uniform] =
3985				program.getSubroutineUniformLocation(subroutine_uniform_names[type][uniform], GL_VERTEX_SHADER);
3986		}
3987
3988		for (GLuint routine = 0; routine < n_subroutines_per_type; ++routine)
3989		{
3990			m_subroutine_indices[type][routine] =
3991				program.getSubroutineIndex(subroutine_names[type][routine], GL_VERTEX_SHADER);
3992		}
3993	}
3994
3995	/* Get uniform locations */
3996	for (GLuint i = 0; i < n_uniform_names; ++i)
3997	{
3998		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
3999	}
4000
4001	/* Draw with each routine combination */
4002	for (GLuint i = 0; i < n_subroutine_combinations; ++i)
4003	{
4004		Utils::vec4<GLfloat> first_routine_result;
4005		Utils::vec4<GLfloat> second_routine_result;
4006		Utils::vec4<GLfloat> third_routine_result;
4007		Utils::vec4<GLuint>  fourth_routine_result;
4008
4009		testDraw(subroutine_combinations[i], input_data, first_routine_result, second_routine_result,
4010				 third_routine_result, fourth_routine_result);
4011
4012		if (false == verify(first_routine_result, second_routine_result, third_routine_result, fourth_routine_result,
4013							expected_result_from_first_routine[subroutine_combinations[i][0]],
4014							expected_result_from_second_routine[subroutine_combinations[i][1]],
4015							expected_result_from_third_routine[subroutine_combinations[i][2]],
4016							expected_result_from_fourth_routine[subroutine_combinations[i][3]]))
4017		{
4018			logError(subroutine_names, subroutine_combinations[i], input_data, first_routine_result,
4019					 second_routine_result, third_routine_result, fourth_routine_result,
4020					 expected_result_from_first_routine[subroutine_combinations[i][0]],
4021					 expected_result_from_second_routine[subroutine_combinations[i][1]],
4022					 expected_result_from_third_routine[subroutine_combinations[i][2]],
4023					 expected_result_from_fourth_routine[subroutine_combinations[i][3]]);
4024
4025			result = false;
4026		}
4027	}
4028
4029	/* Done */
4030	if (true == result)
4031	{
4032		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4033	}
4034	else
4035	{
4036		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4037	}
4038
4039	return tcu::TestNode::STOP;
4040}
4041
4042/** Log error message
4043 *
4044 * @param subroutine_names               Array of subroutine names
4045 * @param subroutine_combination         Combination of subroutines
4046 * @param input_data                     Input data
4047 * @param first_routine_result           Result of first routine
4048 * @param second_routine_result          Result of second routine
4049 * @param third_routine_result           Result of third routine
4050 * @param fourth_routine_result          Result of fourth routine
4051 * @param first_routine_expected_result  Expected result of first routine
4052 * @param second_routine_expected_result Expected result of second routine
4053 * @param third_routine_expected_result  Expected result of third routine
4054 * @param fourth_routine_expected_result Expected result of fourth routine
4055 **/
4056void FunctionalTest5::logError(const glw::GLchar* subroutine_names[4][2], const glw::GLuint subroutine_combination[4],
4057							   const Utils::vec4<glw::GLfloat>  input_data[3],
4058							   const Utils::vec4<glw::GLfloat>& first_routine_result,
4059							   const Utils::vec4<glw::GLfloat>& second_routine_result,
4060							   const Utils::vec4<glw::GLfloat>& third_routine_result,
4061							   const Utils::vec4<glw::GLuint>&  fourth_routine_result,
4062							   const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
4063							   const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
4064							   const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
4065							   const Utils::vec4<glw::GLuint>&  fourth_routine_expected_result) const
4066{
4067	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4068										<< tcu::TestLog::EndMessage;
4069
4070	tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4071
4072	message << "Function: " << subroutine_names[0][subroutine_combination[0]] << "( ";
4073	input_data[0].log(message);
4074	message << ", ";
4075	input_data[1].log(message);
4076	message << " ). Result: ";
4077	first_routine_result.log(message);
4078	message << ". Expected: ";
4079	first_routine_expected_result.log(message);
4080
4081	message << tcu::TestLog::EndMessage;
4082
4083	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4084
4085	message << "Function: " << subroutine_names[1][subroutine_combination[1]] << "( ";
4086	input_data[0].log(message);
4087	message << " ). Result: ";
4088	second_routine_result.log(message);
4089	message << ". Expected: ";
4090	second_routine_expected_result.log(message);
4091
4092	message << tcu::TestLog::EndMessage;
4093
4094	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4095
4096	message << "Function: " << subroutine_names[2][subroutine_combination[2]] << "( ";
4097	input_data[0].log(message);
4098	message << ", ";
4099	input_data[1].log(message);
4100	message << ", ";
4101	input_data[2].log(message);
4102	message << "). Result: ";
4103	third_routine_result.log(message);
4104	message << ". Expected: ";
4105	third_routine_expected_result.log(message);
4106
4107	message << tcu::TestLog::EndMessage;
4108
4109	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4110
4111	message << "Function: " << subroutine_names[3][subroutine_combination[3]] << "( ";
4112	input_data[0].log(message);
4113	message << ", ";
4114	input_data[1].log(message);
4115	message << ", ";
4116	message << " ). Result: ";
4117	fourth_routine_result.log(message);
4118	message << ". Expected: ";
4119	fourth_routine_expected_result.log(message);
4120
4121	message << tcu::TestLog::EndMessage;
4122}
4123
4124/** Execute draw call and capture results
4125 *
4126 * @param subroutine_combination    Combination of subroutines
4127 * @param input_data                Input data
4128 * @param out_first_routine_result  Result of first routine
4129 * @param out_second_routine_result Result of second routine
4130 * @param out_third_routine_result  Result of third routine
4131 * @param out_fourth_routine_result Result of fourth routine
4132 **/
4133void FunctionalTest5::testDraw(const glw::GLuint			   subroutine_combination[4],
4134							   const Utils::vec4<glw::GLfloat> input_data[3],
4135							   Utils::vec4<glw::GLfloat>&	  out_first_routine_result,
4136							   Utils::vec4<glw::GLfloat>&	  out_second_routine_result,
4137							   Utils::vec4<glw::GLfloat>&	  out_third_routine_result,
4138							   Utils::vec4<glw::GLuint>&	   out_fourth_routine_result) const
4139{
4140	static const GLuint   n_uniforms = sizeof(m_uniform_locations) / sizeof(m_uniform_locations[0]);
4141	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
4142	GLuint				  subroutine_indices[4];
4143	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
4144
4145	/* Prepare subroutine uniform data */
4146	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
4147	{
4148		const GLuint location = m_subroutine_uniform_locations[i][0];
4149
4150		subroutine_indices[location] = m_subroutine_indices[i][subroutine_combination[i]];
4151	}
4152
4153	/* Set up subroutine uniforms */
4154	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
4155	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
4156
4157	/* Set up input data uniforms */
4158	for (GLuint i = 0; i < n_uniforms; ++i)
4159	{
4160		gl.uniform4f(m_uniform_locations[i], input_data[i].m_x, input_data[i].m_y, input_data[i].m_z,
4161					 input_data[i].m_w);
4162		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4163	}
4164
4165	/* Execute draw call with transform feedback */
4166	gl.beginTransformFeedback(GL_POINTS);
4167	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4168
4169	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4170	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4171
4172	gl.endTransformFeedback();
4173	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4174
4175	/* Capture results */
4176	GLvoid* feedback_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4177	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4178
4179	GLfloat* float_ptr = (GLfloat*)feedback_data;
4180
4181	/* First result */
4182	out_first_routine_result.m_x = float_ptr[0];
4183	out_first_routine_result.m_y = float_ptr[1];
4184	out_first_routine_result.m_z = float_ptr[2];
4185	out_first_routine_result.m_w = float_ptr[3];
4186
4187	/* Second result */
4188	out_second_routine_result.m_x = float_ptr[4];
4189	out_second_routine_result.m_y = float_ptr[5];
4190	out_second_routine_result.m_z = float_ptr[6];
4191	out_second_routine_result.m_w = float_ptr[7];
4192
4193	/* Third result */
4194	out_third_routine_result.m_x = float_ptr[8];
4195	out_third_routine_result.m_y = float_ptr[9];
4196	out_third_routine_result.m_z = float_ptr[10];
4197	out_third_routine_result.m_w = float_ptr[11];
4198
4199	/* Fourth result */
4200	GLuint* uint_ptr			  = (GLuint*)(float_ptr + 12);
4201	out_fourth_routine_result.m_x = uint_ptr[0];
4202	out_fourth_routine_result.m_y = uint_ptr[1];
4203	out_fourth_routine_result.m_z = uint_ptr[2];
4204	out_fourth_routine_result.m_w = uint_ptr[3];
4205
4206	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4207	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4208}
4209
4210/** Verify if results match expected results
4211 *
4212 * @param first_routine_result           Result of first routine
4213 * @param second_routine_result          Result of second routine
4214 * @param third_routine_result           Result of third routine
4215 * @param fourth_routine_result          Result of fourth routine
4216 * @param first_routine_expected_result  Expected result of first routine
4217 * @param second_routine_expected_result Expected result of second routine
4218 * @param third_routine_expected_result  Expected result of third routine
4219 * @param fourth_routine_expected_result Expected result of fourth routine
4220 **/
4221bool FunctionalTest5::verify(const Utils::vec4<glw::GLfloat>& first_routine_result,
4222							 const Utils::vec4<glw::GLfloat>& second_routine_result,
4223							 const Utils::vec4<glw::GLfloat>& third_routine_result,
4224							 const Utils::vec4<glw::GLuint>&  fourth_routine_result,
4225							 const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
4226							 const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
4227							 const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
4228							 const Utils::vec4<glw::GLuint>&  fourth_routine_expected_result) const
4229{
4230	bool result = true;
4231
4232	result = result && (first_routine_result == first_routine_expected_result);
4233	result = result && (second_routine_result == second_routine_expected_result);
4234	result = result && (third_routine_result == third_routine_expected_result);
4235	result = result && (fourth_routine_result == fourth_routine_expected_result);
4236
4237	return result;
4238}
4239
4240/** Constructor
4241 *
4242 * @param context CTS context
4243 **/
4244FunctionalTest6::FunctionalTest6(deqp::Context& context)
4245	: TestCase(context, "static_subroutine_call", "Verify that subroutine can be called in a static manner")
4246{
4247}
4248
4249/** Execute test
4250 *
4251 * @return tcu::TestNode::STOP
4252 **/
4253tcu::TestNode::IterateResult FunctionalTest6::iterate()
4254{
4255	static const GLchar* vertex_shader_code = "#version 400 core\n"
4256											  "#extension GL_ARB_shader_subroutine : require\n"
4257											  "\n"
4258											  "precision highp float;\n"
4259											  "\n"
4260											  "// Subroutine type\n"
4261											  "subroutine vec4 routine_type(in vec4 iparam);\n"
4262											  "\n"
4263											  "// Subroutine definition\n"
4264											  "subroutine(routine_type) vec4 square(in vec4 iparam)\n"
4265											  "{\n"
4266											  "    return iparam * iparam;\n"
4267											  "}\n"
4268											  "\n"
4269											  "// Sub routine uniform\n"
4270											  "subroutine uniform routine_type routine;\n"
4271											  "\n"
4272											  "// Input data\n"
4273											  "uniform vec4 input_data;\n"
4274											  "\n"
4275											  "// Output\n"
4276											  "out  vec4 out_result;\n"
4277											  "\n"
4278											  "void main()\n"
4279											  "{\n"
4280											  "    out_result  = square(input_data);\n"
4281											  "}\n"
4282											  "\n";
4283
4284	static const GLchar* varying_name = "out_result";
4285
4286	/* Test data */
4287	static const Utils::vec4<GLfloat> input_data(1.0f, 4.0f, 9.0f, 16.0f);
4288
4289	static const Utils::vec4<GLfloat> expected_result(1.0f, 16.0f, 81.0f, 256.0f);
4290
4291	static const GLuint transform_feedback_buffer_size = 4 * sizeof(GLfloat);
4292
4293	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
4294	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
4295	{
4296		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
4297	}
4298
4299	/* GL objects */
4300	Utils::program	 program(m_context);
4301	Utils::buffer	  transform_feedback_buffer(m_context);
4302	Utils::vertexArray vao(m_context);
4303
4304	/* Init GL objects */
4305	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name,
4306				  1 /* n_varyings */);
4307
4308	program.use();
4309
4310	vao.generate();
4311	vao.bind();
4312
4313	transform_feedback_buffer.generate();
4314	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
4315									 GL_DYNAMIC_COPY);
4316	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
4317
4318	/* Test */
4319	{
4320		const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
4321		const GLint			  uniform_location = gl.getUniformLocation(program.m_program_object_id, "input_data");
4322
4323		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
4324
4325		if (-1 == uniform_location)
4326		{
4327			TCU_FAIL("Uniform is not available");
4328		}
4329
4330		/* Set up input data uniforms */
4331		gl.uniform4f(uniform_location, input_data.m_x, input_data.m_y, input_data.m_z, input_data.m_w);
4332		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4333
4334		/* Execute draw call with transform feedback */
4335		gl.beginTransformFeedback(GL_POINTS);
4336		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4337
4338		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4339		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4340
4341		gl.endTransformFeedback();
4342		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4343
4344		/* Capture results */
4345		GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4346		GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4347
4348		Utils::vec4<GLfloat> result(feedback_data[0], feedback_data[1], feedback_data[2], feedback_data[3]);
4349
4350		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4351		GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4352
4353		/* Verify */
4354		if (expected_result == result)
4355		{
4356			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4357		}
4358		else
4359		{
4360			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4361												<< tcu::TestLog::EndMessage;
4362
4363			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4364
4365			message << "Function: square( ";
4366			input_data.log(message);
4367			message << " ). Result: ";
4368			result.log(message);
4369			message << ". Expected: ";
4370			expected_result.log(message);
4371
4372			message << tcu::TestLog::EndMessage;
4373
4374			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4375		}
4376	}
4377
4378	/* Done */
4379	return tcu::TestNode::STOP;
4380}
4381
4382/** Constructor
4383 *
4384 * @param context CTS context
4385 **/
4386FunctionalTest7_8::FunctionalTest7_8(deqp::Context& context)
4387	: TestCase(context, "arrayed_subroutine_uniforms", "Verify that subroutine can be called in a static manner")
4388{
4389}
4390
4391/** Execute test
4392 *
4393 * @return tcu::TestNode::STOP
4394 **/
4395tcu::TestNode::IterateResult FunctionalTest7_8::iterate()
4396{
4397	static const GLchar* vertex_shader_code =
4398		"#version 400 core\n"
4399		"#extension GL_ARB_shader_subroutine : require\n"
4400		"\n"
4401		"precision highp float;\n"
4402		"\n"
4403		"// Subroutine type\n"
4404		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
4405		"\n"
4406		"// Subroutine definitions\n"
4407		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
4408		"{\n"
4409		"    return left + right;\n"
4410		"}\n"
4411		"\n"
4412		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
4413		"{\n"
4414		"    return left * right;\n"
4415		"}\n"
4416		"\n"
4417		"// Sub routine uniform\n"
4418		"subroutine uniform routine_type routine[4];\n"
4419		"\n"
4420		"// Input data\n"
4421		"uniform vec4  uni_left;\n"
4422		"uniform vec4  uni_right;\n"
4423		"uniform uvec4 uni_indices;\n"
4424		"\n"
4425		"// Output\n"
4426		"out vec4 out_combined;\n"
4427		"out vec4 out_combined_inverted;\n"
4428		"out vec4 out_constant;\n"
4429		"out vec4 out_constant_inverted;\n"
4430		"out vec4 out_dynamic;\n"
4431		"out vec4 out_dynamic_inverted;\n"
4432		"out vec4 out_loop;\n"
4433		"out uint out_array_length;\n"
4434		"\n"
4435		"void main()\n"
4436		"{\n"
4437		"    out_combined          = routine[3](routine[2](routine[1](routine[0](uni_left, uni_right), uni_right), "
4438		"uni_right), uni_right);\n"
4439		"    out_combined_inverted = routine[0](routine[1](routine[2](routine[3](uni_left, uni_right), uni_right), "
4440		"uni_right), uni_right);\n"
4441		"    \n"
4442		"    out_constant          = routine[3](routine[2](routine[1](routine[0](vec4(1, 2, 3, 4), vec4(-5, -6, -7, "
4443		"-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n"
4444		"    out_constant_inverted = routine[0](routine[1](routine[2](routine[3](vec4(1, 2, 3, 4), vec4(-5, -6, -7, "
4445		"-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n"
4446		"    \n"
4447		"    out_dynamic           = "
4448		"routine[uni_indices.w](routine[uni_indices.z](routine[uni_indices.y](routine[uni_indices.x](uni_left, "
4449		"uni_right), uni_right), uni_right), uni_right);\n"
4450		"    out_dynamic_inverted  = "
4451		"routine[uni_indices.x](routine[uni_indices.y](routine[uni_indices.z](routine[uni_indices.w](uni_left, "
4452		"uni_right), uni_right), uni_right), uni_right);\n"
4453		"    \n"
4454		"    out_loop              = uni_left;\n"
4455		"    for (uint i = 0u; i < routine.length(); ++i)\n"
4456		"    {\n"
4457		"        out_loop          = routine[i](out_loop, uni_right);\n"
4458		"    }\n"
4459		"    \n"
4460		"    out_array_length      = routine.length() + 6 - (uni_indices.x + uni_indices.y + uni_indices.z + "
4461		"uni_indices.w);\n"
4462		"}\n"
4463		"\n";
4464
4465	static const GLchar* subroutine_names[] = {
4466		"add", "multiply",
4467	};
4468	static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
4469
4470	static const GLchar* subroutine_uniform_names[] = { "routine[0]", "routine[1]", "routine[2]", "routine[3]" };
4471	static const GLuint  n_subroutine_uniform_names =
4472		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
4473
4474	static const GLchar* uniform_names[] = {
4475		"uni_left", "uni_right", "uni_indices",
4476	};
4477	static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
4478
4479	static const GLchar* varying_names[] = { "out_combined", "out_combined_inverted",
4480											 "out_constant", "out_constant_inverted",
4481											 "out_dynamic",  "out_dynamic_inverted",
4482											 "out_loop",	 "out_array_length" };
4483
4484	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
4485	static const GLuint transform_feedback_buffer_size = n_varyings * 4 * sizeof(GLfloat);
4486
4487	/* Test data */
4488	static const Utils::vec4<GLfloat> uni_left(-1.0f, 0.75f, -0.5f, 0.25f);
4489	static const Utils::vec4<GLfloat> uni_right(1.0f, -0.75f, 0.5f, -0.25f);
4490	static const Utils::vec4<GLuint>  uni_indices(1, 2, 0, 3);
4491
4492	static const GLuint subroutine_combinations[][4] = {
4493		{ 0, 0, 0, 0 }, /* + + + + */
4494		{ 0, 0, 0, 1 }, /* + + + * */
4495		{ 0, 0, 1, 0 }, /* + + * + */
4496		{ 0, 0, 1, 1 }, /* + + * * */
4497		{ 0, 1, 0, 0 }, /* + * + + */
4498		{ 0, 1, 0, 1 }, /* + * + * */
4499		{ 0, 1, 1, 0 }, /* + * * + */
4500		{ 0, 1, 1, 1 }, /* + * * * */
4501		{ 1, 0, 0, 0 }, /* * + + + */
4502		{ 1, 0, 0, 1 }, /* * + + * */
4503		{ 1, 0, 1, 0 }, /* * + * + */
4504		{ 1, 0, 1, 1 }, /* * + * * */
4505		{ 1, 1, 0, 0 }, /* * * + + */
4506		{ 1, 1, 0, 1 }, /* * * + * */
4507		{ 1, 1, 1, 0 }, /* * * * + */
4508		{ 1, 1, 1, 1 }  /* * * * * */
4509	};
4510	static const GLuint n_subroutine_combinations =
4511		sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]);
4512
4513	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
4514	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
4515	{
4516		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
4517	}
4518
4519	/* GL objects */
4520	Utils::program	 program(m_context);
4521	Utils::buffer	  transform_feedback_buffer(m_context);
4522	Utils::vertexArray vao(m_context);
4523
4524	bool result = true;
4525
4526	/* Init GL objects */
4527	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
4528				  n_varyings);
4529
4530	program.use();
4531
4532	vao.generate();
4533	vao.bind();
4534
4535	transform_feedback_buffer.generate();
4536
4537	/* Get subroutine indices */
4538	for (GLuint routine = 0; routine < n_subroutine_names; ++routine)
4539	{
4540		m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER);
4541	}
4542
4543	/* Get subroutine uniform locations */
4544	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
4545	{
4546		m_subroutine_uniform_locations[uniform] =
4547			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
4548	}
4549
4550	/* Get uniform locations */
4551	for (GLuint i = 0; i < n_uniform_names; ++i)
4552	{
4553		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
4554	}
4555
4556	/* Test */
4557	for (GLuint i = 0; i < n_subroutine_combinations; ++i)
4558	{
4559		/* Clean */
4560		transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
4561										 GL_DYNAMIC_COPY);
4562		transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
4563
4564		/* Verify */
4565		if (false == testDraw(subroutine_combinations[i], uni_left, uni_right, uni_indices))
4566		{
4567			result = false;
4568		}
4569	}
4570
4571	if (true == result)
4572	{
4573		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4574	}
4575	else
4576	{
4577		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4578	}
4579
4580	/* Done */
4581	return tcu::TestNode::STOP;
4582}
4583
4584/* Calculate result of function applied to operands
4585 *
4586 * @param function Function id, 0 is sum, 1 is multiplication
4587 * @param left     Left operand
4588 * @param right    Right operand
4589 * @param out      Function result
4590 **/
4591void FunctionalTest7_8::calculate(glw::GLuint function, const Utils::vec4<glw::GLfloat>& left,
4592								  const Utils::vec4<glw::GLfloat>& right, Utils::vec4<glw::GLfloat>& out) const
4593{
4594	if (0 == function)
4595	{
4596		out.m_x = left.m_x + right.m_x;
4597		out.m_y = left.m_y + right.m_y;
4598		out.m_z = left.m_z + right.m_z;
4599		out.m_w = left.m_w + right.m_w;
4600	}
4601	else
4602	{
4603		out.m_x = left.m_x * right.m_x;
4604		out.m_y = left.m_y * right.m_y;
4605		out.m_z = left.m_z * right.m_z;
4606		out.m_w = left.m_w * right.m_w;
4607	}
4608}
4609
4610/** Calculate expected values for all operations
4611 *
4612 * @param combination           Function combination, first applied function is at index [0]
4613 * @param left                  Left operand
4614 * @param right                 Right operand
4615 * @param indices               Indices used by dynamic calls
4616 * @param out_combined          Expected result of "combined" operation
4617 * @param out_combined_inverted Expected result of "combined_inverted" operation
4618 * @param out_constant          Expected result of "constant" operation
4619 * @param out_constant_inverted Expected result of "constant_inverted" operation
4620 * @param out_dynamic           Expected result of "dynamic" operation
4621 * @param out_dynamic_inverted  Expected result of "out_dynamic_inverted" operation
4622 * @param out_loop              Expected result of "loop" operation
4623 **/
4624void FunctionalTest7_8::calculate(
4625	const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, const Utils::vec4<glw::GLfloat>& right,
4626	const Utils::vec4<glw::GLuint>& indices, Utils::vec4<glw::GLfloat>& out_combined,
4627	Utils::vec4<glw::GLfloat>& out_combined_inverted, Utils::vec4<glw::GLfloat>& out_constant,
4628	Utils::vec4<glw::GLfloat>& out_constant_inverted, Utils::vec4<glw::GLfloat>& out_dynamic,
4629	Utils::vec4<glw::GLfloat>& out_dynamic_inverted, Utils::vec4<glw::GLfloat>& out_loop) const
4630{
4631	/* Indices used by "dynamic" operations, range <0..4> */
4632	const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y],
4633											combination[indices.m_z], combination[indices.m_w] };
4634
4635	/* Values used by "constant" operations, come from shader code */
4636	const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4),
4637														  Utils::vec4<glw::GLfloat>(-5, -6, -7, -8),
4638														  Utils::vec4<glw::GLfloat>(-1, -2, -3, -4),
4639														  Utils::vec4<glw::GLfloat>(5, 6, 7, 8),
4640														  Utils::vec4<glw::GLfloat>(1, 2, 3, 4) };
4641
4642	/* Start values */
4643	Utils::vec4<glw::GLfloat> combined			= left;
4644	Utils::vec4<glw::GLfloat> combined_inverted = left;
4645	Utils::vec4<glw::GLfloat> constant			= constant_values[0];
4646	Utils::vec4<glw::GLfloat> constant_inverted = constant_values[0];
4647	Utils::vec4<glw::GLfloat> dynamic			= left;
4648	Utils::vec4<glw::GLfloat> dynamic_inverted  = left;
4649
4650	/* Calculate expected results */
4651	for (GLuint i = 0; i < 4; ++i)
4652	{
4653		GLuint function					 = combination[i];
4654		GLuint function_inverted		 = combination[3 - i];
4655		GLuint dynamic_function			 = dynamic_combination[i];
4656		GLuint dynamic_function_inverted = dynamic_combination[3 - i];
4657
4658		calculate(function, combined, right, combined);
4659		calculate(function_inverted, combined_inverted, right, combined_inverted);
4660		calculate(function, constant, constant_values[i + 1], constant);
4661		calculate(function_inverted, constant_inverted, constant_values[i + 1], constant_inverted);
4662		calculate(dynamic_function, dynamic, right, dynamic);
4663		calculate(dynamic_function_inverted, dynamic_inverted, right, dynamic_inverted);
4664	}
4665
4666	/* Store results */
4667	out_combined		  = combined;
4668	out_combined_inverted = combined_inverted;
4669	out_constant		  = constant;
4670	out_constant_inverted = constant_inverted;
4671	out_dynamic			  = dynamic;
4672	out_dynamic_inverted  = dynamic_inverted;
4673	out_loop			  = combined;
4674}
4675
4676/** Log error
4677 *
4678 * @param combination   Operations combination
4679 * @param left          Left operand
4680 * @param right         Right operand
4681 * @param indices       Inidices used by "dynamic" calls
4682 * @param vec4_expected Expected results
4683 * @param vec4_result   Results
4684 * @param array_length  Length of array
4685 * @param result        Comparison results
4686 **/
4687void FunctionalTest7_8::logError(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
4688								 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices,
4689								 const Utils::vec4<glw::GLfloat> vec4_expected[7],
4690								 const Utils::vec4<glw::GLfloat> vec4_result[7], glw::GLuint array_length,
4691								 bool result[7]) const
4692{
4693	static const GLuint n_functions  = 4;
4694	static const GLuint n_operations = 7;
4695
4696	/* Indices used by "dynamic" operations, range <0..4> */
4697	const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y],
4698											combination[indices.m_z], combination[indices.m_w] };
4699
4700	/* Function symbols */
4701	GLchar functions[4];
4702	GLchar functions_inverted[4];
4703	GLchar functions_dynamic[4];
4704	GLchar functions_dynamic_inverted[4];
4705
4706	for (GLuint i = 0; i < n_functions; ++i)
4707	{
4708		GLchar function			= (0 == combination[i]) ? '+' : '*';
4709		GLchar dynamic_function = (0 == dynamic_combination[i]) ? '+' : '*';
4710
4711		functions[i]									= function;
4712		functions_inverted[n_functions - i - 1]			= function;
4713		functions_dynamic[i]							= dynamic_function;
4714		functions_dynamic_inverted[n_functions - i - 1] = dynamic_function;
4715	}
4716
4717	/* Values used by "constant" operations, come from shader code */
4718	const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4),
4719														  Utils::vec4<glw::GLfloat>(-5, -6, -7, -8),
4720														  Utils::vec4<glw::GLfloat>(-1, -2, -3, -4),
4721														  Utils::vec4<glw::GLfloat>(5, 6, 7, 8),
4722														  Utils::vec4<glw::GLfloat>(1, 2, 3, 4) };
4723
4724	/* Values used by non-"constant" operations */
4725	Utils::vec4<glw::GLfloat> dynamic_values[5];
4726	dynamic_values[0] = left;
4727	dynamic_values[1] = right;
4728	dynamic_values[2] = right;
4729	dynamic_values[3] = right;
4730	dynamic_values[4] = right;
4731
4732	/* For each operation */
4733	for (GLuint i = 0; i < n_operations; ++i)
4734	{
4735		/* If result is failure */
4736		if (false == result[i])
4737		{
4738			const GLchar*					 description = 0;
4739			const Utils::vec4<glw::GLfloat>* input		 = 0;
4740			const GLchar*					 operation   = 0;
4741
4742			switch (i)
4743			{
4744			case 0:
4745				description = "Call made with predefined array indices";
4746				input		= dynamic_values;
4747				operation   = functions;
4748				break;
4749			case 1:
4750				description = "Call made with predefined array indices in inverted order";
4751				input		= dynamic_values;
4752				operation   = functions_inverted;
4753				break;
4754			case 2:
4755				description = "Call made with predefined array indices, for constant values";
4756				input		= constant_values;
4757				operation   = functions;
4758				break;
4759			case 3:
4760				description = "Call made with predefined array indices in inverted order, for constant values";
4761				input		= constant_values;
4762				operation   = functions_inverted;
4763				break;
4764			case 4:
4765				description = "Call made with dynamic array indices";
4766				input		= dynamic_values;
4767				operation   = functions_dynamic;
4768				break;
4769			case 5:
4770				description = "Call made with dynamic array indices in inverted order";
4771				input		= dynamic_values;
4772				operation   = functions_dynamic_inverted;
4773				break;
4774			case 6:
4775				description = "Call made with loop";
4776				input		= dynamic_values;
4777				operation   = functions;
4778				break;
4779			}
4780
4781			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4782												<< tcu::TestLog::EndMessage;
4783
4784			m_context.getTestContext().getLog() << tcu::TestLog::Message << description << tcu::TestLog::EndMessage;
4785
4786			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4787
4788			message << "Operation: ((((";
4789			input[0].log(message);
4790			for (GLuint function = 0; function < n_functions; ++function)
4791			{
4792				message << " " << operation[function] << " ";
4793
4794				input[function + 1].log(message);
4795
4796				message << ")";
4797			}
4798
4799			message << tcu::TestLog::EndMessage;
4800
4801			message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4802
4803			message << "Result: ";
4804			vec4_result[i].log(message);
4805
4806			message << tcu::TestLog::EndMessage;
4807
4808			message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4809
4810			message << "Expected: ";
4811			vec4_expected[i].log(message);
4812
4813			message << tcu::TestLog::EndMessage;
4814		}
4815
4816		/* Check array length, it should be 4 */
4817		if (4 != array_length)
4818		{
4819			m_context.getTestContext().getLog() << tcu::TestLog::Message
4820												<< "Error. Invalid array length: " << array_length << ". Expected 4."
4821												<< tcu::TestLog::EndMessage;
4822		}
4823	}
4824}
4825
4826/** Execute draw call and verifies captrued varyings
4827 *
4828 * @param combination           Function combination, first applied function is at index [0]
4829 * @param left                  Left operand
4830 * @param right                 Right operand
4831 * @param indices               Indices used by dynamic calls
4832 *
4833 * @return true if all results match expected values, false otherwise
4834 **/
4835bool FunctionalTest7_8::testDraw(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
4836								 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices) const
4837{
4838	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
4839	static const GLuint   n_vec4_varyings = 7;
4840	bool				  result		  = true;
4841	GLuint				  subroutine_indices[4];
4842	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
4843
4844	/* Prepare expected results */
4845	Utils::vec4<glw::GLfloat> expected_results[7];
4846	calculate(combination, left, right, indices, expected_results[0], expected_results[1], expected_results[2],
4847			  expected_results[3], expected_results[4], expected_results[5], expected_results[6]);
4848
4849	/* Set up input data uniforms */
4850	gl.uniform4f(m_uniform_locations[0], left.m_x, left.m_y, left.m_z, left.m_w);
4851	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4852
4853	gl.uniform4f(m_uniform_locations[1], right.m_x, right.m_y, right.m_z, right.m_w);
4854	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4855
4856	gl.uniform4ui(m_uniform_locations[2], indices.m_x, indices.m_y, indices.m_z, indices.m_w);
4857	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4ui");
4858
4859	/* Prepare subroutine uniform data */
4860	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
4861	{
4862		const GLuint location = m_subroutine_uniform_locations[i];
4863
4864		subroutine_indices[location] = m_subroutine_indices[combination[i]];
4865	}
4866
4867	/* Set up subroutine uniforms */
4868	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
4869	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
4870
4871	/* Execute draw call with transform feedback */
4872	gl.beginTransformFeedback(GL_POINTS);
4873	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4874
4875	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4876	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4877
4878	gl.endTransformFeedback();
4879	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4880
4881	/* Capture results */
4882	GLvoid* feedback_data = (GLvoid*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4883	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4884
4885	Utils::vec4<GLfloat> vec4_results[7];
4886	bool				 results[7];
4887	GLfloat*			 float_data = (GLfloat*)feedback_data;
4888	for (GLuint i = 0; i < n_vec4_varyings; ++i)
4889	{
4890		vec4_results[i].m_x = float_data[i * 4 + 0];
4891		vec4_results[i].m_y = float_data[i * 4 + 1];
4892		vec4_results[i].m_z = float_data[i * 4 + 2];
4893		vec4_results[i].m_w = float_data[i * 4 + 3];
4894	}
4895
4896	GLuint* uint_data	= (GLuint*)(float_data + (n_vec4_varyings)*4);
4897	GLuint  array_length = uint_data[0];
4898
4899	/* Unmap buffer */
4900	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4901	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4902
4903	/* Verification */
4904	for (GLuint i = 0; i < n_vec4_varyings; ++i)
4905	{
4906		results[i] = (vec4_results[i] == expected_results[i]);
4907		result	 = result && results[i];
4908	}
4909
4910	result = result && (4 == array_length);
4911
4912	/* Log error if any */
4913	if (false == result)
4914	{
4915		logError(combination, left, right, indices, expected_results, vec4_results, array_length, results);
4916	}
4917
4918	/* Done */
4919	return result;
4920}
4921
4922/** Constructor.
4923 *
4924 *  @param context Rendering context.
4925 *
4926 **/
4927FunctionalTest9::FunctionalTest9(deqp::Context& context)
4928	: TestCase(context, "subroutines_3_subroutine_types_and_subroutine_uniforms_one_function",
4929			   "Makes sure that program with one function associated with 3 different "
4930			   "subroutine types and 3 subroutine uniforms using that function compiles "
4931			   "and works as expected")
4932	, m_has_test_passed(true)
4933	, m_n_points_to_draw(16) /* arbitrary value */
4934	, m_po_id(0)
4935	, m_vao_id(0)
4936	, m_vs_id(0)
4937	, m_xfb_bo_id(0)
4938{
4939	/* Left blank intentionally */
4940}
4941
4942/** De-initializes GL objects that may have been created during test execution. */
4943void FunctionalTest9::deinit()
4944{
4945	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4946
4947	if (m_po_id != 0)
4948	{
4949		gl.deleteProgram(m_po_id);
4950
4951		m_po_id = 0;
4952	}
4953
4954	if (m_vao_id != 0)
4955	{
4956		gl.deleteVertexArrays(1, &m_vao_id);
4957
4958		m_vao_id = 0;
4959	}
4960
4961	if (m_vs_id != 0)
4962	{
4963		gl.deleteShader(m_vs_id);
4964
4965		m_vs_id = 0;
4966	}
4967
4968	if (m_xfb_bo_id != 0)
4969	{
4970		gl.deleteBuffers(1, &m_xfb_bo_id);
4971
4972		m_xfb_bo_id = 0;
4973	}
4974}
4975
4976/** Retrieves body of a vertex shader that should be used
4977 *  for the testing purposes.
4978 **/
4979std::string FunctionalTest9::getVertexShaderBody() const
4980{
4981	return "#version 400\n"
4982		   "\n"
4983		   "#extension GL_ARB_shader_subroutine : require\n"
4984		   "\n"
4985		   "subroutine void subroutineType1(inout float);\n"
4986		   "subroutine void subroutineType2(inout float);\n"
4987		   "subroutine void subroutineType3(inout float);\n"
4988		   "\n"
4989		   "subroutine(subroutineType1, subroutineType2, subroutineType3) void function(inout float result)\n"
4990		   "{\n"
4991		   "    result += float(0.123) + float(gl_VertexID);\n"
4992		   "}\n"
4993		   "\n"
4994		   "subroutine uniform subroutineType1 subroutine_uniform1;\n"
4995		   "subroutine uniform subroutineType2 subroutine_uniform2;\n"
4996		   "subroutine uniform subroutineType3 subroutine_uniform3;\n"
4997		   "\n"
4998		   "out vec4 result;\n"
4999		   "\n"
5000		   "void main()\n"
5001		   "{\n"
5002		   "    result = vec4(0, 1, 2, 3);\n"
5003		   "\n"
5004		   "    subroutine_uniform1(result.x);\n"
5005		   "    subroutine_uniform2(result.y);\n"
5006		   "    subroutine_uniform3(result.z);\n"
5007		   "\n"
5008		   "    result.w += result.x + result.y + result.z;\n"
5009		   "}\n";
5010}
5011
5012/** Initializes all GL objects required to run the test. */
5013void FunctionalTest9::initTest()
5014{
5015	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5016
5017	/* Set up program object */
5018	const char* xfb_varyings[] = { "result" };
5019
5020	const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
5021	if (!Utils::buildProgram(gl, getVertexShaderBody(), "",					  /* tc_body */
5022							 "",											  /* te_body */
5023							 "",											  /* gs_body */
5024							 "",											  /* fs_body */
5025							 xfb_varyings, n_xfb_varyings, &m_vs_id, DE_NULL, /* out_tc_id */
5026							 DE_NULL,										  /* out_te_id */
5027							 DE_NULL,										  /* out_gs_id */
5028							 DE_NULL,										  /* out_fs_id */
5029							 &m_po_id))
5030	{
5031		TCU_FAIL("Program failed to link successfully");
5032	}
5033
5034	/* Set up a buffer object we will use to hold XFB data */
5035	const unsigned int xfb_bo_size = static_cast<unsigned int>(sizeof(float) * 4 /* components */ * m_n_points_to_draw);
5036
5037	gl.genBuffers(1, &m_xfb_bo_id);
5038	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
5039
5040	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
5041	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
5042
5043	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
5044	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
5045
5046	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL, /* data */
5047				  GL_STATIC_COPY);
5048	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
5049
5050	/* Generate & bind a VAO */
5051	gl.genVertexArrays(1, &m_vao_id);
5052	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
5053
5054	gl.bindVertexArray(m_vao_id);
5055	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
5056}
5057
5058/** Executes test iteration.
5059 *
5060 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
5061 */
5062tcu::TestNode::IterateResult FunctionalTest9::iterate()
5063{
5064	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5065
5066	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5067	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5068	{
5069		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5070	}
5071	initTest();
5072
5073	/* Issue a draw call to make use of the three subroutine uniforms that we've defined */
5074	gl.useProgram(m_po_id);
5075	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
5076
5077	gl.beginTransformFeedback(GL_POINTS);
5078	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
5079	{
5080		gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw);
5081		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
5082	}
5083	gl.endTransformFeedback();
5084	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
5085
5086	/* Map the XFB BO storage into process space */
5087	const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5088	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
5089
5090	verifyXFBData(xfb_data_ptr);
5091
5092	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5093	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
5094
5095	/* All done */
5096	if (m_has_test_passed)
5097	{
5098		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5099	}
5100	else
5101	{
5102		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5103	}
5104
5105	return STOP;
5106}
5107
5108/** Verifies the data XFBed out by the vertex shader. Should the data
5109 *  be found invalid, m_has_test_passed will be set to false.
5110 *
5111 *  @param data_ptr XFB data.
5112 **/
5113void FunctionalTest9::verifyXFBData(const glw::GLvoid* data_ptr)
5114{
5115	const float			epsilon			= 1e-5f;
5116	bool				should_continue = true;
5117	const glw::GLfloat* traveller_ptr   = (const glw::GLfloat*)data_ptr;
5118
5119	for (unsigned int n_point = 0; n_point < m_n_points_to_draw && should_continue; ++n_point)
5120	{
5121		tcu::Vec4 expected_result(0, 1, 2, 3);
5122
5123		for (unsigned int n_component = 0; n_component < 3 /* xyz */; ++n_component)
5124		{
5125			expected_result[n_component] += 0.123f + float(n_point);
5126		}
5127
5128		expected_result[3 /* w */] += expected_result[0] + expected_result[1] + expected_result[2];
5129
5130		if (de::abs(expected_result[0] - traveller_ptr[0]) > epsilon ||
5131			de::abs(expected_result[1] - traveller_ptr[1]) > epsilon ||
5132			de::abs(expected_result[2] - traveller_ptr[2]) > epsilon ||
5133			de::abs(expected_result[3] - traveller_ptr[3]) > epsilon)
5134		{
5135			m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data is invalid. Expected:"
5136														   "("
5137							   << expected_result[0] << ", " << expected_result[1] << ", " << expected_result[2] << ", "
5138							   << expected_result[3] << "), found:(" << traveller_ptr[0] << ", " << traveller_ptr[1]
5139							   << ", " << traveller_ptr[2] << ", " << traveller_ptr[3] << ")."
5140							   << tcu::TestLog::EndMessage;
5141
5142			m_has_test_passed = false;
5143			should_continue   = false;
5144		}
5145
5146		traveller_ptr += 4; /* xyzw */
5147	}						/* for (all rendered points) */
5148}
5149
5150/** Constructor
5151 *
5152 * @param context CTS context
5153 **/
5154FunctionalTest10::FunctionalTest10(deqp::Context& context)
5155	: TestCase(context, "arrays_of_arrays_of_uniforms", "Verify that arrays of arrays of uniforms works as expected")
5156{
5157}
5158
5159/** Execute test
5160 *
5161 * @return tcu::TestNode::STOP
5162 **/
5163tcu::TestNode::IterateResult FunctionalTest10::iterate()
5164{
5165	static const GLchar* vertex_shader_code = "#version 400 core\n"
5166											  "#extension GL_ARB_arrays_of_arrays  : require\n"
5167											  "#extension GL_ARB_shader_subroutine : require\n"
5168											  "\n"
5169											  "precision highp float;\n"
5170											  "\n"
5171											  "// Subroutine type\n"
5172											  "subroutine int routine_type(in int iparam);\n"
5173											  "\n"
5174											  "// Subroutine definitions\n"
5175											  "subroutine(routine_type) int increment(in int iparam)\n"
5176											  "{\n"
5177											  "    return iparam + 1;\n"
5178											  "}\n"
5179											  "\n"
5180											  "subroutine(routine_type) int decrement(in int iparam)\n"
5181											  "{\n"
5182											  "    return iparam - 1;\n"
5183											  "}\n"
5184											  "\n"
5185											  "// Sub routine uniform\n"
5186											  "subroutine uniform routine_type routine[4][4];\n"
5187											  "\n"
5188											  "// Output\n"
5189											  "out int out_result;\n"
5190											  "\n"
5191											  "void main()\n"
5192											  "{\n"
5193											  "    int result = 0;\n"
5194											  "    \n"
5195											  "    for (uint j = 0; j < routine.length(); ++j)\n"
5196											  "    {\n"
5197											  "        for (uint i = 0; i < routine[j].length(); ++i)\n"
5198											  "        {\n"
5199											  "            result = routine[j][i](result);\n"
5200											  "        }\n"
5201											  "    }\n"
5202											  "    \n"
5203											  "    out_result = result;\n"
5204											  "}\n"
5205											  "\n";
5206
5207	static const GLchar* subroutine_names[] = {
5208		"increment", "decrement",
5209	};
5210	static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
5211
5212	static const GLchar* subroutine_uniform_names[] = {
5213		"routine[0][0]", "routine[1][0]", "routine[2][0]", "routine[3][0]", "routine[0][1]", "routine[1][1]",
5214		"routine[2][1]", "routine[3][1]", "routine[0][2]", "routine[1][2]", "routine[2][2]", "routine[3][2]",
5215		"routine[0][3]", "routine[1][3]", "routine[2][3]", "routine[3][3]"
5216	};
5217	static const GLuint n_subroutine_uniform_names =
5218		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
5219
5220	static const GLchar* varying_name					= "out_result";
5221	static const GLuint  transform_feedback_buffer_size = sizeof(GLint);
5222
5223	static const GLuint configuration_increment[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5224
5225	static const GLuint configuration_decrement[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
5226
5227	static const GLuint configuration_mix[16] = { 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1 };
5228
5229	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5230	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5231	{
5232		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5233	}
5234
5235	/* Do not execute the test if GL_ARB_arrays_of_arrays is not supported */
5236	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_arrays_of_arrays"))
5237	{
5238		throw tcu::NotSupportedError("GL_ARB_arrays_of_arrays is not supported.");
5239	}
5240
5241	bool result = true;
5242
5243	/* GL objects */
5244	Utils::program	 program(m_context);
5245	Utils::buffer	  transform_feedback_buffer(m_context);
5246	Utils::vertexArray vao(m_context);
5247
5248	/* Init GL objects */
5249	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name,
5250				  1 /* n_varyings */);
5251
5252	program.use();
5253
5254	vao.generate();
5255	vao.bind();
5256
5257	transform_feedback_buffer.generate();
5258	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
5259									 GL_DYNAMIC_COPY);
5260	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
5261
5262	/* Get subroutine indices */
5263	for (GLuint routine = 0; routine < n_subroutine_names; ++routine)
5264	{
5265		m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER);
5266	}
5267
5268	/* Get subroutine uniform locations */
5269	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
5270	{
5271		m_subroutine_uniform_locations[uniform] =
5272			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
5273	}
5274
5275	/* Test */
5276	GLint increment_result = testDraw(configuration_increment);
5277	GLint decrement_result = testDraw(configuration_decrement);
5278	GLint mix_result	   = testDraw(configuration_mix);
5279
5280	/* Verify */
5281	if (16 != increment_result)
5282	{
5283		result = false;
5284	}
5285
5286	if (-16 != decrement_result)
5287	{
5288		result = false;
5289	}
5290	if (0 != mix_result)
5291	{
5292		result = false;
5293	}
5294
5295	/* Set test result */
5296	if (true == result)
5297	{
5298		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5299	}
5300	else
5301	{
5302		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
5303											<< " Incrementation applied 16 times: " << increment_result
5304											<< ". Decrementation applied 16 times: " << decrement_result
5305											<< ". Incrementation and decrementation applied 8 times: " << mix_result
5306											<< tcu::TestLog::EndMessage;
5307
5308		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5309	}
5310
5311	/* Done */
5312	return tcu::TestNode::STOP;
5313}
5314
5315/** Execute draw call and return captured varying
5316 *
5317 * @param routine_indices Configuration of subroutine uniforms
5318 *
5319 * @return Value of varying captured with transform feedback
5320 **/
5321GLint FunctionalTest10::testDraw(const GLuint routine_indices[16]) const
5322{
5323	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5324	GLuint				  subroutine_indices[16];
5325	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
5326
5327	/* Prepare subroutine uniform data */
5328	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
5329	{
5330		const GLuint location = m_subroutine_uniform_locations[i];
5331
5332		subroutine_indices[location] = m_subroutine_indices[routine_indices[i]];
5333	}
5334
5335	/* Set up subroutine uniforms */
5336	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
5337	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
5338
5339	/* Execute draw call with transform feedback */
5340	gl.beginTransformFeedback(GL_POINTS);
5341	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5342
5343	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5344	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5345
5346	gl.endTransformFeedback();
5347	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5348
5349	/* Capture results */
5350	GLint* feedback_data = (GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5351	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5352
5353	GLint result = feedback_data[0];
5354
5355	/* Unmap buffer */
5356	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5357	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5358
5359	return result;
5360}
5361
5362/* Definitions of constants used by FunctionalTest11 */
5363const GLuint FunctionalTest11::m_texture_height = 32;
5364const GLuint FunctionalTest11::m_texture_width  = 32;
5365
5366/** Constructor
5367 *
5368 * @param context CTS context
5369 **/
5370FunctionalTest11::FunctionalTest11(deqp::Context& context)
5371	: TestCase(context, "globals_sampling_output_discard_function_calls", "Verify that global variables, texture "
5372																		  "sampling, fragment output, fragment discard "
5373																		  "and function calls work as expected")
5374{
5375}
5376
5377/** Execute test
5378 *
5379 * @return tcu::TestNode::STOP
5380 **/
5381tcu::TestNode::IterateResult FunctionalTest11::iterate()
5382{
5383	static const GLchar* fragment_shader_code =
5384		"#version 400 core\n"
5385		"#extension GL_ARB_shader_subroutine : require\n"
5386		"\n"
5387		"precision highp float;\n"
5388		"\n"
5389		"// Output\n"
5390		"layout(location = 0) out vec4 out_color;\n"
5391		"\n"
5392		"// Global variables\n"
5393		"vec4 success_color;\n"
5394		"vec4 failure_color;\n"
5395		"\n"
5396		"// Samplers\n"
5397		"uniform sampler2D sampler_1;\n"
5398		"uniform sampler2D sampler_2;\n"
5399		"\n"
5400		"// Functions\n"
5401		"bool are_same(in vec4 left, in vec4 right)\n"
5402		"{\n"
5403		"    bvec4 result;\n"
5404		"\n"
5405		"    result.x = (left.x == right.x);\n"
5406		"    result.y = (left.y == right.y);\n"
5407		"    result.z = (left.z == right.z);\n"
5408		"    result.w = (left.w == right.w);\n"
5409		"\n"
5410		"    return all(result);\n"
5411		"}\n"
5412		"\n"
5413		"bool are_different(in vec4 left, in vec4 right)\n"
5414		"{\n"
5415		"    bvec4 result;\n"
5416		"\n"
5417		"    result.x = (left.x != right.x);\n"
5418		"    result.y = (left.y != right.y);\n"
5419		"    result.z = (left.z != right.z);\n"
5420		"    result.w = (left.w != right.w);\n"
5421		"\n"
5422		"    return any(result);\n"
5423		"}\n"
5424		"\n"
5425		"// Subroutine types\n"
5426		"subroutine void discard_fragment_type(void);\n"
5427		"subroutine void set_global_colors_type(void);\n"
5428		"subroutine vec4 sample_texture_type(in vec2);\n"
5429		"subroutine bool comparison_type(in vec4 left, in vec4 right);\n"
5430		"subroutine void test_type(void);\n"
5431		"\n"
5432		"// Subroutine definitions\n"
5433		"// discard_fragment_type\n"
5434		"subroutine(discard_fragment_type) void discard_yes(void)\n"
5435		"{\n"
5436		"    discard;\n"
5437		"}\n"
5438		"\n"
5439		"subroutine(discard_fragment_type) void discard_no(void)\n"
5440		"{\n"
5441		"}\n"
5442		"\n"
5443		"// set_global_colors_type\n"
5444		"subroutine(set_global_colors_type) void red_pass_blue_fail(void)\n"
5445		"{\n"
5446		"    success_color = vec4(1, 0, 0, 1);\n"
5447		"    failure_color = vec4(0, 0, 1, 1);\n"
5448		"}\n"
5449		"\n"
5450		"subroutine(set_global_colors_type) void blue_pass_red_fail(void)\n"
5451		"{\n"
5452		"    success_color = vec4(0, 0, 1, 1);\n"
5453		"    failure_color = vec4(1, 0, 0, 1);\n"
5454		"}\n"
5455		"\n"
5456		"// sample_texture_type\n"
5457		"subroutine(sample_texture_type) vec4 first_sampler(in vec2 coord)\n"
5458		"{\n"
5459		"    return texture(sampler_1, coord);\n"
5460		"}\n"
5461		"\n"
5462		"subroutine(sample_texture_type) vec4 second_sampler(in vec2 coord)\n"
5463		"{\n"
5464		"    return texture(sampler_2, coord);\n"
5465		"}\n"
5466		"\n"
5467		"// comparison_type\n"
5468		"subroutine(comparison_type) bool check_equal(in vec4 left, in vec4 right)\n"
5469		"{\n"
5470		"    return are_same(left, right);\n"
5471		"}\n"
5472		"\n"
5473		"subroutine(comparison_type) bool check_not_equal(in vec4 left, in vec4 right)\n"
5474		"{\n"
5475		"    return are_different(left, right);\n"
5476		"}\n"
5477		"\n"
5478		"// Subroutine uniforms\n"
5479		"subroutine uniform discard_fragment_type  discard_fragment;\n"
5480		"subroutine uniform set_global_colors_type set_global_colors;\n"
5481		"subroutine uniform sample_texture_type    sample_texture;\n"
5482		"subroutine uniform comparison_type        compare;\n"
5483		"\n"
5484		"// Subroutine definitions\n"
5485		"// test_type\n"
5486		"subroutine(test_type) void test_with_discard(void)\n"
5487		"{\n"
5488		"    discard_fragment();"
5489		"\n"
5490		"    out_color = failure_color;\n"
5491		"\n"
5492		"    set_global_colors();\n"
5493		"\n"
5494		"    vec4 sampled_color = sample_texture(gl_PointCoord);\n"
5495		"\n"
5496		"    bool comparison_result = compare(success_color, sampled_color);\n"
5497		"\n"
5498		"    if (true == comparison_result)\n"
5499		"    {\n"
5500		"        out_color = success_color;\n"
5501		"    }\n"
5502		"    else\n"
5503		"    {\n"
5504		"        out_color = failure_color;\n"
5505		"    }\n"
5506		"}\n"
5507		"\n"
5508		"subroutine(test_type) void test_without_discard(void)\n"
5509		"{\n"
5510		"    set_global_colors();\n"
5511		"\n"
5512		"    vec4 sampled_color = sample_texture(gl_PointCoord);\n"
5513		"\n"
5514		"    bool comparison_result = compare(success_color, sampled_color);\n"
5515		"\n"
5516		"    if (true == comparison_result)\n"
5517		"    {\n"
5518		"        out_color = success_color;\n"
5519		"    }\n"
5520		"    else\n"
5521		"    {\n"
5522		"        out_color = failure_color;\n"
5523		"    }\n"
5524		"}\n"
5525		"\n"
5526		"// Subroutine uniforms\n"
5527		"subroutine uniform test_type test;\n"
5528		"\n"
5529		"void main()\n"
5530		"{\n"
5531		"    // Set colors\n"
5532		"    success_color = vec4(0.5, 0.5, 0.5, 0.5);\n"
5533		"    failure_color = vec4(0.5, 0.5, 0.5, 0.5);\n"
5534		"\n"
5535		"    test();\n"
5536		"}\n"
5537		"\n";
5538
5539	static const GLchar* geometry_shader_code = "#version 400 core\n"
5540												"#extension GL_ARB_shader_subroutine : require\n"
5541												"\n"
5542												"precision highp float;\n"
5543												"\n"
5544												"layout(points)                           in;\n"
5545												"layout(triangle_strip, max_vertices = 4) out;\n"
5546												"\n"
5547												"void main()\n"
5548												"{\n"
5549												"    gl_Position = vec4(-1, -1, 0, 1);\n"
5550												"    EmitVertex();\n"
5551												"    \n"
5552												"    gl_Position = vec4(-1,  1, 0, 1);\n"
5553												"    EmitVertex();\n"
5554												"    \n"
5555												"    gl_Position = vec4( 1, -1, 0, 1);\n"
5556												"    EmitVertex();\n"
5557												"    \n"
5558												"    gl_Position = vec4( 1,  1, 0, 1);\n"
5559												"    EmitVertex();\n"
5560												"    \n"
5561												"    EndPrimitive();\n"
5562												"}\n"
5563												"\n";
5564
5565	static const GLchar* vertex_shader_code = "#version 400 core\n"
5566											  "#extension GL_ARB_shader_subroutine : require\n"
5567											  "\n"
5568											  "precision highp float;\n"
5569											  "\n"
5570											  "void main()\n"
5571											  "{\n"
5572											  "}\n"
5573											  "\n";
5574
5575	static const GLchar* subroutine_names[][2] = { { "discard_yes", "discard_no" },
5576												   { "red_pass_blue_fail", "blue_pass_red_fail" },
5577												   { "first_sampler", "second_sampler" },
5578												   { "check_equal", "check_not_equal" },
5579												   { "test_with_discard", "test_without_discard" } };
5580	static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
5581
5582	static const GLchar* subroutine_uniform_names[] = { "discard_fragment", "set_global_colors", "sample_texture",
5583														"compare", "test" };
5584	static const GLuint n_subroutine_uniform_names =
5585		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
5586
5587	static const GLchar* uniform_names[] = {
5588		"sampler_1", "sampler_2",
5589	};
5590	static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
5591
5592	/* Colors */
5593	static const GLubyte blue_color[4]  = { 0, 0, 255, 255 };
5594	static const GLubyte clean_color[4] = { 0, 0, 0, 0 };
5595	static const GLubyte red_color[4]   = { 255, 0, 0, 255 };
5596
5597	/* Configurations */
5598	static const testConfiguration test_configurations[] = {
5599		testConfiguration(
5600			"Expect red color from 1st sampler", red_color, 1 /* discard_fragment  : discard_no         */,
5601			0 /* set_global_colors : red_pass_blue_fail */, 0 /* sample_texture    : first_sampler      */,
5602			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */, 1 /* red */,
5603			0 /* blue */),
5604
5605		testConfiguration(
5606			"Test \"without discard\" option, expect no blue color from 2nd sampler", blue_color,
5607			0 /* discard_fragment  : discard_yes           */, 1 /* set_global_colors : blue_pass_red_fail    */,
5608			1 /* sample_texture    : second_sampler        */, 1 /* compare           : check_not_equal       */,
5609			1 /* test              : test_without_discard  */, 0 /* blue */, 1 /* red */),
5610
5611		testConfiguration("Fragment shoud be discarded", clean_color, 0 /* discard_fragment  : discard_yes        */,
5612						  0 /* set_global_colors : red_pass_blue_fail */,
5613						  0 /* sample_texture    : first_sampler      */,
5614						  0 /* compare           : check_equal        */,
5615						  0 /* test              : test_with_discard  */, 1 /* red */, 0 /* blue */),
5616
5617		testConfiguration(
5618			"Expect blue color from 1st sampler", blue_color, 1 /* discard_fragment  : discard_no         */,
5619			1 /* set_global_colors : blue_pass_red_fail */, 0 /* sample_texture    : first_sampler      */,
5620			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */,
5621			0 /* blue */, 1 /* red */),
5622
5623		testConfiguration(
5624			"Expect red color from 2nd sampler", red_color, 1 /* discard_fragment  : discard_no         */,
5625			0 /* set_global_colors : red_pass_blue_fail */, 1 /* sample_texture    : second_sampler     */,
5626			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */,
5627			0 /* blue */, 1 /* red */),
5628
5629		testConfiguration(
5630			"Expect no blue color from 2nd sampler", blue_color, 1 /* discard_fragment  : discard_no         */,
5631			1 /* set_global_colors : blue_pass_red_fail */, 1 /* sample_texture    : second_sampler     */,
5632			1 /* compare           : check_not_equal    */, 0 /* test              : test_with_discard  */,
5633			0 /* blue */, 1 /* red */),
5634	};
5635	static const GLuint n_test_cases = sizeof(test_configurations) / sizeof(test_configurations[0]);
5636
5637	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5638	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5639	{
5640		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5641	}
5642
5643	/* GL objects */
5644	Utils::texture	 blue_texture(m_context);
5645	Utils::texture	 color_texture(m_context);
5646	Utils::framebuffer framebuffer(m_context);
5647	Utils::program	 program(m_context);
5648	Utils::texture	 red_texture(m_context);
5649	Utils::vertexArray vao(m_context);
5650
5651	/* Init GL objects */
5652	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
5653				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
5654
5655	program.use();
5656
5657	vao.generate();
5658	vao.bind();
5659
5660	blue_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5661	color_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5662	red_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5663
5664	framebuffer.generate();
5665	framebuffer.bind();
5666	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
5667
5668	/* Get subroutine indices */
5669	for (GLuint type = 0; type < n_subroutine_types; ++type)
5670	{
5671		m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_FRAGMENT_SHADER);
5672		m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_FRAGMENT_SHADER);
5673	}
5674
5675	/* Get subroutine uniform locations */
5676	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
5677	{
5678		m_subroutine_uniform_locations[uniform] =
5679			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_FRAGMENT_SHADER);
5680	}
5681
5682	/* Get uniform locations */
5683	for (GLuint i = 0; i < n_uniform_names; ++i)
5684	{
5685		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
5686	}
5687
5688	/* Prepare textures */
5689	fillTexture(blue_texture, blue_color);
5690	fillTexture(color_texture, clean_color);
5691	fillTexture(red_texture, red_color);
5692
5693	m_source_textures[0] = blue_texture.m_id;
5694	m_source_textures[1] = red_texture.m_id;
5695
5696	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
5697
5698	/* Test */
5699	bool result = true;
5700	for (GLuint i = 0; i < n_test_cases; ++i)
5701	{
5702		/* Clean output texture */
5703		framebuffer.clear(GL_COLOR_BUFFER_BIT);
5704
5705		/* Execute test */
5706		if (false == testDraw(test_configurations[i].m_routines, test_configurations[i].m_samplers,
5707							  test_configurations[i].m_expected_color, color_texture))
5708		{
5709			m_context.getTestContext().getLog()
5710				<< tcu::TestLog::Message << "Error. Failure for configuration: " << test_configurations[i].m_description
5711				<< tcu::TestLog::EndMessage;
5712
5713			result = false;
5714		}
5715	}
5716
5717	/* Set result */
5718	if (true == result)
5719	{
5720		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5721	}
5722	else
5723	{
5724		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5725	}
5726
5727	/* Done */
5728	return tcu::TestNode::STOP;
5729}
5730
5731/** Fill texture with specified color
5732 *
5733 * @param texture Texture instance
5734 * @param color   Color
5735 **/
5736void FunctionalTest11::fillTexture(Utils::texture& texture, const glw::GLubyte color[4]) const
5737{
5738	std::vector<GLubyte> texture_data;
5739
5740	/* Prepare texture data */
5741	texture_data.resize(m_texture_width * m_texture_height * 4);
5742
5743	for (GLuint y = 0; y < m_texture_height; ++y)
5744	{
5745		const GLuint line_offset = y * m_texture_width * 4;
5746
5747		for (GLuint x = 0; x < m_texture_width; ++x)
5748		{
5749			const GLuint point_offset = x * 4 + line_offset;
5750
5751			texture_data[point_offset + 0] = color[0]; /* red */
5752			texture_data[point_offset + 1] = color[1]; /* green */
5753			texture_data[point_offset + 2] = color[2]; /* blue */
5754			texture_data[point_offset + 3] = color[3]; /* alpha */
5755		}
5756	}
5757
5758	texture.update(m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
5759}
5760
5761/** Execute draw call and verify results
5762 *
5763 * @param routine_configuration Configurations of routines to be used
5764 * @param sampler_configuration Configuration of textures to be bound to samplers
5765 * @param expected_color        Expected color of result image
5766 *
5767 * @return true if result image is filled with expected color, false otherwise
5768 **/
5769bool FunctionalTest11::testDraw(const glw::GLuint routine_configuration[5], const glw::GLuint sampler_configuration[2],
5770								const glw::GLubyte expected_color[4], Utils::texture& color_texture) const
5771{
5772	const glw::Functions& gl					= m_context.getRenderContext().getFunctions();
5773	static const GLint	n_samplers			= 2;
5774	static const GLint	n_subroutine_uniforms = 5;
5775	GLuint				  subroutine_indices[5];
5776
5777	/* Set samplers */
5778	for (GLuint i = 0; i < n_samplers; ++i)
5779	{
5780		const GLuint location = m_uniform_locations[i];
5781		const GLuint texture  = m_source_textures[sampler_configuration[i]];
5782
5783		gl.activeTexture(GL_TEXTURE0 + i);
5784		GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
5785
5786		gl.bindTexture(GL_TEXTURE_2D, texture);
5787		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5788
5789		gl.uniform1i(location, i);
5790		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
5791	}
5792
5793	gl.activeTexture(GL_TEXTURE0 + 0);
5794
5795	/* Set subroutine uniforms */
5796	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
5797	{
5798		const GLuint location = m_subroutine_uniform_locations[i];
5799		const GLuint routine  = routine_configuration[i];
5800
5801		subroutine_indices[location] = m_subroutine_indices[i][routine];
5802	}
5803
5804	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 5, subroutine_indices);
5805	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
5806
5807	/* Draw */
5808	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5809	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5810
5811	/* Capture result */
5812	std::vector<GLubyte> captured_data;
5813	captured_data.resize(m_texture_width * m_texture_height * 4);
5814
5815	color_texture.get(GL_RGBA, GL_UNSIGNED_BYTE, &captured_data[0]);
5816
5817	/* Verify result */
5818	for (GLuint y = 0; y < m_texture_height; ++y)
5819	{
5820		const GLuint line_offset = y * m_texture_width * 4;
5821
5822		for (GLuint x = 0; x < m_texture_width; ++x)
5823		{
5824			const GLuint point_offset   = x * 4 + line_offset;
5825			bool		 is_as_expected = true;
5826
5827			is_as_expected = is_as_expected && (expected_color[0] == captured_data[point_offset + 0]); /* red */
5828			is_as_expected = is_as_expected && (expected_color[1] == captured_data[point_offset + 1]); /* green */
5829			is_as_expected = is_as_expected && (expected_color[2] == captured_data[point_offset + 2]); /* blue */
5830			is_as_expected = is_as_expected && (expected_color[3] == captured_data[point_offset + 3]); /* alpha */
5831
5832			if (false == is_as_expected)
5833			{
5834				return false;
5835			}
5836		}
5837	}
5838
5839	/* Done */
5840	return true;
5841}
5842
5843/* Constatns used by FunctionalTest12 */
5844const glw::GLuint FunctionalTest12::m_texture_height = 16;
5845const glw::GLuint FunctionalTest12::m_texture_width  = 16;
5846
5847/** Constructor
5848 *
5849 * @param context CTS context
5850 **/
5851FunctionalTest12::FunctionalTest12(deqp::Context& context)
5852	: TestCase(context, "ssbo_atomic_image_load_store",
5853			   "Verify that SSBO, atomic counters and image load store work as expected")
5854	, m_left_image(0)
5855	, m_right_image(0)
5856{
5857}
5858
5859/** Execute test
5860 *
5861 * @return tcu::TestNode::STOP
5862 **/
5863tcu::TestNode::IterateResult FunctionalTest12::iterate()
5864{
5865	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5866	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5867	{
5868		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5869	}
5870
5871	bool result = true;
5872
5873	/* Test atomic counters */
5874	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
5875	{
5876		if (false == testAtomic())
5877		{
5878			result = false;
5879		}
5880	}
5881
5882	/* Test shader storage buffer */
5883	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_storage_buffer_object"))
5884	{
5885		if (false == testSSBO())
5886		{
5887			result = false;
5888		}
5889	}
5890
5891	/* Test image load store */
5892	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_image_load_store"))
5893	{
5894		if (false == testImage())
5895		{
5896			result = false;
5897		}
5898	}
5899
5900	/* Set result */
5901	if (true == result)
5902	{
5903		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5904	}
5905	else
5906	{
5907		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5908	}
5909
5910	/* Done */
5911	return tcu::TestNode::STOP;
5912}
5913
5914/** Fill texture with specified color
5915 *
5916 * @param texture Texture instance
5917 * @param color   Color
5918 **/
5919void FunctionalTest12::fillTexture(Utils::texture& texture, const glw::GLuint color[4]) const
5920{
5921	std::vector<GLuint> texture_data;
5922
5923	/* Prepare texture data */
5924	texture_data.resize(m_texture_width * m_texture_height * 4);
5925
5926	for (GLuint y = 0; y < m_texture_height; ++y)
5927	{
5928		const GLuint line_offset = y * m_texture_width * 4;
5929
5930		for (GLuint x = 0; x < m_texture_width; ++x)
5931		{
5932			const GLuint point_offset = x * 4 + line_offset;
5933
5934			texture_data[point_offset + 0] = color[0]; /* red */
5935			texture_data[point_offset + 1] = color[1]; /* green */
5936			texture_data[point_offset + 2] = color[2]; /* blue */
5937			texture_data[point_offset + 3] = color[3]; /* alpha */
5938		}
5939	}
5940
5941	texture.update(m_texture_width, m_texture_height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &texture_data[0]);
5942}
5943
5944/** Test atomic counters
5945 *
5946 * @return true if test pass, false otherwise
5947 **/
5948bool FunctionalTest12::testAtomic()
5949{
5950	static const GLchar* fragment_shader_code = "#version 400 core\n"
5951												"#extension GL_ARB_shader_atomic_counters : require\n"
5952												"#extension GL_ARB_shader_subroutine      : require\n"
5953												"\n"
5954												"precision highp float;\n"
5955												"\n"
5956												"layout(location = 0) out uint out_color;\n"
5957												"\n"
5958												"layout(binding = 0, offset = 8) uniform atomic_uint one;\n"
5959												"layout(binding = 0, offset = 4) uniform atomic_uint two;\n"
5960												"layout(binding = 0, offset = 0) uniform atomic_uint three;\n"
5961												"\n"
5962												"subroutine void atomic_routine(void)\n;"
5963												"\n"
5964												"subroutine(atomic_routine) void increment_two(void)\n"
5965												"{\n"
5966												"    out_color = atomicCounterIncrement(two);\n"
5967												"}\n"
5968												"\n"
5969												"subroutine(atomic_routine) void decrement_three(void)\n"
5970												"{\n"
5971												"    out_color = atomicCounterDecrement(three);\n"
5972												"}\n"
5973												"\n"
5974												"subroutine(atomic_routine) void read_one(void)\n"
5975												"{\n"
5976												"    out_color = atomicCounter(one);\n"
5977												"}\n"
5978												"\n"
5979												"subroutine uniform atomic_routine routine;\n"
5980												"\n"
5981												"void main()\n"
5982												"{\n"
5983												"    routine();\n"
5984												"}\n"
5985												"\n";
5986
5987	static const GLchar* geometry_shader_code = "#version 400 core\n"
5988												"#extension GL_ARB_shader_subroutine : require\n"
5989												"\n"
5990												"precision highp float;\n"
5991												"\n"
5992												"layout(points)                           in;\n"
5993												"layout(triangle_strip, max_vertices = 4) out;\n"
5994												"\n"
5995												"void main()\n"
5996												"{\n"
5997												"    gl_Position = vec4(-1, -1, 0, 1);\n"
5998												"    EmitVertex();\n"
5999												"    \n"
6000												"    gl_Position = vec4(-1,  1, 0, 1);\n"
6001												"    EmitVertex();\n"
6002												"    \n"
6003												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6004												"    EmitVertex();\n"
6005												"    \n"
6006												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6007												"    EmitVertex();\n"
6008												"    \n"
6009												"    EndPrimitive();\n"
6010												"}\n"
6011												"\n";
6012
6013	static const GLchar* vertex_shader_code = "#version 400 core\n"
6014											  "#extension GL_ARB_shader_subroutine : require\n"
6015											  "\n"
6016											  "precision highp float;\n"
6017											  "\n"
6018											  "void main()\n"
6019											  "{\n"
6020											  "}\n"
6021											  "\n";
6022
6023	static const GLchar* subroutine_names[] = { "increment_two", "decrement_three", "read_one" };
6024
6025	/* Test data */
6026	static const glw::GLuint atomic_buffer_data[] = { m_texture_width * m_texture_height,
6027													  m_texture_width * m_texture_height,
6028													  m_texture_width * m_texture_height };
6029
6030	static const glw::GLuint expected_incremented_two[] = { atomic_buffer_data[0], 2 * atomic_buffer_data[1],
6031															atomic_buffer_data[2] };
6032
6033	static const glw::GLuint expected_decremented_three[] = { 0, expected_incremented_two[1],
6034															  expected_incremented_two[2] };
6035
6036	static const glw::GLuint expected_read_one[] = { expected_decremented_three[0], expected_decremented_three[1],
6037													 expected_decremented_three[2] };
6038
6039	/* GL objects */
6040	Utils::buffer	  atomic_buffer(m_context);
6041	Utils::texture	 color_texture(m_context);
6042	Utils::framebuffer framebuffer(m_context);
6043	Utils::program	 program(m_context);
6044	Utils::vertexArray vao(m_context);
6045
6046	/* Init GL objects */
6047	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6048				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6049
6050	program.use();
6051
6052	vao.generate();
6053	vao.bind();
6054
6055	color_texture.create(m_texture_width, m_texture_height, GL_R32UI);
6056
6057	atomic_buffer.generate();
6058	atomic_buffer.update(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomic_buffer_data), (GLvoid*)atomic_buffer_data,
6059						 GL_STATIC_DRAW);
6060	atomic_buffer.bindRange(GL_ATOMIC_COUNTER_BUFFER, 0 /* index */, 0 /* offset */, sizeof(atomic_buffer_data));
6061
6062	framebuffer.generate();
6063	framebuffer.bind();
6064	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6065	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6066	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6067
6068	/* Subroutine indices */
6069	GLuint increment_two   = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6070	GLuint decrement_three = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6071	GLuint read_one		   = program.getSubroutineIndex(subroutine_names[2], GL_FRAGMENT_SHADER);
6072
6073	/* Test */
6074	bool result = true;
6075
6076	if (false == testAtomicDraw(increment_two, expected_incremented_two))
6077	{
6078		result = false;
6079	}
6080
6081	if (false == testAtomicDraw(decrement_three, expected_decremented_three))
6082	{
6083		result = false;
6084	}
6085
6086	if (false == testAtomicDraw(read_one, expected_read_one))
6087	{
6088		result = false;
6089	}
6090
6091	/* Done */
6092	return result;
6093}
6094
6095/** Execture draw call and verify results
6096 *
6097 * @param subroutine_index Index of subroutine that shall be used during draw call
6098 * @param expected_results Expected results
6099 *
6100 * @return true if results are as expected, false otherwise
6101 **/
6102bool FunctionalTest12::testAtomicDraw(GLuint subroutine_index, const GLuint expected_results[3]) const
6103{
6104	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6105
6106	/* Set subroutine uniforms */
6107	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6108	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6109
6110	/* Draw */
6111	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6112	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6113
6114	/* Capture results */
6115	GLuint* atomic_results = (GLuint*)gl.mapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY);
6116	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
6117
6118	/* Verify */
6119	bool result = (0 == memcmp(expected_results, atomic_results, 3 * sizeof(GLuint)));
6120
6121	if (false == result)
6122	{
6123		m_context.getTestContext().getLog()
6124			<< tcu::TestLog::Message << "Error. Invalid result. "
6125			<< "Result: [ " << atomic_results[0] << ", " << atomic_results[1] << ", " << atomic_results[2] << " ] "
6126			<< "Expected: [ " << expected_results[0] << ", " << expected_results[1] << ", " << expected_results[2]
6127			<< " ]" << tcu::TestLog::EndMessage;
6128	}
6129
6130	/* Unmap buffer */
6131	gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
6132	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
6133
6134	/* Done */
6135	return result;
6136}
6137
6138/** Test image load store
6139 *
6140 * @return true if test pass, false otherwise
6141 **/
6142bool FunctionalTest12::testImage()
6143{
6144	static const GLchar* fragment_shader_code =
6145		"#version 400 core\n"
6146		"#extension GL_ARB_shader_image_load_store : require\n"
6147		"#extension GL_ARB_shader_subroutine       : require\n"
6148		"\n"
6149		"precision highp float;\n"
6150		"\n"
6151		"layout(location = 0) out uvec4 out_color;\n"
6152		"\n"
6153		"layout(rgba32ui) uniform uimage2D left_image;\n"
6154		"layout(rgba32ui) uniform uimage2D right_image;\n"
6155		"\n"
6156		"subroutine void image_routine(void);\n"
6157		"\n"
6158		"subroutine(image_routine) void left_to_right(void)\n"
6159		"{\n"
6160		"    out_color = imageLoad (left_image,  ivec2(gl_FragCoord.xy));\n"
6161		"                imageStore(right_image, ivec2(gl_FragCoord.xy), out_color);\n"
6162		"}\n"
6163		"\n"
6164		"subroutine(image_routine) void right_to_left(void)\n"
6165		"{\n"
6166		"    out_color = imageLoad (right_image, ivec2(gl_FragCoord.xy));\n"
6167		"                imageStore(left_image,  ivec2(gl_FragCoord.xy), out_color);\n"
6168		"}\n"
6169		"\n"
6170		"subroutine uniform image_routine routine;\n"
6171		"\n"
6172		"void main()\n"
6173		"{\n"
6174		"    routine();\n"
6175		"}\n"
6176		"\n";
6177
6178	static const GLchar* geometry_shader_code = "#version 400 core\n"
6179												"#extension GL_ARB_shader_subroutine : require\n"
6180												"\n"
6181												"precision highp float;\n"
6182												"\n"
6183												"layout(points)                           in;\n"
6184												"layout(triangle_strip, max_vertices = 4) out;\n"
6185												"\n"
6186												"void main()\n"
6187												"{\n"
6188												"    gl_Position = vec4(-1, -1, 0, 1);\n"
6189												"    EmitVertex();\n"
6190												"    \n"
6191												"    gl_Position = vec4(-1,  1, 0, 1);\n"
6192												"    EmitVertex();\n"
6193												"    \n"
6194												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6195												"    EmitVertex();\n"
6196												"    \n"
6197												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6198												"    EmitVertex();\n"
6199												"    \n"
6200												"    EndPrimitive();\n"
6201												"}\n"
6202												"\n";
6203
6204	static const GLchar* vertex_shader_code = "#version 400 core\n"
6205											  "#extension GL_ARB_shader_subroutine : require\n"
6206											  "\n"
6207											  "precision highp float;\n"
6208											  "\n"
6209											  "void main()\n"
6210											  "{\n"
6211											  "}\n"
6212											  "\n";
6213
6214	static const GLchar* subroutine_names[] = { "left_to_right", "right_to_left" };
6215
6216	static const GLchar* uniform_names[] = { "left_image", "right_image" };
6217
6218	/* Test data */
6219	static const GLuint blue_color[4]  = { 0, 0, 255, 255 };
6220	static const GLuint clean_color[4] = { 16, 32, 64, 128 };
6221	static const GLuint red_color[4]   = { 255, 0, 0, 255 };
6222
6223	/* GL objects */
6224	Utils::texture	 blue_texture(m_context);
6225	Utils::texture	 destination_texture(m_context);
6226	Utils::texture	 color_texture(m_context);
6227	Utils::framebuffer framebuffer(m_context);
6228	Utils::program	 program(m_context);
6229	Utils::texture	 red_texture(m_context);
6230	Utils::vertexArray vao(m_context);
6231
6232	/* Init GL objects */
6233	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6234				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6235
6236	program.use();
6237
6238	vao.generate();
6239	vao.bind();
6240
6241	blue_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6242	destination_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6243	color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6244	red_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6245
6246	fillTexture(blue_texture, blue_color);
6247	fillTexture(destination_texture, clean_color);
6248	fillTexture(red_texture, red_color);
6249
6250	framebuffer.generate();
6251	framebuffer.bind();
6252	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6253	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6254	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6255
6256	/* Subroutine indices */
6257	GLuint left_to_right = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6258	GLuint right_to_left = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6259
6260	/* Uniform locations */
6261	m_left_image  = program.getUniformLocation(uniform_names[0]);
6262	m_right_image = program.getUniformLocation(uniform_names[1]);
6263
6264	/* Test */
6265	bool result = true;
6266
6267	if (false == testImageDraw(left_to_right, blue_texture, destination_texture, blue_color, blue_color))
6268	{
6269		result = false;
6270	}
6271
6272	if (false == testImageDraw(left_to_right, red_texture, destination_texture, red_color, red_color))
6273	{
6274		result = false;
6275	}
6276
6277	if (false == testImageDraw(right_to_left, destination_texture, blue_texture, blue_color, blue_color))
6278	{
6279		result = false;
6280	}
6281
6282	if (false == testImageDraw(right_to_left, destination_texture, red_texture, red_color, red_color))
6283	{
6284		result = false;
6285	}
6286
6287	if (false == testImageDraw(left_to_right, blue_texture, red_texture, blue_color, blue_color))
6288	{
6289		result = false;
6290	}
6291
6292	/* Done */
6293	return result;
6294}
6295
6296/** Execute draw call and verifies results
6297 *
6298 * @param subroutine_index     Index of subroutine that shall be used during draw call
6299 * @param left                 "Left" texture
6300 * @param right                "Right" texture
6301 * @param expected_left_color  Expected color of "left" texture
6302 * @param expected_right_color Expected color of "right" texture
6303 *
6304 * @return true if verification result is positive, false otherwise
6305 **/
6306bool FunctionalTest12::testImageDraw(GLuint subroutine_index, Utils::texture& left, Utils::texture& right,
6307									 const GLuint expected_left_color[4], const GLuint expected_right_color[4]) const
6308{
6309	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6310
6311	/* Set subroutine uniforms */
6312	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6313	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6314
6315	/* Set up image units */
6316	gl.uniform1i(m_left_image, 0);
6317	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
6318
6319	gl.uniform1i(m_right_image, 1);
6320	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
6321
6322	gl.bindImageTexture(0, left.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
6323	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6324
6325	gl.bindImageTexture(1, right.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
6326	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6327
6328	/* Draw */
6329	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6330	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6331
6332	/* Verify results */
6333	bool result = true;
6334
6335	if (false == verifyTexture(left, expected_left_color))
6336	{
6337		m_context.getTestContext().getLog() << tcu::TestLog::Message
6338											<< "Error. Invalid result. Left texture is filled with wrong color."
6339											<< tcu::TestLog::EndMessage;
6340		result = false;
6341	}
6342
6343	if (false == verifyTexture(right, expected_right_color))
6344	{
6345		m_context.getTestContext().getLog() << tcu::TestLog::Message
6346											<< "Error. Invalid result. Right texture is filled with wrong color."
6347											<< tcu::TestLog::EndMessage;
6348		result = false;
6349	}
6350
6351	/* Done */
6352	return result;
6353}
6354
6355/** Test shader storage buffer
6356 *
6357 * @return true if test pass, false otherwise
6358 **/
6359bool FunctionalTest12::testSSBO()
6360{
6361	static const GLchar* fragment_shader_code = "#version 400 core\n"
6362												"#extension GL_ARB_shader_storage_buffer_object : require\n"
6363												"#extension GL_ARB_shader_subroutine            : require\n"
6364												"\n"
6365												"precision highp float;\n"
6366												"\n"
6367												"layout(location = 0) out uvec4 out_color;\n"
6368												"\n"
6369												"layout(std140, binding = 0) buffer Buffer\n"
6370												"{\n"
6371												"    uvec4 entry;\n"
6372												"};\n"
6373												"\n"
6374												"subroutine void ssbo_routine(void)\n;"
6375												"\n"
6376												"subroutine(ssbo_routine) void increment(void)\n"
6377												"{\n"
6378												"    out_color.x = atomicAdd(entry.x, 1);\n"
6379												"    out_color.y = atomicAdd(entry.y, 1);\n"
6380												"    out_color.z = atomicAdd(entry.z, 1);\n"
6381												"    out_color.w = atomicAdd(entry.w, 1);\n"
6382												"}\n"
6383												"\n"
6384												"subroutine(ssbo_routine) void decrement(void)\n"
6385												"{\n"
6386												"    out_color.x = atomicAdd(entry.x, -1);\n"
6387												"    out_color.y = atomicAdd(entry.y, -1);\n"
6388												"    out_color.z = atomicAdd(entry.z, -1);\n"
6389												"    out_color.w = atomicAdd(entry.w, -1);\n"
6390												"}\n"
6391												"\n"
6392												"subroutine uniform ssbo_routine routine;\n"
6393												"\n"
6394												"void main()\n"
6395												"{\n"
6396												"    routine();\n"
6397												"}\n"
6398												"\n";
6399
6400	static const GLchar* geometry_shader_code = "#version 400 core\n"
6401												"#extension GL_ARB_shader_subroutine : require\n"
6402												"\n"
6403												"precision highp float;\n"
6404												"\n"
6405												"layout(points)                           in;\n"
6406												"layout(triangle_strip, max_vertices = 4) out;\n"
6407												"\n"
6408												"void main()\n"
6409												"{\n"
6410												"    gl_Position = vec4(-1, -1, 0, 1);\n"
6411												"    EmitVertex();\n"
6412												"    \n"
6413												"    gl_Position = vec4(-1,  1, 0, 1);\n"
6414												"    EmitVertex();\n"
6415												"    \n"
6416												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6417												"    EmitVertex();\n"
6418												"    \n"
6419												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6420												"    EmitVertex();\n"
6421												"    \n"
6422												"    EndPrimitive();\n"
6423												"}\n"
6424												"\n";
6425
6426	static const GLchar* vertex_shader_code = "#version 400 core\n"
6427											  "#extension GL_ARB_shader_subroutine : require\n"
6428											  "\n"
6429											  "precision highp float;\n"
6430											  "\n"
6431											  "void main()\n"
6432											  "{\n"
6433											  "}\n"
6434											  "\n";
6435
6436	static const GLchar* subroutine_names[] = { "increment", "decrement" };
6437
6438	/* Test data */
6439	static const glw::GLuint buffer_data[] = { m_texture_width * m_texture_height + 1,
6440											   m_texture_width * m_texture_height + 2,
6441											   m_texture_width * m_texture_height + 3,
6442											   m_texture_width * m_texture_height + 4 };
6443
6444	static const glw::GLuint expected_incremented[] = { m_texture_width * m_texture_height + buffer_data[0],
6445														m_texture_width * m_texture_height + buffer_data[1],
6446														m_texture_width * m_texture_height + buffer_data[2],
6447														m_texture_width * m_texture_height + buffer_data[3] };
6448
6449	static const glw::GLuint expected_decremented[] = { buffer_data[0], buffer_data[1], buffer_data[2],
6450														buffer_data[3] };
6451
6452	/* GL objects */
6453	Utils::buffer	  buffer(m_context);
6454	Utils::texture	 color_texture(m_context);
6455	Utils::framebuffer framebuffer(m_context);
6456	Utils::program	 program(m_context);
6457	Utils::vertexArray vao(m_context);
6458
6459	/* Init GL objects */
6460	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6461				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6462
6463	program.use();
6464
6465	vao.generate();
6466	vao.bind();
6467
6468	color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6469
6470	buffer.generate();
6471	buffer.update(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), (GLvoid*)buffer_data, GL_STATIC_DRAW);
6472	buffer.bindRange(GL_SHADER_STORAGE_BUFFER, 0 /* index */, 0 /* offset */, sizeof(buffer_data));
6473
6474	framebuffer.generate();
6475	framebuffer.bind();
6476	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6477	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6478	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6479
6480	/* Subroutine indices */
6481	GLuint increment = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6482	GLuint decrement = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6483
6484	/* Test */
6485	bool result = true;
6486
6487	if (false == testSSBODraw(increment, expected_incremented))
6488	{
6489		result = false;
6490	}
6491
6492	if (false == testSSBODraw(decrement, expected_decremented))
6493	{
6494		result = false;
6495	}
6496
6497	/* Done */
6498	return result;
6499}
6500
6501/** Execute draw call and verify results
6502 *
6503 * @param subroutine_index Index of subroutine that shall be used by draw call
6504 * @param expected_results Expected results
6505 *
6506 *
6507 **/
6508bool FunctionalTest12::testSSBODraw(GLuint subroutine_index, const GLuint expected_results[4]) const
6509{
6510	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6511
6512	/* Set subroutine uniforms */
6513	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6514	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6515
6516	/* Draw */
6517	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6518	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6519
6520	/* Capture results */
6521	GLuint* ssbo_results = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
6522	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
6523
6524	/* Verify */
6525	bool result = (0 == memcmp(expected_results, ssbo_results, 4 * sizeof(GLuint)));
6526
6527	if (false == result)
6528	{
6529		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result. "
6530											<< "Result: [ " << ssbo_results[0] << ", " << ssbo_results[1] << ", "
6531											<< ssbo_results[2] << ", " << ssbo_results[3] << " ] "
6532											<< "Expected: [ " << expected_results[0] << ", " << expected_results[1]
6533											<< ", " << expected_results[2] << ", " << expected_results[3] << " ]"
6534											<< tcu::TestLog::EndMessage;
6535	}
6536
6537	/* Unmap buffer */
6538	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
6539	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
6540
6541	/* Done */
6542	return result;
6543}
6544
6545/** Check if texture is filled with expected color
6546 *
6547 * @param texture        Texture instance
6548 * @param expected_color Expected color
6549 *
6550 * @return true if texture is filled with specified color, false otherwise
6551 **/
6552bool FunctionalTest12::verifyTexture(Utils::texture& texture, const GLuint expected_color[4]) const
6553{
6554	std::vector<GLuint> results;
6555	results.resize(m_texture_width * m_texture_height * 4);
6556
6557	texture.get(GL_RGBA_INTEGER, GL_UNSIGNED_INT, &results[0]);
6558
6559	for (GLuint y = 0; y < m_texture_height; ++y)
6560	{
6561		const GLuint line_offset = y * m_texture_width * 4;
6562
6563		for (GLuint x = 0; x < m_texture_width; ++x)
6564		{
6565			const GLuint point_offset = line_offset + x * 4;
6566			bool		 result		  = true;
6567
6568			result = result && (results[point_offset + 0] == expected_color[0]);
6569			result = result && (results[point_offset + 1] == expected_color[1]);
6570			result = result && (results[point_offset + 2] == expected_color[2]);
6571			result = result && (results[point_offset + 3] == expected_color[3]);
6572
6573			if (false == result)
6574			{
6575				return false;
6576			}
6577		}
6578	}
6579
6580	return true;
6581}
6582
6583/** Constructor.
6584 *
6585 *  @param context Rendering context.
6586 *
6587 **/
6588FunctionalTest13::FunctionalTest13(deqp::Context& context)
6589	: TestCase(context, "subroutines_with_separate_shader_objects",
6590			   "Verifies that subroutines work correctly when used in separate "
6591			   "shader objects")
6592	, m_fbo_id(0)
6593	, m_pipeline_id(0)
6594	, m_read_buffer(DE_NULL)
6595	, m_to_height(4)
6596	, m_to_id(0)
6597	, m_to_width(4)
6598	, m_vao_id(0)
6599	, m_has_test_passed(true)
6600{
6601	memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids));
6602	memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids));
6603	memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids));
6604	memset(m_te_po_ids, 0, sizeof(m_te_po_ids));
6605	memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids));
6606}
6607
6608/** Deinitializes all GL objects that may have been created during test
6609 *  execution, as well as releases all process-side buffers that may have
6610 *  been allocated during the process.
6611 *  The function also restores default GL state configuration.
6612 **/
6613void FunctionalTest13::deinit()
6614{
6615	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6616
6617	if (m_fbo_id != 0)
6618	{
6619		gl.deleteFramebuffers(1, &m_fbo_id);
6620
6621		m_fbo_id = 0;
6622	}
6623
6624	if (m_pipeline_id != 0)
6625	{
6626		gl.deleteProgramPipelines(1, &m_pipeline_id);
6627
6628		m_pipeline_id = 0;
6629	}
6630
6631	if (m_read_buffer != DE_NULL)
6632	{
6633		delete[] m_read_buffer;
6634
6635		m_read_buffer = DE_NULL;
6636	}
6637
6638	for (unsigned int n_id = 0; n_id < 2 /* po id variants */; ++n_id)
6639	{
6640		if (m_fs_po_ids[n_id] != 0)
6641		{
6642			gl.deleteProgram(m_fs_po_ids[n_id]);
6643
6644			m_fs_po_ids[n_id] = 0;
6645		}
6646
6647		if (m_gs_po_ids[n_id] != 0)
6648		{
6649			gl.deleteProgram(m_gs_po_ids[n_id]);
6650
6651			m_gs_po_ids[n_id] = 0;
6652		}
6653
6654		if (m_tc_po_ids[n_id] != 0)
6655		{
6656			gl.deleteProgram(m_tc_po_ids[n_id]);
6657
6658			m_tc_po_ids[n_id] = 0;
6659		}
6660
6661		if (m_te_po_ids[n_id] != 0)
6662		{
6663			gl.deleteProgram(m_te_po_ids[n_id]);
6664
6665			m_te_po_ids[n_id] = 0;
6666		}
6667
6668		if (m_vs_po_ids[n_id] != 0)
6669		{
6670			gl.deleteProgram(m_vs_po_ids[n_id]);
6671
6672			m_vs_po_ids[n_id] = 0;
6673		}
6674	} /* for (both shader program object variants) */
6675
6676	if (m_to_id != 0)
6677	{
6678		gl.deleteTextures(1, &m_to_id);
6679
6680		m_to_id = 0;
6681	}
6682
6683	if (m_vao_id != 0)
6684	{
6685		gl.deleteVertexArrays(1, &m_vao_id);
6686
6687		m_vao_id = 0;
6688	}
6689
6690	/* Restore default GL_PATCH_VERTICES setting value */
6691	gl.patchParameteri(GL_PATCH_VERTICES, 3);
6692
6693	/* Restore default GL_PACK_ALIGNMENT setting value */
6694	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
6695}
6696
6697/** Retrieves body of a fragment shader that should be used for the test.
6698 *  The subroutine implementations are slightly changed, depending on the
6699 *  index of the shader, as specified by the caller.
6700 *
6701 *  @param n_id Index of the shader.
6702 *
6703 *  @return Requested string.
6704 **/
6705std::string FunctionalTest13::getFragmentShaderBody(unsigned int n_id)
6706{
6707	std::stringstream result_sstream;
6708
6709	/* Pre-amble */
6710	result_sstream << "#version 400\n"
6711					  "\n"
6712					  "#extension GL_ARB_shader_subroutine : require\n"
6713					  "\n"
6714					  /* Sub-routine */
6715					  "subroutine void SubroutineFSType(inout vec4 result);\n"
6716					  "\n"
6717					  "subroutine(SubroutineFSType) void SubroutineFS1(inout vec4 result)\n"
6718					  "{\n"
6719					  "    result += vec4("
6720				   << float(n_id + 1) / 10.0f << ", " << float(n_id + 2) / 10.0f << ", " << float(n_id + 3) / 10.0f
6721				   << ", " << float(n_id + 4) / 10.0f
6722				   << ");\n"
6723					  "}\n"
6724					  "subroutine(SubroutineFSType) void SubroutineFS2(inout vec4 result)\n"
6725					  "{\n"
6726					  "    result += vec4("
6727				   << float(n_id + 1) / 20.0f << ", " << float(n_id + 2) / 20.0f << ", " << float(n_id + 3) / 20.0f
6728				   << ", " << float(n_id + 4) / 20.0f << ");\n"
6729														 "}\n"
6730														 "\n"
6731														 "subroutine uniform SubroutineFSType function;\n"
6732														 "\n"
6733														 /* Input block */
6734														 "in GS_DATA\n"
6735														 "{\n"
6736														 "    vec4 data;\n"
6737														 "} in_gs;\n"
6738														 "\n"
6739														 "out vec4 result;\n"
6740														 /* main() declaration */
6741														 "void main()\n"
6742														 "{\n"
6743														 "    vec4 data = in_gs.data;\n"
6744														 "    function(data);\n"
6745														 "\n"
6746														 "    result = data;\n"
6747														 "}\n";
6748
6749	return result_sstream.str();
6750}
6751
6752/** Retrieves body of a geometry shader that should be used for the test.
6753 *  The subroutine implementations are slightly changed, depending on the
6754 *  index of the shader, as specified by the caller.
6755 *
6756 *  @param n_id Index of the shader.
6757 *
6758 *  @return Requested string.
6759 **/
6760std::string FunctionalTest13::getGeometryShaderBody(unsigned int n_id)
6761{
6762	std::stringstream result_sstream;
6763
6764	/* Pre-amble */
6765	result_sstream << "#version 400\n"
6766					  "\n"
6767					  "#extension GL_ARB_shader_subroutine : require\n"
6768					  "\n"
6769					  "layout(points)                           in;\n"
6770					  "layout(triangle_strip, max_vertices = 4) out;\n"
6771					  /* Sub-routine */
6772					  "subroutine void SubroutineGSType(inout vec4 result);\n"
6773					  "\n"
6774					  "subroutine(SubroutineGSType) void SubroutineGS1(inout vec4 result)\n"
6775					  "{\n"
6776					  "    result += vec4(0, 0, 0, "
6777				   << float(n_id + 1) * 0.425f << ");\n"
6778												  "}\n"
6779												  "subroutine(SubroutineGSType) void SubroutineGS2(inout vec4 result)\n"
6780												  "{\n"
6781												  "    result += vec4(0, 0, 0, "
6782				   << float(n_id + 1) * 0.0425f << ");\n"
6783												   "}\n"
6784												   "\n"
6785												   "subroutine uniform SubroutineGSType function;\n"
6786												   "\n"
6787												   /* Input block */
6788												   "in TE_DATA\n"
6789												   "{\n"
6790												   "    vec4 data;\n"
6791												   "} in_te[];\n"
6792												   "\n"
6793												   /* Output block */
6794												   "out GS_DATA\n"
6795												   "{\n"
6796												   "    vec4 data;\n"
6797												   "} out_gs;\n"
6798												   "\n"
6799												   "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6800												   "out gl_PerVertex { vec4 gl_Position; };\n"
6801												   /* main() declaration */
6802												   "void main()\n"
6803												   "{\n"
6804												   "    vec4 data = in_te[0].data;\n"
6805												   "\n"
6806												   "    function(data);\n"
6807												   "\n"
6808												   "    gl_Position = vec4(1, -1, 0, 1);\n"
6809												   "    out_gs.data = data;\n"
6810												   "    EmitVertex();\n"
6811												   "\n"
6812												   "    gl_Position = vec4(-1, -1, 0, 1);\n"
6813												   "    out_gs.data = data;\n"
6814												   "    EmitVertex();\n"
6815												   "\n"
6816												   "    gl_Position = vec4(1, 1, 0, 1);\n"
6817												   "    out_gs.data = data;\n"
6818												   "    EmitVertex();\n"
6819												   "\n"
6820												   "    gl_Position = vec4(-1, 1, 0, 1);\n"
6821												   "    out_gs.data = data;\n"
6822												   "    EmitVertex();\n"
6823												   "    EndPrimitive();\n"
6824												   "}\n";
6825
6826	return result_sstream.str();
6827}
6828
6829/** Retrieves body of a tessellation control shader that should be used for the test.
6830 *  The subroutine implementations are slightly changed, depending on the
6831 *  index of the shader, as specified by the caller.
6832 *
6833 *  @param n_id Index of the shader.
6834 *
6835 *  @return Requested string.
6836 **/
6837std::string FunctionalTest13::getTessellationControlShaderBody(unsigned int n_id)
6838{
6839	std::stringstream result_sstream;
6840
6841	/* Pre-amble */
6842	result_sstream << "#version 400\n"
6843					  "\n"
6844					  "#extension GL_ARB_shader_subroutine : require\n"
6845					  "\n"
6846					  "layout(vertices = 4) out;\n"
6847					  /* Sub-routine */
6848					  "subroutine void SubroutineTCType(inout vec4 result);\n"
6849					  "\n"
6850					  "subroutine(SubroutineTCType) void SubroutineTC1(inout vec4 result)\n"
6851					  "{\n"
6852					  "    result += vec4(0, "
6853				   << float(n_id + 1) * 0.25f << ", 0, 0);\n"
6854												 "}\n"
6855												 "subroutine(SubroutineTCType) void SubroutineTC2(inout vec4 result)\n"
6856												 "{\n"
6857												 "    result += vec4(0, "
6858				   << float(n_id + 1) * 0.025f
6859				   << ", 0, 0);\n"
6860					  "}\n"
6861					  "\n"
6862					  "subroutine uniform SubroutineTCType function;\n"
6863					  "\n"
6864					  /* Input block */
6865					  "in VS_DATA\n"
6866					  "{\n"
6867					  "    vec4 data;\n"
6868					  "} in_vs[];\n"
6869					  "\n"
6870					  /* Output block */
6871					  "out TC_DATA\n"
6872					  "{\n"
6873					  "    vec4 data;\n"
6874					  "} out_tc[];\n"
6875					  "\n"
6876					  "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6877					  "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"
6878					  /* main() declaration */
6879					  "void main()\n"
6880					  "{\n"
6881					  "    gl_TessLevelOuter[0]                = 1.0;\n"
6882					  "    gl_TessLevelOuter[1]                = 1.0;\n"
6883					  "    gl_TessLevelOuter[2]                = 1.0;\n"
6884					  "    gl_TessLevelOuter[3]                = 1.0;\n"
6885					  "    gl_TessLevelInner[0]                = 1.0;\n"
6886					  "    gl_TessLevelInner[1]                = 1.0;\n"
6887					  "    gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n"
6888					  "    out_tc[gl_InvocationID].data        = in_vs[0].data;\n"
6889					  "\n"
6890					  "    function(out_tc[gl_InvocationID].data);\n"
6891					  "}\n";
6892
6893	return result_sstream.str();
6894}
6895
6896/** Retrieves body of a tessellation evaluation shader that should be used for the test.
6897 *  The subroutine implementations are slightly changed, depending on the
6898 *  index of the shader, as specified by the caller.
6899 *
6900 *  @param n_id Index of the shader.
6901 *
6902 *  @return Requested string.
6903 **/
6904std::string FunctionalTest13::getTessellationEvaluationShaderBody(unsigned int n_id)
6905{
6906	std::stringstream result_sstream;
6907
6908	/* Pre-amble */
6909	result_sstream << "#version 400\n"
6910					  "\n"
6911					  "#extension GL_ARB_shader_subroutine : require\n"
6912					  "\n"
6913					  "layout(quads, point_mode) in;\n"
6914					  /* Sub-routine */
6915					  "subroutine void SubroutineTEType(inout vec4 result);\n"
6916					  "\n"
6917					  "subroutine(SubroutineTEType) void SubroutineTE1(inout vec4 result)\n"
6918					  "{\n"
6919					  "    result += vec4(0, 0, "
6920				   << float(n_id + 1) * 0.325f << ", 0);\n"
6921												  "}\n"
6922												  "subroutine(SubroutineTEType) void SubroutineTE2(inout vec4 result)\n"
6923												  "{\n"
6924												  "    result += vec4(0, 0, "
6925				   << float(n_id + 1) * 0.0325f << ", 0);\n"
6926												   "}\n"
6927												   "\n"
6928												   "subroutine uniform SubroutineTEType function;\n"
6929												   "\n"
6930												   /* Input block */
6931												   "in TC_DATA\n"
6932												   "{\n"
6933												   "    vec4 data;\n"
6934												   "} in_tc[];\n"
6935												   "\n"
6936												   /* Output block */
6937												   "out TE_DATA\n"
6938												   "{\n"
6939												   "    vec4 data;\n"
6940												   "} out_te;\n"
6941												   "\n"
6942												   "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6943												   "out gl_PerVertex { vec4 gl_Position; };\n"
6944												   /* main() declaration */
6945												   "void main()\n"
6946												   "{\n"
6947												   "    gl_Position = gl_in[0].gl_Position;\n"
6948												   "    out_te.data = in_tc[0].data;\n"
6949												   "\n"
6950												   "    function(out_te.data);\n"
6951												   "}\n";
6952
6953	return result_sstream.str();
6954}
6955
6956/** Retrieves body of a vertex shader that should be used for the test.
6957 *  The subroutine implementations are slightly changed, depending on the
6958 *  index of the shader, as specified by the caller.
6959 *
6960 *  @param n_id Index of the shader.
6961 *
6962 *  @return Requested string.
6963 **/
6964std::string FunctionalTest13::getVertexShaderBody(unsigned int n_id)
6965{
6966	std::stringstream result_sstream;
6967
6968	/* Pre-amble */
6969	result_sstream << "#version 400\n"
6970					  "\n"
6971					  "#extension GL_ARB_shader_subroutine : require\n"
6972					  "\n"
6973					  /* Sub-routine */
6974					  "subroutine void SubroutineVSType(inout vec4 result);\n"
6975					  "\n"
6976					  "subroutine(SubroutineVSType) void SubroutineVS1(inout vec4 result)\n"
6977					  "{\n"
6978					  "    result += vec4("
6979				   << float(n_id + 1) * 0.125f << ", 0, 0, 0);\n"
6980												  "}\n"
6981												  "subroutine(SubroutineVSType) void SubroutineVS2(inout vec4 result)\n"
6982												  "{\n"
6983												  "    result += vec4("
6984				   << float(n_id + 1) * 0.0125f << ", 0, 0, 0);\n"
6985												   "}\n"
6986												   "\n"
6987												   "subroutine uniform SubroutineVSType function;\n"
6988												   "\n"
6989												   /* Output block */
6990												   "out VS_DATA\n"
6991												   "{\n"
6992												   "    vec4 data;\n"
6993												   "} out_vs;\n"
6994												   "\n"
6995												   "out gl_PerVertex { vec4 gl_Position; };\n"
6996												   /* main() declaration */
6997												   "void main()\n"
6998												   "{\n"
6999												   "    gl_Position = vec4(0, 0, 0, 1);\n"
7000												   "    out_vs.data = vec4(0);\n"
7001												   "\n"
7002												   "    function(out_vs.data);\n"
7003												   "\n"
7004												   "}\n";
7005
7006	return result_sstream.str();
7007}
7008
7009/** Initializes all GL objects required to run the test. Also modifies a few
7010 *  GL states in order for the test to run correctly.
7011 **/
7012void FunctionalTest13::initTest()
7013{
7014	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7015
7016	/* Set up viewport */
7017	gl.viewport(0 /* x */, 0 /* y */, m_to_width, m_to_height);
7018	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
7019
7020	/* Make sure no program is used */
7021	gl.useProgram(0);
7022	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7023
7024	/* Generate a pipeline object */
7025	gl.genProgramPipelines(1, &m_pipeline_id);
7026	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
7027
7028	gl.bindProgramPipeline(m_pipeline_id);
7029	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
7030
7031	/* Initialize all shader programs */
7032	for (unsigned int n_id = 0; n_id < 2 /* variants for each shader type */; ++n_id)
7033	{
7034		std::string fs_body			= getFragmentShaderBody(n_id);
7035		const char* fs_body_raw_ptr = fs_body.c_str();
7036		std::string gs_body			= getGeometryShaderBody(n_id);
7037		const char* gs_body_raw_ptr = gs_body.c_str();
7038		std::string tc_body			= getTessellationControlShaderBody(n_id);
7039		const char* tc_body_raw_ptr = tc_body.c_str();
7040		std::string te_body			= getTessellationEvaluationShaderBody(n_id);
7041		const char* te_body_raw_ptr = te_body.c_str();
7042		std::string vs_body			= getVertexShaderBody(n_id);
7043		const char* vs_body_raw_ptr = vs_body.c_str();
7044
7045		m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr);
7046		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7047
7048		m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr);
7049		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7050
7051		m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr);
7052		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7053
7054		m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr);
7055		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7056
7057		m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr);
7058		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7059
7060		/* Verify that all shader program objects have been linked successfully */
7061		const glw::GLuint po_ids[] = {
7062			m_fs_po_ids[n_id], m_gs_po_ids[n_id], m_tc_po_ids[n_id], m_te_po_ids[n_id], m_vs_po_ids[n_id],
7063		};
7064		const unsigned int n_po_ids = sizeof(po_ids) / sizeof(po_ids[0]);
7065
7066		for (unsigned int n_po_id = 0; n_po_id < n_po_ids; ++n_po_id)
7067		{
7068			glw::GLint  link_status = GL_FALSE;
7069			glw::GLuint po_id		= po_ids[n_po_id];
7070
7071			gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
7072			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7073
7074			if (link_status != GL_TRUE)
7075			{
7076				TCU_FAIL("Shader program object linking failed.");
7077			}
7078		} /* for (all shader program objects) */
7079	}	 /* for (both shader program object variants) */
7080
7081	/* Generate a texture object. We will use the base mip-map as a render-target */
7082	gl.genTextures(1, &m_to_id);
7083	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
7084
7085	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
7086	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7087
7088	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA32F, m_to_width, m_to_height);
7089	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
7090
7091	/* Generate and configure a FBO we will use for the draw call */
7092	gl.genFramebuffers(1, &m_fbo_id);
7093	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
7094
7095	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
7096	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
7097
7098	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
7099	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
7100
7101	/* Generate & bind a VAO */
7102	gl.genVertexArrays(1, &m_vao_id);
7103	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7104
7105	gl.bindVertexArray(m_vao_id);
7106	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7107
7108	/* Set up tessellation */
7109	gl.patchParameteri(GL_PATCH_VERTICES, 1);
7110	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
7111
7112	/* Set up pixel storage alignment */
7113	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
7114	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
7115
7116	/* Allocate enough space to hold color attachment data */
7117	m_read_buffer = (unsigned char*)new float[m_to_width * m_to_height * 4 /* rgba */];
7118}
7119
7120/** Executes test iteration.
7121 *
7122 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7123 */
7124tcu::TestNode::IterateResult FunctionalTest13::iterate()
7125{
7126	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7127
7128	/* Do not execute the test if GL_ARB_shader_subroutine and GL_ARB_separate_shader_objects
7129	 * are not supported */
7130	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
7131	{
7132		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
7133	}
7134
7135	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
7136	{
7137		throw tcu::NotSupportedError("GL_ARB_separate_shader_objects is not supported");
7138	}
7139
7140	/* Initialize all GL objects before we continue */
7141	initTest();
7142
7143	/* Iterate over all possible FS/GS/TC/TE/VS permutations */
7144	for (int n_shader_permutation = 0; n_shader_permutation < 32 /* 2^5 */; ++n_shader_permutation)
7145	{
7146		const unsigned int n_fs_idx = ((n_shader_permutation & (1 << 0)) != 0) ? 1 : 0;
7147		const unsigned int n_gs_idx = ((n_shader_permutation & (1 << 1)) != 0) ? 1 : 0;
7148		const unsigned int n_tc_idx = ((n_shader_permutation & (1 << 2)) != 0) ? 1 : 0;
7149		const unsigned int n_te_idx = ((n_shader_permutation & (1 << 3)) != 0) ? 1 : 0;
7150		const unsigned int n_vs_idx = ((n_shader_permutation & (1 << 4)) != 0) ? 1 : 0;
7151		const unsigned int fs_po_id = m_fs_po_ids[n_fs_idx];
7152		const unsigned int gs_po_id = m_gs_po_ids[n_gs_idx];
7153		const unsigned int tc_po_id = m_tc_po_ids[n_tc_idx];
7154		const unsigned int te_po_id = m_te_po_ids[n_te_idx];
7155		const unsigned int vs_po_id = m_vs_po_ids[n_vs_idx];
7156
7157		/* Configure fragment shader stage */
7158		gl.useProgramStages(m_pipeline_id, GL_FRAGMENT_SHADER_BIT, fs_po_id);
7159		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_FRAGMENT_SHADER_BIT bit");
7160
7161		/* Configure geometry shader stage */
7162		gl.useProgramStages(m_pipeline_id, GL_GEOMETRY_SHADER_BIT, gs_po_id);
7163		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_GEOMETRY_SHADER_BIT bit");
7164
7165		/* Configure tessellation control shader stage */
7166		gl.useProgramStages(m_pipeline_id, GL_TESS_CONTROL_SHADER_BIT, tc_po_id);
7167		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_CONTROL_SHADER_BIT bit");
7168
7169		/* Configure tessellation evaluation shader stage */
7170		gl.useProgramStages(m_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT, te_po_id);
7171		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_EVALUATION_SHADER_BIT bit");
7172
7173		/* Configure vertex shader stage */
7174		gl.useProgramStages(m_pipeline_id, GL_VERTEX_SHADER_BIT, vs_po_id);
7175		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_VERTEX_SHADER_BIT bit");
7176
7177		/* Validate the pipeline */
7178		glw::GLint validate_status = GL_FALSE;
7179
7180		gl.validateProgramPipeline(m_pipeline_id);
7181		GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed.");
7182
7183		gl.getProgramPipelineiv(m_pipeline_id, GL_VALIDATE_STATUS, &validate_status);
7184		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed.");
7185
7186		if (validate_status != GL_TRUE)
7187		{
7188			TCU_FAIL("Program pipeline has not been validated successfully.");
7189		}
7190
7191		/* Retrieve subroutine indices */
7192		GLuint fs_subroutine_indices[2]	= { (GLuint)-1 };
7193		GLint  fs_subroutine_uniform_index = 0;
7194		GLuint gs_subroutine_indices[2]	= { (GLuint)-1 };
7195		GLint  gs_subroutine_uniform_index = 0;
7196		GLuint tc_subroutine_indices[2]	= { (GLuint)-1 };
7197		GLint  tc_subroutine_uniform_index = 0;
7198		GLuint te_subroutine_indices[2]	= { (GLuint)-1 };
7199		GLint  te_subroutine_uniform_index = 0;
7200		GLuint vs_subroutine_indices[2]	= { (GLuint)-1 };
7201		GLint  vs_subroutine_uniform_index = 0;
7202
7203		for (unsigned int n_subroutine = 0; n_subroutine < 2; ++n_subroutine)
7204		{
7205			std::stringstream fs_subroutine_name_sstream;
7206			std::stringstream gs_subroutine_name_sstream;
7207			std::stringstream tc_subroutine_name_sstream;
7208			std::stringstream te_subroutine_name_sstream;
7209			std::stringstream vs_subroutine_name_sstream;
7210
7211			fs_subroutine_name_sstream << "SubroutineFS" << (n_subroutine + 1);
7212			gs_subroutine_name_sstream << "SubroutineGS" << (n_subroutine + 1);
7213			tc_subroutine_name_sstream << "SubroutineTC" << (n_subroutine + 1);
7214			te_subroutine_name_sstream << "SubroutineTE" << (n_subroutine + 1);
7215			vs_subroutine_name_sstream << "SubroutineVS" << (n_subroutine + 1);
7216
7217			fs_subroutine_indices[n_subroutine] =
7218				gl.getSubroutineIndex(fs_po_id, GL_FRAGMENT_SHADER, fs_subroutine_name_sstream.str().c_str());
7219			gs_subroutine_indices[n_subroutine] =
7220				gl.getSubroutineIndex(gs_po_id, GL_GEOMETRY_SHADER, gs_subroutine_name_sstream.str().c_str());
7221			tc_subroutine_indices[n_subroutine] =
7222				gl.getSubroutineIndex(tc_po_id, GL_TESS_CONTROL_SHADER, tc_subroutine_name_sstream.str().c_str());
7223			te_subroutine_indices[n_subroutine] =
7224				gl.getSubroutineIndex(te_po_id, GL_TESS_EVALUATION_SHADER, te_subroutine_name_sstream.str().c_str());
7225			vs_subroutine_indices[n_subroutine] =
7226				gl.getSubroutineIndex(vs_po_id, GL_VERTEX_SHADER, vs_subroutine_name_sstream.str().c_str());
7227			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
7228
7229			if (fs_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7230				gs_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7231				tc_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7232				te_subroutine_indices[n_subroutine] == (GLuint)-1 || vs_subroutine_indices[n_subroutine] == (GLuint)-1)
7233			{
7234				m_testCtx.getLog() << tcu::TestLog::Message
7235								   << "At least one subroutine was not recognized by glGetSubroutineIndex() call. "
7236									  "(fs:"
7237								   << fs_subroutine_indices[n_subroutine]
7238								   << ", gs:" << gs_subroutine_indices[n_subroutine]
7239								   << ", tc:" << tc_subroutine_indices[n_subroutine]
7240								   << ", te:" << te_subroutine_indices[n_subroutine]
7241								   << ", vs:" << vs_subroutine_indices[n_subroutine] << ")."
7242								   << tcu::TestLog::EndMessage;
7243
7244				TCU_FAIL("At least one subroutine was not recognized");
7245			}
7246		} /* for (both subroutines) */
7247
7248		/* Retrieve subroutine uniform indices */
7249		fs_subroutine_uniform_index = gl.getSubroutineUniformLocation(fs_po_id, GL_FRAGMENT_SHADER, "function");
7250		gs_subroutine_uniform_index = gl.getSubroutineUniformLocation(gs_po_id, GL_GEOMETRY_SHADER, "function");
7251		tc_subroutine_uniform_index = gl.getSubroutineUniformLocation(tc_po_id, GL_TESS_CONTROL_SHADER, "function");
7252		te_subroutine_uniform_index = gl.getSubroutineUniformLocation(te_po_id, GL_TESS_EVALUATION_SHADER, "function");
7253		vs_subroutine_uniform_index = gl.getSubroutineUniformLocation(vs_po_id, GL_VERTEX_SHADER, "function");
7254
7255		if (fs_subroutine_uniform_index == -1 || gs_subroutine_uniform_index == -1 ||
7256			tc_subroutine_uniform_index == -1 || te_subroutine_uniform_index == -1 || vs_subroutine_uniform_index == -1)
7257		{
7258			m_testCtx.getLog() << tcu::TestLog::Message << "At least one subroutine uniform is considered inactive by "
7259														   "glGetSubroutineUniformLocation ("
7260														   "fs:"
7261							   << fs_subroutine_uniform_index << ", gs:" << gs_subroutine_uniform_index
7262							   << ", tc:" << tc_subroutine_uniform_index << ", te:" << te_subroutine_uniform_index
7263							   << ", vs:" << vs_subroutine_uniform_index << ")." << tcu::TestLog::EndMessage;
7264
7265			TCU_FAIL("At least one subroutine uniform is considered inactive");
7266		}
7267
7268		/* Check if both subroutines work correctly in each stage */
7269		for (int n_subroutine_permutation = 0; n_subroutine_permutation < 32; /* 2^5 */
7270			 ++n_subroutine_permutation)
7271		{
7272			unsigned int n_fs_subroutine = ((n_subroutine_permutation & (1 << 0)) != 0) ? 1 : 0;
7273			unsigned int n_gs_subroutine = ((n_subroutine_permutation & (1 << 1)) != 0) ? 1 : 0;
7274			unsigned int n_tc_subroutine = ((n_subroutine_permutation & (1 << 2)) != 0) ? 1 : 0;
7275			unsigned int n_te_subroutine = ((n_subroutine_permutation & (1 << 3)) != 0) ? 1 : 0;
7276			unsigned int n_vs_subroutine = ((n_subroutine_permutation & (1 << 4)) != 0) ? 1 : 0;
7277
7278			/* Configure subroutine uniforms */
7279			struct
7280			{
7281				glw::GLenum  stage;
7282				glw::GLuint  po_id;
7283				glw::GLuint* indices;
7284			} configurations[] = {
7285				{ GL_FRAGMENT_SHADER, fs_po_id, fs_subroutine_indices + n_fs_subroutine },
7286				{ GL_GEOMETRY_SHADER, gs_po_id, gs_subroutine_indices + n_gs_subroutine },
7287				{ GL_TESS_CONTROL_SHADER, tc_po_id, tc_subroutine_indices + n_tc_subroutine },
7288				{ GL_TESS_EVALUATION_SHADER, te_po_id, te_subroutine_indices + n_te_subroutine },
7289				{ GL_VERTEX_SHADER, vs_po_id, vs_subroutine_indices + n_vs_subroutine },
7290			};
7291
7292			for (int i = 0; i < 5; ++i)
7293			{
7294				gl.activeShaderProgram(m_pipeline_id, configurations[i].po_id);
7295				GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveShaderProgram() call failed.");
7296
7297				gl.uniformSubroutinesuiv(configurations[i].stage, 1 /* count */, configurations[i].indices);
7298				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
7299			}
7300
7301			/* Render a full-screen quad with the pipeline */
7302			gl.clear(GL_COLOR_BUFFER_BIT);
7303			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
7304
7305			gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
7306			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7307
7308			/* Read color attachment's contents */
7309			gl.readPixels(0, /* x */
7310						  0, /* y */
7311						  m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_read_buffer);
7312			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
7313
7314			/* Verify the contents */
7315			verifyReadBuffer(n_fs_idx, n_fs_subroutine, n_gs_idx, n_gs_subroutine, n_tc_idx, n_tc_subroutine, n_te_idx,
7316							 n_te_subroutine, n_vs_idx, n_vs_subroutine);
7317		} /* for (all subroutine permutations) */
7318	}	 /* for (all program shader object permutations) */
7319
7320	/** All done */
7321	if (m_has_test_passed)
7322	{
7323		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7324	}
7325	else
7326	{
7327		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7328	}
7329
7330	return STOP;
7331}
7332
7333/** Verifies the data that have been rendered using a pipeline object.
7334 *  Contents of the data depends on indices of the shaders, as well as
7335 *  on the subroutines that have been activated for particular iteration.
7336 *
7337 *  @param n_fs_id         Index of the fragment shader used for the iteration;
7338 *  @param n_fs_subroutine Index of the subroutine used in the fragment shader
7339 *                         for the iteration;
7340 *  @param n_gs_id         Index of the geometry shader used for the iteration;
7341 *  @param n_gs_subroutine Index of the subroutine used in the geometry shader
7342 *                         for the iteration;
7343 *  @param n_tc_id         Index of the tessellation control shader used for the iteration;
7344 *  @param n_tc_subroutine Index of the subroutine used in the tessellation control
7345 *                         shader for the iteration;
7346 *  @param n_te_id         Index of the tessellation evaluation shader used for the iteration;
7347 *  @param n_te_subroutine Index of the subroutine used in the tessellation evaluation
7348 *                         shader for the iteration;
7349 *  @param n_vs_id         Index of the vertex shader used for the iteration;
7350 *  @param n_vs_subroutine Index of the subroutine used in the vertex shader for
7351 *                         the iteration.
7352 */
7353void FunctionalTest13::verifyReadBuffer(unsigned int n_fs_id, unsigned int n_fs_subroutine, unsigned int n_gs_id,
7354										unsigned int n_gs_subroutine, unsigned int n_tc_id,
7355										unsigned int n_tc_subroutine, unsigned int n_te_id,
7356										unsigned int n_te_subroutine, unsigned int n_vs_id,
7357										unsigned int n_vs_subroutine)
7358{
7359	float expected_color[4] = { 0 };
7360	float fs_modifier[4]	= { 0 };
7361	float gs_modifier[4]	= { 0 };
7362	float tc_modifier[4]	= { 0 };
7363	float te_modifier[4]	= { 0 };
7364	float vs_modifier[4]	= { 0 };
7365
7366	if (n_fs_subroutine == 0)
7367	{
7368		for (unsigned int n_component = 0; n_component < 4; ++n_component)
7369		{
7370			fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 10.0f;
7371		}
7372	}
7373	else
7374	{
7375		for (unsigned int n_component = 0; n_component < 4; ++n_component)
7376		{
7377			fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 20.0f;
7378		}
7379	}
7380
7381	if (n_gs_subroutine == 0)
7382	{
7383		gs_modifier[3] = float(n_gs_id + 1) * 0.425f;
7384	}
7385	else
7386	{
7387		gs_modifier[3] = float(n_gs_id + 1) * 0.0425f;
7388	}
7389
7390	if (n_tc_subroutine == 0)
7391	{
7392		tc_modifier[1] = float(n_tc_id + 1) * 0.25f;
7393	}
7394	else
7395	{
7396		tc_modifier[1] = float(n_tc_id + 1) * 0.025f;
7397	}
7398
7399	if (n_te_subroutine == 0)
7400	{
7401		te_modifier[2] = float(n_te_id + 1) * 0.325f;
7402	}
7403	else
7404	{
7405		te_modifier[2] = float(n_te_id + 1) * 0.0325f;
7406	}
7407
7408	if (n_vs_subroutine == 0)
7409	{
7410		vs_modifier[0] = float(n_vs_id + 1) * 0.125f;
7411	}
7412	else
7413	{
7414		vs_modifier[0] = float(n_vs_id + 1) * 0.0125f;
7415	}
7416
7417	/* Determine the expected color */
7418	for (unsigned int n_component = 0; n_component < 4 /* rgba */; ++n_component)
7419	{
7420		expected_color[n_component] = fs_modifier[n_component] + gs_modifier[n_component] + tc_modifier[n_component] +
7421									  te_modifier[n_component] + vs_modifier[n_component];
7422	}
7423
7424	/* Verify all read texels are valid */
7425	const float epsilon			= 1e-5f;
7426	bool		should_continue = true;
7427
7428	for (unsigned int y = 0; y < m_to_height && should_continue; ++y)
7429	{
7430		const float* row_ptr = (const float*)m_read_buffer + y * m_to_width * 4; /* rgba */
7431
7432		for (unsigned int x = 0; x < m_to_width && should_continue; ++x)
7433		{
7434			const float* texel_ptr = row_ptr + x * 4; /* rgba */
7435
7436			if (de::abs(texel_ptr[0] - expected_color[0]) > epsilon ||
7437				de::abs(texel_ptr[1] - expected_color[1]) > epsilon ||
7438				de::abs(texel_ptr[2] - expected_color[2]) > epsilon ||
7439				de::abs(texel_ptr[3] - expected_color[3]) > epsilon)
7440			{
7441				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel rendered at (" << x << ", " << y
7442								   << ") for "
7443									  "the following configuration: "
7444									  "n_fs_id:"
7445								   << n_fs_id << " n_fs_subroutine:" << n_fs_subroutine << " n_gs_id:" << n_gs_id
7446								   << " n_gs_subroutine:" << n_gs_subroutine << " n_tc_id:" << n_tc_id
7447								   << " n_tc_subroutine:" << n_tc_subroutine << " n_te_id:" << n_te_id
7448								   << " n_te_subroutine:" << n_te_subroutine << " n_vs_id:" << n_vs_id
7449								   << " n_vs_subroutine:" << n_vs_subroutine << "; expected:"
7450																				"("
7451								   << expected_color[0] << ", " << expected_color[1] << ", " << expected_color[2]
7452								   << ", " << expected_color[3] << "), found:"
7453																   "("
7454								   << texel_ptr[0] << ", " << texel_ptr[1] << ", " << texel_ptr[2] << ", "
7455								   << texel_ptr[3] << ")." << tcu::TestLog::EndMessage;
7456
7457				m_has_test_passed = false;
7458				should_continue   = false;
7459			}
7460		} /* for (all columns) */
7461	}	 /* for (all rows) */
7462}
7463
7464/** Constructor
7465 *
7466 * @param context CTS context
7467 **/
7468FunctionalTest14_15::FunctionalTest14_15(deqp::Context& context)
7469	: TestCase(context, "structure_parameters_program_binary", "Verify structures can be used as parameters")
7470	, m_uniform_location(0)
7471{
7472}
7473
7474/** Execute test
7475 *
7476 * @return tcu::TestNode::STOP
7477 **/
7478tcu::TestNode::IterateResult FunctionalTest14_15::iterate()
7479{
7480	static const GLchar* vertex_shader_code =
7481		"#version 400 core\n"
7482		"#extension GL_ARB_shader_subroutine : require\n"
7483		"\n"
7484		"precision highp float;\n"
7485		"\n"
7486		"struct data\n"
7487		"{\n"
7488		"    uint r;\n"
7489		"    uint g;\n"
7490		"    uint b;\n"
7491		"    uint a;\n"
7492		"};\n"
7493		"\n"
7494		"subroutine void routine_type_1(in data iparam, out data oparam);\n"
7495		"subroutine void routine_type_2(inout data arg);\n"
7496		"\n"
7497		"subroutine (routine_type_1) void invert(in data iparam, out data oparam)\n"
7498		"{\n"
7499		"    oparam.r = iparam.a;\n"
7500		"    oparam.g = iparam.b;\n"
7501		"    oparam.b = iparam.g;\n"
7502		"    oparam.a = iparam.r;\n"
7503		"}\n"
7504		"\n"
7505		"subroutine (routine_type_1) void increment(in data iparam, out data oparam)\n"
7506		"{\n"
7507		"    oparam.r = 1 + iparam.r;\n"
7508		"    oparam.g = 1 + iparam.g;\n"
7509		"    oparam.b = 1 + iparam.b;\n"
7510		"    oparam.a = 1 + iparam.a;\n"
7511		"}\n"
7512		"\n"
7513		"subroutine (routine_type_2) void div_by_2(inout data arg)\n"
7514		"{\n"
7515		"    arg.r = arg.r / 2;\n"
7516		"    arg.g = arg.g / 2;\n"
7517		"    arg.b = arg.b / 2;\n"
7518		"    arg.a = arg.a / 2;\n"
7519		"}\n"
7520		"\n"
7521		"subroutine (routine_type_2) void decrement(inout data arg)\n"
7522		"{\n"
7523		"    arg.r = arg.r - 1;\n"
7524		"    arg.g = arg.g - 1;\n"
7525		"    arg.b = arg.b - 1;\n"
7526		"    arg.a = arg.a - 1;\n"
7527		"}\n"
7528		"\n"
7529		"subroutine uniform routine_type_1 routine_1;\n"
7530		"subroutine uniform routine_type_2 routine_2;\n"
7531		"\n"
7532		"uniform uvec4 uni_input;\n"
7533		"\n"
7534		"out uvec4 out_routine_1;\n"
7535		"out uvec4 out_routine_2;\n"
7536		"\n"
7537		"\n"
7538		"void main()\n"
7539		"{\n"
7540		"    data routine_1_input;\n"
7541		"    data routine_1_output;\n"
7542		"    data routine_2_arg;\n"
7543		"\n"
7544		"    routine_1_input.r = uni_input.r;\n"
7545		"    routine_1_input.g = uni_input.g;\n"
7546		"    routine_1_input.b = uni_input.b;\n"
7547		"    routine_1_input.a = uni_input.a;\n"
7548		"\n"
7549		"    routine_2_arg.r = uni_input.r;\n"
7550		"    routine_2_arg.g = uni_input.g;\n"
7551		"    routine_2_arg.b = uni_input.b;\n"
7552		"    routine_2_arg.a = uni_input.a;\n"
7553		"\n"
7554		"    routine_1(routine_1_input, routine_1_output);\n"
7555		"    routine_2(routine_2_arg);\n"
7556		"\n"
7557		"    out_routine_1.r = routine_1_output.r;\n"
7558		"    out_routine_1.g = routine_1_output.g;\n"
7559		"    out_routine_1.b = routine_1_output.b;\n"
7560		"    out_routine_1.a = routine_1_output.a;\n"
7561		"\n"
7562		"    out_routine_2.r = routine_2_arg.r;\n"
7563		"    out_routine_2.g = routine_2_arg.g;\n"
7564		"    out_routine_2.b = routine_2_arg.b;\n"
7565		"    out_routine_2.a = routine_2_arg.a;\n"
7566		"}\n"
7567		"\n";
7568
7569	static const GLchar* subroutine_names[][2] = { { "invert", "increment" }, { "div_by_2", "decrement" } };
7570	static const GLuint  n_subroutine_types	= sizeof(subroutine_names) / sizeof(subroutine_names[0]);
7571
7572	static const GLchar* subroutine_uniform_names[] = { "routine_1", "routine_2" };
7573	static const GLuint  n_subroutine_uniform_names =
7574		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
7575
7576	static const GLchar* uniform_name	= "uni_input";
7577	static const GLchar* varying_names[] = { "out_routine_1", "out_routine_2" };
7578
7579	static const GLuint n_varying_names				   = sizeof(varying_names) / sizeof(varying_names[0]);
7580	static const GLuint transform_feedback_buffer_size = n_varying_names * 4 * sizeof(GLuint);
7581
7582	/* Test data */
7583	static const Utils::vec4<GLuint> uni_input[] = { Utils::vec4<GLuint>(8, 64, 4096, 16777216),
7584													 Utils::vec4<GLuint>(8, 64, 4096, 16777216) };
7585
7586	static const Utils::vec4<GLuint> out_routine_1[] = { Utils::vec4<GLuint>(16777216, 4096, 64, 8),
7587														 Utils::vec4<GLuint>(9, 65, 4097, 16777217) };
7588
7589	static const Utils::vec4<GLuint> out_routine_2[] = { Utils::vec4<GLuint>(4, 32, 2048, 8388608),
7590														 Utils::vec4<GLuint>(7, 63, 4095, 16777215) };
7591
7592	static const GLuint n_test_cases = 2;
7593
7594	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
7595	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
7596	{
7597		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
7598	}
7599
7600	/* GL objects */
7601	Utils::program	 program(m_context);
7602	Utils::buffer	  transform_feedback_buffer(m_context);
7603	Utils::vertexArray vao(m_context);
7604
7605	bool is_program_binary_supported = program.isProgramBinarySupported();
7606
7607	/* Init GL objects */
7608	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code,
7609				  varying_names /* varying_names */, n_varying_names /* n_varyings */);
7610
7611	/* Do not execute the test if GL_ARB_get_program_binary is not supported */
7612	if (true == is_program_binary_supported)
7613	{
7614		/* Get subroutine indices */
7615		for (GLuint type = 0; type < n_subroutine_types; ++type)
7616		{
7617			m_initial_subroutine_indices[type][0] =
7618				program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER);
7619
7620			m_initial_subroutine_indices[type][1] =
7621				program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER);
7622		}
7623
7624		/* Get subroutine uniform locations */
7625		for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7626		{
7627			m_initial_subroutine_uniform_locations[uniform] =
7628				program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
7629		}
7630
7631		/* Delete program and recreate it from binary */
7632		std::vector<GLubyte> program_binary;
7633		GLenum				 binary_format;
7634
7635		program.getBinary(program_binary, binary_format);
7636		program.remove();
7637		program.createFromBinary(program_binary, binary_format);
7638	}
7639
7640	program.use();
7641
7642	vao.generate();
7643	vao.bind();
7644
7645	transform_feedback_buffer.generate();
7646	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
7647									 GL_DYNAMIC_COPY);
7648	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
7649
7650	/* Get subroutine indices */
7651	for (GLuint type = 0; type < n_subroutine_types; ++type)
7652	{
7653		m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER);
7654		m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER);
7655	}
7656
7657	/* Get subroutine uniform locations */
7658	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7659	{
7660		m_subroutine_uniform_locations[uniform] =
7661			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
7662	}
7663
7664	/* Get uniform locations */
7665	m_uniform_location = program.getUniformLocation(uniform_name);
7666
7667	/* Test */
7668	bool result = true;
7669
7670	/* Test program binary */
7671	if (true == is_program_binary_supported)
7672	{
7673		/* Test indices and locations */
7674		if (false == testIndicesAndLocations())
7675		{
7676			static const GLuint n_subroutines_per_type = 2;
7677
7678			m_context.getTestContext().getLog() << tcu::TestLog::Message
7679												<< "Error. Subroutine indices or subroutine uniform location changed."
7680												<< tcu::TestLog::EndMessage;
7681
7682			for (GLuint type = 0; type < n_subroutine_types; ++type)
7683			{
7684				for (GLuint i = 0; i < n_subroutines_per_type; ++i)
7685				{
7686					m_context.getTestContext().getLog()
7687						<< tcu::TestLog::Message << "Subroutine: " << subroutine_names[type][i]
7688						<< " index: " << m_subroutine_indices[type][i]
7689						<< " initial index: " << m_initial_subroutine_indices[type][i] << tcu::TestLog::EndMessage;
7690				}
7691			}
7692
7693			for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7694			{
7695				m_context.getTestContext().getLog()
7696					<< tcu::TestLog::Message << "Subroutine uniform: " << subroutine_uniform_names[uniform]
7697					<< " location: " << m_subroutine_uniform_locations[uniform]
7698					<< " initial location: " << m_initial_subroutine_uniform_locations[uniform]
7699					<< tcu::TestLog::EndMessage;
7700			}
7701
7702			result = false;
7703		}
7704
7705		/* Test draw with deafult set of subroutines */
7706		if (false == testDefaultSubroutineSet(uni_input[0], out_routine_1, out_routine_2))
7707		{
7708			result = false;
7709		}
7710	}
7711
7712	for (GLuint i = 0; i < n_test_cases; ++i)
7713	{
7714		if (false == testDraw(i, uni_input[i], out_routine_1[i], out_routine_2[i]))
7715		{
7716			result = false;
7717		}
7718	}
7719
7720	/* Set result */
7721	if (true == result)
7722	{
7723		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7724	}
7725	else
7726	{
7727		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7728	}
7729
7730	/* Done */
7731	return tcu::TestNode::STOP;
7732}
7733
7734/** Execute draw call and verify results
7735 *
7736 * @param uni_input                 Input data
7737 * @param expected_routine_1_result Set of expected results of "routine_1"
7738 * @param expected_routine_2_result Set of expected results of "routine_2"
7739 *
7740 * @return true if test pass, false otherwise
7741 **/
7742bool FunctionalTest14_15::testDefaultSubroutineSet(const Utils::vec4<glw::GLuint>& uni_input,
7743												   const Utils::vec4<glw::GLuint>  expected_routine_1_result[2],
7744												   const Utils::vec4<glw::GLuint>  expected_routine_2_result[2]) const
7745{
7746	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
7747	bool				  result = true;
7748
7749	/* Set up input data uniforms */
7750	gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w);
7751	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
7752
7753	/* Execute draw call with transform feedback */
7754	gl.beginTransformFeedback(GL_POINTS);
7755	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
7756
7757	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
7758	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
7759
7760	gl.endTransformFeedback();
7761	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
7762
7763	/* Capture results */
7764	GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7765	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
7766
7767	Utils::vec4<GLuint> routine_1_result;
7768	Utils::vec4<GLuint> routine_2_result;
7769
7770	routine_1_result.m_x = feedback_data[0 + 0];
7771	routine_1_result.m_y = feedback_data[0 + 1];
7772	routine_1_result.m_z = feedback_data[0 + 2];
7773	routine_1_result.m_w = feedback_data[0 + 3];
7774
7775	routine_2_result.m_x = feedback_data[4 + 0];
7776	routine_2_result.m_y = feedback_data[4 + 1];
7777	routine_2_result.m_z = feedback_data[4 + 2];
7778	routine_2_result.m_w = feedback_data[4 + 3];
7779
7780	/* Unmap buffer */
7781	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7782	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
7783
7784	/* Verifiy */
7785	result = result &&
7786			 ((routine_1_result == expected_routine_1_result[0]) || (routine_1_result == expected_routine_1_result[1]));
7787
7788	result = result &&
7789			 ((routine_2_result == expected_routine_2_result[0]) || (routine_2_result == expected_routine_2_result[1]));
7790
7791	/* Log error if any */
7792	if (false == result)
7793	{
7794		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
7795											<< tcu::TestLog::EndMessage;
7796
7797		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
7798
7799		message << "Routine_1, result: ";
7800
7801		routine_1_result.log(message);
7802
7803		message << "Routine_2, result: ";
7804
7805		routine_2_result.log(message);
7806
7807		message << tcu::TestLog::EndMessage;
7808	}
7809
7810	/* Done */
7811	return result;
7812}
7813
7814/** Execute draw call and verify results
7815 *
7816 * @param routine_configuration     Subroutine "type" ordinal
7817 * @param uni_input                 Input data
7818 * @param expected_routine_1_result Expected results of "routine_1"
7819 * @param expected_routine_2_result Expected results of "routine_2"
7820 *
7821 * @return true if test pass, false otherwise
7822 **/
7823bool FunctionalTest14_15::testDraw(glw::GLuint routine_configuration, const Utils::vec4<glw::GLuint>& uni_input,
7824								   const Utils::vec4<glw::GLuint>& expected_routine_1_result,
7825								   const Utils::vec4<glw::GLuint>& expected_routine_2_result) const
7826{
7827	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
7828	bool				  result = true;
7829	GLuint				  subroutine_indices[2];
7830	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
7831
7832	/* Set up input data uniforms */
7833	gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w);
7834	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
7835
7836	/* Prepare subroutine uniform data */
7837	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
7838	{
7839		const GLuint location = m_subroutine_uniform_locations[i];
7840
7841		subroutine_indices[location] = m_subroutine_indices[i][routine_configuration];
7842	}
7843
7844	/* Set up subroutine uniforms */
7845	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
7846	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
7847
7848	/* Execute draw call with transform feedback */
7849	gl.beginTransformFeedback(GL_POINTS);
7850	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
7851
7852	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
7853	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
7854
7855	gl.endTransformFeedback();
7856	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
7857
7858	/* Capture results */
7859	GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7860	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
7861
7862	Utils::vec4<GLuint> routine_1_result;
7863	Utils::vec4<GLuint> routine_2_result;
7864
7865	routine_1_result.m_x = feedback_data[0 + 0];
7866	routine_1_result.m_y = feedback_data[0 + 1];
7867	routine_1_result.m_z = feedback_data[0 + 2];
7868	routine_1_result.m_w = feedback_data[0 + 3];
7869
7870	routine_2_result.m_x = feedback_data[4 + 0];
7871	routine_2_result.m_y = feedback_data[4 + 1];
7872	routine_2_result.m_z = feedback_data[4 + 2];
7873	routine_2_result.m_w = feedback_data[4 + 3];
7874
7875	/* Unmap buffer */
7876	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7877	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
7878
7879	/* Verifiy */
7880	result = result && (routine_1_result == expected_routine_1_result);
7881	result = result && (routine_2_result == expected_routine_2_result);
7882
7883	/* Log error if any */
7884	if (false == result)
7885	{
7886		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
7887											<< tcu::TestLog::EndMessage;
7888
7889		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
7890
7891		message << "Routine_1, result: ";
7892
7893		routine_1_result.log(message);
7894
7895		message << ", expected: ";
7896
7897		expected_routine_1_result.log(message);
7898
7899		message << "Routine_2, result: ";
7900
7901		routine_2_result.log(message);
7902
7903		message << ", expected: ";
7904
7905		expected_routine_2_result.log(message);
7906
7907		message << tcu::TestLog::EndMessage;
7908	}
7909
7910	/* Done */
7911	return result;
7912}
7913
7914/** Verify initial and current values of subroutine indices and subroutines uniform locations
7915 *
7916 * @return true if test pass, false otherwise
7917 **/
7918bool FunctionalTest14_15::testIndicesAndLocations() const
7919{
7920	static const GLuint n_subroutine_types = 2;
7921	bool				result			   = true;
7922
7923	/* Verify subroutine indices */
7924	for (GLuint type = 0; type < n_subroutine_types; ++type)
7925	{
7926		result = result && (m_subroutine_indices[type][0] == m_initial_subroutine_indices[type][0]);
7927		result = result && (m_subroutine_indices[type][1] == m_initial_subroutine_indices[type][1]);
7928	}
7929
7930	/* Verify subroutine uniform locations */
7931	for (GLuint uniform = 0; uniform < n_subroutine_types; ++uniform)
7932	{
7933		result = result && (m_subroutine_uniform_locations[uniform] == m_initial_subroutine_uniform_locations[uniform]);
7934	}
7935
7936	return result;
7937}
7938
7939/** Constructor.
7940 *
7941 *  @param context Rendering context.
7942 *
7943 **/
7944FunctionalTest16::FunctionalTest16(deqp::Context& context)
7945	: TestCase(context, "subroutine_uniform_reset",
7946			   "Checks that when the active program for a shader stage is re-linke or "
7947			   "changed by a call to UseProgram, BindProgramPipeline, or UseProgramStages,"
7948			   " subroutine uniforms for that stage are reset to arbitrarily chosen default "
7949			   "functions with compatible subroutine types.")
7950	, m_are_pipeline_objects_supported(false)
7951	, m_has_test_passed(true)
7952{
7953	memset(m_fs_ids, 0, sizeof(m_fs_ids));
7954	memset(m_gs_ids, 0, sizeof(m_gs_ids));
7955	memset(m_po_ids, 0, sizeof(m_po_ids));
7956	memset(m_tc_ids, 0, sizeof(m_tc_ids));
7957	memset(m_te_ids, 0, sizeof(m_te_ids));
7958	memset(m_vs_ids, 0, sizeof(m_vs_ids));
7959
7960	memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids));
7961	memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids));
7962	memset(m_pipeline_object_ids, 0, sizeof(m_pipeline_object_ids));
7963	memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids));
7964	memset(m_te_po_ids, 0, sizeof(m_te_po_ids));
7965	memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids));
7966}
7967
7968/** Deinitializes all GL objects that may have been created during test execution. */
7969void FunctionalTest16::deinit()
7970{
7971	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7972
7973	for (unsigned int n_id = 0; n_id < 2; ++n_id)
7974	{
7975		if (m_fs_ids[n_id] != 0)
7976		{
7977			gl.deleteShader(m_fs_ids[n_id]);
7978
7979			m_fs_ids[n_id] = 0;
7980		}
7981
7982		if (m_fs_po_ids[n_id] != 0)
7983		{
7984			gl.deleteProgram(m_fs_po_ids[n_id]);
7985
7986			m_fs_po_ids[n_id] = 0;
7987		}
7988
7989		if (m_gs_ids[n_id] != 0)
7990		{
7991			gl.deleteShader(m_gs_ids[n_id]);
7992
7993			m_gs_ids[n_id] = 0;
7994		}
7995
7996		if (m_gs_po_ids[n_id] != 0)
7997		{
7998			gl.deleteProgram(m_gs_po_ids[n_id]);
7999
8000			m_gs_po_ids[n_id] = 0;
8001		}
8002
8003		if (m_pipeline_object_ids[n_id] != 0)
8004		{
8005			gl.deleteProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id);
8006		}
8007
8008		if (m_po_ids[n_id] != 0)
8009		{
8010			gl.deleteProgram(m_po_ids[n_id]);
8011
8012			m_po_ids[n_id] = 0;
8013		}
8014
8015		if (m_tc_ids[n_id] != 0)
8016		{
8017			gl.deleteShader(m_tc_ids[n_id]);
8018
8019			m_tc_ids[n_id] = 0;
8020		}
8021
8022		if (m_tc_po_ids[n_id] != 0)
8023		{
8024			gl.deleteProgram(m_tc_po_ids[n_id]);
8025
8026			m_tc_po_ids[n_id] = 0;
8027		}
8028
8029		if (m_te_ids[n_id] != 0)
8030		{
8031			gl.deleteShader(m_te_ids[n_id]);
8032
8033			m_te_ids[n_id] = 0;
8034		}
8035
8036		if (m_te_po_ids[n_id] != 0)
8037		{
8038			gl.deleteProgram(m_te_po_ids[n_id]);
8039
8040			m_te_po_ids[n_id] = 0;
8041		}
8042
8043		if (m_vs_ids[n_id] != 0)
8044		{
8045			gl.deleteShader(m_vs_ids[n_id]);
8046
8047			m_vs_ids[n_id] = 0;
8048		}
8049
8050		if (m_vs_po_ids[n_id] != 0)
8051		{
8052			gl.deleteProgram(m_vs_po_ids[n_id]);
8053
8054			m_vs_po_ids[n_id] = 0;
8055		}
8056	} /* for (both IDs) */
8057}
8058
8059/** Retrieves body of a shader that should be used for user-specified shader stage.
8060 *  This function returns slightly different implementations, depending on index of
8061 *  the program/pipeline object the shader will be used for.
8062 *
8063 *  @param shader_stage Stage the shader body is to be returned for.
8064 *  @param n_id         Index of the shader (as per description).
8065 *
8066 *  @return Requested string.
8067 **/
8068std::string FunctionalTest16::getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_id) const
8069{
8070	std::stringstream result_sstream;
8071
8072	result_sstream << "#version 400\n"
8073					  "\n"
8074					  "#extension GL_ARB_shader_subroutine : require\n"
8075					  "\n";
8076
8077	switch (shader_stage)
8078	{
8079	case Utils::SHADER_STAGE_VERTEX:
8080	{
8081		result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n";
8082		break;
8083	}
8084	case Utils::SHADER_STAGE_GEOMETRY:
8085	{
8086		result_sstream << "layout(points)                   in;\n"
8087						  "layout(points, max_vertices = 1) out;\n";
8088		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8089		result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n";
8090		break;
8091	}
8092
8093	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
8094	{
8095		result_sstream << "layout(vertices = 4) out;\n";
8096		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8097		result_sstream << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n";
8098		break;
8099	}
8100
8101	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
8102	{
8103		result_sstream << "layout(quads) in;\n";
8104		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8105		result_sstream << "out gl_PerVertex { vec4 gl_Position; };\n";
8106		break;
8107	}
8108
8109	default:
8110		break;
8111	} /* switch (shader_stage) */
8112
8113	result_sstream << "\n"
8114					  "subroutine void subroutineType (inout vec4 result);\n"
8115					  "subroutine vec4 subroutineType2(in    vec4 data);\n"
8116					  "\n"
8117					  "subroutine(subroutineType) void function1(inout vec4 result)\n"
8118					  "{\n"
8119					  "    result += vec4("
8120				   << (n_id + 1) << ", " << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4)
8121				   << ");\n"
8122					  "}\n"
8123					  "subroutine(subroutineType) void function2(inout vec4 result)\n"
8124					  "{\n"
8125					  "    result += vec4("
8126				   << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4) << ", " << (n_id + 5)
8127				   << ");\n"
8128					  "}\n"
8129					  "\n"
8130					  "subroutine(subroutineType2) vec4 function3(in vec4 data)\n"
8131					  "{\n"
8132					  "    return data * data;\n"
8133					  "}\n"
8134					  "subroutine(subroutineType2) vec4 function4(in vec4 data)\n"
8135					  "{\n"
8136					  "    return data + data;\n"
8137					  "}\n"
8138					  "\n"
8139					  "subroutine uniform subroutineType  subroutine1;\n"
8140					  "subroutine uniform subroutineType  subroutine2;\n"
8141					  "subroutine uniform subroutineType2 subroutine3;\n"
8142					  "subroutine uniform subroutineType2 subroutine4;\n"
8143					  "\n";
8144
8145	if (shader_stage == Utils::SHADER_STAGE_FRAGMENT)
8146	{
8147		result_sstream << "out vec4 result;\n";
8148	}
8149
8150	result_sstream << "void main()\n"
8151					  "{\n";
8152
8153	switch (shader_stage)
8154	{
8155	case Utils::SHADER_STAGE_FRAGMENT:
8156	{
8157		result_sstream << "    result = vec4(0);\n"
8158					   << "    subroutine1(result);\n"
8159						  "    subroutine2(result);\n"
8160						  "    result = subroutine3(result) + subroutine4(result);\n";
8161
8162		break;
8163	}
8164
8165	case Utils::SHADER_STAGE_GEOMETRY:
8166	{
8167		result_sstream << "    gl_Position = vec4(0);\n"
8168						  "    subroutine1(gl_Position);\n"
8169						  "    subroutine2(gl_Position);\n"
8170						  "    gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n"
8171						  "    EmitVertex();\n";
8172
8173		break;
8174	}
8175
8176	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
8177	{
8178		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0);\n"
8179						  "    subroutine1(gl_out[gl_InvocationID].gl_Position);\n"
8180						  "    subroutine2(gl_out[gl_InvocationID].gl_Position);\n"
8181						  "    gl_out[gl_InvocationID].gl_Position = subroutine3(gl_in[0].gl_Position) + "
8182						  "subroutine4(gl_in[0].gl_Position);\n";
8183
8184		break;
8185	}
8186
8187	case Utils::SHADER_STAGE_VERTEX:
8188	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
8189	{
8190		result_sstream << "    gl_Position = vec4(0);\n"
8191						  "    subroutine1(gl_Position);\n"
8192						  "    subroutine2(gl_Position);\n"
8193						  "    gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n";
8194
8195		break;
8196	}
8197
8198	default:
8199		break;
8200	} /* switch (shader_stage) */
8201
8202	result_sstream << "}\n";
8203
8204	return result_sstream.str();
8205}
8206
8207/** Initializes all objects required to run the test. */
8208void FunctionalTest16::initTest()
8209{
8210	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8211
8212	for (unsigned int n_id = 0; n_id < 2 /* test program/shader objects */; ++n_id)
8213	{
8214		const std::string fs_body = getShaderBody(Utils::SHADER_STAGE_FRAGMENT, n_id);
8215		const std::string gs_body = getShaderBody(Utils::SHADER_STAGE_GEOMETRY, n_id);
8216		const std::string tc_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_CONTROL, n_id);
8217		const std::string te_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_EVALUATION, n_id);
8218		const std::string vs_body = getShaderBody(Utils::SHADER_STAGE_VERTEX, n_id);
8219
8220		if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */
8221								 DE_NULL,												   /* n_xfb_varyings */
8222								 m_vs_ids + n_id, m_tc_ids + n_id, m_te_ids + n_id, m_gs_ids + n_id, m_fs_ids + n_id,
8223								 m_po_ids + n_id))
8224		{
8225			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build test program object, index:"
8226														   "["
8227							   << n_id << "]" << tcu::TestLog::EndMessage;
8228
8229			TCU_FAIL("Failed to build a test program");
8230		}
8231
8232		if (m_are_pipeline_objects_supported)
8233		{
8234			/* Initialize shader program objects */
8235			const char* fs_body_raw_ptr = fs_body.c_str();
8236			const char* gs_body_raw_ptr = gs_body.c_str();
8237			glw::GLint  link_status[5]  = { GL_FALSE };
8238			const char* tc_body_raw_ptr = tc_body.c_str();
8239			const char* te_body_raw_ptr = te_body.c_str();
8240			const char* vs_body_raw_ptr = vs_body.c_str();
8241
8242			m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr);
8243			m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr);
8244			m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr);
8245			m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr);
8246			m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr);
8247			GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
8248
8249			gl.getProgramiv(m_fs_po_ids[n_id], GL_LINK_STATUS, link_status + 0);
8250			gl.getProgramiv(m_gs_po_ids[n_id], GL_LINK_STATUS, link_status + 1);
8251			gl.getProgramiv(m_tc_po_ids[n_id], GL_LINK_STATUS, link_status + 2);
8252			gl.getProgramiv(m_te_po_ids[n_id], GL_LINK_STATUS, link_status + 3);
8253			gl.getProgramiv(m_vs_po_ids[n_id], GL_LINK_STATUS, link_status + 4);
8254			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8255
8256			if (link_status[0] == GL_FALSE)
8257				TCU_FAIL("Fragment shader program failed to link");
8258			if (link_status[1] == GL_FALSE)
8259				TCU_FAIL("Geometry shader program failed to link");
8260			if (link_status[2] == GL_FALSE)
8261				TCU_FAIL("Tessellation control shader program failed to link");
8262			if (link_status[3] == GL_FALSE)
8263				TCU_FAIL("Tessellation evaluation shader program failed to link");
8264			if (link_status[4] == GL_FALSE)
8265				TCU_FAIL("Vertex shader program failed to link");
8266
8267			/* Initialize pipeline program object */
8268			gl.genProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id);
8269			GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
8270
8271			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_FRAGMENT_SHADER_BIT, m_fs_po_ids[n_id]);
8272			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_GEOMETRY_SHADER_BIT, m_gs_po_ids[n_id]);
8273			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_CONTROL_SHADER_BIT, m_tc_po_ids[n_id]);
8274			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_EVALUATION_SHADER_BIT, m_te_po_ids[n_id]);
8275			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_id]);
8276			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8277		}
8278
8279		/* Retrieve subroutine locations */
8280		struct _item
8281		{
8282			glw::GLuint	po_id;
8283			_shader_stage& stage;
8284			glw::GLuint	so_id;
8285			glw::GLenum	so_type;
8286		} items[] = {
8287			{ m_po_ids[n_id], m_po_descriptors[n_id].fragment, m_fs_ids[n_id], GL_FRAGMENT_SHADER },
8288			{ m_po_ids[n_id], m_po_descriptors[n_id].geometry, m_gs_ids[n_id], GL_GEOMETRY_SHADER },
8289			{ m_po_ids[n_id], m_po_descriptors[n_id].tess_control, m_tc_ids[n_id], GL_TESS_CONTROL_SHADER },
8290			{ m_po_ids[n_id], m_po_descriptors[n_id].tess_evaluation, m_te_ids[n_id], GL_TESS_EVALUATION_SHADER },
8291			{ m_po_ids[n_id], m_po_descriptors[n_id].vertex, m_vs_ids[n_id], GL_VERTEX_SHADER },
8292
8293			{ m_fs_po_ids[n_id], m_fs_po_descriptors[n_id], m_fs_po_ids[n_id], GL_FRAGMENT_SHADER },
8294			{ m_gs_po_ids[n_id], m_gs_po_descriptors[n_id], m_gs_po_ids[n_id], GL_GEOMETRY_SHADER },
8295			{ m_tc_po_ids[n_id], m_tc_po_descriptors[n_id], m_tc_po_ids[n_id], GL_TESS_CONTROL_SHADER },
8296			{ m_te_po_ids[n_id], m_te_po_descriptors[n_id], m_te_po_ids[n_id], GL_TESS_EVALUATION_SHADER },
8297			{ m_vs_po_ids[n_id], m_vs_po_descriptors[n_id], m_vs_po_ids[n_id], GL_VERTEX_SHADER },
8298		};
8299		const unsigned int n_items = sizeof(items) / sizeof(items[0]);
8300
8301		for (unsigned int n_item = 0; n_item < n_items; ++n_item)
8302		{
8303			_item& current_item = items[n_item];
8304
8305			current_item.stage.function1_index =
8306				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function1");
8307			current_item.stage.function2_index =
8308				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function2");
8309			current_item.stage.function3_index =
8310				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function3");
8311			current_item.stage.function4_index =
8312				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function4");
8313			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
8314
8315			if (current_item.stage.function1_index == GL_INVALID_INDEX ||
8316				current_item.stage.function2_index == GL_INVALID_INDEX ||
8317				current_item.stage.function3_index == GL_INVALID_INDEX ||
8318				current_item.stage.function4_index == GL_INVALID_INDEX)
8319			{
8320				TCU_FAIL("Subroutine name was not recognized.");
8321			}
8322
8323			current_item.stage.subroutine1_uniform_location =
8324				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine1");
8325			current_item.stage.subroutine2_uniform_location =
8326				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine2");
8327			current_item.stage.subroutine3_uniform_location =
8328				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine3");
8329			current_item.stage.subroutine4_uniform_location =
8330				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine4");
8331			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
8332
8333			if (current_item.stage.subroutine1_uniform_location == -1 ||
8334				current_item.stage.subroutine2_uniform_location == -1 ||
8335				current_item.stage.subroutine3_uniform_location == -1 ||
8336				current_item.stage.subroutine4_uniform_location == -1)
8337			{
8338				TCU_FAIL("Subroutine uniform name was not recognized.");
8339			}
8340
8341			if (m_po_ids[n_id] == current_item.po_id)
8342			{
8343				gl.useProgram(current_item.po_id);
8344				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8345			}
8346			else
8347			{
8348				/* Temporarily bind the program pipeline. */
8349				gl.bindProgramPipeline(m_pipeline_object_ids[n_id]);
8350				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8351			}
8352
8353			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine1_uniform_location,
8354									   &current_item.stage.default_subroutine1_value);
8355			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine2_uniform_location,
8356									   &current_item.stage.default_subroutine2_value);
8357			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine3_uniform_location,
8358									   &current_item.stage.default_subroutine3_value);
8359			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine4_uniform_location,
8360									   &current_item.stage.default_subroutine4_value);
8361			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed.");
8362
8363			current_item.stage.gl_stage = current_item.so_type;
8364
8365			if (m_po_ids[n_id] != current_item.po_id)
8366			{
8367				/* Unbind the program pipeline object */
8368				gl.bindProgramPipeline(0);
8369				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8370			}
8371		} /* for (all items) */
8372
8373		/* Make sure the default subroutine choices are valid. */
8374		verifySubroutineUniformValues(
8375			TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, /* makes the verification routine use program object descriptor */
8376			n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES);
8377
8378		if (m_are_pipeline_objects_supported)
8379		{
8380			gl.useProgram(0);
8381			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8382
8383			gl.bindProgramPipeline(m_pipeline_object_ids[n_id]);
8384			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8385			{
8386				verifySubroutineUniformValues(
8387					TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT, /* makes the verification routine use pipeline object descriptor */
8388					n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES);
8389			}
8390			gl.bindProgramPipeline(0);
8391			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8392		}
8393	} /* for (both program descriptors) */
8394}
8395
8396/** Retrieves IDs of shaders OR shader program objects, depending on which of the two
8397 *  the caller requests for.
8398 *
8399 *  @param retrieve_program_object_shader_ids true if the caller wishes to retrieve shader object IDs,
8400 *                                            false to return shader program IDs.
8401 *  @param n_id                               Index of the program/pipeline object the shaders
8402 *                                            are a part of.
8403 *  @param out_shader_stages                  Deref will be used to store exactly five IDs. Must not
8404 *                                            be NULL.
8405 **/
8406void FunctionalTest16::getShaderStages(bool retrieve_program_object_shader_ids, const unsigned int& n_id,
8407									   const _shader_stage** out_shader_stages) const
8408{
8409	if (retrieve_program_object_shader_ids)
8410	{
8411		out_shader_stages[0] = &m_po_descriptors[n_id].vertex;
8412		out_shader_stages[1] = &m_po_descriptors[n_id].tess_control;
8413		out_shader_stages[2] = &m_po_descriptors[n_id].tess_evaluation;
8414		out_shader_stages[3] = &m_po_descriptors[n_id].geometry;
8415		out_shader_stages[4] = &m_po_descriptors[n_id].fragment;
8416	}
8417	else
8418	{
8419		out_shader_stages[0] = m_vs_po_descriptors + n_id;
8420		out_shader_stages[1] = m_tc_po_descriptors + n_id;
8421		out_shader_stages[2] = m_te_po_descriptors + n_id;
8422		out_shader_stages[3] = m_gs_po_descriptors + n_id;
8423		out_shader_stages[4] = m_fs_po_descriptors + n_id;
8424	}
8425}
8426
8427/** Executes test iteration.
8428 *
8429 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8430 */
8431tcu::TestNode::IterateResult FunctionalTest16::iterate()
8432{
8433	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8434
8435	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
8436	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
8437	{
8438		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
8439	}
8440
8441	m_are_pipeline_objects_supported =
8442		m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects");
8443
8444	/* Initialize GL objects required to run the test */
8445	initTest();
8446
8447	/* Iterate over both pipelines/programs and verify that calling glUseProgram() /
8448	 * glBindProgramPipeline() / glUseProgramStages() resets subroutine uniform configuration.
8449	 */
8450	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
8451	{
8452		if (static_cast<_test_case>(test_case) != TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT &&
8453			!m_are_pipeline_objects_supported)
8454		{
8455			/* Current test case requires GL_ARB_separate_shader_objects support which is
8456			 * unavaiable on the platform that we're testing
8457			 */
8458			continue;
8459		}
8460
8461		for (unsigned int n_object_id = 0; n_object_id < 2; /* pipeline/program objects allocated for the test */
8462			 ++n_object_id)
8463		{
8464			/* Verify that currently reported subroutine uniform values are equal to default values */
8465			if (test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT)
8466			{
8467				gl.useProgram(m_po_ids[n_object_id]);
8468				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
8469			}
8470			else
8471			{
8472				gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]);
8473				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed");
8474			}
8475
8476			verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8477										  SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8478
8479			/* Re-configure subroutine uniforms so that they point to different subroutines than
8480			 * the default ones.
8481			 */
8482			const _shader_stage* stages[5 /* fs+gs+tc+te+vs */] = { DE_NULL };
8483
8484			getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT,
8485							n_object_id, stages);
8486
8487			for (unsigned int n_stage = 0; n_stage < 5 /* fs+gs+tc+te+vs stages */; ++n_stage)
8488			{
8489				const _shader_stage& current_stage				 = *(stages[n_stage]);
8490				glw::GLuint			 subroutine_configuration[4] = { GL_INVALID_INDEX };
8491
8492				subroutine_configuration[0] =
8493					(current_stage.default_subroutine1_value == current_stage.function1_index) ?
8494						current_stage.function2_index :
8495						current_stage.function1_index;
8496				subroutine_configuration[1] =
8497					(current_stage.default_subroutine2_value == current_stage.function1_index) ?
8498						current_stage.function2_index :
8499						current_stage.function1_index;
8500				subroutine_configuration[2] =
8501					(current_stage.default_subroutine3_value == current_stage.function3_index) ?
8502						current_stage.function4_index :
8503						current_stage.function3_index;
8504				subroutine_configuration[3] =
8505					(current_stage.default_subroutine4_value == current_stage.function3_index) ?
8506						current_stage.function4_index :
8507						current_stage.function3_index;
8508
8509				gl.uniformSubroutinesuiv(current_stage.gl_stage, 4 /* count */, subroutine_configuration);
8510				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
8511			} /* for (all stages) */
8512
8513			verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8514										  SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8515
8516			/* Execute test case-specific code */
8517			_shader_stage cached_shader_stage_data;
8518			bool		  stage_reset_status[Utils::SHADER_STAGE_COUNT] = { false, false, false, false, false };
8519			bool		  uses_stage_reset_status						= false;
8520
8521			switch (test_case)
8522			{
8523			case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT:
8524			{
8525				/* Switch to a different program object and then back to current PO.
8526				 * Subroutine uniforms should be back at their default settings, instead of
8527				 * the ones we've just set.
8528				 */
8529				gl.useProgram(m_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8530				gl.useProgram(m_po_ids[n_object_id]);
8531				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
8532
8533				break;
8534			}
8535
8536			case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT:
8537			{
8538				/* Switch to a different pipeline object and then back to the current one.
8539				 * Subroutine uniforms should be back at their default settings, instead of
8540				 * the ones we've just set.
8541				 */
8542				gl.bindProgramPipeline(
8543					m_pipeline_object_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8544				gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]);
8545				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
8546
8547				break;
8548			}
8549
8550			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE:
8551			{
8552				/* Change the fragment shader stage to a different one.
8553				 *
8554				 * Note: We also need to update internal descriptor since the subroutine/uniform
8555				 *       locations may be different between the two programs.
8556				 */
8557				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT,
8558									m_fs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8559				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8560
8561				cached_shader_stage_data		 = m_fs_po_descriptors[n_object_id];
8562				m_fs_po_descriptors[n_object_id] = m_fs_po_descriptors[(n_object_id + 1) % 2];
8563
8564				stage_reset_status[Utils::SHADER_STAGE_FRAGMENT] = true;
8565				uses_stage_reset_status							 = true;
8566
8567				break;
8568			}
8569
8570			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE:
8571			{
8572				/* Change the geometry shader stage to a different one.
8573				 *
8574				 * Note: We also need to update internal descriptor since the subroutine/uniform
8575				 *       locations may be different between the two programs.
8576				 */
8577				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT,
8578									m_gs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8579				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8580
8581				cached_shader_stage_data		 = m_gs_po_descriptors[n_object_id];
8582				m_gs_po_descriptors[n_object_id] = m_gs_po_descriptors[(n_object_id + 1) % 2];
8583
8584				stage_reset_status[Utils::SHADER_STAGE_GEOMETRY] = true;
8585				uses_stage_reset_status							 = true;
8586
8587				break;
8588			}
8589
8590			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE:
8591			{
8592				/* Change the tessellation control shader stage to a different one.
8593				 *
8594				 * Note: We also need to update internal descriptor since the subroutine/uniform
8595				 *       locations may be different between the two programs.
8596				 */
8597				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT,
8598									m_tc_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8599				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8600
8601				cached_shader_stage_data		 = m_tc_po_descriptors[n_object_id];
8602				m_tc_po_descriptors[n_object_id] = m_tc_po_descriptors[(n_object_id + 1) % 2];
8603
8604				stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_CONTROL] = true;
8605				uses_stage_reset_status										 = true;
8606
8607				break;
8608			}
8609
8610			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE:
8611			{
8612				/* Change the tessellation evaluation shader stage to a different one.
8613				 *
8614				 * Note: We also need to update internal descriptor since the subroutine/uniform
8615				 *       locations may be different between the two programs.
8616				 */
8617				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT,
8618									m_te_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8619				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8620
8621				cached_shader_stage_data		 = m_te_po_descriptors[n_object_id];
8622				m_te_po_descriptors[n_object_id] = m_te_po_descriptors[(n_object_id + 1) % 2];
8623
8624				stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_EVALUATION] = true;
8625				uses_stage_reset_status											= true;
8626
8627				break;
8628			}
8629
8630			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE:
8631			{
8632				/* Change the vertex shader stage to a different one.
8633				 *
8634				 * Note: We also need to update internal descriptor since the subroutine/uniform
8635				 *       locations may be different between the two programs.
8636				 */
8637				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT,
8638									m_vs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8639				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8640
8641				cached_shader_stage_data		 = m_vs_po_descriptors[n_object_id];
8642				m_vs_po_descriptors[n_object_id] = m_vs_po_descriptors[(n_object_id + 1) % 2];
8643
8644				stage_reset_status[Utils::SHADER_STAGE_VERTEX] = true;
8645				uses_stage_reset_status						   = true;
8646
8647				break;
8648			}
8649
8650			default:
8651			{
8652				TCU_FAIL("Unrecognized test case");
8653			}
8654			} /* switch (test_case) */
8655
8656			/* Verify the subroutine uniform values are valid */
8657			if (!uses_stage_reset_status)
8658			{
8659				verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8660											  SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8661			}
8662			else
8663			{
8664				const _shader_stage* shader_stages[Utils::SHADER_STAGE_COUNT] = { DE_NULL };
8665
8666				getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT,
8667								n_object_id, shader_stages);
8668
8669				for (unsigned int n_shader_stage = 0; n_shader_stage < Utils::SHADER_STAGE_COUNT; ++n_shader_stage)
8670				{
8671					const _shader_stage& current_shader_stage = *(shader_stages[n_shader_stage]);
8672
8673					if (stage_reset_status[n_shader_stage])
8674					{
8675						verifySubroutineUniformValuesForShaderStage(current_shader_stage,
8676																	SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8677					}
8678					else
8679					{
8680						verifySubroutineUniformValuesForShaderStage(current_shader_stage,
8681																	SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8682					}
8683				} /* for (all shader stages) */
8684			}
8685
8686			/* Revert the changes some of the test cases appied */
8687			switch (test_case)
8688			{
8689			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE:
8690			{
8691				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT,
8692									m_fs_po_ids[n_object_id]);
8693				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8694
8695				m_fs_po_descriptors[n_object_id] = cached_shader_stage_data;
8696
8697				break;
8698			}
8699
8700			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE:
8701			{
8702				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT,
8703									m_gs_po_ids[n_object_id]);
8704				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8705
8706				m_gs_po_descriptors[n_object_id] = cached_shader_stage_data;
8707
8708				break;
8709			}
8710
8711			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE:
8712			{
8713				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT,
8714									m_tc_po_ids[n_object_id]);
8715				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8716
8717				m_tc_po_descriptors[n_object_id] = cached_shader_stage_data;
8718
8719				break;
8720			}
8721
8722			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE:
8723			{
8724				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT,
8725									m_te_po_ids[n_object_id]);
8726				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8727
8728				m_te_po_descriptors[n_object_id] = cached_shader_stage_data;
8729
8730				break;
8731			}
8732
8733			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE:
8734			{
8735				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_object_id]);
8736				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8737
8738				m_vs_po_descriptors[n_object_id] = cached_shader_stage_data;
8739
8740				break;
8741			}
8742
8743			default:
8744				break;
8745			} /* switch (test_case) */
8746
8747		} /* for (all program object descriptors) */
8748
8749		/* Unbind the program object */
8750		gl.useProgram(0);
8751		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8752	} /* for (all test cases) */
8753
8754	if (m_has_test_passed)
8755	{
8756		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8757	}
8758	else
8759	{
8760		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8761	}
8762
8763	return STOP;
8764}
8765
8766/** Verifies the subroutine uniform values reported by GL implementation. Depending on the test case,
8767 *  it will either query program object stages or separate shader objects.
8768 *
8769 *  @param test_case    Test case the verification is to be performed for.
8770 *  @param n_id         Index of the program/pipeline object to use for the verification
8771 *  @param verification Verification method.
8772 */
8773void FunctionalTest16::verifySubroutineUniformValues(const _test_case& test_case, const unsigned int& n_id,
8774													 const _subroutine_uniform_value_verification& verification)
8775{
8776	const _shader_stage* stages[] = {
8777		DE_NULL, /* fragment shader     stage slot */
8778		DE_NULL, /* geometry shader     stage slot */
8779		DE_NULL, /* tess control shader stage slot */
8780		DE_NULL, /* tess eval shader    stage slot */
8781		DE_NULL  /* vertex shader       stage slot */
8782	};
8783	const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
8784
8785	/* Verify that currently reported subroutine uniform values are equal to default values */
8786	getShaderStages(test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, n_id, stages);
8787
8788	for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
8789	{
8790		const _shader_stage& current_stage = *(stages[n_stage]);
8791
8792		verifySubroutineUniformValuesForShaderStage(current_stage, verification);
8793	} /* for (all items) */
8794}
8795
8796/** Verifies the subroutine uniform values reported by GL implementation for user-specified
8797 *  shader stage. If the verification fails, m_has_test_passed will be set to false.
8798 *
8799 *  @param shader_stage Descriptor of a shader stage that should be used for the process.
8800 *  @param verification Type of verification that should be performed.
8801 *
8802 **/
8803void FunctionalTest16::verifySubroutineUniformValuesForShaderStage(
8804	const _shader_stage& shader_stage, const _subroutine_uniform_value_verification& verification)
8805{
8806	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
8807	glw::GLuint			  result_values[4] = { 0 };
8808
8809	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine1_uniform_location, result_values + 0);
8810	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine2_uniform_location, result_values + 1);
8811	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine3_uniform_location, result_values + 2);
8812	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine4_uniform_location, result_values + 3);
8813	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed.");
8814
8815	if (verification == SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES)
8816	{
8817		if (!((result_values[0] == (GLuint)shader_stage.subroutine1_uniform_location ||
8818			   result_values[0] == (GLuint)shader_stage.subroutine2_uniform_location) &&
8819			  (result_values[1] == (GLuint)shader_stage.subroutine1_uniform_location ||
8820			   result_values[1] == (GLuint)shader_stage.subroutine2_uniform_location) &&
8821			  (result_values[2] == (GLuint)shader_stage.subroutine3_uniform_location ||
8822			   result_values[2] == (GLuint)shader_stage.subroutine4_uniform_location) &&
8823			  (result_values[3] == (GLuint)shader_stage.subroutine3_uniform_location ||
8824			   result_values[3] == (GLuint)shader_stage.subroutine4_uniform_location)))
8825		{
8826			m_testCtx.getLog() << tcu::TestLog::Message << "SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES validation failed. "
8827														   "Shader stage:["
8828							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8829																								  "expected data:["
8830							   << shader_stage.subroutine1_uniform_location << " OR "
8831							   << shader_stage.subroutine2_uniform_location << " x 2, "
8832							   << shader_stage.subroutine3_uniform_location << " OR "
8833							   << shader_stage.subroutine4_uniform_location << " x 2], "
8834																			   "found data:["
8835							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8836							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8837
8838			m_has_test_passed = false;
8839		}
8840	}
8841	else if (verification == SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES)
8842	{
8843		if (result_values[0] != shader_stage.default_subroutine1_value ||
8844			result_values[1] != shader_stage.default_subroutine2_value ||
8845			result_values[2] != shader_stage.default_subroutine3_value ||
8846			result_values[3] != shader_stage.default_subroutine4_value)
8847		{
8848			m_testCtx.getLog() << tcu::TestLog::Message
8849							   << "SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES validation failed. "
8850								  "Shader stage:["
8851							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8852																								  "expected data:["
8853							   << shader_stage.default_subroutine1_value << ", "
8854							   << shader_stage.default_subroutine2_value << ", "
8855							   << shader_stage.default_subroutine3_value << ", "
8856							   << shader_stage.default_subroutine4_value << "], "
8857																			"found data:["
8858							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8859							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8860
8861			m_has_test_passed = false;
8862		}
8863	}
8864	else
8865	{
8866		DE_ASSERT(verification == SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8867
8868		if (result_values[0] == shader_stage.default_subroutine1_value ||
8869			result_values[1] == shader_stage.default_subroutine2_value ||
8870			result_values[2] == shader_stage.default_subroutine3_value ||
8871			result_values[3] == shader_stage.default_subroutine4_value)
8872		{
8873			m_testCtx.getLog() << tcu::TestLog::Message
8874							   << "SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES validation failed. "
8875								  "Shader stage:["
8876							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8877																								  "expected data:!["
8878							   << shader_stage.default_subroutine1_value << ", "
8879							   << shader_stage.default_subroutine2_value << ", "
8880							   << shader_stage.default_subroutine3_value << ", "
8881							   << shader_stage.default_subroutine4_value << "], "
8882																			"found data:["
8883							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8884							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8885
8886			m_has_test_passed = false;
8887		}
8888	}
8889}
8890
8891/** Constructor.
8892 *
8893 *  @param context Rendering context.
8894 *
8895 **/
8896FunctionalTest17::FunctionalTest17(deqp::Context& context)
8897	: TestCase(context, "same_subroutine_and_subroutine_uniform_but_different_type_used_in_all_stages",
8898			   "Creates a program which uses the same subroutine and subroutine uniform "
8899			   "names for every stage (types of subroutines are different in each stage) "
8900			   "and then makes sure that such program compiles and works as expected.")
8901	, m_fbo_id(0)
8902	, m_fs_id(0)
8903	, m_gs_id(0)
8904	, m_has_test_passed(true)
8905	, m_po_id(0)
8906	, m_tc_id(0)
8907	, m_te_id(0)
8908	, m_to_data(DE_NULL)
8909	, m_to_height(4) /* arbitrary value */
8910	, m_to_id(0)
8911	, m_to_width(4) /* arbitrary value */
8912	, m_vao_id(0)
8913	, m_vs_id(0)
8914{
8915	/* Left blank intentionally */
8916}
8917
8918/** Deinitializes all GL objects that may have been created during test execution. */
8919void FunctionalTest17::deinit()
8920{
8921	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8922
8923	if (m_fbo_id != 0)
8924	{
8925		gl.deleteFramebuffers(1, &m_fbo_id);
8926
8927		m_fbo_id = 0;
8928	}
8929
8930	if (m_fs_id != 0)
8931	{
8932		gl.deleteShader(m_fs_id);
8933
8934		m_fs_id = 0;
8935	}
8936
8937	if (m_gs_id != 0)
8938	{
8939		gl.deleteShader(m_gs_id);
8940
8941		m_gs_id = 0;
8942	}
8943
8944	if (m_po_id != 0)
8945	{
8946		gl.deleteProgram(m_po_id);
8947
8948		m_po_id = 0;
8949	}
8950
8951	if (m_tc_id != 0)
8952	{
8953		gl.deleteShader(m_tc_id);
8954
8955		m_tc_id = 0;
8956	}
8957
8958	if (m_te_id != 0)
8959	{
8960		gl.deleteShader(m_te_id);
8961
8962		m_te_id = 0;
8963	}
8964
8965	if (m_to_data != DE_NULL)
8966	{
8967		delete[] m_to_data;
8968
8969		m_to_data = DE_NULL;
8970	}
8971
8972	if (m_to_id != 0)
8973	{
8974		gl.deleteTextures(1, &m_to_id);
8975
8976		m_to_id = 0;
8977	}
8978
8979	if (m_vao_id != 0)
8980	{
8981		gl.deleteVertexArrays(1, &m_vao_id);
8982
8983		m_vao_id = 0;
8984	}
8985
8986	if (m_vs_id != 0)
8987	{
8988		gl.deleteShader(m_vs_id);
8989
8990		m_vs_id = 0;
8991	}
8992
8993	/* Restore original GL configuration */
8994	gl.patchParameteri(GL_PATCH_VERTICES, 3);
8995	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
8996
8997	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
8998	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
8999}
9000
9001/** Retrieves body of a fragment shader that should be used by the test program.
9002 *
9003 *  @return Requested string.
9004 **/
9005std::string FunctionalTest17::getFragmentShaderBody() const
9006{
9007	return "#version 400\n"
9008		   "\n"
9009		   "#extension GL_ARB_shader_subroutine : require\n"
9010		   "\n"
9011		   "in GS_DATA\n"
9012		   "{\n"
9013		   "    vec4 gs_data;\n"
9014		   "    vec4 tc_data;\n"
9015		   "    vec4 te_data;\n"
9016		   "    vec4 vs_data;\n"
9017		   "} gs;\n"
9018		   "\n"
9019		   "out vec4 result;\n"
9020		   "\n"
9021		   "subroutine void subroutineTypeFS(out vec4 result);\n"
9022		   "\n"
9023		   "subroutine(subroutineTypeFS) void subroutine1(out vec4 result)\n"
9024		   "{\n"
9025		   "    result = vec4(5, 6, 7, 8);\n"
9026		   "}\n"
9027		   "\n"
9028		   "subroutine uniform subroutineTypeFS function;\n"
9029		   "\n"
9030		   "void main()\n"
9031		   "{\n"
9032		   "    vec4 fs_data;\n"
9033		   "\n"
9034		   "    function(fs_data);\n"
9035		   "    result = gs.gs_data + gs.tc_data + gs.te_data + gs.vs_data + fs_data;\n"
9036		   "}\n";
9037}
9038
9039/** Retrieves body of a geometry shader that should be used by the test program.
9040 *
9041 *  @return Requested string.
9042 **/
9043std::string FunctionalTest17::getGeometryShaderBody() const
9044{
9045	return "#version 400\n"
9046		   "\n"
9047		   "#extension GL_ARB_shader_subroutine : require\n"
9048		   "\n"
9049		   "layout(points)                           in;\n"
9050		   "layout(triangle_strip, max_vertices = 4) out;\n"
9051		   "\n"
9052		   "subroutine void subroutineTypeGS(out vec4 result);\n"
9053		   "\n"
9054		   "subroutine(subroutineTypeGS) void subroutine1(out vec4 result)\n"
9055		   "{\n"
9056		   "    result = vec4(4, 5, 6, 7);\n"
9057		   "}\n"
9058		   "\n"
9059		   "subroutine uniform subroutineTypeGS function;\n"
9060		   "\n"
9061		   "in TE_DATA\n"
9062		   "{\n"
9063		   "    vec4 tc_data;\n"
9064		   "    vec4 te_data;\n"
9065		   "    vec4 vs_data;\n"
9066		   "} te[];\n"
9067		   "\n"
9068		   "out GS_DATA\n"
9069		   "{\n"
9070		   "    vec4 gs_data;\n"
9071		   "    vec4 tc_data;\n"
9072		   "    vec4 te_data;\n"
9073		   "    vec4 vs_data;\n"
9074		   "} result;\n"
9075		   "\n"
9076		   "void main()\n"
9077		   "{\n"
9078		   "    function(result.gs_data);\n"
9079		   "    gl_Position    = vec4(1, -1, 0, 1);\n"
9080		   "    result.tc_data = te[0].tc_data;\n"
9081		   "    result.te_data = te[0].te_data;\n"
9082		   "    result.vs_data = te[0].vs_data;\n"
9083		   "    EmitVertex();\n"
9084		   "\n"
9085		   "    function(result.gs_data);\n"
9086		   "    gl_Position    = vec4(-1, -1, 0, 1);\n"
9087		   "    result.tc_data = te[0].tc_data;\n"
9088		   "    result.te_data = te[0].te_data;\n"
9089		   "    result.vs_data = te[0].vs_data;\n"
9090		   "    EmitVertex();\n"
9091		   "\n"
9092		   "    function(result.gs_data);\n"
9093		   "    gl_Position    = vec4(1, 1, 0, 1);\n"
9094		   "    result.tc_data = te[0].tc_data;\n"
9095		   "    result.te_data = te[0].te_data;\n"
9096		   "    result.vs_data = te[0].vs_data;\n"
9097		   "    EmitVertex();\n"
9098		   "\n"
9099		   "    function(result.gs_data);\n"
9100		   "    gl_Position    = vec4(-1, 1, 0, 1);\n"
9101		   "    result.tc_data = te[0].tc_data;\n"
9102		   "    result.te_data = te[0].te_data;\n"
9103		   "    result.vs_data = te[0].vs_data;\n"
9104		   "    EmitVertex();\n"
9105		   "    EndPrimitive();\n"
9106		   "}\n";
9107}
9108
9109/** Retrieves body of a tessellation control shader that should be used by the test program.
9110 *
9111 *  @return Requested string.
9112 **/
9113std::string FunctionalTest17::getTessellationControlShaderBody() const
9114{
9115	return "#version 400\n"
9116		   "\n"
9117		   "#extension GL_ARB_shader_subroutine : require\n"
9118		   "\n"
9119		   "layout (vertices = 4) out;\n"
9120		   "\n"
9121		   "subroutine void subroutineTypeTC(out vec4 result);\n"
9122		   "\n"
9123		   "subroutine(subroutineTypeTC) void subroutine1(out vec4 result)\n"
9124		   "{\n"
9125		   "    result = vec4(2, 3, 4, 5);\n"
9126		   "}\n"
9127		   "\n"
9128		   "subroutine uniform subroutineTypeTC function;\n"
9129		   "\n"
9130		   "in VS_DATA\n"
9131		   "{\n"
9132		   "    vec4 vs_data;\n"
9133		   "} vs[];\n"
9134		   "\n"
9135		   "out TC_DATA\n"
9136		   "{\n"
9137		   "    vec4 tc_data;\n"
9138		   "    vec4 vs_data;\n"
9139		   "} result[];\n"
9140		   "\n"
9141		   "void main()\n"
9142		   "{\n"
9143		   "    gl_TessLevelInner[0] = 1.0;\n"
9144		   "    gl_TessLevelInner[1] = 1.0;\n"
9145		   "    gl_TessLevelOuter[0] = 1.0;\n"
9146		   "    gl_TessLevelOuter[1] = 1.0;\n"
9147		   "    gl_TessLevelOuter[2] = 1.0;\n"
9148		   "    gl_TessLevelOuter[3] = 1.0;\n"
9149		   "\n"
9150		   "    function(result[gl_InvocationID].tc_data);\n"
9151		   "    result[gl_InvocationID].vs_data = vs[gl_InvocationID].vs_data;\n"
9152		   "}\n";
9153}
9154
9155/** Retrieves body of a tessellation evaluation shader that should be used
9156 *  by the test program.
9157 *
9158 *  @return Requested string.
9159 **/
9160std::string FunctionalTest17::getTessellationEvaluationShaderBody() const
9161{
9162	return "#version 400\n"
9163		   "\n"
9164		   "#extension GL_ARB_shader_subroutine : require\n"
9165		   "\n"
9166		   "layout (quads, point_mode) in;\n"
9167		   "\n"
9168		   "subroutine void subroutineTypeTE(out vec4 result);\n"
9169		   "\n"
9170		   "subroutine(subroutineTypeTE) void subroutine1(out vec4 result)\n"
9171		   "{\n"
9172		   "    result = vec4(3, 4, 5, 6);\n"
9173		   "}\n"
9174		   "\n"
9175		   "subroutine uniform subroutineTypeTE function;\n"
9176		   "\n"
9177		   "in TC_DATA\n"
9178		   "{\n"
9179		   "    vec4 tc_data;\n"
9180		   "    vec4 vs_data;\n"
9181		   "} tc[];\n"
9182		   "\n"
9183		   "out TE_DATA\n"
9184		   "{\n"
9185		   "    vec4 tc_data;\n"
9186		   "    vec4 te_data;\n"
9187		   "    vec4 vs_data;\n"
9188		   "} result;\n"
9189		   "\n"
9190		   "void main()\n"
9191		   "{\n"
9192		   "    result.vs_data = tc[0].vs_data;\n"
9193		   "    result.tc_data = tc[0].tc_data;\n"
9194		   "    function(result.te_data);\n"
9195		   "}\n";
9196}
9197
9198/** Retrieves body of a vertex shader that should be used by the test program.
9199 *
9200 *  @return Requested string.
9201 **/
9202std::string FunctionalTest17::getVertexShaderBody() const
9203{
9204	return "#version 400\n"
9205		   "\n"
9206		   "#extension GL_ARB_shader_subroutine : require\n"
9207		   "\n"
9208		   "out VS_DATA\n"
9209		   "{\n"
9210		   "    vec4 vs_data;\n"
9211		   "} result;\n"
9212		   "\n"
9213		   "subroutine void subroutineTypeVS(out vec4 result);\n"
9214		   "\n"
9215		   "subroutine(subroutineTypeVS) void subroutine1(out vec4 result)\n"
9216		   "{\n"
9217		   "    result = vec4(1, 2, 3, 4);\n"
9218		   "}\n"
9219		   "\n"
9220		   "subroutine uniform subroutineTypeVS function;\n"
9221		   "\n"
9222		   "void main()\n"
9223		   "{\n"
9224		   "    function(result.vs_data);\n"
9225		   "}\n";
9226}
9227
9228/** Initializes all buffers and GL objects required to run the test. */
9229void FunctionalTest17::initTest()
9230{
9231	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9232
9233	/* Configure GL_PATCH_VERTICES so that TC only takes a single patch vertex */
9234	gl.patchParameteri(GL_PATCH_VERTICES, 1);
9235	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
9236
9237	/* Generate & bind a VAO */
9238	gl.genVertexArrays(1, &m_vao_id);
9239	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9240
9241	gl.bindVertexArray(m_vao_id);
9242	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9243
9244	/* Set up test program object */
9245	std::string fs_body = getFragmentShaderBody();
9246	std::string gs_body = getGeometryShaderBody();
9247	std::string tc_body = getTessellationControlShaderBody();
9248	std::string te_body = getTessellationEvaluationShaderBody();
9249	std::string vs_body = getVertexShaderBody();
9250
9251	if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */
9252							 DE_NULL,												   /* n_xfb_varyings */
9253							 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
9254	{
9255		TCU_FAIL("Failed to link test program object");
9256	}
9257
9258	/* Set up a texture object that will be used as a color attachment */
9259	gl.genTextures(1, &m_to_id);
9260	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
9261
9262	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9263	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9264
9265	gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
9266					GL_RGBA32F, m_to_width, m_to_height);
9267	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9268
9269	/* Set up FBO */
9270	gl.genFramebuffers(1, &m_fbo_id);
9271	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9272
9273	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9274	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
9275
9276	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
9277	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
9278
9279	/* Make sure glReadPixels() does not return misaligned data */
9280	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
9281	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
9282
9283	/* Initialize a buffer that will be used to store rendered data */
9284	m_to_data = new float[m_to_width * m_to_height * 4 /* rgba */];
9285}
9286
9287/** Executes test iteration.
9288 *
9289 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9290 */
9291tcu::TestNode::IterateResult FunctionalTest17::iterate()
9292{
9293	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9294
9295	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9296	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9297	{
9298		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9299	}
9300
9301	initTest();
9302
9303	/* Use the test program to render a full-screen test quad */
9304	gl.useProgram(m_po_id);
9305	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9306
9307	gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
9308	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9309
9310	/* Read back the data that was rendered */
9311	gl.readPixels(0, /* x */
9312				  0, /* y */
9313				  m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_to_data);
9314	GLU_EXPECT_NO_ERROR(gl.getError(), "glReaDPixels() call failed.");
9315
9316	/* Verify the data */
9317	verifyRenderedData();
9318
9319	/** All done */
9320	if (m_has_test_passed)
9321	{
9322		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9323	}
9324	else
9325	{
9326		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
9327	}
9328
9329	return STOP;
9330}
9331
9332/** Verifies the data that have been rendered by the test program.
9333 *
9334 *  It is assumed the rendered data have already been copied to
9335 *  m_to_data.
9336 *
9337 *  If the rendered data is found to be invalid, m_has_test_passed
9338 *  will be set to false.
9339 **/
9340void FunctionalTest17::verifyRenderedData()
9341{
9342	const float epsilon			 = 1e-5f;
9343	const float expected_data[4] = { 15.0f, 20.0f, 25.0f, 30.0f };
9344
9345	for (unsigned int y = 0; y < m_to_height && m_has_test_passed; ++y)
9346	{
9347		const float* row_ptr = m_to_data + y * 4 /* rgba */ * m_to_width;
9348
9349		for (unsigned int x = 0; x < m_to_width && m_has_test_passed; ++x)
9350		{
9351			const float* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9352
9353			if (de::abs(pixel_ptr[0] - expected_data[0]) > epsilon ||
9354				de::abs(pixel_ptr[1] - expected_data[1]) > epsilon ||
9355				de::abs(pixel_ptr[2] - expected_data[2]) > epsilon ||
9356				de::abs(pixel_ptr[3] - expected_data[3]) > epsilon)
9357			{
9358				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel found at (" << x << ", " << y
9359								   << "): "
9360									  "expected:("
9361								   << expected_data[0] << ", " << expected_data[1] << ", " << expected_data[2] << ", "
9362								   << expected_data[3] << "), found:(" << pixel_ptr[0] << ", " << pixel_ptr[1] << ", "
9363								   << pixel_ptr[2] << ", " << pixel_ptr[3] << ")." << tcu::TestLog::EndMessage;
9364
9365				m_has_test_passed = false;
9366			}
9367		} /* for (all columns) */
9368	}	 /* for (all rows) */
9369}
9370
9371/** Constructor.
9372 *
9373 *  @param context Rendering context.
9374 *
9375 **/
9376FunctionalTest18_19::FunctionalTest18_19(deqp::Context& context)
9377	: TestCase(context, "control_flow_and_returned_subroutine_values_used_as_subroutine_input",
9378			   "Makes sure that calling a subroutine with argument value returned by "
9379			   "another subroutine works correctly. Also checks that subroutine and "
9380			   "subroutine uniforms work as expected when used in connection with control "
9381			   "flow functions.")
9382	, m_has_test_passed(true)
9383	, m_n_points_to_draw(16) /* arbitrary value */
9384	, m_po_id(0)
9385	, m_po_subroutine_divide_by_two_location(GL_INVALID_INDEX)
9386	, m_po_subroutine_multiply_by_four_location(GL_INVALID_INDEX)
9387	, m_po_subroutine_returns_false_location(GL_INVALID_INDEX)
9388	, m_po_subroutine_returns_true_location(GL_INVALID_INDEX)
9389	, m_po_subroutine_uniform_bool_operator1(-1)
9390	, m_po_subroutine_uniform_bool_operator2(-1)
9391	, m_po_subroutine_uniform_vec4_processor1(-1)
9392	, m_po_subroutine_uniform_vec4_processor2(-1)
9393	, m_xfb_bo_id(0)
9394	, m_vao_id(0)
9395	, m_vs_id(0)
9396{
9397	/* Left blank intentionally */
9398}
9399
9400/** De-initializes all GL objects that may have been created during test execution */
9401void FunctionalTest18_19::deinit()
9402{
9403	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9404
9405	if (m_po_id != 0)
9406	{
9407		gl.deleteProgram(m_po_id);
9408
9409		m_po_id = 0;
9410	}
9411
9412	if (m_vao_id != 0)
9413	{
9414		gl.deleteVertexArrays(1, &m_vao_id);
9415
9416		m_vao_id = 0;
9417	}
9418
9419	if (m_vs_id != 0)
9420	{
9421		gl.deleteShader(m_vs_id);
9422
9423		m_vs_id = 0;
9424	}
9425
9426	if (m_xfb_bo_id != 0)
9427	{
9428		gl.deleteBuffers(1, &m_xfb_bo_id);
9429
9430		m_xfb_bo_id = 0;
9431	}
9432}
9433
9434/** Executes a single test iteration using user-specified properties. If the
9435 *  iterations fails, m_has_test_passed is set to false.
9436 *
9437 *  @param bool_operator1_subroutine_location Location of a subroutine to be assigned to
9438 *                                            bool_operator1 subroutine uniform.
9439 *  @param bool_operator2_subroutine_location Location of a subroutine to be assigned to
9440 *                                            bool_operator2 subroutine uniform.
9441 *  @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to
9442 *                                            vec4_operator1 subroutine uniform.
9443 *  @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to
9444 *                                            vec4_operator2 subroutine uniform.
9445 &**/
9446void FunctionalTest18_19::executeTest(glw::GLuint bool_operator1_subroutine_location,
9447									  glw::GLuint bool_operator2_subroutine_location,
9448									  glw::GLuint vec4_operator1_subroutine_location,
9449									  glw::GLuint vec4_operator2_subroutine_location)
9450{
9451	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9452
9453	/* Set up subroutines */
9454	glw::GLuint subroutine_configuration[4 /* total number of subroutines */] = { 0 };
9455
9456	subroutine_configuration[m_po_subroutine_uniform_bool_operator1]  = bool_operator1_subroutine_location;
9457	subroutine_configuration[m_po_subroutine_uniform_bool_operator2]  = bool_operator2_subroutine_location;
9458	subroutine_configuration[m_po_subroutine_uniform_vec4_processor1] = vec4_operator1_subroutine_location;
9459	subroutine_configuration[m_po_subroutine_uniform_vec4_processor2] = vec4_operator2_subroutine_location;
9460
9461	gl.useProgram(m_po_id);
9462	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
9463
9464	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 4 /* count */, subroutine_configuration);
9465	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed");
9466
9467	/* Draw test-specific number of points */
9468	gl.beginTransformFeedback(GL_POINTS);
9469	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
9470	{
9471		gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw);
9472		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
9473	}
9474	gl.endTransformFeedback();
9475	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
9476
9477	/* Map the BO storage into process space */
9478	const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
9479	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
9480
9481	verifyXFBData(xfb_data_ptr, bool_operator1_subroutine_location, bool_operator2_subroutine_location,
9482				  vec4_operator1_subroutine_location, vec4_operator2_subroutine_location);
9483
9484	/* Unmap BO storage */
9485	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
9486	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
9487}
9488
9489/** Retrieves body of a vertex shader to be used by the test. */
9490std::string FunctionalTest18_19::getVertexShaderBody() const
9491{
9492	return "#version 400\n"
9493		   "\n"
9494		   "subroutine bool bool_processor();\n"
9495		   "subroutine vec4 vec4_processor(in vec4 iparam);\n"
9496		   "\n"
9497		   "subroutine(bool_processor) bool returnsFalse()\n"
9498		   "{\n"
9499		   "    return false;\n"
9500		   "}\n"
9501		   "\n"
9502		   "subroutine(bool_processor) bool returnsTrue()\n"
9503		   "{\n"
9504		   "    return true;\n"
9505		   "}\n"
9506		   "\n"
9507		   "subroutine(vec4_processor) vec4 divideByTwo(in vec4 iparam)\n"
9508		   "{\n"
9509		   "    return iparam * vec4(0.5);\n"
9510		   "}\n"
9511		   "\n"
9512		   "subroutine(vec4_processor) vec4 multiplyByFour(in vec4 iparam)\n"
9513		   "{\n"
9514		   "    return iparam * vec4(4.0);\n"
9515		   "}\n"
9516		   "\n"
9517		   "subroutine uniform bool_processor bool_operator1;\n"
9518		   "subroutine uniform bool_processor bool_operator2;\n"
9519		   "subroutine uniform vec4_processor vec4_operator1;\n"
9520		   "subroutine uniform vec4_processor vec4_operator2;\n"
9521		   "\n"
9522		   "out float result;\n"
9523		   "\n"
9524		   "void main()\n"
9525		   "{\n"
9526		   "    if (bool_operator1() )\n"
9527		   "    {\n"
9528		   "        float value = float( (3 * gl_VertexID + 1) * 2);\n"
9529		   "\n"
9530		   "        while (bool_operator1() )\n"
9531		   "        {\n"
9532		   "            value /= float(gl_VertexID + 2);\n"
9533		   "\n"
9534		   "            if (value <= 1.0f) break;\n"
9535		   "        }\n"
9536		   "\n"
9537		   "        result = value;\n"
9538		   "    }\n"
9539		   "    else\n"
9540		   "    {\n"
9541		   "        vec4 value = vec4(gl_VertexID,     gl_VertexID + 1,\n"
9542		   "                          gl_VertexID + 2, gl_VertexID + 3);\n"
9543		   "\n"
9544		   "        switch (gl_VertexID % 2)\n"
9545		   "        {\n"
9546		   "            case 0:\n"
9547		   "            {\n"
9548		   "                for (int iteration = 0; iteration < gl_VertexID && bool_operator2(); ++iteration)\n"
9549		   "                {\n"
9550		   "                    value = vec4_operator2(vec4_operator1(value));\n"
9551		   "                }\n"
9552		   "\n"
9553		   "                break;\n"
9554		   "            }\n"
9555		   "\n"
9556		   "            case 1:\n"
9557		   "            {\n"
9558		   "                for (int iteration = 0; iteration < gl_VertexID * 2; ++iteration)\n"
9559		   "                {\n"
9560		   "                    value = vec4_operator1(vec4_operator2(value));\n"
9561		   "                }\n"
9562		   "\n"
9563		   "                break;\n"
9564		   "            }\n"
9565		   "        }\n"
9566		   "\n"
9567		   "        result = value.x + value.y + value.z + value.w;\n"
9568		   "\n"
9569		   "    }\n"
9570		   "}\n";
9571}
9572
9573/** Initializes all GL objects required to run the test. */
9574void FunctionalTest18_19::initTest()
9575{
9576	const glw::Functions& gl		  = m_context.getRenderContext().getFunctions();
9577	const char*			  varyings[1] = { "result" };
9578	std::string			  vs_body	 = getVertexShaderBody();
9579	const unsigned int	n_varyings  = sizeof(varyings) / sizeof(varyings[0]);
9580
9581	if (!Utils::buildProgram(gl, vs_body, "",						  /* tc_body */
9582							 "",									  /* te_body */
9583							 "",									  /* gs_body */
9584							 "",									  /* fs_body */
9585							 varyings, n_varyings, &m_vs_id, DE_NULL, /* out_tc_id */
9586							 DE_NULL,								  /* out_te_id */
9587							 DE_NULL,								  /* out_gs_id */
9588							 DE_NULL,								  /* out_fs_id */
9589							 &m_po_id))
9590	{
9591		TCU_FAIL("Failed to build test program object");
9592	}
9593
9594	/* Retrieve subroutine & subroutine uniform locations */
9595	m_po_subroutine_divide_by_two_location	= gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "divideByTwo");
9596	m_po_subroutine_multiply_by_four_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "multiplyByFour");
9597	m_po_subroutine_returns_false_location	= gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsFalse");
9598	m_po_subroutine_returns_true_location	 = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsTrue");
9599	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed");
9600
9601	if (m_po_subroutine_divide_by_two_location == GL_INVALID_INDEX ||
9602		m_po_subroutine_multiply_by_four_location == GL_INVALID_INDEX ||
9603		m_po_subroutine_returns_false_location == GL_INVALID_INDEX ||
9604		m_po_subroutine_returns_true_location == GL_INVALID_INDEX)
9605	{
9606		TCU_FAIL("glGetSubroutineIndex() returned GL_INVALID_INDEX for a valid subroutine");
9607	}
9608
9609	m_po_subroutine_uniform_bool_operator1 =
9610		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator1");
9611	m_po_subroutine_uniform_bool_operator2 =
9612		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator2");
9613	m_po_subroutine_uniform_vec4_processor1 =
9614		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator1");
9615	m_po_subroutine_uniform_vec4_processor2 =
9616		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator2");
9617	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed");
9618
9619	if (m_po_subroutine_uniform_bool_operator1 == -1 || m_po_subroutine_uniform_bool_operator2 == -1 ||
9620		m_po_subroutine_uniform_vec4_processor1 == -1 || m_po_subroutine_uniform_vec4_processor2 == -1)
9621	{
9622		TCU_FAIL("glGetSubroutineUniformLocation() returned -1 for an active subroutine uniform");
9623	}
9624
9625	/* Set up XFB BO */
9626	const unsigned int bo_size = static_cast<unsigned int>(sizeof(float) * m_n_points_to_draw);
9627
9628	gl.genBuffers(1, &m_xfb_bo_id);
9629	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
9630
9631	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
9632	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
9633
9634	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
9635	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
9636
9637	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_COPY);
9638	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9639
9640	/* Set up a VAO */
9641	gl.genVertexArrays(1, &m_vao_id);
9642	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9643
9644	gl.bindVertexArray(m_vao_id);
9645	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9646}
9647
9648/** Executes test iteration.
9649 *
9650 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9651 */
9652tcu::TestNode::IterateResult FunctionalTest18_19::iterate()
9653{
9654	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9655	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9656	{
9657		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9658	}
9659
9660	/* Initialize all GL objects required to run the test */
9661	initTest();
9662
9663	/* Iterate over all subroutine permutations */
9664	const glw::GLuint subroutine_bool_operators[] = { m_po_subroutine_returns_false_location,
9665													  m_po_subroutine_returns_true_location };
9666	const unsigned int n_subroutine_bool_operators =
9667		sizeof(subroutine_bool_operators) / sizeof(subroutine_bool_operators[0]);
9668
9669	const glw::GLuint subroutine_vec4_operators[] = { m_po_subroutine_divide_by_two_location,
9670													  m_po_subroutine_multiply_by_four_location };
9671	const unsigned int n_subroutine_vec4_operators =
9672		sizeof(subroutine_vec4_operators) / sizeof(subroutine_vec4_operators[0]);
9673
9674	for (unsigned int n_subroutine_uniform_bool_operator1 = 0;
9675		 n_subroutine_uniform_bool_operator1 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator1)
9676	{
9677		for (unsigned int n_subroutine_uniform_bool_operator2 = 0;
9678			 n_subroutine_uniform_bool_operator2 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator2)
9679		{
9680			for (unsigned int n_subroutine_uniform_vec4_operator1 = 0;
9681				 n_subroutine_uniform_vec4_operator1 < n_subroutine_vec4_operators;
9682				 ++n_subroutine_uniform_vec4_operator1)
9683			{
9684				for (unsigned int n_subroutine_uniform_vec4_operator2 = 0;
9685					 n_subroutine_uniform_vec4_operator2 < n_subroutine_vec4_operators;
9686					 ++n_subroutine_uniform_vec4_operator2)
9687				{
9688					executeTest(subroutine_bool_operators[n_subroutine_uniform_bool_operator1],
9689								subroutine_bool_operators[n_subroutine_uniform_bool_operator2],
9690								subroutine_vec4_operators[n_subroutine_uniform_vec4_operator1],
9691								subroutine_vec4_operators[n_subroutine_uniform_vec4_operator2]);
9692				} /* for (all subroutine vec4 operator subroutines used for processor2) */
9693			}	 /* for (all subroutine vec4 operator subroutines used for processor1) */
9694		}		  /* for (all subroutine bool operator subroutines used for operator2) */
9695	}			  /* for (all subroutine bool operator subroutines used for operator1) */
9696
9697	/* All done */
9698	if (m_has_test_passed)
9699	{
9700		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9701	}
9702	else
9703	{
9704		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
9705	}
9706
9707	return STOP;
9708}
9709
9710/** Divides input argument by two. The result value is returned to the
9711 *  caller.
9712 *
9713 *  @param data Input value.
9714 *
9715 *  @return As per description.
9716 **/
9717tcu::Vec4 FunctionalTest18_19::vec4operator_div2(tcu::Vec4 data)
9718{
9719	return data * 0.5f;
9720}
9721
9722/** Multiplies input argument by four. The result value is returned to the
9723 *  caller.
9724 *
9725 *  @param data Input value.
9726 *
9727 *  @return As per description.
9728 **/
9729tcu::Vec4 FunctionalTest18_19::vec4operator_mul4(tcu::Vec4 data)
9730{
9731	return data * 4.0f;
9732}
9733
9734/** Verifies data XFBed out by the vertex shader. It is assumed the subroutines were configured
9735 *  as per passed arguments, prior to the draw call.
9736 *
9737 *  If the result data is found to be invalid, m_has_test_passed is set to false.
9738 *
9739 *  @param data                               XFBed data.
9740 *  @param bool_operator1_subroutine_location Location of a subroutine to be assigned to
9741 *                                            bool_operator1 subroutine uniform.
9742 *  @param bool_operator2_subroutine_location Location of a subroutine to be assigned to
9743 *                                            bool_operator2 subroutine uniform.
9744 *  @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to
9745 *                                            vec4_operator1 subroutine uniform.
9746 *  @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to
9747 *                                            vec4_operator2 subroutine uniform.
9748 */
9749void FunctionalTest18_19::verifyXFBData(const glw::GLvoid* data, glw::GLuint bool_operator1_subroutine_location,
9750										glw::GLuint bool_operator2_subroutine_location,
9751										glw::GLuint vec4_operator1_subroutine_location,
9752										glw::GLuint vec4_operator2_subroutine_location)
9753{
9754	bool				bool_operator1_result = false;
9755	bool				bool_operator2_result = false;
9756	const float			epsilon				  = 1e-5f;
9757	PFNVEC4OPERATORPROC pVec4Operator1		  = NULL;
9758	PFNVEC4OPERATORPROC pVec4Operator2		  = NULL;
9759	const glw::GLfloat* traveller_ptr		  = (const glw::GLfloat*)data;
9760
9761	bool_operator1_result = (bool_operator1_subroutine_location == m_po_subroutine_returns_true_location);
9762	bool_operator2_result = (bool_operator2_subroutine_location == m_po_subroutine_returns_true_location);
9763	pVec4Operator1		  = (vec4_operator1_subroutine_location == m_po_subroutine_divide_by_two_location) ?
9764						 vec4operator_div2 :
9765						 vec4operator_mul4;
9766	pVec4Operator2 = (vec4_operator2_subroutine_location == m_po_subroutine_divide_by_two_location) ?
9767						 vec4operator_div2 :
9768						 vec4operator_mul4;
9769
9770	for (unsigned int n_vertex = 0; n_vertex < m_n_points_to_draw; ++n_vertex)
9771	{
9772		float expected_value = 0.0f;
9773
9774		if (bool_operator1_result)
9775		{
9776			float value = float((3 * n_vertex + 1) * 2);
9777
9778			while (bool_operator1_result)
9779			{
9780				value /= float(n_vertex + 2);
9781
9782				if (value <= 1.0f)
9783					break;
9784			}
9785
9786			expected_value = value;
9787		}
9788		else
9789		{
9790			tcu::Vec4 value((float)n_vertex, (float)n_vertex + 1, (float)n_vertex + 2, (float)n_vertex + 3);
9791
9792			switch (n_vertex % 2)
9793			{
9794			case 0:
9795			{
9796				for (unsigned int iteration = 0; iteration < n_vertex && bool_operator2_result; ++iteration)
9797				{
9798					value = pVec4Operator2(pVec4Operator1(value));
9799				}
9800
9801				break;
9802			}
9803
9804			case 1:
9805			{
9806				for (unsigned int iteration = 0; iteration < n_vertex * 2; ++iteration)
9807				{
9808					value = pVec4Operator1(pVec4Operator2(value));
9809				}
9810
9811				break;
9812			}
9813			} /* switch (n_vertex % 2) */
9814
9815			expected_value = value.x() + value.y() + value.z() + value.w();
9816		}
9817
9818		if (de::abs(expected_value - *traveller_ptr) > epsilon)
9819		{
9820			m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data was found to be invalid at index [" << n_vertex
9821							   << "]"
9822								  "for the following subroutine location configuration:"
9823								  " bool_operator1_subroutine_location:["
9824							   << bool_operator1_subroutine_location << "]"
9825																		" bool_operator2_subroutine_location:["
9826							   << bool_operator2_subroutine_location << "]"
9827																		" vec4_operator1_subroutine_location:["
9828							   << vec4_operator1_subroutine_location << "]"
9829																		" vec4_operator2_subroutine_location:["
9830							   << vec4_operator2_subroutine_location << "];"
9831																		" expected data:"
9832							   << expected_value << ", found:" << *traveller_ptr << tcu::TestLog::EndMessage;
9833
9834			m_has_test_passed = false;
9835		}
9836
9837		++traveller_ptr;
9838	} /* for (all drawn points) */
9839}
9840
9841/* Constants used by FunctionalTest20_21 */
9842const GLuint FunctionalTest20_21::m_n_shared_contexts				   = 4;
9843const GLuint FunctionalTest20_21::m_fragment_stage_index			   = 0;
9844const GLuint FunctionalTest20_21::m_geometry_stage_index			   = 1;
9845const GLuint FunctionalTest20_21::m_tesselation_control_stage_index	= 2;
9846const GLuint FunctionalTest20_21::m_tesselation_evaluation_stage_index = 3;
9847const GLuint FunctionalTest20_21::m_vertex_stage_index				   = 4;
9848
9849/** Set subroutine indices, indices are taken from one of two sets according to provided <bit_field>
9850 *
9851 * @param bit_field          Selects source of of index for each stage
9852 * @param subroutine_indices Array of two indices sets
9853 **/
9854void FunctionalTest20_21::subroutineUniformSet::set(GLuint bit_field, const subroutineUniformSet subroutine_indices[2])
9855{
9856	GLuint vertex_stage					= ((bit_field & (0x01 << 0)) >> 0);
9857	GLuint tesselation_control_stage	= ((bit_field & (0x01 << 1)) >> 1);
9858	GLuint tesselation_evaluation_stage = ((bit_field & (0x01 << 2)) >> 2);
9859	GLuint geometry_stage				= ((bit_field & (0x01 << 3)) >> 3);
9860	GLuint fragment_stage				= ((bit_field & (0x01 << 4)) >> 4);
9861
9862	m_vertex_shader_stage = subroutine_indices[vertex_stage].m_vertex_shader_stage;
9863	m_tesselation_control_shader_stage =
9864		subroutine_indices[tesselation_control_stage].m_tesselation_control_shader_stage;
9865	m_tesselation_evaluation_shader_stage =
9866		subroutine_indices[tesselation_evaluation_stage].m_tesselation_evaluation_shader_stage;
9867	m_geometry_shader_stage = subroutine_indices[geometry_stage].m_geometry_shader_stage;
9868	m_fragment_shader_stage = subroutine_indices[fragment_stage].m_fragment_shader_stage;
9869}
9870
9871/** Negated comparison of two sets
9872 *
9873 * @param arg Instance that will be compared to this
9874 *
9875 * @return false when both objects are equal, true otherwise
9876 **/
9877bool FunctionalTest20_21::subroutineUniformSet::operator!=(const subroutineUniformSet& arg) const
9878{
9879	if ((arg.m_vertex_shader_stage != m_vertex_shader_stage) ||
9880		(arg.m_tesselation_control_shader_stage != m_tesselation_control_shader_stage) ||
9881		(arg.m_tesselation_evaluation_shader_stage != m_tesselation_evaluation_shader_stage) ||
9882		(arg.m_geometry_shader_stage != m_geometry_shader_stage) ||
9883		(arg.m_fragment_shader_stage != m_fragment_shader_stage))
9884	{
9885		return true;
9886	}
9887
9888	return false;
9889}
9890
9891/** Constructor.
9892 *
9893 *  @param context Rendering context.
9894 *
9895 **/
9896FunctionalTest20_21::FunctionalTest20_21(deqp::Context& context)
9897	: TestCase(context, "multiple_contexts",
9898			   "Verifies that shader uniforms are preserved when rendering context is switched.")
9899{
9900	for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
9901	{
9902		m_program_pipelines[i] = 0;
9903	}
9904
9905	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
9906	{
9907		m_shared_contexts[i] = 0;
9908	}
9909}
9910
9911/** Deinitializes all GL objects that may have been created during
9912 *  test execution.
9913 **/
9914void FunctionalTest20_21::deinit()
9915{
9916	/* GL entry points */
9917	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9918
9919	for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
9920	{
9921		if (0 != m_program_pipelines[i])
9922		{
9923			gl.deleteProgramPipelines(1, &m_program_pipelines[i]);
9924			m_program_pipelines[i] = 0;
9925		}
9926	}
9927
9928	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
9929	{
9930		if (0 != m_shared_contexts[i])
9931		{
9932			delete m_shared_contexts[i];
9933			m_shared_contexts[i] = 0;
9934		}
9935	}
9936
9937	m_context.getRenderContext().makeCurrent();
9938}
9939
9940/** Executes test iteration.
9941 *
9942 *  @return Returns STOP
9943 */
9944tcu::TestNode::IterateResult FunctionalTest20_21::iterate()
9945{
9946	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9947	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9948	{
9949		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9950	}
9951
9952	/* Test cases, values stored here are used as bit fields */
9953	static const GLuint test_cases[][m_n_shared_contexts + 1] = {
9954		{ 0, 1, 2, 3, 4 },		{ 1, 2, 3, 4, 0 },		{ 2, 3, 4, 0, 1 },		{ 3, 4, 0, 1, 2 },
9955		{ 4, 0, 1, 2, 3 },		{ 27, 28, 29, 30, 31 }, { 28, 29, 30, 31, 27 }, { 29, 30, 31, 27, 28 },
9956		{ 30, 31, 27, 28, 29 }, { 31, 27, 28, 29, 30 },
9957	};
9958	static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
9959
9960	/* Prepare contexts */
9961	initSharedContexts();
9962
9963	/* Test result */
9964	bool result = true;
9965
9966	/* Program pointers */
9967	Utils::program* program_pointers[5];
9968
9969	/* Test monolithic program */
9970	{
9971		/* Prepare program */
9972		Utils::program program(m_context);
9973
9974		program_pointers[m_fragment_stage_index] = &program;
9975
9976		prepareProgram(program_pointers, false);
9977
9978		/* Execute test */
9979		if (false == testProgram(program_pointers, false, test_cases, n_test_cases))
9980		{
9981			m_context.getTestContext().getLog() << tcu::TestLog::Message
9982												<< "Last error message was caused by monolithic program."
9983												<< tcu::TestLog::EndMessage;
9984
9985			result = false;
9986		}
9987	}
9988
9989	/* Test separable programs */
9990	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
9991	{
9992		/* Prepare programs */
9993		Utils::program vertex_program(m_context);
9994		Utils::program tesselation_control_program(m_context);
9995		Utils::program tesselation_evaluation_program(m_context);
9996		Utils::program geometry_program(m_context);
9997		Utils::program fragment_program(m_context);
9998
9999		program_pointers[m_fragment_stage_index]			   = &fragment_program;
10000		program_pointers[m_geometry_stage_index]			   = &geometry_program;
10001		program_pointers[m_tesselation_control_stage_index]	= &tesselation_control_program;
10002		program_pointers[m_tesselation_evaluation_stage_index] = &tesselation_evaluation_program;
10003		program_pointers[m_vertex_stage_index]				   = &vertex_program;
10004
10005		prepareProgram(program_pointers, true);
10006
10007		/* Execute test */
10008		if (false == testProgram(program_pointers, true, test_cases, n_test_cases))
10009		{
10010			m_context.getTestContext().getLog() << tcu::TestLog::Message
10011												<< "Last error message was caused by separable program."
10012												<< tcu::TestLog::EndMessage;
10013			result = false;
10014		}
10015	}
10016
10017	/* All done */
10018	if (true == result)
10019	{
10020		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10021	}
10022	else
10023	{
10024		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10025	}
10026
10027	return tcu::TestNode::STOP;
10028}
10029
10030/** Query state of subroutine uniforms of current program/pipeline
10031 *
10032 * @param set Storage for results
10033 **/
10034void FunctionalTest20_21::captureCurrentSubroutineSet(subroutineUniformSet& set)
10035{
10036	/* GL entry points */
10037	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10038
10039	/* Fragment */
10040	gl.getUniformSubroutineuiv(GL_FRAGMENT_SHADER, m_subroutine_uniform_locations.m_fragment_shader_stage,
10041							   &set.m_fragment_shader_stage);
10042	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10043
10044	/* Geometry */
10045	gl.getUniformSubroutineuiv(GL_GEOMETRY_SHADER, m_subroutine_uniform_locations.m_geometry_shader_stage,
10046							   &set.m_geometry_shader_stage);
10047	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10048
10049	/* Tess ctrl */
10050	gl.getUniformSubroutineuiv(GL_TESS_CONTROL_SHADER,
10051							   m_subroutine_uniform_locations.m_tesselation_control_shader_stage,
10052							   &set.m_tesselation_control_shader_stage);
10053	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10054
10055	/* Tess eval */
10056	gl.getUniformSubroutineuiv(GL_TESS_EVALUATION_SHADER,
10057							   m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage,
10058							   &set.m_tesselation_evaluation_shader_stage);
10059	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10060
10061	/* Vertex */
10062	gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_subroutine_uniform_locations.m_vertex_shader_stage,
10063							   &set.m_vertex_shader_stage);
10064	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10065}
10066
10067/** Get shaders' source code
10068 *
10069 * @param out_vertex_shader_code                 Vertex source code
10070 * @param out_tesselation_control_shader_code    Tess ctrl source code
10071 * @param out_tesselation_evaluation_shader_code Tess eval source code
10072 * @param out_geometry_shader_code               Geometry source code
10073 * @param out_fragment_shader_code               Fragment source code
10074 **/
10075void FunctionalTest20_21::getShaders(const glw::GLchar*& out_vertex_shader_code,
10076									 const glw::GLchar*& out_tesselation_control_shader_code,
10077									 const glw::GLchar*& out_tesselation_evaluation_shader_code,
10078									 const glw::GLchar*& out_geometry_shader_code,
10079									 const glw::GLchar*& out_fragment_shader_code)
10080{
10081	static const GLchar* vertex_shader_code = "#version 400 core\n"
10082											  "#extension GL_ARB_shader_subroutine : require\n"
10083											  "\n"
10084											  "precision highp float;\n"
10085											  "\n"
10086											  "// Subroutine type\n"
10087											  "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10088											  "\n"
10089											  "// Subroutine definition\n"
10090											  "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10091											  "{\n"
10092											  "    return left + right;\n"
10093											  "}\n"
10094											  "\n"
10095											  "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10096											  "{\n"
10097											  "    return left * right;\n"
10098											  "}\n"
10099											  "\n"
10100											  "// Sub routine uniform\n"
10101											  "subroutine uniform routine_type routine;\n"
10102											  "\n"
10103											  "// Input data\n"
10104											  "uniform vec4 uni_vs_left;\n"
10105											  "uniform vec4 uni_vs_right;\n"
10106											  "\n"
10107											  "// Output\n"
10108											  "out vec4 vs_tcs_result;\n"
10109											  "\n"
10110											  "void main()\n"
10111											  "{\n"
10112											  "    vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n"
10113											  "}\n"
10114											  "\n";
10115
10116	static const GLchar* tesselation_control_shader_code =
10117		"#version 400 core\n"
10118		"#extension GL_ARB_shader_subroutine : require\n"
10119		"\n"
10120		"precision highp float;\n"
10121		"\n"
10122		"layout(vertices = 1) out;\n"
10123		"\n"
10124		"// Subroutine type\n"
10125		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10126		"\n"
10127		"// Subroutine definition\n"
10128		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10129		"{\n"
10130		"    return left + right;\n"
10131		"}\n"
10132		"\n"
10133		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10134		"{\n"
10135		"    return left * right;\n"
10136		"}\n"
10137		"\n"
10138		"// Sub routine uniform\n"
10139		"subroutine uniform routine_type routine;\n"
10140		"\n"
10141		"// Input data\n"
10142		"uniform vec4 uni_tcs_left;\n"
10143		"uniform vec4 uni_tcs_right;\n"
10144		"\n"
10145		"in vec4 vs_tcs_result[];\n"
10146		"\n"
10147		"// Output\n"
10148		"out vec4 tcs_tes_result[];\n"
10149		"\n"
10150		"void main()\n"
10151		"{\n"
10152		"    gl_TessLevelOuter[0] = 1.0;\n"
10153		"    gl_TessLevelOuter[1] = 1.0;\n"
10154		"    gl_TessLevelOuter[2] = 1.0;\n"
10155		"    gl_TessLevelOuter[3] = 1.0;\n"
10156		"    gl_TessLevelInner[0] = 1.0;\n"
10157		"    gl_TessLevelInner[1] = 1.0;\n"
10158		"\n"
10159		"    tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n"
10160		"}\n"
10161		"\n";
10162
10163	static const GLchar* tesselation_evaluation_shader_code =
10164		"#version 400 core\n"
10165		"#extension GL_ARB_shader_subroutine : require\n"
10166		"\n"
10167		"precision highp float;\n"
10168		"\n"
10169		"layout(isolines, point_mode) in;\n"
10170		"\n"
10171		"// Subroutine type\n"
10172		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10173		"\n"
10174		"// Subroutine definition\n"
10175		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10176		"{\n"
10177		"    return left + right;\n"
10178		"}\n"
10179		"\n"
10180		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10181		"{\n"
10182		"    return left * right;\n"
10183		"}\n"
10184		"\n"
10185		"// Sub routine uniform\n"
10186		"subroutine uniform routine_type routine;\n"
10187		"\n"
10188		"// Input data\n"
10189		"uniform vec4 uni_tes_left;\n"
10190		"uniform vec4 uni_tes_right;\n"
10191		"\n"
10192		"in vec4 tcs_tes_result[];\n"
10193		"\n"
10194		"// Output\n"
10195		"out vec4 tes_gs_result;\n"
10196		"\n"
10197		"void main()\n"
10198		"{\n"
10199		"    tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n"
10200		"}\n"
10201		"\n";
10202
10203	static const GLchar* geometry_shader_code =
10204		"#version 400 core\n"
10205		"#extension GL_ARB_shader_subroutine : require\n"
10206		"\n"
10207		"precision highp float;\n"
10208		"\n"
10209		"layout(points)                   in;\n"
10210		"layout(points, max_vertices = 1) out;\n"
10211		"\n"
10212		"// Subroutine type\n"
10213		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10214		"\n"
10215		"// Subroutine definition\n"
10216		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10217		"{\n"
10218		"    return left + right;\n"
10219		"}\n"
10220		"\n"
10221		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10222		"{\n"
10223		"    return left * right;\n"
10224		"}\n"
10225		"\n"
10226		"// Sub routine uniform\n"
10227		"subroutine uniform routine_type routine;\n"
10228		"\n"
10229		"// Input data\n"
10230		"uniform vec4 uni_gs_left;\n"
10231		"uniform vec4 uni_gs_right;\n"
10232		"\n"
10233		"in vec4 tes_gs_result[];\n"
10234		"\n"
10235		"// Output\n"
10236		"out vec4 gs_fs_result;\n"
10237		"\n"
10238		"void main()\n"
10239		"{\n"
10240		"    gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n"
10241		"}\n"
10242		"\n";
10243
10244	static const GLchar* fragmenty_shader_code =
10245		"#version 400 core\n"
10246		"#extension GL_ARB_shader_subroutine : require\n"
10247		"\n"
10248		"precision highp float;\n"
10249		"\n"
10250		"// Subroutine type\n"
10251		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10252		"\n"
10253		"// Subroutine definition\n"
10254		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10255		"{\n"
10256		"    return left + right;\n"
10257		"}\n"
10258		"\n"
10259		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10260		"{\n"
10261		"    return left * right;\n"
10262		"}\n"
10263		"\n"
10264		"// Sub routine uniform\n"
10265		"subroutine uniform routine_type routine;\n"
10266		"\n"
10267		"// Input data\n"
10268		"uniform vec4 uni_fs_left;\n"
10269		"uniform vec4 uni_fs_right;\n"
10270		"\n"
10271		"in vec4 gs_fs_result;\n"
10272		"\n"
10273		"// Output\n"
10274		"out vec4 fs_out_result;\n"
10275		"\n"
10276		"void main()\n"
10277		"{\n"
10278		"    fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n"
10279		"}\n"
10280		"\n";
10281
10282	out_vertex_shader_code				   = vertex_shader_code;
10283	out_tesselation_control_shader_code	= tesselation_control_shader_code;
10284	out_tesselation_evaluation_shader_code = tesselation_evaluation_shader_code;
10285	out_geometry_shader_code			   = geometry_shader_code;
10286	out_fragment_shader_code			   = fragmenty_shader_code;
10287}
10288
10289/** Create <m_n_shared_contexts> shared contexts
10290 *
10291 **/
10292void FunctionalTest20_21::initSharedContexts()
10293{
10294	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10295	{
10296		m_shared_contexts[i] = m_context.createSharedContext();
10297	}
10298}
10299
10300/** Prepare program(s)
10301 *
10302 * @param programs     An array of 5 programs' pointers. If monolithic program is prepared that only index m_fragment_stage_index should be initialized, otherwise all 5
10303 * @param is_separable Select if monolithic or separable programs should be prepared
10304 **/
10305void FunctionalTest20_21::prepareProgram(Utils::program** programs, bool is_separable)
10306{
10307	/* Get shader sources */
10308	const GLchar* vertex_shader_code;
10309	const GLchar* tesselation_control_shader_code;
10310	const GLchar* tesselation_evaluation_shader_code;
10311	const GLchar* geometry_shader_code;
10312	const GLchar* fragmenty_shader_code;
10313
10314	getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
10315			   geometry_shader_code, fragmenty_shader_code);
10316
10317	/* Subroutines and uniform names */
10318	static const GLchar* subroutine_names[] = { "add", "multiply" };
10319	static const GLuint  n_subroutines		= sizeof(subroutine_names) / sizeof(subroutine_names[0]);
10320
10321	static const GLchar* subroutine_uniform_name = "routine";
10322
10323	/* Build program */
10324	if (false == is_separable)
10325	{
10326		programs[0]->build(0 /* compute shader source */, fragmenty_shader_code, geometry_shader_code,
10327						   tesselation_control_shader_code, tesselation_evaluation_shader_code, vertex_shader_code,
10328						   0 /* varying_names */, 0 /* n_varying_names */);
10329
10330		programs[m_geometry_stage_index]			   = programs[m_fragment_stage_index];
10331		programs[m_tesselation_control_stage_index]	= programs[m_fragment_stage_index];
10332		programs[m_tesselation_evaluation_stage_index] = programs[m_fragment_stage_index];
10333		programs[m_vertex_stage_index]				   = programs[m_fragment_stage_index];
10334	}
10335	else
10336	{
10337		programs[m_fragment_stage_index]->build(0, fragmenty_shader_code, 0, 0, 0, 0, 0, 0, true);
10338		programs[m_geometry_stage_index]->build(0, 0, geometry_shader_code, 0, 0, 0, 0, 0, true);
10339		programs[m_tesselation_control_stage_index]->build(0, 0, 0, tesselation_control_shader_code, 0, 0, 0, 0, true);
10340		programs[m_tesselation_evaluation_stage_index]->build(0, 0, 0, 0, tesselation_evaluation_shader_code, 0, 0, 0,
10341															  true);
10342		programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true);
10343	}
10344
10345	/* Get subroutine indices */
10346	for (GLuint i = 0; i < n_subroutines; ++i)
10347	{
10348		m_subroutine_indices[i].m_fragment_shader_stage =
10349			programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER);
10350
10351		m_subroutine_indices[i].m_geometry_shader_stage =
10352			programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER);
10353
10354		m_subroutine_indices[i].m_tesselation_control_shader_stage =
10355			programs[m_tesselation_control_stage_index]->getSubroutineIndex(subroutine_names[i],
10356																			GL_TESS_CONTROL_SHADER);
10357
10358		m_subroutine_indices[i].m_tesselation_evaluation_shader_stage =
10359			programs[m_tesselation_evaluation_stage_index]->getSubroutineIndex(subroutine_names[i],
10360																			   GL_TESS_EVALUATION_SHADER);
10361
10362		m_subroutine_indices[i].m_vertex_shader_stage =
10363			programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER);
10364	}
10365
10366	/* Get subroutine uniform locations */
10367	m_subroutine_uniform_locations.m_fragment_shader_stage =
10368		programs[m_fragment_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_FRAGMENT_SHADER);
10369
10370	m_subroutine_uniform_locations.m_geometry_shader_stage =
10371		programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER);
10372
10373	m_subroutine_uniform_locations.m_tesselation_control_shader_stage =
10374		programs[m_tesselation_control_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
10375																				  GL_TESS_CONTROL_SHADER);
10376
10377	m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage =
10378		programs[m_tesselation_evaluation_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
10379																					 GL_TESS_EVALUATION_SHADER);
10380
10381	m_subroutine_uniform_locations.m_vertex_shader_stage =
10382		programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER);
10383}
10384
10385/** Generate program pipeline for current context and attach separable programs
10386 *
10387 * @param out_pipeline_id Id of generated pipeline
10388 * @param programs        Collection of separable programs
10389 **/
10390void FunctionalTest20_21::prepareProgramPipeline(glw::GLuint& out_pipeline_id, Utils::program** programs)
10391{
10392	/* GL entry points */
10393	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10394
10395	/* Generate */
10396	gl.genProgramPipelines(1, &out_pipeline_id);
10397	GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
10398
10399	/* Bind */
10400	gl.bindProgramPipeline(out_pipeline_id);
10401	GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
10402
10403	/* Set up programs */
10404	gl.useProgramStages(out_pipeline_id, GL_FRAGMENT_SHADER_BIT, programs[m_fragment_stage_index]->m_program_object_id);
10405	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10406
10407	gl.useProgramStages(out_pipeline_id, GL_GEOMETRY_SHADER_BIT, programs[m_geometry_stage_index]->m_program_object_id);
10408	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10409
10410	gl.useProgramStages(out_pipeline_id, GL_TESS_CONTROL_SHADER_BIT,
10411						programs[m_tesselation_control_stage_index]->m_program_object_id);
10412	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10413
10414	gl.useProgramStages(out_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT,
10415						programs[m_tesselation_evaluation_stage_index]->m_program_object_id);
10416	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10417
10418	gl.useProgramStages(out_pipeline_id, GL_VERTEX_SHADER_BIT, programs[m_vertex_stage_index]->m_program_object_id);
10419	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10420}
10421
10422/** Test specific case
10423 *
10424 * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context
10425 *
10426 * @return True if test pass, false otherwise
10427 **/
10428bool FunctionalTest20_21::testCase(const glw::GLuint bit_field[5])
10429{
10430	/* Storage for subroutine indices */
10431	subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1];
10432	subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1];
10433
10434	/* Prepare subroutine_indices with bit fields */
10435	for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
10436	{
10437		subroutine_indices[i].set(bit_field[i], m_subroutine_indices);
10438	};
10439
10440	/* Update subroutine uniforms, each context gets different set */
10441	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10442	{
10443		m_shared_contexts[i]->makeCurrent();
10444		updateCurrentSubroutineSet(subroutine_indices[i]);
10445	}
10446
10447	m_context.getRenderContext().makeCurrent();
10448	updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]);
10449
10450	/* Capture subroutine uniforms */
10451	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10452	{
10453		m_shared_contexts[i]->makeCurrent();
10454		captureCurrentSubroutineSet(captured_subroutine_indices[i]);
10455	}
10456
10457	m_context.getRenderContext().makeCurrent();
10458	captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]);
10459
10460	/* Verify that captured uniforms match expected values */
10461	for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
10462	{
10463		if (subroutine_indices[i] != captured_subroutine_indices[i])
10464		{
10465			m_context.getTestContext().getLog()
10466				<< tcu::TestLog::Message << "Error."
10467				<< " Context: " << i << " VS, expected: " << subroutine_indices[i].m_vertex_shader_stage
10468				<< " captured: " << captured_subroutine_indices[i].m_vertex_shader_stage
10469				<< " TCS, expected: " << subroutine_indices[i].m_tesselation_control_shader_stage
10470				<< " captured: " << captured_subroutine_indices[i].m_tesselation_control_shader_stage
10471				<< " TES, expected: " << subroutine_indices[i].m_tesselation_evaluation_shader_stage
10472				<< " captured: " << captured_subroutine_indices[i].m_tesselation_evaluation_shader_stage
10473				<< " GS, expected: " << subroutine_indices[i].m_geometry_shader_stage
10474				<< " captured: " << captured_subroutine_indices[i].m_geometry_shader_stage
10475				<< " FS, expected: " << subroutine_indices[i].m_fragment_shader_stage
10476				<< " captured: " << captured_subroutine_indices[i].m_fragment_shader_stage << tcu::TestLog::EndMessage;
10477
10478			return false;
10479		}
10480	}
10481
10482	return true;
10483}
10484
10485/** Test a program or pipeline
10486 *
10487 * @param programs     An array of 5 programs\ pointers, as in preparePrograms
10488 * @param is_separable Selects if monolithic or separable programs should be used
10489 * @param test_cases   Collection of test cases
10490 * @param n_test_cases Number of test cases
10491 *
10492 * @return True if all cases pass, false otherwise
10493 **/
10494bool FunctionalTest20_21::testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
10495									  glw::GLuint n_test_cases)
10496{
10497	/* Set program/pipeline as current for all contexts */
10498	if (false == is_separable)
10499	{
10500		programs[0]->use();
10501
10502		for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10503		{
10504			m_shared_contexts[i]->makeCurrent();
10505			programs[0]->use();
10506		}
10507	}
10508	else
10509	{
10510		/* GL entry points */
10511		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10512
10513		/* Make sure that program pipeline will be used */
10514		gl.useProgram(0);
10515		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
10516
10517		prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs);
10518
10519		for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10520		{
10521			m_shared_contexts[i]->makeCurrent();
10522
10523			/* Make sure that program pipeline will be used */
10524			gl.useProgram(0);
10525			GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
10526
10527			prepareProgramPipeline(m_program_pipelines[i], programs);
10528		}
10529	}
10530
10531	/* Execute test */
10532	bool result = true;
10533	for (GLuint i = 0; i < n_test_cases; ++i)
10534	{
10535		if (false == testCase(test_cases[i]))
10536		{
10537			result = false;
10538			break;
10539		}
10540	}
10541
10542	return result;
10543}
10544
10545/** Set up subroutine uniforms for current program or pipeline
10546 *
10547 * @param set Set of subroutine indices
10548 **/
10549void FunctionalTest20_21::updateCurrentSubroutineSet(const subroutineUniformSet& set)
10550{
10551	/* GL entry points */
10552	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10553
10554	/* Fragment */
10555	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage);
10556	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10557
10558	/* Geometry */
10559	gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage);
10560	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10561
10562	/* Tess ctrl */
10563	gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage);
10564	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10565
10566	/* Tess eval */
10567	gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage);
10568	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10569
10570	/* Vertex */
10571	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage);
10572	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10573}
10574
10575/** Constructor.
10576 *
10577 *  @param context Rendering context.
10578 *
10579 **/
10580NegativeTest1::NegativeTest1(deqp::Context& context)
10581	: TestCase(context, "subroutine_errors", "Verifies all GL_INVALID_OPERATION, GL_INVALID_VALUE, GL_INVALID ENUM "
10582											 "errors related to subroutine usage are properly generated.")
10583	, m_has_test_passed(true)
10584	, m_po_active_subroutine_uniform_locations(0)
10585	, m_po_active_subroutine_uniforms(0)
10586	, m_po_active_subroutines(0)
10587	, m_po_subroutine_uniform_function_index(-1)
10588	, m_po_subroutine_uniform_function2_index(-1)
10589	, m_po_subroutine_test1_index(GL_INVALID_INDEX)
10590	, m_po_subroutine_test2_index(GL_INVALID_INDEX)
10591	, m_po_subroutine_test3_index(GL_INVALID_INDEX)
10592	, m_po_not_linked_id(0)
10593	, m_po_id(0)
10594	, m_vs_id(0)
10595{
10596	/* Left blank intentionally */
10597}
10598
10599/** Deinitializes all GL objects that may have been created during
10600 *  test execution.
10601 **/
10602void NegativeTest1::deinit()
10603{
10604	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10605
10606	if (m_po_id != 0)
10607	{
10608		gl.deleteProgram(m_po_id);
10609
10610		m_po_id = 0;
10611	}
10612
10613	if (m_po_not_linked_id != 0)
10614	{
10615		gl.deleteProgram(m_po_not_linked_id);
10616
10617		m_po_not_linked_id = 0;
10618	}
10619
10620	if (m_vs_id != 0)
10621	{
10622		gl.deleteShader(m_vs_id);
10623
10624		m_vs_id = 0;
10625	}
10626}
10627
10628/** Initializes all GL objects required to run the test.  */
10629void NegativeTest1::initTest()
10630{
10631	glw::GLint			  compile_status = GL_FALSE;
10632	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
10633
10634	/* Create program objects */
10635	m_po_not_linked_id = gl.createProgram();
10636	m_po_id			   = gl.createProgram();
10637	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
10638
10639	/* Create vertex shader object */
10640	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10641	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
10642
10643	/* Set up vertex shader */
10644	const char* vs_body = "#version 400\n"
10645						  "\n"
10646						  "#extension GL_ARB_shader_subroutine : require\n"
10647						  "\n"
10648						  "subroutine void subroutineType (out ivec2 arg);\n"
10649						  "subroutine void subroutineType2(out ivec4 arg);\n"
10650						  "\n"
10651						  "subroutine(subroutineType) void test1(out ivec2 arg)\n"
10652						  "{\n"
10653						  "    arg = ivec2(1, 2);\n"
10654						  "}\n"
10655						  "subroutine(subroutineType) void test2(out ivec2 arg)\n"
10656						  "{\n"
10657						  "    arg = ivec2(3,4);\n"
10658						  "}\n"
10659						  "subroutine(subroutineType2) void test3(out ivec4 arg)\n"
10660						  "{\n"
10661						  "    arg = ivec4(1, 2, 3, 4);\n"
10662						  "}\n"
10663						  "\n"
10664						  "subroutine uniform subroutineType  function;\n"
10665						  "subroutine uniform subroutineType2 function2;\n"
10666						  "\n"
10667						  "void main()\n"
10668						  "{\n"
10669						  "    ivec2 test;\n"
10670						  "    ivec4 test2;\n"
10671						  "\n"
10672						  "    function(test);\n"
10673						  "\n"
10674						  "    if (test.x > 2)\n"
10675						  "    {\n"
10676						  "        gl_Position = vec4(1);\n"
10677						  "    }\n"
10678						  "    else\n"
10679						  "    {\n"
10680						  "        function2(test2);\n"
10681						  "\n"
10682						  "        gl_Position = vec4(float(test2.x) );\n"
10683						  "    }\n"
10684						  "}\n";
10685
10686	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
10687	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
10688
10689	gl.compileShader(m_vs_id);
10690	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
10691
10692	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
10693	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
10694
10695	if (compile_status == GL_FALSE)
10696	{
10697		TCU_FAIL("Shader compilation failed");
10698	}
10699
10700	/* Set up & link the test program object */
10701	glw::GLint link_status = GL_FALSE;
10702
10703	gl.attachShader(m_po_id, m_vs_id);
10704	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
10705
10706	gl.linkProgram(m_po_id);
10707	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
10708
10709	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
10710	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
10711
10712	if (link_status == GL_FALSE)
10713	{
10714		TCU_FAIL("Program linking failed");
10715	}
10716
10717	/* Query test program object's properties */
10718	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
10719						 &m_po_active_subroutine_uniform_locations);
10720	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &m_po_active_subroutine_uniforms);
10721	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &m_po_active_subroutines);
10722	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call(s) failed.");
10723
10724	if (m_po_active_subroutine_uniform_locations != 2)
10725	{
10726		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS value returned");
10727	}
10728
10729	m_po_subroutine_test1_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test1");
10730	m_po_subroutine_test2_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test2");
10731	m_po_subroutine_test3_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test3");
10732	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
10733
10734	if (m_po_subroutine_test1_index == GL_INVALID_INDEX || m_po_subroutine_test2_index == GL_INVALID_INDEX ||
10735		m_po_subroutine_test3_index == GL_INVALID_INDEX)
10736	{
10737		TCU_FAIL("Invalid subroutine index returned");
10738	}
10739
10740	m_po_subroutine_uniform_function_index  = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function");
10741	m_po_subroutine_uniform_function2_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function2");
10742	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
10743
10744	if (m_po_subroutine_uniform_function_index == -1 || m_po_subroutine_uniform_function2_index == -1)
10745	{
10746		TCU_FAIL("Invalid subroutine uniform index returned");
10747	}
10748}
10749
10750/** Executes test iteration.
10751 *
10752 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10753 */
10754tcu::TestNode::IterateResult NegativeTest1::iterate()
10755{
10756	glw::GLenum			  error_code = GL_NO_ERROR;
10757	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
10758
10759	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10760	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10761	{
10762		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10763	}
10764
10765	/* Initialize GL objects required to run the test */
10766	initTest();
10767
10768	/* The error INVALID_OPERATION is generated by GetSubroutineUniformLocation
10769	 * if the program object identified by <program> has not been successfully
10770	 * linked.
10771	 */
10772	gl.getSubroutineUniformLocation(m_po_not_linked_id, GL_FRAGMENT_SHADER, "subroutine_uniform_name");
10773
10774	error_code = gl.getError();
10775
10776	if (error_code != GL_INVALID_OPERATION)
10777	{
10778		m_testCtx.getLog() << tcu::TestLog::Message
10779						   << "glGetSubroutineUniformLocation() does not generate GL_INVALID_OPERATION "
10780							  "error code when called for a non-linked program object."
10781						   << tcu::TestLog::EndMessage;
10782
10783		m_has_test_passed = false;
10784	}
10785
10786	/* The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or
10787	 * GetActiveSubroutineUniformName if <index> is greater than or equal to the
10788	 * value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage.
10789	 */
10790	glw::GLint temp_length = 0;
10791	glw::GLint temp_values = 0;
10792
10793	gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms,
10794									GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10795	error_code = gl.getError();
10796
10797	if (error_code == GL_INVALID_VALUE)
10798	{
10799		gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10800										GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10801
10802		error_code = gl.getError();
10803	}
10804
10805	if (error_code != GL_INVALID_VALUE)
10806	{
10807		m_testCtx.getLog() << tcu::TestLog::Message
10808						   << "glGetActiveSubroutineUniformiv() does not generate GL_INVALID_VALUE "
10809							  "when passed <index> argument that is greater than or equal to "
10810							  "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10811						   << tcu::TestLog::EndMessage;
10812
10813		m_has_test_passed = false;
10814	}
10815
10816	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 0, /* bufsize */
10817									  &temp_length, DE_NULL);										 /* name */
10818	error_code = gl.getError();
10819
10820	if (error_code == GL_INVALID_VALUE)
10821	{
10822		gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10823										  0,					  /* bufsize */
10824										  &temp_length, DE_NULL); /* name */
10825
10826		error_code = gl.getError();
10827	}
10828
10829	if (error_code != GL_INVALID_VALUE)
10830	{
10831		m_testCtx.getLog() << tcu::TestLog::Message
10832						   << "glGetActiveSubroutineUniformName() does not generate GL_INVALID_VALUE "
10833							  "when passed <index> argument that is greater than or equal to "
10834							  "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10835						   << tcu::TestLog::EndMessage;
10836
10837		m_has_test_passed = false;
10838	}
10839
10840	/* The error INVALID_VALUE is generated by GetActiveSubroutineName if <index>
10841	 * is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader
10842	 * stage.
10843	 */
10844	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines, 0, /* bufsize */
10845							   &temp_length, DE_NULL);								  /* name */
10846	error_code = gl.getError();
10847
10848	if (error_code == GL_INVALID_VALUE)
10849	{
10850		gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines + 1, 0, /* bufsize */
10851								   &temp_length, DE_NULL);									  /* name */
10852
10853		error_code = gl.getError();
10854	}
10855
10856	if (error_code != GL_INVALID_VALUE)
10857	{
10858		m_testCtx.getLog() << tcu::TestLog::Message << "glGetActiveSubroutineName() does not generate GL_INVALID_VALUE "
10859													   "when passed <index> argument that is greater than or equal to "
10860													   "the value of GL_ACTIVE_SUBROUTINES."
10861						   << tcu::TestLog::EndMessage;
10862
10863		m_has_test_passed = false;
10864	}
10865
10866	/* The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count>
10867	 * is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the
10868	 * shader stage <shadertype>.
10869	 */
10870	glw::GLuint index = 0;
10871
10872	gl.useProgram(m_po_id);
10873	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10874
10875	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations - 1, &index);
10876	error_code = gl.getError();
10877
10878	if (error_code == GL_INVALID_VALUE)
10879	{
10880		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &index);
10881
10882		error_code = gl.getError();
10883	}
10884
10885	if (error_code != GL_INVALID_VALUE)
10886	{
10887		m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesiv() does not generate GL_INVALID_VALUE "
10888													   "when passed <count> argument that is not equal to the value of "
10889													   "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10890						   << tcu::TestLog::EndMessage;
10891
10892		m_has_test_passed = false;
10893	}
10894
10895	/* The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value
10896	 * in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES
10897	 * for the shader stage.
10898	 */
10899	glw::GLuint invalid_subroutine_indices[4] = { (GLuint)m_po_active_subroutines, (GLuint)m_po_active_subroutines,
10900												  (GLuint)m_po_active_subroutines + 1,
10901												  (GLuint)m_po_active_subroutines + 1 };
10902
10903	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, /* count */
10904							 invalid_subroutine_indices + 0);
10905	error_code = gl.getError();
10906
10907	if (error_code == GL_INVALID_VALUE)
10908	{
10909		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations,
10910								 invalid_subroutine_indices + 2);
10911
10912		error_code = gl.getError();
10913	}
10914
10915	if (error_code != GL_INVALID_VALUE)
10916	{
10917		m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesuiv() does not generate GL_INVALID_VALUE "
10918													   "when the value passed via <indices> argument is greater than "
10919													   "or equal to the value of GL_ACTIVE_SUBROUTINES."
10920						   << tcu::TestLog::EndMessage;
10921
10922		m_has_test_passed = false;
10923	}
10924
10925	/* The error INVALID_OPERATION is generated by UniformSubroutinesuiv() if any
10926	 * subroutine index in <indices> identifies a subroutine not associated with
10927	 * the type of the subroutine uniform variable assigned to the corresponding
10928	 * location.
10929	 */
10930	glw::GLuint invalid_subroutine_indices2[2] = { m_po_subroutine_test1_index, m_po_subroutine_test1_index };
10931
10932	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, invalid_subroutine_indices2);
10933	error_code = gl.getError();
10934
10935	if (error_code != GL_INVALID_OPERATION)
10936	{
10937		m_testCtx.getLog() << tcu::TestLog::Message
10938						   << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10939							  "when the subroutine index passed via <indices> argument identifies"
10940							  "a subroutine not associated with the type of the subroutine uniform "
10941							  "assigned to the corresponding location."
10942						   << tcu::TestLog::EndMessage;
10943
10944		m_has_test_passed = false;
10945	}
10946
10947	/* The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no
10948	 * program is active.
10949	 */
10950	glw::GLuint valid_subroutine_locations[2] = { 0 };
10951
10952	valid_subroutine_locations[m_po_subroutine_uniform_function_index]  = m_po_subroutine_test1_index;
10953	valid_subroutine_locations[m_po_subroutine_uniform_function2_index] = m_po_subroutine_test3_index;
10954
10955	gl.useProgram(0);
10956	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10957
10958	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, valid_subroutine_locations);
10959	error_code = gl.getError();
10960
10961	if (error_code != GL_INVALID_OPERATION)
10962	{
10963		m_testCtx.getLog() << tcu::TestLog::Message
10964						   << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10965							  "when called without an active program object."
10966						   << tcu::TestLog::EndMessage;
10967
10968		m_has_test_passed = false;
10969	}
10970
10971	/* The error INVALID_VALUE is generated by GetUniformSubroutineuiv if
10972	 * <location> is greater than or equal to the value of
10973	 * ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage.
10974	 */
10975	glw::GLuint temp_value = 0;
10976
10977	gl.useProgram(m_po_id);
10978	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10979
10980	gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, &temp_value);
10981	error_code = gl.getError();
10982
10983	if (error_code == GL_INVALID_VALUE)
10984	{
10985		gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &temp_value);
10986		error_code = gl.getError();
10987	}
10988
10989	if (error_code != GL_INVALID_VALUE)
10990	{
10991		m_testCtx.getLog() << tcu::TestLog::Message
10992						   << "glGetUniformSubroutineuiv() does not generate GL_INVALID_VALUE "
10993							  "when called for location that is greater than or equal to the value "
10994							  "of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10995						   << tcu::TestLog::EndMessage;
10996
10997		m_has_test_passed = false;
10998	}
10999
11000	/* The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no
11001	 * program is active for the shader stage identified by <shadertype>.
11002	 */
11003	const glw::GLenum undefined_shader_stages[] = { GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER,
11004													GL_TESS_EVALUATION_SHADER };
11005	const unsigned int n_undefined_shader_stages = sizeof(undefined_shader_stages) / sizeof(undefined_shader_stages[0]);
11006
11007	for (unsigned int n_undefined_shader_stage = 0; n_undefined_shader_stage < n_undefined_shader_stages;
11008		 ++n_undefined_shader_stage)
11009	{
11010		glw::GLenum shader_stage = undefined_shader_stages[n_undefined_shader_stage];
11011
11012		gl.getUniformSubroutineuiv(shader_stage, 0, /* location */
11013								   &temp_value);
11014		error_code = gl.getError();
11015
11016		if (error_code != GL_INVALID_OPERATION)
11017		{
11018			m_testCtx.getLog() << tcu::TestLog::Message
11019							   << "glGetUniformSubroutineuiv() does not generate GL_INVALID_OPERATION "
11020								  "when called for a shader stage that is not defined for active "
11021								  "program object."
11022							   << tcu::TestLog::EndMessage;
11023
11024			m_has_test_passed = false;
11025		}
11026	} /* for (all undefined shader stages) */
11027
11028	/* All done */
11029	if (m_has_test_passed)
11030	{
11031		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11032	}
11033	else
11034	{
11035		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11036	}
11037
11038	return STOP;
11039}
11040
11041/** Constructor
11042 *
11043 *  @param context Rendering context.
11044 *
11045 **/
11046NegativeTest2::NegativeTest2(deqp::Context& context)
11047	: TestCase(context, "subroutine_uniform_scope", "Verifies subroutine uniforms declared in shader stage A"
11048													"cannot be accessed from a different stage.")
11049	, m_fs_id(0)
11050	, m_gs_id(0)
11051	, m_has_test_passed(true)
11052	, m_po_id(0)
11053	, m_tc_id(0)
11054	, m_te_id(0)
11055	, m_vs_id(0)
11056{
11057	/* Left blank intentionally */
11058}
11059
11060/** Deinitializes all GL objects that may have been created during test execution */
11061void NegativeTest2::deinit()
11062{
11063	deinitGLObjects();
11064}
11065
11066/** Deinitializes all GL objects that may have been created during test execution */
11067void NegativeTest2::deinitGLObjects()
11068{
11069	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11070
11071	if (m_fs_id != 0)
11072	{
11073		gl.deleteShader(m_fs_id);
11074
11075		m_fs_id = 0;
11076	}
11077
11078	if (m_gs_id != 0)
11079	{
11080		gl.deleteShader(m_gs_id);
11081
11082		m_gs_id = 0;
11083	}
11084
11085	if (m_tc_id != 0)
11086	{
11087		gl.deleteShader(m_tc_id);
11088
11089		m_tc_id = 0;
11090	}
11091
11092	if (m_te_id != 0)
11093	{
11094		gl.deleteShader(m_te_id);
11095
11096		m_te_id = 0;
11097	}
11098
11099	if (m_vs_id != 0)
11100	{
11101		gl.deleteShader(m_vs_id);
11102
11103		m_vs_id = 0;
11104	}
11105
11106	if (m_po_id != 0)
11107	{
11108		gl.deleteProgram(m_po_id);
11109
11110		m_po_id = 0;
11111	}
11112}
11113
11114/** Builds an offending program object and tries to link it. We're either expecting
11115 *  a compile-time or link-time error here.
11116 *
11117 *  If the program object builds successfully, the test has failed.
11118 *
11119 *  @param referencing_stage Shader stage which defines a subroutine uniform that
11120 *                           should be called from fragment/geometry/tess control/
11121 *                           tess evaluation/vertex shader stages.
11122 *
11123 **/
11124void NegativeTest2::executeTestCase(const Utils::_shader_stage& referencing_stage)
11125{
11126	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11127
11128	const std::string fs_body = getFragmentShaderBody(referencing_stage);
11129	const std::string gs_body = getGeometryShaderBody(referencing_stage);
11130	const std::string tc_body = getTessellationControlShaderBody(referencing_stage);
11131	const std::string te_body = getTessellationEvaluationShaderBody(referencing_stage);
11132	const std::string vs_body = getVertexShaderBody(referencing_stage);
11133
11134	if (Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, NULL, /* xfb_varyings */
11135							0,													   /* n_xfb_varyings */
11136							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
11137	{
11138		/* Test program should not have built correctly ! */
11139		m_testCtx.getLog() << tcu::TestLog::Message << "In the following program, one of the stages references "
11140													   "a subroutine that is defined in another stage. This "
11141													   "is forbidden by the specification.\n"
11142													   "\n"
11143													   "Vertex shader:\n\n"
11144						   << vs_body.c_str() << "\n\nTessellation control shader:\n\n"
11145						   << tc_body.c_str() << "\n\nTessellation evaluation shader:\n\n"
11146						   << te_body.c_str() << "\n\nGeometry shader:\n\n"
11147						   << gs_body.c_str() << "\n\nFragment shader:\n\n"
11148						   << fs_body.c_str() << tcu::TestLog::EndMessage;
11149
11150		m_has_test_passed = false;
11151	} /* if (test program was built successfully) */
11152
11153	/* Release the shaders & the program object that buildProgram() created */
11154	deinitGLObjects();
11155}
11156
11157/** Retrieves an offending fragment shader body.
11158 *
11159 *  @param referencing_stage Shader stage which defines the subroutine uniform that
11160 *                           will be called from fragment shader.
11161 *
11162 *  @return Requested string.
11163 **/
11164std::string NegativeTest2::getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const
11165{
11166	std::stringstream result;
11167
11168	/* Form the pre-amble */
11169	result << "#version 400\n"
11170			  "\n"
11171			  "#extension GL_ARB_shader_subroutine : require\n"
11172			  "\n"
11173			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
11174			  "\n"
11175			  /* Define a subroutine */
11176			  "subroutine(testSubroutineType) void fs_subroutine(out vec4 test_argument)\n"
11177			  "{\n"
11178			  "    test_argument = vec4(1, 0, 0, 0);\n"
11179			  "}\n"
11180			  "\n"
11181			  /* Define output variables */
11182			  "out vec4 result;\n"
11183			  "\n"
11184			  /* Define uniforms */
11185			  "subroutine uniform testSubroutineType test_fs_subroutine;\n"
11186			  "\n"
11187			  /* Define main() */
11188			  "void main()\n"
11189			  "{\n"
11190			  "    "
11191		   << getSubroutineUniformName(referencing_stage) << "(result);\n"
11192															 "}\n";
11193
11194	return result.str();
11195}
11196
11197/** Retrieves an offending geometry shader body.
11198 *
11199 *  @param referencing_stage Shader stage which defines the subroutine uniform that
11200 *                           will be called from geometry shader.
11201 *
11202 *  @return Requested string.
11203 **/
11204std::string NegativeTest2::getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const
11205{
11206	std::stringstream result;
11207
11208	/* Form the pre-amble */
11209	result << "#version 400\n"
11210			  "\n"
11211			  "#extension GL_ARB_shader_subroutine : require\n"
11212			  "\n"
11213			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
11214			  "\n"
11215			  "layout(points)                   in;\n"
11216			  "layout(points, max_vertices = 1) out;\n"
11217			  "\n"
11218			  /* Define a subroutine */
11219			  "subroutine(testSubroutineType) void gs_subroutine(out vec4 test_argument)\n"
11220			  "{\n"
11221			  "    test_argument = vec4(0, 1, 1, 1);\n"
11222			  "}\n"
11223			  "\n"
11224			  /* Define output variables */
11225			  "out vec4 result;\n"
11226			  "\n"
11227			  /* Define uniforms */
11228			  "subroutine uniform testSubroutineType test_gs_subroutine;\n"
11229			  "\n"
11230			  /* Define main() */
11231			  "void main()\n"
11232			  "{\n"
11233			  "    "
11234		   << getSubroutineUniformName(referencing_stage) << "(result);\n"
11235															 "}\n";
11236
11237	return result.str();
11238}
11239
11240/** Retrieves name of the subroutine uniform that is defined in user-specified
11241 *  shader stage.
11242 *
11243 *  @param stage Shader stage to retrieve the subroutine uniform name for.
11244 *
11245 *  @return As per description.
11246 **/
11247std::string NegativeTest2::getSubroutineUniformName(const Utils::_shader_stage& stage) const
11248{
11249	std::string result = "?";
11250
11251	switch (stage)
11252	{
11253	case Utils::SHADER_STAGE_FRAGMENT:
11254	{
11255		result = "test_fs_subroutine";
11256
11257		break;
11258	}
11259
11260	case Utils::SHADER_STAGE_GEOMETRY:
11261	{
11262		result = "test_gs_subroutine";
11263
11264		break;
11265	}
11266
11267	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11268	{
11269		result = "test_tc_subroutine";
11270
11271		break;
11272	}
11273
11274	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11275	{
11276		result = "test_te_subroutine";
11277
11278		break;
11279	}
11280
11281	case Utils::SHADER_STAGE_VERTEX:
11282	{
11283		result = "test_vs_subroutine";
11284
11285		break;
11286	}
11287
11288	default:
11289	{
11290		TCU_FAIL("Unrecognized shader stage requested");
11291	}
11292	} /* switch (stage) */
11293
11294	return result;
11295}
11296
11297/** Retrieves an offending tessellation control shader body.
11298 *
11299 *  @param referencing_stage Shader stage which defines the subroutine uniform that
11300 *                           will be called from tessellation control shader.
11301 *
11302 *  @return Requested string.
11303 **/
11304std::string NegativeTest2::getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const
11305{
11306	std::stringstream result;
11307
11308	/* Form the pre-amble */
11309	result << "#version 400\n"
11310			  "\n"
11311			  "#extension GL_ARB_shader_subroutine : require\n"
11312			  "\n"
11313			  "layout(vertices = 4) out;\n"
11314			  "\n"
11315			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
11316			  "\n"
11317			  /* Define a subroutine */
11318			  "subroutine(testSubroutineType) void tc_subroutine(out vec4 test_argument)\n"
11319			  "{\n"
11320			  "    test_argument = vec4(0, 0, 1, 0);\n"
11321			  "}\n"
11322			  "\n"
11323			  /* Define uniforms */
11324			  "subroutine uniform testSubroutineType test_tc_subroutine;\n"
11325			  "\n"
11326			  /* Define main() */
11327			  "void main()\n"
11328			  "{\n"
11329			  "    "
11330		   << getSubroutineUniformName(referencing_stage) << "(gl_out[gl_InvocationID].gl_Position);\n"
11331															 "}\n";
11332
11333	return result.str();
11334}
11335
11336/** Retrieves an offending tessellation evaluation shader body.
11337 *
11338 *  @param referencing_stage Shader stage which defines the subroutine uniform that
11339 *                           will be called from tessellation evaluation shader.
11340 *
11341 *  @return Requested string.
11342 **/
11343std::string NegativeTest2::getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const
11344{
11345	std::stringstream result;
11346
11347	/* Form the pre-amble */
11348	result << "#version 400\n"
11349			  "\n"
11350			  "#extension GL_ARB_shader_subroutine : require\n"
11351			  "\n"
11352			  "layout(quads) in;\n"
11353			  "\n"
11354			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
11355			  "\n"
11356			  /* Define a subroutine */
11357			  "subroutine(testSubroutineType) void te_subroutine(out vec4 test_argument)\n"
11358			  "{\n"
11359			  "    test_argument = vec4(1, 1, 1, 1);\n"
11360			  "}\n"
11361			  "\n"
11362			  /* Define uniforms */
11363			  "subroutine uniform testSubroutineType test_te_subroutine;\n"
11364			  "\n"
11365			  /* Define main() */
11366			  "void main()\n"
11367			  "{\n"
11368			  "    "
11369		   << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
11370															 "}\n";
11371
11372	return result.str();
11373}
11374
11375/** Retrieves an offending vertex shader body.
11376 *
11377 *  @param referencing_stage Shader stage which defines the subroutine uniform that
11378 *                           will be called from vertex shader.
11379 *
11380 *  @return Requested string.
11381 **/
11382std::string NegativeTest2::getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const
11383{
11384	std::stringstream result;
11385
11386	/* Form the pre-amble */
11387	result << "#version 400\n"
11388			  "\n"
11389			  "#extension GL_ARB_shader_subroutine : require\n"
11390			  "\n"
11391			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
11392			  "\n"
11393			  /* Define a subroutine */
11394			  "subroutine(testSubroutineType) void vs_subroutine(out vec4 test_argument)\n"
11395			  "{\n"
11396			  "    test_argument = vec4(0, 1, 0, 0);\n"
11397			  "}\n"
11398			  "\n"
11399			  /* Define uniforms */
11400			  "subroutine uniform testSubroutineType test_vs_subroutine;\n"
11401			  "\n"
11402			  /* Define main() */
11403			  "void main()\n"
11404			  "{\n"
11405			  "    "
11406		   << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
11407															 "}\n";
11408
11409	return result.str();
11410}
11411
11412/** Executes test iteration.
11413 *
11414 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11415 */
11416tcu::TestNode::IterateResult NegativeTest2::iterate()
11417{
11418	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11419	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11420	{
11421		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11422	}
11423
11424	/* Iterate over all shader stages and execute the checks */
11425	for (int referencing_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11426		 referencing_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++referencing_stage)
11427	{
11428		executeTestCase(static_cast<Utils::_shader_stage>(referencing_stage));
11429	} /* for (all test cases) */
11430
11431	/* All done */
11432	if (m_has_test_passed)
11433	{
11434		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11435	}
11436	else
11437	{
11438		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11439	}
11440
11441	return STOP;
11442}
11443
11444/** Constructor.
11445 *
11446 *  @param context Rendering context.
11447 *
11448 **/
11449NegativeTest3::NegativeTest3(deqp::Context& context)
11450	: TestCase(context, "missing_subroutine_keyword", "Verifies that subroutine keyword is necessary when declaring a "
11451													  "subroutine uniforn and a compilation error occurs without it.")
11452	, m_has_test_passed(true)
11453	, m_so_id(0)
11454{
11455	/* Left blank intentionally */
11456}
11457
11458/** Deinitializes all GL objects that may have been created during test execution */
11459void NegativeTest3::deinit()
11460{
11461	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11462
11463	if (m_so_id != 0)
11464	{
11465		gl.deleteShader(m_so_id);
11466
11467		m_so_id = 0;
11468	}
11469}
11470
11471/** Verifies that broken shader (for user-specified shader stage) does not compile.
11472 *
11473 *  @param shader_stage Shader stage to use for the test.
11474 **/
11475void NegativeTest3::executeTest(const Utils::_shader_stage& shader_stage)
11476{
11477	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11478
11479	/* Generate a new shader object */
11480	m_so_id = gl.createShader(Utils::getGLenumForShaderStage(shader_stage));
11481	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
11482
11483	/* Assign body to the shader */
11484	std::string body;
11485	const char* body_raw_ptr = DE_NULL;
11486
11487	switch (shader_stage)
11488	{
11489	case Utils::SHADER_STAGE_VERTEX:
11490		body = getVertexShaderBody();
11491		break;
11492	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11493		body = getTessellationControlShaderBody();
11494		break;
11495	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11496		body = getTessellationEvaluationShaderBody();
11497		break;
11498	case Utils::SHADER_STAGE_GEOMETRY:
11499		body = getGeometryShaderBody();
11500		break;
11501	case Utils::SHADER_STAGE_FRAGMENT:
11502		body = getFragmentShaderBody();
11503		break;
11504
11505	default:
11506	{
11507		TCU_FAIL("Unrecognized shader stage requested");
11508	}
11509	} /* switch (shader_stage) */
11510
11511	body_raw_ptr = body.c_str();
11512
11513	gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
11514	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11515
11516	/* Try to compile the shader */
11517	glw::GLint compile_status = 0;
11518
11519	gl.compileShader(m_so_id);
11520	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11521
11522	gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
11523	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11524
11525	if (compile_status == GL_TRUE)
11526	{
11527		m_testCtx.getLog() << tcu::TestLog::Message << "The following shader was expected to fail to compile but was "
11528													   "accepted by the compiler:\n"
11529													   "\n"
11530						   << body.c_str() << tcu::TestLog::EndMessage;
11531
11532		m_has_test_passed = false;
11533	}
11534
11535	/* Good to release the shader at this point */
11536	gl.deleteShader(m_so_id);
11537	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
11538}
11539
11540/** Retrieves body of a broken fragment shader.
11541 *
11542 *  @return Requested string.
11543 **/
11544std::string NegativeTest3::getFragmentShaderBody() const
11545{
11546	return "#version 400\n"
11547		   "\n"
11548		   "#extension GL_ARB_shader_subroutine : require\n"
11549		   "\n"
11550		   "subroutine void testSubroutineType(inout vec4 test);\n"
11551		   "\n"
11552		   "void testSubroutine1(inout vec4 test)\n"
11553		   "{\n"
11554		   "    test += vec4(3, 4, 5, 6);\n"
11555		   "}\n"
11556		   "\n"
11557		   "uniform testSubroutineType subroutineFunction;\n"
11558		   "out     vec4               result;\n"
11559		   "\n"
11560		   "void main()\n"
11561		   "{\n"
11562		   "    vec4 test = vec4(2, 3, 4, 5);\n"
11563		   "\n"
11564		   "    subroutineFunction(test);\n"
11565		   "\n"
11566		   "    result = test;\n"
11567		   "}\n";
11568}
11569
11570/** Retrieves body of a broken geometry shader.
11571 *
11572 *  @return Requested string.
11573 **/
11574std::string NegativeTest3::getGeometryShaderBody() const
11575{
11576	return "#version 400\n"
11577		   "\n"
11578		   "#extension GL_ARB_shader_subroutine : require\n"
11579		   "\n"
11580		   "layout(points)                   in;\n"
11581		   "layout(points, max_vertices = 1) out;\n"
11582		   "\n"
11583		   "subroutine void testSubroutineType(inout vec4 test);\n"
11584		   "\n"
11585		   "void testSubroutine1(inout vec4 test)\n"
11586		   "{\n"
11587		   "    test += vec4(3, 4, 5, 6);\n"
11588		   "}\n"
11589		   "\n"
11590		   "uniform testSubroutineType subroutineFunction;\n"
11591		   "\n"
11592		   "void main()\n"
11593		   "{\n"
11594		   "    vec4 test = vec4(2, 3, 4, 5);\n"
11595		   "\n"
11596		   "    subroutineFunction(test);\n"
11597		   "\n"
11598		   "    gl_Position = test;\n"
11599		   "    EmitVertex();\n"
11600		   "}\n";
11601}
11602
11603/** Retrieves body of a broken tessellation control shader.
11604 *
11605 *  @return Requested string.
11606 **/
11607std::string NegativeTest3::getTessellationControlShaderBody() const
11608{
11609	return "#version 400\n"
11610		   "\n"
11611		   "#extension GL_ARB_shader_subroutine : require\n"
11612		   "\n"
11613		   "layout(vertices=4) out;\n"
11614		   "\n"
11615		   "subroutine void testSubroutineType(inout vec4 test);\n"
11616		   "\n"
11617		   "void testSubroutine1(inout vec4 test)\n"
11618		   "{\n"
11619		   "    test += vec4(1, 2, 3, 4);\n"
11620		   "}\n"
11621		   "\n"
11622		   "uniform testSubroutineType subroutineFunction;\n"
11623		   "\n"
11624		   "void main()\n"
11625		   "{\n"
11626		   "    vec4 test = vec4(0, 1, 2, 3);\n"
11627		   "\n"
11628		   "    subroutineFunction(test);\n"
11629		   "\n"
11630		   "    gl_out[gl_InvocationID].gl_Position = test;\n"
11631		   "}\n";
11632}
11633
11634/** Retrieves body of a broken tessellation evaluation shader.
11635 *
11636 *  @return Requested string.
11637 **/
11638std::string NegativeTest3::getTessellationEvaluationShaderBody() const
11639{
11640	return "#version 400\n"
11641		   "\n"
11642		   "#extension GL_ARB_shader_subroutine : require\n"
11643		   "\n"
11644		   "layout(quads) in;\n"
11645		   "\n"
11646		   "subroutine void testSubroutineType(inout vec4 test);\n"
11647		   "\n"
11648		   "void testSubroutine1(inout vec4 test)\n"
11649		   "{\n"
11650		   "    test += vec4(2, 3, 4, 5);\n"
11651		   "}\n"
11652		   "\n"
11653		   "uniform testSubroutineType subroutineFunction;\n"
11654		   "\n"
11655		   "void main()\n"
11656		   "{\n"
11657		   "    vec4 test = vec4(1, 2, 3, 4);\n"
11658		   "\n"
11659		   "    subroutineFunction(test);\n"
11660		   "\n"
11661		   "    gl_Position = test;\n"
11662		   "}\n";
11663}
11664
11665/** Retrieves body of a broken vertex shader.
11666 *
11667 *  @return Requested string.
11668 **/
11669std::string NegativeTest3::getVertexShaderBody() const
11670{
11671	return "#version 400\n"
11672		   "\n"
11673		   "#extension GL_ARB_shader_subroutine : require\n"
11674		   "\n"
11675		   "subroutine void testSubroutineType(inout vec4 test);\n"
11676		   "\n"
11677		   "void testSubroutine1(inout vec4 test)\n"
11678		   "{\n"
11679		   "    test += vec4(0, 1, 2, 3);\n"
11680		   "}\n"
11681		   "\n"
11682		   "uniform testSubroutineType subroutineFunction;\n"
11683		   "\n"
11684		   "void main()\n"
11685		   "{\n"
11686		   "    subroutineFunction(gl_Position);\n"
11687		   "}\n";
11688}
11689
11690/** Executes test iteration.
11691 *
11692 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11693 */
11694tcu::TestNode::IterateResult NegativeTest3::iterate()
11695{
11696	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11697	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11698	{
11699		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11700	}
11701
11702	/* Iterate over all shader stages */
11703	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11704		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11705	{
11706		executeTest(static_cast<Utils::_shader_stage>(shader_stage));
11707	} /* for (all shader stages) */
11708
11709	/* Done */
11710	if (m_has_test_passed)
11711	{
11712		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11713	}
11714	else
11715	{
11716		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11717	}
11718
11719	return STOP;
11720}
11721
11722/** Constructor.
11723 *
11724 *  @param context Rendering context.
11725 *
11726 **/
11727NegativeTest4::NegativeTest4(deqp::Context& context)
11728	: TestCase(context, "subroutines_incompatible_with_subroutine_type",
11729			   "Verifies that a compile-time error is generated when arguments and "
11730			   "return type do not match beween the function and each associated "
11731			   "subroutine type.")
11732	, m_has_test_passed(true)
11733	, m_so_id(0)
11734{
11735	/* Left blank intentionally */
11736}
11737
11738/** Deinitializes GL objects that may have been created during test
11739 *  execution.
11740 **/
11741void NegativeTest4::deinit()
11742{
11743	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11744
11745	if (m_so_id != 0)
11746	{
11747		gl.deleteShader(m_so_id);
11748
11749		m_so_id = 0;
11750	}
11751}
11752
11753/** Retrieves body of a shader of user-specified type that should be used
11754 *  for a single test iteration. The shader will define user-specified number
11755 *  of subroutine types, with the last type either defining an additional argument
11756 *  or using a different return type.
11757 *  A subroutine (claimed compatible with *all* subroutine types) will also be
11758 *  defined in the shader.
11759 *
11760 *  @param shader_stage       Shader stage to use for the query.
11761 *  @param n_subroutine_types Overall number of subroutine types that will be
11762 *                            declared & used in the shader. Please see description
11763 *                            for more details.
11764 *
11765 *  @return Requested string.
11766 **/
11767std::string NegativeTest4::getShaderBody(const Utils::_shader_stage& shader_stage,
11768										 const unsigned int& n_subroutine_types, const _test_case& test_case) const
11769{
11770	std::stringstream result_sstream;
11771
11772	/* Form the pre-amble */
11773	result_sstream << "#version 400\n"
11774					  "\n"
11775					  "#extension GL_ARB_shader_subroutine : require\n"
11776					  "\n";
11777
11778	/* Inject stage-specific code */
11779	switch (shader_stage)
11780	{
11781	case Utils::SHADER_STAGE_GEOMETRY:
11782	{
11783		result_sstream << "layout (points) in;\n"
11784						  "layout (points, max_vertices = 1) out;\n"
11785						  "\n";
11786
11787		break;
11788	}
11789
11790	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11791	{
11792		result_sstream << "layout (vertices = 4) out;\n"
11793						  "\n";
11794
11795		break;
11796	}
11797
11798	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11799	{
11800		result_sstream << "layout (quads) in;\n"
11801						  "\n";
11802
11803		break;
11804	}
11805
11806	default:
11807		break;
11808	} /* switch (shader_stage) */
11809
11810	/* Insert subroutine type declarations */
11811	for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types - 1; ++n_subroutine_type)
11812	{
11813		result_sstream << "subroutine void subroutineType" << n_subroutine_type << "(inout vec3 argument);\n";
11814	} /* for (all subroutine types) */
11815
11816	switch (test_case)
11817	{
11818	case TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST:
11819	{
11820		result_sstream << "subroutine void subroutineType" << (n_subroutine_types - 1)
11821					   << "(inout vec3 argument, out vec4 argument2);\n";
11822
11823		break;
11824	}
11825
11826	case TEST_CASE_INCOMPATIBLE_RETURN_TYPE:
11827	{
11828		result_sstream << "subroutine int subroutineType" << (n_subroutine_types - 1) << "(inout vec3 argument);\n";
11829
11830		break;
11831	}
11832
11833	default:
11834	{
11835		TCU_FAIL("Unrecognized test case");
11836	}
11837	} /* switch (test_case) */
11838
11839	/* Insert subroutine declarations */
11840	result_sstream << "subroutine(";
11841
11842	for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types; ++n_subroutine_type)
11843	{
11844		result_sstream << "subroutineType" << n_subroutine_type;
11845
11846		if (n_subroutine_type != (n_subroutine_types - 1))
11847		{
11848			result_sstream << ", ";
11849		}
11850	} /* for (all subroutine types) */
11851
11852	result_sstream << ") void function(inout vec3 argument)\n"
11853					  "{\n"
11854					  "    argument = vec3(1, 2, 3);\n"
11855					  "}\n"
11856					  "\n";
11857
11858	/* Insert remaining required stage-specific bits */
11859	switch (shader_stage)
11860	{
11861	case Utils::SHADER_STAGE_FRAGMENT:
11862	{
11863		result_sstream << "out vec4 result;\n"
11864						  "\n"
11865						  "void main()\n"
11866						  "{\n"
11867						  "    result = vec4(1, 2, 3, 4);\n"
11868						  "}\n";
11869
11870		break;
11871	}
11872
11873	case Utils::SHADER_STAGE_GEOMETRY:
11874	{
11875		result_sstream << "void main()\n"
11876						  "{\n"
11877						  "    gl_Position = vec4(1, 2, 3, 4);\n"
11878						  "    EmitVertex();\n"
11879						  "}\n";
11880
11881		break;
11882	}
11883
11884	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11885	{
11886		result_sstream << "void main()\n"
11887						  "{\n"
11888						  "    gl_TessLevelInner[0]                = 1;\n"
11889						  "    gl_TessLevelInner[1]                = 1;\n"
11890						  "    gl_TessLevelOuter[0]                = 1;\n"
11891						  "    gl_TessLevelOuter[1]                = 1;\n"
11892						  "    gl_TessLevelOuter[2]                = 1;\n"
11893						  "    gl_TessLevelOuter[3]                = 1;\n"
11894						  "    gl_out[gl_InvocationID].gl_Position = vec4(2, 3, 4, 5);\n"
11895						  "}\n";
11896
11897		break;
11898	}
11899
11900	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11901	case Utils::SHADER_STAGE_VERTEX:
11902	{
11903		result_sstream << "void main()\n"
11904						  "{\n"
11905						  "    gl_Position = vec4(1, 2, 3, 4);\n"
11906						  "}\n";
11907
11908		break;
11909	}
11910
11911	default:
11912	{
11913		TCU_FAIL("Unrecognized shader stage");
11914	}
11915	} /* switch (shader_stage) */
11916
11917	return result_sstream.str();
11918}
11919
11920/** Executes test iteration.
11921 *
11922 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11923 */
11924tcu::TestNode::IterateResult NegativeTest4::iterate()
11925{
11926	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11927
11928	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11929	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11930	{
11931		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11932	}
11933
11934	/* Iterate over all shader stages.. */
11935	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11936		 shader_stage != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11937	{
11938		/* For each shader stage, we will be trying to compile a number of invalid shaders.
11939		 * Each shader defines N different subroutine types. (N-1) of them are compatible
11940		 * with a subroutine, but exactly 1 will be mismatched. The test passes if GLSL
11941		 * compiler correctly detects that all shaders we will be trying to compile are
11942		 * broken.
11943		 */
11944		const glw::GLenum shader_type = Utils::getGLenumForShaderStage(static_cast<Utils::_shader_stage>(shader_stage));
11945
11946		for (unsigned int n_subroutine_types = 1; n_subroutine_types < 6; /* arbitrary number */
11947			 ++n_subroutine_types)
11948		{
11949			for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT);
11950				 ++test_case)
11951			{
11952				std::string body;
11953				const char* body_raw_ptr   = NULL;
11954				glw::GLint  compile_status = GL_FALSE;
11955
11956				body = getShaderBody(static_cast<Utils::_shader_stage>(shader_stage), n_subroutine_types,
11957									 static_cast<_test_case>(test_case));
11958				body_raw_ptr = body.c_str();
11959
11960				/* Try to compile the shader */
11961				m_so_id = gl.createShader(shader_type);
11962				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
11963
11964				gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL);
11965				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
11966
11967				gl.compileShader(m_so_id);
11968				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
11969
11970				gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
11971				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11972
11973				if (compile_status == GL_TRUE)
11974				{
11975					m_testCtx.getLog() << tcu::TestLog::Message << "A malformed "
11976									   << Utils::getShaderStageString(static_cast<Utils::_shader_stage>(shader_stage))
11977									   << " compiled successfully "
11978										  "("
11979									   << n_subroutine_types << " subroutine types "
11980																"were defined)."
11981									   << tcu::TestLog::EndMessage;
11982
11983					m_has_test_passed = false;
11984				}
11985
11986				/* Release the object */
11987				gl.deleteShader(m_so_id);
11988				GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
11989			} /* for (all test cases) */
11990		}	 /* for (a number of different subroutine type declarations) */
11991	}		  /* for (all shader stages) */
11992
11993	/* Done */
11994	if (m_has_test_passed)
11995	{
11996		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11997	}
11998	else
11999	{
12000		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12001	}
12002
12003	return STOP;
12004}
12005
12006/** Constructor.
12007 *
12008 *  @param context Rendering context.
12009 *
12010 **/
12011NegativeTest5::NegativeTest5(deqp::Context& context)
12012	: TestCase(context, "subroutine_uniform_wo_matching_subroutines",
12013			   "Verifies that a link- or compile-time error occurs when "
12014			   "trying to link a program with no subroutine for subroutine "
12015			   "uniform variable.")
12016	, m_fs_id(0)
12017	, m_gs_id(0)
12018	, m_has_test_passed(true)
12019	, m_po_id(0)
12020	, m_tc_id(0)
12021	, m_te_id(0)
12022	, m_vs_id(0)
12023{
12024	/* Left blank intentionally */
12025}
12026
12027/** Deinitializes all GL objects that may have been created during test execution */
12028void NegativeTest5::deinit()
12029{
12030	deinitIteration();
12031}
12032
12033/** Deinitializes all GL objects that may have been created during a single test
12034 *  iteration.
12035 ***/
12036void NegativeTest5::deinitIteration()
12037{
12038	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12039
12040	if (m_fs_id != 0)
12041	{
12042		gl.deleteShader(m_fs_id);
12043
12044		m_fs_id = 0;
12045	}
12046
12047	if (m_gs_id != 0)
12048	{
12049		gl.deleteShader(m_gs_id);
12050
12051		m_gs_id = 0;
12052	}
12053
12054	if (m_po_id != 0)
12055	{
12056		gl.deleteProgram(m_po_id);
12057
12058		m_po_id = 0;
12059	}
12060
12061	if (m_tc_id != 0)
12062	{
12063		gl.deleteShader(m_tc_id);
12064
12065		m_tc_id = 0;
12066	}
12067
12068	if (m_te_id != 0)
12069	{
12070		gl.deleteShader(m_te_id);
12071
12072		m_te_id = 0;
12073	}
12074
12075	if (m_vs_id != 0)
12076	{
12077		gl.deleteShader(m_vs_id);
12078
12079		m_vs_id = 0;
12080	}
12081}
12082
12083/** Executes a single test iteration.
12084 *
12085 *  If the iteration fails, m_has_test_passed will be set to false.
12086 *
12087 *  @param shader_stage Shader stage, for which a subroutine uniform should be
12088 *                      declared in the shader without a matching subroutine.
12089 **/
12090void NegativeTest5::executeIteration(const Utils::_shader_stage& shader_stage)
12091{
12092	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
12093	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
12094	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
12095	std::string te_body =
12096		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
12097	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
12098
12099	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
12100							DE_NULL, /* xfb_varyings */
12101							DE_NULL, /* n_xfb_varyings */
12102							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
12103	{
12104		/* None of the test programs should ever build successfully */
12105		m_testCtx.getLog() << tcu::TestLog::Message
12106						   << "A program object, consisting of the following shaders, has linked"
12107							  " correctly. One of the shaders defines a subroutine uniform but does "
12108							  "not implement any function that matches subroutine type of the uniform."
12109							  " This should have resulted in a compilation/link-time error.\n"
12110							  "\n"
12111							  "Vertex shader:\n"
12112							  "\n"
12113						   << vs_body << "\n"
12114										 "Tessellation control shader:\n"
12115										 "\n"
12116						   << tc_body << "\n"
12117										 "Tessellation evaluation shader:\n"
12118										 "\n"
12119						   << te_body << "\n"
12120										 "Geometry shader:\n"
12121										 "\n"
12122						   << gs_body << "\n"
12123										 "Fragment shader:\n"
12124										 "\n"
12125						   << fs_body << tcu::TestLog::EndMessage;
12126
12127		m_has_test_passed = false;
12128	}
12129}
12130
12131/** Retrieves fragment shader body.
12132 *
12133 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12134 *                                                        a subroutine uniform without
12135 *                                                        a matching subroutine, false otherwise.
12136 *
12137 *  @return Requested string.
12138 **/
12139std::string NegativeTest5::getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12140{
12141	std::stringstream result_sstream;
12142
12143	result_sstream << "#version 400\n"
12144					  "\n"
12145					  "#extension GL_ARB_shader_subroutine : require\n"
12146					  "\n";
12147
12148	if (include_invalid_subroutine_uniform_declaration)
12149	{
12150		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
12151						  "\n"
12152						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
12153	};
12154
12155	result_sstream << "\n"
12156					  "out vec4 result;\n"
12157					  "\n"
12158					  "void main()\n"
12159					  "{\n";
12160
12161	if (include_invalid_subroutine_uniform_declaration)
12162	{
12163		result_sstream << "    test_subroutineFS(result);\n";
12164	}
12165	else
12166	{
12167		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
12168	}
12169
12170	result_sstream << "}\n";
12171
12172	return result_sstream.str();
12173}
12174
12175/** Retrieves geometry shader body.
12176 *
12177 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12178 *                                                        a subroutine uniform without
12179 *                                                        a matching subroutine, false otherwise.
12180 *
12181 *  @return Requested string.
12182 **/
12183std::string NegativeTest5::getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12184{
12185	std::stringstream result_sstream;
12186
12187	result_sstream << "#version 400\n"
12188					  "\n"
12189					  "#extension GL_ARB_shader_subroutine : require\n"
12190					  "\n"
12191					  "layout (points)                   in;\n"
12192					  "layout (points, max_vertices = 1) out;\n"
12193					  "\n";
12194
12195	if (include_invalid_subroutine_uniform_declaration)
12196	{
12197		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
12198						  "\n"
12199						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
12200	};
12201
12202	result_sstream << "\n"
12203					  "void main()\n"
12204					  "{\n";
12205
12206	if (include_invalid_subroutine_uniform_declaration)
12207	{
12208		result_sstream << "    test_subroutineGS(gl_Position);\n";
12209	}
12210	else
12211	{
12212		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12213	}
12214
12215	result_sstream << "EmitVertex();\n"
12216					  "}\n";
12217
12218	return result_sstream.str();
12219}
12220
12221/** Retrieves tessellation control shader body.
12222 *
12223 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12224 *                                                        a subroutine uniform without
12225 *                                                        a matching subroutine, false otherwise.
12226 *
12227 *  @return Requested string.
12228 **/
12229std::string NegativeTest5::getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12230{
12231	std::stringstream result_sstream;
12232
12233	result_sstream << "#version 400\n"
12234					  "\n"
12235					  "#extension GL_ARB_shader_subroutine : require\n"
12236					  "\n"
12237					  "layout (vertices = 4) out;\n"
12238					  "\n";
12239
12240	if (include_invalid_subroutine_uniform_declaration)
12241	{
12242		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
12243						  "\n"
12244						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
12245	};
12246
12247	result_sstream << "\n"
12248					  "void main()\n"
12249					  "{\n";
12250
12251	if (include_invalid_subroutine_uniform_declaration)
12252	{
12253		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
12254	}
12255	else
12256	{
12257		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
12258	}
12259
12260	result_sstream << "}\n";
12261
12262	return result_sstream.str();
12263}
12264
12265/** Retrieves tessellation evaluation body.
12266 *
12267 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12268 *                                                        a subroutine uniform without
12269 *                                                        a matching subroutine, false otherwise.
12270 *
12271 *  @return Requested string.
12272 **/
12273std::string NegativeTest5::getTessellationEvaluationShaderBody(
12274	bool include_invalid_subroutine_uniform_declaration) const
12275{
12276	std::stringstream result_sstream;
12277
12278	result_sstream << "#version 400\n"
12279					  "\n"
12280					  "#extension GL_ARB_shader_subroutine : require\n"
12281					  "\n"
12282					  "layout (quads) in;\n"
12283					  "\n";
12284
12285	if (include_invalid_subroutine_uniform_declaration)
12286	{
12287		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
12288						  "\n"
12289						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
12290	};
12291
12292	result_sstream << "\n"
12293					  "void main()\n"
12294					  "{\n";
12295
12296	if (include_invalid_subroutine_uniform_declaration)
12297	{
12298		result_sstream << "    test_subroutineTE(gl_Position);\n";
12299	}
12300	else
12301	{
12302		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12303	}
12304
12305	result_sstream << "}\n";
12306
12307	return result_sstream.str();
12308}
12309
12310/** Retrieves vertex shader body.
12311 *
12312 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12313 *                                                        a subroutine uniform without
12314 *                                                        a matching subroutine, false otherwise.
12315 *
12316 *  @return Requested string.
12317 **/
12318std::string NegativeTest5::getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12319{
12320	std::stringstream result_sstream;
12321
12322	result_sstream << "#version 400\n"
12323					  "\n"
12324					  "#extension GL_ARB_shader_subroutine : require\n"
12325					  "\n";
12326
12327	if (include_invalid_subroutine_uniform_declaration)
12328	{
12329		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12330						  "\n"
12331						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12332	};
12333
12334	result_sstream << "\n"
12335					  "void main()\n"
12336					  "{\n";
12337
12338	if (include_invalid_subroutine_uniform_declaration)
12339	{
12340		result_sstream << "    test_subroutineVS(gl_Position);\n";
12341	}
12342	else
12343	{
12344		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12345	}
12346
12347	result_sstream << "}\n";
12348
12349	return result_sstream.str();
12350}
12351
12352/** Executes test iteration.
12353 *
12354 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12355 */
12356tcu::TestNode::IterateResult NegativeTest5::iterate()
12357{
12358	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12359	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12360	{
12361		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12362	}
12363
12364	/* Iterate over all shader stages. Iteration-specific shader stage defines a subroutine type &
12365	 * a corresponding subroutine uniform, for which no compatible subroutines are available. All
12366	 * other shader stages are defined correctly.
12367	 */
12368	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12369		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12370	{
12371		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12372		deinitIteration();
12373	} /* for (all shader stages) */
12374
12375	/* All done */
12376	if (m_has_test_passed)
12377	{
12378		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12379	}
12380	else
12381	{
12382		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12383	}
12384
12385	return STOP;
12386}
12387
12388/** Constructor.
12389 *
12390 *  @param context Rendering context.
12391 *
12392 **/
12393NegativeTest6::NegativeTest6(deqp::Context& context)
12394	: TestCase(context, "two_duplicate_functions_one_being_a_subroutine",
12395			   "Verifies that a link- or compile-time error occurs if any shader in "
12396			   "a program object includes two functions with the same name and one "
12397			   "of which is associated with a subroutine type.")
12398	, m_fs_id(0)
12399	, m_gs_id(0)
12400	, m_has_test_passed(true)
12401	, m_po_id(0)
12402	, m_tc_id(0)
12403	, m_te_id(0)
12404	, m_vs_id(0)
12405{
12406	/* Left blank intentionally */
12407}
12408
12409/** Deinitializes all GL objects that may have been created during test execution */
12410void NegativeTest6::deinit()
12411{
12412	deinitIteration();
12413}
12414
12415/** Deinitializes all GL objects that may have been created during a single test
12416 *  iteration.
12417 ***/
12418void NegativeTest6::deinitIteration()
12419{
12420	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12421
12422	if (m_fs_id != 0)
12423	{
12424		gl.deleteShader(m_fs_id);
12425
12426		m_fs_id = 0;
12427	}
12428
12429	if (m_gs_id != 0)
12430	{
12431		gl.deleteShader(m_gs_id);
12432
12433		m_gs_id = 0;
12434	}
12435
12436	if (m_po_id != 0)
12437	{
12438		gl.deleteProgram(m_po_id);
12439
12440		m_po_id = 0;
12441	}
12442
12443	if (m_tc_id != 0)
12444	{
12445		gl.deleteShader(m_tc_id);
12446
12447		m_tc_id = 0;
12448	}
12449
12450	if (m_te_id != 0)
12451	{
12452		gl.deleteShader(m_te_id);
12453
12454		m_te_id = 0;
12455	}
12456
12457	if (m_vs_id != 0)
12458	{
12459		gl.deleteShader(m_vs_id);
12460
12461		m_vs_id = 0;
12462	}
12463}
12464
12465/** Executes a single test iteration.
12466 *
12467 *  If the iteration fails, m_has_test_passed will be set to false.
12468 *
12469 *  @param shader_stage Shader stage, for which two duplicate functions
12470 *                      (one additionally marked as subroutine) should
12471 *                      be defined.
12472 **/
12473void NegativeTest6::executeIteration(const Utils::_shader_stage& shader_stage)
12474{
12475	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
12476	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
12477	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
12478	std::string te_body =
12479		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
12480	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
12481
12482	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
12483							DE_NULL, /* xfb_varyings */
12484							DE_NULL, /* n_xfb_varyings */
12485							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
12486	{
12487		/* None of the test programs should ever build successfully */
12488		m_testCtx.getLog() << tcu::TestLog::Message
12489						   << "A program object, consisting of the following shaders, has linked"
12490							  " correctly. This is invalid, because one of the shaders defines two"
12491							  " functions with the same name, with an exception that one of the"
12492							  " functions is marked as a subroutine.\n"
12493							  "\n"
12494							  "Vertex shader:\n"
12495							  "\n"
12496						   << vs_body << "\n"
12497										 "Tessellation control shader:\n"
12498										 "\n"
12499						   << tc_body << "\n"
12500										 "Tessellation evaluation shader:\n"
12501										 "\n"
12502						   << te_body << "\n"
12503										 "Geometry shader:\n"
12504										 "\n"
12505						   << gs_body << "\n"
12506										 "Fragment shader:\n"
12507										 "\n"
12508						   << fs_body << tcu::TestLog::EndMessage;
12509
12510		m_has_test_passed = false;
12511	}
12512}
12513
12514/** Retrieves fragment shader body.
12515 *
12516 *  @param include_invalid_declaration true if the shader should include duplicate function
12517 *                                     declaration.
12518 *
12519 *  @return Requested string.
12520 **/
12521std::string NegativeTest6::getFragmentShaderBody(bool include_invalid_declaration) const
12522{
12523	std::stringstream result_sstream;
12524
12525	result_sstream << "#version 400\n"
12526					  "\n"
12527					  "#extension GL_ARB_shader_subroutine : require\n"
12528					  "\n";
12529
12530	if (include_invalid_declaration)
12531	{
12532		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
12533						  "\n"
12534						  "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test)\n"
12535						  "{\n"
12536						  "    test = vec4(1, 2, 3, 4);\n"
12537						  "}\n"
12538						  "\n"
12539						  "void test_impl1(out vec4 test)\n"
12540						  "{\n"
12541						  "    test = vec4(2, 3, 4, 5);\n"
12542						  "}\n"
12543						  "\n"
12544						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
12545	};
12546
12547	result_sstream << "\n"
12548					  "out vec4 result;\n"
12549					  "\n"
12550					  "void main()\n"
12551					  "{\n";
12552
12553	if (include_invalid_declaration)
12554	{
12555		result_sstream << "    test_subroutineFS(result);\n";
12556	}
12557	else
12558	{
12559		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
12560	}
12561
12562	result_sstream << "}\n";
12563
12564	return result_sstream.str();
12565}
12566
12567/** Retrieves geometry shader body.
12568 *
12569 *  @param include_invalid_declaration true if the shader should include duplicate function
12570 *                                     declaration.
12571 *
12572 *  @return Requested string.
12573 **/
12574std::string NegativeTest6::getGeometryShaderBody(bool include_invalid_declaration) const
12575{
12576	std::stringstream result_sstream;
12577
12578	result_sstream << "#version 400\n"
12579					  "\n"
12580					  "#extension GL_ARB_shader_subroutine : require\n"
12581					  "\n"
12582					  "layout (points)                   in;\n"
12583					  "layout (points, max_vertices = 1) out;\n"
12584					  "\n";
12585
12586	if (include_invalid_declaration)
12587	{
12588		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
12589						  "\n"
12590						  "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test)\n"
12591						  "{\n"
12592						  "    test = vec4(1, 2, 3, 4);\n"
12593						  "}\n"
12594						  "\n"
12595						  "void test_impl1(out vec4 test)\n"
12596						  "{\n"
12597						  "    test = vec4(2, 3, 4, 5);\n"
12598						  "}\n"
12599						  "\n"
12600						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
12601	};
12602
12603	result_sstream << "\n"
12604					  "void main()\n"
12605					  "{\n";
12606
12607	if (include_invalid_declaration)
12608	{
12609		result_sstream << "    test_subroutineGS(gl_Position);\n";
12610	}
12611	else
12612	{
12613		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12614	}
12615
12616	result_sstream << "EmitVertex();\n"
12617					  "}\n";
12618
12619	return result_sstream.str();
12620}
12621
12622/** Retrieves tessellation control shader body.
12623 *
12624 *  @param include_invalid_declaration true if the shader should include duplicate function
12625 *                                     declaration.
12626 *
12627 *  @return Requested string.
12628 **/
12629std::string NegativeTest6::getTessellationControlShaderBody(bool include_invalid_declaration) const
12630{
12631	std::stringstream result_sstream;
12632
12633	result_sstream << "#version 400\n"
12634					  "\n"
12635					  "#extension GL_ARB_shader_subroutine : require\n"
12636					  "\n"
12637					  "layout (vertices = 4) out;\n"
12638					  "\n";
12639
12640	if (include_invalid_declaration)
12641	{
12642		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
12643						  "\n"
12644						  "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test)\n"
12645						  "{\n"
12646						  "    test = vec4(1, 2, 3, 4);\n"
12647						  "}\n"
12648						  "\n"
12649						  "void test_impl1(out vec4 test)\n"
12650						  "{\n"
12651						  "    test = vec4(2, 3, 4, 5);\n"
12652						  "}\n"
12653						  "\n"
12654						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
12655	};
12656
12657	result_sstream << "\n"
12658					  "void main()\n"
12659					  "{\n";
12660
12661	if (include_invalid_declaration)
12662	{
12663		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
12664	}
12665	else
12666	{
12667		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
12668	}
12669
12670	result_sstream << "}\n";
12671
12672	return result_sstream.str();
12673}
12674
12675/** Retrieves tessellation evaluation body.
12676 *
12677 *  @param include_invalid_declaration true if the shader should include duplicate function
12678 *                                     declaration.
12679 *
12680 *  @return Requested string.
12681 **/
12682std::string NegativeTest6::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
12683{
12684	std::stringstream result_sstream;
12685
12686	result_sstream << "#version 400\n"
12687					  "\n"
12688					  "#extension GL_ARB_shader_subroutine : require\n"
12689					  "\n"
12690					  "layout (quads) in;\n"
12691					  "\n";
12692
12693	if (include_invalid_declaration)
12694	{
12695		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
12696						  "\n"
12697						  "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test)\n"
12698						  "{\n"
12699						  "    test = vec4(1, 2, 3, 4);\n"
12700						  "}\n"
12701						  "\n"
12702						  "void test_impl1(out vec4 test)\n"
12703						  "{\n"
12704						  "    test = vec4(2, 3, 4, 5);\n"
12705						  "}\n"
12706						  "\n"
12707						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
12708	};
12709
12710	result_sstream << "\n"
12711					  "void main()\n"
12712					  "{\n";
12713
12714	if (include_invalid_declaration)
12715	{
12716		result_sstream << "    test_subroutineTE(gl_Position);\n";
12717	}
12718	else
12719	{
12720		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12721	}
12722
12723	result_sstream << "}\n";
12724
12725	return result_sstream.str();
12726}
12727
12728/** Retrieves vertex shader body.
12729 *
12730 *  @param include_invalid_declaration true if the shader should include duplicate function
12731 *                                     declaration.
12732 *
12733 *  @return Requested string.
12734 **/
12735std::string NegativeTest6::getVertexShaderBody(bool include_invalid_declaration) const
12736{
12737	std::stringstream result_sstream;
12738
12739	result_sstream << "#version 400\n"
12740					  "\n"
12741					  "#extension GL_ARB_shader_subroutine : require\n"
12742					  "\n";
12743
12744	if (include_invalid_declaration)
12745	{
12746		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12747						  "\n"
12748						  "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test)\n"
12749						  "{\n"
12750						  "    test = vec4(1, 2, 3, 4);\n"
12751						  "}\n"
12752						  "\n"
12753						  "void test_impl1(out vec4 test)\n"
12754						  "{\n"
12755						  "    test = vec4(2, 3, 4, 5);\n"
12756						  "}\n"
12757						  "\n"
12758						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12759	};
12760
12761	result_sstream << "\n"
12762					  "void main()\n"
12763					  "{\n";
12764
12765	if (include_invalid_declaration)
12766	{
12767		result_sstream << "    test_subroutineVS(gl_Position);\n";
12768	}
12769	else
12770	{
12771		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12772	}
12773
12774	result_sstream << "}\n";
12775
12776	return result_sstream.str();
12777}
12778
12779/** Executes test iteration.
12780 *
12781 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12782 */
12783tcu::TestNode::IterateResult NegativeTest6::iterate()
12784{
12785	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12786	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12787	{
12788		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12789	}
12790
12791	/* Iterate over all shader stages. In each iteration, we will inject invalid
12792	 * duplicate function declarations to iteration-specific shader stage. All other
12793	 * shader stages will be assigned valid bodies. Test should fail if the program
12794	 * links successfully.
12795	 */
12796	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12797		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12798	{
12799		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12800		deinitIteration();
12801	} /* for (all shader stages) */
12802
12803	/* All done */
12804	if (m_has_test_passed)
12805	{
12806		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12807	}
12808	else
12809	{
12810		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12811	}
12812
12813	return STOP;
12814}
12815
12816/** Constructor
12817 *
12818 * @param context CTS context
12819 **/
12820NegativeTest7::NegativeTest7(deqp::Context& context)
12821	: TestCase(context, "recursion", "Verify that it is not possible to build program with recursing subroutines")
12822	, m_program_id(0)
12823	, m_vertex_shader_id(0)
12824{
12825	/* Nothing to be done here */
12826}
12827
12828/** Deinitializes all GL objects that may have been created during test execution
12829 *
12830 **/
12831void NegativeTest7::deinit()
12832{
12833	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12834
12835	if (m_program_id != 0)
12836	{
12837		gl.deleteProgram(m_program_id);
12838
12839		m_program_id = 0;
12840	}
12841
12842	if (m_vertex_shader_id != 0)
12843	{
12844		gl.deleteShader(m_vertex_shader_id);
12845
12846		m_vertex_shader_id = 0;
12847	}
12848}
12849
12850/** Executes test iteration.
12851 *
12852 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12853 **/
12854tcu::TestNode::IterateResult NegativeTest7::iterate()
12855{
12856	static const GLchar* vertex_shader_with_static_recursion =
12857		"#version 400\n"
12858		"\n"
12859		"#extension GL_ARB_shader_subroutine : require\n"
12860		"\n"
12861		"precision highp float;\n"
12862		"\n"
12863		"subroutine vec4 routine_type(in vec4 data, in uint control);\n"
12864		"\n"
12865		"subroutine (routine_type) vec4 power_routine(in vec4 data, in uint control)\n"
12866		"{\n"
12867		"    if (0 != control)\n"
12868		"    {\n"
12869		"        return data * power_routine(data, control - 1);\n"
12870		"    }\n"
12871		"    else\n"
12872		"    {\n"
12873		"        return vec4(1, 1, 1, 1);\n"
12874		"    }\n"
12875		"}\n"
12876		"\n"
12877		"subroutine (routine_type) vec4 select_routine(in vec4 data, in uint control)\n"
12878		"{\n"
12879		"    if (0 == control)\n"
12880		"    {\n"
12881		"        return data.rrrr;\n"
12882		"    }\n"
12883		"    else if (1 == control)\n"
12884		"    {\n"
12885		"        return data.gggg;\n"
12886		"    }\n"
12887		"    else if (2 == control)\n"
12888		"    {\n"
12889		"        return data.bbbb;\n"
12890		"    }\n"
12891		"    else\n"
12892		"    {\n"
12893		"        return data.aaaa;\n"
12894		"    }\n"
12895		"}\n"
12896		"\n"
12897		"subroutine uniform routine_type routine;\n"
12898		"\n"
12899		"uniform vec4 uni_value;\n"
12900		"uniform uint uni_control;\n"
12901		"\n"
12902		"out vec4 out_result;\n"
12903		"\n"
12904		"void main()\n"
12905		"{\n"
12906		"    out_result = routine(uni_value, uni_control);\n"
12907		"}\n"
12908		"\n";
12909
12910	static const GLchar* vertex_shader_with_dynamic_recursion =
12911		"#version 400\n"
12912		"\n"
12913		"#extension GL_ARB_shader_subroutine : require\n"
12914		"\n"
12915		"precision highp float;\n"
12916		"\n"
12917		"subroutine vec4 routine_type(in vec4 data);\n"
12918		"\n"
12919		"subroutine uniform routine_type routine;\n"
12920		"\n"
12921		"subroutine (routine_type) vec4 div_by_2(in vec4 data)\n"
12922		"{\n"
12923		"    return data / 2;\n"
12924		"}\n"
12925		"\n"
12926		"subroutine (routine_type) vec4 div_routine_result_by_2(in vec4 data)\n"
12927		"{\n"
12928		"    return routine(data) / 2;\n"
12929		"}\n"
12930		"\n"
12931		"uniform vec4 uni_value;\n"
12932		"\n"
12933		"out vec4 out_result;\n"
12934		"\n"
12935		"void main()\n"
12936		"{\n"
12937		"    out_result = routine(uni_value);\n"
12938		"}\n"
12939		"\n";
12940
12941	static const GLchar* vertex_shader_with_subroutine_function_recursion =
12942		"#version 400\n"
12943		"\n"
12944		"#extension GL_ARB_shader_subroutine : require\n"
12945		"\n"
12946		"precision highp float;\n"
12947		"\n"
12948		"subroutine vec4 routine_type(in vec4 data);\n"
12949		"\n"
12950		"subroutine uniform routine_type routine;\n"
12951		"\n"
12952		"vec4 function(in vec4 data)\n"
12953		"{\n"
12954		"    return routine(data) + vec4(0.5, 0.5, 0.5, 0.5);\n"
12955		"}\n"
12956		"\n"
12957		"subroutine (routine_type) vec4 routine_a(in vec4 data)\n"
12958		"{\n"
12959		"    return function(data) / 2;\n"
12960		"}\n"
12961		"\n"
12962		"subroutine (routine_type) vec4 routine_b(in vec4 data)\n"
12963		"{\n"
12964		"    return routine_a(data) * 2;\n"
12965		"}\n"
12966		"\n"
12967		"uniform vec4 uni_value;\n"
12968		"\n"
12969		"out vec4 out_result;\n"
12970		"\n"
12971		"void main()\n"
12972		"{\n"
12973		"    out_result = routine(uni_value);\n"
12974		"}\n"
12975		"\n";
12976
12977	bool result = true;
12978
12979	if (false == test(vertex_shader_with_subroutine_function_recursion, "routine_a"))
12980	{
12981		result = false;
12982	}
12983
12984	if (false == test(vertex_shader_with_dynamic_recursion, "div_routine_result_by_2"))
12985	{
12986		result = false;
12987	}
12988
12989	if (false == test(vertex_shader_with_static_recursion, "power_routine"))
12990	{
12991		result = false;
12992	}
12993
12994	/* Set result */
12995	if (true == result)
12996	{
12997		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12998	}
12999	else
13000	{
13001		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13002	}
13003
13004	/* Done */
13005	return tcu::TestNode::STOP;
13006}
13007
13008/** Try to build program from vertex shader code.
13009 *
13010 * @param vertex_shader_code        Source code of vertex shader
13011 * @param name_of_recursive_routine Name of subroutine that should cause link failure due to recursion
13012 *
13013 * @return true build process failed, false otherwise
13014 **/
13015bool NegativeTest7::test(const GLchar* vertex_shader_code, const GLchar* name_of_recursive_routine)
13016{
13017	const glw::Functions& gl		   = m_context.getRenderContext().getFunctions();
13018	bool				  result	   = true;
13019	static const GLchar*  varying_name = "out_result";
13020
13021	/* Try to build program */
13022	if (true == Utils::buildProgram(gl, vertex_shader_code, "", "", "", "", &varying_name /* varying_names */,
13023									1 /* n_varyings */, &m_vertex_shader_id, 0, 0, 0, 0, &m_program_id))
13024	{
13025		/* Success is considered an error */
13026
13027		Utils::program program(m_context);
13028		GLuint		   index = 0;
13029
13030		program.build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0);
13031
13032		/* Verify that recursive subroutine is active */
13033		try
13034		{
13035			index = program.getSubroutineIndex(name_of_recursive_routine, GL_VERTEX_SHADER);
13036		}
13037		catch (const std::exception& exc)
13038		{
13039			/* Something wrong with shader or compilation */
13040			m_context.getTestContext().getLog()
13041				<< tcu::TestLog::Message << "It is expected that subroutine: \n"
13042				<< name_of_recursive_routine
13043				<< " is considered active. This subroutine is potentially recursive and should cause link failure."
13044				<< tcu::TestLog::EndMessage;
13045
13046			throw exc;
13047		}
13048
13049		/* Subsoutine is active, however linking should fail */
13050		m_context.getTestContext().getLog()
13051			<< tcu::TestLog::Message << "Error. Program with potentially recursive subroutine, "
13052			<< name_of_recursive_routine << ", which is active, index: " << index << ", has been built successfully.\n"
13053			<< vertex_shader_code << tcu::TestLog::EndMessage;
13054
13055		result = false;
13056	}
13057
13058	/* Delete program and shader */
13059	deinit();
13060
13061	/* Done */
13062	return result;
13063}
13064
13065/** Constructor.
13066 *
13067 *  @param context Rendering context.
13068 *
13069 **/
13070NegativeTest8::NegativeTest8(deqp::Context& context)
13071	: TestCase(context, "subroutine_wo_body", "Verifies that a compile- or link-time error occurs if a function "
13072											  "declared as a subroutine does not include a body.")
13073	, m_fs_id(0)
13074	, m_gs_id(0)
13075	, m_has_test_passed(true)
13076	, m_po_id(0)
13077	, m_tc_id(0)
13078	, m_te_id(0)
13079	, m_vs_id(0)
13080{
13081	/* Left blank intentionally */
13082}
13083
13084/** Deinitializes all GL objects that may have been created during test execution */
13085void NegativeTest8::deinit()
13086{
13087	deinitIteration();
13088}
13089
13090/** Deinitializes all GL objects that may have been created during a single test
13091 *  iteration.
13092 ***/
13093void NegativeTest8::deinitIteration()
13094{
13095	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13096
13097	if (m_fs_id != 0)
13098	{
13099		gl.deleteShader(m_fs_id);
13100
13101		m_fs_id = 0;
13102	}
13103
13104	if (m_gs_id != 0)
13105	{
13106		gl.deleteShader(m_gs_id);
13107
13108		m_gs_id = 0;
13109	}
13110
13111	if (m_po_id != 0)
13112	{
13113		gl.deleteProgram(m_po_id);
13114
13115		m_po_id = 0;
13116	}
13117
13118	if (m_tc_id != 0)
13119	{
13120		gl.deleteShader(m_tc_id);
13121
13122		m_tc_id = 0;
13123	}
13124
13125	if (m_te_id != 0)
13126	{
13127		gl.deleteShader(m_te_id);
13128
13129		m_te_id = 0;
13130	}
13131
13132	if (m_vs_id != 0)
13133	{
13134		gl.deleteShader(m_vs_id);
13135
13136		m_vs_id = 0;
13137	}
13138}
13139
13140/** Executes a single test iteration.
13141 *
13142 *  If the iteration fails, m_has_test_passed will be set to false.
13143 *
13144 *  @param shader_stage Shader stage, for which two duplicate functions
13145 *                      (one additionally marked as subroutine) should
13146 *                      be defined.
13147 **/
13148void NegativeTest8::executeIteration(const Utils::_shader_stage& shader_stage)
13149{
13150	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
13151	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
13152	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
13153	std::string te_body =
13154		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
13155	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
13156
13157	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
13158							DE_NULL, /* xfb_varyings */
13159							DE_NULL, /* n_xfb_varyings */
13160							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
13161	{
13162		/* None of the test programs should ever build successfully */
13163		m_testCtx.getLog() << tcu::TestLog::Message
13164						   << "A program object consisting of FS+GS+TC+TE+VS stages has linked successfully, "
13165							  "even though one of the shaders only defines a subroutine that lacks any body."
13166							  "\n"
13167							  "Vertex shader:\n"
13168							  "\n"
13169						   << vs_body << "\n"
13170										 "Tessellation control shader:\n"
13171										 "\n"
13172						   << tc_body << "\n"
13173										 "Tessellation evaluation shader:\n"
13174										 "\n"
13175						   << te_body << "\n"
13176										 "Geometry shader:\n"
13177										 "\n"
13178						   << gs_body << "\n"
13179										 "Fragment shader:\n"
13180										 "\n"
13181						   << fs_body << tcu::TestLog::EndMessage;
13182
13183		m_has_test_passed = false;
13184	}
13185}
13186
13187/** Retrieves fragment shader body.
13188 *
13189 *  @param include_invalid_declaration true if a subroutine prototype should be included in
13190 *                                     the shader, false to skip it.
13191 *
13192 *  @return Requested string.
13193 **/
13194std::string NegativeTest8::getFragmentShaderBody(bool include_invalid_declaration) const
13195{
13196	std::stringstream result_sstream;
13197
13198	result_sstream << "#version 400\n"
13199					  "\n"
13200					  "#extension GL_ARB_shader_subroutine : require\n"
13201					  "\n";
13202
13203	if (include_invalid_declaration)
13204	{
13205		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
13206						  "\n"
13207						  "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test);\n"
13208						  "\n"
13209						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
13210	};
13211
13212	result_sstream << "\n"
13213					  "out vec4 result;\n"
13214					  "\n"
13215					  "void main()\n"
13216					  "{\n";
13217
13218	if (include_invalid_declaration)
13219	{
13220		result_sstream << "    test_subroutineFS(result);\n";
13221	}
13222	else
13223	{
13224		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
13225	}
13226
13227	result_sstream << "}\n";
13228
13229	return result_sstream.str();
13230}
13231
13232/** Retrieves geometry shader body.
13233 *
13234 *  @param include_invalid_declaration true if a subroutine prototype should be included in
13235 *                                     the shader, false to skip it.
13236 *
13237 *  @return Requested string.
13238 **/
13239std::string NegativeTest8::getGeometryShaderBody(bool include_invalid_declaration) const
13240{
13241	std::stringstream result_sstream;
13242
13243	result_sstream << "#version 400\n"
13244					  "\n"
13245					  "#extension GL_ARB_shader_subroutine : require\n"
13246					  "\n"
13247					  "layout (points)                   in;\n"
13248					  "layout (points, max_vertices = 1) out;\n"
13249					  "\n";
13250
13251	if (include_invalid_declaration)
13252	{
13253		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
13254						  "\n"
13255						  "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test);\n"
13256						  "\n"
13257						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
13258	};
13259
13260	result_sstream << "\n"
13261					  "void main()\n"
13262					  "{\n";
13263
13264	if (include_invalid_declaration)
13265	{
13266		result_sstream << "    test_subroutineGS(gl_Position);\n";
13267	}
13268	else
13269	{
13270		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
13271	}
13272
13273	result_sstream << "EmitVertex();\n"
13274					  "}\n";
13275
13276	return result_sstream.str();
13277}
13278
13279/** Retrieves tessellation control shader body.
13280 *
13281 *  @param include_invalid_declaration true if a subroutine prototype should be included in
13282 *                                     the shader, false to skip it.
13283 *
13284 *  @return Requested string.
13285 **/
13286std::string NegativeTest8::getTessellationControlShaderBody(bool include_invalid_declaration) const
13287{
13288	std::stringstream result_sstream;
13289
13290	result_sstream << "#version 400\n"
13291					  "\n"
13292					  "#extension GL_ARB_shader_subroutine : require\n"
13293					  "\n"
13294					  "layout (vertices = 4) out;\n"
13295					  "\n";
13296
13297	if (include_invalid_declaration)
13298	{
13299		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
13300						  "\n"
13301						  "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test);\n"
13302						  "\n"
13303						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
13304	};
13305
13306	result_sstream << "\n"
13307					  "void main()\n"
13308					  "{\n";
13309
13310	if (include_invalid_declaration)
13311	{
13312		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
13313	}
13314	else
13315	{
13316		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
13317	}
13318
13319	result_sstream << "}\n";
13320
13321	return result_sstream.str();
13322}
13323
13324/** Retrieves tessellation evaluation body.
13325 *
13326 *  @param include_invalid_declaration true if a subroutine prototype should be included in
13327 *                                     the shader, false to skip it.
13328 *
13329 *  @return Requested string.
13330 **/
13331std::string NegativeTest8::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
13332{
13333	std::stringstream result_sstream;
13334
13335	result_sstream << "#version 400\n"
13336					  "\n"
13337					  "#extension GL_ARB_shader_subroutine : require\n"
13338					  "\n"
13339					  "layout (quads) in;\n"
13340					  "\n";
13341
13342	if (include_invalid_declaration)
13343	{
13344		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
13345						  "\n"
13346						  "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test);\n"
13347						  "\n"
13348						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
13349	};
13350
13351	result_sstream << "\n"
13352					  "void main()\n"
13353					  "{\n";
13354
13355	if (include_invalid_declaration)
13356	{
13357		result_sstream << "    test_subroutineTE(gl_Position);\n";
13358	}
13359	else
13360	{
13361		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
13362	}
13363
13364	result_sstream << "}\n";
13365
13366	return result_sstream.str();
13367}
13368
13369/** Retrieves vertex shader body.
13370 *
13371 *  @param include_invalid_declaration true if a subroutine prototype should be included in
13372 *                                     the shader, false to skip it.
13373 *
13374 *  @return Requested string.
13375 **/
13376std::string NegativeTest8::getVertexShaderBody(bool include_invalid_declaration) const
13377{
13378	std::stringstream result_sstream;
13379
13380	result_sstream << "#version 400\n"
13381					  "\n"
13382					  "#extension GL_ARB_shader_subroutine : require\n"
13383					  "\n";
13384
13385	if (include_invalid_declaration)
13386	{
13387		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
13388						  "\n"
13389						  "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test);\n"
13390						  "\n"
13391						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
13392	};
13393
13394	result_sstream << "\n"
13395					  "void main()\n"
13396					  "{\n";
13397
13398	if (include_invalid_declaration)
13399	{
13400		result_sstream << "    test_subroutineVS(gl_Position);\n";
13401	}
13402	else
13403	{
13404		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
13405	}
13406
13407	result_sstream << "}\n";
13408
13409	return result_sstream.str();
13410}
13411
13412/** Executes test iteration.
13413 *
13414 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13415 */
13416tcu::TestNode::IterateResult NegativeTest8::iterate()
13417{
13418	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13419	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13420	{
13421		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13422	}
13423
13424	/* Iterate over all shader stages. For each iteration, iteration-specific shader stage
13425	 * will feature an invalid subroutine definition. Other shader stages will be assigned
13426	 * valid bodies. The test fails if a program built of such shaders links successfully.
13427	 */
13428	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
13429		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
13430	{
13431		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
13432		deinitIteration();
13433	} /* for (all shader stages) */
13434
13435	/* All done */
13436	if (m_has_test_passed)
13437	{
13438		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13439	}
13440	else
13441	{
13442		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13443	}
13444
13445	return STOP;
13446}
13447
13448/** Constructor.
13449 *
13450 *  @param context Rendering context.
13451 **/
13452NegativeTest9::NegativeTest9(deqp::Context& context)
13453	: TestCase(context, "subroutines_cannot_be_assigned_float_int_values_or_be_compared",
13454			   "Make sure it is not possible to assign float/int to subroutine "
13455			   "uniform and that subroutine uniform values cannot be compared.")
13456	, m_has_test_passed(true)
13457	, m_po_id(0)
13458	, m_vs_id(0)
13459{
13460	/* Left blank intentionally */
13461}
13462
13463/** Deinitializes any GL objects that may have been created during
13464 *  test execution.
13465 **/
13466void NegativeTest9::deinit()
13467{
13468	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13469
13470	if (m_po_id != 0)
13471	{
13472		gl.deleteProgram(m_po_id);
13473
13474		m_po_id = 0;
13475	}
13476
13477	if (m_vs_id != 0)
13478	{
13479		gl.deleteShader(m_vs_id);
13480
13481		m_vs_id = 0;
13482	}
13483}
13484
13485/** Returns a literal corresponding to user-specified test case enum.
13486 *
13487 *  @param test_case As per description.
13488 *
13489 *  @return Requested string.
13490 **/
13491std::string NegativeTest9::getTestCaseString(const _test_case& test_case)
13492{
13493	std::string result = "?";
13494
13495	switch (test_case)
13496	{
13497	case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13498		result = "TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
13499		break;
13500	case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13501		result = "TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
13502		break;
13503	case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
13504		result = "TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON";
13505		break;
13506	default:
13507		break;
13508	}
13509
13510	return result;
13511}
13512
13513/** Retrieves vertex shader body for user-specified test case.
13514 *
13515 *  @param test_case As per description.
13516 *
13517 *  @return Requested string.
13518 **/
13519std::string NegativeTest9::getVertexShader(const _test_case& test_case)
13520{
13521	std::stringstream result_sstream;
13522
13523	/* Form pre-amble */
13524	result_sstream << "#version 400\n"
13525					  "\n"
13526					  "#extension GL_ARB_shader_subroutine : require\n"
13527					  "\n"
13528					  /* Define a subroutine */
13529					  "subroutine void subroutineType(inout vec4 test);\n"
13530					  "\n"
13531					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13532					  "{\n"
13533					  "    test += vec4(0, 1, 2, 3);\n"
13534					  "}\n"
13535					  "\n"
13536					  "subroutine uniform subroutineType function;\n"
13537					  "\n";
13538
13539	/* Include case-specific implementation */
13540	switch (test_case)
13541	{
13542	case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13543	{
13544		result_sstream << "void main()\n"
13545						  "{\n"
13546						  "    function = 1.0f;\n"
13547						  "\n"
13548						  "    function(gl_Position);\n"
13549						  "}\n";
13550
13551		break;
13552	}
13553
13554	case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13555	{
13556		result_sstream << "void main()\n"
13557						  "{\n"
13558						  "    function = 1;\n"
13559						  "\n"
13560						  "    function(gl_Position);\n"
13561						  "}\n";
13562
13563		break;
13564	}
13565
13566	case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
13567	{
13568		result_sstream << "subroutine uniform subroutineType function2;\n"
13569						  "\n"
13570						  "void main()\n"
13571						  "{\n"
13572						  "    if (function == function2)\n"
13573						  "    {\n"
13574						  "        function(gl_Position);\n"
13575						  "    }\n"
13576						  "    else\n"
13577						  "    {\n"
13578						  "        function2(gl_Position);\n"
13579						  "    }\n"
13580						  "}\n";
13581
13582		break;
13583	}
13584
13585	default:
13586		break;
13587	} /* switch (test_case) */
13588
13589	/* Done */
13590	return result_sstream.str();
13591}
13592
13593/** Executes test iteration.
13594 *
13595 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13596 */
13597tcu::TestNode::IterateResult NegativeTest9::iterate()
13598{
13599	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13600
13601	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13602	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13603	{
13604		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13605	}
13606
13607	/* Iterate over all test cases */
13608	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
13609	{
13610		/* Try to build a program object using invalid vertex shader, specific to the
13611		 * iteration we're currently in */
13612		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
13613
13614		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
13615												  "",				 /* te_body */
13616												  "",				 /* gs_body */
13617												  "",				 /* fs_body */
13618												  DE_NULL,			 /* xfb_varyings */
13619												  0,				 /* n_xfb_varyings */
13620												  &m_vs_id, DE_NULL, /* out_tc_id */
13621												  DE_NULL,			 /* out_te_id */
13622												  DE_NULL,			 /* out_gs_id */
13623												  DE_NULL,			 /* out_fs_id */
13624												  &m_po_id))
13625		{
13626			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13627							   << getTestCaseString(static_cast<_test_case>(test_case))
13628							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
13629
13630			m_has_test_passed = false;
13631		}
13632
13633		/* Delete any objects that may have been created */
13634		deinit();
13635	} /* for (all test cases) */
13636
13637	/** All done */
13638	if (m_has_test_passed)
13639	{
13640		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13641	}
13642	else
13643	{
13644		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13645	}
13646
13647	return STOP;
13648}
13649
13650/** Constructor.
13651 *
13652 *  @param context Rendering context.
13653 **/
13654NegativeTest10::NegativeTest10(deqp::Context& context)
13655	: TestCase(context, "function_overloading_forbidden_for_subroutines",
13656			   "Check that an overloaded function cannot be declared with subroutine and "
13657			   "a program will fail to compile or link if any shader or stage contains"
13658			   " two or more  functions with the same name if the name is associated with"
13659			   " a subroutine type.")
13660	, m_has_test_passed(true)
13661	, m_fs_id(0)
13662	, m_gs_id(0)
13663	, m_po_id(0)
13664	, m_tc_id(0)
13665	, m_te_id(0)
13666	, m_vs_id(0)
13667{
13668	/* Left blank intentionally */
13669}
13670
13671/** Deinitializes any GL objects that may have been created during
13672 *  test execution.
13673 **/
13674void NegativeTest10::deinit()
13675{
13676	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13677
13678	if (m_fs_id != 0)
13679	{
13680		gl.deleteShader(m_fs_id);
13681
13682		m_fs_id = 0;
13683	}
13684
13685	if (m_gs_id != 0)
13686	{
13687		gl.deleteShader(m_gs_id);
13688
13689		m_gs_id = 0;
13690	}
13691
13692	if (m_po_id != 0)
13693	{
13694		gl.deleteProgram(m_po_id);
13695
13696		m_po_id = 0;
13697	}
13698
13699	if (m_tc_id != 0)
13700	{
13701		gl.deleteShader(m_tc_id);
13702
13703		m_tc_id = 0;
13704	}
13705
13706	if (m_te_id != 0)
13707	{
13708		gl.deleteShader(m_te_id);
13709
13710		m_te_id = 0;
13711	}
13712
13713	if (m_vs_id != 0)
13714	{
13715		gl.deleteShader(m_vs_id);
13716
13717		m_vs_id = 0;
13718	}
13719}
13720
13721/** Retrieves fragment shader that should be used for the purpose of the test.
13722 *  An overloaded version of a subroutine function is inserted if
13723 *  @param include_duplicate_function flag is set to true.
13724 *
13725 *  @param include_duplicate_function As per description.
13726 *
13727 *  @return Requested string.
13728 **/
13729std::string NegativeTest10::getFragmentShader(bool include_duplicate_function)
13730{
13731	std::stringstream result_sstream;
13732
13733	result_sstream << "#version 400\n"
13734					  "\n"
13735					  "#extension GL_ARB_shader_subroutine : require\n"
13736					  "\n"
13737					  "subroutine void subroutineType(inout vec4 test);\n"
13738					  "\n"
13739					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13740					  "{\n"
13741					  "    test = vec4(2, 3, 4, 5);\n"
13742					  "}\n"
13743					  "\n"
13744					  "subroutine uniform subroutineType function;\n"
13745					  "out vec4 result;\n"
13746					  "\n";
13747
13748	if (include_duplicate_function)
13749	{
13750		result_sstream << "void test_function(inout vec4 test)\n"
13751						  "{\n"
13752						  "    test = vec4(3, 4, 5, 6);\n"
13753						  "}\n"
13754						  "\n";
13755	}
13756
13757	result_sstream << "void main()\n"
13758					  "{\n"
13759					  "    test_function(result);\n"
13760					  "}\n";
13761
13762	return result_sstream.str();
13763}
13764
13765/** Retrieves geometry shader that should be used for the purpose of the test.
13766 *  An overloaded version of a subroutine function is inserted if
13767 *  @param include_duplicate_function flag is set to true.
13768 *
13769 *  @param include_duplicate_function As per description.
13770 *
13771 *  @return Requested string.
13772 **/
13773std::string NegativeTest10::getGeometryShader(bool include_duplicate_function)
13774{
13775	std::stringstream result_sstream;
13776
13777	result_sstream << "#version 400\n"
13778					  "\n"
13779					  "#extension GL_ARB_shader_subroutine : require\n"
13780					  "\n"
13781					  "layout (triangles)                        in;\n"
13782					  "layout (triangle_strip, max_vertices = 4) out;\n"
13783					  "\n"
13784					  "subroutine void subroutineType(inout vec4 test);\n"
13785					  "\n"
13786					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13787					  "{\n"
13788					  "    test = vec4(2, 3, 4, 5);\n"
13789					  "}\n"
13790					  "\n"
13791					  "subroutine uniform subroutineType function;\n"
13792					  "\n";
13793
13794	if (include_duplicate_function)
13795	{
13796		result_sstream << "void test_function(inout vec4 test)\n"
13797						  "{\n"
13798						  "    test = vec4(3, 4, 5, 6);\n"
13799						  "}\n"
13800						  "\n";
13801	}
13802
13803	result_sstream << "void main()\n"
13804					  "{\n"
13805					  "    function(gl_Position);\n"
13806					  "    EmitVertex();\n"
13807					  "    EndPrimitive();\n"
13808					  "}\n";
13809
13810	return result_sstream.str();
13811}
13812
13813/** Retrieves tess control shader that should be used for the purpose of the test.
13814 *  An overloaded version of a subroutine function is inserted if
13815 *  @param include_duplicate_function flag is set to true.
13816 *
13817 *  @param include_duplicate_function As per description.
13818 *
13819 *  @return Requested string.
13820 **/
13821std::string NegativeTest10::getTessellationControlShader(bool include_duplicate_function)
13822{
13823	std::stringstream result_sstream;
13824
13825	result_sstream << "#version 400\n"
13826					  "\n"
13827					  "#extension GL_ARB_shader_subroutine : require\n"
13828					  "\n"
13829					  "layout (vertices = 4) out;\n"
13830					  "\n"
13831					  "subroutine void subroutineType(inout vec4 test);\n"
13832					  "\n"
13833					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13834					  "{\n"
13835					  "    test = vec4(2, 3, 4, 5);\n"
13836					  "}\n"
13837					  "\n"
13838					  "subroutine uniform subroutineType function;\n"
13839					  "\n";
13840
13841	if (include_duplicate_function)
13842	{
13843		result_sstream << "void test_function(inout vec4 test)\n"
13844						  "{\n"
13845						  "    test = vec4(3, 4, 5, 6);\n"
13846						  "}\n"
13847						  "\n";
13848	}
13849
13850	result_sstream << "void main()\n"
13851					  "{\n"
13852					  "    vec4 temp;\n"
13853					  "\n"
13854					  "    function(temp);\n"
13855					  "\n"
13856					  "    gl_out[gl_InvocationID].gl_Position = temp;\n"
13857					  "    gl_TessLevelInner[0]                = temp.x;\n"
13858					  "    gl_TessLevelInner[1]                = temp.y;\n"
13859					  "    gl_TessLevelOuter[0]                = temp.z;\n"
13860					  "    gl_TessLevelOuter[1]                = temp.w;\n"
13861					  "    gl_TessLevelOuter[2]                = temp.x;\n"
13862					  "    gl_TessLevelOuter[3]                = temp.y;\n"
13863					  "}\n";
13864
13865	return result_sstream.str();
13866}
13867
13868/** Retrieves tess evaluation shader that should be used for the purpose of the test.
13869 *  An overloaded version of a subroutine function is inserted if
13870 *  @param include_duplicate_function flag is set to true.
13871 *
13872 *  @param include_duplicate_function As per description.
13873 *
13874 *  @return Requested string.
13875 **/
13876std::string NegativeTest10::getTessellationEvaluationShader(bool include_duplicate_function)
13877{
13878	std::stringstream result_sstream;
13879
13880	result_sstream << "#version 400\n"
13881					  "\n"
13882					  "#extension GL_ARB_shader_subroutine : require\n"
13883					  "\n"
13884					  "layout (quads) in;\n"
13885					  "\n"
13886					  "subroutine void subroutineType(inout vec4 test);\n"
13887					  "\n"
13888					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13889					  "{\n"
13890					  "    test = vec4(2, 3, 4, 5);\n"
13891					  "}\n"
13892					  "\n"
13893					  "subroutine uniform subroutineType function;\n"
13894					  "\n";
13895
13896	if (include_duplicate_function)
13897	{
13898		result_sstream << "void test_function(inout vec4 test)\n"
13899						  "{\n"
13900						  "    test = vec4(3, 4, 5, 6);\n"
13901						  "}\n"
13902						  "\n";
13903	}
13904
13905	result_sstream << "void main()\n"
13906					  "{\n"
13907					  "    vec4 temp;\n"
13908					  "\n"
13909					  "    function(temp);\n"
13910					  "\n"
13911					  "    gl_Position = temp;\n"
13912					  "}\n";
13913
13914	return result_sstream.str();
13915}
13916
13917/** Retrieves vertex shader that should be used for the purpose of the test.
13918 *  An overloaded version of a subroutine function is inserted if
13919 *  @param include_duplicate_function flag is set to true.
13920 *
13921 *  @param include_duplicate_function As per description.
13922 *
13923 *  @return Requested string.
13924 **/
13925std::string NegativeTest10::getVertexShader(bool include_duplicate_function)
13926{
13927	std::stringstream result_sstream;
13928
13929	result_sstream << "#version 400\n"
13930					  "\n"
13931					  "#extension GL_ARB_shader_subroutine : require\n"
13932					  "\n"
13933					  "subroutine void subroutineType(inout vec4 test);\n"
13934					  "\n"
13935					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13936					  "{\n"
13937					  "    test = vec4(2, 3, 4, 5);\n"
13938					  "}\n"
13939					  "\n"
13940					  "subroutine uniform subroutineType function;\n"
13941					  "\n";
13942
13943	if (include_duplicate_function)
13944	{
13945		result_sstream << "void test_function(inout vec4 test)\n"
13946						  "{\n"
13947						  "    test = vec4(3, 4, 5, 6);\n"
13948						  "}\n"
13949						  "\n";
13950	}
13951
13952	result_sstream << "void main()\n"
13953					  "{\n"
13954					  "    function(gl_Position);\n"
13955					  "}\n";
13956
13957	return result_sstream.str();
13958}
13959
13960/** Fills m_test_cases field with test case descriptors */
13961void NegativeTest10::initTestCases()
13962{
13963	/* For each test case, only one shader stage should define a function that
13964	 * has already been defined as a subroutine. */
13965	for (int offending_shader_stage_it = static_cast<int>(Utils::SHADER_STAGE_FIRST);
13966		 offending_shader_stage_it != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++offending_shader_stage_it)
13967	{
13968		Utils::_shader_stage offending_shader_stage = static_cast<Utils::_shader_stage>(offending_shader_stage_it);
13969		/* Form the test case descriptor */
13970		std::stringstream name_sstream;
13971		_test_case		  test_case;
13972
13973		name_sstream << "Broken shader stage:" << Utils::getShaderStageString(offending_shader_stage);
13974
13975		test_case.fs_body = getFragmentShader(offending_shader_stage == Utils::SHADER_STAGE_FRAGMENT);
13976		test_case.gs_body = getGeometryShader(offending_shader_stage == Utils::SHADER_STAGE_GEOMETRY);
13977		test_case.name	= name_sstream.str();
13978		test_case.tc_body =
13979			getTessellationControlShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
13980		test_case.te_body =
13981			getTessellationEvaluationShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
13982		test_case.vs_body = getVertexShader(offending_shader_stage == Utils::SHADER_STAGE_VERTEX);
13983
13984		m_test_cases.push_back(test_case);
13985	}
13986}
13987
13988/** Executes test iteration.
13989 *
13990 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13991 */
13992tcu::TestNode::IterateResult NegativeTest10::iterate()
13993{
13994	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13995
13996	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13997	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13998	{
13999		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14000	}
14001
14002	/* Form test cases */
14003	initTestCases();
14004
14005	/* Iterate over all test cases */
14006	for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
14007		 ++test_case_iterator)
14008	{
14009		const _test_case& test_case = *test_case_iterator;
14010
14011		/* Try to build the program object */
14012		if (ShaderSubroutine::Utils::buildProgram(gl, test_case.vs_body, test_case.tc_body, test_case.te_body,
14013												  test_case.gs_body, test_case.fs_body, DE_NULL, /* xfb_varyings */
14014												  0,											 /* n_xfb_varyings */
14015												  &m_vs_id, (test_case.tc_body.length() > 0) ? &m_tc_id : DE_NULL,
14016												  (test_case.te_body.length() > 0) ? &m_te_id : DE_NULL,
14017												  (test_case.gs_body.length() > 0) ? &m_gs_id : DE_NULL,
14018												  (test_case.fs_body.length() > 0) ? &m_fs_id : DE_NULL, &m_po_id))
14019		{
14020			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14021							   << test_case.name << "] test case, even though it was invalid."
14022							   << tcu::TestLog::EndMessage;
14023
14024			m_has_test_passed = false;
14025		}
14026
14027		/* Delete any objects that may have been created */
14028		deinit();
14029	} /* for (all test cases) */
14030
14031	/** All done */
14032	if (m_has_test_passed)
14033	{
14034		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14035	}
14036	else
14037	{
14038		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14039	}
14040
14041	return STOP;
14042}
14043
14044/** Constructor.
14045 *
14046 *  @param context Rendering context.
14047 **/
14048NegativeTest11::NegativeTest11(deqp::Context& context)
14049	: TestCase(context, "subroutine_uniforms_used_for_sampling_atomic_image_functions",
14050			   "Tries to use subroutine uniforms in invalid way in sampling, "
14051			   "atomic and image functions. Verifies that compile- or link-time "
14052			   "error occurs.")
14053	, m_has_test_passed(true)
14054	, m_po_id(0)
14055	, m_vs_id(0)
14056{
14057	/* Left blank intentionally */
14058}
14059
14060/** Deinitializes any GL objects that may have been created during
14061 *  test execution.
14062 **/
14063void NegativeTest11::deinit()
14064{
14065	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14066
14067	if (m_po_id != 0)
14068	{
14069		gl.deleteProgram(m_po_id);
14070
14071		m_po_id = 0;
14072	}
14073
14074	if (m_vs_id != 0)
14075	{
14076		gl.deleteShader(m_vs_id);
14077
14078		m_vs_id = 0;
14079	}
14080}
14081
14082/** Returns a literal corresponding to user-specified test case enum.
14083 *
14084 *  @param test_case As per description.
14085 *
14086 *  @return Requested string.
14087 **/
14088std::string NegativeTest11::getTestCaseString(const _test_case& test_case)
14089{
14090	std::string result = "?";
14091
14092	switch (test_case)
14093	{
14094	case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
14095		result = "TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT";
14096		break;
14097	case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
14098		result = "TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT";
14099		break;
14100	case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
14101		result = "TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT";
14102		break;
14103	default:
14104		break;
14105	}
14106
14107	return result;
14108}
14109
14110/** Retrieves vertex shader body for user-specified test case.
14111 *
14112 *  @param test_case As per description.
14113 *
14114 *  @return Requested string.
14115 **/
14116std::string NegativeTest11::getVertexShader(const _test_case& test_case)
14117{
14118	std::stringstream result_sstream;
14119
14120	/* Form pre-amble */
14121	result_sstream << "#version 400\n"
14122					  "\n"
14123					  "#extension GL_ARB_shader_subroutine : require\n";
14124
14125	if (test_case == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT)
14126	{
14127		result_sstream << "#extension GL_ARB_shader_atomic_counters : require\n";
14128	}
14129
14130	result_sstream << "\n"
14131					  /* Define a subroutine */
14132					  "subroutine void subroutineType(inout vec4 test);\n"
14133					  "\n"
14134					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
14135					  "{\n"
14136					  "    test += vec4(0, 1, 2, 3);\n"
14137					  "}\n"
14138					  "\n"
14139					  "subroutine uniform subroutineType function;\n"
14140					  "\n"
14141
14142					  /* Define main() body */
14143					  "void main()\n"
14144					  "{\n";
14145
14146	/* Implement case-specific behavior */
14147	switch (test_case)
14148	{
14149	case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
14150	{
14151		result_sstream << "if (atomicCounter(function) > 2)\n"
14152						  "{\n"
14153						  "    gl_Position = vec4(1);\n"
14154						  "}\n";
14155
14156		break;
14157	}
14158
14159	case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
14160	{
14161		result_sstream << "imageStore(function, vec2(0.0, 1.0), vec4(1.0) );\n";
14162
14163		break;
14164	}
14165
14166	case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
14167	{
14168		result_sstream << "gl_Position = texture(function, vec2(1.0) );\n";
14169
14170		break;
14171	}
14172
14173	default:
14174		break;
14175	} /* switch (test_case) */
14176
14177	/* Close main() body */
14178	result_sstream << "}\n";
14179
14180	/* Done */
14181	return result_sstream.str();
14182}
14183
14184/** Executes test iteration.
14185 *
14186 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
14187 */
14188tcu::TestNode::IterateResult NegativeTest11::iterate()
14189{
14190	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14191
14192	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
14193	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
14194	{
14195		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14196	}
14197
14198	/* Iterate over all test cases */
14199	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
14200	{
14201		if (static_cast<_test_case>(test_case) == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT &&
14202			!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
14203		{
14204			/* This iteration requires atomic counter support that this GL implementation
14205			 * is not capable of. Skip the iteration
14206			 */
14207			continue;
14208		}
14209
14210		/* Try to build a program object using invalid vertex shader, specific to the
14211		 * iteration we're currently in */
14212		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
14213
14214		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
14215												  "",				 /* te_body */
14216												  "",				 /* gs_body */
14217												  "",				 /* fs_body */
14218												  DE_NULL,			 /* xfb_varyings */
14219												  0,				 /* n_xfb_varyings */
14220												  &m_vs_id, DE_NULL, /* out_tc_id */
14221												  DE_NULL,			 /* out_te_id */
14222												  DE_NULL,			 /* out_gs_id */
14223												  DE_NULL,			 /* out_fs_id */
14224												  &m_po_id))
14225		{
14226			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14227							   << getTestCaseString(static_cast<_test_case>(test_case))
14228							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
14229
14230			m_has_test_passed = false;
14231		}
14232
14233		/* Delete any objects that may have been created */
14234		deinit();
14235	} /* for (all test cases) */
14236
14237	/** All done */
14238	if (m_has_test_passed)
14239	{
14240		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14241	}
14242	else
14243	{
14244		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14245	}
14246
14247	return STOP;
14248}
14249
14250/** Constructor.
14251 *
14252 *  @param context Rendering context.
14253 **/
14254NegativeTest12::NegativeTest12(deqp::Context& context)
14255	: TestCase(context, "subroutines_not_allowed_as_variables_constructors_and_argument_or_return_types",
14256			   "Verifies that it is not allowed to use subroutine type for "
14257			   "local/global variables, constructors or argument/return type.")
14258	, m_has_test_passed(true)
14259	, m_po_id(0)
14260	, m_vs_id(0)
14261{
14262	/* Left blank intentionally */
14263}
14264
14265/** Deinitializes any GL objects that may have been created during
14266 *  test execution.
14267 **/
14268void NegativeTest12::deinit()
14269{
14270	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14271
14272	if (m_po_id != 0)
14273	{
14274		gl.deleteProgram(m_po_id);
14275
14276		m_po_id = 0;
14277	}
14278
14279	if (m_vs_id != 0)
14280	{
14281		gl.deleteShader(m_vs_id);
14282
14283		m_vs_id = 0;
14284	}
14285}
14286
14287/** Returns a literal corresponding to user-specified test case enum.
14288 *
14289 *  @param test_case As per description.
14290 *
14291 *  @return Requested string.
14292 **/
14293std::string NegativeTest12::getTestCaseString(const _test_case& test_case)
14294{
14295	std::string result = "?";
14296
14297	switch (test_case)
14298	{
14299	case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
14300		result = "TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE";
14301		break;
14302	case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
14303		result = "TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE";
14304		break;
14305	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
14306		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR";
14307		break;
14308	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
14309		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT";
14310		break;
14311	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
14312		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE";
14313		break;
14314	default:
14315		break;
14316	}
14317
14318	return result;
14319}
14320
14321/** Retrieves vertex shader body for user-specified test case.
14322 *
14323 *  @param test_case As per description.
14324 *
14325 *  @return Requested string.
14326 **/
14327std::string NegativeTest12::getVertexShader(const _test_case& test_case)
14328{
14329	std::stringstream result_sstream;
14330
14331	/* Form pre-amble */
14332	result_sstream << "#version 400\n"
14333					  "\n"
14334					  "#extension GL_ARB_shader_subroutine : require\n"
14335					  "\n"
14336					  /* Define a subroutine */
14337					  "subroutine void subroutineType(inout vec4 test);\n"
14338					  "\n"
14339					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
14340					  "{\n"
14341					  "    test += vec4(0, 1, 2, 3);\n"
14342					  "}\n"
14343					  "\n"
14344					  "subroutine uniform subroutineType function;\n"
14345					  "\n";
14346
14347	/* Include case-specific implementation */
14348	switch (test_case)
14349	{
14350	case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
14351	{
14352		result_sstream << "void main()\n"
14353						  "{\n"
14354						  "    subroutine subroutineType function2;\n"
14355						  "    vec4                      result;\n"
14356						  "\n"
14357						  "    function2(result);\n"
14358						  "    gl_Position = result;\n"
14359						  "}\n";
14360
14361		break;
14362	}
14363
14364	case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
14365	{
14366		result_sstream << "subroutine subroutineType function2;\n"
14367						  "\n"
14368						  "void main()\n"
14369						  "{\n"
14370						  "    vec4 result;\n"
14371						  "\n"
14372						  "    function2(result);\n"
14373						  "    gl_Position = result;\n"
14374						  "}\n";
14375
14376		break;
14377	}
14378
14379	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
14380	{
14381		result_sstream << "void main()\n"
14382						  "{\n"
14383						  "    subroutineType(function);\n"
14384						  "}\n";
14385
14386		break;
14387	}
14388
14389	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
14390	{
14391		result_sstream << "vec4 test_function(subroutineType argument)\n"
14392						  "{\n"
14393						  "    vec4 result = vec4(1, 2, 3, 4);\n"
14394						  "\n"
14395						  "    argument(result);\n"
14396						  "\n"
14397						  "    return result;\n"
14398						  "}\n"
14399						  "\n"
14400						  "void main()\n"
14401						  "{\n"
14402						  "    test_function(function);\n"
14403						  "}\n";
14404
14405		break;
14406	}
14407
14408	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
14409	{
14410		result_sstream << "subroutineType test_function()\n"
14411						  "{\n"
14412						  "    return function;\n"
14413						  "}\n"
14414						  "\n"
14415						  "void main()\n"
14416						  "{\n"
14417						  "    test_function()(gl_Position);\n"
14418						  "}\n";
14419
14420		break;
14421	}
14422
14423	default:
14424		break;
14425	} /* switch (test_case) */
14426
14427	/* Done */
14428	return result_sstream.str();
14429}
14430
14431/** Executes test iteration.
14432 *
14433 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
14434 */
14435tcu::TestNode::IterateResult NegativeTest12::iterate()
14436{
14437	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14438
14439	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
14440	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
14441	{
14442		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14443	}
14444
14445	/* Iterate over all test cases */
14446	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
14447	{
14448		/* Try to build a program object using invalid vertex shader, specific to the
14449		 * iteration we're currently in */
14450		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
14451
14452		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
14453												  "",				 /* te_body */
14454												  "",				 /* gs_body */
14455												  "",				 /* fs_body */
14456												  DE_NULL,			 /* xfb_varyings */
14457												  0,				 /* n_xfb_varyings */
14458												  &m_vs_id, DE_NULL, /* out_tc_id */
14459												  DE_NULL,			 /* out_te_id */
14460												  DE_NULL,			 /* out_gs_id */
14461												  DE_NULL,			 /* out_fs_id */
14462												  &m_po_id))
14463		{
14464			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14465							   << getTestCaseString(static_cast<_test_case>(test_case))
14466							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
14467
14468			m_has_test_passed = false;
14469		}
14470
14471		/* Delete any objects that may have been created */
14472		deinit();
14473	} /* for (all test cases) */
14474
14475	/** All done */
14476	if (m_has_test_passed)
14477	{
14478		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14479	}
14480	else
14481	{
14482		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14483	}
14484
14485	return STOP;
14486}
14487
14488} /* ShaderSubroutine */
14489
14490/** Constructor.
14491 *
14492 *  @param context Rendering context.
14493 **/
14494ShaderSubroutineTests::ShaderSubroutineTests(deqp::Context& context)
14495	: TestCaseGroup(context, "shader_subroutine", "Verifies \"shader_subroutine\" functionality")
14496{
14497	/* Left blank on purpose */
14498}
14499
14500/** Initializes a texture_storage_multisample test group.
14501 *
14502 **/
14503void ShaderSubroutineTests::init(void)
14504{
14505	addChild(new ShaderSubroutine::APITest1(m_context));
14506	addChild(new ShaderSubroutine::APITest2(m_context));
14507	addChild(new ShaderSubroutine::FunctionalTest1_2(m_context));
14508	addChild(new ShaderSubroutine::FunctionalTest3_4(m_context));
14509	addChild(new ShaderSubroutine::FunctionalTest5(m_context));
14510	addChild(new ShaderSubroutine::FunctionalTest6(m_context));
14511	addChild(new ShaderSubroutine::FunctionalTest7_8(m_context));
14512	addChild(new ShaderSubroutine::FunctionalTest9(m_context));
14513	addChild(new ShaderSubroutine::FunctionalTest10(m_context));
14514	addChild(new ShaderSubroutine::FunctionalTest11(m_context));
14515	addChild(new ShaderSubroutine::FunctionalTest12(m_context));
14516	addChild(new ShaderSubroutine::FunctionalTest13(m_context));
14517	addChild(new ShaderSubroutine::FunctionalTest14_15(m_context));
14518	addChild(new ShaderSubroutine::FunctionalTest16(m_context));
14519	addChild(new ShaderSubroutine::FunctionalTest17(m_context));
14520	addChild(new ShaderSubroutine::FunctionalTest18_19(m_context));
14521	addChild(new ShaderSubroutine::FunctionalTest20_21(m_context));
14522	addChild(new ShaderSubroutine::NegativeTest1(m_context));
14523	addChild(new ShaderSubroutine::NegativeTest2(m_context));
14524	addChild(new ShaderSubroutine::NegativeTest3(m_context));
14525	addChild(new ShaderSubroutine::NegativeTest4(m_context));
14526	addChild(new ShaderSubroutine::NegativeTest5(m_context));
14527	addChild(new ShaderSubroutine::NegativeTest6(m_context));
14528	addChild(new ShaderSubroutine::NegativeTest7(m_context));
14529	addChild(new ShaderSubroutine::NegativeTest8(m_context));
14530	addChild(new ShaderSubroutine::NegativeTest9(m_context));
14531	addChild(new ShaderSubroutine::NegativeTest10(m_context));
14532	addChild(new ShaderSubroutine::NegativeTest11(m_context));
14533	addChild(new ShaderSubroutine::NegativeTest12(m_context));
14534}
14535
14536} /* glcts namespace */
14537