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	}
1323
1324	return string;
1325}
1326
1327/** Returns string that represents pname's name
1328 *
1329 * @param pname pname
1330 *
1331 * @return String representation of known pnames
1332 **/
1333const GLchar* Utils::pnameToStr(glw::GLenum pname)
1334{
1335	const GLchar* string = "Unknown pname";
1336
1337	switch (pname)
1338	{
1339	case GL_ACTIVE_SUBROUTINE_UNIFORMS:
1340		string = "GL_ACTIVE_SUBROUTINE_UNIFORMS";
1341		break;
1342	case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS:
1343		string = "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS";
1344		break;
1345	case GL_ACTIVE_SUBROUTINES:
1346		string = "GL_ACTIVE_SUBROUTINES";
1347		break;
1348	case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH:
1349		string = "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH";
1350		break;
1351	case GL_ACTIVE_SUBROUTINE_MAX_LENGTH:
1352		string = "GL_ACTIVE_SUBROUTINE_MAX_LENGTH";
1353		break;
1354	case GL_NUM_COMPATIBLE_SUBROUTINES:
1355		string = "GL_NUM_COMPATIBLE_SUBROUTINES";
1356		break;
1357	case GL_UNIFORM_SIZE:
1358		string = "GL_UNIFORM_SIZE";
1359		break;
1360	case GL_COMPATIBLE_SUBROUTINES:
1361		string = "GL_COMPATIBLE_SUBROUTINES";
1362		break;
1363	case GL_UNIFORM_NAME_LENGTH:
1364		string = "GL_UNIFORM_NAME_LENGTH";
1365		break;
1366	case GL_ACTIVE_RESOURCES:
1367		string = "GL_ACTIVE_RESOURCES";
1368		break;
1369	case GL_MAX_NAME_LENGTH:
1370		string = "GL_MAX_NAME_LENGTH";
1371		break;
1372	case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
1373		string = "GL_MAX_NUM_COMPATIBLE_SUBROUTINES";
1374		break;
1375	case GL_NAME_LENGTH:
1376		string = "GL_NAME_LENGTH";
1377		break;
1378	case GL_ARRAY_SIZE:
1379		string = "GL_ARRAY_SIZE";
1380		break;
1381	case GL_LOCATION:
1382		string = "GL_LOCATION";
1383		break;
1384	default:
1385		TCU_FAIL("Not implemented");
1386	}
1387
1388	return string;
1389}
1390
1391bool Utils::compare(const glw::GLfloat& left, const glw::GLfloat& right)
1392{
1393	static const glw::GLfloat m_epsilon = 0.00001f;
1394
1395	if (m_epsilon < std::abs(right - left))
1396	{
1397		return false;
1398	}
1399	else
1400	{
1401		return true;
1402	}
1403}
1404
1405/** Returns a variable type enum corresponding to user-specified base variable type
1406 *  and the number of components it should support.
1407 *
1408 *  @param base_variable_type Base variable type to use for the query.
1409 *  @param n_components       Number of components to consider for the query.
1410 *
1411 *  @return As per description.
1412 **/
1413Utils::_variable_type Utils::getVariableTypeFromProperties(const _variable_type& base_variable_type,
1414														   const unsigned int&   n_components)
1415{
1416	_variable_type result = VARIABLE_TYPE_UNKNOWN;
1417
1418	switch (base_variable_type)
1419	{
1420	case VARIABLE_TYPE_BOOL:
1421	{
1422		switch (n_components)
1423		{
1424		case 1:
1425			result = VARIABLE_TYPE_BOOL;
1426			break;
1427		case 2:
1428			result = VARIABLE_TYPE_BVEC2;
1429			break;
1430		case 3:
1431			result = VARIABLE_TYPE_BVEC3;
1432			break;
1433		case 4:
1434			result = VARIABLE_TYPE_BVEC4;
1435			break;
1436
1437		default:
1438		{
1439			TCU_FAIL("Unsupported number of components requested");
1440		}
1441		} /* switch (n_components) */
1442
1443		break;
1444	}
1445
1446	case VARIABLE_TYPE_DOUBLE:
1447	{
1448		switch (n_components)
1449		{
1450		case 1:
1451			result = VARIABLE_TYPE_DOUBLE;
1452			break;
1453		case 2:
1454			result = VARIABLE_TYPE_DVEC2;
1455			break;
1456		case 3:
1457			result = VARIABLE_TYPE_DVEC3;
1458			break;
1459		case 4:
1460			result = VARIABLE_TYPE_DVEC4;
1461			break;
1462
1463		default:
1464		{
1465			TCU_FAIL("Unsupported number of components requested");
1466		}
1467		} /* switch (n_components) */
1468
1469		break;
1470	}
1471
1472	case VARIABLE_TYPE_FLOAT:
1473	{
1474		switch (n_components)
1475		{
1476		case 1:
1477			result = VARIABLE_TYPE_FLOAT;
1478			break;
1479		case 2:
1480			result = VARIABLE_TYPE_VEC2;
1481			break;
1482		case 3:
1483			result = VARIABLE_TYPE_VEC3;
1484			break;
1485		case 4:
1486			result = VARIABLE_TYPE_VEC4;
1487			break;
1488
1489		default:
1490		{
1491			TCU_FAIL("Unsupported number of components requested");
1492		}
1493		} /* switch (n_components) */
1494
1495		break;
1496	}
1497
1498	case VARIABLE_TYPE_INT:
1499	{
1500		switch (n_components)
1501		{
1502		case 1:
1503			result = VARIABLE_TYPE_INT;
1504			break;
1505		case 2:
1506			result = VARIABLE_TYPE_IVEC2;
1507			break;
1508		case 3:
1509			result = VARIABLE_TYPE_IVEC3;
1510			break;
1511		case 4:
1512			result = VARIABLE_TYPE_IVEC4;
1513			break;
1514
1515		default:
1516		{
1517			TCU_FAIL("Unsupported number of components requested");
1518		}
1519		} /* switch (n_components) */
1520
1521		break;
1522	}
1523
1524	case VARIABLE_TYPE_UINT:
1525	{
1526		switch (n_components)
1527		{
1528		case 1:
1529			result = VARIABLE_TYPE_UINT;
1530			break;
1531		case 2:
1532			result = VARIABLE_TYPE_UVEC2;
1533			break;
1534		case 3:
1535			result = VARIABLE_TYPE_UVEC3;
1536			break;
1537		case 4:
1538			result = VARIABLE_TYPE_UVEC4;
1539			break;
1540
1541		default:
1542		{
1543			TCU_FAIL("Unsupported number of components requested");
1544		}
1545		} /* switch (n_components) */
1546
1547		break;
1548	}
1549
1550	default:
1551	{
1552		TCU_FAIL("Unrecognized base variable type");
1553	}
1554	} /* switch (base_variable_type) */
1555
1556	return result;
1557}
1558
1559/** Returns a GLSL literal corresponding to user-specified variable type.
1560 *
1561 *  @param variable_type Variable type to use for the query.
1562 *
1563 *  @return As per description or [?] if @param variable_type was not
1564 *          recognized.
1565 **/
1566std::string Utils::getVariableTypeGLSLString(const _variable_type& variable_type)
1567{
1568	std::string result = "[?]";
1569
1570	switch (variable_type)
1571	{
1572	case VARIABLE_TYPE_BOOL:
1573		result = "bool";
1574		break;
1575	case VARIABLE_TYPE_BVEC2:
1576		result = "bvec2";
1577		break;
1578	case VARIABLE_TYPE_BVEC3:
1579		result = "bvec3";
1580		break;
1581	case VARIABLE_TYPE_BVEC4:
1582		result = "bvec4";
1583		break;
1584	case VARIABLE_TYPE_DOUBLE:
1585		result = "double";
1586		break;
1587	case VARIABLE_TYPE_DVEC2:
1588		result = "dvec2";
1589		break;
1590	case VARIABLE_TYPE_DVEC3:
1591		result = "dvec3";
1592		break;
1593	case VARIABLE_TYPE_DVEC4:
1594		result = "dvec4";
1595		break;
1596	case VARIABLE_TYPE_FLOAT:
1597		result = "float";
1598		break;
1599	case VARIABLE_TYPE_INT:
1600		result = "int";
1601		break;
1602	case VARIABLE_TYPE_IVEC2:
1603		result = "ivec2";
1604		break;
1605	case VARIABLE_TYPE_IVEC3:
1606		result = "ivec3";
1607		break;
1608	case VARIABLE_TYPE_IVEC4:
1609		result = "ivec4";
1610		break;
1611	case VARIABLE_TYPE_MAT2:
1612		result = "mat2";
1613		break;
1614	case VARIABLE_TYPE_MAT2X3:
1615		result = "mat2x3";
1616		break;
1617	case VARIABLE_TYPE_MAT2X4:
1618		result = "mat2x4";
1619		break;
1620	case VARIABLE_TYPE_MAT3:
1621		result = "mat3";
1622		break;
1623	case VARIABLE_TYPE_MAT3X2:
1624		result = "mat3x2";
1625		break;
1626	case VARIABLE_TYPE_MAT3X4:
1627		result = "mat3x4";
1628		break;
1629	case VARIABLE_TYPE_MAT4:
1630		result = "mat4";
1631		break;
1632	case VARIABLE_TYPE_MAT4X2:
1633		result = "mat4x2";
1634		break;
1635	case VARIABLE_TYPE_MAT4X3:
1636		result = "mat4x3";
1637		break;
1638	case VARIABLE_TYPE_UINT:
1639		result = "uint";
1640		break;
1641	case VARIABLE_TYPE_UVEC2:
1642		result = "uvec2";
1643		break;
1644	case VARIABLE_TYPE_UVEC3:
1645		result = "uvec3";
1646		break;
1647	case VARIABLE_TYPE_UVEC4:
1648		result = "uvec4";
1649		break;
1650	case VARIABLE_TYPE_VEC2:
1651		result = "vec2";
1652		break;
1653	case VARIABLE_TYPE_VEC3:
1654		result = "vec3";
1655		break;
1656	case VARIABLE_TYPE_VEC4:
1657		result = "vec4";
1658		break;
1659
1660	default:
1661	{
1662		TCU_FAIL("Unrecognized variable type");
1663	}
1664	} /* switch (variable_type) */
1665
1666	return result;
1667}
1668
1669/** Constructor.
1670 *
1671 *  @param context Rendering context.
1672 *
1673 **/
1674APITest1::APITest1(deqp::Context& context)
1675	: TestCase(context, "min_maxes", "Verifies the implementation returns valid GL_MAX_SUBROUTINE* pnames "
1676									 "which meet the minimum maximum requirements enforced by the spec.")
1677	, m_has_test_passed(true)
1678{
1679	/* Left blank intentionally */
1680}
1681
1682/** Executes test iteration.
1683 *
1684 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1685 */
1686tcu::TestNode::IterateResult APITest1::iterate()
1687{
1688	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1689
1690	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
1691	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
1692	{
1693		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
1694	}
1695
1696	/* Iterate over all pnames */
1697	const struct
1698	{
1699		glw::GLenum pname;
1700		const char* pname_string;
1701		glw::GLint  min_value;
1702	} pnames[] = { { GL_MAX_SUBROUTINES, "GL_MAX_SUBROUTINES", 256 },
1703				   { GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS", 1024 } };
1704	const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
1705
1706	for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
1707	{
1708		glw::GLboolean	 bool_value   = GL_FALSE;
1709		glw::GLdouble	  double_value = 0.0;
1710		glw::GLfloat	   float_value  = 0.0f;
1711		glw::GLint		   int_value	= 0;
1712		glw::GLint64	   int64_value  = 0;
1713		const glw::GLint   min_value	= pnames[n_pname].min_value;
1714		const glw::GLenum& pname		= pnames[n_pname].pname;
1715		const char*		   pname_string = pnames[n_pname].pname_string;
1716
1717		/* Retrieve the pname values */
1718		gl.getBooleanv(pname, &bool_value);
1719		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() call failed.");
1720
1721		gl.getDoublev(pname, &double_value);
1722		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetDoublev() call failed.");
1723
1724		gl.getFloatv(pname, &float_value);
1725		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed.");
1726
1727		gl.getIntegerv(pname, &int_value);
1728		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
1729
1730		gl.getInteger64v(pname, &int64_value);
1731		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v() call failed.");
1732
1733		/* Make sure the value reported meets the min max requirement */
1734		if (int_value < min_value)
1735		{
1736			m_testCtx.getLog() << tcu::TestLog::Message << "GL implementation reports a value of [" << int_value
1737							   << "]"
1738								  " for property ["
1739							   << pname_string << "]"
1740												  ", whereas the min max for the property is ["
1741							   << min_value << "]." << tcu::TestLog::EndMessage;
1742
1743			m_has_test_passed = false;
1744		}
1745
1746		/* Verify the other getters reported valid values */
1747		const float epsilon = 1e-5f;
1748
1749		if (((int_value == 0) && (bool_value == GL_TRUE)) || ((int_value != 0) && (bool_value != GL_TRUE)))
1750		{
1751			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid boolean value [" << bool_value
1752							   << "]"
1753								  " reported for property ["
1754							   << pname_string << "]"
1755												  " (int value:["
1756							   << int_value << "])" << tcu::TestLog::EndMessage;
1757
1758			m_has_test_passed = false;
1759		}
1760
1761		if (de::abs(double_value - (double)int_value) > epsilon)
1762		{
1763			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid double value [" << double_value
1764							   << "]"
1765								  " reported for property ["
1766							   << pname_string << "]"
1767												  " (int value:["
1768							   << int_value << "])" << tcu::TestLog::EndMessage;
1769
1770			m_has_test_passed = false;
1771		}
1772
1773		if (de::abs(float_value - (float)int_value) > epsilon)
1774		{
1775			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid float value [" << float_value
1776							   << "]"
1777								  " reported for property ["
1778							   << pname_string << "]"
1779												  " (int value:["
1780							   << int_value << "])" << tcu::TestLog::EndMessage;
1781
1782			m_has_test_passed = false;
1783		}
1784
1785		if (int64_value != int_value)
1786		{
1787			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid 64-bit integer value [" << float_value
1788							   << "]"
1789								  " reported for property ["
1790							   << pname_string << "]"
1791												  " (int value:["
1792							   << int_value << "])" << tcu::TestLog::EndMessage;
1793
1794			m_has_test_passed = false;
1795		}
1796	} /* for (all pnames) */
1797
1798	if (m_has_test_passed)
1799	{
1800		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1801	}
1802	else
1803	{
1804		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1805	}
1806
1807	return STOP;
1808}
1809
1810/** Constructor.
1811 *
1812 *  @param context Rendering context.
1813 *
1814 **/
1815APITest2::APITest2(deqp::Context& context)
1816	: TestCase(context, "name_getters", "Verifies glGetActiveSubroutineName() and glGetActiveSubroutineUniformName() "
1817										"functions work correctly.")
1818	, m_buffer(DE_NULL)
1819	, m_has_test_passed(true)
1820	, m_po_id(0)
1821	, m_subroutine_name1("subroutine1")
1822	, m_subroutine_name2("subroutine2")
1823	, m_subroutine_uniform_name("data_provider")
1824	, m_vs_id(0)
1825{
1826	/* Left blank intentionally */
1827}
1828
1829/** Destroys all ES objects that may have been created during test initialization,
1830 *  as well as releases any buffers that may have been allocated during the process.
1831 */
1832void APITest2::deinit()
1833{
1834	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1835
1836	if (m_buffer != DE_NULL)
1837	{
1838		delete[] m_buffer;
1839
1840		m_buffer = DE_NULL;
1841	}
1842
1843	if (m_po_id != 0)
1844	{
1845		gl.deleteProgram(m_po_id);
1846
1847		m_po_id = 0;
1848	}
1849
1850	if (m_vs_id != 0)
1851	{
1852		gl.deleteShader(m_vs_id);
1853
1854		m_vs_id = 0;
1855	}
1856}
1857
1858/** Returns body of a vertex shader that should be used for the test.
1859 *
1860 *  @return As per description.
1861 **/
1862std::string APITest2::getVertexShaderBody()
1863{
1864	return "#version 400\n"
1865		   "\n"
1866		   "#extension GL_ARB_shader_subroutine : require\n"
1867		   "\n"
1868		   "subroutine int ExampleSubroutineType(int example_argument);\n"
1869		   "\n"
1870		   "subroutine(ExampleSubroutineType) int subroutine1(int example_argument)\n"
1871		   "{\n"
1872		   "    return 1;\n"
1873		   "}\n"
1874		   "\n"
1875		   "subroutine(ExampleSubroutineType) int subroutine2(int example_argument)\n"
1876		   "{\n"
1877		   "    return 2;\n"
1878		   "}\n"
1879		   "\n"
1880		   "subroutine uniform ExampleSubroutineType data_provider;\n"
1881		   "\n"
1882		   "void main()\n"
1883		   "{\n"
1884		   "    gl_Position = vec4(float(data_provider(0)), vec3(1) );\n"
1885		   "}\n";
1886}
1887
1888/** Initializes all ES objects required to run the test. */
1889void APITest2::initTest()
1890{
1891	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1892
1893	/* Generate program & shader objects */
1894	m_po_id = gl.createProgram();
1895	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1896
1897	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call(s) failed.");
1898
1899	/* Attach the shader to the program object */
1900	gl.attachShader(m_po_id, m_vs_id);
1901	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
1902
1903	/* Compile the shader */
1904	glw::GLint  compile_status  = GL_FALSE;
1905	std::string vs_body			= getVertexShaderBody();
1906	const char* vs_body_raw_ptr = vs_body.c_str();
1907
1908	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
1909	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1910
1911	gl.compileShader(m_vs_id);
1912	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1913
1914	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1915	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1916
1917	if (compile_status != GL_TRUE)
1918	{
1919		TCU_FAIL("Shader compilation failed.");
1920	}
1921
1922	/* Try to link the program object */
1923	glw::GLint link_status = GL_FALSE;
1924
1925	gl.linkProgram(m_po_id);
1926	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1927
1928	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1929	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
1930
1931	if (link_status != GL_TRUE)
1932	{
1933		TCU_FAIL("Program linking failed.");
1934	}
1935
1936	/* Perform a few quick checks */
1937	glw::GLint n_active_subroutines			= 0;
1938	glw::GLint n_active_subroutine_uniforms = 0;
1939
1940	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
1941	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
1942	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call failed.");
1943
1944	if (n_active_subroutines != 2 /* subroutines declared in vertex shader */)
1945	{
1946		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid amount of active subroutines reported; expected: 2,"
1947													   " reported:"
1948						   << n_active_subroutines << tcu::TestLog::EndMessage;
1949
1950		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINES property value.");
1951	}
1952
1953	if (n_active_subroutine_uniforms != 1)
1954	{
1955		m_testCtx.getLog() << tcu::TestLog::Message
1956						   << "Invalid amount of active subroutine uniforms reported: expected: 1,"
1957							  " reported: "
1958						   << n_active_subroutine_uniforms << tcu::TestLog::EndMessage;
1959
1960		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORMS property value.");
1961	}
1962}
1963
1964/** Executes test iteration.
1965 *
1966 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1967 */
1968tcu::TestNode::IterateResult APITest2::iterate()
1969{
1970	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
1971	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
1972	{
1973		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
1974	}
1975
1976	/* Initialize a test program object */
1977	initTest();
1978
1979	/* Verify glGetActiveSubroutineName() works correctly */
1980	verifyGLGetActiveSubroutineNameFunctionality();
1981
1982	/* Verify glGetActiveSubroutineUniformName() works correctly */
1983	verifyGLGetActiveSubroutineUniformNameFunctionality();
1984
1985	/* Done */
1986	if (m_has_test_passed)
1987	{
1988		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1989	}
1990	else
1991	{
1992		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1993	}
1994
1995	return STOP;
1996}
1997
1998/** Verifies glGetActiveSubroutineName() behaves as per GL_ARB_shader_subroutine
1999 *  specification.
2000 **/
2001void APITest2::verifyGLGetActiveSubroutineNameFunctionality()
2002{
2003	GLsizei				  expected_length1 = (GLsizei)strlen(m_subroutine_name1) + 1;
2004	GLsizei				  expected_length2 = (GLsizei)strlen(m_subroutine_name1) + 1;
2005	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
2006	GLsizei				  reported_length  = 0;
2007
2008	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2009							   0,							 /* bufsize */
2010							   DE_NULL,						 /* length */
2011							   DE_NULL);					 /* name */
2012	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2013
2014	gl.getProgramInterfaceiv(m_po_id, GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, &reported_length);
2015	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2016
2017	if ((reported_length != expected_length1) && (reported_length != expected_length2))
2018	{
2019		m_testCtx.getLog() << tcu::TestLog::Message
2020						   << "Invalid active subroutine name length reported:" << reported_length
2021						   << ", instead of: " << expected_length1 << " or " << expected_length2
2022						   << tcu::TestLog::EndMessage;
2023
2024		TCU_FAIL("Incorrect length of active subroutine name");
2025	}
2026
2027	m_buffer = new glw::GLchar[reported_length];
2028
2029	memset(m_buffer, 0, reported_length);
2030
2031	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, reported_length, DE_NULL, /* length */
2032							   m_buffer);
2033	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2034
2035	if (strcmp(m_buffer, m_subroutine_name1) != 0 && strcmp(m_buffer, m_subroutine_name2) != 0)
2036	{
2037		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine name reported:[" << m_buffer
2038						   << "]"
2039							  " instead of:["
2040						   << m_subroutine_name1 << "]"
2041													" or:["
2042						   << m_subroutine_name2 << "]." << tcu::TestLog::EndMessage;
2043
2044		TCU_FAIL("Invalid active subroutine name reported.");
2045	}
2046
2047	delete[] m_buffer;
2048	m_buffer = DE_NULL;
2049}
2050
2051/** Verifies glGetActiveSubroutineUniformName() behaves as per GL_ARB_shader_subroutine
2052 *  specification.
2053 **/
2054void APITest2::verifyGLGetActiveSubroutineUniformNameFunctionality()
2055{
2056	GLsizei				  expected_length = (GLsizei)strlen(m_subroutine_uniform_name);
2057	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
2058	GLsizei				  reported_length = 0;
2059
2060	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2061									  0,							/* bufsize */
2062									  DE_NULL,						/* length */
2063									  DE_NULL);						/* name */
2064	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed.");
2065
2066	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2067									  0,							/* bufsize */
2068									  &reported_length, DE_NULL);   /* name */
2069	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed.");
2070
2071	// reported_length is the actual number of characters written into <name>
2072	// If <bufSize> is 0, reported_length should be 0
2073	if (reported_length != 0)
2074	{
2075		m_testCtx.getLog() << tcu::TestLog::Message
2076						   << "Invalid active subroutine uniform name length reported:" << reported_length
2077						   << ", instead of: " << 0 << tcu::TestLog::EndMessage;
2078
2079		TCU_FAIL("Incorrect length of active subroutine uniform name");
2080	}
2081
2082	m_buffer = new glw::GLchar[expected_length + 1];
2083
2084	memset(m_buffer, 0, expected_length + 1);
2085
2086	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, expected_length + 1, &reported_length, m_buffer);
2087	GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformName() call failed.");
2088
2089	if (reported_length != expected_length)
2090	{
2091		m_testCtx.getLog() << tcu::TestLog::Message
2092						   << "Invalid active subroutine uniform name length reported:" << reported_length
2093						   << ", instead of: " << expected_length << tcu::TestLog::EndMessage;
2094
2095		TCU_FAIL("Incorrect length of active subroutine uniform name");
2096	}
2097
2098	if (strcmp(m_buffer, m_subroutine_uniform_name) != 0)
2099	{
2100		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine uniform name reported:[" << m_buffer
2101						   << "]"
2102							  " instead of:["
2103						   << m_subroutine_uniform_name << "]" << tcu::TestLog::EndMessage;
2104
2105		TCU_FAIL("Invalid active subroutine uniform name reported.");
2106	}
2107
2108	delete[] m_buffer;
2109	m_buffer = DE_NULL;
2110}
2111
2112/** Constructor.
2113 *
2114 *  @param context Rendering context.
2115 *
2116 **/
2117FunctionalTest1_2::FunctionalTest1_2(deqp::Context& context)
2118	: TestCase(context, "two_subroutines_single_subroutine_uniform",
2119			   "Verifies the subroutines work correctly in a vertex shader for"
2120			   " bool/float/int/uint/double/*vec*/*mat* argument and return types")
2121	, m_has_test_passed(true)
2122	, m_po_id(0)
2123	, m_po_getter0_subroutine_index(GL_INVALID_INDEX)
2124	, m_po_getter1_subroutine_index(GL_INVALID_INDEX)
2125	, m_po_subroutine_uniform_index(-1)
2126	, m_xfb_bo_id(0)
2127	, m_vao_id(0)
2128	, m_vs_id(0)
2129{
2130	/* Left blank intentionally */
2131}
2132
2133/** Destroys all ES objects that may have been created during test initialization,
2134 *  as well as releases any buffers that may have been allocated during the process.
2135 */
2136void FunctionalTest1_2::deinit()
2137{
2138	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2139
2140	deinitTestIteration();
2141
2142	if (m_xfb_bo_id != 0)
2143	{
2144		gl.deleteBuffers(1, &m_xfb_bo_id);
2145
2146		m_xfb_bo_id = 0;
2147	}
2148
2149	if (m_vao_id != 0)
2150	{
2151		gl.deleteVertexArrays(1, &m_vao_id);
2152
2153		m_vao_id = 0;
2154	}
2155}
2156
2157/** Deinitializes GL objects that are iteration-specific */
2158void FunctionalTest1_2::deinitTestIteration()
2159{
2160	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2161
2162	if (m_po_id != 0)
2163	{
2164		gl.deleteProgram(m_po_id);
2165
2166		m_po_id = 0;
2167	}
2168
2169	if (m_vs_id != 0)
2170	{
2171		gl.deleteShader(m_vs_id);
2172
2173		m_vs_id = 0;
2174	}
2175}
2176
2177/** Executes a single test iteration using user-specified test case propertiesz.
2178 *
2179 *  @param test-case Test case descriptor.
2180 *
2181 *  @return true if the test iteration passed, false otherwise.
2182 **/
2183bool FunctionalTest1_2::executeTestIteration(const _test_case& test_case)
2184{
2185	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2186	bool				  result = true;
2187
2188	/* Build the test program */
2189	std::string		   empty_body;
2190	std::string		   vs_body		  = getVertexShaderBody(test_case.variable_type, test_case.array_size);
2191	const glw::GLchar* xfb_varyings[] = { "result" };
2192	const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
2193
2194	if (!Utils::buildProgram(gl, vs_body, empty_body, empty_body, empty_body, empty_body, xfb_varyings, n_xfb_varyings,
2195							 &m_vs_id, NULL, /* out_tc_id */
2196							 NULL,			 /* out_te_id */
2197							 NULL,			 /* out_gs_id */
2198							 NULL, &m_po_id))
2199	{
2200		TCU_FAIL("Test program failed to build.");
2201	}
2202
2203	/* Retrieve subroutine locations */
2204	m_po_getter0_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter0");
2205	m_po_getter1_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter1");
2206
2207	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
2208
2209	if (m_po_getter0_subroutine_index == GL_INVALID_INDEX || m_po_getter1_subroutine_index == GL_INVALID_INDEX)
2210	{
2211		TCU_FAIL("At least one subroutine is considered inactive which is invalid.");
2212	}
2213
2214	/* Retrieve subroutine uniform location */
2215	m_po_subroutine_uniform_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "colorGetterUniform");
2216
2217	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call failed.");
2218
2219	if (m_po_subroutine_uniform_index == -1)
2220	{
2221		TCU_FAIL("Subroutine uniform is considered inactive which is invalid.");
2222	}
2223
2224	/* Set up XFB BO storage */
2225	const Utils::_variable_type base_variable_type	= Utils::getBaseVariableType(test_case.variable_type);
2226	unsigned int				iteration_xfb_bo_size = Utils::getComponentSizeForVariableType(base_variable_type) *
2227										 Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
2228	unsigned int total_xfb_bo_size = 0;
2229
2230	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2231	{
2232		/* Boolean varyings are not supported by OpenGL. Instead, we use ints to output
2233		 * boolean values. */
2234		iteration_xfb_bo_size = static_cast<unsigned int>(iteration_xfb_bo_size * sizeof(int));
2235	}
2236
2237	total_xfb_bo_size = iteration_xfb_bo_size * 2 /* subroutines we will be testing */;
2238
2239	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, total_xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
2240	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2241
2242	/* Activate test program object */
2243	gl.useProgram(m_po_id);
2244	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2245
2246	/* Run two iterations. Each iteration should invoke different subroutine. */
2247	const glw::GLuint  subroutine_indices[] = { m_po_getter0_subroutine_index, m_po_getter1_subroutine_index };
2248	const unsigned int n_subroutine_indices = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
2249
2250	for (unsigned int n_subroutine_index = 0; n_subroutine_index < n_subroutine_indices; ++n_subroutine_index)
2251	{
2252		/* Configure which subroutine should be used for the draw call */
2253		glw::GLuint current_subroutine_index = subroutine_indices[n_subroutine_index];
2254
2255		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &current_subroutine_index);
2256		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
2257
2258		/* Update XFB binding so that we do not overwrite data XFBed in previous iterations */
2259		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2260						   m_xfb_bo_id, iteration_xfb_bo_size * n_subroutine_index, iteration_xfb_bo_size);
2261		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() call failed.");
2262
2263		/* Draw a single point */
2264		gl.beginTransformFeedback(GL_POINTS);
2265		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2266		{
2267			gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2268			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
2269		}
2270		gl.endTransformFeedback();
2271		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
2272	} /* for (all subroutine indices) */
2273
2274	/* Map the BO storage into process space */
2275	const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2276	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
2277
2278	result &= verifyXFBData(xfb_data_ptr, test_case.variable_type);
2279
2280	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2281	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffeR() call failed.");
2282
2283	return result;
2284}
2285
2286/** Retrieves body of a vertex shader that should be used to verify
2287 *  subroutine support, given user-specified test iteration properties.
2288 *
2289 *  @param variable_type GLSL type that should be used for argument and
2290 *                       return type definition in a subroutine. This setting
2291 *                       also affects type of the only output variable in the shader.
2292 *  @param array_size    1 if non-arrayed arguments/return types should be tested;
2293 *                       2 if arrayed arguments/return types should be tested.
2294 *
2295 *  @return Requested string.
2296 **/
2297std::string FunctionalTest1_2::getVertexShaderBody(const Utils::_variable_type& variable_type, unsigned int array_size)
2298{
2299	Utils::_variable_type base_variable_type		 = Utils::getBaseVariableType(variable_type);
2300	unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
2301	std::stringstream	 result_sstream;
2302	std::string			  variable_type_glsl = Utils::getVariableTypeGLSLString(variable_type);
2303	std::stringstream	 variable_type_glsl_array_sstream;
2304	std::stringstream	 variable_type_glsl_arrayed_sstream;
2305
2306	variable_type_glsl_arrayed_sstream << variable_type_glsl;
2307
2308	if (array_size > 1)
2309	{
2310		variable_type_glsl_array_sstream << "[" << array_size << "]";
2311		variable_type_glsl_arrayed_sstream << variable_type_glsl_array_sstream.str();
2312	}
2313
2314	/* Form pre-amble */
2315	result_sstream << "#version 400\n"
2316					  "\n"
2317					  "#extension GL_ARB_shader_subroutine : require\n";
2318
2319	if (variable_type == Utils::VARIABLE_TYPE_DOUBLE)
2320	{
2321		result_sstream << "#extension GL_ARB_gpu_shader_fp64 : require\n";
2322	}
2323
2324	/* Form subroutine type declaration */
2325	result_sstream << "\n"
2326					  "subroutine "
2327				   << variable_type_glsl_arrayed_sstream.str() << " colorGetter(in " << variable_type_glsl
2328				   << " in_value" << variable_type_glsl_array_sstream.str() << ");\n"
2329																			   "\n";
2330
2331	/* Declare getter functions */
2332	for (int n_getter = 0; n_getter < 2; ++n_getter)
2333	{
2334		result_sstream << "subroutine(colorGetter) " << variable_type_glsl_arrayed_sstream.str() << " getter"
2335					   << n_getter << "(in " << variable_type_glsl << " in_value"
2336					   << variable_type_glsl_array_sstream.str() << ")\n"
2337																	"{\n";
2338
2339		if (array_size > 1)
2340		{
2341			result_sstream << variable_type_glsl << " temp" << variable_type_glsl_array_sstream.str() << ";\n";
2342		}
2343
2344		if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2345		{
2346			if (array_size > 1)
2347			{
2348				for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2349				{
2350					result_sstream << "    temp[" << array_index << "]"
2351																	" = "
2352								   << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "")
2353								   << "(in_value[" << array_index << "]);\n";
2354				}
2355
2356				result_sstream << "    return temp;\n";
2357			}
2358			else
2359			{
2360				result_sstream << "    return "
2361							   << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "")
2362							   << "(in_value);\n";
2363			}
2364		} /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */
2365		else
2366		{
2367			if (array_size > 1)
2368			{
2369				for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2370				{
2371					result_sstream << "    temp[" << array_index << "]"
2372																	" = in_value["
2373								   << array_index << "] + " << (n_getter + 1) << ";\n";
2374				}
2375
2376				result_sstream << "    return temp;\n";
2377			}
2378			else
2379			{
2380				result_sstream << "    return (in_value + " << (n_getter + 1) << ");\n";
2381			}
2382		}
2383
2384		result_sstream << "}\n";
2385	} /* for (both getter functions) */
2386
2387	/* Declare subroutine uniform */
2388	result_sstream << "subroutine uniform colorGetter colorGetterUniform;\n"
2389					  "\n";
2390
2391	/* Declare output variable */
2392	result_sstream << "out ";
2393
2394	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2395	{
2396		Utils::_variable_type result_as_int_variable_type =
2397			Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components);
2398		std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type);
2399
2400		result_sstream << variable_type_glsl_as_int;
2401	}
2402	else
2403	{
2404		result_sstream << variable_type_glsl;
2405	}
2406
2407	result_sstream << " result;\n"
2408					  "\n";
2409
2410	/* Declare main(): prepare input argument for the subroutine function */
2411	result_sstream << "void main()\n"
2412					  "{\n"
2413					  "    "
2414				   << variable_type_glsl << " temp";
2415
2416	if (array_size > 1)
2417	{
2418		result_sstream << "[" << array_size << "]";
2419	}
2420
2421	result_sstream << ";\n";
2422
2423	for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2424	{
2425		result_sstream << "    temp";
2426
2427		if (array_size > 1)
2428		{
2429			result_sstream << "[" << array_index << "]";
2430		}
2431
2432		result_sstream << " = " << variable_type_glsl << "(";
2433
2434		if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2435		{
2436			result_sstream << "true";
2437		}
2438		else
2439		{
2440			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2441			{
2442				result_sstream << "3";
2443
2444				if (n_component != (n_variable_type_components - 1))
2445				{
2446					result_sstream << ", ";
2447				}
2448			} /* for (all components) */
2449		}
2450
2451		result_sstream << ");\n";
2452	} /* for (all array indices) */
2453
2454	/* Declare main(): call the subroutine. Verify the input and write the result
2455	 *                 to the output variable.
2456	 **/
2457	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2458	{
2459		Utils::_variable_type result_as_int_variable_type =
2460			Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components);
2461		std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type);
2462
2463		result_sstream << variable_type_glsl_arrayed_sstream.str() << " subroutine_result = colorGetterUniform(temp);\n"
2464																	  "result = ";
2465
2466		for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2467		{
2468			if (variable_type_glsl == "bool")
2469				result_sstream << "bool(subroutine_result";
2470			else
2471				result_sstream << "all(subroutine_result";
2472
2473			if (array_size > 1)
2474			{
2475				result_sstream << "[" << array_index << "]";
2476			}
2477
2478			result_sstream << ")";
2479
2480			if (array_index != (array_size - 1))
2481			{
2482				result_sstream << "&& ";
2483			}
2484		}
2485
2486		result_sstream << " == true ? " << variable_type_glsl_as_int << "(1) : " << variable_type_glsl_as_int << "(0);";
2487	}
2488	else
2489	{
2490		if (array_size > 1)
2491		{
2492			DE_ASSERT(array_size == 2);
2493
2494			result_sstream << variable_type_glsl << " subroutine_result" << variable_type_glsl_array_sstream.str()
2495						   << " = colorGetterUniform(temp);\n"
2496							  "\n"
2497							  "if (subroutine_result[0] == subroutine_result[1]) result = subroutine_result[0];\n"
2498							  "else\n"
2499							  "result = "
2500						   << variable_type_glsl << "(-1);\n";
2501		}
2502		else
2503		{
2504			result_sstream << "result = colorGetterUniform(temp);\n";
2505		}
2506	}
2507
2508	/* All done */
2509	result_sstream << "}\n";
2510
2511	return result_sstream.str();
2512}
2513
2514/** Initializes all GL objects required to run the test. */
2515void FunctionalTest1_2::initTest()
2516{
2517	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2518
2519	/* Generate buffer object to hold result XFB data */
2520	gl.genBuffers(1, &m_xfb_bo_id);
2521	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2522
2523	/* Set up XFB BO bindings */
2524	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
2525	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2526
2527	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
2528	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
2529
2530	/* Generate VAO to use for the draw calls */
2531	gl.genVertexArrays(1, &m_vao_id);
2532	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2533
2534	gl.bindVertexArray(m_vao_id);
2535	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2536}
2537
2538/** Executes test iteration.
2539 *
2540 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2541 */
2542tcu::TestNode::IterateResult FunctionalTest1_2::iterate()
2543{
2544	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
2545	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
2546	{
2547		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
2548	}
2549
2550	/* Initialize a test program object */
2551	initTest();
2552
2553	/* Construct test case descriptors: first, iIerate over all
2554	 * variable types we want to cover */
2555	const Utils::_variable_type variable_types[] = {
2556		Utils::VARIABLE_TYPE_BOOL,   Utils::VARIABLE_TYPE_BVEC2,  Utils::VARIABLE_TYPE_BVEC3,
2557		Utils::VARIABLE_TYPE_BVEC4,  Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT,
2558		Utils::VARIABLE_TYPE_INT,	Utils::VARIABLE_TYPE_IVEC2,  Utils::VARIABLE_TYPE_IVEC3,
2559		Utils::VARIABLE_TYPE_IVEC4,  Utils::VARIABLE_TYPE_MAT2,   Utils::VARIABLE_TYPE_MAT2X3,
2560		Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_MAT3,   Utils::VARIABLE_TYPE_MAT3X2,
2561		Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_MAT4,   Utils::VARIABLE_TYPE_MAT4X2,
2562		Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_UINT,   Utils::VARIABLE_TYPE_UVEC2,
2563		Utils::VARIABLE_TYPE_UVEC3,  Utils::VARIABLE_TYPE_UVEC4,  Utils::VARIABLE_TYPE_VEC2,
2564		Utils::VARIABLE_TYPE_VEC3,   Utils::VARIABLE_TYPE_VEC4
2565	};
2566	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
2567
2568	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
2569	{
2570		Utils::_variable_type current_variable_type = variable_types[n_variable_type];
2571
2572		/* We need to test both arrayed and non-arrayed arguments */
2573		for (unsigned int array_size = 1; array_size < 3; ++array_size)
2574		{
2575			/* Exclude double variables if the relevant extension is unavailable */
2576			if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64") &&
2577				current_variable_type == Utils::VARIABLE_TYPE_DOUBLE)
2578			{
2579				continue;
2580			}
2581
2582			/* Form the descriptor */
2583			_test_case test_case;
2584
2585			test_case.array_size	= array_size;
2586			test_case.variable_type = current_variable_type;
2587
2588			/* Store the test case descriptor */
2589			m_test_cases.push_back(test_case);
2590		} /* for (both arrayed and non-arrayed arguments) */
2591	}	 /* for (all variable types) */
2592
2593	/* Iterate over all test cases and execute the test */
2594	for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
2595		 ++test_case_iterator)
2596	{
2597		const _test_case& test_case = *test_case_iterator;
2598
2599		m_has_test_passed &= executeTestIteration(test_case);
2600
2601		/* Release GL objects that were created during the execution */
2602		deinitTestIteration();
2603	} /* for (all test cases) */
2604
2605	/* Done */
2606	if (m_has_test_passed)
2607	{
2608		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2609	}
2610	else
2611	{
2612		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2613	}
2614
2615	return STOP;
2616}
2617
2618/** Verifies data that has been XFBed out by the vertex shader.
2619 *
2620 *  @param xfb_data      Buffer holding the data.
2621 *  @param variable_type GLSL type used for the test iteration
2622 *                       that generated the data at @param xfb_data.
2623 *
2624 *  @return true if the data was found to be valid, false if it
2625 *               was detected to be incorrect.
2626 **/
2627bool FunctionalTest1_2::verifyXFBData(const void* xfb_data, const Utils::_variable_type& variable_type)
2628{
2629	const Utils::_variable_type base_variable_type		   = Utils::getBaseVariableType(variable_type);
2630	const float					epsilon					   = 1e-5f;
2631	const unsigned int			n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
2632	bool						result					   = true;
2633	const unsigned char*		traveller_ptr			   = (const unsigned char*)xfb_data;
2634
2635	/* Boolean arguments/return types are tested with a slightly different shader so we
2636	 * need to test them in a separate code-path.
2637	 */
2638	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2639	{
2640		/* 0 should be returned when getter0 is used, 1 otherwise */
2641		const unsigned int ref_values[] = { 0, 1 };
2642		const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]);
2643
2644		for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value)
2645		{
2646			const unsigned int ref_value = ref_values[n_ref_value];
2647
2648			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2649			{
2650				int* result_value_ptr = (int*)(traveller_ptr);
2651
2652				if (*result_value_ptr != (int)ref_value)
2653				{
2654					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2655																   "["
2656									   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2657									   << " argument/return types ("
2658										  "expected:["
2659									   << ref_value << "], found:[" << *result_value_ptr << "])"
2660									   << tcu::TestLog::EndMessage;
2661
2662					result = false;
2663					break;
2664				}
2665
2666				traveller_ptr += sizeof(int);
2667			} /* for (all components) */
2668		}	 /* for (all reference values) */
2669	}		  /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */
2670	else
2671	{
2672		/* 4 should be returned when getter0 is used, 5 otherwise */
2673		const unsigned int ref_values[] = { 4, 5 };
2674		const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]);
2675
2676		for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value)
2677		{
2678			const unsigned int ref_value = ref_values[n_ref_value];
2679
2680			DE_ASSERT(
2681				base_variable_type == Utils::VARIABLE_TYPE_DOUBLE || base_variable_type == Utils::VARIABLE_TYPE_FLOAT ||
2682				base_variable_type == Utils::VARIABLE_TYPE_INT || base_variable_type == Utils::VARIABLE_TYPE_UINT);
2683
2684			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2685			{
2686				const double* double_value_ptr = (double*)traveller_ptr;
2687				const float*  float_value_ptr  = (float*)traveller_ptr;
2688				const int*	int_value_ptr	= (int*)traveller_ptr;
2689
2690				switch (base_variable_type)
2691				{
2692				case Utils::VARIABLE_TYPE_DOUBLE:
2693				{
2694					if (de::abs(*double_value_ptr - (double)ref_value) > epsilon)
2695					{
2696						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2697																	   "["
2698										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2699										   << " argument/return types ("
2700											  "expected:["
2701										   << ref_value << "], found:[" << *double_value_ptr << "])"
2702										   << tcu::TestLog::EndMessage;
2703
2704						result = false;
2705					}
2706
2707					traveller_ptr += sizeof(double);
2708					break;
2709				}
2710
2711				case Utils::VARIABLE_TYPE_FLOAT:
2712				{
2713					if (de::abs(*float_value_ptr - (float)ref_value) > epsilon)
2714					{
2715						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2716																	   "["
2717										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2718										   << " argument/return types ("
2719											  "expected:["
2720										   << ref_value << "], found:[" << *float_value_ptr << "])"
2721										   << tcu::TestLog::EndMessage;
2722
2723						result = false;
2724					}
2725
2726					traveller_ptr += sizeof(float);
2727					break;
2728				}
2729
2730				case Utils::VARIABLE_TYPE_INT:
2731				case Utils::VARIABLE_TYPE_UINT:
2732				{
2733					if (*int_value_ptr != (int)ref_value)
2734					{
2735						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2736																	   "["
2737										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2738										   << " argument/return types ("
2739											  "expected:["
2740										   << ref_value << "], found:[" << *int_value_ptr << "])"
2741										   << tcu::TestLog::EndMessage;
2742
2743						result = false;
2744					}
2745
2746					traveller_ptr += sizeof(int);
2747					break;
2748				}
2749
2750				default:
2751					break;
2752				} /* switch (base_variable_type) */
2753			}	 /* for (all components) */
2754		}		  /* for (all reference values) */
2755	}
2756
2757	return result;
2758}
2759
2760/** Constructor
2761 *
2762 * @param context CTS context
2763 **/
2764FunctionalTest3_4::FunctionalTest3_4(deqp::Context& context)
2765	: TestCase(context, "four_subroutines_with_two_uniforms", "Verify Get* API and draw calls")
2766	, m_n_active_subroutine_uniforms(0)
2767	, m_n_active_subroutine_uniform_locations(0)
2768	, m_n_active_subroutines(0)
2769	, m_n_active_subroutine_uniform_name_length(0)
2770	, m_n_active_subroutine_name_length(0)
2771	, m_n_active_subroutine_uniform_size(0)
2772{
2773	/* Nothing to be done here */
2774}
2775
2776/** Execute test
2777 *
2778 * @return tcu::TestNode::STOP
2779 **/
2780tcu::TestNode::IterateResult FunctionalTest3_4::iterate()
2781{
2782	static const glw::GLchar* vertex_shader_code =
2783		"#version 400 core\n"
2784		"#extension GL_ARB_shader_subroutine : require\n"
2785		"\n"
2786		"precision highp float;\n"
2787		"\n"
2788		"// Sub routine type declaration\n"
2789		"subroutine vec4 routine_type(in vec4 iparam);\n"
2790		"\n"
2791		"// Sub routine definitions\n"
2792		"subroutine(routine_type) vec4 inverse_order(in vec4 iparam)\n"
2793		"{\n"
2794		"    return iparam.wzyx;\n"
2795		"}\n"
2796		"\n"
2797		"subroutine(routine_type) vec4 negate(in vec4 iparam)\n"
2798		"{\n"
2799		"    return -iparam;\n"
2800		"}\n"
2801		"\n"
2802		"subroutine(routine_type) vec4 inverse(in vec4 iparam)\n"
2803		"{\n"
2804		"    return 1 / iparam;\n"
2805		"}\n"
2806		"\n"
2807		"subroutine(routine_type) vec4 square(in vec4 iparam)\n"
2808		"{\n"
2809		"    return iparam * iparam;\n"
2810		"}\n"
2811		"\n"
2812		"// Sub routine uniforms\n"
2813		"subroutine uniform routine_type first_routine;\n"
2814		"subroutine uniform routine_type second_routine;\n"
2815		"\n"
2816		"// Input data\n"
2817		"uniform vec4 input_data;\n"
2818		"\n"
2819		"// Output\n"
2820		"out vec4 out_input_data;\n"
2821		"out vec4 out_result_from_first_routine;\n"
2822		"out vec4 out_result_from_second_routine;\n"
2823		"out vec4 out_result_from_combined_routines;\n"
2824		"out vec4 out_result_from_routines_combined_in_reveresed_order;\n"
2825		"\n"
2826		"void main()\n"
2827		"{\n"
2828		"    out_input_data                                       = input_data;\n"
2829		"    out_result_from_first_routine                        = first_routine(input_data);\n"
2830		"    out_result_from_second_routine                       = second_routine(input_data);\n"
2831		"    out_result_from_combined_routines                    = second_routine(first_routine(input_data));\n"
2832		"    out_result_from_routines_combined_in_reveresed_order = first_routine(second_routine(input_data));\n"
2833		"}\n"
2834		"\n";
2835
2836	static const GLchar* varying_names[] = {
2837		"out_input_data",
2838		"out_result_from_first_routine",
2839		"out_result_from_second_routine",
2840		"out_result_from_combined_routines",
2841		"out_result_from_routines_combined_in_reveresed_order",
2842	};
2843
2844	static const GLchar* subroutine_uniform_names[] = { "first_routine", "second_routine" };
2845
2846	static const GLchar* subroutine_names[] = { "inverse_order", "negate", "inverse", "square" };
2847
2848	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
2849	static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */;
2850
2851	static const GLuint inverse_order_routine_index = 0;
2852	static const GLuint negate_routine_index		= 1;
2853	static const GLuint inverse_routine_index		= 2;
2854	static const GLuint square_routine_index		= 3;
2855
2856	/* Test data */
2857	static const Utils::vec4<GLfloat> inverse_order_negate_data[5] = {
2858		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2859		Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),
2860		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),
2861	};
2862
2863	static const Utils::vec4<GLfloat> inverse_order_inverse_data[5] = {
2864		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2865		Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2866		Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2867	};
2868
2869	static const Utils::vec4<GLfloat> inverse_order_square_data[5] = {
2870		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2871		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),   Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2872		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2873	};
2874
2875	static const Utils::vec4<GLfloat> negate_inverse_data[5] = {
2876		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2877		Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2878		Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2879	};
2880
2881	static const Utils::vec4<GLfloat> negate_square_data[5] = {
2882		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),   Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2883		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),	 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2884		Utils::vec4<GLfloat>(-4.0f, -1.0f, -1.0f, -4.0f),
2885	};
2886
2887	static const Utils::vec4<GLfloat> inverse_square_data[5] = {
2888		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f),
2889		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),   Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f),
2890		Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f),
2891	};
2892
2893	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
2894	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
2895	{
2896		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
2897	}
2898
2899	m_n_active_subroutine_uniforms			  = 2;
2900	m_n_active_subroutine_uniform_locations   = 2;
2901	m_n_active_subroutines					  = 4;
2902	m_n_active_subroutine_uniform_name_length = 0;
2903	m_n_active_subroutine_name_length		  = 0;
2904	m_n_active_subroutine_uniform_size		  = 1;
2905
2906	/* GL objects */
2907	Utils::program	 program(m_context);
2908	Utils::buffer	  transform_feedback_buffer(m_context);
2909	Utils::vertexArray vao(m_context);
2910
2911	bool result = true;
2912
2913	/* Calculate max name lengths for subroutines and subroutine uniforms */
2914	for (GLint i = 0; i < m_n_active_subroutine_uniforms; ++i)
2915	{
2916		const GLsizei length = (GLsizei)strlen(subroutine_uniform_names[i]);
2917
2918		if (length > m_n_active_subroutine_uniform_name_length)
2919		{
2920			m_n_active_subroutine_uniform_name_length = length;
2921		}
2922	}
2923
2924	for (GLint i = 0; i < m_n_active_subroutines; ++i)
2925	{
2926		const GLsizei length = (GLsizei)strlen(subroutine_names[i]);
2927
2928		if (length > m_n_active_subroutine_name_length)
2929		{
2930			m_n_active_subroutine_name_length = length;
2931		}
2932	}
2933
2934	/* Init */
2935	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
2936				  n_varyings);
2937
2938	vao.generate();
2939	vao.bind();
2940
2941	transform_feedback_buffer.generate();
2942	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
2943									 GL_DYNAMIC_COPY);
2944	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
2945
2946	program.use();
2947
2948	/* Inspect Get* API */
2949	if ((false == inspectProgramStageiv(program.m_program_object_id)) ||
2950		(false == inspectActiveSubroutineUniformiv(program.m_program_object_id, subroutine_uniform_names)) ||
2951		(false == inspectActiveSubroutineUniformName(program.m_program_object_id, subroutine_uniform_names)) ||
2952		(false == inspectActiveSubroutineName(program.m_program_object_id, subroutine_names)) ||
2953		(false ==
2954		 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, false)))
2955	{
2956		result = false;
2957	}
2958
2959	/* Inspect GetProgram* API */
2960	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
2961	{
2962		if ((false == inspectProgramInterfaceiv(program.m_program_object_id)) ||
2963			(false ==
2964			 inspectProgramResourceiv(program.m_program_object_id, subroutine_names, subroutine_uniform_names)) ||
2965			(false ==
2966			 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, true)))
2967		{
2968			result = false;
2969		}
2970	}
2971
2972	/* Test shader execution */
2973	if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2974						   subroutine_names[negate_routine_index], subroutine_uniform_names, inverse_order_negate_data,
2975						   false)) ||
2976		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2977						   subroutine_names[inverse_routine_index], subroutine_uniform_names,
2978						   inverse_order_inverse_data, false)) ||
2979		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2980						   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_order_square_data,
2981						   false)) ||
2982		(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
2983						   subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data,
2984						   false)) ||
2985		(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
2986						   subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data,
2987						   false)) ||
2988		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index],
2989						   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data,
2990						   false)))
2991	{
2992		result = false;
2993	}
2994
2995	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
2996	{
2997		if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2998							   subroutine_names[negate_routine_index], subroutine_uniform_names,
2999							   inverse_order_negate_data, true)) ||
3000			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3001							   subroutine_names[inverse_routine_index], subroutine_uniform_names,
3002							   inverse_order_inverse_data, true)) ||
3003			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3004							   subroutine_names[square_routine_index], subroutine_uniform_names,
3005							   inverse_order_square_data, true)) ||
3006			(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
3007							   subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data,
3008							   true)) ||
3009			(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
3010							   subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data,
3011							   true)) ||
3012			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index],
3013							   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data,
3014							   true)))
3015		{
3016			result = false;
3017		}
3018	}
3019
3020	/* Done */
3021	if (true == result)
3022	{
3023		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3024	}
3025	else
3026	{
3027		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3028	}
3029
3030	return tcu::TestNode::STOP;
3031}
3032
3033/** Verify result of getProgramStageiv
3034 *
3035 * @param program_id Program object id
3036 * @param pname      <pname> parameter for getProgramStageiv
3037 * @param expected   Expected value
3038 *
3039 * @return true if result is equal to expected value, flase otherwise
3040 **/
3041bool FunctionalTest3_4::checkProgramStageiv(glw::GLuint program_id, glw::GLenum pname, glw::GLint expected) const
3042{
3043	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3044	GLint				  value = 0;
3045
3046	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, pname, &value);
3047	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3048
3049	if (expected != value)
3050	{
3051		m_context.getTestContext().getLog() << tcu::TestLog::Message
3052											<< "Error. Invalid result. Function: getProgramStageiv. "
3053											<< "pname: " << Utils::pnameToStr(pname) << ". "
3054											<< "Result: " << value << ". "
3055											<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3056
3057		return false;
3058	}
3059	else
3060	{
3061		return true;
3062	}
3063}
3064
3065/** Verify result of getProgramResourceiv
3066 *
3067 * @param program_id        Program object id
3068 * @param program_interface Program interface
3069 * @param pname             <pname> parameter for getProgramStageiv
3070 * @param resource_name     Resource name
3071 * @param expected          Expected value
3072 *
3073 * @return true if result is equal to expected value, false otherwise
3074 **/
3075bool FunctionalTest3_4::checkProgramResourceiv(GLuint program_id, GLenum program_interface, GLenum pname,
3076											   const glw::GLchar* resource_name, GLint expected) const
3077{
3078	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3079	GLuint				  index = gl.getProgramResourceIndex(program_id, program_interface, resource_name);
3080	GLint				  value = 0;
3081
3082	if (GL_INVALID_INDEX == index)
3083	{
3084		return false;
3085	}
3086
3087	gl.getProgramResourceiv(program_id, program_interface, index, 1, &pname, 1, 0, &value);
3088	GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceiv");
3089
3090	if (expected != value)
3091	{
3092		m_context.getTestContext().getLog()
3093			<< tcu::TestLog::Message << "Error. Invalid result. Function: getProgramResourceiv. "
3094			<< "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". "
3095			<< "Resource name: " << resource_name << ". "
3096			<< "Property: " << Utils::pnameToStr(pname) << ". "
3097			<< "Result: " << value << ". "
3098			<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3099
3100		return false;
3101	}
3102	else
3103	{
3104		return true;
3105	}
3106}
3107
3108/** Verify result of getProgramInterfaceiv
3109 *
3110 * @param program_id        Program object id
3111 * @param program_interface Program interface
3112 * @param pname             <pname> parameter for getProgramStageiv
3113 * @param expected          Expected value
3114 *
3115 * @return true if result is equal to expected value, flase otherwise
3116 **/
3117bool FunctionalTest3_4::checkProgramInterfaceiv(GLuint program_id, GLenum program_interface, GLenum pname,
3118												GLint expected) const
3119{
3120	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3121	GLint				  value = 0;
3122
3123	gl.getProgramInterfaceiv(program_id, program_interface, pname, &value);
3124	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInterfaceiv");
3125
3126	if (expected != value)
3127	{
3128		m_context.getTestContext().getLog()
3129			<< tcu::TestLog::Message << "Error. Invalid result. Function: getProgramInterfaceiv. "
3130			<< "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". "
3131			<< "pname: " << Utils::pnameToStr(pname) << ". "
3132			<< "Result: " << value << ". "
3133			<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3134
3135		return false;
3136	}
3137	else
3138	{
3139		return true;
3140	}
3141}
3142
3143/** Verify result of getActiveSubroutineUniformiv
3144 *
3145 * @param program_id Program object id
3146 * @param index      <index> parameter for getActiveSubroutineUniformiv
3147 * @param pname      <pname> parameter for getActiveSubroutineUniformiv
3148 * @param expected   Expected value
3149 *
3150 * @return true if result is equal to expected value, flase otherwise
3151 **/
3152bool FunctionalTest3_4::checkActiveSubroutineUniformiv(GLuint program_id, GLuint index, GLenum pname,
3153													   GLint expected) const
3154{
3155	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3156	GLint				  value = 0;
3157
3158	gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, index, pname, &value);
3159	GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv");
3160
3161	if (expected != value)
3162	{
3163		m_context.getTestContext().getLog() << tcu::TestLog::Message
3164											<< "Error. Invalid result. Function: getActiveSubroutineUniformiv. "
3165											<< "idnex: " << index << ". "
3166											<< "pname: " << Utils::pnameToStr(pname) << ". "
3167											<< "Result: " << value << ". "
3168											<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3169
3170		return false;
3171	}
3172	else
3173	{
3174		return true;
3175	}
3176}
3177
3178/** Returns index of program resource
3179 *
3180 * @param program_id        Program object id
3181 * @param program_interface Program interface
3182 * @param resource_name     Name of resource
3183 *
3184 * @return Index of specified resource
3185 **/
3186GLuint FunctionalTest3_4::getProgramResourceIndex(GLuint program_id, GLenum program_interface,
3187												  const glw::GLchar* resource_name) const
3188{
3189	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3190	GLuint				  index = gl.getProgramResourceIndex(program_id, program_interface, resource_name);
3191
3192	GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceIndex");
3193
3194	if (GL_INVALID_INDEX == index)
3195	{
3196		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Program resource is not available. "
3197											<< "Program interface: " << Utils::programInterfaceToStr(program_interface)
3198											<< ". "
3199											<< "Resource name: " << resource_name << "." << tcu::TestLog::EndMessage;
3200	}
3201
3202	return index;
3203}
3204
3205/** Get subroutine index
3206 *
3207 * @param program_id        Program object id
3208 * @param subroutine_name   Subroutine name
3209 * @param use_program_query If true getProgramResourceIndex is used, otherwise getSubroutineIndex
3210 *
3211 * @return Index of subroutine
3212 **/
3213GLuint FunctionalTest3_4::getSubroutineIndex(GLuint program_id, const glw::GLchar* subroutine_name,
3214											 bool use_program_query) const
3215{
3216	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3217	GLuint				  index = -1;
3218
3219	if (false == use_program_query)
3220	{
3221		index = gl.getSubroutineIndex(program_id, GL_VERTEX_SHADER, subroutine_name);
3222		GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
3223	}
3224	else
3225	{
3226		index = gl.getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE, subroutine_name);
3227		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex");
3228	}
3229
3230	if (GL_INVALID_INDEX == index)
3231	{
3232		TCU_FAIL("Subroutine is not available");
3233	}
3234
3235	return index;
3236}
3237
3238/** Get subroutine uniform location
3239 *
3240 * @param program_id        Program object id
3241 * @param uniform_name      Subroutine uniform name
3242 * @param use_program_query If true getProgramResourceLocation is used, otherwise getSubroutineUniformLocation
3243 *
3244 * @return Location of subroutine uniform
3245 **/
3246GLint FunctionalTest3_4::getSubroutineUniformLocation(GLuint program_id, const glw::GLchar* uniform_name,
3247													  bool use_program_query) const
3248{
3249	const glw::Functions& gl	   = m_context.getRenderContext().getFunctions();
3250	GLint				  location = -1;
3251
3252	if (false == use_program_query)
3253	{
3254		location = gl.getSubroutineUniformLocation(program_id, GL_VERTEX_SHADER, uniform_name);
3255		GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
3256	}
3257	else
3258	{
3259		location = gl.getProgramResourceLocation(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name);
3260		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceLocation");
3261	}
3262
3263	if (-1 == location)
3264	{
3265		TCU_FAIL("Subroutine uniform is not available");
3266	}
3267
3268	return location;
3269}
3270
3271/** Test if getProgramStageiv results are as expected
3272 *
3273 * @param program_id Program object id
3274 *
3275 * @result false in case of invalid result for any pname, true otherwise
3276 **/
3277bool FunctionalTest3_4::inspectProgramStageiv(glw::GLuint program_id) const
3278{
3279	bool result = true;
3280
3281	const inspectionDetails details[] = {
3282		{ GL_ACTIVE_SUBROUTINE_UNIFORMS, m_n_active_subroutine_uniforms },
3283		{ GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, m_n_active_subroutine_uniform_locations },
3284		{ GL_ACTIVE_SUBROUTINES, m_n_active_subroutines },
3285		{ GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH, m_n_active_subroutine_uniform_name_length + 1 },
3286		{ GL_ACTIVE_SUBROUTINE_MAX_LENGTH, m_n_active_subroutine_name_length + 1 }
3287	};
3288	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3289
3290	for (GLuint i = 0; i < n_details; ++i)
3291	{
3292		if (false == checkProgramStageiv(program_id, details[i].pname, details[i].expected_value))
3293		{
3294			result = false;
3295		}
3296	}
3297
3298	return result;
3299}
3300
3301/** Test if checkProgramInterfaceiv results are as expected
3302 *
3303 * @param program_id Program object id
3304 *
3305 * @result false in case of invalid result for any pname, true otherwise
3306 **/
3307bool FunctionalTest3_4::inspectProgramInterfaceiv(glw::GLuint program_id) const
3308{
3309	bool result = true;
3310
3311	const inspectionDetailsForProgramInterface details[] = {
3312		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, m_n_active_subroutine_uniforms },
3313		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, m_n_active_subroutine_uniform_name_length + 1 },
3314		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3315		{ GL_VERTEX_SUBROUTINE, GL_ACTIVE_RESOURCES, m_n_active_subroutines },
3316		{ GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, m_n_active_subroutine_name_length + 1 }
3317	};
3318	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3319
3320	for (GLuint i = 0; i < n_details; ++i)
3321	{
3322		if (false == checkProgramInterfaceiv(program_id, details[i].program_interface, details[i].pname,
3323											 details[i].expected_value))
3324		{
3325			result = false;
3326		}
3327	}
3328
3329	return result;
3330}
3331
3332/** Test if checkProgramResourceiv results are as expected
3333 *
3334 * @param program_id       Program object id
3335 * @param subroutine_names Array of subroutine names
3336 * @param uniform_names    Array of uniform names
3337 *
3338 * @result false in case of invalid result for any pname, true otherwise
3339 **/
3340bool FunctionalTest3_4::inspectProgramResourceiv(GLuint program_id, const GLchar** subroutine_names,
3341												 const GLchar** uniform_names) const
3342{
3343	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
3344	bool				  result = true;
3345
3346	for (GLint subroutine = 0; subroutine < m_n_active_subroutines; ++subroutine)
3347	{
3348		const GLchar* subroutine_name = subroutine_names[subroutine];
3349		const GLint   length		  = (GLint)strlen(subroutine_name) + 1;
3350
3351		if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE, GL_NAME_LENGTH, subroutine_name, length))
3352		{
3353			result = false;
3354		}
3355	}
3356
3357	inspectionDetails details[] = {
3358		{ GL_NAME_LENGTH, 0 },
3359		{ GL_ARRAY_SIZE, 1 },
3360		{ GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3361		{ GL_LOCATION, 0 },
3362	};
3363	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3364
3365	for (GLint uniform = 0; uniform < m_n_active_subroutine_uniforms; ++uniform)
3366	{
3367		const GLchar* uniform_name = uniform_names[uniform];
3368		const GLint   length	   = (GLint)strlen(uniform_name) + 1;
3369		const GLint   location	 = getSubroutineUniformLocation(program_id, uniform_name, true);
3370
3371		details[0].expected_value = length;
3372		details[3].expected_value = location;
3373
3374		for (GLuint i = 0; i < n_details; ++i)
3375		{
3376			if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, details[i].pname,
3377												uniform_name, details[i].expected_value))
3378			{
3379				result = false;
3380			}
3381		}
3382
3383		/* Check compatible subroutines */
3384		GLuint index = getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name);
3385
3386		if (GL_INVALID_INDEX != index)
3387		{
3388			std::vector<GLint> compatible_subroutines;
3389			GLint			   index_sum = 0;
3390			GLenum			   prop		 = GL_COMPATIBLE_SUBROUTINES;
3391
3392			compatible_subroutines.resize(m_n_active_subroutines);
3393
3394			gl.getProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, index, 1, &prop, m_n_active_subroutines,
3395									0, &compatible_subroutines[0]);
3396
3397			GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv");
3398
3399			/* Expected indices are 0, 1, 2, ... N */
3400			for (GLint i = 0; i < m_n_active_subroutines; ++i)
3401			{
3402				index_sum += compatible_subroutines[i];
3403			}
3404
3405			/* Sum of E1, ..., EN = (E1 + EN) * N / 2 */
3406			if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum)
3407			{
3408				tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3409
3410				message << "Error. Invalid result. Function: getProgramResourceiv. "
3411						<< "Program interface: GL_VERTEX_SUBROUTINE_UNIFORM. "
3412						<< "Resource name: " << uniform_name << ". "
3413						<< "Property: GL_COMPATIBLE_SUBROUTINES. "
3414						<< "Results: ";
3415
3416				for (GLint i = 1; i < m_n_active_subroutines; ++i)
3417				{
3418					message << compatible_subroutines[i];
3419				}
3420
3421				message << tcu::TestLog::EndMessage;
3422
3423				result = false;
3424			}
3425		}
3426	}
3427
3428	return result;
3429}
3430
3431/** Test if getActiveSubroutineUniformiv results are as expected
3432 *
3433 * @param program_id    Program object id
3434 * @param uniform_names Array of subroutine uniform names available in program
3435 *
3436 * @result false in case of invalid result for any pname, true otherwise
3437 **/
3438bool FunctionalTest3_4::inspectActiveSubroutineUniformiv(GLuint program_id, const GLchar** uniform_names) const
3439{
3440	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3441	bool				  result					   = true;
3442	GLint				  n_active_subroutine_uniforms = 0;
3443
3444	inspectionDetails details[] = {
3445		{ GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3446		{ GL_UNIFORM_SIZE, m_n_active_subroutine_uniform_size },
3447		{ GL_UNIFORM_NAME_LENGTH, 0 },
3448	};
3449	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3450
3451	/* Get amount of active subroutine uniforms */
3452	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3453	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3454
3455	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3456	{
3457		GLint name_length = (GLint)strlen(uniform_names[uniform]);
3458
3459		details[2].expected_value = name_length + 1;
3460
3461		/* Checks from "details" */
3462		for (GLuint i = 0; i < n_details; ++i)
3463		{
3464			if (false ==
3465				checkActiveSubroutineUniformiv(program_id, uniform, details[i].pname, details[i].expected_value))
3466			{
3467				result = false;
3468			}
3469		}
3470
3471		/* Check compatible subroutines */
3472		std::vector<GLint> compatible_subroutines;
3473		compatible_subroutines.resize(m_n_active_subroutines);
3474		GLint index_sum = 0;
3475
3476		gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, uniform, GL_COMPATIBLE_SUBROUTINES,
3477										&compatible_subroutines[0]);
3478		GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv");
3479
3480		/* Expected indices are 0, 1, 2, ... N */
3481		for (GLint i = 0; i < m_n_active_subroutines; ++i)
3482		{
3483			index_sum += compatible_subroutines[i];
3484		}
3485
3486		/* Sum of E1, ..., EN = (E1 + EN) * N / 2 */
3487		if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum)
3488		{
3489			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3490
3491			message << "Error. Invalid result. Function: getActiveSubroutineUniformiv. idnex: " << uniform
3492					<< ". pname: " << Utils::pnameToStr(GL_COMPATIBLE_SUBROUTINES) << ". Results: ";
3493
3494			for (GLint i = 1; i < m_n_active_subroutines; ++i)
3495			{
3496				message << compatible_subroutines[i];
3497			}
3498
3499			message << tcu::TestLog::EndMessage;
3500
3501			result = false;
3502		}
3503	}
3504
3505	return result;
3506}
3507
3508/** Test if getActiveSubroutineUniformName results are as expected
3509 *
3510 * @param program_id    Program object id
3511 * @param uniform_names Array of subroutine uniform names available in program
3512 *
3513 * @result false in case of invalid result, true otherwise
3514 **/
3515bool FunctionalTest3_4::inspectActiveSubroutineUniformName(GLuint program_id, const GLchar** uniform_names) const
3516{
3517	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3518	bool				  result					   = true;
3519	GLint				  n_active_subroutine_uniforms = 0;
3520	std::vector<GLchar>   active_uniform_name;
3521
3522	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3523	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3524
3525	active_uniform_name.resize(m_n_active_subroutine_uniform_name_length + 1);
3526
3527	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3528	{
3529		bool is_name_ok = false;
3530
3531		gl.getActiveSubroutineUniformName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_uniform_name.size(),
3532										  0 /* length */, &active_uniform_name[0]);
3533		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveSubroutineUniformName");
3534
3535		for (GLint name = 0; name < n_active_subroutine_uniforms; ++name)
3536		{
3537			if (0 == strcmp(uniform_names[name], &active_uniform_name[0]))
3538			{
3539				is_name_ok = true;
3540				break;
3541			}
3542		}
3543
3544		if (false == is_name_ok)
3545		{
3546			m_context.getTestContext().getLog()
3547				<< tcu::TestLog::Message
3548				<< "Error. Invalid result. Function: getActiveSubroutineUniformName. idnex: " << uniform
3549				<< ". Result: " << &active_uniform_name[0] << tcu::TestLog::EndMessage;
3550
3551			result = false;
3552			break;
3553		}
3554	}
3555
3556	return result;
3557}
3558
3559/** Test if getActiveSubroutineUniformName results are as expected
3560 *
3561 * @param program_id       Program object id
3562 * @param subroutine_names Array of subroutine names available in program
3563 *
3564 * @result false in case of invalid result, true otherwise
3565 **/
3566bool FunctionalTest3_4::inspectActiveSubroutineName(GLuint program_id, const GLchar** subroutine_names) const
3567{
3568	const glw::Functions& gl				   = m_context.getRenderContext().getFunctions();
3569	bool				  result			   = true;
3570	GLint				  n_active_subroutines = 0;
3571	std::vector<GLchar>   active_subroutine_name;
3572
3573	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
3574	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3575
3576	active_subroutine_name.resize(m_n_active_subroutine_name_length + 1);
3577
3578	for (GLint uniform = 0; uniform < n_active_subroutines; ++uniform)
3579	{
3580		bool is_name_ok = false;
3581
3582		gl.getActiveSubroutineName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_subroutine_name.size(),
3583								   0 /* length */, &active_subroutine_name[0]);
3584		GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineName");
3585
3586		for (GLint name = 0; name < n_active_subroutines; ++name)
3587		{
3588			if (0 == strcmp(subroutine_names[name], &active_subroutine_name[0]))
3589			{
3590				is_name_ok = true;
3591				break;
3592			}
3593		}
3594
3595		if (false == is_name_ok)
3596		{
3597			m_context.getTestContext().getLog()
3598				<< tcu::TestLog::Message
3599				<< "Error. Invalid result. Function: getActiveSubroutineName. idnex: " << uniform
3600				<< ". Result: " << &active_subroutine_name[0] << tcu::TestLog::EndMessage;
3601
3602			result = false;
3603			break;
3604		}
3605	}
3606
3607	return result;
3608}
3609
3610/** Test if it is possible to "bind" all subroutines uniforms with all subroutines
3611 *
3612 * @param program_id       Program object id
3613 * @param subroutine_names Array of subroutine names available in program
3614 * @param uniform_names    Array of subroutine uniform names available in program
3615 *
3616 * @result false in case of invalid result, true otherwise
3617 **/
3618bool FunctionalTest3_4::inspectSubroutineBinding(GLuint program_id, const GLchar** subroutine_names,
3619												 const GLchar** uniform_names, bool use_program_query) const
3620{
3621	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3622	bool				  result					   = true;
3623	GLint				  n_active_subroutines		   = 0;
3624	GLint				  n_active_subroutine_uniforms = 0;
3625	std::vector<GLuint>   subroutine_uniforms;
3626	GLuint				  queried_subroutine_index = 0;
3627
3628	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
3629	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3630
3631	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3632	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3633
3634	subroutine_uniforms.resize(n_active_subroutine_uniforms);
3635
3636	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3637	{
3638		GLuint uniform_location = getSubroutineUniformLocation(program_id, uniform_names[uniform], use_program_query);
3639
3640		for (GLint routine = 0; routine < n_active_subroutines; ++routine)
3641		{
3642			GLuint routine_index = getSubroutineIndex(program_id, subroutine_names[routine], use_program_query);
3643
3644			subroutine_uniforms[uniform] = routine_index;
3645
3646			gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_active_subroutine_uniforms, &subroutine_uniforms[0]);
3647			GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3648
3649			gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, uniform_location, &queried_subroutine_index);
3650			GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
3651
3652			if (queried_subroutine_index != routine_index)
3653			{
3654				m_context.getTestContext().getLog()
3655					<< tcu::TestLog::Message << "Error. Invalid result. Function: gl.getUniformSubroutineuiv."
3656					<< " Subroutine uniform: " << uniform << ", name: " << uniform_names[uniform]
3657					<< ", location: " << uniform_location << ". Subroutine: " << routine
3658					<< ", name: " << subroutine_names[routine] << ", index: " << routine_index
3659					<< ". Result: " << queried_subroutine_index << tcu::TestLog::EndMessage;
3660
3661				result = false;
3662			}
3663		}
3664	}
3665
3666	return result;
3667}
3668
3669/** Execute draw call and verify results
3670 *
3671 * @param program_id                   Program object id
3672 * @param first_routine_name           Name of subroutine that shall be used aas first_routine
3673 * @param second_routine_name          Name of subroutine that shall be used aas second_routine
3674 * @param uniform_names                Name of uniforms
3675 * @param expected_results             Test data. [0] is used as input data. All are used as expected_results
3676 * @param use_program_query            If true GetProgram* API will be used
3677 *
3678 * @return false in case of invalid result, true otherwise
3679 **/
3680bool FunctionalTest3_4::testDraw(GLuint program_id, const GLchar* first_routine_name, const GLchar* second_routine_name,
3681								 const GLchar** uniform_names, const Utils::vec4<GLfloat> expected_results[5],
3682								 bool use_program_query) const
3683{
3684	static const GLuint   n_varyings			 = 5;
3685	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3686	bool				  result				 = true;
3687	GLuint				  subroutine_uniforms[2] = { 0 };
3688
3689	/* Get subroutine uniform locations */
3690	GLint first_routine_location = getSubroutineUniformLocation(program_id, uniform_names[0], use_program_query);
3691
3692	GLint second_routine_location = getSubroutineUniformLocation(program_id, uniform_names[1], use_program_query);
3693
3694	/* Get subroutine indices */
3695	GLuint first_routine_index = getSubroutineIndex(program_id, first_routine_name, use_program_query);
3696
3697	GLuint second_routine_index = getSubroutineIndex(program_id, second_routine_name, use_program_query);
3698
3699	/* Map uniforms with subroutines */
3700	subroutine_uniforms[first_routine_location]  = first_routine_index;
3701	subroutine_uniforms[second_routine_location] = second_routine_index;
3702
3703	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 2 /* number of uniforms */, &subroutine_uniforms[0]);
3704	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3705
3706	/* Get location of input_data */
3707	GLint input_data_location = gl.getUniformLocation(program_id, "input_data");
3708	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
3709
3710	if (-1 == input_data_location)
3711	{
3712		TCU_FAIL("Uniform is not available");
3713	}
3714
3715	/* Set up input_data */
3716	gl.uniform4f(input_data_location, expected_results[0].m_x, expected_results[0].m_y, expected_results[0].m_z,
3717				 expected_results[0].m_w);
3718	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
3719
3720	/* Execute draw call with transform feedback */
3721	gl.beginTransformFeedback(GL_POINTS);
3722	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
3723
3724	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
3725	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
3726
3727	gl.endTransformFeedback();
3728	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
3729
3730	/* Verify results */
3731	GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3732	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3733
3734	Utils::vec4<GLfloat> results[5];
3735
3736	results[0].m_x = feedback_data[0];
3737	results[0].m_y = feedback_data[1];
3738	results[0].m_z = feedback_data[2];
3739	results[0].m_w = feedback_data[3];
3740
3741	results[1].m_x = feedback_data[4];
3742	results[1].m_y = feedback_data[5];
3743	results[1].m_z = feedback_data[6];
3744	results[1].m_w = feedback_data[7];
3745
3746	results[2].m_x = feedback_data[8];
3747	results[2].m_y = feedback_data[9];
3748	results[2].m_z = feedback_data[10];
3749	results[2].m_w = feedback_data[11];
3750
3751	results[3].m_x = feedback_data[12];
3752	results[3].m_y = feedback_data[13];
3753	results[3].m_z = feedback_data[14];
3754	results[3].m_w = feedback_data[15];
3755
3756	results[4].m_x = feedback_data[16];
3757	results[4].m_y = feedback_data[17];
3758	results[4].m_z = feedback_data[18];
3759	results[4].m_w = feedback_data[19];
3760
3761	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3762	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3763
3764	for (GLuint i = 0; i < n_varyings; ++i)
3765	{
3766		result = result && (results[i] == expected_results[i]);
3767	}
3768
3769	if (false == result)
3770	{
3771		m_context.getTestContext().getLog() << tcu::TestLog::Message
3772											<< "Error. Invalid result. First routine: " << first_routine_name
3773											<< ". Second routine: " << second_routine_name << tcu::TestLog::EndMessage;
3774
3775		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3776
3777		message << "Results:";
3778
3779		for (GLuint i = 0; i < n_varyings; ++i)
3780		{
3781			results[i].log(message);
3782		}
3783
3784		message << tcu::TestLog::EndMessage;
3785
3786		message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3787
3788		message << "Expected:";
3789
3790		for (GLuint i = 0; i < n_varyings; ++i)
3791		{
3792			expected_results[i].log(message);
3793		}
3794
3795		message << tcu::TestLog::EndMessage;
3796	}
3797
3798	return result;
3799}
3800
3801/** Constructor
3802 *
3803 * @param context CTS context
3804 **/
3805FunctionalTest5::FunctionalTest5(deqp::Context& context)
3806	: TestCase(context, "eight_subroutines_four_uniforms", "Verify multiple subroutine sets")
3807{
3808}
3809
3810/** Execute test
3811 *
3812 * @return tcu::TestNode::STOP
3813 **/
3814tcu::TestNode::IterateResult FunctionalTest5::iterate()
3815{
3816	static const GLchar* vertex_shader_code =
3817		"#version 400 core\n"
3818		"#extension GL_ARB_shader_subroutine : require\n"
3819		"\n"
3820		"precision highp float;\n"
3821		"\n"
3822		"// Subroutine types\n"
3823		"subroutine vec4  routine_type_1(in vec4 left, in vec4 right);\n"
3824		"subroutine vec4  routine_type_2(in vec4 iparam);\n"
3825		"subroutine vec4  routine_type_3(in vec4 a,    in vec4 b,    in vec4 c);\n"
3826		"subroutine bvec4 routine_type_4(in vec4 left, in vec4 right);\n"
3827		"\n"
3828		"// Subroutine definitions\n"
3829		"// 1st type\n"
3830		"subroutine(routine_type_1) vec4 add(in vec4 left, in vec4 right)\n"
3831		"{\n"
3832		"    return left + right;\n"
3833		"}\n"
3834		"\n"
3835		"subroutine(routine_type_1) vec4 subtract(in vec4 left, in vec4 right)\n"
3836		"{\n"
3837		"    return left - right;\n"
3838		"}\n"
3839		"\n"
3840		"// 2nd type\n"
3841		"subroutine(routine_type_2) vec4 square(in vec4 iparam)\n"
3842		"{\n"
3843		"    return iparam * iparam;\n"
3844		"}\n"
3845		"\n"
3846		"subroutine(routine_type_2) vec4 square_root(in vec4 iparam)\n"
3847		"{\n"
3848		"    return sqrt(iparam);\n"
3849		"}\n"
3850		"\n"
3851		"// 3rd type\n"
3852		"subroutine(routine_type_3) vec4 do_fma(in vec4 a, in vec4 b, in vec4 c)\n"
3853		"{\n"
3854		"    return fma(a, b, c);\n"
3855		"}\n"
3856		"\n"
3857		"subroutine(routine_type_3) vec4 blend(in vec4 a, in vec4 b, in vec4 c)\n"
3858		"{\n"
3859		"    return c * a + (vec4(1) - c) * b;\n"
3860		"}\n"
3861		"\n"
3862		"// 4th type\n"
3863		"subroutine(routine_type_4) bvec4 are_equal(in vec4 left, in vec4 right)\n"
3864		"{\n"
3865		"    return equal(left, right);\n"
3866		"}\n"
3867		"\n"
3868		"subroutine(routine_type_4) bvec4 are_greater(in vec4 left, in vec4 right)\n"
3869		"{\n"
3870		"    return greaterThan(left, right);\n"
3871		"}\n"
3872		"\n"
3873		"// Sub routine uniforms\n"
3874		"subroutine uniform routine_type_1 first_routine;\n"
3875		"subroutine uniform routine_type_2 second_routine;\n"
3876		"subroutine uniform routine_type_3 third_routine;\n"
3877		"subroutine uniform routine_type_4 fourth_routine;\n"
3878		"\n"
3879		"// Input data\n"
3880		"uniform vec4 first_input;\n"
3881		"uniform vec4 second_input;\n"
3882		"uniform vec4 third_input;\n"
3883		"\n"
3884		"// Output\n"
3885		"out  vec4 out_result_from_first_routine;\n"
3886		"out  vec4 out_result_from_second_routine;\n"
3887		"out  vec4 out_result_from_third_routine;\n"
3888		"out uvec4 out_result_from_fourth_routine;\n"
3889		"\n"
3890		"void main()\n"
3891		"{\n"
3892		"    out_result_from_first_routine  =       first_routine (first_input, second_input);\n"
3893		"    out_result_from_second_routine =       second_routine(first_input);\n"
3894		"    out_result_from_third_routine  =       third_routine (first_input, second_input, third_input);\n"
3895		"    out_result_from_fourth_routine = uvec4(fourth_routine(first_input, second_input));\n"
3896		"}\n"
3897		"\n";
3898
3899	static const GLchar* subroutine_names[4][2] = {
3900		{ "add", "subtract" }, { "square", "square_root" }, { "do_fma", "blend" }, { "are_equal", "are_greater" }
3901	};
3902
3903	static const GLchar* subroutine_uniform_names[4][1] = {
3904		{ "first_routine" }, { "second_routine" }, { "third_routine" }, { "fourth_routine" }
3905	};
3906
3907	static const GLuint n_subroutine_types	 = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
3908	static const GLuint n_subroutines_per_type = sizeof(subroutine_names[0]) / sizeof(subroutine_names[0][0]);
3909	static const GLuint n_subroutine_uniforms_per_type =
3910		sizeof(subroutine_uniform_names[0]) / sizeof(subroutine_uniform_names[0][0]);
3911
3912	static const GLchar* uniform_names[] = { "first_input", "second_input", "third_input" };
3913	static const GLuint  n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
3914
3915	static const GLchar* varying_names[] = { "out_result_from_first_routine", "out_result_from_second_routine",
3916											 "out_result_from_third_routine", "out_result_from_fourth_routine" };
3917	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
3918	static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */;
3919
3920	/* Test data */
3921	static const Utils::vec4<GLfloat> input_data[3] = { Utils::vec4<GLfloat>(1.0f, 4.0f, 9.0f, 16.0f),
3922														Utils::vec4<GLfloat>(16.0f, 9.0f, 4.0f, 1.0f),
3923														Utils::vec4<GLfloat>(0.25f, 0.5f, 0.75f, 1.0f) };
3924
3925	static const Utils::vec4<GLfloat> expected_result_from_first_routine[2] = {
3926		Utils::vec4<GLfloat>(17.0f, 13.0f, 13.0f, 17.0f), Utils::vec4<GLfloat>(-15.0f, -5.0f, 5.0f, 15.0f)
3927	};
3928
3929	static const Utils::vec4<GLfloat> expected_result_from_second_routine[2] = {
3930		Utils::vec4<GLfloat>(1.0f, 16.0f, 81.0f, 256.0f), Utils::vec4<GLfloat>(1.0f, 2.0f, 3.0f, 4.0f)
3931	};
3932
3933	static const Utils::vec4<GLfloat> expected_result_from_third_routine[2] = {
3934		Utils::vec4<GLfloat>(16.25f, 36.5f, 36.75f, 17.0f), Utils::vec4<GLfloat>(12.25f, 6.5f, 7.75f, 16.0f)
3935	};
3936
3937	static const Utils::vec4<GLuint> expected_result_from_fourth_routine[2] = { Utils::vec4<GLuint>(0, 0, 0, 0),
3938																				Utils::vec4<GLuint>(0, 0, 1, 1) };
3939
3940	/* All combinations of subroutines */
3941	static const GLuint subroutine_combinations[][4] = {
3942		{ 0, 0, 0, 0 }, { 0, 0, 0, 1 }, { 0, 0, 1, 0 }, { 0, 0, 1, 1 }, { 0, 1, 0, 0 }, { 0, 1, 0, 1 },
3943		{ 0, 1, 1, 0 }, { 0, 1, 1, 1 }, { 1, 0, 0, 0 }, { 1, 0, 0, 1 }, { 1, 0, 1, 0 }, { 1, 0, 1, 1 },
3944		{ 1, 1, 0, 0 }, { 1, 1, 0, 1 }, { 1, 1, 1, 0 }, { 1, 1, 1, 1 }
3945	};
3946	static const GLuint n_subroutine_combinations =
3947		sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]);
3948
3949	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
3950	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
3951	{
3952		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
3953	}
3954
3955	/* Result */
3956	bool result = true;
3957
3958	/* GL objects */
3959	Utils::program	 program(m_context);
3960	Utils::buffer	  transform_feedback_buffer(m_context);
3961	Utils::vertexArray vao(m_context);
3962
3963	/* Init GL objects */
3964	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
3965				  n_varyings);
3966
3967	program.use();
3968
3969	vao.generate();
3970	vao.bind();
3971
3972	transform_feedback_buffer.generate();
3973	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
3974									 GL_DYNAMIC_COPY);
3975	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
3976
3977	/* Get subroutine uniform locations and subroutine indices */
3978	for (GLuint type = 0; type < n_subroutine_types; ++type)
3979	{
3980		for (GLuint uniform = 0; uniform < n_subroutine_uniforms_per_type; ++uniform)
3981		{
3982			m_subroutine_uniform_locations[type][uniform] =
3983				program.getSubroutineUniformLocation(subroutine_uniform_names[type][uniform], GL_VERTEX_SHADER);
3984		}
3985
3986		for (GLuint routine = 0; routine < n_subroutines_per_type; ++routine)
3987		{
3988			m_subroutine_indices[type][routine] =
3989				program.getSubroutineIndex(subroutine_names[type][routine], GL_VERTEX_SHADER);
3990		}
3991	}
3992
3993	/* Get uniform locations */
3994	for (GLuint i = 0; i < n_uniform_names; ++i)
3995	{
3996		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
3997	}
3998
3999	/* Draw with each routine combination */
4000	for (GLuint i = 0; i < n_subroutine_combinations; ++i)
4001	{
4002		Utils::vec4<GLfloat> first_routine_result;
4003		Utils::vec4<GLfloat> second_routine_result;
4004		Utils::vec4<GLfloat> third_routine_result;
4005		Utils::vec4<GLuint>  fourth_routine_result;
4006
4007		testDraw(subroutine_combinations[i], input_data, first_routine_result, second_routine_result,
4008				 third_routine_result, fourth_routine_result);
4009
4010		if (false == verify(first_routine_result, second_routine_result, third_routine_result, fourth_routine_result,
4011							expected_result_from_first_routine[subroutine_combinations[i][0]],
4012							expected_result_from_second_routine[subroutine_combinations[i][1]],
4013							expected_result_from_third_routine[subroutine_combinations[i][2]],
4014							expected_result_from_fourth_routine[subroutine_combinations[i][3]]))
4015		{
4016			logError(subroutine_names, subroutine_combinations[i], input_data, first_routine_result,
4017					 second_routine_result, third_routine_result, fourth_routine_result,
4018					 expected_result_from_first_routine[subroutine_combinations[i][0]],
4019					 expected_result_from_second_routine[subroutine_combinations[i][1]],
4020					 expected_result_from_third_routine[subroutine_combinations[i][2]],
4021					 expected_result_from_fourth_routine[subroutine_combinations[i][3]]);
4022
4023			result = false;
4024		}
4025	}
4026
4027	/* Done */
4028	if (true == result)
4029	{
4030		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4031	}
4032	else
4033	{
4034		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4035	}
4036
4037	return tcu::TestNode::STOP;
4038}
4039
4040/** Log error message
4041 *
4042 * @param subroutine_names               Array of subroutine names
4043 * @param subroutine_combination         Combination of subroutines
4044 * @param input_data                     Input data
4045 * @param first_routine_result           Result of first routine
4046 * @param second_routine_result          Result of second routine
4047 * @param third_routine_result           Result of third routine
4048 * @param fourth_routine_result          Result of fourth routine
4049 * @param first_routine_expected_result  Expected result of first routine
4050 * @param second_routine_expected_result Expected result of second routine
4051 * @param third_routine_expected_result  Expected result of third routine
4052 * @param fourth_routine_expected_result Expected result of fourth routine
4053 **/
4054void FunctionalTest5::logError(const glw::GLchar* subroutine_names[4][2], const glw::GLuint subroutine_combination[4],
4055							   const Utils::vec4<glw::GLfloat>  input_data[3],
4056							   const Utils::vec4<glw::GLfloat>& first_routine_result,
4057							   const Utils::vec4<glw::GLfloat>& second_routine_result,
4058							   const Utils::vec4<glw::GLfloat>& third_routine_result,
4059							   const Utils::vec4<glw::GLuint>&  fourth_routine_result,
4060							   const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
4061							   const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
4062							   const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
4063							   const Utils::vec4<glw::GLuint>&  fourth_routine_expected_result) const
4064{
4065	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4066										<< tcu::TestLog::EndMessage;
4067
4068	tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4069
4070	message << "Function: " << subroutine_names[0][subroutine_combination[0]] << "( ";
4071	input_data[0].log(message);
4072	message << ", ";
4073	input_data[1].log(message);
4074	message << " ). Result: ";
4075	first_routine_result.log(message);
4076	message << ". Expected: ";
4077	first_routine_expected_result.log(message);
4078
4079	message << tcu::TestLog::EndMessage;
4080
4081	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4082
4083	message << "Function: " << subroutine_names[1][subroutine_combination[1]] << "( ";
4084	input_data[0].log(message);
4085	message << " ). Result: ";
4086	second_routine_result.log(message);
4087	message << ". Expected: ";
4088	second_routine_expected_result.log(message);
4089
4090	message << tcu::TestLog::EndMessage;
4091
4092	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4093
4094	message << "Function: " << subroutine_names[2][subroutine_combination[2]] << "( ";
4095	input_data[0].log(message);
4096	message << ", ";
4097	input_data[1].log(message);
4098	message << ", ";
4099	input_data[2].log(message);
4100	message << "). Result: ";
4101	third_routine_result.log(message);
4102	message << ". Expected: ";
4103	third_routine_expected_result.log(message);
4104
4105	message << tcu::TestLog::EndMessage;
4106
4107	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4108
4109	message << "Function: " << subroutine_names[3][subroutine_combination[3]] << "( ";
4110	input_data[0].log(message);
4111	message << ", ";
4112	input_data[1].log(message);
4113	message << ", ";
4114	message << " ). Result: ";
4115	fourth_routine_result.log(message);
4116	message << ". Expected: ";
4117	fourth_routine_expected_result.log(message);
4118
4119	message << tcu::TestLog::EndMessage;
4120}
4121
4122/** Execute draw call and capture results
4123 *
4124 * @param subroutine_combination    Combination of subroutines
4125 * @param input_data                Input data
4126 * @param out_first_routine_result  Result of first routine
4127 * @param out_second_routine_result Result of second routine
4128 * @param out_third_routine_result  Result of third routine
4129 * @param out_fourth_routine_result Result of fourth routine
4130 **/
4131void FunctionalTest5::testDraw(const glw::GLuint			   subroutine_combination[4],
4132							   const Utils::vec4<glw::GLfloat> input_data[3],
4133							   Utils::vec4<glw::GLfloat>&	  out_first_routine_result,
4134							   Utils::vec4<glw::GLfloat>&	  out_second_routine_result,
4135							   Utils::vec4<glw::GLfloat>&	  out_third_routine_result,
4136							   Utils::vec4<glw::GLuint>&	   out_fourth_routine_result) const
4137{
4138	static const GLuint   n_uniforms = sizeof(m_uniform_locations) / sizeof(m_uniform_locations[0]);
4139	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
4140	GLuint				  subroutine_indices[4];
4141	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
4142
4143	/* Prepare subroutine uniform data */
4144	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
4145	{
4146		const GLuint location = m_subroutine_uniform_locations[i][0];
4147
4148		subroutine_indices[location] = m_subroutine_indices[i][subroutine_combination[i]];
4149	}
4150
4151	/* Set up subroutine uniforms */
4152	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
4153	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
4154
4155	/* Set up input data uniforms */
4156	for (GLuint i = 0; i < n_uniforms; ++i)
4157	{
4158		gl.uniform4f(m_uniform_locations[i], input_data[i].m_x, input_data[i].m_y, input_data[i].m_z,
4159					 input_data[i].m_w);
4160		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4161	}
4162
4163	/* Execute draw call with transform feedback */
4164	gl.beginTransformFeedback(GL_POINTS);
4165	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4166
4167	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4168	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4169
4170	gl.endTransformFeedback();
4171	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4172
4173	/* Capture results */
4174	GLvoid* feedback_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4175	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4176
4177	GLfloat* float_ptr = (GLfloat*)feedback_data;
4178
4179	/* First result */
4180	out_first_routine_result.m_x = float_ptr[0];
4181	out_first_routine_result.m_y = float_ptr[1];
4182	out_first_routine_result.m_z = float_ptr[2];
4183	out_first_routine_result.m_w = float_ptr[3];
4184
4185	/* Second result */
4186	out_second_routine_result.m_x = float_ptr[4];
4187	out_second_routine_result.m_y = float_ptr[5];
4188	out_second_routine_result.m_z = float_ptr[6];
4189	out_second_routine_result.m_w = float_ptr[7];
4190
4191	/* Third result */
4192	out_third_routine_result.m_x = float_ptr[8];
4193	out_third_routine_result.m_y = float_ptr[9];
4194	out_third_routine_result.m_z = float_ptr[10];
4195	out_third_routine_result.m_w = float_ptr[11];
4196
4197	/* Fourth result */
4198	GLuint* uint_ptr			  = (GLuint*)(float_ptr + 12);
4199	out_fourth_routine_result.m_x = uint_ptr[0];
4200	out_fourth_routine_result.m_y = uint_ptr[1];
4201	out_fourth_routine_result.m_z = uint_ptr[2];
4202	out_fourth_routine_result.m_w = uint_ptr[3];
4203
4204	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4205	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4206}
4207
4208/** Verify if results match expected results
4209 *
4210 * @param first_routine_result           Result of first routine
4211 * @param second_routine_result          Result of second routine
4212 * @param third_routine_result           Result of third routine
4213 * @param fourth_routine_result          Result of fourth routine
4214 * @param first_routine_expected_result  Expected result of first routine
4215 * @param second_routine_expected_result Expected result of second routine
4216 * @param third_routine_expected_result  Expected result of third routine
4217 * @param fourth_routine_expected_result Expected result of fourth routine
4218 **/
4219bool FunctionalTest5::verify(const Utils::vec4<glw::GLfloat>& first_routine_result,
4220							 const Utils::vec4<glw::GLfloat>& second_routine_result,
4221							 const Utils::vec4<glw::GLfloat>& third_routine_result,
4222							 const Utils::vec4<glw::GLuint>&  fourth_routine_result,
4223							 const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
4224							 const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
4225							 const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
4226							 const Utils::vec4<glw::GLuint>&  fourth_routine_expected_result) const
4227{
4228	bool result = true;
4229
4230	result = result && (first_routine_result == first_routine_expected_result);
4231	result = result && (second_routine_result == second_routine_expected_result);
4232	result = result && (third_routine_result == third_routine_expected_result);
4233	result = result && (fourth_routine_result == fourth_routine_expected_result);
4234
4235	return result;
4236}
4237
4238/** Constructor
4239 *
4240 * @param context CTS context
4241 **/
4242FunctionalTest6::FunctionalTest6(deqp::Context& context)
4243	: TestCase(context, "static_subroutine_call", "Verify that subroutine can be called in a static manner")
4244{
4245}
4246
4247/** Execute test
4248 *
4249 * @return tcu::TestNode::STOP
4250 **/
4251tcu::TestNode::IterateResult FunctionalTest6::iterate()
4252{
4253	static const GLchar* vertex_shader_code = "#version 400 core\n"
4254											  "#extension GL_ARB_shader_subroutine : require\n"
4255											  "\n"
4256											  "precision highp float;\n"
4257											  "\n"
4258											  "// Subroutine type\n"
4259											  "subroutine vec4 routine_type(in vec4 iparam);\n"
4260											  "\n"
4261											  "// Subroutine definition\n"
4262											  "subroutine(routine_type) vec4 square(in vec4 iparam)\n"
4263											  "{\n"
4264											  "    return iparam * iparam;\n"
4265											  "}\n"
4266											  "\n"
4267											  "// Sub routine uniform\n"
4268											  "subroutine uniform routine_type routine;\n"
4269											  "\n"
4270											  "// Input data\n"
4271											  "uniform vec4 input_data;\n"
4272											  "\n"
4273											  "// Output\n"
4274											  "out  vec4 out_result;\n"
4275											  "\n"
4276											  "void main()\n"
4277											  "{\n"
4278											  "    out_result  = square(input_data);\n"
4279											  "}\n"
4280											  "\n";
4281
4282	static const GLchar* varying_name = "out_result";
4283
4284	/* Test data */
4285	static const Utils::vec4<GLfloat> input_data(1.0f, 4.0f, 9.0f, 16.0f);
4286
4287	static const Utils::vec4<GLfloat> expected_result(1.0f, 16.0f, 81.0f, 256.0f);
4288
4289	static const GLuint transform_feedback_buffer_size = 4 * sizeof(GLfloat);
4290
4291	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
4292	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
4293	{
4294		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
4295	}
4296
4297	/* GL objects */
4298	Utils::program	 program(m_context);
4299	Utils::buffer	  transform_feedback_buffer(m_context);
4300	Utils::vertexArray vao(m_context);
4301
4302	/* Init GL objects */
4303	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name,
4304				  1 /* n_varyings */);
4305
4306	program.use();
4307
4308	vao.generate();
4309	vao.bind();
4310
4311	transform_feedback_buffer.generate();
4312	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
4313									 GL_DYNAMIC_COPY);
4314	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
4315
4316	/* Test */
4317	{
4318		const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
4319		const GLint			  uniform_location = gl.getUniformLocation(program.m_program_object_id, "input_data");
4320
4321		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
4322
4323		if (-1 == uniform_location)
4324		{
4325			TCU_FAIL("Uniform is not available");
4326		}
4327
4328		/* Set up input data uniforms */
4329		gl.uniform4f(uniform_location, input_data.m_x, input_data.m_y, input_data.m_z, input_data.m_w);
4330		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4331
4332		/* Execute draw call with transform feedback */
4333		gl.beginTransformFeedback(GL_POINTS);
4334		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4335
4336		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4337		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4338
4339		gl.endTransformFeedback();
4340		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4341
4342		/* Capture results */
4343		GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4344		GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4345
4346		Utils::vec4<GLfloat> result(feedback_data[0], feedback_data[1], feedback_data[2], feedback_data[3]);
4347
4348		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4349		GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4350
4351		/* Verify */
4352		if (expected_result == result)
4353		{
4354			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4355		}
4356		else
4357		{
4358			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4359												<< tcu::TestLog::EndMessage;
4360
4361			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4362
4363			message << "Function: square( ";
4364			input_data.log(message);
4365			message << " ). Result: ";
4366			result.log(message);
4367			message << ". Expected: ";
4368			expected_result.log(message);
4369
4370			message << tcu::TestLog::EndMessage;
4371
4372			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4373		}
4374	}
4375
4376	/* Done */
4377	return tcu::TestNode::STOP;
4378}
4379
4380/** Constructor
4381 *
4382 * @param context CTS context
4383 **/
4384FunctionalTest7_8::FunctionalTest7_8(deqp::Context& context)
4385	: TestCase(context, "arrayed_subroutine_uniforms", "Verify that subroutine can be called in a static manner")
4386{
4387}
4388
4389/** Execute test
4390 *
4391 * @return tcu::TestNode::STOP
4392 **/
4393tcu::TestNode::IterateResult FunctionalTest7_8::iterate()
4394{
4395	static const GLchar* vertex_shader_code =
4396		"#version 400 core\n"
4397		"#extension GL_ARB_shader_subroutine : require\n"
4398		"\n"
4399		"precision highp float;\n"
4400		"\n"
4401		"// Subroutine type\n"
4402		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
4403		"\n"
4404		"// Subroutine definitions\n"
4405		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
4406		"{\n"
4407		"    return left + right;\n"
4408		"}\n"
4409		"\n"
4410		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
4411		"{\n"
4412		"    return left * right;\n"
4413		"}\n"
4414		"\n"
4415		"// Sub routine uniform\n"
4416		"subroutine uniform routine_type routine[4];\n"
4417		"\n"
4418		"// Input data\n"
4419		"uniform vec4  uni_left;\n"
4420		"uniform vec4  uni_right;\n"
4421		"uniform uvec4 uni_indices;\n"
4422		"\n"
4423		"// Output\n"
4424		"out vec4 out_combined;\n"
4425		"out vec4 out_combined_inverted;\n"
4426		"out vec4 out_constant;\n"
4427		"out vec4 out_constant_inverted;\n"
4428		"out vec4 out_dynamic;\n"
4429		"out vec4 out_dynamic_inverted;\n"
4430		"out vec4 out_loop;\n"
4431		"out uint out_array_length;\n"
4432		"\n"
4433		"void main()\n"
4434		"{\n"
4435		"    out_combined          = routine[3](routine[2](routine[1](routine[0](uni_left, uni_right), uni_right), "
4436		"uni_right), uni_right);\n"
4437		"    out_combined_inverted = routine[0](routine[1](routine[2](routine[3](uni_left, uni_right), uni_right), "
4438		"uni_right), uni_right);\n"
4439		"    \n"
4440		"    out_constant          = routine[3](routine[2](routine[1](routine[0](vec4(1, 2, 3, 4), vec4(-5, -6, -7, "
4441		"-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n"
4442		"    out_constant_inverted = routine[0](routine[1](routine[2](routine[3](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		"    \n"
4445		"    out_dynamic           = "
4446		"routine[uni_indices.w](routine[uni_indices.z](routine[uni_indices.y](routine[uni_indices.x](uni_left, "
4447		"uni_right), uni_right), uni_right), uni_right);\n"
4448		"    out_dynamic_inverted  = "
4449		"routine[uni_indices.x](routine[uni_indices.y](routine[uni_indices.z](routine[uni_indices.w](uni_left, "
4450		"uni_right), uni_right), uni_right), uni_right);\n"
4451		"    \n"
4452		"    out_loop              = uni_left;\n"
4453		"    for (uint i = 0u; i < routine.length(); ++i)\n"
4454		"    {\n"
4455		"        out_loop          = routine[i](out_loop, uni_right);\n"
4456		"    }\n"
4457		"    \n"
4458		"    out_array_length      = routine.length() + 6 - (uni_indices.x + uni_indices.y + uni_indices.z + "
4459		"uni_indices.w);\n"
4460		"}\n"
4461		"\n";
4462
4463	static const GLchar* subroutine_names[] = {
4464		"add", "multiply",
4465	};
4466	static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
4467
4468	static const GLchar* subroutine_uniform_names[] = { "routine[0]", "routine[1]", "routine[2]", "routine[3]" };
4469	static const GLuint  n_subroutine_uniform_names =
4470		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
4471
4472	static const GLchar* uniform_names[] = {
4473		"uni_left", "uni_right", "uni_indices",
4474	};
4475	static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
4476
4477	static const GLchar* varying_names[] = { "out_combined", "out_combined_inverted",
4478											 "out_constant", "out_constant_inverted",
4479											 "out_dynamic",  "out_dynamic_inverted",
4480											 "out_loop",	 "out_array_length" };
4481
4482	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
4483	static const GLuint transform_feedback_buffer_size = n_varyings * 4 * sizeof(GLfloat);
4484
4485	/* Test data */
4486	static const Utils::vec4<GLfloat> uni_left(-1.0f, 0.75f, -0.5f, 0.25f);
4487	static const Utils::vec4<GLfloat> uni_right(1.0f, -0.75f, 0.5f, -0.25f);
4488	static const Utils::vec4<GLuint>  uni_indices(1, 2, 0, 3);
4489
4490	static const GLuint subroutine_combinations[][4] = {
4491		{ 0, 0, 0, 0 }, /* + + + + */
4492		{ 0, 0, 0, 1 }, /* + + + * */
4493		{ 0, 0, 1, 0 }, /* + + * + */
4494		{ 0, 0, 1, 1 }, /* + + * * */
4495		{ 0, 1, 0, 0 }, /* + * + + */
4496		{ 0, 1, 0, 1 }, /* + * + * */
4497		{ 0, 1, 1, 0 }, /* + * * + */
4498		{ 0, 1, 1, 1 }, /* + * * * */
4499		{ 1, 0, 0, 0 }, /* * + + + */
4500		{ 1, 0, 0, 1 }, /* * + + * */
4501		{ 1, 0, 1, 0 }, /* * + * + */
4502		{ 1, 0, 1, 1 }, /* * + * * */
4503		{ 1, 1, 0, 0 }, /* * * + + */
4504		{ 1, 1, 0, 1 }, /* * * + * */
4505		{ 1, 1, 1, 0 }, /* * * * + */
4506		{ 1, 1, 1, 1 }  /* * * * * */
4507	};
4508	static const GLuint n_subroutine_combinations =
4509		sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]);
4510
4511	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
4512	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
4513	{
4514		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
4515	}
4516
4517	/* GL objects */
4518	Utils::program	 program(m_context);
4519	Utils::buffer	  transform_feedback_buffer(m_context);
4520	Utils::vertexArray vao(m_context);
4521
4522	bool result = true;
4523
4524	/* Init GL objects */
4525	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
4526				  n_varyings);
4527
4528	program.use();
4529
4530	vao.generate();
4531	vao.bind();
4532
4533	transform_feedback_buffer.generate();
4534
4535	/* Get subroutine indices */
4536	for (GLuint routine = 0; routine < n_subroutine_names; ++routine)
4537	{
4538		m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER);
4539	}
4540
4541	/* Get subroutine uniform locations */
4542	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
4543	{
4544		m_subroutine_uniform_locations[uniform] =
4545			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
4546	}
4547
4548	/* Get uniform locations */
4549	for (GLuint i = 0; i < n_uniform_names; ++i)
4550	{
4551		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
4552	}
4553
4554	/* Test */
4555	for (GLuint i = 0; i < n_subroutine_combinations; ++i)
4556	{
4557		/* Clean */
4558		transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
4559										 GL_DYNAMIC_COPY);
4560		transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
4561
4562		/* Verify */
4563		if (false == testDraw(subroutine_combinations[i], uni_left, uni_right, uni_indices))
4564		{
4565			result = false;
4566		}
4567	}
4568
4569	if (true == result)
4570	{
4571		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4572	}
4573	else
4574	{
4575		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4576	}
4577
4578	/* Done */
4579	return tcu::TestNode::STOP;
4580}
4581
4582/* Calculate result of function applied to operands
4583 *
4584 * @param function Function id, 0 is sum, 1 is multiplication
4585 * @param left     Left operand
4586 * @param right    Right operand
4587 * @param out      Function result
4588 **/
4589void FunctionalTest7_8::calculate(glw::GLuint function, const Utils::vec4<glw::GLfloat>& left,
4590								  const Utils::vec4<glw::GLfloat>& right, Utils::vec4<glw::GLfloat>& out) const
4591{
4592	if (0 == function)
4593	{
4594		out.m_x = left.m_x + right.m_x;
4595		out.m_y = left.m_y + right.m_y;
4596		out.m_z = left.m_z + right.m_z;
4597		out.m_w = left.m_w + right.m_w;
4598	}
4599	else
4600	{
4601		out.m_x = left.m_x * right.m_x;
4602		out.m_y = left.m_y * right.m_y;
4603		out.m_z = left.m_z * right.m_z;
4604		out.m_w = left.m_w * right.m_w;
4605	}
4606}
4607
4608/** Calculate expected values for all operations
4609 *
4610 * @param combination           Function combination, first applied function is at index [0]
4611 * @param left                  Left operand
4612 * @param right                 Right operand
4613 * @param indices               Indices used by dynamic calls
4614 * @param out_combined          Expected result of "combined" operation
4615 * @param out_combined_inverted Expected result of "combined_inverted" operation
4616 * @param out_constant          Expected result of "constant" operation
4617 * @param out_constant_inverted Expected result of "constant_inverted" operation
4618 * @param out_dynamic           Expected result of "dynamic" operation
4619 * @param out_dynamic_inverted  Expected result of "out_dynamic_inverted" operation
4620 * @param out_loop              Expected result of "loop" operation
4621 **/
4622void FunctionalTest7_8::calculate(
4623	const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, const Utils::vec4<glw::GLfloat>& right,
4624	const Utils::vec4<glw::GLuint>& indices, Utils::vec4<glw::GLfloat>& out_combined,
4625	Utils::vec4<glw::GLfloat>& out_combined_inverted, Utils::vec4<glw::GLfloat>& out_constant,
4626	Utils::vec4<glw::GLfloat>& out_constant_inverted, Utils::vec4<glw::GLfloat>& out_dynamic,
4627	Utils::vec4<glw::GLfloat>& out_dynamic_inverted, Utils::vec4<glw::GLfloat>& out_loop) const
4628{
4629	/* Indices used by "dynamic" operations, range <0..4> */
4630	const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y],
4631											combination[indices.m_z], combination[indices.m_w] };
4632
4633	/* Values used by "constant" operations, come from shader code */
4634	const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4),
4635														  Utils::vec4<glw::GLfloat>(-5, -6, -7, -8),
4636														  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
4640	/* Start values */
4641	Utils::vec4<glw::GLfloat> combined			= left;
4642	Utils::vec4<glw::GLfloat> combined_inverted = left;
4643	Utils::vec4<glw::GLfloat> constant			= constant_values[0];
4644	Utils::vec4<glw::GLfloat> constant_inverted = constant_values[0];
4645	Utils::vec4<glw::GLfloat> dynamic			= left;
4646	Utils::vec4<glw::GLfloat> dynamic_inverted  = left;
4647
4648	/* Calculate expected results */
4649	for (GLuint i = 0; i < 4; ++i)
4650	{
4651		GLuint function					 = combination[i];
4652		GLuint function_inverted		 = combination[3 - i];
4653		GLuint dynamic_function			 = dynamic_combination[i];
4654		GLuint dynamic_function_inverted = dynamic_combination[3 - i];
4655
4656		calculate(function, combined, right, combined);
4657		calculate(function_inverted, combined_inverted, right, combined_inverted);
4658		calculate(function, constant, constant_values[i + 1], constant);
4659		calculate(function_inverted, constant_inverted, constant_values[i + 1], constant_inverted);
4660		calculate(dynamic_function, dynamic, right, dynamic);
4661		calculate(dynamic_function_inverted, dynamic_inverted, right, dynamic_inverted);
4662	}
4663
4664	/* Store results */
4665	out_combined		  = combined;
4666	out_combined_inverted = combined_inverted;
4667	out_constant		  = constant;
4668	out_constant_inverted = constant_inverted;
4669	out_dynamic			  = dynamic;
4670	out_dynamic_inverted  = dynamic_inverted;
4671	out_loop			  = combined;
4672}
4673
4674/** Log error
4675 *
4676 * @param combination   Operations combination
4677 * @param left          Left operand
4678 * @param right         Right operand
4679 * @param indices       Inidices used by "dynamic" calls
4680 * @param vec4_expected Expected results
4681 * @param vec4_result   Results
4682 * @param array_length  Length of array
4683 * @param result        Comparison results
4684 **/
4685void FunctionalTest7_8::logError(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
4686								 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices,
4687								 const Utils::vec4<glw::GLfloat> vec4_expected[7],
4688								 const Utils::vec4<glw::GLfloat> vec4_result[7], glw::GLuint array_length,
4689								 bool result[7]) const
4690{
4691	static const GLuint n_functions  = 4;
4692	static const GLuint n_operations = 7;
4693
4694	/* Indices used by "dynamic" operations, range <0..4> */
4695	const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y],
4696											combination[indices.m_z], combination[indices.m_w] };
4697
4698	/* Function symbols */
4699	GLchar functions[4];
4700	GLchar functions_inverted[4];
4701	GLchar functions_dynamic[4];
4702	GLchar functions_dynamic_inverted[4];
4703
4704	for (GLuint i = 0; i < n_functions; ++i)
4705	{
4706		GLchar function			= (0 == combination[i]) ? '+' : '*';
4707		GLchar dynamic_function = (0 == dynamic_combination[i]) ? '+' : '*';
4708
4709		functions[i]									= function;
4710		functions_inverted[n_functions - i - 1]			= function;
4711		functions_dynamic[i]							= dynamic_function;
4712		functions_dynamic_inverted[n_functions - i - 1] = dynamic_function;
4713	}
4714
4715	/* Values used by "constant" operations, come from shader code */
4716	const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4),
4717														  Utils::vec4<glw::GLfloat>(-5, -6, -7, -8),
4718														  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
4722	/* Values used by non-"constant" operations */
4723	Utils::vec4<glw::GLfloat> dynamic_values[5];
4724	dynamic_values[0] = left;
4725	dynamic_values[1] = right;
4726	dynamic_values[2] = right;
4727	dynamic_values[3] = right;
4728	dynamic_values[4] = right;
4729
4730	/* For each operation */
4731	for (GLuint i = 0; i < n_operations; ++i)
4732	{
4733		/* If result is failure */
4734		if (false == result[i])
4735		{
4736			const GLchar*					 description = 0;
4737			const Utils::vec4<glw::GLfloat>* input		 = 0;
4738			const GLchar*					 operation   = 0;
4739
4740			switch (i)
4741			{
4742			case 0:
4743				description = "Call made with predefined array indices";
4744				input		= dynamic_values;
4745				operation   = functions;
4746				break;
4747			case 1:
4748				description = "Call made with predefined array indices in inverted order";
4749				input		= dynamic_values;
4750				operation   = functions_inverted;
4751				break;
4752			case 2:
4753				description = "Call made with predefined array indices, for constant values";
4754				input		= constant_values;
4755				operation   = functions;
4756				break;
4757			case 3:
4758				description = "Call made with predefined array indices in inverted order, for constant values";
4759				input		= constant_values;
4760				operation   = functions_inverted;
4761				break;
4762			case 4:
4763				description = "Call made with dynamic array indices";
4764				input		= dynamic_values;
4765				operation   = functions_dynamic;
4766				break;
4767			case 5:
4768				description = "Call made with dynamic array indices in inverted order";
4769				input		= dynamic_values;
4770				operation   = functions_dynamic_inverted;
4771				break;
4772			case 6:
4773				description = "Call made with loop";
4774				input		= dynamic_values;
4775				operation   = functions;
4776				break;
4777			}
4778
4779			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4780												<< tcu::TestLog::EndMessage;
4781
4782			m_context.getTestContext().getLog() << tcu::TestLog::Message << description << tcu::TestLog::EndMessage;
4783
4784			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4785
4786			message << "Operation: ((((";
4787			input[0].log(message);
4788			for (GLuint function = 0; function < n_functions; ++function)
4789			{
4790				message << " " << operation[function] << " ";
4791
4792				input[function + 1].log(message);
4793
4794				message << ")";
4795			}
4796
4797			message << tcu::TestLog::EndMessage;
4798
4799			message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4800
4801			message << "Result: ";
4802			vec4_result[i].log(message);
4803
4804			message << tcu::TestLog::EndMessage;
4805
4806			message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4807
4808			message << "Expected: ";
4809			vec4_expected[i].log(message);
4810
4811			message << tcu::TestLog::EndMessage;
4812		}
4813
4814		/* Check array length, it should be 4 */
4815		if (4 != array_length)
4816		{
4817			m_context.getTestContext().getLog() << tcu::TestLog::Message
4818												<< "Error. Invalid array length: " << array_length << ". Expected 4."
4819												<< tcu::TestLog::EndMessage;
4820		}
4821	}
4822}
4823
4824/** Execute draw call and verifies captrued varyings
4825 *
4826 * @param combination           Function combination, first applied function is at index [0]
4827 * @param left                  Left operand
4828 * @param right                 Right operand
4829 * @param indices               Indices used by dynamic calls
4830 *
4831 * @return true if all results match expected values, false otherwise
4832 **/
4833bool FunctionalTest7_8::testDraw(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
4834								 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices) const
4835{
4836	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
4837	static const GLuint   n_vec4_varyings = 7;
4838	bool				  result		  = true;
4839	GLuint				  subroutine_indices[4];
4840	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
4841
4842	/* Prepare expected results */
4843	Utils::vec4<glw::GLfloat> expected_results[7];
4844	calculate(combination, left, right, indices, expected_results[0], expected_results[1], expected_results[2],
4845			  expected_results[3], expected_results[4], expected_results[5], expected_results[6]);
4846
4847	/* Set up input data uniforms */
4848	gl.uniform4f(m_uniform_locations[0], left.m_x, left.m_y, left.m_z, left.m_w);
4849	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4850
4851	gl.uniform4f(m_uniform_locations[1], right.m_x, right.m_y, right.m_z, right.m_w);
4852	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4853
4854	gl.uniform4ui(m_uniform_locations[2], indices.m_x, indices.m_y, indices.m_z, indices.m_w);
4855	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4ui");
4856
4857	/* Prepare subroutine uniform data */
4858	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
4859	{
4860		const GLuint location = m_subroutine_uniform_locations[i];
4861
4862		subroutine_indices[location] = m_subroutine_indices[combination[i]];
4863	}
4864
4865	/* Set up subroutine uniforms */
4866	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
4867	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
4868
4869	/* Execute draw call with transform feedback */
4870	gl.beginTransformFeedback(GL_POINTS);
4871	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4872
4873	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4874	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4875
4876	gl.endTransformFeedback();
4877	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4878
4879	/* Capture results */
4880	GLvoid* feedback_data = (GLvoid*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4881	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4882
4883	Utils::vec4<GLfloat> vec4_results[7];
4884	bool				 results[7];
4885	GLfloat*			 float_data = (GLfloat*)feedback_data;
4886	for (GLuint i = 0; i < n_vec4_varyings; ++i)
4887	{
4888		vec4_results[i].m_x = float_data[i * 4 + 0];
4889		vec4_results[i].m_y = float_data[i * 4 + 1];
4890		vec4_results[i].m_z = float_data[i * 4 + 2];
4891		vec4_results[i].m_w = float_data[i * 4 + 3];
4892	}
4893
4894	GLuint* uint_data	= (GLuint*)(float_data + (n_vec4_varyings)*4);
4895	GLuint  array_length = uint_data[0];
4896
4897	/* Unmap buffer */
4898	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4899	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4900
4901	/* Verification */
4902	for (GLuint i = 0; i < n_vec4_varyings; ++i)
4903	{
4904		results[i] = (vec4_results[i] == expected_results[i]);
4905		result	 = result && results[i];
4906	}
4907
4908	result = result && (4 == array_length);
4909
4910	/* Log error if any */
4911	if (false == result)
4912	{
4913		logError(combination, left, right, indices, expected_results, vec4_results, array_length, results);
4914	}
4915
4916	/* Done */
4917	return result;
4918}
4919
4920/** Constructor.
4921 *
4922 *  @param context Rendering context.
4923 *
4924 **/
4925FunctionalTest9::FunctionalTest9(deqp::Context& context)
4926	: TestCase(context, "subroutines_3_subroutine_types_and_subroutine_uniforms_one_function",
4927			   "Makes sure that program with one function associated with 3 different "
4928			   "subroutine types and 3 subroutine uniforms using that function compiles "
4929			   "and works as expected")
4930	, m_has_test_passed(true)
4931	, m_n_points_to_draw(16) /* arbitrary value */
4932	, m_po_id(0)
4933	, m_vao_id(0)
4934	, m_vs_id(0)
4935	, m_xfb_bo_id(0)
4936{
4937	/* Left blank intentionally */
4938}
4939
4940/** De-initializes GL objects that may have been created during test execution. */
4941void FunctionalTest9::deinit()
4942{
4943	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4944
4945	if (m_po_id != 0)
4946	{
4947		gl.deleteProgram(m_po_id);
4948
4949		m_po_id = 0;
4950	}
4951
4952	if (m_vao_id != 0)
4953	{
4954		gl.deleteVertexArrays(1, &m_vao_id);
4955
4956		m_vao_id = 0;
4957	}
4958
4959	if (m_vs_id != 0)
4960	{
4961		gl.deleteShader(m_vs_id);
4962
4963		m_vs_id = 0;
4964	}
4965
4966	if (m_xfb_bo_id != 0)
4967	{
4968		gl.deleteBuffers(1, &m_xfb_bo_id);
4969
4970		m_xfb_bo_id = 0;
4971	}
4972}
4973
4974/** Retrieves body of a vertex shader that should be used
4975 *  for the testing purposes.
4976 **/
4977std::string FunctionalTest9::getVertexShaderBody() const
4978{
4979	return "#version 400\n"
4980		   "\n"
4981		   "#extension GL_ARB_shader_subroutine : require\n"
4982		   "\n"
4983		   "subroutine void subroutineType1(inout float);\n"
4984		   "subroutine void subroutineType2(inout float);\n"
4985		   "subroutine void subroutineType3(inout float);\n"
4986		   "\n"
4987		   "subroutine(subroutineType1, subroutineType2, subroutineType3) void function(inout float result)\n"
4988		   "{\n"
4989		   "    result += float(0.123) + float(gl_VertexID);\n"
4990		   "}\n"
4991		   "\n"
4992		   "subroutine uniform subroutineType1 subroutine_uniform1;\n"
4993		   "subroutine uniform subroutineType2 subroutine_uniform2;\n"
4994		   "subroutine uniform subroutineType3 subroutine_uniform3;\n"
4995		   "\n"
4996		   "out vec4 result;\n"
4997		   "\n"
4998		   "void main()\n"
4999		   "{\n"
5000		   "    result = vec4(0, 1, 2, 3);\n"
5001		   "\n"
5002		   "    subroutine_uniform1(result.x);\n"
5003		   "    subroutine_uniform2(result.y);\n"
5004		   "    subroutine_uniform3(result.z);\n"
5005		   "\n"
5006		   "    result.w += result.x + result.y + result.z;\n"
5007		   "}\n";
5008}
5009
5010/** Initializes all GL objects required to run the test. */
5011void FunctionalTest9::initTest()
5012{
5013	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5014
5015	/* Set up program object */
5016	const char* xfb_varyings[] = { "result" };
5017
5018	const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
5019	if (!Utils::buildProgram(gl, getVertexShaderBody(), "",					  /* tc_body */
5020							 "",											  /* te_body */
5021							 "",											  /* gs_body */
5022							 "",											  /* fs_body */
5023							 xfb_varyings, n_xfb_varyings, &m_vs_id, DE_NULL, /* out_tc_id */
5024							 DE_NULL,										  /* out_te_id */
5025							 DE_NULL,										  /* out_gs_id */
5026							 DE_NULL,										  /* out_fs_id */
5027							 &m_po_id))
5028	{
5029		TCU_FAIL("Program failed to link successfully");
5030	}
5031
5032	/* Set up a buffer object we will use to hold XFB data */
5033	const unsigned int xfb_bo_size = static_cast<unsigned int>(sizeof(float) * 4 /* components */ * m_n_points_to_draw);
5034
5035	gl.genBuffers(1, &m_xfb_bo_id);
5036	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
5037
5038	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
5039	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
5040
5041	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
5042	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
5043
5044	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL, /* data */
5045				  GL_STATIC_COPY);
5046	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
5047
5048	/* Generate & bind a VAO */
5049	gl.genVertexArrays(1, &m_vao_id);
5050	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
5051
5052	gl.bindVertexArray(m_vao_id);
5053	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
5054}
5055
5056/** Executes test iteration.
5057 *
5058 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
5059 */
5060tcu::TestNode::IterateResult FunctionalTest9::iterate()
5061{
5062	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5063
5064	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5065	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5066	{
5067		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5068	}
5069	initTest();
5070
5071	/* Issue a draw call to make use of the three subroutine uniforms that we've defined */
5072	gl.useProgram(m_po_id);
5073	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
5074
5075	gl.beginTransformFeedback(GL_POINTS);
5076	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
5077	{
5078		gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw);
5079		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
5080	}
5081	gl.endTransformFeedback();
5082	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
5083
5084	/* Map the XFB BO storage into process space */
5085	const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5086	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
5087
5088	verifyXFBData(xfb_data_ptr);
5089
5090	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5091	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
5092
5093	/* All done */
5094	if (m_has_test_passed)
5095	{
5096		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5097	}
5098	else
5099	{
5100		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5101	}
5102
5103	return STOP;
5104}
5105
5106/** Verifies the data XFBed out by the vertex shader. Should the data
5107 *  be found invalid, m_has_test_passed will be set to false.
5108 *
5109 *  @param data_ptr XFB data.
5110 **/
5111void FunctionalTest9::verifyXFBData(const glw::GLvoid* data_ptr)
5112{
5113	const float			epsilon			= 1e-5f;
5114	bool				should_continue = true;
5115	const glw::GLfloat* traveller_ptr   = (const glw::GLfloat*)data_ptr;
5116
5117	for (unsigned int n_point = 0; n_point < m_n_points_to_draw && should_continue; ++n_point)
5118	{
5119		tcu::Vec4 expected_result(0, 1, 2, 3);
5120
5121		for (unsigned int n_component = 0; n_component < 3 /* xyz */; ++n_component)
5122		{
5123			expected_result[n_component] += 0.123f + float(n_point);
5124		}
5125
5126		expected_result[3 /* w */] += expected_result[0] + expected_result[1] + expected_result[2];
5127
5128		if (de::abs(expected_result[0] - traveller_ptr[0]) > epsilon ||
5129			de::abs(expected_result[1] - traveller_ptr[1]) > epsilon ||
5130			de::abs(expected_result[2] - traveller_ptr[2]) > epsilon ||
5131			de::abs(expected_result[3] - traveller_ptr[3]) > epsilon)
5132		{
5133			m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data is invalid. Expected:"
5134														   "("
5135							   << expected_result[0] << ", " << expected_result[1] << ", " << expected_result[2] << ", "
5136							   << expected_result[3] << "), found:(" << traveller_ptr[0] << ", " << traveller_ptr[1]
5137							   << ", " << traveller_ptr[2] << ", " << traveller_ptr[3] << ")."
5138							   << tcu::TestLog::EndMessage;
5139
5140			m_has_test_passed = false;
5141			should_continue   = false;
5142		}
5143
5144		traveller_ptr += 4; /* xyzw */
5145	}						/* for (all rendered points) */
5146}
5147
5148/** Constructor
5149 *
5150 * @param context CTS context
5151 **/
5152FunctionalTest10::FunctionalTest10(deqp::Context& context)
5153	: TestCase(context, "arrays_of_arrays_of_uniforms", "Verify that arrays of arrays of uniforms works as expected")
5154{
5155}
5156
5157/** Execute test
5158 *
5159 * @return tcu::TestNode::STOP
5160 **/
5161tcu::TestNode::IterateResult FunctionalTest10::iterate()
5162{
5163	static const GLchar* vertex_shader_code = "#version 400 core\n"
5164											  "#extension GL_ARB_arrays_of_arrays  : require\n"
5165											  "#extension GL_ARB_shader_subroutine : require\n"
5166											  "\n"
5167											  "precision highp float;\n"
5168											  "\n"
5169											  "// Subroutine type\n"
5170											  "subroutine int routine_type(in int iparam);\n"
5171											  "\n"
5172											  "// Subroutine definitions\n"
5173											  "subroutine(routine_type) int increment(in int iparam)\n"
5174											  "{\n"
5175											  "    return iparam + 1;\n"
5176											  "}\n"
5177											  "\n"
5178											  "subroutine(routine_type) int decrement(in int iparam)\n"
5179											  "{\n"
5180											  "    return iparam - 1;\n"
5181											  "}\n"
5182											  "\n"
5183											  "// Sub routine uniform\n"
5184											  "subroutine uniform routine_type routine[4][4];\n"
5185											  "\n"
5186											  "// Output\n"
5187											  "out int out_result;\n"
5188											  "\n"
5189											  "void main()\n"
5190											  "{\n"
5191											  "    int result = 0;\n"
5192											  "    \n"
5193											  "    for (uint j = 0; j < routine.length(); ++j)\n"
5194											  "    {\n"
5195											  "        for (uint i = 0; i < routine[j].length(); ++i)\n"
5196											  "        {\n"
5197											  "            result = routine[j][i](result);\n"
5198											  "        }\n"
5199											  "    }\n"
5200											  "    \n"
5201											  "    out_result = result;\n"
5202											  "}\n"
5203											  "\n";
5204
5205	static const GLchar* subroutine_names[] = {
5206		"increment", "decrement",
5207	};
5208	static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
5209
5210	static const GLchar* subroutine_uniform_names[] = {
5211		"routine[0][0]", "routine[1][0]", "routine[2][0]", "routine[3][0]", "routine[0][1]", "routine[1][1]",
5212		"routine[2][1]", "routine[3][1]", "routine[0][2]", "routine[1][2]", "routine[2][2]", "routine[3][2]",
5213		"routine[0][3]", "routine[1][3]", "routine[2][3]", "routine[3][3]"
5214	};
5215	static const GLuint n_subroutine_uniform_names =
5216		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
5217
5218	static const GLchar* varying_name					= "out_result";
5219	static const GLuint  transform_feedback_buffer_size = sizeof(GLint);
5220
5221	static const GLuint configuration_increment[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5222
5223	static const GLuint configuration_decrement[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
5224
5225	static const GLuint configuration_mix[16] = { 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1 };
5226
5227	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5228	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5229	{
5230		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5231	}
5232
5233	/* Do not execute the test if GL_ARB_arrays_of_arrays is not supported */
5234	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_arrays_of_arrays"))
5235	{
5236		throw tcu::NotSupportedError("GL_ARB_arrays_of_arrays is not supported.");
5237	}
5238
5239	bool result = true;
5240
5241	/* GL objects */
5242	Utils::program	 program(m_context);
5243	Utils::buffer	  transform_feedback_buffer(m_context);
5244	Utils::vertexArray vao(m_context);
5245
5246	/* Init GL objects */
5247	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name,
5248				  1 /* n_varyings */);
5249
5250	program.use();
5251
5252	vao.generate();
5253	vao.bind();
5254
5255	transform_feedback_buffer.generate();
5256	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
5257									 GL_DYNAMIC_COPY);
5258	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
5259
5260	/* Get subroutine indices */
5261	for (GLuint routine = 0; routine < n_subroutine_names; ++routine)
5262	{
5263		m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER);
5264	}
5265
5266	/* Get subroutine uniform locations */
5267	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
5268	{
5269		m_subroutine_uniform_locations[uniform] =
5270			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
5271	}
5272
5273	/* Test */
5274	GLint increment_result = testDraw(configuration_increment);
5275	GLint decrement_result = testDraw(configuration_decrement);
5276	GLint mix_result	   = testDraw(configuration_mix);
5277
5278	/* Verify */
5279	if (16 != increment_result)
5280	{
5281		result = false;
5282	}
5283
5284	if (-16 != decrement_result)
5285	{
5286		result = false;
5287	}
5288	if (0 != mix_result)
5289	{
5290		result = false;
5291	}
5292
5293	/* Set test result */
5294	if (true == result)
5295	{
5296		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5297	}
5298	else
5299	{
5300		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
5301											<< " Incrementation applied 16 times: " << increment_result
5302											<< ". Decrementation applied 16 times: " << decrement_result
5303											<< ". Incrementation and decrementation applied 8 times: " << mix_result
5304											<< tcu::TestLog::EndMessage;
5305
5306		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5307	}
5308
5309	/* Done */
5310	return tcu::TestNode::STOP;
5311}
5312
5313/** Execute draw call and return captured varying
5314 *
5315 * @param routine_indices Configuration of subroutine uniforms
5316 *
5317 * @return Value of varying captured with transform feedback
5318 **/
5319GLint FunctionalTest10::testDraw(const GLuint routine_indices[16]) const
5320{
5321	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5322	GLuint				  subroutine_indices[16];
5323	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
5324
5325	/* Prepare subroutine uniform data */
5326	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
5327	{
5328		const GLuint location = m_subroutine_uniform_locations[i];
5329
5330		subroutine_indices[location] = m_subroutine_indices[routine_indices[i]];
5331	}
5332
5333	/* Set up subroutine uniforms */
5334	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
5335	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
5336
5337	/* Execute draw call with transform feedback */
5338	gl.beginTransformFeedback(GL_POINTS);
5339	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5340
5341	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5342	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5343
5344	gl.endTransformFeedback();
5345	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5346
5347	/* Capture results */
5348	GLint* feedback_data = (GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5349	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5350
5351	GLint result = feedback_data[0];
5352
5353	/* Unmap buffer */
5354	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5355	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5356
5357	return result;
5358}
5359
5360/* Definitions of constants used by FunctionalTest11 */
5361const GLuint FunctionalTest11::m_texture_height = 32;
5362const GLuint FunctionalTest11::m_texture_width  = 32;
5363
5364/** Constructor
5365 *
5366 * @param context CTS context
5367 **/
5368FunctionalTest11::FunctionalTest11(deqp::Context& context)
5369	: TestCase(context, "globals_sampling_output_discard_function_calls", "Verify that global variables, texture "
5370																		  "sampling, fragment output, fragment discard "
5371																		  "and function calls work as expected")
5372{
5373}
5374
5375/** Execute test
5376 *
5377 * @return tcu::TestNode::STOP
5378 **/
5379tcu::TestNode::IterateResult FunctionalTest11::iterate()
5380{
5381	static const GLchar* fragment_shader_code =
5382		"#version 400 core\n"
5383		"#extension GL_ARB_shader_subroutine : require\n"
5384		"\n"
5385		"precision highp float;\n"
5386		"\n"
5387		"// Output\n"
5388		"layout(location = 0) out vec4 out_color;\n"
5389		"\n"
5390		"// Global variables\n"
5391		"vec4 success_color;\n"
5392		"vec4 failure_color;\n"
5393		"\n"
5394		"// Samplers\n"
5395		"uniform sampler2D sampler_1;\n"
5396		"uniform sampler2D sampler_2;\n"
5397		"\n"
5398		"// Functions\n"
5399		"bool are_same(in vec4 left, in vec4 right)\n"
5400		"{\n"
5401		"    bvec4 result;\n"
5402		"\n"
5403		"    result.x = (left.x == right.x);\n"
5404		"    result.y = (left.y == right.y);\n"
5405		"    result.z = (left.z == right.z);\n"
5406		"    result.w = (left.w == right.w);\n"
5407		"\n"
5408		"    return all(result);\n"
5409		"}\n"
5410		"\n"
5411		"bool are_different(in vec4 left, in vec4 right)\n"
5412		"{\n"
5413		"    bvec4 result;\n"
5414		"\n"
5415		"    result.x = (left.x != right.x);\n"
5416		"    result.y = (left.y != right.y);\n"
5417		"    result.z = (left.z != right.z);\n"
5418		"    result.w = (left.w != right.w);\n"
5419		"\n"
5420		"    return any(result);\n"
5421		"}\n"
5422		"\n"
5423		"// Subroutine types\n"
5424		"subroutine void discard_fragment_type(void);\n"
5425		"subroutine void set_global_colors_type(void);\n"
5426		"subroutine vec4 sample_texture_type(in vec2);\n"
5427		"subroutine bool comparison_type(in vec4 left, in vec4 right);\n"
5428		"subroutine void test_type(void);\n"
5429		"\n"
5430		"// Subroutine definitions\n"
5431		"// discard_fragment_type\n"
5432		"subroutine(discard_fragment_type) void discard_yes(void)\n"
5433		"{\n"
5434		"    discard;\n"
5435		"}\n"
5436		"\n"
5437		"subroutine(discard_fragment_type) void discard_no(void)\n"
5438		"{\n"
5439		"}\n"
5440		"\n"
5441		"// set_global_colors_type\n"
5442		"subroutine(set_global_colors_type) void red_pass_blue_fail(void)\n"
5443		"{\n"
5444		"    success_color = vec4(1, 0, 0, 1);\n"
5445		"    failure_color = vec4(0, 0, 1, 1);\n"
5446		"}\n"
5447		"\n"
5448		"subroutine(set_global_colors_type) void blue_pass_red_fail(void)\n"
5449		"{\n"
5450		"    success_color = vec4(0, 0, 1, 1);\n"
5451		"    failure_color = vec4(1, 0, 0, 1);\n"
5452		"}\n"
5453		"\n"
5454		"// sample_texture_type\n"
5455		"subroutine(sample_texture_type) vec4 first_sampler(in vec2 coord)\n"
5456		"{\n"
5457		"    return texture(sampler_1, coord);\n"
5458		"}\n"
5459		"\n"
5460		"subroutine(sample_texture_type) vec4 second_sampler(in vec2 coord)\n"
5461		"{\n"
5462		"    return texture(sampler_2, coord);\n"
5463		"}\n"
5464		"\n"
5465		"// comparison_type\n"
5466		"subroutine(comparison_type) bool check_equal(in vec4 left, in vec4 right)\n"
5467		"{\n"
5468		"    return are_same(left, right);\n"
5469		"}\n"
5470		"\n"
5471		"subroutine(comparison_type) bool check_not_equal(in vec4 left, in vec4 right)\n"
5472		"{\n"
5473		"    return are_different(left, right);\n"
5474		"}\n"
5475		"\n"
5476		"// Subroutine uniforms\n"
5477		"subroutine uniform discard_fragment_type  discard_fragment;\n"
5478		"subroutine uniform set_global_colors_type set_global_colors;\n"
5479		"subroutine uniform sample_texture_type    sample_texture;\n"
5480		"subroutine uniform comparison_type        compare;\n"
5481		"\n"
5482		"// Subroutine definitions\n"
5483		"// test_type\n"
5484		"subroutine(test_type) void test_with_discard(void)\n"
5485		"{\n"
5486		"    discard_fragment();"
5487		"\n"
5488		"    out_color = failure_color;\n"
5489		"\n"
5490		"    set_global_colors();\n"
5491		"\n"
5492		"    vec4 sampled_color = sample_texture(gl_PointCoord);\n"
5493		"\n"
5494		"    bool comparison_result = compare(success_color, sampled_color);\n"
5495		"\n"
5496		"    if (true == comparison_result)\n"
5497		"    {\n"
5498		"        out_color = success_color;\n"
5499		"    }\n"
5500		"    else\n"
5501		"    {\n"
5502		"        out_color = failure_color;\n"
5503		"    }\n"
5504		"}\n"
5505		"\n"
5506		"subroutine(test_type) void test_without_discard(void)\n"
5507		"{\n"
5508		"    set_global_colors();\n"
5509		"\n"
5510		"    vec4 sampled_color = sample_texture(gl_PointCoord);\n"
5511		"\n"
5512		"    bool comparison_result = compare(success_color, sampled_color);\n"
5513		"\n"
5514		"    if (true == comparison_result)\n"
5515		"    {\n"
5516		"        out_color = success_color;\n"
5517		"    }\n"
5518		"    else\n"
5519		"    {\n"
5520		"        out_color = failure_color;\n"
5521		"    }\n"
5522		"}\n"
5523		"\n"
5524		"// Subroutine uniforms\n"
5525		"subroutine uniform test_type test;\n"
5526		"\n"
5527		"void main()\n"
5528		"{\n"
5529		"    // Set colors\n"
5530		"    success_color = vec4(0.5, 0.5, 0.5, 0.5);\n"
5531		"    failure_color = vec4(0.5, 0.5, 0.5, 0.5);\n"
5532		"\n"
5533		"    test();\n"
5534		"}\n"
5535		"\n";
5536
5537	static const GLchar* geometry_shader_code = "#version 400 core\n"
5538												"#extension GL_ARB_shader_subroutine : require\n"
5539												"\n"
5540												"precision highp float;\n"
5541												"\n"
5542												"layout(points)                           in;\n"
5543												"layout(triangle_strip, max_vertices = 4) out;\n"
5544												"\n"
5545												"void main()\n"
5546												"{\n"
5547												"    gl_Position = vec4(-1, -1, 0, 1);\n"
5548												"    EmitVertex();\n"
5549												"    \n"
5550												"    gl_Position = vec4(-1,  1, 0, 1);\n"
5551												"    EmitVertex();\n"
5552												"    \n"
5553												"    gl_Position = vec4( 1, -1, 0, 1);\n"
5554												"    EmitVertex();\n"
5555												"    \n"
5556												"    gl_Position = vec4( 1,  1, 0, 1);\n"
5557												"    EmitVertex();\n"
5558												"    \n"
5559												"    EndPrimitive();\n"
5560												"}\n"
5561												"\n";
5562
5563	static const GLchar* vertex_shader_code = "#version 400 core\n"
5564											  "#extension GL_ARB_shader_subroutine : require\n"
5565											  "\n"
5566											  "precision highp float;\n"
5567											  "\n"
5568											  "void main()\n"
5569											  "{\n"
5570											  "}\n"
5571											  "\n";
5572
5573	static const GLchar* subroutine_names[][2] = { { "discard_yes", "discard_no" },
5574												   { "red_pass_blue_fail", "blue_pass_red_fail" },
5575												   { "first_sampler", "second_sampler" },
5576												   { "check_equal", "check_not_equal" },
5577												   { "test_with_discard", "test_without_discard" } };
5578	static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
5579
5580	static const GLchar* subroutine_uniform_names[] = { "discard_fragment", "set_global_colors", "sample_texture",
5581														"compare", "test" };
5582	static const GLuint n_subroutine_uniform_names =
5583		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
5584
5585	static const GLchar* uniform_names[] = {
5586		"sampler_1", "sampler_2",
5587	};
5588	static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
5589
5590	/* Colors */
5591	static const GLubyte blue_color[4]  = { 0, 0, 255, 255 };
5592	static const GLubyte clean_color[4] = { 0, 0, 0, 0 };
5593	static const GLubyte red_color[4]   = { 255, 0, 0, 255 };
5594
5595	/* Configurations */
5596	static const testConfiguration test_configurations[] = {
5597		testConfiguration(
5598			"Expect red color from 1st sampler", red_color, 1 /* discard_fragment  : discard_no         */,
5599			0 /* set_global_colors : red_pass_blue_fail */, 0 /* sample_texture    : first_sampler      */,
5600			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */, 1 /* red */,
5601			0 /* blue */),
5602
5603		testConfiguration(
5604			"Test \"without discard\" option, expect no blue color from 2nd sampler", blue_color,
5605			0 /* discard_fragment  : discard_yes           */, 1 /* set_global_colors : blue_pass_red_fail    */,
5606			1 /* sample_texture    : second_sampler        */, 1 /* compare           : check_not_equal       */,
5607			1 /* test              : test_without_discard  */, 0 /* blue */, 1 /* red */),
5608
5609		testConfiguration("Fragment shoud be discarded", clean_color, 0 /* discard_fragment  : discard_yes        */,
5610						  0 /* set_global_colors : red_pass_blue_fail */,
5611						  0 /* sample_texture    : first_sampler      */,
5612						  0 /* compare           : check_equal        */,
5613						  0 /* test              : test_with_discard  */, 1 /* red */, 0 /* blue */),
5614
5615		testConfiguration(
5616			"Expect blue color from 1st sampler", blue_color, 1 /* discard_fragment  : discard_no         */,
5617			1 /* set_global_colors : blue_pass_red_fail */, 0 /* sample_texture    : first_sampler      */,
5618			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */,
5619			0 /* blue */, 1 /* red */),
5620
5621		testConfiguration(
5622			"Expect red color from 2nd sampler", red_color, 1 /* discard_fragment  : discard_no         */,
5623			0 /* set_global_colors : red_pass_blue_fail */, 1 /* sample_texture    : second_sampler     */,
5624			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */,
5625			0 /* blue */, 1 /* red */),
5626
5627		testConfiguration(
5628			"Expect no blue color from 2nd sampler", blue_color, 1 /* discard_fragment  : discard_no         */,
5629			1 /* set_global_colors : blue_pass_red_fail */, 1 /* sample_texture    : second_sampler     */,
5630			1 /* compare           : check_not_equal    */, 0 /* test              : test_with_discard  */,
5631			0 /* blue */, 1 /* red */),
5632	};
5633	static const GLuint n_test_cases = sizeof(test_configurations) / sizeof(test_configurations[0]);
5634
5635	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5636	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5637	{
5638		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5639	}
5640
5641	/* GL objects */
5642	Utils::texture	 blue_texture(m_context);
5643	Utils::texture	 color_texture(m_context);
5644	Utils::framebuffer framebuffer(m_context);
5645	Utils::program	 program(m_context);
5646	Utils::texture	 red_texture(m_context);
5647	Utils::vertexArray vao(m_context);
5648
5649	/* Init GL objects */
5650	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
5651				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
5652
5653	program.use();
5654
5655	vao.generate();
5656	vao.bind();
5657
5658	blue_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5659	color_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5660	red_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5661
5662	framebuffer.generate();
5663	framebuffer.bind();
5664	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
5665
5666	/* Get subroutine indices */
5667	for (GLuint type = 0; type < n_subroutine_types; ++type)
5668	{
5669		m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_FRAGMENT_SHADER);
5670		m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_FRAGMENT_SHADER);
5671	}
5672
5673	/* Get subroutine uniform locations */
5674	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
5675	{
5676		m_subroutine_uniform_locations[uniform] =
5677			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_FRAGMENT_SHADER);
5678	}
5679
5680	/* Get uniform locations */
5681	for (GLuint i = 0; i < n_uniform_names; ++i)
5682	{
5683		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
5684	}
5685
5686	/* Prepare textures */
5687	fillTexture(blue_texture, blue_color);
5688	fillTexture(color_texture, clean_color);
5689	fillTexture(red_texture, red_color);
5690
5691	m_source_textures[0] = blue_texture.m_id;
5692	m_source_textures[1] = red_texture.m_id;
5693
5694	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
5695
5696	/* Test */
5697	bool result = true;
5698	for (GLuint i = 0; i < n_test_cases; ++i)
5699	{
5700		/* Clean output texture */
5701		framebuffer.clear(GL_COLOR_BUFFER_BIT);
5702
5703		/* Execute test */
5704		if (false == testDraw(test_configurations[i].m_routines, test_configurations[i].m_samplers,
5705							  test_configurations[i].m_expected_color, color_texture))
5706		{
5707			m_context.getTestContext().getLog()
5708				<< tcu::TestLog::Message << "Error. Failure for configuration: " << test_configurations[i].m_description
5709				<< tcu::TestLog::EndMessage;
5710
5711			result = false;
5712		}
5713	}
5714
5715	/* Set result */
5716	if (true == result)
5717	{
5718		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5719	}
5720	else
5721	{
5722		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5723	}
5724
5725	/* Done */
5726	return tcu::TestNode::STOP;
5727}
5728
5729/** Fill texture with specified color
5730 *
5731 * @param texture Texture instance
5732 * @param color   Color
5733 **/
5734void FunctionalTest11::fillTexture(Utils::texture& texture, const glw::GLubyte color[4]) const
5735{
5736	std::vector<GLubyte> texture_data;
5737
5738	/* Prepare texture data */
5739	texture_data.resize(m_texture_width * m_texture_height * 4);
5740
5741	for (GLuint y = 0; y < m_texture_height; ++y)
5742	{
5743		const GLuint line_offset = y * m_texture_width * 4;
5744
5745		for (GLuint x = 0; x < m_texture_width; ++x)
5746		{
5747			const GLuint point_offset = x * 4 + line_offset;
5748
5749			texture_data[point_offset + 0] = color[0]; /* red */
5750			texture_data[point_offset + 1] = color[1]; /* green */
5751			texture_data[point_offset + 2] = color[2]; /* blue */
5752			texture_data[point_offset + 3] = color[3]; /* alpha */
5753		}
5754	}
5755
5756	texture.update(m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
5757}
5758
5759/** Execute draw call and verify results
5760 *
5761 * @param routine_configuration Configurations of routines to be used
5762 * @param sampler_configuration Configuration of textures to be bound to samplers
5763 * @param expected_color        Expected color of result image
5764 *
5765 * @return true if result image is filled with expected color, false otherwise
5766 **/
5767bool FunctionalTest11::testDraw(const glw::GLuint routine_configuration[5], const glw::GLuint sampler_configuration[2],
5768								const glw::GLubyte expected_color[4], Utils::texture& color_texture) const
5769{
5770	const glw::Functions& gl					= m_context.getRenderContext().getFunctions();
5771	static const GLint	n_samplers			= 2;
5772	static const GLint	n_subroutine_uniforms = 5;
5773	GLuint				  subroutine_indices[5];
5774
5775	/* Set samplers */
5776	for (GLuint i = 0; i < n_samplers; ++i)
5777	{
5778		const GLuint location = m_uniform_locations[i];
5779		const GLuint texture  = m_source_textures[sampler_configuration[i]];
5780
5781		gl.activeTexture(GL_TEXTURE0 + i);
5782		GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
5783
5784		gl.bindTexture(GL_TEXTURE_2D, texture);
5785		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5786
5787		gl.uniform1i(location, i);
5788		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
5789	}
5790
5791	gl.activeTexture(GL_TEXTURE0 + 0);
5792
5793	/* Set subroutine uniforms */
5794	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
5795	{
5796		const GLuint location = m_subroutine_uniform_locations[i];
5797		const GLuint routine  = routine_configuration[i];
5798
5799		subroutine_indices[location] = m_subroutine_indices[i][routine];
5800	}
5801
5802	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 5, subroutine_indices);
5803	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
5804
5805	/* Draw */
5806	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5807	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5808
5809	/* Capture result */
5810	std::vector<GLubyte> captured_data;
5811	captured_data.resize(m_texture_width * m_texture_height * 4);
5812
5813	color_texture.get(GL_RGBA, GL_UNSIGNED_BYTE, &captured_data[0]);
5814
5815	/* Verify result */
5816	for (GLuint y = 0; y < m_texture_height; ++y)
5817	{
5818		const GLuint line_offset = y * m_texture_width * 4;
5819
5820		for (GLuint x = 0; x < m_texture_width; ++x)
5821		{
5822			const GLuint point_offset   = x * 4 + line_offset;
5823			bool		 is_as_expected = true;
5824
5825			is_as_expected = is_as_expected && (expected_color[0] == captured_data[point_offset + 0]); /* red */
5826			is_as_expected = is_as_expected && (expected_color[1] == captured_data[point_offset + 1]); /* green */
5827			is_as_expected = is_as_expected && (expected_color[2] == captured_data[point_offset + 2]); /* blue */
5828			is_as_expected = is_as_expected && (expected_color[3] == captured_data[point_offset + 3]); /* alpha */
5829
5830			if (false == is_as_expected)
5831			{
5832				return false;
5833			}
5834		}
5835	}
5836
5837	/* Done */
5838	return true;
5839}
5840
5841/* Constatns used by FunctionalTest12 */
5842const glw::GLuint FunctionalTest12::m_texture_height = 16;
5843const glw::GLuint FunctionalTest12::m_texture_width  = 16;
5844
5845/** Constructor
5846 *
5847 * @param context CTS context
5848 **/
5849FunctionalTest12::FunctionalTest12(deqp::Context& context)
5850	: TestCase(context, "ssbo_atomic_image_load_store",
5851			   "Verify that SSBO, atomic counters and image load store work as expected")
5852	, m_left_image(0)
5853	, m_right_image(0)
5854{
5855}
5856
5857/** Execute test
5858 *
5859 * @return tcu::TestNode::STOP
5860 **/
5861tcu::TestNode::IterateResult FunctionalTest12::iterate()
5862{
5863	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5864	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5865	{
5866		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5867	}
5868
5869	bool result = true;
5870
5871	/* Test atomic counters */
5872	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
5873	{
5874		if (false == testAtomic())
5875		{
5876			result = false;
5877		}
5878	}
5879
5880	/* Test shader storage buffer */
5881	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_storage_buffer_object"))
5882	{
5883		if (false == testSSBO())
5884		{
5885			result = false;
5886		}
5887	}
5888
5889	/* Test image load store */
5890	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_image_load_store"))
5891	{
5892		if (false == testImage())
5893		{
5894			result = false;
5895		}
5896	}
5897
5898	/* Set result */
5899	if (true == result)
5900	{
5901		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5902	}
5903	else
5904	{
5905		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5906	}
5907
5908	/* Done */
5909	return tcu::TestNode::STOP;
5910}
5911
5912/** Fill texture with specified color
5913 *
5914 * @param texture Texture instance
5915 * @param color   Color
5916 **/
5917void FunctionalTest12::fillTexture(Utils::texture& texture, const glw::GLuint color[4]) const
5918{
5919	std::vector<GLuint> texture_data;
5920
5921	/* Prepare texture data */
5922	texture_data.resize(m_texture_width * m_texture_height * 4);
5923
5924	for (GLuint y = 0; y < m_texture_height; ++y)
5925	{
5926		const GLuint line_offset = y * m_texture_width * 4;
5927
5928		for (GLuint x = 0; x < m_texture_width; ++x)
5929		{
5930			const GLuint point_offset = x * 4 + line_offset;
5931
5932			texture_data[point_offset + 0] = color[0]; /* red */
5933			texture_data[point_offset + 1] = color[1]; /* green */
5934			texture_data[point_offset + 2] = color[2]; /* blue */
5935			texture_data[point_offset + 3] = color[3]; /* alpha */
5936		}
5937	}
5938
5939	texture.update(m_texture_width, m_texture_height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &texture_data[0]);
5940}
5941
5942/** Test atomic counters
5943 *
5944 * @return true if test pass, false otherwise
5945 **/
5946bool FunctionalTest12::testAtomic()
5947{
5948	static const GLchar* fragment_shader_code = "#version 410 core\n"
5949												"#extension GL_ARB_shader_atomic_counters : require\n"
5950												"#extension GL_ARB_shader_subroutine      : require\n"
5951												"\n"
5952												"precision highp float;\n"
5953												"\n"
5954												"layout(location = 0) out uint out_color;\n"
5955												"\n"
5956												"layout(binding = 0, offset = 8) uniform atomic_uint one;\n"
5957												"layout(binding = 0, offset = 4) uniform atomic_uint two;\n"
5958												"layout(binding = 0, offset = 0) uniform atomic_uint three;\n"
5959												"\n"
5960												"subroutine void atomic_routine(void)\n;"
5961												"\n"
5962												"subroutine(atomic_routine) void increment_two(void)\n"
5963												"{\n"
5964												"    out_color = atomicCounterIncrement(two);\n"
5965												"}\n"
5966												"\n"
5967												"subroutine(atomic_routine) void decrement_three(void)\n"
5968												"{\n"
5969												"    out_color = atomicCounterDecrement(three);\n"
5970												"}\n"
5971												"\n"
5972												"subroutine(atomic_routine) void read_one(void)\n"
5973												"{\n"
5974												"    out_color = atomicCounter(one);\n"
5975												"}\n"
5976												"\n"
5977												"subroutine uniform atomic_routine routine;\n"
5978												"\n"
5979												"void main()\n"
5980												"{\n"
5981												"    routine();\n"
5982												"}\n"
5983												"\n";
5984
5985	static const GLchar* geometry_shader_code = "#version 400 core\n"
5986												"#extension GL_ARB_shader_subroutine : require\n"
5987												"\n"
5988												"precision highp float;\n"
5989												"\n"
5990												"layout(points)                           in;\n"
5991												"layout(triangle_strip, max_vertices = 4) out;\n"
5992												"\n"
5993												"void main()\n"
5994												"{\n"
5995												"    gl_Position = vec4(-1, -1, 0, 1);\n"
5996												"    EmitVertex();\n"
5997												"    \n"
5998												"    gl_Position = vec4(-1,  1, 0, 1);\n"
5999												"    EmitVertex();\n"
6000												"    \n"
6001												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6002												"    EmitVertex();\n"
6003												"    \n"
6004												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6005												"    EmitVertex();\n"
6006												"    \n"
6007												"    EndPrimitive();\n"
6008												"}\n"
6009												"\n";
6010
6011	static const GLchar* vertex_shader_code = "#version 400 core\n"
6012											  "#extension GL_ARB_shader_subroutine : require\n"
6013											  "\n"
6014											  "precision highp float;\n"
6015											  "\n"
6016											  "void main()\n"
6017											  "{\n"
6018											  "}\n"
6019											  "\n";
6020
6021	static const GLchar* subroutine_names[] = { "increment_two", "decrement_three", "read_one" };
6022
6023	/* Test data */
6024	static const glw::GLuint atomic_buffer_data[] = { m_texture_width * m_texture_height,
6025													  m_texture_width * m_texture_height,
6026													  m_texture_width * m_texture_height };
6027
6028	static const glw::GLuint expected_incremented_two[] = { atomic_buffer_data[0], 2 * atomic_buffer_data[1],
6029															atomic_buffer_data[2] };
6030
6031	static const glw::GLuint expected_decremented_three[] = { 0, expected_incremented_two[1],
6032															  expected_incremented_two[2] };
6033
6034	static const glw::GLuint expected_read_one[] = { expected_decremented_three[0], expected_decremented_three[1],
6035													 expected_decremented_three[2] };
6036
6037	/* GL objects */
6038	Utils::buffer	  atomic_buffer(m_context);
6039	Utils::texture	 color_texture(m_context);
6040	Utils::framebuffer framebuffer(m_context);
6041	Utils::program	 program(m_context);
6042	Utils::vertexArray vao(m_context);
6043
6044	/* Init GL objects */
6045	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6046				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6047
6048	program.use();
6049
6050	vao.generate();
6051	vao.bind();
6052
6053	color_texture.create(m_texture_width, m_texture_height, GL_R32UI);
6054
6055	atomic_buffer.generate();
6056	atomic_buffer.update(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomic_buffer_data), (GLvoid*)atomic_buffer_data,
6057						 GL_STATIC_DRAW);
6058	atomic_buffer.bindRange(GL_ATOMIC_COUNTER_BUFFER, 0 /* index */, 0 /* offset */, sizeof(atomic_buffer_data));
6059
6060	framebuffer.generate();
6061	framebuffer.bind();
6062	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6063	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6064	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6065
6066	/* Subroutine indices */
6067	GLuint increment_two   = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6068	GLuint decrement_three = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6069	GLuint read_one		   = program.getSubroutineIndex(subroutine_names[2], GL_FRAGMENT_SHADER);
6070
6071	/* Test */
6072	bool result = true;
6073
6074	if (false == testAtomicDraw(increment_two, expected_incremented_two))
6075	{
6076		result = false;
6077	}
6078
6079	if (false == testAtomicDraw(decrement_three, expected_decremented_three))
6080	{
6081		result = false;
6082	}
6083
6084	if (false == testAtomicDraw(read_one, expected_read_one))
6085	{
6086		result = false;
6087	}
6088
6089	/* Done */
6090	return result;
6091}
6092
6093/** Execture draw call and verify results
6094 *
6095 * @param subroutine_index Index of subroutine that shall be used during draw call
6096 * @param expected_results Expected results
6097 *
6098 * @return true if results are as expected, false otherwise
6099 **/
6100bool FunctionalTest12::testAtomicDraw(GLuint subroutine_index, const GLuint expected_results[3]) const
6101{
6102	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6103
6104	/* Set subroutine uniforms */
6105	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6106	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6107
6108	/* Draw */
6109	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6110	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6111
6112	/* Capture results */
6113	GLuint* atomic_results = (GLuint*)gl.mapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY);
6114	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
6115
6116	/* Verify */
6117	bool result = (0 == memcmp(expected_results, atomic_results, 3 * sizeof(GLuint)));
6118
6119	if (false == result)
6120	{
6121		m_context.getTestContext().getLog()
6122			<< tcu::TestLog::Message << "Error. Invalid result. "
6123			<< "Result: [ " << atomic_results[0] << ", " << atomic_results[1] << ", " << atomic_results[2] << " ] "
6124			<< "Expected: [ " << expected_results[0] << ", " << expected_results[1] << ", " << expected_results[2]
6125			<< " ]" << tcu::TestLog::EndMessage;
6126	}
6127
6128	/* Unmap buffer */
6129	gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
6130	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
6131
6132	/* Done */
6133	return result;
6134}
6135
6136/** Test image load store
6137 *
6138 * @return true if test pass, false otherwise
6139 **/
6140bool FunctionalTest12::testImage()
6141{
6142	static const GLchar* fragment_shader_code =
6143		"#version 400 core\n"
6144		"#extension GL_ARB_shader_image_load_store : require\n"
6145		"#extension GL_ARB_shader_subroutine       : require\n"
6146		"\n"
6147		"precision highp float;\n"
6148		"\n"
6149		"layout(location = 0) out uvec4 out_color;\n"
6150		"\n"
6151		"layout(rgba32ui) uniform uimage2D left_image;\n"
6152		"layout(rgba32ui) uniform uimage2D right_image;\n"
6153		"\n"
6154		"subroutine void image_routine(void);\n"
6155		"\n"
6156		"subroutine(image_routine) void left_to_right(void)\n"
6157		"{\n"
6158		"    out_color = imageLoad (left_image,  ivec2(gl_FragCoord.xy));\n"
6159		"                imageStore(right_image, ivec2(gl_FragCoord.xy), out_color);\n"
6160		"}\n"
6161		"\n"
6162		"subroutine(image_routine) void right_to_left(void)\n"
6163		"{\n"
6164		"    out_color = imageLoad (right_image, ivec2(gl_FragCoord.xy));\n"
6165		"                imageStore(left_image,  ivec2(gl_FragCoord.xy), out_color);\n"
6166		"}\n"
6167		"\n"
6168		"subroutine uniform image_routine routine;\n"
6169		"\n"
6170		"void main()\n"
6171		"{\n"
6172		"    routine();\n"
6173		"}\n"
6174		"\n";
6175
6176	static const GLchar* geometry_shader_code = "#version 400 core\n"
6177												"#extension GL_ARB_shader_subroutine : require\n"
6178												"\n"
6179												"precision highp float;\n"
6180												"\n"
6181												"layout(points)                           in;\n"
6182												"layout(triangle_strip, max_vertices = 4) out;\n"
6183												"\n"
6184												"void main()\n"
6185												"{\n"
6186												"    gl_Position = vec4(-1, -1, 0, 1);\n"
6187												"    EmitVertex();\n"
6188												"    \n"
6189												"    gl_Position = vec4(-1,  1, 0, 1);\n"
6190												"    EmitVertex();\n"
6191												"    \n"
6192												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6193												"    EmitVertex();\n"
6194												"    \n"
6195												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6196												"    EmitVertex();\n"
6197												"    \n"
6198												"    EndPrimitive();\n"
6199												"}\n"
6200												"\n";
6201
6202	static const GLchar* vertex_shader_code = "#version 400 core\n"
6203											  "#extension GL_ARB_shader_subroutine : require\n"
6204											  "\n"
6205											  "precision highp float;\n"
6206											  "\n"
6207											  "void main()\n"
6208											  "{\n"
6209											  "}\n"
6210											  "\n";
6211
6212	static const GLchar* subroutine_names[] = { "left_to_right", "right_to_left" };
6213
6214	static const GLchar* uniform_names[] = { "left_image", "right_image" };
6215
6216	/* Test data */
6217	static const GLuint blue_color[4]  = { 0, 0, 255, 255 };
6218	static const GLuint clean_color[4] = { 16, 32, 64, 128 };
6219	static const GLuint red_color[4]   = { 255, 0, 0, 255 };
6220
6221	/* GL objects */
6222	Utils::texture	 blue_texture(m_context);
6223	Utils::texture	 destination_texture(m_context);
6224	Utils::texture	 color_texture(m_context);
6225	Utils::framebuffer framebuffer(m_context);
6226	Utils::program	 program(m_context);
6227	Utils::texture	 red_texture(m_context);
6228	Utils::vertexArray vao(m_context);
6229
6230	/* Init GL objects */
6231	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6232				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6233
6234	program.use();
6235
6236	vao.generate();
6237	vao.bind();
6238
6239	blue_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6240	destination_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6241	color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6242	red_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6243
6244	fillTexture(blue_texture, blue_color);
6245	fillTexture(destination_texture, clean_color);
6246	fillTexture(red_texture, red_color);
6247
6248	framebuffer.generate();
6249	framebuffer.bind();
6250	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6251	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6252	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6253
6254	/* Subroutine indices */
6255	GLuint left_to_right = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6256	GLuint right_to_left = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6257
6258	/* Uniform locations */
6259	m_left_image  = program.getUniformLocation(uniform_names[0]);
6260	m_right_image = program.getUniformLocation(uniform_names[1]);
6261
6262	/* Test */
6263	bool result = true;
6264
6265	if (false == testImageDraw(left_to_right, blue_texture, destination_texture, blue_color, blue_color))
6266	{
6267		result = false;
6268	}
6269
6270	if (false == testImageDraw(left_to_right, red_texture, destination_texture, red_color, red_color))
6271	{
6272		result = false;
6273	}
6274
6275	if (false == testImageDraw(right_to_left, destination_texture, blue_texture, blue_color, blue_color))
6276	{
6277		result = false;
6278	}
6279
6280	if (false == testImageDraw(right_to_left, destination_texture, red_texture, red_color, red_color))
6281	{
6282		result = false;
6283	}
6284
6285	if (false == testImageDraw(left_to_right, blue_texture, red_texture, blue_color, blue_color))
6286	{
6287		result = false;
6288	}
6289
6290	/* Done */
6291	return result;
6292}
6293
6294/** Execute draw call and verifies results
6295 *
6296 * @param subroutine_index     Index of subroutine that shall be used during draw call
6297 * @param left                 "Left" texture
6298 * @param right                "Right" texture
6299 * @param expected_left_color  Expected color of "left" texture
6300 * @param expected_right_color Expected color of "right" texture
6301 *
6302 * @return true if verification result is positive, false otherwise
6303 **/
6304bool FunctionalTest12::testImageDraw(GLuint subroutine_index, Utils::texture& left, Utils::texture& right,
6305									 const GLuint expected_left_color[4], const GLuint expected_right_color[4]) const
6306{
6307	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6308
6309	/* Set subroutine uniforms */
6310	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6311	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6312
6313	/* Set up image units */
6314	gl.uniform1i(m_left_image, 0);
6315	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
6316
6317	gl.uniform1i(m_right_image, 1);
6318	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
6319
6320	gl.bindImageTexture(0, left.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
6321	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6322
6323	gl.bindImageTexture(1, right.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
6324	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6325
6326	/* Draw */
6327	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6328	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6329
6330	/* Verify results */
6331	bool result = true;
6332
6333	if (false == verifyTexture(left, expected_left_color))
6334	{
6335		m_context.getTestContext().getLog() << tcu::TestLog::Message
6336											<< "Error. Invalid result. Left texture is filled with wrong color."
6337											<< tcu::TestLog::EndMessage;
6338		result = false;
6339	}
6340
6341	if (false == verifyTexture(right, expected_right_color))
6342	{
6343		m_context.getTestContext().getLog() << tcu::TestLog::Message
6344											<< "Error. Invalid result. Right texture is filled with wrong color."
6345											<< tcu::TestLog::EndMessage;
6346		result = false;
6347	}
6348
6349	/* Done */
6350	return result;
6351}
6352
6353/** Test shader storage buffer
6354 *
6355 * @return true if test pass, false otherwise
6356 **/
6357bool FunctionalTest12::testSSBO()
6358{
6359	static const GLchar* fragment_shader_code = "#version 400 core\n"
6360												"#extension GL_ARB_shader_storage_buffer_object : require\n"
6361												"#extension GL_ARB_shader_subroutine            : require\n"
6362												"\n"
6363												"precision highp float;\n"
6364												"\n"
6365												"layout(location = 0) out uvec4 out_color;\n"
6366												"\n"
6367												"layout(std140, binding = 0) buffer Buffer\n"
6368												"{\n"
6369												"    uvec4 entry;\n"
6370												"};\n"
6371												"\n"
6372												"subroutine void ssbo_routine(void)\n;"
6373												"\n"
6374												"subroutine(ssbo_routine) void increment(void)\n"
6375												"{\n"
6376												"    out_color.x = atomicAdd(entry.x, 1);\n"
6377												"    out_color.y = atomicAdd(entry.y, 1);\n"
6378												"    out_color.z = atomicAdd(entry.z, 1);\n"
6379												"    out_color.w = atomicAdd(entry.w, 1);\n"
6380												"}\n"
6381												"\n"
6382												"subroutine(ssbo_routine) void decrement(void)\n"
6383												"{\n"
6384												"    out_color.x = atomicAdd(entry.x, -1);\n"
6385												"    out_color.y = atomicAdd(entry.y, -1);\n"
6386												"    out_color.z = atomicAdd(entry.z, -1);\n"
6387												"    out_color.w = atomicAdd(entry.w, -1);\n"
6388												"}\n"
6389												"\n"
6390												"subroutine uniform ssbo_routine routine;\n"
6391												"\n"
6392												"void main()\n"
6393												"{\n"
6394												"    routine();\n"
6395												"}\n"
6396												"\n";
6397
6398	static const GLchar* geometry_shader_code = "#version 400 core\n"
6399												"#extension GL_ARB_shader_subroutine : require\n"
6400												"\n"
6401												"precision highp float;\n"
6402												"\n"
6403												"layout(points)                           in;\n"
6404												"layout(triangle_strip, max_vertices = 4) out;\n"
6405												"\n"
6406												"void main()\n"
6407												"{\n"
6408												"    gl_Position = vec4(-1, -1, 0, 1);\n"
6409												"    EmitVertex();\n"
6410												"    \n"
6411												"    gl_Position = vec4(-1,  1, 0, 1);\n"
6412												"    EmitVertex();\n"
6413												"    \n"
6414												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6415												"    EmitVertex();\n"
6416												"    \n"
6417												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6418												"    EmitVertex();\n"
6419												"    \n"
6420												"    EndPrimitive();\n"
6421												"}\n"
6422												"\n";
6423
6424	static const GLchar* vertex_shader_code = "#version 400 core\n"
6425											  "#extension GL_ARB_shader_subroutine : require\n"
6426											  "\n"
6427											  "precision highp float;\n"
6428											  "\n"
6429											  "void main()\n"
6430											  "{\n"
6431											  "}\n"
6432											  "\n";
6433
6434	static const GLchar* subroutine_names[] = { "increment", "decrement" };
6435
6436	/* Test data */
6437	static const glw::GLuint buffer_data[] = { m_texture_width * m_texture_height + 1,
6438											   m_texture_width * m_texture_height + 2,
6439											   m_texture_width * m_texture_height + 3,
6440											   m_texture_width * m_texture_height + 4 };
6441
6442	static const glw::GLuint expected_incremented[] = { m_texture_width * m_texture_height + buffer_data[0],
6443														m_texture_width * m_texture_height + buffer_data[1],
6444														m_texture_width * m_texture_height + buffer_data[2],
6445														m_texture_width * m_texture_height + buffer_data[3] };
6446
6447	static const glw::GLuint expected_decremented[] = { buffer_data[0], buffer_data[1], buffer_data[2],
6448														buffer_data[3] };
6449
6450	/* GL objects */
6451	Utils::buffer	  buffer(m_context);
6452	Utils::texture	 color_texture(m_context);
6453	Utils::framebuffer framebuffer(m_context);
6454	Utils::program	 program(m_context);
6455	Utils::vertexArray vao(m_context);
6456
6457	/* Init GL objects */
6458	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6459				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6460
6461	program.use();
6462
6463	vao.generate();
6464	vao.bind();
6465
6466	color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6467
6468	buffer.generate();
6469	buffer.update(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), (GLvoid*)buffer_data, GL_STATIC_DRAW);
6470	buffer.bindRange(GL_SHADER_STORAGE_BUFFER, 0 /* index */, 0 /* offset */, sizeof(buffer_data));
6471
6472	framebuffer.generate();
6473	framebuffer.bind();
6474	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6475	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6476	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6477
6478	/* Subroutine indices */
6479	GLuint increment = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6480	GLuint decrement = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6481
6482	/* Test */
6483	bool result = true;
6484
6485	if (false == testSSBODraw(increment, expected_incremented))
6486	{
6487		result = false;
6488	}
6489
6490	if (false == testSSBODraw(decrement, expected_decremented))
6491	{
6492		result = false;
6493	}
6494
6495	/* Done */
6496	return result;
6497}
6498
6499/** Execute draw call and verify results
6500 *
6501 * @param subroutine_index Index of subroutine that shall be used by draw call
6502 * @param expected_results Expected results
6503 *
6504 *
6505 **/
6506bool FunctionalTest12::testSSBODraw(GLuint subroutine_index, const GLuint expected_results[4]) const
6507{
6508	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6509
6510	/* Set subroutine uniforms */
6511	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6512	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6513
6514	/* Draw */
6515	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6516	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6517
6518	/* Capture results */
6519	GLuint* ssbo_results = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
6520	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
6521
6522	/* Verify */
6523	bool result = (0 == memcmp(expected_results, ssbo_results, 4 * sizeof(GLuint)));
6524
6525	if (false == result)
6526	{
6527		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result. "
6528											<< "Result: [ " << ssbo_results[0] << ", " << ssbo_results[1] << ", "
6529											<< ssbo_results[2] << ", " << ssbo_results[3] << " ] "
6530											<< "Expected: [ " << expected_results[0] << ", " << expected_results[1]
6531											<< ", " << expected_results[2] << ", " << expected_results[3] << " ]"
6532											<< tcu::TestLog::EndMessage;
6533	}
6534
6535	/* Unmap buffer */
6536	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
6537	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
6538
6539	/* Done */
6540	return result;
6541}
6542
6543/** Check if texture is filled with expected color
6544 *
6545 * @param texture        Texture instance
6546 * @param expected_color Expected color
6547 *
6548 * @return true if texture is filled with specified color, false otherwise
6549 **/
6550bool FunctionalTest12::verifyTexture(Utils::texture& texture, const GLuint expected_color[4]) const
6551{
6552	std::vector<GLuint> results;
6553	results.resize(m_texture_width * m_texture_height * 4);
6554
6555	texture.get(GL_RGBA_INTEGER, GL_UNSIGNED_INT, &results[0]);
6556
6557	for (GLuint y = 0; y < m_texture_height; ++y)
6558	{
6559		const GLuint line_offset = y * m_texture_width * 4;
6560
6561		for (GLuint x = 0; x < m_texture_width; ++x)
6562		{
6563			const GLuint point_offset = line_offset + x * 4;
6564			bool		 result		  = true;
6565
6566			result = result && (results[point_offset + 0] == expected_color[0]);
6567			result = result && (results[point_offset + 1] == expected_color[1]);
6568			result = result && (results[point_offset + 2] == expected_color[2]);
6569			result = result && (results[point_offset + 3] == expected_color[3]);
6570
6571			if (false == result)
6572			{
6573				return false;
6574			}
6575		}
6576	}
6577
6578	return true;
6579}
6580
6581/** Constructor.
6582 *
6583 *  @param context Rendering context.
6584 *
6585 **/
6586FunctionalTest13::FunctionalTest13(deqp::Context& context)
6587	: TestCase(context, "subroutines_with_separate_shader_objects",
6588			   "Verifies that subroutines work correctly when used in separate "
6589			   "shader objects")
6590	, m_fbo_id(0)
6591	, m_pipeline_id(0)
6592	, m_read_buffer(DE_NULL)
6593	, m_to_height(4)
6594	, m_to_id(0)
6595	, m_to_width(4)
6596	, m_vao_id(0)
6597	, m_has_test_passed(true)
6598{
6599	memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids));
6600	memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids));
6601	memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids));
6602	memset(m_te_po_ids, 0, sizeof(m_te_po_ids));
6603	memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids));
6604}
6605
6606/** Deinitializes all GL objects that may have been created during test
6607 *  execution, as well as releases all process-side buffers that may have
6608 *  been allocated during the process.
6609 *  The function also restores default GL state configuration.
6610 **/
6611void FunctionalTest13::deinit()
6612{
6613	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6614
6615	if (m_fbo_id != 0)
6616	{
6617		gl.deleteFramebuffers(1, &m_fbo_id);
6618
6619		m_fbo_id = 0;
6620	}
6621
6622	if (m_pipeline_id != 0)
6623	{
6624		gl.deleteProgramPipelines(1, &m_pipeline_id);
6625
6626		m_pipeline_id = 0;
6627	}
6628
6629	if (m_read_buffer != DE_NULL)
6630	{
6631		delete[] m_read_buffer;
6632
6633		m_read_buffer = DE_NULL;
6634	}
6635
6636	for (unsigned int n_id = 0; n_id < 2 /* po id variants */; ++n_id)
6637	{
6638		if (m_fs_po_ids[n_id] != 0)
6639		{
6640			gl.deleteProgram(m_fs_po_ids[n_id]);
6641
6642			m_fs_po_ids[n_id] = 0;
6643		}
6644
6645		if (m_gs_po_ids[n_id] != 0)
6646		{
6647			gl.deleteProgram(m_gs_po_ids[n_id]);
6648
6649			m_gs_po_ids[n_id] = 0;
6650		}
6651
6652		if (m_tc_po_ids[n_id] != 0)
6653		{
6654			gl.deleteProgram(m_tc_po_ids[n_id]);
6655
6656			m_tc_po_ids[n_id] = 0;
6657		}
6658
6659		if (m_te_po_ids[n_id] != 0)
6660		{
6661			gl.deleteProgram(m_te_po_ids[n_id]);
6662
6663			m_te_po_ids[n_id] = 0;
6664		}
6665
6666		if (m_vs_po_ids[n_id] != 0)
6667		{
6668			gl.deleteProgram(m_vs_po_ids[n_id]);
6669
6670			m_vs_po_ids[n_id] = 0;
6671		}
6672	} /* for (both shader program object variants) */
6673
6674	if (m_to_id != 0)
6675	{
6676		gl.deleteTextures(1, &m_to_id);
6677
6678		m_to_id = 0;
6679	}
6680
6681	if (m_vao_id != 0)
6682	{
6683		gl.deleteVertexArrays(1, &m_vao_id);
6684
6685		m_vao_id = 0;
6686	}
6687
6688	/* Restore default GL_PATCH_VERTICES setting value */
6689	gl.patchParameteri(GL_PATCH_VERTICES, 3);
6690
6691	/* Restore default GL_PACK_ALIGNMENT setting value */
6692	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
6693}
6694
6695/** Retrieves body of a fragment shader that should be used for the test.
6696 *  The subroutine implementations are slightly changed, depending on the
6697 *  index of the shader, as specified by the caller.
6698 *
6699 *  @param n_id Index of the shader.
6700 *
6701 *  @return Requested string.
6702 **/
6703std::string FunctionalTest13::getFragmentShaderBody(unsigned int n_id)
6704{
6705	std::stringstream result_sstream;
6706
6707	/* Pre-amble */
6708	result_sstream << "#version 400\n"
6709					  "\n"
6710					  "#extension GL_ARB_shader_subroutine : require\n"
6711					  "\n"
6712					  /* Sub-routine */
6713					  "subroutine void SubroutineFSType(inout vec4 result);\n"
6714					  "\n"
6715					  "subroutine(SubroutineFSType) void SubroutineFS1(inout vec4 result)\n"
6716					  "{\n"
6717					  "    result += vec4("
6718				   << float(n_id + 1) / 10.0f << ", " << float(n_id + 2) / 10.0f << ", " << float(n_id + 3) / 10.0f
6719				   << ", " << float(n_id + 4) / 10.0f
6720				   << ");\n"
6721					  "}\n"
6722					  "subroutine(SubroutineFSType) void SubroutineFS2(inout vec4 result)\n"
6723					  "{\n"
6724					  "    result += vec4("
6725				   << float(n_id + 1) / 20.0f << ", " << float(n_id + 2) / 20.0f << ", " << float(n_id + 3) / 20.0f
6726				   << ", " << float(n_id + 4) / 20.0f << ");\n"
6727														 "}\n"
6728														 "\n"
6729														 "subroutine uniform SubroutineFSType function;\n"
6730														 "\n"
6731														 /* Input block */
6732														 "in GS_DATA\n"
6733														 "{\n"
6734														 "    vec4 data;\n"
6735														 "} in_gs;\n"
6736														 "\n"
6737														 "out vec4 result;\n"
6738														 /* main() declaration */
6739														 "void main()\n"
6740														 "{\n"
6741														 "    vec4 data = in_gs.data;\n"
6742														 "    function(data);\n"
6743														 "\n"
6744														 "    result = data;\n"
6745														 "}\n";
6746
6747	return result_sstream.str();
6748}
6749
6750/** Retrieves body of a geometry shader that should be used for the test.
6751 *  The subroutine implementations are slightly changed, depending on the
6752 *  index of the shader, as specified by the caller.
6753 *
6754 *  @param n_id Index of the shader.
6755 *
6756 *  @return Requested string.
6757 **/
6758std::string FunctionalTest13::getGeometryShaderBody(unsigned int n_id)
6759{
6760	std::stringstream result_sstream;
6761
6762	/* Pre-amble */
6763	result_sstream << "#version 400\n"
6764					  "\n"
6765					  "#extension GL_ARB_shader_subroutine : require\n"
6766					  "\n"
6767					  "layout(points)                           in;\n"
6768					  "layout(triangle_strip, max_vertices = 4) out;\n"
6769					  /* Sub-routine */
6770					  "subroutine void SubroutineGSType(inout vec4 result);\n"
6771					  "\n"
6772					  "subroutine(SubroutineGSType) void SubroutineGS1(inout vec4 result)\n"
6773					  "{\n"
6774					  "    result += vec4(0, 0, 0, "
6775				   << float(n_id + 1) * 0.425f << ");\n"
6776												  "}\n"
6777												  "subroutine(SubroutineGSType) void SubroutineGS2(inout vec4 result)\n"
6778												  "{\n"
6779												  "    result += vec4(0, 0, 0, "
6780				   << float(n_id + 1) * 0.0425f << ");\n"
6781												   "}\n"
6782												   "\n"
6783												   "subroutine uniform SubroutineGSType function;\n"
6784												   "\n"
6785												   /* Input block */
6786												   "in TE_DATA\n"
6787												   "{\n"
6788												   "    vec4 data;\n"
6789												   "} in_te[];\n"
6790												   "\n"
6791												   /* Output block */
6792												   "out GS_DATA\n"
6793												   "{\n"
6794												   "    vec4 data;\n"
6795												   "} out_gs;\n"
6796												   "\n"
6797												   "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6798												   "out gl_PerVertex { vec4 gl_Position; };\n"
6799												   /* main() declaration */
6800												   "void main()\n"
6801												   "{\n"
6802												   "    vec4 data = in_te[0].data;\n"
6803												   "\n"
6804												   "    function(data);\n"
6805												   "\n"
6806												   "    gl_Position = vec4(1, -1, 0, 1);\n"
6807												   "    out_gs.data = data;\n"
6808												   "    EmitVertex();\n"
6809												   "\n"
6810												   "    gl_Position = vec4(-1, -1, 0, 1);\n"
6811												   "    out_gs.data = data;\n"
6812												   "    EmitVertex();\n"
6813												   "\n"
6814												   "    gl_Position = vec4(1, 1, 0, 1);\n"
6815												   "    out_gs.data = data;\n"
6816												   "    EmitVertex();\n"
6817												   "\n"
6818												   "    gl_Position = vec4(-1, 1, 0, 1);\n"
6819												   "    out_gs.data = data;\n"
6820												   "    EmitVertex();\n"
6821												   "    EndPrimitive();\n"
6822												   "}\n";
6823
6824	return result_sstream.str();
6825}
6826
6827/** Retrieves body of a tessellation control shader that should be used for the test.
6828 *  The subroutine implementations are slightly changed, depending on the
6829 *  index of the shader, as specified by the caller.
6830 *
6831 *  @param n_id Index of the shader.
6832 *
6833 *  @return Requested string.
6834 **/
6835std::string FunctionalTest13::getTessellationControlShaderBody(unsigned int n_id)
6836{
6837	std::stringstream result_sstream;
6838
6839	/* Pre-amble */
6840	result_sstream << "#version 400\n"
6841					  "\n"
6842					  "#extension GL_ARB_shader_subroutine : require\n"
6843					  "\n"
6844					  "layout(vertices = 4) out;\n"
6845					  /* Sub-routine */
6846					  "subroutine void SubroutineTCType(inout vec4 result);\n"
6847					  "\n"
6848					  "subroutine(SubroutineTCType) void SubroutineTC1(inout vec4 result)\n"
6849					  "{\n"
6850					  "    result += vec4(0, "
6851				   << float(n_id + 1) * 0.25f << ", 0, 0);\n"
6852												 "}\n"
6853												 "subroutine(SubroutineTCType) void SubroutineTC2(inout vec4 result)\n"
6854												 "{\n"
6855												 "    result += vec4(0, "
6856				   << float(n_id + 1) * 0.025f
6857				   << ", 0, 0);\n"
6858					  "}\n"
6859					  "\n"
6860					  "subroutine uniform SubroutineTCType function;\n"
6861					  "\n"
6862					  /* Input block */
6863					  "in VS_DATA\n"
6864					  "{\n"
6865					  "    vec4 data;\n"
6866					  "} in_vs[];\n"
6867					  "\n"
6868					  /* Output block */
6869					  "out TC_DATA\n"
6870					  "{\n"
6871					  "    vec4 data;\n"
6872					  "} out_tc[];\n"
6873					  "\n"
6874					  "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6875					  "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"
6876					  /* main() declaration */
6877					  "void main()\n"
6878					  "{\n"
6879					  "    gl_TessLevelOuter[0]                = 1.0;\n"
6880					  "    gl_TessLevelOuter[1]                = 1.0;\n"
6881					  "    gl_TessLevelOuter[2]                = 1.0;\n"
6882					  "    gl_TessLevelOuter[3]                = 1.0;\n"
6883					  "    gl_TessLevelInner[0]                = 1.0;\n"
6884					  "    gl_TessLevelInner[1]                = 1.0;\n"
6885					  "    gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n"
6886					  "    out_tc[gl_InvocationID].data        = in_vs[0].data;\n"
6887					  "\n"
6888					  "    function(out_tc[gl_InvocationID].data);\n"
6889					  "}\n";
6890
6891	return result_sstream.str();
6892}
6893
6894/** Retrieves body of a tessellation evaluation shader that should be used for the test.
6895 *  The subroutine implementations are slightly changed, depending on the
6896 *  index of the shader, as specified by the caller.
6897 *
6898 *  @param n_id Index of the shader.
6899 *
6900 *  @return Requested string.
6901 **/
6902std::string FunctionalTest13::getTessellationEvaluationShaderBody(unsigned int n_id)
6903{
6904	std::stringstream result_sstream;
6905
6906	/* Pre-amble */
6907	result_sstream << "#version 400\n"
6908					  "\n"
6909					  "#extension GL_ARB_shader_subroutine : require\n"
6910					  "\n"
6911					  "layout(quads, point_mode) in;\n"
6912					  /* Sub-routine */
6913					  "subroutine void SubroutineTEType(inout vec4 result);\n"
6914					  "\n"
6915					  "subroutine(SubroutineTEType) void SubroutineTE1(inout vec4 result)\n"
6916					  "{\n"
6917					  "    result += vec4(0, 0, "
6918				   << float(n_id + 1) * 0.325f << ", 0);\n"
6919												  "}\n"
6920												  "subroutine(SubroutineTEType) void SubroutineTE2(inout vec4 result)\n"
6921												  "{\n"
6922												  "    result += vec4(0, 0, "
6923				   << float(n_id + 1) * 0.0325f << ", 0);\n"
6924												   "}\n"
6925												   "\n"
6926												   "subroutine uniform SubroutineTEType function;\n"
6927												   "\n"
6928												   /* Input block */
6929												   "in TC_DATA\n"
6930												   "{\n"
6931												   "    vec4 data;\n"
6932												   "} in_tc[];\n"
6933												   "\n"
6934												   /* Output block */
6935												   "out TE_DATA\n"
6936												   "{\n"
6937												   "    vec4 data;\n"
6938												   "} out_te;\n"
6939												   "\n"
6940												   "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6941												   "out gl_PerVertex { vec4 gl_Position; };\n"
6942												   /* main() declaration */
6943												   "void main()\n"
6944												   "{\n"
6945												   "    gl_Position = gl_in[0].gl_Position;\n"
6946												   "    out_te.data = in_tc[0].data;\n"
6947												   "\n"
6948												   "    function(out_te.data);\n"
6949												   "}\n";
6950
6951	return result_sstream.str();
6952}
6953
6954/** Retrieves body of a vertex shader that should be used for the test.
6955 *  The subroutine implementations are slightly changed, depending on the
6956 *  index of the shader, as specified by the caller.
6957 *
6958 *  @param n_id Index of the shader.
6959 *
6960 *  @return Requested string.
6961 **/
6962std::string FunctionalTest13::getVertexShaderBody(unsigned int n_id)
6963{
6964	std::stringstream result_sstream;
6965
6966	/* Pre-amble */
6967	result_sstream << "#version 400\n"
6968					  "\n"
6969					  "#extension GL_ARB_shader_subroutine : require\n"
6970					  "#extension GL_ARB_separate_shader_objects: require\n"
6971					  "\n"
6972					  /* Sub-routine */
6973					  "subroutine void SubroutineVSType(inout vec4 result);\n"
6974					  "\n"
6975					  "subroutine(SubroutineVSType) void SubroutineVS1(inout vec4 result)\n"
6976					  "{\n"
6977					  "    result += vec4("
6978				   << float(n_id + 1) * 0.125f << ", 0, 0, 0);\n"
6979												  "}\n"
6980												  "subroutine(SubroutineVSType) void SubroutineVS2(inout vec4 result)\n"
6981												  "{\n"
6982												  "    result += vec4("
6983				   << float(n_id + 1) * 0.0125f << ", 0, 0, 0);\n"
6984												   "}\n"
6985												   "\n"
6986												   "subroutine uniform SubroutineVSType function;\n"
6987												   "\n"
6988												   /* Output block */
6989												   "out VS_DATA\n"
6990												   "{\n"
6991												   "    vec4 data;\n"
6992												   "} out_vs;\n"
6993												   "\n"
6994												   "out gl_PerVertex { vec4 gl_Position; };\n"
6995												   /* main() declaration */
6996												   "void main()\n"
6997												   "{\n"
6998												   "    gl_Position = vec4(0, 0, 0, 1);\n"
6999												   "    out_vs.data = vec4(0);\n"
7000												   "\n"
7001												   "    function(out_vs.data);\n"
7002												   "\n"
7003												   "}\n";
7004
7005	return result_sstream.str();
7006}
7007
7008/** Initializes all GL objects required to run the test. Also modifies a few
7009 *  GL states in order for the test to run correctly.
7010 **/
7011void FunctionalTest13::initTest()
7012{
7013	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7014
7015	/* Set up viewport */
7016	gl.viewport(0 /* x */, 0 /* y */, m_to_width, m_to_height);
7017	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
7018
7019	/* Make sure no program is used */
7020	gl.useProgram(0);
7021	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7022
7023	/* Generate a pipeline object */
7024	gl.genProgramPipelines(1, &m_pipeline_id);
7025	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
7026
7027	gl.bindProgramPipeline(m_pipeline_id);
7028	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
7029
7030	/* Initialize all shader programs */
7031	for (unsigned int n_id = 0; n_id < 2 /* variants for each shader type */; ++n_id)
7032	{
7033		std::string fs_body			= getFragmentShaderBody(n_id);
7034		const char* fs_body_raw_ptr = fs_body.c_str();
7035		std::string gs_body			= getGeometryShaderBody(n_id);
7036		const char* gs_body_raw_ptr = gs_body.c_str();
7037		std::string tc_body			= getTessellationControlShaderBody(n_id);
7038		const char* tc_body_raw_ptr = tc_body.c_str();
7039		std::string te_body			= getTessellationEvaluationShaderBody(n_id);
7040		const char* te_body_raw_ptr = te_body.c_str();
7041		std::string vs_body			= getVertexShaderBody(n_id);
7042		const char* vs_body_raw_ptr = vs_body.c_str();
7043
7044		m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr);
7045		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7046
7047		m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr);
7048		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7049
7050		m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr);
7051		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7052
7053		m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr);
7054		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7055
7056		m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr);
7057		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7058
7059		/* Verify that all shader program objects have been linked successfully */
7060		const glw::GLuint po_ids[] = {
7061			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],
7062		};
7063		const unsigned int n_po_ids = sizeof(po_ids) / sizeof(po_ids[0]);
7064
7065		for (unsigned int n_po_id = 0; n_po_id < n_po_ids; ++n_po_id)
7066		{
7067			glw::GLint  link_status = GL_FALSE;
7068			glw::GLuint po_id		= po_ids[n_po_id];
7069
7070			gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
7071			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7072
7073			if (link_status != GL_TRUE)
7074			{
7075				TCU_FAIL("Shader program object linking failed.");
7076			}
7077		} /* for (all shader program objects) */
7078	}	 /* for (both shader program object variants) */
7079
7080	/* Generate a texture object. We will use the base mip-map as a render-target */
7081	gl.genTextures(1, &m_to_id);
7082	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
7083
7084	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
7085	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7086
7087	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA32F, m_to_width, m_to_height);
7088	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
7089
7090	/* Generate and configure a FBO we will use for the draw call */
7091	gl.genFramebuffers(1, &m_fbo_id);
7092	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
7093
7094	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
7095	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
7096
7097	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
7098	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
7099
7100	/* Generate & bind a VAO */
7101	gl.genVertexArrays(1, &m_vao_id);
7102	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7103
7104	gl.bindVertexArray(m_vao_id);
7105	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7106
7107	/* Set up tessellation */
7108	gl.patchParameteri(GL_PATCH_VERTICES, 1);
7109	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
7110
7111	/* Set up pixel storage alignment */
7112	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
7113	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
7114
7115	/* Allocate enough space to hold color attachment data */
7116	m_read_buffer = (unsigned char*)new float[m_to_width * m_to_height * 4 /* rgba */];
7117}
7118
7119/** Executes test iteration.
7120 *
7121 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7122 */
7123tcu::TestNode::IterateResult FunctionalTest13::iterate()
7124{
7125	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7126
7127	/* Do not execute the test if GL_ARB_shader_subroutine and GL_ARB_separate_shader_objects
7128	 * are not supported */
7129	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
7130	{
7131		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
7132	}
7133
7134	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
7135	{
7136		throw tcu::NotSupportedError("GL_ARB_separate_shader_objects is not supported");
7137	}
7138
7139	/* Initialize all GL objects before we continue */
7140	initTest();
7141
7142	/* Iterate over all possible FS/GS/TC/TE/VS permutations */
7143	for (int n_shader_permutation = 0; n_shader_permutation < 32 /* 2^5 */; ++n_shader_permutation)
7144	{
7145		const unsigned int n_fs_idx = ((n_shader_permutation & (1 << 0)) != 0) ? 1 : 0;
7146		const unsigned int n_gs_idx = ((n_shader_permutation & (1 << 1)) != 0) ? 1 : 0;
7147		const unsigned int n_tc_idx = ((n_shader_permutation & (1 << 2)) != 0) ? 1 : 0;
7148		const unsigned int n_te_idx = ((n_shader_permutation & (1 << 3)) != 0) ? 1 : 0;
7149		const unsigned int n_vs_idx = ((n_shader_permutation & (1 << 4)) != 0) ? 1 : 0;
7150		const unsigned int fs_po_id = m_fs_po_ids[n_fs_idx];
7151		const unsigned int gs_po_id = m_gs_po_ids[n_gs_idx];
7152		const unsigned int tc_po_id = m_tc_po_ids[n_tc_idx];
7153		const unsigned int te_po_id = m_te_po_ids[n_te_idx];
7154		const unsigned int vs_po_id = m_vs_po_ids[n_vs_idx];
7155
7156		/* Configure fragment shader stage */
7157		gl.useProgramStages(m_pipeline_id, GL_FRAGMENT_SHADER_BIT, fs_po_id);
7158		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_FRAGMENT_SHADER_BIT bit");
7159
7160		/* Configure geometry shader stage */
7161		gl.useProgramStages(m_pipeline_id, GL_GEOMETRY_SHADER_BIT, gs_po_id);
7162		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_GEOMETRY_SHADER_BIT bit");
7163
7164		/* Configure tessellation control shader stage */
7165		gl.useProgramStages(m_pipeline_id, GL_TESS_CONTROL_SHADER_BIT, tc_po_id);
7166		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_CONTROL_SHADER_BIT bit");
7167
7168		/* Configure tessellation evaluation shader stage */
7169		gl.useProgramStages(m_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT, te_po_id);
7170		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_EVALUATION_SHADER_BIT bit");
7171
7172		/* Configure vertex shader stage */
7173		gl.useProgramStages(m_pipeline_id, GL_VERTEX_SHADER_BIT, vs_po_id);
7174		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_VERTEX_SHADER_BIT bit");
7175
7176		/* Validate the pipeline */
7177		glw::GLint validate_status = GL_FALSE;
7178
7179		gl.validateProgramPipeline(m_pipeline_id);
7180		GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed.");
7181
7182		gl.getProgramPipelineiv(m_pipeline_id, GL_VALIDATE_STATUS, &validate_status);
7183		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed.");
7184
7185		if (validate_status != GL_TRUE)
7186		{
7187			TCU_FAIL("Program pipeline has not been validated successfully.");
7188		}
7189
7190		/* Retrieve subroutine indices */
7191		GLuint fs_subroutine_indices[2]	= { (GLuint)-1 };
7192		GLint  fs_subroutine_uniform_index = 0;
7193		GLuint gs_subroutine_indices[2]	= { (GLuint)-1 };
7194		GLint  gs_subroutine_uniform_index = 0;
7195		GLuint tc_subroutine_indices[2]	= { (GLuint)-1 };
7196		GLint  tc_subroutine_uniform_index = 0;
7197		GLuint te_subroutine_indices[2]	= { (GLuint)-1 };
7198		GLint  te_subroutine_uniform_index = 0;
7199		GLuint vs_subroutine_indices[2]	= { (GLuint)-1 };
7200		GLint  vs_subroutine_uniform_index = 0;
7201
7202		for (unsigned int n_subroutine = 0; n_subroutine < 2; ++n_subroutine)
7203		{
7204			std::stringstream fs_subroutine_name_sstream;
7205			std::stringstream gs_subroutine_name_sstream;
7206			std::stringstream tc_subroutine_name_sstream;
7207			std::stringstream te_subroutine_name_sstream;
7208			std::stringstream vs_subroutine_name_sstream;
7209
7210			fs_subroutine_name_sstream << "SubroutineFS" << (n_subroutine + 1);
7211			gs_subroutine_name_sstream << "SubroutineGS" << (n_subroutine + 1);
7212			tc_subroutine_name_sstream << "SubroutineTC" << (n_subroutine + 1);
7213			te_subroutine_name_sstream << "SubroutineTE" << (n_subroutine + 1);
7214			vs_subroutine_name_sstream << "SubroutineVS" << (n_subroutine + 1);
7215
7216			fs_subroutine_indices[n_subroutine] =
7217				gl.getSubroutineIndex(fs_po_id, GL_FRAGMENT_SHADER, fs_subroutine_name_sstream.str().c_str());
7218			gs_subroutine_indices[n_subroutine] =
7219				gl.getSubroutineIndex(gs_po_id, GL_GEOMETRY_SHADER, gs_subroutine_name_sstream.str().c_str());
7220			tc_subroutine_indices[n_subroutine] =
7221				gl.getSubroutineIndex(tc_po_id, GL_TESS_CONTROL_SHADER, tc_subroutine_name_sstream.str().c_str());
7222			te_subroutine_indices[n_subroutine] =
7223				gl.getSubroutineIndex(te_po_id, GL_TESS_EVALUATION_SHADER, te_subroutine_name_sstream.str().c_str());
7224			vs_subroutine_indices[n_subroutine] =
7225				gl.getSubroutineIndex(vs_po_id, GL_VERTEX_SHADER, vs_subroutine_name_sstream.str().c_str());
7226			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
7227
7228			if (fs_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7229				gs_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7230				tc_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7231				te_subroutine_indices[n_subroutine] == (GLuint)-1 || vs_subroutine_indices[n_subroutine] == (GLuint)-1)
7232			{
7233				m_testCtx.getLog() << tcu::TestLog::Message
7234								   << "At least one subroutine was not recognized by glGetSubroutineIndex() call. "
7235									  "(fs:"
7236								   << fs_subroutine_indices[n_subroutine]
7237								   << ", gs:" << gs_subroutine_indices[n_subroutine]
7238								   << ", tc:" << tc_subroutine_indices[n_subroutine]
7239								   << ", te:" << te_subroutine_indices[n_subroutine]
7240								   << ", vs:" << vs_subroutine_indices[n_subroutine] << ")."
7241								   << tcu::TestLog::EndMessage;
7242
7243				TCU_FAIL("At least one subroutine was not recognized");
7244			}
7245		} /* for (both subroutines) */
7246
7247		/* Retrieve subroutine uniform indices */
7248		fs_subroutine_uniform_index = gl.getSubroutineUniformLocation(fs_po_id, GL_FRAGMENT_SHADER, "function");
7249		gs_subroutine_uniform_index = gl.getSubroutineUniformLocation(gs_po_id, GL_GEOMETRY_SHADER, "function");
7250		tc_subroutine_uniform_index = gl.getSubroutineUniformLocation(tc_po_id, GL_TESS_CONTROL_SHADER, "function");
7251		te_subroutine_uniform_index = gl.getSubroutineUniformLocation(te_po_id, GL_TESS_EVALUATION_SHADER, "function");
7252		vs_subroutine_uniform_index = gl.getSubroutineUniformLocation(vs_po_id, GL_VERTEX_SHADER, "function");
7253
7254		if (fs_subroutine_uniform_index == -1 || gs_subroutine_uniform_index == -1 ||
7255			tc_subroutine_uniform_index == -1 || te_subroutine_uniform_index == -1 || vs_subroutine_uniform_index == -1)
7256		{
7257			m_testCtx.getLog() << tcu::TestLog::Message << "At least one subroutine uniform is considered inactive by "
7258														   "glGetSubroutineUniformLocation ("
7259														   "fs:"
7260							   << fs_subroutine_uniform_index << ", gs:" << gs_subroutine_uniform_index
7261							   << ", tc:" << tc_subroutine_uniform_index << ", te:" << te_subroutine_uniform_index
7262							   << ", vs:" << vs_subroutine_uniform_index << ")." << tcu::TestLog::EndMessage;
7263
7264			TCU_FAIL("At least one subroutine uniform is considered inactive");
7265		}
7266
7267		/* Check if both subroutines work correctly in each stage */
7268		for (int n_subroutine_permutation = 0; n_subroutine_permutation < 32; /* 2^5 */
7269			 ++n_subroutine_permutation)
7270		{
7271			unsigned int n_fs_subroutine = ((n_subroutine_permutation & (1 << 0)) != 0) ? 1 : 0;
7272			unsigned int n_gs_subroutine = ((n_subroutine_permutation & (1 << 1)) != 0) ? 1 : 0;
7273			unsigned int n_tc_subroutine = ((n_subroutine_permutation & (1 << 2)) != 0) ? 1 : 0;
7274			unsigned int n_te_subroutine = ((n_subroutine_permutation & (1 << 3)) != 0) ? 1 : 0;
7275			unsigned int n_vs_subroutine = ((n_subroutine_permutation & (1 << 4)) != 0) ? 1 : 0;
7276
7277			/* Configure subroutine uniforms */
7278			struct
7279			{
7280				glw::GLenum  stage;
7281				glw::GLuint  po_id;
7282				glw::GLuint* indices;
7283			} configurations[] = {
7284				{ GL_FRAGMENT_SHADER, fs_po_id, fs_subroutine_indices + n_fs_subroutine },
7285				{ GL_GEOMETRY_SHADER, gs_po_id, gs_subroutine_indices + n_gs_subroutine },
7286				{ GL_TESS_CONTROL_SHADER, tc_po_id, tc_subroutine_indices + n_tc_subroutine },
7287				{ GL_TESS_EVALUATION_SHADER, te_po_id, te_subroutine_indices + n_te_subroutine },
7288				{ GL_VERTEX_SHADER, vs_po_id, vs_subroutine_indices + n_vs_subroutine },
7289			};
7290
7291			for (int i = 0; i < 5; ++i)
7292			{
7293				gl.activeShaderProgram(m_pipeline_id, configurations[i].po_id);
7294				GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveShaderProgram() call failed.");
7295
7296				gl.uniformSubroutinesuiv(configurations[i].stage, 1 /* count */, configurations[i].indices);
7297				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
7298			}
7299
7300			/* Render a full-screen quad with the pipeline */
7301			gl.clear(GL_COLOR_BUFFER_BIT);
7302			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
7303
7304			gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
7305			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7306
7307			/* Read color attachment's contents */
7308			gl.readPixels(0, /* x */
7309						  0, /* y */
7310						  m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_read_buffer);
7311			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
7312
7313			/* Verify the contents */
7314			verifyReadBuffer(n_fs_idx, n_fs_subroutine, n_gs_idx, n_gs_subroutine, n_tc_idx, n_tc_subroutine, n_te_idx,
7315							 n_te_subroutine, n_vs_idx, n_vs_subroutine);
7316		} /* for (all subroutine permutations) */
7317	}	 /* for (all program shader object permutations) */
7318
7319	/** All done */
7320	if (m_has_test_passed)
7321	{
7322		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7323	}
7324	else
7325	{
7326		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7327	}
7328
7329	return STOP;
7330}
7331
7332/** Verifies the data that have been rendered using a pipeline object.
7333 *  Contents of the data depends on indices of the shaders, as well as
7334 *  on the subroutines that have been activated for particular iteration.
7335 *
7336 *  @param n_fs_id         Index of the fragment shader used for the iteration;
7337 *  @param n_fs_subroutine Index of the subroutine used in the fragment shader
7338 *                         for the iteration;
7339 *  @param n_gs_id         Index of the geometry shader used for the iteration;
7340 *  @param n_gs_subroutine Index of the subroutine used in the geometry shader
7341 *                         for the iteration;
7342 *  @param n_tc_id         Index of the tessellation control shader used for the iteration;
7343 *  @param n_tc_subroutine Index of the subroutine used in the tessellation control
7344 *                         shader for the iteration;
7345 *  @param n_te_id         Index of the tessellation evaluation shader used for the iteration;
7346 *  @param n_te_subroutine Index of the subroutine used in the tessellation evaluation
7347 *                         shader for the iteration;
7348 *  @param n_vs_id         Index of the vertex shader used for the iteration;
7349 *  @param n_vs_subroutine Index of the subroutine used in the vertex shader for
7350 *                         the iteration.
7351 */
7352void FunctionalTest13::verifyReadBuffer(unsigned int n_fs_id, unsigned int n_fs_subroutine, unsigned int n_gs_id,
7353										unsigned int n_gs_subroutine, unsigned int n_tc_id,
7354										unsigned int n_tc_subroutine, unsigned int n_te_id,
7355										unsigned int n_te_subroutine, unsigned int n_vs_id,
7356										unsigned int n_vs_subroutine)
7357{
7358	float expected_color[4] = { 0 };
7359	float fs_modifier[4]	= { 0 };
7360	float gs_modifier[4]	= { 0 };
7361	float tc_modifier[4]	= { 0 };
7362	float te_modifier[4]	= { 0 };
7363	float vs_modifier[4]	= { 0 };
7364
7365	if (n_fs_subroutine == 0)
7366	{
7367		for (unsigned int n_component = 0; n_component < 4; ++n_component)
7368		{
7369			fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 10.0f;
7370		}
7371	}
7372	else
7373	{
7374		for (unsigned int n_component = 0; n_component < 4; ++n_component)
7375		{
7376			fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 20.0f;
7377		}
7378	}
7379
7380	if (n_gs_subroutine == 0)
7381	{
7382		gs_modifier[3] = float(n_gs_id + 1) * 0.425f;
7383	}
7384	else
7385	{
7386		gs_modifier[3] = float(n_gs_id + 1) * 0.0425f;
7387	}
7388
7389	if (n_tc_subroutine == 0)
7390	{
7391		tc_modifier[1] = float(n_tc_id + 1) * 0.25f;
7392	}
7393	else
7394	{
7395		tc_modifier[1] = float(n_tc_id + 1) * 0.025f;
7396	}
7397
7398	if (n_te_subroutine == 0)
7399	{
7400		te_modifier[2] = float(n_te_id + 1) * 0.325f;
7401	}
7402	else
7403	{
7404		te_modifier[2] = float(n_te_id + 1) * 0.0325f;
7405	}
7406
7407	if (n_vs_subroutine == 0)
7408	{
7409		vs_modifier[0] = float(n_vs_id + 1) * 0.125f;
7410	}
7411	else
7412	{
7413		vs_modifier[0] = float(n_vs_id + 1) * 0.0125f;
7414	}
7415
7416	/* Determine the expected color */
7417	for (unsigned int n_component = 0; n_component < 4 /* rgba */; ++n_component)
7418	{
7419		expected_color[n_component] = fs_modifier[n_component] + gs_modifier[n_component] + tc_modifier[n_component] +
7420									  te_modifier[n_component] + vs_modifier[n_component];
7421	}
7422
7423	/* Verify all read texels are valid */
7424	const float epsilon			= 1e-5f;
7425	bool		should_continue = true;
7426
7427	for (unsigned int y = 0; y < m_to_height && should_continue; ++y)
7428	{
7429		const float* row_ptr = (const float*)m_read_buffer + y * m_to_width * 4; /* rgba */
7430
7431		for (unsigned int x = 0; x < m_to_width && should_continue; ++x)
7432		{
7433			const float* texel_ptr = row_ptr + x * 4; /* rgba */
7434
7435			if (de::abs(texel_ptr[0] - expected_color[0]) > epsilon ||
7436				de::abs(texel_ptr[1] - expected_color[1]) > epsilon ||
7437				de::abs(texel_ptr[2] - expected_color[2]) > epsilon ||
7438				de::abs(texel_ptr[3] - expected_color[3]) > epsilon)
7439			{
7440				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel rendered at (" << x << ", " << y
7441								   << ") for "
7442									  "the following configuration: "
7443									  "n_fs_id:"
7444								   << n_fs_id << " n_fs_subroutine:" << n_fs_subroutine << " n_gs_id:" << n_gs_id
7445								   << " n_gs_subroutine:" << n_gs_subroutine << " n_tc_id:" << n_tc_id
7446								   << " n_tc_subroutine:" << n_tc_subroutine << " n_te_id:" << n_te_id
7447								   << " n_te_subroutine:" << n_te_subroutine << " n_vs_id:" << n_vs_id
7448								   << " n_vs_subroutine:" << n_vs_subroutine << "; expected:"
7449																				"("
7450								   << expected_color[0] << ", " << expected_color[1] << ", " << expected_color[2]
7451								   << ", " << expected_color[3] << "), found:"
7452																   "("
7453								   << texel_ptr[0] << ", " << texel_ptr[1] << ", " << texel_ptr[2] << ", "
7454								   << texel_ptr[3] << ")." << tcu::TestLog::EndMessage;
7455
7456				m_has_test_passed = false;
7457				should_continue   = false;
7458			}
7459		} /* for (all columns) */
7460	}	 /* for (all rows) */
7461}
7462
7463/** Constructor
7464 *
7465 * @param context CTS context
7466 **/
7467FunctionalTest14_15::FunctionalTest14_15(deqp::Context& context)
7468	: TestCase(context, "structure_parameters_program_binary", "Verify structures can be used as parameters")
7469	, m_uniform_location(0)
7470{
7471}
7472
7473/** Execute test
7474 *
7475 * @return tcu::TestNode::STOP
7476 **/
7477tcu::TestNode::IterateResult FunctionalTest14_15::iterate()
7478{
7479	static const GLchar* vertex_shader_code =
7480		"#version 400 core\n"
7481		"#extension GL_ARB_shader_subroutine : require\n"
7482		"\n"
7483		"precision highp float;\n"
7484		"\n"
7485		"struct data\n"
7486		"{\n"
7487		"    uint r;\n"
7488		"    uint g;\n"
7489		"    uint b;\n"
7490		"    uint a;\n"
7491		"};\n"
7492		"\n"
7493		"subroutine void routine_type_1(in data iparam, out data oparam);\n"
7494		"subroutine void routine_type_2(inout data arg);\n"
7495		"\n"
7496		"subroutine (routine_type_1) void invert(in data iparam, out data oparam)\n"
7497		"{\n"
7498		"    oparam.r = iparam.a;\n"
7499		"    oparam.g = iparam.b;\n"
7500		"    oparam.b = iparam.g;\n"
7501		"    oparam.a = iparam.r;\n"
7502		"}\n"
7503		"\n"
7504		"subroutine (routine_type_1) void increment(in data iparam, out data oparam)\n"
7505		"{\n"
7506		"    oparam.r = 1 + iparam.r;\n"
7507		"    oparam.g = 1 + iparam.g;\n"
7508		"    oparam.b = 1 + iparam.b;\n"
7509		"    oparam.a = 1 + iparam.a;\n"
7510		"}\n"
7511		"\n"
7512		"subroutine (routine_type_2) void div_by_2(inout data arg)\n"
7513		"{\n"
7514		"    arg.r = arg.r / 2;\n"
7515		"    arg.g = arg.g / 2;\n"
7516		"    arg.b = arg.b / 2;\n"
7517		"    arg.a = arg.a / 2;\n"
7518		"}\n"
7519		"\n"
7520		"subroutine (routine_type_2) void decrement(inout data arg)\n"
7521		"{\n"
7522		"    arg.r = arg.r - 1;\n"
7523		"    arg.g = arg.g - 1;\n"
7524		"    arg.b = arg.b - 1;\n"
7525		"    arg.a = arg.a - 1;\n"
7526		"}\n"
7527		"\n"
7528		"subroutine uniform routine_type_1 routine_1;\n"
7529		"subroutine uniform routine_type_2 routine_2;\n"
7530		"\n"
7531		"uniform uvec4 uni_input;\n"
7532		"\n"
7533		"out uvec4 out_routine_1;\n"
7534		"out uvec4 out_routine_2;\n"
7535		"\n"
7536		"\n"
7537		"void main()\n"
7538		"{\n"
7539		"    data routine_1_input;\n"
7540		"    data routine_1_output;\n"
7541		"    data routine_2_arg;\n"
7542		"\n"
7543		"    routine_1_input.r = uni_input.r;\n"
7544		"    routine_1_input.g = uni_input.g;\n"
7545		"    routine_1_input.b = uni_input.b;\n"
7546		"    routine_1_input.a = uni_input.a;\n"
7547		"\n"
7548		"    routine_2_arg.r = uni_input.r;\n"
7549		"    routine_2_arg.g = uni_input.g;\n"
7550		"    routine_2_arg.b = uni_input.b;\n"
7551		"    routine_2_arg.a = uni_input.a;\n"
7552		"\n"
7553		"    routine_1(routine_1_input, routine_1_output);\n"
7554		"    routine_2(routine_2_arg);\n"
7555		"\n"
7556		"    out_routine_1.r = routine_1_output.r;\n"
7557		"    out_routine_1.g = routine_1_output.g;\n"
7558		"    out_routine_1.b = routine_1_output.b;\n"
7559		"    out_routine_1.a = routine_1_output.a;\n"
7560		"\n"
7561		"    out_routine_2.r = routine_2_arg.r;\n"
7562		"    out_routine_2.g = routine_2_arg.g;\n"
7563		"    out_routine_2.b = routine_2_arg.b;\n"
7564		"    out_routine_2.a = routine_2_arg.a;\n"
7565		"}\n"
7566		"\n";
7567
7568	static const GLchar* subroutine_names[][2] = { { "invert", "increment" }, { "div_by_2", "decrement" } };
7569	static const GLuint  n_subroutine_types	= sizeof(subroutine_names) / sizeof(subroutine_names[0]);
7570
7571	static const GLchar* subroutine_uniform_names[] = { "routine_1", "routine_2" };
7572	static const GLuint  n_subroutine_uniform_names =
7573		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
7574
7575	static const GLchar* uniform_name	= "uni_input";
7576	static const GLchar* varying_names[] = { "out_routine_1", "out_routine_2" };
7577
7578	static const GLuint n_varying_names				   = sizeof(varying_names) / sizeof(varying_names[0]);
7579	static const GLuint transform_feedback_buffer_size = n_varying_names * 4 * sizeof(GLuint);
7580
7581	/* Test data */
7582	static const Utils::vec4<GLuint> uni_input[] = { Utils::vec4<GLuint>(8, 64, 4096, 16777216),
7583													 Utils::vec4<GLuint>(8, 64, 4096, 16777216) };
7584
7585	static const Utils::vec4<GLuint> out_routine_1[] = { Utils::vec4<GLuint>(16777216, 4096, 64, 8),
7586														 Utils::vec4<GLuint>(9, 65, 4097, 16777217) };
7587
7588	static const Utils::vec4<GLuint> out_routine_2[] = { Utils::vec4<GLuint>(4, 32, 2048, 8388608),
7589														 Utils::vec4<GLuint>(7, 63, 4095, 16777215) };
7590
7591	static const GLuint n_test_cases = 2;
7592
7593	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
7594	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
7595	{
7596		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
7597	}
7598
7599	/* GL objects */
7600	Utils::program	 program(m_context);
7601	Utils::buffer	  transform_feedback_buffer(m_context);
7602	Utils::vertexArray vao(m_context);
7603
7604	bool is_program_binary_supported = program.isProgramBinarySupported();
7605
7606	/* Init GL objects */
7607	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code,
7608				  varying_names /* varying_names */, n_varying_names /* n_varyings */);
7609
7610	/* Do not execute the test if GL_ARB_get_program_binary is not supported */
7611	if (true == is_program_binary_supported)
7612	{
7613		/* Get subroutine indices */
7614		for (GLuint type = 0; type < n_subroutine_types; ++type)
7615		{
7616			m_initial_subroutine_indices[type][0] =
7617				program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER);
7618
7619			m_initial_subroutine_indices[type][1] =
7620				program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER);
7621		}
7622
7623		/* Get subroutine uniform locations */
7624		for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7625		{
7626			m_initial_subroutine_uniform_locations[uniform] =
7627				program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
7628		}
7629
7630		/* Delete program and recreate it from binary */
7631		std::vector<GLubyte> program_binary;
7632		GLenum				 binary_format;
7633
7634		program.getBinary(program_binary, binary_format);
7635		program.remove();
7636		program.createFromBinary(program_binary, binary_format);
7637	}
7638
7639	program.use();
7640
7641	vao.generate();
7642	vao.bind();
7643
7644	transform_feedback_buffer.generate();
7645	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
7646									 GL_DYNAMIC_COPY);
7647	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
7648
7649	/* Get subroutine indices */
7650	for (GLuint type = 0; type < n_subroutine_types; ++type)
7651	{
7652		m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER);
7653		m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER);
7654	}
7655
7656	/* Get subroutine uniform locations */
7657	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7658	{
7659		m_subroutine_uniform_locations[uniform] =
7660			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
7661	}
7662
7663	/* Get uniform locations */
7664	m_uniform_location = program.getUniformLocation(uniform_name);
7665
7666	/* Test */
7667	bool result = true;
7668
7669	/* Test program binary */
7670	if (true == is_program_binary_supported)
7671	{
7672		/* Test indices and locations */
7673		if (false == testIndicesAndLocations())
7674		{
7675			static const GLuint n_subroutines_per_type = 2;
7676
7677			m_context.getTestContext().getLog() << tcu::TestLog::Message
7678												<< "Error. Subroutine indices or subroutine uniform location changed."
7679												<< tcu::TestLog::EndMessage;
7680
7681			for (GLuint type = 0; type < n_subroutine_types; ++type)
7682			{
7683				for (GLuint i = 0; i < n_subroutines_per_type; ++i)
7684				{
7685					m_context.getTestContext().getLog()
7686						<< tcu::TestLog::Message << "Subroutine: " << subroutine_names[type][i]
7687						<< " index: " << m_subroutine_indices[type][i]
7688						<< " initial index: " << m_initial_subroutine_indices[type][i] << tcu::TestLog::EndMessage;
7689				}
7690			}
7691
7692			for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7693			{
7694				m_context.getTestContext().getLog()
7695					<< tcu::TestLog::Message << "Subroutine uniform: " << subroutine_uniform_names[uniform]
7696					<< " location: " << m_subroutine_uniform_locations[uniform]
7697					<< " initial location: " << m_initial_subroutine_uniform_locations[uniform]
7698					<< tcu::TestLog::EndMessage;
7699			}
7700
7701			result = false;
7702		}
7703
7704		/* Test draw with deafult set of subroutines */
7705		if (false == testDefaultSubroutineSet(uni_input[0], out_routine_1, out_routine_2))
7706		{
7707			result = false;
7708		}
7709	}
7710
7711	for (GLuint i = 0; i < n_test_cases; ++i)
7712	{
7713		if (false == testDraw(i, uni_input[i], out_routine_1[i], out_routine_2[i]))
7714		{
7715			result = false;
7716		}
7717	}
7718
7719	/* Set result */
7720	if (true == result)
7721	{
7722		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7723	}
7724	else
7725	{
7726		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7727	}
7728
7729	/* Done */
7730	return tcu::TestNode::STOP;
7731}
7732
7733/** Execute draw call and verify results
7734 *
7735 * @param uni_input                 Input data
7736 * @param expected_routine_1_result Set of expected results of "routine_1"
7737 * @param expected_routine_2_result Set of expected results of "routine_2"
7738 *
7739 * @return true if test pass, false otherwise
7740 **/
7741bool FunctionalTest14_15::testDefaultSubroutineSet(const Utils::vec4<glw::GLuint>& uni_input,
7742												   const Utils::vec4<glw::GLuint>  expected_routine_1_result[2],
7743												   const Utils::vec4<glw::GLuint>  expected_routine_2_result[2]) const
7744{
7745	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
7746	bool				  result = true;
7747
7748	/* Set up input data uniforms */
7749	gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w);
7750	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
7751
7752	/* Execute draw call with transform feedback */
7753	gl.beginTransformFeedback(GL_POINTS);
7754	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
7755
7756	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
7757	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
7758
7759	gl.endTransformFeedback();
7760	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
7761
7762	/* Capture results */
7763	GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7764	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
7765
7766	Utils::vec4<GLuint> routine_1_result;
7767	Utils::vec4<GLuint> routine_2_result;
7768
7769	routine_1_result.m_x = feedback_data[0 + 0];
7770	routine_1_result.m_y = feedback_data[0 + 1];
7771	routine_1_result.m_z = feedback_data[0 + 2];
7772	routine_1_result.m_w = feedback_data[0 + 3];
7773
7774	routine_2_result.m_x = feedback_data[4 + 0];
7775	routine_2_result.m_y = feedback_data[4 + 1];
7776	routine_2_result.m_z = feedback_data[4 + 2];
7777	routine_2_result.m_w = feedback_data[4 + 3];
7778
7779	/* Unmap buffer */
7780	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7781	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
7782
7783	/* Verifiy */
7784	result = result &&
7785			 ((routine_1_result == expected_routine_1_result[0]) || (routine_1_result == expected_routine_1_result[1]));
7786
7787	result = result &&
7788			 ((routine_2_result == expected_routine_2_result[0]) || (routine_2_result == expected_routine_2_result[1]));
7789
7790	/* Log error if any */
7791	if (false == result)
7792	{
7793		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
7794											<< tcu::TestLog::EndMessage;
7795
7796		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
7797
7798		message << "Routine_1, result: ";
7799
7800		routine_1_result.log(message);
7801
7802		message << "Routine_2, result: ";
7803
7804		routine_2_result.log(message);
7805
7806		message << tcu::TestLog::EndMessage;
7807	}
7808
7809	/* Done */
7810	return result;
7811}
7812
7813/** Execute draw call and verify results
7814 *
7815 * @param routine_configuration     Subroutine "type" ordinal
7816 * @param uni_input                 Input data
7817 * @param expected_routine_1_result Expected results of "routine_1"
7818 * @param expected_routine_2_result Expected results of "routine_2"
7819 *
7820 * @return true if test pass, false otherwise
7821 **/
7822bool FunctionalTest14_15::testDraw(glw::GLuint routine_configuration, const Utils::vec4<glw::GLuint>& uni_input,
7823								   const Utils::vec4<glw::GLuint>& expected_routine_1_result,
7824								   const Utils::vec4<glw::GLuint>& expected_routine_2_result) const
7825{
7826	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
7827	bool				  result = true;
7828	GLuint				  subroutine_indices[2];
7829	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
7830
7831	/* Set up input data uniforms */
7832	gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w);
7833	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
7834
7835	/* Prepare subroutine uniform data */
7836	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
7837	{
7838		const GLuint location = m_subroutine_uniform_locations[i];
7839
7840		subroutine_indices[location] = m_subroutine_indices[i][routine_configuration];
7841	}
7842
7843	/* Set up subroutine uniforms */
7844	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
7845	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
7846
7847	/* Execute draw call with transform feedback */
7848	gl.beginTransformFeedback(GL_POINTS);
7849	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
7850
7851	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
7852	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
7853
7854	gl.endTransformFeedback();
7855	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
7856
7857	/* Capture results */
7858	GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7859	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
7860
7861	Utils::vec4<GLuint> routine_1_result;
7862	Utils::vec4<GLuint> routine_2_result;
7863
7864	routine_1_result.m_x = feedback_data[0 + 0];
7865	routine_1_result.m_y = feedback_data[0 + 1];
7866	routine_1_result.m_z = feedback_data[0 + 2];
7867	routine_1_result.m_w = feedback_data[0 + 3];
7868
7869	routine_2_result.m_x = feedback_data[4 + 0];
7870	routine_2_result.m_y = feedback_data[4 + 1];
7871	routine_2_result.m_z = feedback_data[4 + 2];
7872	routine_2_result.m_w = feedback_data[4 + 3];
7873
7874	/* Unmap buffer */
7875	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7876	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
7877
7878	/* Verifiy */
7879	result = result && (routine_1_result == expected_routine_1_result);
7880	result = result && (routine_2_result == expected_routine_2_result);
7881
7882	/* Log error if any */
7883	if (false == result)
7884	{
7885		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
7886											<< tcu::TestLog::EndMessage;
7887
7888		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
7889
7890		message << "Routine_1, result: ";
7891
7892		routine_1_result.log(message);
7893
7894		message << ", expected: ";
7895
7896		expected_routine_1_result.log(message);
7897
7898		message << "Routine_2, result: ";
7899
7900		routine_2_result.log(message);
7901
7902		message << ", expected: ";
7903
7904		expected_routine_2_result.log(message);
7905
7906		message << tcu::TestLog::EndMessage;
7907	}
7908
7909	/* Done */
7910	return result;
7911}
7912
7913/** Verify initial and current values of subroutine indices and subroutines uniform locations
7914 *
7915 * @return true if test pass, false otherwise
7916 **/
7917bool FunctionalTest14_15::testIndicesAndLocations() const
7918{
7919	static const GLuint n_subroutine_types = 2;
7920	bool				result			   = true;
7921
7922	/* Verify subroutine indices */
7923	for (GLuint type = 0; type < n_subroutine_types; ++type)
7924	{
7925		result = result && (m_subroutine_indices[type][0] == m_initial_subroutine_indices[type][0]);
7926		result = result && (m_subroutine_indices[type][1] == m_initial_subroutine_indices[type][1]);
7927	}
7928
7929	/* Verify subroutine uniform locations */
7930	for (GLuint uniform = 0; uniform < n_subroutine_types; ++uniform)
7931	{
7932		result = result && (m_subroutine_uniform_locations[uniform] == m_initial_subroutine_uniform_locations[uniform]);
7933	}
7934
7935	return result;
7936}
7937
7938/** Constructor.
7939 *
7940 *  @param context Rendering context.
7941 *
7942 **/
7943FunctionalTest16::FunctionalTest16(deqp::Context& context)
7944	: TestCase(context, "subroutine_uniform_reset",
7945			   "Checks that when the active program for a shader stage is re-linke or "
7946			   "changed by a call to UseProgram, BindProgramPipeline, or UseProgramStages,"
7947			   " subroutine uniforms for that stage are reset to arbitrarily chosen default "
7948			   "functions with compatible subroutine types.")
7949	, m_are_pipeline_objects_supported(false)
7950	, m_has_test_passed(true)
7951{
7952	memset(m_fs_ids, 0, sizeof(m_fs_ids));
7953	memset(m_gs_ids, 0, sizeof(m_gs_ids));
7954	memset(m_po_ids, 0, sizeof(m_po_ids));
7955	memset(m_tc_ids, 0, sizeof(m_tc_ids));
7956	memset(m_te_ids, 0, sizeof(m_te_ids));
7957	memset(m_vs_ids, 0, sizeof(m_vs_ids));
7958
7959	memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids));
7960	memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids));
7961	memset(m_pipeline_object_ids, 0, sizeof(m_pipeline_object_ids));
7962	memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids));
7963	memset(m_te_po_ids, 0, sizeof(m_te_po_ids));
7964	memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids));
7965}
7966
7967/** Deinitializes all GL objects that may have been created during test execution. */
7968void FunctionalTest16::deinit()
7969{
7970	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7971
7972	for (unsigned int n_id = 0; n_id < 2; ++n_id)
7973	{
7974		if (m_fs_ids[n_id] != 0)
7975		{
7976			gl.deleteShader(m_fs_ids[n_id]);
7977
7978			m_fs_ids[n_id] = 0;
7979		}
7980
7981		if (m_fs_po_ids[n_id] != 0)
7982		{
7983			gl.deleteProgram(m_fs_po_ids[n_id]);
7984
7985			m_fs_po_ids[n_id] = 0;
7986		}
7987
7988		if (m_gs_ids[n_id] != 0)
7989		{
7990			gl.deleteShader(m_gs_ids[n_id]);
7991
7992			m_gs_ids[n_id] = 0;
7993		}
7994
7995		if (m_gs_po_ids[n_id] != 0)
7996		{
7997			gl.deleteProgram(m_gs_po_ids[n_id]);
7998
7999			m_gs_po_ids[n_id] = 0;
8000		}
8001
8002		if (m_pipeline_object_ids[n_id] != 0)
8003		{
8004			gl.deleteProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id);
8005		}
8006
8007		if (m_po_ids[n_id] != 0)
8008		{
8009			gl.deleteProgram(m_po_ids[n_id]);
8010
8011			m_po_ids[n_id] = 0;
8012		}
8013
8014		if (m_tc_ids[n_id] != 0)
8015		{
8016			gl.deleteShader(m_tc_ids[n_id]);
8017
8018			m_tc_ids[n_id] = 0;
8019		}
8020
8021		if (m_tc_po_ids[n_id] != 0)
8022		{
8023			gl.deleteProgram(m_tc_po_ids[n_id]);
8024
8025			m_tc_po_ids[n_id] = 0;
8026		}
8027
8028		if (m_te_ids[n_id] != 0)
8029		{
8030			gl.deleteShader(m_te_ids[n_id]);
8031
8032			m_te_ids[n_id] = 0;
8033		}
8034
8035		if (m_te_po_ids[n_id] != 0)
8036		{
8037			gl.deleteProgram(m_te_po_ids[n_id]);
8038
8039			m_te_po_ids[n_id] = 0;
8040		}
8041
8042		if (m_vs_ids[n_id] != 0)
8043		{
8044			gl.deleteShader(m_vs_ids[n_id]);
8045
8046			m_vs_ids[n_id] = 0;
8047		}
8048
8049		if (m_vs_po_ids[n_id] != 0)
8050		{
8051			gl.deleteProgram(m_vs_po_ids[n_id]);
8052
8053			m_vs_po_ids[n_id] = 0;
8054		}
8055	} /* for (both IDs) */
8056}
8057
8058/** Retrieves body of a shader that should be used for user-specified shader stage.
8059 *  This function returns slightly different implementations, depending on index of
8060 *  the program/pipeline object the shader will be used for.
8061 *
8062 *  @param shader_stage Stage the shader body is to be returned for.
8063 *  @param n_id         Index of the shader (as per description).
8064 *
8065 *  @return Requested string.
8066 **/
8067std::string FunctionalTest16::getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_id) const
8068{
8069	std::stringstream result_sstream;
8070
8071	result_sstream << "#version 400\n"
8072					  "\n"
8073					  "#extension GL_ARB_shader_subroutine : require\n"
8074					  "\n";
8075
8076	switch (shader_stage)
8077	{
8078	case Utils::SHADER_STAGE_VERTEX:
8079	{
8080		result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n";
8081		break;
8082	}
8083	case Utils::SHADER_STAGE_GEOMETRY:
8084	{
8085		result_sstream << "layout(points)                   in;\n"
8086						  "layout(points, max_vertices = 1) out;\n";
8087		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8088		result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n";
8089		break;
8090	}
8091
8092	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
8093	{
8094		result_sstream << "layout(vertices = 4) out;\n";
8095		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8096		result_sstream << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n";
8097		break;
8098	}
8099
8100	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
8101	{
8102		result_sstream << "layout(quads) in;\n";
8103		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8104		result_sstream << "out gl_PerVertex { vec4 gl_Position; };\n";
8105		break;
8106	}
8107
8108	default:
8109		break;
8110	} /* switch (shader_stage) */
8111
8112	result_sstream << "\n"
8113					  "subroutine void subroutineType (inout vec4 result);\n"
8114					  "subroutine vec4 subroutineType2(in    vec4 data);\n"
8115					  "\n"
8116					  "subroutine(subroutineType) void function1(inout vec4 result)\n"
8117					  "{\n"
8118					  "    result += vec4("
8119				   << (n_id + 1) << ", " << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4)
8120				   << ");\n"
8121					  "}\n"
8122					  "subroutine(subroutineType) void function2(inout vec4 result)\n"
8123					  "{\n"
8124					  "    result += vec4("
8125				   << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4) << ", " << (n_id + 5)
8126				   << ");\n"
8127					  "}\n"
8128					  "\n"
8129					  "subroutine(subroutineType2) vec4 function3(in vec4 data)\n"
8130					  "{\n"
8131					  "    return data * data;\n"
8132					  "}\n"
8133					  "subroutine(subroutineType2) vec4 function4(in vec4 data)\n"
8134					  "{\n"
8135					  "    return data + data;\n"
8136					  "}\n"
8137					  "\n"
8138					  "subroutine uniform subroutineType  subroutine1;\n"
8139					  "subroutine uniform subroutineType  subroutine2;\n"
8140					  "subroutine uniform subroutineType2 subroutine3;\n"
8141					  "subroutine uniform subroutineType2 subroutine4;\n"
8142					  "\n";
8143
8144	if (shader_stage == Utils::SHADER_STAGE_FRAGMENT)
8145	{
8146		result_sstream << "out vec4 result;\n";
8147	}
8148
8149	result_sstream << "void main()\n"
8150					  "{\n";
8151
8152	switch (shader_stage)
8153	{
8154	case Utils::SHADER_STAGE_FRAGMENT:
8155	{
8156		result_sstream << "    result = vec4(0);\n"
8157					   << "    subroutine1(result);\n"
8158						  "    subroutine2(result);\n"
8159						  "    result = subroutine3(result) + subroutine4(result);\n";
8160
8161		break;
8162	}
8163
8164	case Utils::SHADER_STAGE_GEOMETRY:
8165	{
8166		result_sstream << "    gl_Position = vec4(0);\n"
8167						  "    subroutine1(gl_Position);\n"
8168						  "    subroutine2(gl_Position);\n"
8169						  "    gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n"
8170						  "    EmitVertex();\n";
8171
8172		break;
8173	}
8174
8175	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
8176	{
8177		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0);\n"
8178						  "    subroutine1(gl_out[gl_InvocationID].gl_Position);\n"
8179						  "    subroutine2(gl_out[gl_InvocationID].gl_Position);\n"
8180						  "    gl_out[gl_InvocationID].gl_Position = subroutine3(gl_in[0].gl_Position) + "
8181						  "subroutine4(gl_in[0].gl_Position);\n";
8182
8183		break;
8184	}
8185
8186	case Utils::SHADER_STAGE_VERTEX:
8187	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
8188	{
8189		result_sstream << "    gl_Position = vec4(0);\n"
8190						  "    subroutine1(gl_Position);\n"
8191						  "    subroutine2(gl_Position);\n"
8192						  "    gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n";
8193
8194		break;
8195	}
8196
8197	default:
8198		break;
8199	} /* switch (shader_stage) */
8200
8201	result_sstream << "}\n";
8202
8203	return result_sstream.str();
8204}
8205
8206/** Initializes all objects required to run the test. */
8207void FunctionalTest16::initTest()
8208{
8209	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8210
8211	for (unsigned int n_id = 0; n_id < 2 /* test program/shader objects */; ++n_id)
8212	{
8213		const std::string fs_body = getShaderBody(Utils::SHADER_STAGE_FRAGMENT, n_id);
8214		const std::string gs_body = getShaderBody(Utils::SHADER_STAGE_GEOMETRY, n_id);
8215		const std::string tc_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_CONTROL, n_id);
8216		const std::string te_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_EVALUATION, n_id);
8217		const std::string vs_body = getShaderBody(Utils::SHADER_STAGE_VERTEX, n_id);
8218
8219		if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */
8220								 DE_NULL,												   /* n_xfb_varyings */
8221								 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,
8222								 m_po_ids + n_id))
8223		{
8224			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build test program object, index:"
8225														   "["
8226							   << n_id << "]" << tcu::TestLog::EndMessage;
8227
8228			TCU_FAIL("Failed to build a test program");
8229		}
8230
8231		if (m_are_pipeline_objects_supported)
8232		{
8233			/* Initialize shader program objects */
8234			const char* fs_body_raw_ptr = fs_body.c_str();
8235			const char* gs_body_raw_ptr = gs_body.c_str();
8236			glw::GLint  link_status[5]  = { GL_FALSE };
8237			const char* tc_body_raw_ptr = tc_body.c_str();
8238			const char* te_body_raw_ptr = te_body.c_str();
8239			const char* vs_body_raw_ptr = vs_body.c_str();
8240
8241			m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr);
8242			m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr);
8243			m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr);
8244			m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr);
8245			m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr);
8246			GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
8247
8248			gl.getProgramiv(m_fs_po_ids[n_id], GL_LINK_STATUS, link_status + 0);
8249			gl.getProgramiv(m_gs_po_ids[n_id], GL_LINK_STATUS, link_status + 1);
8250			gl.getProgramiv(m_tc_po_ids[n_id], GL_LINK_STATUS, link_status + 2);
8251			gl.getProgramiv(m_te_po_ids[n_id], GL_LINK_STATUS, link_status + 3);
8252			gl.getProgramiv(m_vs_po_ids[n_id], GL_LINK_STATUS, link_status + 4);
8253			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8254
8255			if (link_status[0] == GL_FALSE)
8256				TCU_FAIL("Fragment shader program failed to link");
8257			if (link_status[1] == GL_FALSE)
8258				TCU_FAIL("Geometry shader program failed to link");
8259			if (link_status[2] == GL_FALSE)
8260				TCU_FAIL("Tessellation control shader program failed to link");
8261			if (link_status[3] == GL_FALSE)
8262				TCU_FAIL("Tessellation evaluation shader program failed to link");
8263			if (link_status[4] == GL_FALSE)
8264				TCU_FAIL("Vertex shader program failed to link");
8265
8266			/* Initialize pipeline program object */
8267			gl.genProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id);
8268			GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
8269
8270			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_FRAGMENT_SHADER_BIT, m_fs_po_ids[n_id]);
8271			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_GEOMETRY_SHADER_BIT, m_gs_po_ids[n_id]);
8272			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_CONTROL_SHADER_BIT, m_tc_po_ids[n_id]);
8273			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_EVALUATION_SHADER_BIT, m_te_po_ids[n_id]);
8274			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_id]);
8275			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8276		}
8277
8278		/* Retrieve subroutine locations */
8279		struct _item
8280		{
8281			glw::GLuint	po_id;
8282			_shader_stage& stage;
8283			glw::GLuint	so_id;
8284			glw::GLenum	so_type;
8285		} items[] = {
8286			{ m_po_ids[n_id], m_po_descriptors[n_id].fragment, m_fs_ids[n_id], GL_FRAGMENT_SHADER },
8287			{ m_po_ids[n_id], m_po_descriptors[n_id].geometry, m_gs_ids[n_id], GL_GEOMETRY_SHADER },
8288			{ m_po_ids[n_id], m_po_descriptors[n_id].tess_control, m_tc_ids[n_id], GL_TESS_CONTROL_SHADER },
8289			{ m_po_ids[n_id], m_po_descriptors[n_id].tess_evaluation, m_te_ids[n_id], GL_TESS_EVALUATION_SHADER },
8290			{ m_po_ids[n_id], m_po_descriptors[n_id].vertex, m_vs_ids[n_id], GL_VERTEX_SHADER },
8291
8292			{ m_fs_po_ids[n_id], m_fs_po_descriptors[n_id], m_fs_po_ids[n_id], GL_FRAGMENT_SHADER },
8293			{ m_gs_po_ids[n_id], m_gs_po_descriptors[n_id], m_gs_po_ids[n_id], GL_GEOMETRY_SHADER },
8294			{ m_tc_po_ids[n_id], m_tc_po_descriptors[n_id], m_tc_po_ids[n_id], GL_TESS_CONTROL_SHADER },
8295			{ m_te_po_ids[n_id], m_te_po_descriptors[n_id], m_te_po_ids[n_id], GL_TESS_EVALUATION_SHADER },
8296			{ m_vs_po_ids[n_id], m_vs_po_descriptors[n_id], m_vs_po_ids[n_id], GL_VERTEX_SHADER },
8297		};
8298		const unsigned int n_items = sizeof(items) / sizeof(items[0]);
8299
8300		for (unsigned int n_item = 0; n_item < n_items; ++n_item)
8301		{
8302			_item& current_item = items[n_item];
8303
8304			current_item.stage.function1_index =
8305				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function1");
8306			current_item.stage.function2_index =
8307				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function2");
8308			current_item.stage.function3_index =
8309				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function3");
8310			current_item.stage.function4_index =
8311				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function4");
8312			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
8313
8314			if (current_item.stage.function1_index == GL_INVALID_INDEX ||
8315				current_item.stage.function2_index == GL_INVALID_INDEX ||
8316				current_item.stage.function3_index == GL_INVALID_INDEX ||
8317				current_item.stage.function4_index == GL_INVALID_INDEX)
8318			{
8319				TCU_FAIL("Subroutine name was not recognized.");
8320			}
8321
8322			current_item.stage.subroutine1_uniform_location =
8323				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine1");
8324			current_item.stage.subroutine2_uniform_location =
8325				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine2");
8326			current_item.stage.subroutine3_uniform_location =
8327				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine3");
8328			current_item.stage.subroutine4_uniform_location =
8329				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine4");
8330			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
8331
8332			if (current_item.stage.subroutine1_uniform_location == -1 ||
8333				current_item.stage.subroutine2_uniform_location == -1 ||
8334				current_item.stage.subroutine3_uniform_location == -1 ||
8335				current_item.stage.subroutine4_uniform_location == -1)
8336			{
8337				TCU_FAIL("Subroutine uniform name was not recognized.");
8338			}
8339
8340			if (m_po_ids[n_id] == current_item.po_id)
8341			{
8342				gl.useProgram(current_item.po_id);
8343				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8344			}
8345			else
8346			{
8347				/* Temporarily bind the program pipeline. */
8348				gl.bindProgramPipeline(m_pipeline_object_ids[n_id]);
8349				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8350			}
8351
8352			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine1_uniform_location,
8353									   &current_item.stage.default_subroutine1_value);
8354			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine2_uniform_location,
8355									   &current_item.stage.default_subroutine2_value);
8356			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine3_uniform_location,
8357									   &current_item.stage.default_subroutine3_value);
8358			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine4_uniform_location,
8359									   &current_item.stage.default_subroutine4_value);
8360			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed.");
8361
8362			current_item.stage.gl_stage = current_item.so_type;
8363
8364			if (m_po_ids[n_id] != current_item.po_id)
8365			{
8366				/* Unbind the program pipeline object */
8367				gl.bindProgramPipeline(0);
8368				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8369			}
8370		} /* for (all items) */
8371
8372		/* Make sure the default subroutine choices are valid. */
8373		verifySubroutineUniformValues(
8374			TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, /* makes the verification routine use program object descriptor */
8375			n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES);
8376
8377		if (m_are_pipeline_objects_supported)
8378		{
8379			gl.useProgram(0);
8380			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8381
8382			gl.bindProgramPipeline(m_pipeline_object_ids[n_id]);
8383			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8384			{
8385				verifySubroutineUniformValues(
8386					TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT, /* makes the verification routine use pipeline object descriptor */
8387					n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES);
8388			}
8389			gl.bindProgramPipeline(0);
8390			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8391		}
8392	} /* for (both program descriptors) */
8393}
8394
8395/** Retrieves IDs of shaders OR shader program objects, depending on which of the two
8396 *  the caller requests for.
8397 *
8398 *  @param retrieve_program_object_shader_ids true if the caller wishes to retrieve shader object IDs,
8399 *                                            false to return shader program IDs.
8400 *  @param n_id                               Index of the program/pipeline object the shaders
8401 *                                            are a part of.
8402 *  @param out_shader_stages                  Deref will be used to store exactly five IDs. Must not
8403 *                                            be NULL.
8404 **/
8405void FunctionalTest16::getShaderStages(bool retrieve_program_object_shader_ids, const unsigned int& n_id,
8406									   const _shader_stage** out_shader_stages) const
8407{
8408	if (retrieve_program_object_shader_ids)
8409	{
8410		out_shader_stages[0] = &m_po_descriptors[n_id].vertex;
8411		out_shader_stages[1] = &m_po_descriptors[n_id].tess_control;
8412		out_shader_stages[2] = &m_po_descriptors[n_id].tess_evaluation;
8413		out_shader_stages[3] = &m_po_descriptors[n_id].geometry;
8414		out_shader_stages[4] = &m_po_descriptors[n_id].fragment;
8415	}
8416	else
8417	{
8418		out_shader_stages[0] = m_vs_po_descriptors + n_id;
8419		out_shader_stages[1] = m_tc_po_descriptors + n_id;
8420		out_shader_stages[2] = m_te_po_descriptors + n_id;
8421		out_shader_stages[3] = m_gs_po_descriptors + n_id;
8422		out_shader_stages[4] = m_fs_po_descriptors + n_id;
8423	}
8424}
8425
8426/** Executes test iteration.
8427 *
8428 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8429 */
8430tcu::TestNode::IterateResult FunctionalTest16::iterate()
8431{
8432	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8433
8434	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
8435	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
8436	{
8437		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
8438	}
8439
8440	m_are_pipeline_objects_supported =
8441		m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects");
8442
8443	/* Initialize GL objects required to run the test */
8444	initTest();
8445
8446	/* Iterate over both pipelines/programs and verify that calling glUseProgram() /
8447	 * glBindProgramPipeline() / glUseProgramStages() resets subroutine uniform configuration.
8448	 */
8449	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
8450	{
8451		if (static_cast<_test_case>(test_case) != TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT &&
8452			!m_are_pipeline_objects_supported)
8453		{
8454			/* Current test case requires GL_ARB_separate_shader_objects support which is
8455			 * unavaiable on the platform that we're testing
8456			 */
8457			continue;
8458		}
8459
8460		for (unsigned int n_object_id = 0; n_object_id < 2; /* pipeline/program objects allocated for the test */
8461			 ++n_object_id)
8462		{
8463			/* Verify that currently reported subroutine uniform values are equal to default values */
8464			if (test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT)
8465			{
8466				gl.useProgram(m_po_ids[n_object_id]);
8467				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
8468			}
8469			else
8470			{
8471				gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]);
8472				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed");
8473			}
8474
8475			verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8476										  SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8477
8478			/* Re-configure subroutine uniforms so that they point to different subroutines than
8479			 * the default ones.
8480			 */
8481			const _shader_stage* stages[5 /* fs+gs+tc+te+vs */] = { DE_NULL };
8482
8483			getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT,
8484							n_object_id, stages);
8485
8486			for (unsigned int n_stage = 0; n_stage < 5 /* fs+gs+tc+te+vs stages */; ++n_stage)
8487			{
8488				const _shader_stage& current_stage				 = *(stages[n_stage]);
8489				glw::GLuint			 subroutine_configuration[4] = { GL_INVALID_INDEX };
8490
8491				subroutine_configuration[0] =
8492					(current_stage.default_subroutine1_value == current_stage.function1_index) ?
8493						current_stage.function2_index :
8494						current_stage.function1_index;
8495				subroutine_configuration[1] =
8496					(current_stage.default_subroutine2_value == current_stage.function1_index) ?
8497						current_stage.function2_index :
8498						current_stage.function1_index;
8499				subroutine_configuration[2] =
8500					(current_stage.default_subroutine3_value == current_stage.function3_index) ?
8501						current_stage.function4_index :
8502						current_stage.function3_index;
8503				subroutine_configuration[3] =
8504					(current_stage.default_subroutine4_value == current_stage.function3_index) ?
8505						current_stage.function4_index :
8506						current_stage.function3_index;
8507
8508				gl.uniformSubroutinesuiv(current_stage.gl_stage, 4 /* count */, subroutine_configuration);
8509				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
8510			} /* for (all stages) */
8511
8512			verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8513										  SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8514
8515			/* Execute test case-specific code */
8516			_shader_stage cached_shader_stage_data;
8517			bool		  stage_reset_status[Utils::SHADER_STAGE_COUNT] = { false, false, false, false, false };
8518			bool		  uses_stage_reset_status						= false;
8519
8520			switch (test_case)
8521			{
8522			case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT:
8523			{
8524				/* Switch to a different program object and then back to current PO.
8525				 * Subroutine uniforms should be back at their default settings, instead of
8526				 * the ones we've just set.
8527				 */
8528				gl.useProgram(m_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8529				gl.useProgram(m_po_ids[n_object_id]);
8530				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
8531
8532				break;
8533			}
8534
8535			case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT:
8536			{
8537				/* Switch to a different pipeline object and then back to the current one.
8538				 * Subroutine uniforms should be back at their default settings, instead of
8539				 * the ones we've just set.
8540				 */
8541				gl.bindProgramPipeline(
8542					m_pipeline_object_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8543				gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]);
8544				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
8545
8546				break;
8547			}
8548
8549			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE:
8550			{
8551				/* Change the fragment shader stage to a different one.
8552				 *
8553				 * Note: We also need to update internal descriptor since the subroutine/uniform
8554				 *       locations may be different between the two programs.
8555				 */
8556				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT,
8557									m_fs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8558				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8559
8560				cached_shader_stage_data		 = m_fs_po_descriptors[n_object_id];
8561				m_fs_po_descriptors[n_object_id] = m_fs_po_descriptors[(n_object_id + 1) % 2];
8562
8563				stage_reset_status[Utils::SHADER_STAGE_FRAGMENT] = true;
8564				uses_stage_reset_status							 = true;
8565
8566				break;
8567			}
8568
8569			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE:
8570			{
8571				/* Change the geometry shader stage to a different one.
8572				 *
8573				 * Note: We also need to update internal descriptor since the subroutine/uniform
8574				 *       locations may be different between the two programs.
8575				 */
8576				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT,
8577									m_gs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8578				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8579
8580				cached_shader_stage_data		 = m_gs_po_descriptors[n_object_id];
8581				m_gs_po_descriptors[n_object_id] = m_gs_po_descriptors[(n_object_id + 1) % 2];
8582
8583				stage_reset_status[Utils::SHADER_STAGE_GEOMETRY] = true;
8584				uses_stage_reset_status							 = true;
8585
8586				break;
8587			}
8588
8589			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE:
8590			{
8591				/* Change the tessellation control shader stage to a different one.
8592				 *
8593				 * Note: We also need to update internal descriptor since the subroutine/uniform
8594				 *       locations may be different between the two programs.
8595				 */
8596				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT,
8597									m_tc_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8598				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8599
8600				cached_shader_stage_data		 = m_tc_po_descriptors[n_object_id];
8601				m_tc_po_descriptors[n_object_id] = m_tc_po_descriptors[(n_object_id + 1) % 2];
8602
8603				stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_CONTROL] = true;
8604				uses_stage_reset_status										 = true;
8605
8606				break;
8607			}
8608
8609			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE:
8610			{
8611				/* Change the tessellation evaluation shader stage to a different one.
8612				 *
8613				 * Note: We also need to update internal descriptor since the subroutine/uniform
8614				 *       locations may be different between the two programs.
8615				 */
8616				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT,
8617									m_te_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8618				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8619
8620				cached_shader_stage_data		 = m_te_po_descriptors[n_object_id];
8621				m_te_po_descriptors[n_object_id] = m_te_po_descriptors[(n_object_id + 1) % 2];
8622
8623				stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_EVALUATION] = true;
8624				uses_stage_reset_status											= true;
8625
8626				break;
8627			}
8628
8629			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE:
8630			{
8631				/* Change the vertex shader stage to a different one.
8632				 *
8633				 * Note: We also need to update internal descriptor since the subroutine/uniform
8634				 *       locations may be different between the two programs.
8635				 */
8636				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT,
8637									m_vs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8638				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8639
8640				cached_shader_stage_data		 = m_vs_po_descriptors[n_object_id];
8641				m_vs_po_descriptors[n_object_id] = m_vs_po_descriptors[(n_object_id + 1) % 2];
8642
8643				stage_reset_status[Utils::SHADER_STAGE_VERTEX] = true;
8644				uses_stage_reset_status						   = true;
8645
8646				break;
8647			}
8648
8649			default:
8650			{
8651				TCU_FAIL("Unrecognized test case");
8652			}
8653			} /* switch (test_case) */
8654
8655			/* Verify the subroutine uniform values are valid */
8656			if (!uses_stage_reset_status)
8657			{
8658				verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8659											  SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8660			}
8661			else
8662			{
8663				const _shader_stage* shader_stages[Utils::SHADER_STAGE_COUNT] = { DE_NULL };
8664
8665				getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT,
8666								n_object_id, shader_stages);
8667
8668				for (unsigned int n_shader_stage = 0; n_shader_stage < Utils::SHADER_STAGE_COUNT; ++n_shader_stage)
8669				{
8670					const _shader_stage& current_shader_stage = *(shader_stages[n_shader_stage]);
8671
8672					if (stage_reset_status[n_shader_stage])
8673					{
8674						verifySubroutineUniformValuesForShaderStage(current_shader_stage,
8675																	SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8676					}
8677					else
8678					{
8679						verifySubroutineUniformValuesForShaderStage(current_shader_stage,
8680																	SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8681					}
8682				} /* for (all shader stages) */
8683			}
8684
8685			/* Revert the changes some of the test cases appied */
8686			switch (test_case)
8687			{
8688			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE:
8689			{
8690				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT,
8691									m_fs_po_ids[n_object_id]);
8692				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8693
8694				m_fs_po_descriptors[n_object_id] = cached_shader_stage_data;
8695
8696				break;
8697			}
8698
8699			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE:
8700			{
8701				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT,
8702									m_gs_po_ids[n_object_id]);
8703				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8704
8705				m_gs_po_descriptors[n_object_id] = cached_shader_stage_data;
8706
8707				break;
8708			}
8709
8710			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE:
8711			{
8712				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT,
8713									m_tc_po_ids[n_object_id]);
8714				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8715
8716				m_tc_po_descriptors[n_object_id] = cached_shader_stage_data;
8717
8718				break;
8719			}
8720
8721			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE:
8722			{
8723				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT,
8724									m_te_po_ids[n_object_id]);
8725				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8726
8727				m_te_po_descriptors[n_object_id] = cached_shader_stage_data;
8728
8729				break;
8730			}
8731
8732			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE:
8733			{
8734				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_object_id]);
8735				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8736
8737				m_vs_po_descriptors[n_object_id] = cached_shader_stage_data;
8738
8739				break;
8740			}
8741
8742			default:
8743				break;
8744			} /* switch (test_case) */
8745
8746		} /* for (all program object descriptors) */
8747
8748		/* Unbind the program object */
8749		gl.useProgram(0);
8750		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8751	} /* for (all test cases) */
8752
8753	if (m_has_test_passed)
8754	{
8755		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8756	}
8757	else
8758	{
8759		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8760	}
8761
8762	return STOP;
8763}
8764
8765/** Verifies the subroutine uniform values reported by GL implementation. Depending on the test case,
8766 *  it will either query program object stages or separate shader objects.
8767 *
8768 *  @param test_case    Test case the verification is to be performed for.
8769 *  @param n_id         Index of the program/pipeline object to use for the verification
8770 *  @param verification Verification method.
8771 */
8772void FunctionalTest16::verifySubroutineUniformValues(const _test_case& test_case, const unsigned int& n_id,
8773													 const _subroutine_uniform_value_verification& verification)
8774{
8775	const _shader_stage* stages[] = {
8776		DE_NULL, /* fragment shader     stage slot */
8777		DE_NULL, /* geometry shader     stage slot */
8778		DE_NULL, /* tess control shader stage slot */
8779		DE_NULL, /* tess eval shader    stage slot */
8780		DE_NULL  /* vertex shader       stage slot */
8781	};
8782	const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
8783
8784	/* Verify that currently reported subroutine uniform values are equal to default values */
8785	getShaderStages(test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, n_id, stages);
8786
8787	for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
8788	{
8789		const _shader_stage& current_stage = *(stages[n_stage]);
8790
8791		verifySubroutineUniformValuesForShaderStage(current_stage, verification);
8792	} /* for (all items) */
8793}
8794
8795/** Verifies the subroutine uniform values reported by GL implementation for user-specified
8796 *  shader stage. If the verification fails, m_has_test_passed will be set to false.
8797 *
8798 *  @param shader_stage Descriptor of a shader stage that should be used for the process.
8799 *  @param verification Type of verification that should be performed.
8800 *
8801 **/
8802void FunctionalTest16::verifySubroutineUniformValuesForShaderStage(
8803	const _shader_stage& shader_stage, const _subroutine_uniform_value_verification& verification)
8804{
8805	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
8806	glw::GLuint			  result_values[4] = { 0 };
8807
8808	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine1_uniform_location, result_values + 0);
8809	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine2_uniform_location, result_values + 1);
8810	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine3_uniform_location, result_values + 2);
8811	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine4_uniform_location, result_values + 3);
8812	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed.");
8813
8814	if (verification == SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES)
8815	{
8816		if (!((result_values[0] == (GLuint)shader_stage.subroutine1_uniform_location ||
8817			   result_values[0] == (GLuint)shader_stage.subroutine2_uniform_location) &&
8818			  (result_values[1] == (GLuint)shader_stage.subroutine1_uniform_location ||
8819			   result_values[1] == (GLuint)shader_stage.subroutine2_uniform_location) &&
8820			  (result_values[2] == (GLuint)shader_stage.subroutine3_uniform_location ||
8821			   result_values[2] == (GLuint)shader_stage.subroutine4_uniform_location) &&
8822			  (result_values[3] == (GLuint)shader_stage.subroutine3_uniform_location ||
8823			   result_values[3] == (GLuint)shader_stage.subroutine4_uniform_location)))
8824		{
8825			m_testCtx.getLog() << tcu::TestLog::Message << "SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES validation failed. "
8826														   "Shader stage:["
8827							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8828																								  "expected data:["
8829							   << shader_stage.subroutine1_uniform_location << " OR "
8830							   << shader_stage.subroutine2_uniform_location << " x 2, "
8831							   << shader_stage.subroutine3_uniform_location << " OR "
8832							   << shader_stage.subroutine4_uniform_location << " x 2], "
8833																			   "found data:["
8834							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8835							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8836
8837			m_has_test_passed = false;
8838		}
8839	}
8840	else if (verification == SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES)
8841	{
8842		if (result_values[0] != shader_stage.default_subroutine1_value ||
8843			result_values[1] != shader_stage.default_subroutine2_value ||
8844			result_values[2] != shader_stage.default_subroutine3_value ||
8845			result_values[3] != shader_stage.default_subroutine4_value)
8846		{
8847			m_testCtx.getLog() << tcu::TestLog::Message
8848							   << "SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES validation failed. "
8849								  "Shader stage:["
8850							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8851																								  "expected data:["
8852							   << shader_stage.default_subroutine1_value << ", "
8853							   << shader_stage.default_subroutine2_value << ", "
8854							   << shader_stage.default_subroutine3_value << ", "
8855							   << shader_stage.default_subroutine4_value << "], "
8856																			"found data:["
8857							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8858							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8859
8860			m_has_test_passed = false;
8861		}
8862	}
8863	else
8864	{
8865		DE_ASSERT(verification == SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8866
8867		if (result_values[0] == shader_stage.default_subroutine1_value ||
8868			result_values[1] == shader_stage.default_subroutine2_value ||
8869			result_values[2] == shader_stage.default_subroutine3_value ||
8870			result_values[3] == shader_stage.default_subroutine4_value)
8871		{
8872			m_testCtx.getLog() << tcu::TestLog::Message
8873							   << "SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES validation failed. "
8874								  "Shader stage:["
8875							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8876																								  "expected data:!["
8877							   << shader_stage.default_subroutine1_value << ", "
8878							   << shader_stage.default_subroutine2_value << ", "
8879							   << shader_stage.default_subroutine3_value << ", "
8880							   << shader_stage.default_subroutine4_value << "], "
8881																			"found data:["
8882							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8883							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8884
8885			m_has_test_passed = false;
8886		}
8887	}
8888}
8889
8890/** Constructor.
8891 *
8892 *  @param context Rendering context.
8893 *
8894 **/
8895FunctionalTest17::FunctionalTest17(deqp::Context& context)
8896	: TestCase(context, "same_subroutine_and_subroutine_uniform_but_different_type_used_in_all_stages",
8897			   "Creates a program which uses the same subroutine and subroutine uniform "
8898			   "names for every stage (types of subroutines are different in each stage) "
8899			   "and then makes sure that such program compiles and works as expected.")
8900	, m_fbo_id(0)
8901	, m_fs_id(0)
8902	, m_gs_id(0)
8903	, m_has_test_passed(true)
8904	, m_po_id(0)
8905	, m_tc_id(0)
8906	, m_te_id(0)
8907	, m_to_data(DE_NULL)
8908	, m_to_height(4) /* arbitrary value */
8909	, m_to_id(0)
8910	, m_to_width(4) /* arbitrary value */
8911	, m_vao_id(0)
8912	, m_vs_id(0)
8913{
8914	/* Left blank intentionally */
8915}
8916
8917/** Deinitializes all GL objects that may have been created during test execution. */
8918void FunctionalTest17::deinit()
8919{
8920	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8921
8922	if (m_fbo_id != 0)
8923	{
8924		gl.deleteFramebuffers(1, &m_fbo_id);
8925
8926		m_fbo_id = 0;
8927	}
8928
8929	if (m_fs_id != 0)
8930	{
8931		gl.deleteShader(m_fs_id);
8932
8933		m_fs_id = 0;
8934	}
8935
8936	if (m_gs_id != 0)
8937	{
8938		gl.deleteShader(m_gs_id);
8939
8940		m_gs_id = 0;
8941	}
8942
8943	if (m_po_id != 0)
8944	{
8945		gl.deleteProgram(m_po_id);
8946
8947		m_po_id = 0;
8948	}
8949
8950	if (m_tc_id != 0)
8951	{
8952		gl.deleteShader(m_tc_id);
8953
8954		m_tc_id = 0;
8955	}
8956
8957	if (m_te_id != 0)
8958	{
8959		gl.deleteShader(m_te_id);
8960
8961		m_te_id = 0;
8962	}
8963
8964	if (m_to_data != DE_NULL)
8965	{
8966		delete[] m_to_data;
8967
8968		m_to_data = DE_NULL;
8969	}
8970
8971	if (m_to_id != 0)
8972	{
8973		gl.deleteTextures(1, &m_to_id);
8974
8975		m_to_id = 0;
8976	}
8977
8978	if (m_vao_id != 0)
8979	{
8980		gl.deleteVertexArrays(1, &m_vao_id);
8981
8982		m_vao_id = 0;
8983	}
8984
8985	if (m_vs_id != 0)
8986	{
8987		gl.deleteShader(m_vs_id);
8988
8989		m_vs_id = 0;
8990	}
8991
8992	/* Restore original GL configuration */
8993	gl.patchParameteri(GL_PATCH_VERTICES, 3);
8994	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
8995
8996	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
8997	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
8998}
8999
9000/** Retrieves body of a fragment shader that should be used by the test program.
9001 *
9002 *  @return Requested string.
9003 **/
9004std::string FunctionalTest17::getFragmentShaderBody() const
9005{
9006	return "#version 400\n"
9007		   "\n"
9008		   "#extension GL_ARB_shader_subroutine : require\n"
9009		   "\n"
9010		   "in GS_DATA\n"
9011		   "{\n"
9012		   "    vec4 gs_data;\n"
9013		   "    vec4 tc_data;\n"
9014		   "    vec4 te_data;\n"
9015		   "    vec4 vs_data;\n"
9016		   "} gs;\n"
9017		   "\n"
9018		   "out vec4 result;\n"
9019		   "\n"
9020		   "subroutine void subroutineTypeFS(out vec4 result);\n"
9021		   "\n"
9022		   "subroutine(subroutineTypeFS) void subroutine1(out vec4 result)\n"
9023		   "{\n"
9024		   "    result = vec4(5, 6, 7, 8);\n"
9025		   "}\n"
9026		   "\n"
9027		   "subroutine uniform subroutineTypeFS function;\n"
9028		   "\n"
9029		   "void main()\n"
9030		   "{\n"
9031		   "    vec4 fs_data;\n"
9032		   "\n"
9033		   "    function(fs_data);\n"
9034		   "    result = gs.gs_data + gs.tc_data + gs.te_data + gs.vs_data + fs_data;\n"
9035		   "}\n";
9036}
9037
9038/** Retrieves body of a geometry shader that should be used by the test program.
9039 *
9040 *  @return Requested string.
9041 **/
9042std::string FunctionalTest17::getGeometryShaderBody() const
9043{
9044	return "#version 400\n"
9045		   "\n"
9046		   "#extension GL_ARB_shader_subroutine : require\n"
9047		   "\n"
9048		   "layout(points)                           in;\n"
9049		   "layout(triangle_strip, max_vertices = 4) out;\n"
9050		   "\n"
9051		   "subroutine void subroutineTypeGS(out vec4 result);\n"
9052		   "\n"
9053		   "subroutine(subroutineTypeGS) void subroutine1(out vec4 result)\n"
9054		   "{\n"
9055		   "    result = vec4(4, 5, 6, 7);\n"
9056		   "}\n"
9057		   "\n"
9058		   "subroutine uniform subroutineTypeGS function;\n"
9059		   "\n"
9060		   "in TE_DATA\n"
9061		   "{\n"
9062		   "    vec4 tc_data;\n"
9063		   "    vec4 te_data;\n"
9064		   "    vec4 vs_data;\n"
9065		   "} te[];\n"
9066		   "\n"
9067		   "out GS_DATA\n"
9068		   "{\n"
9069		   "    vec4 gs_data;\n"
9070		   "    vec4 tc_data;\n"
9071		   "    vec4 te_data;\n"
9072		   "    vec4 vs_data;\n"
9073		   "} result;\n"
9074		   "\n"
9075		   "void main()\n"
9076		   "{\n"
9077		   "    function(result.gs_data);\n"
9078		   "    gl_Position    = vec4(1, -1, 0, 1);\n"
9079		   "    result.tc_data = te[0].tc_data;\n"
9080		   "    result.te_data = te[0].te_data;\n"
9081		   "    result.vs_data = te[0].vs_data;\n"
9082		   "    EmitVertex();\n"
9083		   "\n"
9084		   "    function(result.gs_data);\n"
9085		   "    gl_Position    = vec4(-1, -1, 0, 1);\n"
9086		   "    result.tc_data = te[0].tc_data;\n"
9087		   "    result.te_data = te[0].te_data;\n"
9088		   "    result.vs_data = te[0].vs_data;\n"
9089		   "    EmitVertex();\n"
9090		   "\n"
9091		   "    function(result.gs_data);\n"
9092		   "    gl_Position    = vec4(1, 1, 0, 1);\n"
9093		   "    result.tc_data = te[0].tc_data;\n"
9094		   "    result.te_data = te[0].te_data;\n"
9095		   "    result.vs_data = te[0].vs_data;\n"
9096		   "    EmitVertex();\n"
9097		   "\n"
9098		   "    function(result.gs_data);\n"
9099		   "    gl_Position    = vec4(-1, 1, 0, 1);\n"
9100		   "    result.tc_data = te[0].tc_data;\n"
9101		   "    result.te_data = te[0].te_data;\n"
9102		   "    result.vs_data = te[0].vs_data;\n"
9103		   "    EmitVertex();\n"
9104		   "    EndPrimitive();\n"
9105		   "}\n";
9106}
9107
9108/** Retrieves body of a tessellation control shader that should be used by the test program.
9109 *
9110 *  @return Requested string.
9111 **/
9112std::string FunctionalTest17::getTessellationControlShaderBody() const
9113{
9114	return "#version 400\n"
9115		   "\n"
9116		   "#extension GL_ARB_shader_subroutine : require\n"
9117		   "\n"
9118		   "layout (vertices = 4) out;\n"
9119		   "\n"
9120		   "subroutine void subroutineTypeTC(out vec4 result);\n"
9121		   "\n"
9122		   "subroutine(subroutineTypeTC) void subroutine1(out vec4 result)\n"
9123		   "{\n"
9124		   "    result = vec4(2, 3, 4, 5);\n"
9125		   "}\n"
9126		   "\n"
9127		   "subroutine uniform subroutineTypeTC function;\n"
9128		   "\n"
9129		   "in VS_DATA\n"
9130		   "{\n"
9131		   "    vec4 vs_data;\n"
9132		   "} vs[];\n"
9133		   "\n"
9134		   "out TC_DATA\n"
9135		   "{\n"
9136		   "    vec4 tc_data;\n"
9137		   "    vec4 vs_data;\n"
9138		   "} result[];\n"
9139		   "\n"
9140		   "void main()\n"
9141		   "{\n"
9142		   "    gl_TessLevelInner[0] = 1.0;\n"
9143		   "    gl_TessLevelInner[1] = 1.0;\n"
9144		   "    gl_TessLevelOuter[0] = 1.0;\n"
9145		   "    gl_TessLevelOuter[1] = 1.0;\n"
9146		   "    gl_TessLevelOuter[2] = 1.0;\n"
9147		   "    gl_TessLevelOuter[3] = 1.0;\n"
9148		   "\n"
9149		   "    function(result[gl_InvocationID].tc_data);\n"
9150		   "    result[gl_InvocationID].vs_data = vs[gl_InvocationID].vs_data;\n"
9151		   "}\n";
9152}
9153
9154/** Retrieves body of a tessellation evaluation shader that should be used
9155 *  by the test program.
9156 *
9157 *  @return Requested string.
9158 **/
9159std::string FunctionalTest17::getTessellationEvaluationShaderBody() const
9160{
9161	return "#version 400\n"
9162		   "\n"
9163		   "#extension GL_ARB_shader_subroutine : require\n"
9164		   "\n"
9165		   "layout (quads, point_mode) in;\n"
9166		   "\n"
9167		   "subroutine void subroutineTypeTE(out vec4 result);\n"
9168		   "\n"
9169		   "subroutine(subroutineTypeTE) void subroutine1(out vec4 result)\n"
9170		   "{\n"
9171		   "    result = vec4(3, 4, 5, 6);\n"
9172		   "}\n"
9173		   "\n"
9174		   "subroutine uniform subroutineTypeTE function;\n"
9175		   "\n"
9176		   "in TC_DATA\n"
9177		   "{\n"
9178		   "    vec4 tc_data;\n"
9179		   "    vec4 vs_data;\n"
9180		   "} tc[];\n"
9181		   "\n"
9182		   "out TE_DATA\n"
9183		   "{\n"
9184		   "    vec4 tc_data;\n"
9185		   "    vec4 te_data;\n"
9186		   "    vec4 vs_data;\n"
9187		   "} result;\n"
9188		   "\n"
9189		   "void main()\n"
9190		   "{\n"
9191		   "    result.vs_data = tc[0].vs_data;\n"
9192		   "    result.tc_data = tc[0].tc_data;\n"
9193		   "    function(result.te_data);\n"
9194		   "}\n";
9195}
9196
9197/** Retrieves body of a vertex shader that should be used by the test program.
9198 *
9199 *  @return Requested string.
9200 **/
9201std::string FunctionalTest17::getVertexShaderBody() const
9202{
9203	return "#version 400\n"
9204		   "\n"
9205		   "#extension GL_ARB_shader_subroutine : require\n"
9206		   "\n"
9207		   "out VS_DATA\n"
9208		   "{\n"
9209		   "    vec4 vs_data;\n"
9210		   "} result;\n"
9211		   "\n"
9212		   "subroutine void subroutineTypeVS(out vec4 result);\n"
9213		   "\n"
9214		   "subroutine(subroutineTypeVS) void subroutine1(out vec4 result)\n"
9215		   "{\n"
9216		   "    result = vec4(1, 2, 3, 4);\n"
9217		   "}\n"
9218		   "\n"
9219		   "subroutine uniform subroutineTypeVS function;\n"
9220		   "\n"
9221		   "void main()\n"
9222		   "{\n"
9223		   "    function(result.vs_data);\n"
9224		   "}\n";
9225}
9226
9227/** Initializes all buffers and GL objects required to run the test. */
9228void FunctionalTest17::initTest()
9229{
9230	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9231
9232	/* Configure GL_PATCH_VERTICES so that TC only takes a single patch vertex */
9233	gl.patchParameteri(GL_PATCH_VERTICES, 1);
9234	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
9235
9236	/* Generate & bind a VAO */
9237	gl.genVertexArrays(1, &m_vao_id);
9238	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9239
9240	gl.bindVertexArray(m_vao_id);
9241	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9242
9243	/* Set up test program object */
9244	std::string fs_body = getFragmentShaderBody();
9245	std::string gs_body = getGeometryShaderBody();
9246	std::string tc_body = getTessellationControlShaderBody();
9247	std::string te_body = getTessellationEvaluationShaderBody();
9248	std::string vs_body = getVertexShaderBody();
9249
9250	if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */
9251							 DE_NULL,												   /* n_xfb_varyings */
9252							 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
9253	{
9254		TCU_FAIL("Failed to link test program object");
9255	}
9256
9257	/* Set up a texture object that will be used as a color attachment */
9258	gl.genTextures(1, &m_to_id);
9259	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
9260
9261	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9262	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9263
9264	gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
9265					GL_RGBA32F, m_to_width, m_to_height);
9266	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9267
9268	/* Set up FBO */
9269	gl.genFramebuffers(1, &m_fbo_id);
9270	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9271
9272	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9273	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
9274
9275	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
9276	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
9277
9278	/* Make sure glReadPixels() does not return misaligned data */
9279	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
9280	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
9281
9282	/* Initialize a buffer that will be used to store rendered data */
9283	m_to_data = new float[m_to_width * m_to_height * 4 /* rgba */];
9284}
9285
9286/** Executes test iteration.
9287 *
9288 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9289 */
9290tcu::TestNode::IterateResult FunctionalTest17::iterate()
9291{
9292	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9293
9294	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9295	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9296	{
9297		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9298	}
9299
9300	initTest();
9301
9302	/* Use the test program to render a full-screen test quad */
9303	gl.useProgram(m_po_id);
9304	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9305
9306	gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
9307	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9308
9309	/* Read back the data that was rendered */
9310	gl.readPixels(0, /* x */
9311				  0, /* y */
9312				  m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_to_data);
9313	GLU_EXPECT_NO_ERROR(gl.getError(), "glReaDPixels() call failed.");
9314
9315	/* Verify the data */
9316	verifyRenderedData();
9317
9318	/** All done */
9319	if (m_has_test_passed)
9320	{
9321		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9322	}
9323	else
9324	{
9325		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
9326	}
9327
9328	return STOP;
9329}
9330
9331/** Verifies the data that have been rendered by the test program.
9332 *
9333 *  It is assumed the rendered data have already been copied to
9334 *  m_to_data.
9335 *
9336 *  If the rendered data is found to be invalid, m_has_test_passed
9337 *  will be set to false.
9338 **/
9339void FunctionalTest17::verifyRenderedData()
9340{
9341	const float epsilon			 = 1e-5f;
9342	const float expected_data[4] = { 15.0f, 20.0f, 25.0f, 30.0f };
9343
9344	for (unsigned int y = 0; y < m_to_height && m_has_test_passed; ++y)
9345	{
9346		const float* row_ptr = m_to_data + y * 4 /* rgba */ * m_to_width;
9347
9348		for (unsigned int x = 0; x < m_to_width && m_has_test_passed; ++x)
9349		{
9350			const float* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9351
9352			if (de::abs(pixel_ptr[0] - expected_data[0]) > epsilon ||
9353				de::abs(pixel_ptr[1] - expected_data[1]) > epsilon ||
9354				de::abs(pixel_ptr[2] - expected_data[2]) > epsilon ||
9355				de::abs(pixel_ptr[3] - expected_data[3]) > epsilon)
9356			{
9357				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel found at (" << x << ", " << y
9358								   << "): "
9359									  "expected:("
9360								   << expected_data[0] << ", " << expected_data[1] << ", " << expected_data[2] << ", "
9361								   << expected_data[3] << "), found:(" << pixel_ptr[0] << ", " << pixel_ptr[1] << ", "
9362								   << pixel_ptr[2] << ", " << pixel_ptr[3] << ")." << tcu::TestLog::EndMessage;
9363
9364				m_has_test_passed = false;
9365			}
9366		} /* for (all columns) */
9367	}	 /* for (all rows) */
9368}
9369
9370/** Constructor.
9371 *
9372 *  @param context Rendering context.
9373 *
9374 **/
9375FunctionalTest18_19::FunctionalTest18_19(deqp::Context& context)
9376	: TestCase(context, "control_flow_and_returned_subroutine_values_used_as_subroutine_input",
9377			   "Makes sure that calling a subroutine with argument value returned by "
9378			   "another subroutine works correctly. Also checks that subroutine and "
9379			   "subroutine uniforms work as expected when used in connection with control "
9380			   "flow functions.")
9381	, m_has_test_passed(true)
9382	, m_n_points_to_draw(16) /* arbitrary value */
9383	, m_po_id(0)
9384	, m_po_subroutine_divide_by_two_location(GL_INVALID_INDEX)
9385	, m_po_subroutine_multiply_by_four_location(GL_INVALID_INDEX)
9386	, m_po_subroutine_returns_false_location(GL_INVALID_INDEX)
9387	, m_po_subroutine_returns_true_location(GL_INVALID_INDEX)
9388	, m_po_subroutine_uniform_bool_operator1(-1)
9389	, m_po_subroutine_uniform_bool_operator2(-1)
9390	, m_po_subroutine_uniform_vec4_processor1(-1)
9391	, m_po_subroutine_uniform_vec4_processor2(-1)
9392	, m_xfb_bo_id(0)
9393	, m_vao_id(0)
9394	, m_vs_id(0)
9395{
9396	/* Left blank intentionally */
9397}
9398
9399/** De-initializes all GL objects that may have been created during test execution */
9400void FunctionalTest18_19::deinit()
9401{
9402	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9403
9404	if (m_po_id != 0)
9405	{
9406		gl.deleteProgram(m_po_id);
9407
9408		m_po_id = 0;
9409	}
9410
9411	if (m_vao_id != 0)
9412	{
9413		gl.deleteVertexArrays(1, &m_vao_id);
9414
9415		m_vao_id = 0;
9416	}
9417
9418	if (m_vs_id != 0)
9419	{
9420		gl.deleteShader(m_vs_id);
9421
9422		m_vs_id = 0;
9423	}
9424
9425	if (m_xfb_bo_id != 0)
9426	{
9427		gl.deleteBuffers(1, &m_xfb_bo_id);
9428
9429		m_xfb_bo_id = 0;
9430	}
9431}
9432
9433/** Executes a single test iteration using user-specified properties. If the
9434 *  iterations fails, m_has_test_passed is set to false.
9435 *
9436 *  @param bool_operator1_subroutine_location Location of a subroutine to be assigned to
9437 *                                            bool_operator1 subroutine uniform.
9438 *  @param bool_operator2_subroutine_location Location of a subroutine to be assigned to
9439 *                                            bool_operator2 subroutine uniform.
9440 *  @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to
9441 *                                            vec4_operator1 subroutine uniform.
9442 *  @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to
9443 *                                            vec4_operator2 subroutine uniform.
9444 &**/
9445void FunctionalTest18_19::executeTest(glw::GLuint bool_operator1_subroutine_location,
9446									  glw::GLuint bool_operator2_subroutine_location,
9447									  glw::GLuint vec4_operator1_subroutine_location,
9448									  glw::GLuint vec4_operator2_subroutine_location)
9449{
9450	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9451
9452	/* Set up subroutines */
9453	glw::GLuint subroutine_configuration[4 /* total number of subroutines */] = { 0 };
9454
9455	subroutine_configuration[m_po_subroutine_uniform_bool_operator1]  = bool_operator1_subroutine_location;
9456	subroutine_configuration[m_po_subroutine_uniform_bool_operator2]  = bool_operator2_subroutine_location;
9457	subroutine_configuration[m_po_subroutine_uniform_vec4_processor1] = vec4_operator1_subroutine_location;
9458	subroutine_configuration[m_po_subroutine_uniform_vec4_processor2] = vec4_operator2_subroutine_location;
9459
9460	gl.useProgram(m_po_id);
9461	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
9462
9463	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 4 /* count */, subroutine_configuration);
9464	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed");
9465
9466	/* Draw test-specific number of points */
9467	gl.beginTransformFeedback(GL_POINTS);
9468	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
9469	{
9470		gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw);
9471		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
9472	}
9473	gl.endTransformFeedback();
9474	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
9475
9476	/* Map the BO storage into process space */
9477	const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
9478	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
9479
9480	verifyXFBData(xfb_data_ptr, bool_operator1_subroutine_location, bool_operator2_subroutine_location,
9481				  vec4_operator1_subroutine_location, vec4_operator2_subroutine_location);
9482
9483	/* Unmap BO storage */
9484	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
9485	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
9486}
9487
9488/** Retrieves body of a vertex shader to be used by the test. */
9489std::string FunctionalTest18_19::getVertexShaderBody() const
9490{
9491	return "#version 400\n"
9492		   "\n"
9493		   "subroutine bool bool_processor();\n"
9494		   "subroutine vec4 vec4_processor(in vec4 iparam);\n"
9495		   "\n"
9496		   "subroutine(bool_processor) bool returnsFalse()\n"
9497		   "{\n"
9498		   "    return false;\n"
9499		   "}\n"
9500		   "\n"
9501		   "subroutine(bool_processor) bool returnsTrue()\n"
9502		   "{\n"
9503		   "    return true;\n"
9504		   "}\n"
9505		   "\n"
9506		   "subroutine(vec4_processor) vec4 divideByTwo(in vec4 iparam)\n"
9507		   "{\n"
9508		   "    return iparam * vec4(0.5);\n"
9509		   "}\n"
9510		   "\n"
9511		   "subroutine(vec4_processor) vec4 multiplyByFour(in vec4 iparam)\n"
9512		   "{\n"
9513		   "    return iparam * vec4(4.0);\n"
9514		   "}\n"
9515		   "\n"
9516		   "subroutine uniform bool_processor bool_operator1;\n"
9517		   "subroutine uniform bool_processor bool_operator2;\n"
9518		   "subroutine uniform vec4_processor vec4_operator1;\n"
9519		   "subroutine uniform vec4_processor vec4_operator2;\n"
9520		   "\n"
9521		   "out float result;\n"
9522		   "\n"
9523		   "void main()\n"
9524		   "{\n"
9525		   "    if (bool_operator1() )\n"
9526		   "    {\n"
9527		   "        float value = float( (3 * gl_VertexID + 1) * 2);\n"
9528		   "\n"
9529		   "        while (bool_operator1() )\n"
9530		   "        {\n"
9531		   "            value /= float(gl_VertexID + 2);\n"
9532		   "\n"
9533		   "            if (value <= 1.0f) break;\n"
9534		   "        }\n"
9535		   "\n"
9536		   "        result = value;\n"
9537		   "    }\n"
9538		   "    else\n"
9539		   "    {\n"
9540		   "        vec4 value = vec4(gl_VertexID,     gl_VertexID + 1,\n"
9541		   "                          gl_VertexID + 2, gl_VertexID + 3);\n"
9542		   "\n"
9543		   "        switch (gl_VertexID % 2)\n"
9544		   "        {\n"
9545		   "            case 0:\n"
9546		   "            {\n"
9547		   "                for (int iteration = 0; iteration < gl_VertexID && bool_operator2(); ++iteration)\n"
9548		   "                {\n"
9549		   "                    value = vec4_operator2(vec4_operator1(value));\n"
9550		   "                }\n"
9551		   "\n"
9552		   "                break;\n"
9553		   "            }\n"
9554		   "\n"
9555		   "            case 1:\n"
9556		   "            {\n"
9557		   "                for (int iteration = 0; iteration < gl_VertexID * 2; ++iteration)\n"
9558		   "                {\n"
9559		   "                    value = vec4_operator1(vec4_operator2(value));\n"
9560		   "                }\n"
9561		   "\n"
9562		   "                break;\n"
9563		   "            }\n"
9564		   "        }\n"
9565		   "\n"
9566		   "        result = value.x + value.y + value.z + value.w;\n"
9567		   "\n"
9568		   "    }\n"
9569		   "}\n";
9570}
9571
9572/** Initializes all GL objects required to run the test. */
9573void FunctionalTest18_19::initTest()
9574{
9575	const glw::Functions& gl		  = m_context.getRenderContext().getFunctions();
9576	const char*			  varyings[1] = { "result" };
9577	std::string			  vs_body	 = getVertexShaderBody();
9578	const unsigned int	n_varyings  = sizeof(varyings) / sizeof(varyings[0]);
9579
9580	if (!Utils::buildProgram(gl, vs_body, "",						  /* tc_body */
9581							 "",									  /* te_body */
9582							 "",									  /* gs_body */
9583							 "",									  /* fs_body */
9584							 varyings, n_varyings, &m_vs_id, DE_NULL, /* out_tc_id */
9585							 DE_NULL,								  /* out_te_id */
9586							 DE_NULL,								  /* out_gs_id */
9587							 DE_NULL,								  /* out_fs_id */
9588							 &m_po_id))
9589	{
9590		TCU_FAIL("Failed to build test program object");
9591	}
9592
9593	/* Retrieve subroutine & subroutine uniform locations */
9594	m_po_subroutine_divide_by_two_location	= gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "divideByTwo");
9595	m_po_subroutine_multiply_by_four_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "multiplyByFour");
9596	m_po_subroutine_returns_false_location	= gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsFalse");
9597	m_po_subroutine_returns_true_location	 = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsTrue");
9598	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed");
9599
9600	if (m_po_subroutine_divide_by_two_location == GL_INVALID_INDEX ||
9601		m_po_subroutine_multiply_by_four_location == GL_INVALID_INDEX ||
9602		m_po_subroutine_returns_false_location == GL_INVALID_INDEX ||
9603		m_po_subroutine_returns_true_location == GL_INVALID_INDEX)
9604	{
9605		TCU_FAIL("glGetSubroutineIndex() returned GL_INVALID_INDEX for a valid subroutine");
9606	}
9607
9608	m_po_subroutine_uniform_bool_operator1 =
9609		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator1");
9610	m_po_subroutine_uniform_bool_operator2 =
9611		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator2");
9612	m_po_subroutine_uniform_vec4_processor1 =
9613		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator1");
9614	m_po_subroutine_uniform_vec4_processor2 =
9615		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator2");
9616	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed");
9617
9618	if (m_po_subroutine_uniform_bool_operator1 == -1 || m_po_subroutine_uniform_bool_operator2 == -1 ||
9619		m_po_subroutine_uniform_vec4_processor1 == -1 || m_po_subroutine_uniform_vec4_processor2 == -1)
9620	{
9621		TCU_FAIL("glGetSubroutineUniformLocation() returned -1 for an active subroutine uniform");
9622	}
9623
9624	/* Set up XFB BO */
9625	const unsigned int bo_size = static_cast<unsigned int>(sizeof(float) * m_n_points_to_draw);
9626
9627	gl.genBuffers(1, &m_xfb_bo_id);
9628	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
9629
9630	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
9631	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
9632
9633	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
9634	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
9635
9636	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_COPY);
9637	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9638
9639	/* Set up a VAO */
9640	gl.genVertexArrays(1, &m_vao_id);
9641	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9642
9643	gl.bindVertexArray(m_vao_id);
9644	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9645}
9646
9647/** Executes test iteration.
9648 *
9649 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9650 */
9651tcu::TestNode::IterateResult FunctionalTest18_19::iterate()
9652{
9653	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9654	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9655	{
9656		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9657	}
9658
9659	/* Initialize all GL objects required to run the test */
9660	initTest();
9661
9662	/* Iterate over all subroutine permutations */
9663	const glw::GLuint subroutine_bool_operators[] = { m_po_subroutine_returns_false_location,
9664													  m_po_subroutine_returns_true_location };
9665	const unsigned int n_subroutine_bool_operators =
9666		sizeof(subroutine_bool_operators) / sizeof(subroutine_bool_operators[0]);
9667
9668	const glw::GLuint subroutine_vec4_operators[] = { m_po_subroutine_divide_by_two_location,
9669													  m_po_subroutine_multiply_by_four_location };
9670	const unsigned int n_subroutine_vec4_operators =
9671		sizeof(subroutine_vec4_operators) / sizeof(subroutine_vec4_operators[0]);
9672
9673	for (unsigned int n_subroutine_uniform_bool_operator1 = 0;
9674		 n_subroutine_uniform_bool_operator1 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator1)
9675	{
9676		for (unsigned int n_subroutine_uniform_bool_operator2 = 0;
9677			 n_subroutine_uniform_bool_operator2 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator2)
9678		{
9679			for (unsigned int n_subroutine_uniform_vec4_operator1 = 0;
9680				 n_subroutine_uniform_vec4_operator1 < n_subroutine_vec4_operators;
9681				 ++n_subroutine_uniform_vec4_operator1)
9682			{
9683				for (unsigned int n_subroutine_uniform_vec4_operator2 = 0;
9684					 n_subroutine_uniform_vec4_operator2 < n_subroutine_vec4_operators;
9685					 ++n_subroutine_uniform_vec4_operator2)
9686				{
9687					executeTest(subroutine_bool_operators[n_subroutine_uniform_bool_operator1],
9688								subroutine_bool_operators[n_subroutine_uniform_bool_operator2],
9689								subroutine_vec4_operators[n_subroutine_uniform_vec4_operator1],
9690								subroutine_vec4_operators[n_subroutine_uniform_vec4_operator2]);
9691				} /* for (all subroutine vec4 operator subroutines used for processor2) */
9692			}	 /* for (all subroutine vec4 operator subroutines used for processor1) */
9693		}		  /* for (all subroutine bool operator subroutines used for operator2) */
9694	}			  /* for (all subroutine bool operator subroutines used for operator1) */
9695
9696	/* All done */
9697	if (m_has_test_passed)
9698	{
9699		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9700	}
9701	else
9702	{
9703		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
9704	}
9705
9706	return STOP;
9707}
9708
9709/** Divides input argument by two. The result value is returned to the
9710 *  caller.
9711 *
9712 *  @param data Input value.
9713 *
9714 *  @return As per description.
9715 **/
9716tcu::Vec4 FunctionalTest18_19::vec4operator_div2(tcu::Vec4 data)
9717{
9718	return data * 0.5f;
9719}
9720
9721/** Multiplies input argument by four. The result value is returned to the
9722 *  caller.
9723 *
9724 *  @param data Input value.
9725 *
9726 *  @return As per description.
9727 **/
9728tcu::Vec4 FunctionalTest18_19::vec4operator_mul4(tcu::Vec4 data)
9729{
9730	return data * 4.0f;
9731}
9732
9733/** Verifies data XFBed out by the vertex shader. It is assumed the subroutines were configured
9734 *  as per passed arguments, prior to the draw call.
9735 *
9736 *  If the result data is found to be invalid, m_has_test_passed is set to false.
9737 *
9738 *  @param data                               XFBed data.
9739 *  @param bool_operator1_subroutine_location Location of a subroutine to be assigned to
9740 *                                            bool_operator1 subroutine uniform.
9741 *  @param bool_operator2_subroutine_location Location of a subroutine to be assigned to
9742 *                                            bool_operator2 subroutine uniform.
9743 *  @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to
9744 *                                            vec4_operator1 subroutine uniform.
9745 *  @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to
9746 *                                            vec4_operator2 subroutine uniform.
9747 */
9748void FunctionalTest18_19::verifyXFBData(const glw::GLvoid* data, glw::GLuint bool_operator1_subroutine_location,
9749										glw::GLuint bool_operator2_subroutine_location,
9750										glw::GLuint vec4_operator1_subroutine_location,
9751										glw::GLuint vec4_operator2_subroutine_location)
9752{
9753	bool				bool_operator1_result = false;
9754	bool				bool_operator2_result = false;
9755	const float			epsilon				  = 1e-5f;
9756	PFNVEC4OPERATORPROC pVec4Operator1		  = NULL;
9757	PFNVEC4OPERATORPROC pVec4Operator2		  = NULL;
9758	const glw::GLfloat* traveller_ptr		  = (const glw::GLfloat*)data;
9759
9760	bool_operator1_result = (bool_operator1_subroutine_location == m_po_subroutine_returns_true_location);
9761	bool_operator2_result = (bool_operator2_subroutine_location == m_po_subroutine_returns_true_location);
9762	pVec4Operator1		  = (vec4_operator1_subroutine_location == m_po_subroutine_divide_by_two_location) ?
9763						 vec4operator_div2 :
9764						 vec4operator_mul4;
9765	pVec4Operator2 = (vec4_operator2_subroutine_location == m_po_subroutine_divide_by_two_location) ?
9766						 vec4operator_div2 :
9767						 vec4operator_mul4;
9768
9769	for (unsigned int n_vertex = 0; n_vertex < m_n_points_to_draw; ++n_vertex)
9770	{
9771		float expected_value = 0.0f;
9772
9773		if (bool_operator1_result)
9774		{
9775			float value = float((3 * n_vertex + 1) * 2);
9776
9777			while (bool_operator1_result)
9778			{
9779				value /= float(n_vertex + 2);
9780
9781				if (value <= 1.0f)
9782					break;
9783			}
9784
9785			expected_value = value;
9786		}
9787		else
9788		{
9789			tcu::Vec4 value((float)n_vertex, (float)n_vertex + 1, (float)n_vertex + 2, (float)n_vertex + 3);
9790
9791			switch (n_vertex % 2)
9792			{
9793			case 0:
9794			{
9795				for (unsigned int iteration = 0; iteration < n_vertex && bool_operator2_result; ++iteration)
9796				{
9797					value = pVec4Operator2(pVec4Operator1(value));
9798				}
9799
9800				break;
9801			}
9802
9803			case 1:
9804			{
9805				for (unsigned int iteration = 0; iteration < n_vertex * 2; ++iteration)
9806				{
9807					value = pVec4Operator1(pVec4Operator2(value));
9808				}
9809
9810				break;
9811			}
9812			} /* switch (n_vertex % 2) */
9813
9814			expected_value = value.x() + value.y() + value.z() + value.w();
9815		}
9816
9817		if (de::abs(expected_value - *traveller_ptr) > epsilon)
9818		{
9819			m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data was found to be invalid at index [" << n_vertex
9820							   << "]"
9821								  "for the following subroutine location configuration:"
9822								  " bool_operator1_subroutine_location:["
9823							   << bool_operator1_subroutine_location << "]"
9824																		" bool_operator2_subroutine_location:["
9825							   << bool_operator2_subroutine_location << "]"
9826																		" vec4_operator1_subroutine_location:["
9827							   << vec4_operator1_subroutine_location << "]"
9828																		" vec4_operator2_subroutine_location:["
9829							   << vec4_operator2_subroutine_location << "];"
9830																		" expected data:"
9831							   << expected_value << ", found:" << *traveller_ptr << tcu::TestLog::EndMessage;
9832
9833			m_has_test_passed = false;
9834		}
9835
9836		++traveller_ptr;
9837	} /* for (all drawn points) */
9838}
9839
9840/** Constructor.
9841 *
9842 *  @param context Rendering context.
9843 *
9844 **/
9845NegativeTest1::NegativeTest1(deqp::Context& context)
9846	: TestCase(context, "subroutine_errors", "Verifies all GL_INVALID_OPERATION, GL_INVALID_VALUE, GL_INVALID ENUM "
9847											 "errors related to subroutine usage are properly generated.")
9848	, m_has_test_passed(true)
9849	, m_po_active_subroutine_uniform_locations(0)
9850	, m_po_active_subroutine_uniforms(0)
9851	, m_po_active_subroutines(0)
9852	, m_po_subroutine_uniform_function_index(-1)
9853	, m_po_subroutine_uniform_function2_index(-1)
9854	, m_po_subroutine_test1_index(GL_INVALID_INDEX)
9855	, m_po_subroutine_test2_index(GL_INVALID_INDEX)
9856	, m_po_subroutine_test3_index(GL_INVALID_INDEX)
9857	, m_po_not_linked_id(0)
9858	, m_po_id(0)
9859	, m_vs_id(0)
9860{
9861	/* Left blank intentionally */
9862}
9863
9864/** Deinitializes all GL objects that may have been created during
9865 *  test execution.
9866 **/
9867void NegativeTest1::deinit()
9868{
9869	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9870
9871	if (m_po_id != 0)
9872	{
9873		gl.deleteProgram(m_po_id);
9874
9875		m_po_id = 0;
9876	}
9877
9878	if (m_po_not_linked_id != 0)
9879	{
9880		gl.deleteProgram(m_po_not_linked_id);
9881
9882		m_po_not_linked_id = 0;
9883	}
9884
9885	if (m_vs_id != 0)
9886	{
9887		gl.deleteShader(m_vs_id);
9888
9889		m_vs_id = 0;
9890	}
9891}
9892
9893/** Initializes all GL objects required to run the test.  */
9894void NegativeTest1::initTest()
9895{
9896	glw::GLint			  compile_status = GL_FALSE;
9897	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
9898
9899	/* Create program objects */
9900	m_po_not_linked_id = gl.createProgram();
9901	m_po_id			   = gl.createProgram();
9902	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
9903
9904	/* Create vertex shader object */
9905	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
9906	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
9907
9908	/* Set up vertex shader */
9909	const char* vs_body = "#version 400\n"
9910						  "\n"
9911						  "#extension GL_ARB_shader_subroutine : require\n"
9912						  "\n"
9913						  "subroutine void subroutineType (out ivec2 arg);\n"
9914						  "subroutine void subroutineType2(out ivec4 arg);\n"
9915						  "\n"
9916						  "subroutine(subroutineType) void test1(out ivec2 arg)\n"
9917						  "{\n"
9918						  "    arg = ivec2(1, 2);\n"
9919						  "}\n"
9920						  "subroutine(subroutineType) void test2(out ivec2 arg)\n"
9921						  "{\n"
9922						  "    arg = ivec2(3,4);\n"
9923						  "}\n"
9924						  "subroutine(subroutineType2) void test3(out ivec4 arg)\n"
9925						  "{\n"
9926						  "    arg = ivec4(1, 2, 3, 4);\n"
9927						  "}\n"
9928						  "\n"
9929						  "subroutine uniform subroutineType  function;\n"
9930						  "subroutine uniform subroutineType2 function2;\n"
9931						  "\n"
9932						  "void main()\n"
9933						  "{\n"
9934						  "    ivec2 test;\n"
9935						  "    ivec4 test2;\n"
9936						  "\n"
9937						  "    function(test);\n"
9938						  "\n"
9939						  "    if (test.x > 2)\n"
9940						  "    {\n"
9941						  "        gl_Position = vec4(1);\n"
9942						  "    }\n"
9943						  "    else\n"
9944						  "    {\n"
9945						  "        function2(test2);\n"
9946						  "\n"
9947						  "        gl_Position = vec4(float(test2.x) );\n"
9948						  "    }\n"
9949						  "}\n";
9950
9951	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
9952	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
9953
9954	gl.compileShader(m_vs_id);
9955	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
9956
9957	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
9958	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
9959
9960	if (compile_status == GL_FALSE)
9961	{
9962		TCU_FAIL("Shader compilation failed");
9963	}
9964
9965	/* Set up & link the test program object */
9966	glw::GLint link_status = GL_FALSE;
9967
9968	gl.attachShader(m_po_id, m_vs_id);
9969	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
9970
9971	gl.linkProgram(m_po_id);
9972	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
9973
9974	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
9975	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
9976
9977	if (link_status == GL_FALSE)
9978	{
9979		TCU_FAIL("Program linking failed");
9980	}
9981
9982	/* Query test program object's properties */
9983	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
9984						 &m_po_active_subroutine_uniform_locations);
9985	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &m_po_active_subroutine_uniforms);
9986	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &m_po_active_subroutines);
9987	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call(s) failed.");
9988
9989	if (m_po_active_subroutine_uniform_locations != 2)
9990	{
9991		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS value returned");
9992	}
9993
9994	m_po_subroutine_test1_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test1");
9995	m_po_subroutine_test2_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test2");
9996	m_po_subroutine_test3_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test3");
9997	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
9998
9999	if (m_po_subroutine_test1_index == GL_INVALID_INDEX || m_po_subroutine_test2_index == GL_INVALID_INDEX ||
10000		m_po_subroutine_test3_index == GL_INVALID_INDEX)
10001	{
10002		TCU_FAIL("Invalid subroutine index returned");
10003	}
10004
10005	m_po_subroutine_uniform_function_index  = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function");
10006	m_po_subroutine_uniform_function2_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function2");
10007	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
10008
10009	if (m_po_subroutine_uniform_function_index == -1 || m_po_subroutine_uniform_function2_index == -1)
10010	{
10011		TCU_FAIL("Invalid subroutine uniform index returned");
10012	}
10013}
10014
10015/** Executes test iteration.
10016 *
10017 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10018 */
10019tcu::TestNode::IterateResult NegativeTest1::iterate()
10020{
10021	glw::GLenum			  error_code = GL_NO_ERROR;
10022	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
10023
10024	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10025	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10026	{
10027		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10028	}
10029
10030	/* Initialize GL objects required to run the test */
10031	initTest();
10032
10033	/* The error INVALID_OPERATION is generated by GetSubroutineUniformLocation
10034	 * if the program object identified by <program> has not been successfully
10035	 * linked.
10036	 */
10037	gl.getSubroutineUniformLocation(m_po_not_linked_id, GL_FRAGMENT_SHADER, "subroutine_uniform_name");
10038
10039	error_code = gl.getError();
10040
10041	if (error_code != GL_INVALID_OPERATION)
10042	{
10043		m_testCtx.getLog() << tcu::TestLog::Message
10044						   << "glGetSubroutineUniformLocation() does not generate GL_INVALID_OPERATION "
10045							  "error code when called for a non-linked program object."
10046						   << tcu::TestLog::EndMessage;
10047
10048		m_has_test_passed = false;
10049	}
10050
10051	/* The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or
10052	 * GetActiveSubroutineUniformName if <index> is greater than or equal to the
10053	 * value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage.
10054	 */
10055	glw::GLint temp_length = 0;
10056	glw::GLint temp_values = 0;
10057
10058	gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms,
10059									GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10060	error_code = gl.getError();
10061
10062	if (error_code == GL_INVALID_VALUE)
10063	{
10064		gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10065										GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10066
10067		error_code = gl.getError();
10068	}
10069
10070	if (error_code != GL_INVALID_VALUE)
10071	{
10072		m_testCtx.getLog() << tcu::TestLog::Message
10073						   << "glGetActiveSubroutineUniformiv() does not generate GL_INVALID_VALUE "
10074							  "when passed <index> argument that is greater than or equal to "
10075							  "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10076						   << tcu::TestLog::EndMessage;
10077
10078		m_has_test_passed = false;
10079	}
10080
10081	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 0, /* bufsize */
10082									  &temp_length, DE_NULL);										 /* name */
10083	error_code = gl.getError();
10084
10085	if (error_code == GL_INVALID_VALUE)
10086	{
10087		gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10088										  0,					  /* bufsize */
10089										  &temp_length, DE_NULL); /* name */
10090
10091		error_code = gl.getError();
10092	}
10093
10094	if (error_code != GL_INVALID_VALUE)
10095	{
10096		m_testCtx.getLog() << tcu::TestLog::Message
10097						   << "glGetActiveSubroutineUniformName() does not generate GL_INVALID_VALUE "
10098							  "when passed <index> argument that is greater than or equal to "
10099							  "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10100						   << tcu::TestLog::EndMessage;
10101
10102		m_has_test_passed = false;
10103	}
10104
10105	/* The error INVALID_VALUE is generated by GetActiveSubroutineName if <index>
10106	 * is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader
10107	 * stage.
10108	 */
10109	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines, 0, /* bufsize */
10110							   &temp_length, DE_NULL);								  /* name */
10111	error_code = gl.getError();
10112
10113	if (error_code == GL_INVALID_VALUE)
10114	{
10115		gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines + 1, 0, /* bufsize */
10116								   &temp_length, DE_NULL);									  /* name */
10117
10118		error_code = gl.getError();
10119	}
10120
10121	if (error_code != GL_INVALID_VALUE)
10122	{
10123		m_testCtx.getLog() << tcu::TestLog::Message << "glGetActiveSubroutineName() does not generate GL_INVALID_VALUE "
10124													   "when passed <index> argument that is greater than or equal to "
10125													   "the value of GL_ACTIVE_SUBROUTINES."
10126						   << tcu::TestLog::EndMessage;
10127
10128		m_has_test_passed = false;
10129	}
10130
10131	/* The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count>
10132	 * is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the
10133	 * shader stage <shadertype>.
10134	 */
10135	glw::GLuint index = 0;
10136
10137	gl.useProgram(m_po_id);
10138	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10139
10140	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations - 1, &index);
10141	error_code = gl.getError();
10142
10143	if (error_code == GL_INVALID_VALUE)
10144	{
10145		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &index);
10146
10147		error_code = gl.getError();
10148	}
10149
10150	if (error_code != GL_INVALID_VALUE)
10151	{
10152		m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesiv() does not generate GL_INVALID_VALUE "
10153													   "when passed <count> argument that is not equal to the value of "
10154													   "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10155						   << tcu::TestLog::EndMessage;
10156
10157		m_has_test_passed = false;
10158	}
10159
10160	/* The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value
10161	 * in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES
10162	 * for the shader stage.
10163	 */
10164	glw::GLuint invalid_subroutine_indices[4] = { (GLuint)m_po_active_subroutines, (GLuint)m_po_active_subroutines,
10165												  (GLuint)m_po_active_subroutines + 1,
10166												  (GLuint)m_po_active_subroutines + 1 };
10167
10168	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, /* count */
10169							 invalid_subroutine_indices + 0);
10170	error_code = gl.getError();
10171
10172	if (error_code == GL_INVALID_VALUE)
10173	{
10174		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations,
10175								 invalid_subroutine_indices + 2);
10176
10177		error_code = gl.getError();
10178	}
10179
10180	if (error_code != GL_INVALID_VALUE)
10181	{
10182		m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesuiv() does not generate GL_INVALID_VALUE "
10183													   "when the value passed via <indices> argument is greater than "
10184													   "or equal to the value of GL_ACTIVE_SUBROUTINES."
10185						   << tcu::TestLog::EndMessage;
10186
10187		m_has_test_passed = false;
10188	}
10189
10190	/* The error INVALID_OPERATION is generated by UniformSubroutinesuiv() if any
10191	 * subroutine index in <indices> identifies a subroutine not associated with
10192	 * the type of the subroutine uniform variable assigned to the corresponding
10193	 * location.
10194	 */
10195	glw::GLuint invalid_subroutine_indices2[2] = { m_po_subroutine_test1_index, m_po_subroutine_test1_index };
10196
10197	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, invalid_subroutine_indices2);
10198	error_code = gl.getError();
10199
10200	if (error_code != GL_INVALID_OPERATION)
10201	{
10202		m_testCtx.getLog() << tcu::TestLog::Message
10203						   << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10204							  "when the subroutine index passed via <indices> argument identifies"
10205							  "a subroutine not associated with the type of the subroutine uniform "
10206							  "assigned to the corresponding location."
10207						   << tcu::TestLog::EndMessage;
10208
10209		m_has_test_passed = false;
10210	}
10211
10212	/* The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no
10213	 * program is active.
10214	 */
10215	glw::GLuint valid_subroutine_locations[2] = { 0 };
10216
10217	valid_subroutine_locations[m_po_subroutine_uniform_function_index]  = m_po_subroutine_test1_index;
10218	valid_subroutine_locations[m_po_subroutine_uniform_function2_index] = m_po_subroutine_test3_index;
10219
10220	gl.useProgram(0);
10221	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10222
10223	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, valid_subroutine_locations);
10224	error_code = gl.getError();
10225
10226	if (error_code != GL_INVALID_OPERATION)
10227	{
10228		m_testCtx.getLog() << tcu::TestLog::Message
10229						   << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10230							  "when called without an active program object."
10231						   << tcu::TestLog::EndMessage;
10232
10233		m_has_test_passed = false;
10234	}
10235
10236	/* The error INVALID_VALUE is generated by GetUniformSubroutineuiv if
10237	 * <location> is greater than or equal to the value of
10238	 * ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage.
10239	 */
10240	glw::GLuint temp_value = 0;
10241
10242	gl.useProgram(m_po_id);
10243	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10244
10245	gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, &temp_value);
10246	error_code = gl.getError();
10247
10248	if (error_code == GL_INVALID_VALUE)
10249	{
10250		gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &temp_value);
10251		error_code = gl.getError();
10252	}
10253
10254	if (error_code != GL_INVALID_VALUE)
10255	{
10256		m_testCtx.getLog() << tcu::TestLog::Message
10257						   << "glGetUniformSubroutineuiv() does not generate GL_INVALID_VALUE "
10258							  "when called for location that is greater than or equal to the value "
10259							  "of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10260						   << tcu::TestLog::EndMessage;
10261
10262		m_has_test_passed = false;
10263	}
10264
10265	/* The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no
10266	 * program is active for the shader stage identified by <shadertype>.
10267	 */
10268	const glw::GLenum undefined_shader_stages[] = { GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER,
10269													GL_TESS_EVALUATION_SHADER };
10270	const unsigned int n_undefined_shader_stages = sizeof(undefined_shader_stages) / sizeof(undefined_shader_stages[0]);
10271
10272	for (unsigned int n_undefined_shader_stage = 0; n_undefined_shader_stage < n_undefined_shader_stages;
10273		 ++n_undefined_shader_stage)
10274	{
10275		glw::GLenum shader_stage = undefined_shader_stages[n_undefined_shader_stage];
10276
10277		gl.getUniformSubroutineuiv(shader_stage, 0, /* location */
10278								   &temp_value);
10279		error_code = gl.getError();
10280
10281		if (error_code != GL_INVALID_OPERATION)
10282		{
10283			m_testCtx.getLog() << tcu::TestLog::Message
10284							   << "glGetUniformSubroutineuiv() does not generate GL_INVALID_OPERATION "
10285								  "when called for a shader stage that is not defined for active "
10286								  "program object."
10287							   << tcu::TestLog::EndMessage;
10288
10289			m_has_test_passed = false;
10290		}
10291	} /* for (all undefined shader stages) */
10292
10293	/* All done */
10294	if (m_has_test_passed)
10295	{
10296		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10297	}
10298	else
10299	{
10300		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10301	}
10302
10303	return STOP;
10304}
10305
10306/** Constructor
10307 *
10308 *  @param context Rendering context.
10309 *
10310 **/
10311NegativeTest2::NegativeTest2(deqp::Context& context)
10312	: TestCase(context, "subroutine_uniform_scope", "Verifies subroutine uniforms declared in shader stage A"
10313													"cannot be accessed from a different stage.")
10314	, m_fs_id(0)
10315	, m_gs_id(0)
10316	, m_has_test_passed(true)
10317	, m_po_id(0)
10318	, m_tc_id(0)
10319	, m_te_id(0)
10320	, m_vs_id(0)
10321{
10322	/* Left blank intentionally */
10323}
10324
10325/** Deinitializes all GL objects that may have been created during test execution */
10326void NegativeTest2::deinit()
10327{
10328	deinitGLObjects();
10329}
10330
10331/** Deinitializes all GL objects that may have been created during test execution */
10332void NegativeTest2::deinitGLObjects()
10333{
10334	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10335
10336	if (m_fs_id != 0)
10337	{
10338		gl.deleteShader(m_fs_id);
10339
10340		m_fs_id = 0;
10341	}
10342
10343	if (m_gs_id != 0)
10344	{
10345		gl.deleteShader(m_gs_id);
10346
10347		m_gs_id = 0;
10348	}
10349
10350	if (m_tc_id != 0)
10351	{
10352		gl.deleteShader(m_tc_id);
10353
10354		m_tc_id = 0;
10355	}
10356
10357	if (m_te_id != 0)
10358	{
10359		gl.deleteShader(m_te_id);
10360
10361		m_te_id = 0;
10362	}
10363
10364	if (m_vs_id != 0)
10365	{
10366		gl.deleteShader(m_vs_id);
10367
10368		m_vs_id = 0;
10369	}
10370
10371	if (m_po_id != 0)
10372	{
10373		gl.deleteProgram(m_po_id);
10374
10375		m_po_id = 0;
10376	}
10377}
10378
10379/** Builds an offending program object and tries to link it. We're either expecting
10380 *  a compile-time or link-time error here.
10381 *
10382 *  If the program object builds successfully, the test has failed.
10383 *
10384 *  @param referencing_stage Shader stage which defines a subroutine uniform that
10385 *                           should be called from fragment/geometry/tess control/
10386 *                           tess evaluation/vertex shader stages.
10387 *
10388 **/
10389void NegativeTest2::executeTestCase(const Utils::_shader_stage& referencing_stage)
10390{
10391	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10392
10393	const std::string fs_body = getFragmentShaderBody(referencing_stage);
10394	const std::string gs_body = getGeometryShaderBody(referencing_stage);
10395	const std::string tc_body = getTessellationControlShaderBody(referencing_stage);
10396	const std::string te_body = getTessellationEvaluationShaderBody(referencing_stage);
10397	const std::string vs_body = getVertexShaderBody(referencing_stage);
10398
10399	if (Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, NULL, /* xfb_varyings */
10400							0,													   /* n_xfb_varyings */
10401							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
10402	{
10403		/* Test program should not have built correctly ! */
10404		m_testCtx.getLog() << tcu::TestLog::Message << "In the following program, one of the stages references "
10405													   "a subroutine that is defined in another stage. This "
10406													   "is forbidden by the specification.\n"
10407													   "\n"
10408													   "Vertex shader:\n\n"
10409						   << vs_body.c_str() << "\n\nTessellation control shader:\n\n"
10410						   << tc_body.c_str() << "\n\nTessellation evaluation shader:\n\n"
10411						   << te_body.c_str() << "\n\nGeometry shader:\n\n"
10412						   << gs_body.c_str() << "\n\nFragment shader:\n\n"
10413						   << fs_body.c_str() << tcu::TestLog::EndMessage;
10414
10415		m_has_test_passed = false;
10416	} /* if (test program was built successfully) */
10417
10418	/* Release the shaders & the program object that buildProgram() created */
10419	deinitGLObjects();
10420}
10421
10422/** Retrieves an offending fragment shader body.
10423 *
10424 *  @param referencing_stage Shader stage which defines the subroutine uniform that
10425 *                           will be called from fragment shader.
10426 *
10427 *  @return Requested string.
10428 **/
10429std::string NegativeTest2::getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const
10430{
10431	std::stringstream result;
10432
10433	/* Form the pre-amble */
10434	result << "#version 400\n"
10435			  "\n"
10436			  "#extension GL_ARB_shader_subroutine : require\n"
10437			  "\n"
10438			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10439			  "\n"
10440			  /* Define a subroutine */
10441			  "subroutine(testSubroutineType) void fs_subroutine(out vec4 test_argument)\n"
10442			  "{\n"
10443			  "    test_argument = vec4(1, 0, 0, 0);\n"
10444			  "}\n"
10445			  "\n"
10446			  /* Define output variables */
10447			  "out vec4 result;\n"
10448			  "\n"
10449			  /* Define uniforms */
10450			  "subroutine uniform testSubroutineType test_fs_subroutine;\n"
10451			  "\n"
10452			  /* Define main() */
10453			  "void main()\n"
10454			  "{\n"
10455			  "    "
10456		   << getSubroutineUniformName(referencing_stage) << "(result);\n"
10457															 "}\n";
10458
10459	return result.str();
10460}
10461
10462/** Retrieves an offending geometry shader body.
10463 *
10464 *  @param referencing_stage Shader stage which defines the subroutine uniform that
10465 *                           will be called from geometry shader.
10466 *
10467 *  @return Requested string.
10468 **/
10469std::string NegativeTest2::getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const
10470{
10471	std::stringstream result;
10472
10473	/* Form the pre-amble */
10474	result << "#version 400\n"
10475			  "\n"
10476			  "#extension GL_ARB_shader_subroutine : require\n"
10477			  "\n"
10478			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10479			  "\n"
10480			  "layout(points)                   in;\n"
10481			  "layout(points, max_vertices = 1) out;\n"
10482			  "\n"
10483			  /* Define a subroutine */
10484			  "subroutine(testSubroutineType) void gs_subroutine(out vec4 test_argument)\n"
10485			  "{\n"
10486			  "    test_argument = vec4(0, 1, 1, 1);\n"
10487			  "}\n"
10488			  "\n"
10489			  /* Define output variables */
10490			  "out vec4 result;\n"
10491			  "\n"
10492			  /* Define uniforms */
10493			  "subroutine uniform testSubroutineType test_gs_subroutine;\n"
10494			  "\n"
10495			  /* Define main() */
10496			  "void main()\n"
10497			  "{\n"
10498			  "    "
10499		   << getSubroutineUniformName(referencing_stage) << "(result);\n"
10500															 "}\n";
10501
10502	return result.str();
10503}
10504
10505/** Retrieves name of the subroutine uniform that is defined in user-specified
10506 *  shader stage.
10507 *
10508 *  @param stage Shader stage to retrieve the subroutine uniform name for.
10509 *
10510 *  @return As per description.
10511 **/
10512std::string NegativeTest2::getSubroutineUniformName(const Utils::_shader_stage& stage) const
10513{
10514	std::string result = "?";
10515
10516	switch (stage)
10517	{
10518	case Utils::SHADER_STAGE_FRAGMENT:
10519	{
10520		result = "test_fs_subroutine";
10521
10522		break;
10523	}
10524
10525	case Utils::SHADER_STAGE_GEOMETRY:
10526	{
10527		result = "test_gs_subroutine";
10528
10529		break;
10530	}
10531
10532	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
10533	{
10534		result = "test_tc_subroutine";
10535
10536		break;
10537	}
10538
10539	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
10540	{
10541		result = "test_te_subroutine";
10542
10543		break;
10544	}
10545
10546	case Utils::SHADER_STAGE_VERTEX:
10547	{
10548		result = "test_vs_subroutine";
10549
10550		break;
10551	}
10552
10553	default:
10554	{
10555		TCU_FAIL("Unrecognized shader stage requested");
10556	}
10557	} /* switch (stage) */
10558
10559	return result;
10560}
10561
10562/** Retrieves an offending tessellation control shader body.
10563 *
10564 *  @param referencing_stage Shader stage which defines the subroutine uniform that
10565 *                           will be called from tessellation control shader.
10566 *
10567 *  @return Requested string.
10568 **/
10569std::string NegativeTest2::getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const
10570{
10571	std::stringstream result;
10572
10573	/* Form the pre-amble */
10574	result << "#version 400\n"
10575			  "\n"
10576			  "#extension GL_ARB_shader_subroutine : require\n"
10577			  "\n"
10578			  "layout(vertices = 4) out;\n"
10579			  "\n"
10580			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10581			  "\n"
10582			  /* Define a subroutine */
10583			  "subroutine(testSubroutineType) void tc_subroutine(out vec4 test_argument)\n"
10584			  "{\n"
10585			  "    test_argument = vec4(0, 0, 1, 0);\n"
10586			  "}\n"
10587			  "\n"
10588			  /* Define uniforms */
10589			  "subroutine uniform testSubroutineType test_tc_subroutine;\n"
10590			  "\n"
10591			  /* Define main() */
10592			  "void main()\n"
10593			  "{\n"
10594			  "    "
10595		   << getSubroutineUniformName(referencing_stage) << "(gl_out[gl_InvocationID].gl_Position);\n"
10596															 "}\n";
10597
10598	return result.str();
10599}
10600
10601/** Retrieves an offending tessellation evaluation shader body.
10602 *
10603 *  @param referencing_stage Shader stage which defines the subroutine uniform that
10604 *                           will be called from tessellation evaluation shader.
10605 *
10606 *  @return Requested string.
10607 **/
10608std::string NegativeTest2::getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const
10609{
10610	std::stringstream result;
10611
10612	/* Form the pre-amble */
10613	result << "#version 400\n"
10614			  "\n"
10615			  "#extension GL_ARB_shader_subroutine : require\n"
10616			  "\n"
10617			  "layout(quads) in;\n"
10618			  "\n"
10619			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10620			  "\n"
10621			  /* Define a subroutine */
10622			  "subroutine(testSubroutineType) void te_subroutine(out vec4 test_argument)\n"
10623			  "{\n"
10624			  "    test_argument = vec4(1, 1, 1, 1);\n"
10625			  "}\n"
10626			  "\n"
10627			  /* Define uniforms */
10628			  "subroutine uniform testSubroutineType test_te_subroutine;\n"
10629			  "\n"
10630			  /* Define main() */
10631			  "void main()\n"
10632			  "{\n"
10633			  "    "
10634		   << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
10635															 "}\n";
10636
10637	return result.str();
10638}
10639
10640/** Retrieves an offending vertex shader body.
10641 *
10642 *  @param referencing_stage Shader stage which defines the subroutine uniform that
10643 *                           will be called from vertex shader.
10644 *
10645 *  @return Requested string.
10646 **/
10647std::string NegativeTest2::getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const
10648{
10649	std::stringstream result;
10650
10651	/* Form the pre-amble */
10652	result << "#version 400\n"
10653			  "\n"
10654			  "#extension GL_ARB_shader_subroutine : require\n"
10655			  "\n"
10656			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10657			  "\n"
10658			  /* Define a subroutine */
10659			  "subroutine(testSubroutineType) void vs_subroutine(out vec4 test_argument)\n"
10660			  "{\n"
10661			  "    test_argument = vec4(0, 1, 0, 0);\n"
10662			  "}\n"
10663			  "\n"
10664			  /* Define uniforms */
10665			  "subroutine uniform testSubroutineType test_vs_subroutine;\n"
10666			  "\n"
10667			  /* Define main() */
10668			  "void main()\n"
10669			  "{\n"
10670			  "    "
10671		   << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
10672															 "}\n";
10673
10674	return result.str();
10675}
10676
10677/** Executes test iteration.
10678 *
10679 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10680 */
10681tcu::TestNode::IterateResult NegativeTest2::iterate()
10682{
10683	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10684	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10685	{
10686		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10687	}
10688
10689	/* Iterate over all shader stages and execute the checks */
10690	for (int referencing_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
10691		 referencing_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++referencing_stage)
10692	{
10693		executeTestCase(static_cast<Utils::_shader_stage>(referencing_stage));
10694	} /* for (all test cases) */
10695
10696	/* All done */
10697	if (m_has_test_passed)
10698	{
10699		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10700	}
10701	else
10702	{
10703		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10704	}
10705
10706	return STOP;
10707}
10708
10709/** Constructor.
10710 *
10711 *  @param context Rendering context.
10712 *
10713 **/
10714NegativeTest3::NegativeTest3(deqp::Context& context)
10715	: TestCase(context, "missing_subroutine_keyword", "Verifies that subroutine keyword is necessary when declaring a "
10716													  "subroutine uniforn and a compilation error occurs without it.")
10717	, m_has_test_passed(true)
10718	, m_so_id(0)
10719{
10720	/* Left blank intentionally */
10721}
10722
10723/** Deinitializes all GL objects that may have been created during test execution */
10724void NegativeTest3::deinit()
10725{
10726	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10727
10728	if (m_so_id != 0)
10729	{
10730		gl.deleteShader(m_so_id);
10731
10732		m_so_id = 0;
10733	}
10734}
10735
10736/** Verifies that broken shader (for user-specified shader stage) does not compile.
10737 *
10738 *  @param shader_stage Shader stage to use for the test.
10739 **/
10740void NegativeTest3::executeTest(const Utils::_shader_stage& shader_stage)
10741{
10742	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10743
10744	/* Generate a new shader object */
10745	m_so_id = gl.createShader(Utils::getGLenumForShaderStage(shader_stage));
10746	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
10747
10748	/* Assign body to the shader */
10749	std::string body;
10750	const char* body_raw_ptr = DE_NULL;
10751
10752	switch (shader_stage)
10753	{
10754	case Utils::SHADER_STAGE_VERTEX:
10755		body = getVertexShaderBody();
10756		break;
10757	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
10758		body = getTessellationControlShaderBody();
10759		break;
10760	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
10761		body = getTessellationEvaluationShaderBody();
10762		break;
10763	case Utils::SHADER_STAGE_GEOMETRY:
10764		body = getGeometryShaderBody();
10765		break;
10766	case Utils::SHADER_STAGE_FRAGMENT:
10767		body = getFragmentShaderBody();
10768		break;
10769
10770	default:
10771	{
10772		TCU_FAIL("Unrecognized shader stage requested");
10773	}
10774	} /* switch (shader_stage) */
10775
10776	body_raw_ptr = body.c_str();
10777
10778	gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
10779	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
10780
10781	/* Try to compile the shader */
10782	glw::GLint compile_status = 0;
10783
10784	gl.compileShader(m_so_id);
10785	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10786
10787	gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
10788	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10789
10790	if (compile_status == GL_TRUE)
10791	{
10792		m_testCtx.getLog() << tcu::TestLog::Message << "The following shader was expected to fail to compile but was "
10793													   "accepted by the compiler:\n"
10794													   "\n"
10795						   << body.c_str() << tcu::TestLog::EndMessage;
10796
10797		m_has_test_passed = false;
10798	}
10799
10800	/* Good to release the shader at this point */
10801	gl.deleteShader(m_so_id);
10802	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
10803}
10804
10805/** Retrieves body of a broken fragment shader.
10806 *
10807 *  @return Requested string.
10808 **/
10809std::string NegativeTest3::getFragmentShaderBody() const
10810{
10811	return "#version 400\n"
10812		   "\n"
10813		   "#extension GL_ARB_shader_subroutine : require\n"
10814		   "\n"
10815		   "subroutine void testSubroutineType(inout vec4 test);\n"
10816		   "\n"
10817		   "void testSubroutine1(inout vec4 test)\n"
10818		   "{\n"
10819		   "    test += vec4(3, 4, 5, 6);\n"
10820		   "}\n"
10821		   "\n"
10822		   "uniform testSubroutineType subroutineFunction;\n"
10823		   "out     vec4               result;\n"
10824		   "\n"
10825		   "void main()\n"
10826		   "{\n"
10827		   "    vec4 test = vec4(2, 3, 4, 5);\n"
10828		   "\n"
10829		   "    subroutineFunction(test);\n"
10830		   "\n"
10831		   "    result = test;\n"
10832		   "}\n";
10833}
10834
10835/** Retrieves body of a broken geometry shader.
10836 *
10837 *  @return Requested string.
10838 **/
10839std::string NegativeTest3::getGeometryShaderBody() const
10840{
10841	return "#version 400\n"
10842		   "\n"
10843		   "#extension GL_ARB_shader_subroutine : require\n"
10844		   "\n"
10845		   "layout(points)                   in;\n"
10846		   "layout(points, max_vertices = 1) out;\n"
10847		   "\n"
10848		   "subroutine void testSubroutineType(inout vec4 test);\n"
10849		   "\n"
10850		   "void testSubroutine1(inout vec4 test)\n"
10851		   "{\n"
10852		   "    test += vec4(3, 4, 5, 6);\n"
10853		   "}\n"
10854		   "\n"
10855		   "uniform testSubroutineType subroutineFunction;\n"
10856		   "\n"
10857		   "void main()\n"
10858		   "{\n"
10859		   "    vec4 test = vec4(2, 3, 4, 5);\n"
10860		   "\n"
10861		   "    subroutineFunction(test);\n"
10862		   "\n"
10863		   "    gl_Position = test;\n"
10864		   "    EmitVertex();\n"
10865		   "}\n";
10866}
10867
10868/** Retrieves body of a broken tessellation control shader.
10869 *
10870 *  @return Requested string.
10871 **/
10872std::string NegativeTest3::getTessellationControlShaderBody() const
10873{
10874	return "#version 400\n"
10875		   "\n"
10876		   "#extension GL_ARB_shader_subroutine : require\n"
10877		   "\n"
10878		   "layout(vertices=4) out;\n"
10879		   "\n"
10880		   "subroutine void testSubroutineType(inout vec4 test);\n"
10881		   "\n"
10882		   "void testSubroutine1(inout vec4 test)\n"
10883		   "{\n"
10884		   "    test += vec4(1, 2, 3, 4);\n"
10885		   "}\n"
10886		   "\n"
10887		   "uniform testSubroutineType subroutineFunction;\n"
10888		   "\n"
10889		   "void main()\n"
10890		   "{\n"
10891		   "    vec4 test = vec4(0, 1, 2, 3);\n"
10892		   "\n"
10893		   "    subroutineFunction(test);\n"
10894		   "\n"
10895		   "    gl_out[gl_InvocationID].gl_Position = test;\n"
10896		   "}\n";
10897}
10898
10899/** Retrieves body of a broken tessellation evaluation shader.
10900 *
10901 *  @return Requested string.
10902 **/
10903std::string NegativeTest3::getTessellationEvaluationShaderBody() const
10904{
10905	return "#version 400\n"
10906		   "\n"
10907		   "#extension GL_ARB_shader_subroutine : require\n"
10908		   "\n"
10909		   "layout(quads) in;\n"
10910		   "\n"
10911		   "subroutine void testSubroutineType(inout vec4 test);\n"
10912		   "\n"
10913		   "void testSubroutine1(inout vec4 test)\n"
10914		   "{\n"
10915		   "    test += vec4(2, 3, 4, 5);\n"
10916		   "}\n"
10917		   "\n"
10918		   "uniform testSubroutineType subroutineFunction;\n"
10919		   "\n"
10920		   "void main()\n"
10921		   "{\n"
10922		   "    vec4 test = vec4(1, 2, 3, 4);\n"
10923		   "\n"
10924		   "    subroutineFunction(test);\n"
10925		   "\n"
10926		   "    gl_Position = test;\n"
10927		   "}\n";
10928}
10929
10930/** Retrieves body of a broken vertex shader.
10931 *
10932 *  @return Requested string.
10933 **/
10934std::string NegativeTest3::getVertexShaderBody() const
10935{
10936	return "#version 400\n"
10937		   "\n"
10938		   "#extension GL_ARB_shader_subroutine : require\n"
10939		   "\n"
10940		   "subroutine void testSubroutineType(inout vec4 test);\n"
10941		   "\n"
10942		   "void testSubroutine1(inout vec4 test)\n"
10943		   "{\n"
10944		   "    test += vec4(0, 1, 2, 3);\n"
10945		   "}\n"
10946		   "\n"
10947		   "uniform testSubroutineType subroutineFunction;\n"
10948		   "\n"
10949		   "void main()\n"
10950		   "{\n"
10951		   "    subroutineFunction(gl_Position);\n"
10952		   "}\n";
10953}
10954
10955/** Executes test iteration.
10956 *
10957 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10958 */
10959tcu::TestNode::IterateResult NegativeTest3::iterate()
10960{
10961	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10962	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10963	{
10964		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10965	}
10966
10967	/* Iterate over all shader stages */
10968	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
10969		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
10970	{
10971		executeTest(static_cast<Utils::_shader_stage>(shader_stage));
10972	} /* for (all shader stages) */
10973
10974	/* Done */
10975	if (m_has_test_passed)
10976	{
10977		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10978	}
10979	else
10980	{
10981		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10982	}
10983
10984	return STOP;
10985}
10986
10987/** Constructor.
10988 *
10989 *  @param context Rendering context.
10990 *
10991 **/
10992NegativeTest4::NegativeTest4(deqp::Context& context)
10993	: TestCase(context, "subroutines_incompatible_with_subroutine_type",
10994			   "Verifies that a compile-time error is generated when arguments and "
10995			   "return type do not match beween the function and each associated "
10996			   "subroutine type.")
10997	, m_has_test_passed(true)
10998	, m_so_id(0)
10999{
11000	/* Left blank intentionally */
11001}
11002
11003/** Deinitializes GL objects that may have been created during test
11004 *  execution.
11005 **/
11006void NegativeTest4::deinit()
11007{
11008	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11009
11010	if (m_so_id != 0)
11011	{
11012		gl.deleteShader(m_so_id);
11013
11014		m_so_id = 0;
11015	}
11016}
11017
11018/** Retrieves body of a shader of user-specified type that should be used
11019 *  for a single test iteration. The shader will define user-specified number
11020 *  of subroutine types, with the last type either defining an additional argument
11021 *  or using a different return type.
11022 *  A subroutine (claimed compatible with *all* subroutine types) will also be
11023 *  defined in the shader.
11024 *
11025 *  @param shader_stage       Shader stage to use for the query.
11026 *  @param n_subroutine_types Overall number of subroutine types that will be
11027 *                            declared & used in the shader. Please see description
11028 *                            for more details.
11029 *
11030 *  @return Requested string.
11031 **/
11032std::string NegativeTest4::getShaderBody(const Utils::_shader_stage& shader_stage,
11033										 const unsigned int& n_subroutine_types, const _test_case& test_case) const
11034{
11035	std::stringstream result_sstream;
11036
11037	/* Form the pre-amble */
11038	result_sstream << "#version 400\n"
11039					  "\n"
11040					  "#extension GL_ARB_shader_subroutine : require\n"
11041					  "\n";
11042
11043	/* Inject stage-specific code */
11044	switch (shader_stage)
11045	{
11046	case Utils::SHADER_STAGE_GEOMETRY:
11047	{
11048		result_sstream << "layout (points) in;\n"
11049						  "layout (points, max_vertices = 1) out;\n"
11050						  "\n";
11051
11052		break;
11053	}
11054
11055	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11056	{
11057		result_sstream << "layout (vertices = 4) out;\n"
11058						  "\n";
11059
11060		break;
11061	}
11062
11063	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11064	{
11065		result_sstream << "layout (quads) in;\n"
11066						  "\n";
11067
11068		break;
11069	}
11070
11071	default:
11072		break;
11073	} /* switch (shader_stage) */
11074
11075	/* Insert subroutine type declarations */
11076	for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types - 1; ++n_subroutine_type)
11077	{
11078		result_sstream << "subroutine void subroutineType" << n_subroutine_type << "(inout vec3 argument);\n";
11079	} /* for (all subroutine types) */
11080
11081	switch (test_case)
11082	{
11083	case TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST:
11084	{
11085		result_sstream << "subroutine void subroutineType" << (n_subroutine_types - 1)
11086					   << "(inout vec3 argument, out vec4 argument2);\n";
11087
11088		break;
11089	}
11090
11091	case TEST_CASE_INCOMPATIBLE_RETURN_TYPE:
11092	{
11093		result_sstream << "subroutine int subroutineType" << (n_subroutine_types - 1) << "(inout vec3 argument);\n";
11094
11095		break;
11096	}
11097
11098	default:
11099	{
11100		TCU_FAIL("Unrecognized test case");
11101	}
11102	} /* switch (test_case) */
11103
11104	/* Insert subroutine declarations */
11105	result_sstream << "subroutine(";
11106
11107	for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types; ++n_subroutine_type)
11108	{
11109		result_sstream << "subroutineType" << n_subroutine_type;
11110
11111		if (n_subroutine_type != (n_subroutine_types - 1))
11112		{
11113			result_sstream << ", ";
11114		}
11115	} /* for (all subroutine types) */
11116
11117	result_sstream << ") void function(inout vec3 argument)\n"
11118					  "{\n"
11119					  "    argument = vec3(1, 2, 3);\n"
11120					  "}\n"
11121					  "\n";
11122
11123	/* Insert remaining required stage-specific bits */
11124	switch (shader_stage)
11125	{
11126	case Utils::SHADER_STAGE_FRAGMENT:
11127	{
11128		result_sstream << "out vec4 result;\n"
11129						  "\n"
11130						  "void main()\n"
11131						  "{\n"
11132						  "    result = vec4(1, 2, 3, 4);\n"
11133						  "}\n";
11134
11135		break;
11136	}
11137
11138	case Utils::SHADER_STAGE_GEOMETRY:
11139	{
11140		result_sstream << "void main()\n"
11141						  "{\n"
11142						  "    gl_Position = vec4(1, 2, 3, 4);\n"
11143						  "    EmitVertex();\n"
11144						  "}\n";
11145
11146		break;
11147	}
11148
11149	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11150	{
11151		result_sstream << "void main()\n"
11152						  "{\n"
11153						  "    gl_TessLevelInner[0]                = 1;\n"
11154						  "    gl_TessLevelInner[1]                = 1;\n"
11155						  "    gl_TessLevelOuter[0]                = 1;\n"
11156						  "    gl_TessLevelOuter[1]                = 1;\n"
11157						  "    gl_TessLevelOuter[2]                = 1;\n"
11158						  "    gl_TessLevelOuter[3]                = 1;\n"
11159						  "    gl_out[gl_InvocationID].gl_Position = vec4(2, 3, 4, 5);\n"
11160						  "}\n";
11161
11162		break;
11163	}
11164
11165	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11166	case Utils::SHADER_STAGE_VERTEX:
11167	{
11168		result_sstream << "void main()\n"
11169						  "{\n"
11170						  "    gl_Position = vec4(1, 2, 3, 4);\n"
11171						  "}\n";
11172
11173		break;
11174	}
11175
11176	default:
11177	{
11178		TCU_FAIL("Unrecognized shader stage");
11179	}
11180	} /* switch (shader_stage) */
11181
11182	return result_sstream.str();
11183}
11184
11185/** Executes test iteration.
11186 *
11187 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11188 */
11189tcu::TestNode::IterateResult NegativeTest4::iterate()
11190{
11191	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11192
11193	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11194	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11195	{
11196		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11197	}
11198
11199	/* Iterate over all shader stages.. */
11200	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11201		 shader_stage != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11202	{
11203		/* For each shader stage, we will be trying to compile a number of invalid shaders.
11204		 * Each shader defines N different subroutine types. (N-1) of them are compatible
11205		 * with a subroutine, but exactly 1 will be mismatched. The test passes if GLSL
11206		 * compiler correctly detects that all shaders we will be trying to compile are
11207		 * broken.
11208		 */
11209		const glw::GLenum shader_type = Utils::getGLenumForShaderStage(static_cast<Utils::_shader_stage>(shader_stage));
11210
11211		for (unsigned int n_subroutine_types = 1; n_subroutine_types < 6; /* arbitrary number */
11212			 ++n_subroutine_types)
11213		{
11214			for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT);
11215				 ++test_case)
11216			{
11217				std::string body;
11218				const char* body_raw_ptr   = NULL;
11219				glw::GLint  compile_status = GL_FALSE;
11220
11221				body = getShaderBody(static_cast<Utils::_shader_stage>(shader_stage), n_subroutine_types,
11222									 static_cast<_test_case>(test_case));
11223				body_raw_ptr = body.c_str();
11224
11225				/* Try to compile the shader */
11226				m_so_id = gl.createShader(shader_type);
11227				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
11228
11229				gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL);
11230				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
11231
11232				gl.compileShader(m_so_id);
11233				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
11234
11235				gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
11236				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11237
11238				if (compile_status == GL_TRUE)
11239				{
11240					m_testCtx.getLog() << tcu::TestLog::Message << "A malformed "
11241									   << Utils::getShaderStageString(static_cast<Utils::_shader_stage>(shader_stage))
11242									   << " compiled successfully "
11243										  "("
11244									   << n_subroutine_types << " subroutine types "
11245																"were defined)."
11246									   << tcu::TestLog::EndMessage;
11247
11248					m_has_test_passed = false;
11249				}
11250
11251				/* Release the object */
11252				gl.deleteShader(m_so_id);
11253				GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
11254			} /* for (all test cases) */
11255		}	 /* for (a number of different subroutine type declarations) */
11256	}		  /* for (all shader stages) */
11257
11258	/* Done */
11259	if (m_has_test_passed)
11260	{
11261		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11262	}
11263	else
11264	{
11265		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11266	}
11267
11268	return STOP;
11269}
11270
11271/** Constructor.
11272 *
11273 *  @param context Rendering context.
11274 *
11275 **/
11276NegativeTest5::NegativeTest5(deqp::Context& context)
11277	: TestCase(context, "subroutine_uniform_wo_matching_subroutines",
11278			   "Verifies that a link- or compile-time error occurs when "
11279			   "trying to link a program with no subroutine for subroutine "
11280			   "uniform variable.")
11281	, m_fs_id(0)
11282	, m_gs_id(0)
11283	, m_has_test_passed(true)
11284	, m_po_id(0)
11285	, m_tc_id(0)
11286	, m_te_id(0)
11287	, m_vs_id(0)
11288{
11289	/* Left blank intentionally */
11290}
11291
11292/** Deinitializes all GL objects that may have been created during test execution */
11293void NegativeTest5::deinit()
11294{
11295	deinitIteration();
11296}
11297
11298/** Deinitializes all GL objects that may have been created during a single test
11299 *  iteration.
11300 ***/
11301void NegativeTest5::deinitIteration()
11302{
11303	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11304
11305	if (m_fs_id != 0)
11306	{
11307		gl.deleteShader(m_fs_id);
11308
11309		m_fs_id = 0;
11310	}
11311
11312	if (m_gs_id != 0)
11313	{
11314		gl.deleteShader(m_gs_id);
11315
11316		m_gs_id = 0;
11317	}
11318
11319	if (m_po_id != 0)
11320	{
11321		gl.deleteProgram(m_po_id);
11322
11323		m_po_id = 0;
11324	}
11325
11326	if (m_tc_id != 0)
11327	{
11328		gl.deleteShader(m_tc_id);
11329
11330		m_tc_id = 0;
11331	}
11332
11333	if (m_te_id != 0)
11334	{
11335		gl.deleteShader(m_te_id);
11336
11337		m_te_id = 0;
11338	}
11339
11340	if (m_vs_id != 0)
11341	{
11342		gl.deleteShader(m_vs_id);
11343
11344		m_vs_id = 0;
11345	}
11346}
11347
11348/** Executes a single test iteration.
11349 *
11350 *  If the iteration fails, m_has_test_passed will be set to false.
11351 *
11352 *  @param shader_stage Shader stage, for which a subroutine uniform should be
11353 *                      declared in the shader without a matching subroutine.
11354 **/
11355void NegativeTest5::executeIteration(const Utils::_shader_stage& shader_stage)
11356{
11357	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
11358	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
11359	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
11360	std::string te_body =
11361		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
11362	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
11363
11364	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
11365							DE_NULL, /* xfb_varyings */
11366							DE_NULL, /* n_xfb_varyings */
11367							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
11368	{
11369		/* None of the test programs should ever build successfully */
11370		m_testCtx.getLog() << tcu::TestLog::Message
11371						   << "A program object, consisting of the following shaders, has linked"
11372							  " correctly. One of the shaders defines a subroutine uniform but does "
11373							  "not implement any function that matches subroutine type of the uniform."
11374							  " This should have resulted in a compilation/link-time error.\n"
11375							  "\n"
11376							  "Vertex shader:\n"
11377							  "\n"
11378						   << vs_body << "\n"
11379										 "Tessellation control shader:\n"
11380										 "\n"
11381						   << tc_body << "\n"
11382										 "Tessellation evaluation shader:\n"
11383										 "\n"
11384						   << te_body << "\n"
11385										 "Geometry shader:\n"
11386										 "\n"
11387						   << gs_body << "\n"
11388										 "Fragment shader:\n"
11389										 "\n"
11390						   << fs_body << tcu::TestLog::EndMessage;
11391
11392		m_has_test_passed = false;
11393	}
11394}
11395
11396/** Retrieves fragment shader body.
11397 *
11398 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11399 *                                                        a subroutine uniform without
11400 *                                                        a matching subroutine, false otherwise.
11401 *
11402 *  @return Requested string.
11403 **/
11404std::string NegativeTest5::getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const
11405{
11406	std::stringstream result_sstream;
11407
11408	result_sstream << "#version 400\n"
11409					  "\n"
11410					  "#extension GL_ARB_shader_subroutine : require\n"
11411					  "\n";
11412
11413	if (include_invalid_subroutine_uniform_declaration)
11414	{
11415		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
11416						  "\n"
11417						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
11418	}
11419
11420	result_sstream << "\n"
11421					  "out vec4 result;\n"
11422					  "\n"
11423					  "void main()\n"
11424					  "{\n";
11425
11426	if (include_invalid_subroutine_uniform_declaration)
11427	{
11428		result_sstream << "    test_subroutineFS(result);\n";
11429	}
11430	else
11431	{
11432		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
11433	}
11434
11435	result_sstream << "}\n";
11436
11437	return result_sstream.str();
11438}
11439
11440/** Retrieves geometry shader body.
11441 *
11442 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11443 *                                                        a subroutine uniform without
11444 *                                                        a matching subroutine, false otherwise.
11445 *
11446 *  @return Requested string.
11447 **/
11448std::string NegativeTest5::getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const
11449{
11450	std::stringstream result_sstream;
11451
11452	result_sstream << "#version 400\n"
11453					  "\n"
11454					  "#extension GL_ARB_shader_subroutine : require\n"
11455					  "\n"
11456					  "layout (points)                   in;\n"
11457					  "layout (points, max_vertices = 1) out;\n"
11458					  "\n";
11459
11460	if (include_invalid_subroutine_uniform_declaration)
11461	{
11462		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
11463						  "\n"
11464						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
11465	}
11466
11467	result_sstream << "\n"
11468					  "void main()\n"
11469					  "{\n";
11470
11471	if (include_invalid_subroutine_uniform_declaration)
11472	{
11473		result_sstream << "    test_subroutineGS(gl_Position);\n";
11474	}
11475	else
11476	{
11477		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11478	}
11479
11480	result_sstream << "EmitVertex();\n"
11481					  "}\n";
11482
11483	return result_sstream.str();
11484}
11485
11486/** Retrieves tessellation control shader body.
11487 *
11488 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11489 *                                                        a subroutine uniform without
11490 *                                                        a matching subroutine, false otherwise.
11491 *
11492 *  @return Requested string.
11493 **/
11494std::string NegativeTest5::getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const
11495{
11496	std::stringstream result_sstream;
11497
11498	result_sstream << "#version 400\n"
11499					  "\n"
11500					  "#extension GL_ARB_shader_subroutine : require\n"
11501					  "\n"
11502					  "layout (vertices = 4) out;\n"
11503					  "\n";
11504
11505	if (include_invalid_subroutine_uniform_declaration)
11506	{
11507		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
11508						  "\n"
11509						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
11510	}
11511
11512	result_sstream << "\n"
11513					  "void main()\n"
11514					  "{\n";
11515
11516	if (include_invalid_subroutine_uniform_declaration)
11517	{
11518		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
11519	}
11520	else
11521	{
11522		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
11523	}
11524
11525	result_sstream << "}\n";
11526
11527	return result_sstream.str();
11528}
11529
11530/** Retrieves tessellation evaluation body.
11531 *
11532 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11533 *                                                        a subroutine uniform without
11534 *                                                        a matching subroutine, false otherwise.
11535 *
11536 *  @return Requested string.
11537 **/
11538std::string NegativeTest5::getTessellationEvaluationShaderBody(
11539	bool include_invalid_subroutine_uniform_declaration) const
11540{
11541	std::stringstream result_sstream;
11542
11543	result_sstream << "#version 400\n"
11544					  "\n"
11545					  "#extension GL_ARB_shader_subroutine : require\n"
11546					  "\n"
11547					  "layout (quads) in;\n"
11548					  "\n";
11549
11550	if (include_invalid_subroutine_uniform_declaration)
11551	{
11552		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
11553						  "\n"
11554						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
11555	}
11556
11557	result_sstream << "\n"
11558					  "void main()\n"
11559					  "{\n";
11560
11561	if (include_invalid_subroutine_uniform_declaration)
11562	{
11563		result_sstream << "    test_subroutineTE(gl_Position);\n";
11564	}
11565	else
11566	{
11567		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11568	}
11569
11570	result_sstream << "}\n";
11571
11572	return result_sstream.str();
11573}
11574
11575/** Retrieves vertex shader body.
11576 *
11577 *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11578 *                                                        a subroutine uniform without
11579 *                                                        a matching subroutine, false otherwise.
11580 *
11581 *  @return Requested string.
11582 **/
11583std::string NegativeTest5::getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const
11584{
11585	std::stringstream result_sstream;
11586
11587	result_sstream << "#version 400\n"
11588					  "\n"
11589					  "#extension GL_ARB_shader_subroutine : require\n"
11590					  "\n";
11591
11592	if (include_invalid_subroutine_uniform_declaration)
11593	{
11594		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
11595						  "\n"
11596						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
11597	}
11598
11599	result_sstream << "\n"
11600					  "void main()\n"
11601					  "{\n";
11602
11603	if (include_invalid_subroutine_uniform_declaration)
11604	{
11605		result_sstream << "    test_subroutineVS(gl_Position);\n";
11606	}
11607	else
11608	{
11609		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11610	}
11611
11612	result_sstream << "}\n";
11613
11614	return result_sstream.str();
11615}
11616
11617/** Executes test iteration.
11618 *
11619 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11620 */
11621tcu::TestNode::IterateResult NegativeTest5::iterate()
11622{
11623	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11624	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11625	{
11626		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11627	}
11628
11629	/* Iterate over all shader stages. Iteration-specific shader stage defines a subroutine type &
11630	 * a corresponding subroutine uniform, for which no compatible subroutines are available. All
11631	 * other shader stages are defined correctly.
11632	 */
11633	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11634		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11635	{
11636		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
11637		deinitIteration();
11638	} /* for (all shader stages) */
11639
11640	/* All done */
11641	if (m_has_test_passed)
11642	{
11643		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11644	}
11645	else
11646	{
11647		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11648	}
11649
11650	return STOP;
11651}
11652
11653/** Constructor.
11654 *
11655 *  @param context Rendering context.
11656 *
11657 **/
11658NegativeTest6::NegativeTest6(deqp::Context& context)
11659	: TestCase(context, "two_duplicate_functions_one_being_a_subroutine",
11660			   "Verifies that a link- or compile-time error occurs if any shader in "
11661			   "a program object includes two functions with the same name and one "
11662			   "of which is associated with a subroutine type.")
11663	, m_fs_id(0)
11664	, m_gs_id(0)
11665	, m_has_test_passed(true)
11666	, m_po_id(0)
11667	, m_tc_id(0)
11668	, m_te_id(0)
11669	, m_vs_id(0)
11670{
11671	/* Left blank intentionally */
11672}
11673
11674/** Deinitializes all GL objects that may have been created during test execution */
11675void NegativeTest6::deinit()
11676{
11677	deinitIteration();
11678}
11679
11680/** Deinitializes all GL objects that may have been created during a single test
11681 *  iteration.
11682 ***/
11683void NegativeTest6::deinitIteration()
11684{
11685	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11686
11687	if (m_fs_id != 0)
11688	{
11689		gl.deleteShader(m_fs_id);
11690
11691		m_fs_id = 0;
11692	}
11693
11694	if (m_gs_id != 0)
11695	{
11696		gl.deleteShader(m_gs_id);
11697
11698		m_gs_id = 0;
11699	}
11700
11701	if (m_po_id != 0)
11702	{
11703		gl.deleteProgram(m_po_id);
11704
11705		m_po_id = 0;
11706	}
11707
11708	if (m_tc_id != 0)
11709	{
11710		gl.deleteShader(m_tc_id);
11711
11712		m_tc_id = 0;
11713	}
11714
11715	if (m_te_id != 0)
11716	{
11717		gl.deleteShader(m_te_id);
11718
11719		m_te_id = 0;
11720	}
11721
11722	if (m_vs_id != 0)
11723	{
11724		gl.deleteShader(m_vs_id);
11725
11726		m_vs_id = 0;
11727	}
11728}
11729
11730/** Executes a single test iteration.
11731 *
11732 *  If the iteration fails, m_has_test_passed will be set to false.
11733 *
11734 *  @param shader_stage Shader stage, for which two duplicate functions
11735 *                      (one additionally marked as subroutine) should
11736 *                      be defined.
11737 **/
11738void NegativeTest6::executeIteration(const Utils::_shader_stage& shader_stage)
11739{
11740	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
11741	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
11742	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
11743	std::string te_body =
11744		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
11745	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
11746
11747	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
11748							DE_NULL, /* xfb_varyings */
11749							DE_NULL, /* n_xfb_varyings */
11750							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
11751	{
11752		/* None of the test programs should ever build successfully */
11753		m_testCtx.getLog() << tcu::TestLog::Message
11754						   << "A program object, consisting of the following shaders, has linked"
11755							  " correctly. This is invalid, because one of the shaders defines two"
11756							  " functions with the same name, with an exception that one of the"
11757							  " functions is marked as a subroutine.\n"
11758							  "\n"
11759							  "Vertex shader:\n"
11760							  "\n"
11761						   << vs_body << "\n"
11762										 "Tessellation control shader:\n"
11763										 "\n"
11764						   << tc_body << "\n"
11765										 "Tessellation evaluation shader:\n"
11766										 "\n"
11767						   << te_body << "\n"
11768										 "Geometry shader:\n"
11769										 "\n"
11770						   << gs_body << "\n"
11771										 "Fragment shader:\n"
11772										 "\n"
11773						   << fs_body << tcu::TestLog::EndMessage;
11774
11775		m_has_test_passed = false;
11776	}
11777}
11778
11779/** Retrieves fragment shader body.
11780 *
11781 *  @param include_invalid_declaration true if the shader should include duplicate function
11782 *                                     declaration.
11783 *
11784 *  @return Requested string.
11785 **/
11786std::string NegativeTest6::getFragmentShaderBody(bool include_invalid_declaration) const
11787{
11788	std::stringstream result_sstream;
11789
11790	result_sstream << "#version 400\n"
11791					  "\n"
11792					  "#extension GL_ARB_shader_subroutine : require\n"
11793					  "\n";
11794
11795	if (include_invalid_declaration)
11796	{
11797		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
11798						  "\n"
11799						  "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test)\n"
11800						  "{\n"
11801						  "    test = vec4(1, 2, 3, 4);\n"
11802						  "}\n"
11803						  "\n"
11804						  "void test_impl1(out vec4 test)\n"
11805						  "{\n"
11806						  "    test = vec4(2, 3, 4, 5);\n"
11807						  "}\n"
11808						  "\n"
11809						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
11810	}
11811
11812	result_sstream << "\n"
11813					  "out vec4 result;\n"
11814					  "\n"
11815					  "void main()\n"
11816					  "{\n";
11817
11818	if (include_invalid_declaration)
11819	{
11820		result_sstream << "    test_subroutineFS(result);\n";
11821	}
11822	else
11823	{
11824		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
11825	}
11826
11827	result_sstream << "}\n";
11828
11829	return result_sstream.str();
11830}
11831
11832/** Retrieves geometry shader body.
11833 *
11834 *  @param include_invalid_declaration true if the shader should include duplicate function
11835 *                                     declaration.
11836 *
11837 *  @return Requested string.
11838 **/
11839std::string NegativeTest6::getGeometryShaderBody(bool include_invalid_declaration) const
11840{
11841	std::stringstream result_sstream;
11842
11843	result_sstream << "#version 400\n"
11844					  "\n"
11845					  "#extension GL_ARB_shader_subroutine : require\n"
11846					  "\n"
11847					  "layout (points)                   in;\n"
11848					  "layout (points, max_vertices = 1) out;\n"
11849					  "\n";
11850
11851	if (include_invalid_declaration)
11852	{
11853		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
11854						  "\n"
11855						  "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test)\n"
11856						  "{\n"
11857						  "    test = vec4(1, 2, 3, 4);\n"
11858						  "}\n"
11859						  "\n"
11860						  "void test_impl1(out vec4 test)\n"
11861						  "{\n"
11862						  "    test = vec4(2, 3, 4, 5);\n"
11863						  "}\n"
11864						  "\n"
11865						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
11866	}
11867
11868	result_sstream << "\n"
11869					  "void main()\n"
11870					  "{\n";
11871
11872	if (include_invalid_declaration)
11873	{
11874		result_sstream << "    test_subroutineGS(gl_Position);\n";
11875	}
11876	else
11877	{
11878		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11879	}
11880
11881	result_sstream << "EmitVertex();\n"
11882					  "}\n";
11883
11884	return result_sstream.str();
11885}
11886
11887/** Retrieves tessellation control shader body.
11888 *
11889 *  @param include_invalid_declaration true if the shader should include duplicate function
11890 *                                     declaration.
11891 *
11892 *  @return Requested string.
11893 **/
11894std::string NegativeTest6::getTessellationControlShaderBody(bool include_invalid_declaration) const
11895{
11896	std::stringstream result_sstream;
11897
11898	result_sstream << "#version 400\n"
11899					  "\n"
11900					  "#extension GL_ARB_shader_subroutine : require\n"
11901					  "\n"
11902					  "layout (vertices = 4) out;\n"
11903					  "\n";
11904
11905	if (include_invalid_declaration)
11906	{
11907		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
11908						  "\n"
11909						  "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test)\n"
11910						  "{\n"
11911						  "    test = vec4(1, 2, 3, 4);\n"
11912						  "}\n"
11913						  "\n"
11914						  "void test_impl1(out vec4 test)\n"
11915						  "{\n"
11916						  "    test = vec4(2, 3, 4, 5);\n"
11917						  "}\n"
11918						  "\n"
11919						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
11920	}
11921
11922	result_sstream << "\n"
11923					  "void main()\n"
11924					  "{\n";
11925
11926	if (include_invalid_declaration)
11927	{
11928		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
11929	}
11930	else
11931	{
11932		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
11933	}
11934
11935	result_sstream << "}\n";
11936
11937	return result_sstream.str();
11938}
11939
11940/** Retrieves tessellation evaluation body.
11941 *
11942 *  @param include_invalid_declaration true if the shader should include duplicate function
11943 *                                     declaration.
11944 *
11945 *  @return Requested string.
11946 **/
11947std::string NegativeTest6::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
11948{
11949	std::stringstream result_sstream;
11950
11951	result_sstream << "#version 400\n"
11952					  "\n"
11953					  "#extension GL_ARB_shader_subroutine : require\n"
11954					  "\n"
11955					  "layout (quads) in;\n"
11956					  "\n";
11957
11958	if (include_invalid_declaration)
11959	{
11960		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
11961						  "\n"
11962						  "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test)\n"
11963						  "{\n"
11964						  "    test = vec4(1, 2, 3, 4);\n"
11965						  "}\n"
11966						  "\n"
11967						  "void test_impl1(out vec4 test)\n"
11968						  "{\n"
11969						  "    test = vec4(2, 3, 4, 5);\n"
11970						  "}\n"
11971						  "\n"
11972						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
11973	}
11974
11975	result_sstream << "\n"
11976					  "void main()\n"
11977					  "{\n";
11978
11979	if (include_invalid_declaration)
11980	{
11981		result_sstream << "    test_subroutineTE(gl_Position);\n";
11982	}
11983	else
11984	{
11985		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11986	}
11987
11988	result_sstream << "}\n";
11989
11990	return result_sstream.str();
11991}
11992
11993/** Retrieves vertex shader body.
11994 *
11995 *  @param include_invalid_declaration true if the shader should include duplicate function
11996 *                                     declaration.
11997 *
11998 *  @return Requested string.
11999 **/
12000std::string NegativeTest6::getVertexShaderBody(bool include_invalid_declaration) const
12001{
12002	std::stringstream result_sstream;
12003
12004	result_sstream << "#version 400\n"
12005					  "\n"
12006					  "#extension GL_ARB_shader_subroutine : require\n"
12007					  "\n";
12008
12009	if (include_invalid_declaration)
12010	{
12011		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12012						  "\n"
12013						  "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test)\n"
12014						  "{\n"
12015						  "    test = vec4(1, 2, 3, 4);\n"
12016						  "}\n"
12017						  "\n"
12018						  "void test_impl1(out vec4 test)\n"
12019						  "{\n"
12020						  "    test = vec4(2, 3, 4, 5);\n"
12021						  "}\n"
12022						  "\n"
12023						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12024	}
12025
12026	result_sstream << "\n"
12027					  "void main()\n"
12028					  "{\n";
12029
12030	if (include_invalid_declaration)
12031	{
12032		result_sstream << "    test_subroutineVS(gl_Position);\n";
12033	}
12034	else
12035	{
12036		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12037	}
12038
12039	result_sstream << "}\n";
12040
12041	return result_sstream.str();
12042}
12043
12044/** Executes test iteration.
12045 *
12046 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12047 */
12048tcu::TestNode::IterateResult NegativeTest6::iterate()
12049{
12050	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12051	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12052	{
12053		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12054	}
12055
12056	/* Iterate over all shader stages. In each iteration, we will inject invalid
12057	 * duplicate function declarations to iteration-specific shader stage. All other
12058	 * shader stages will be assigned valid bodies. Test should fail if the program
12059	 * links successfully.
12060	 */
12061	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12062		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12063	{
12064		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12065		deinitIteration();
12066	} /* for (all shader stages) */
12067
12068	/* All done */
12069	if (m_has_test_passed)
12070	{
12071		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12072	}
12073	else
12074	{
12075		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12076	}
12077
12078	return STOP;
12079}
12080
12081/** Constructor
12082 *
12083 * @param context CTS context
12084 **/
12085NegativeTest7::NegativeTest7(deqp::Context& context)
12086	: TestCase(context, "recursion", "Verify that it is not possible to build program with recursing subroutines")
12087	, m_program_id(0)
12088	, m_vertex_shader_id(0)
12089{
12090	/* Nothing to be done here */
12091}
12092
12093/** Deinitializes all GL objects that may have been created during test execution
12094 *
12095 **/
12096void NegativeTest7::deinit()
12097{
12098	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12099
12100	if (m_program_id != 0)
12101	{
12102		gl.deleteProgram(m_program_id);
12103
12104		m_program_id = 0;
12105	}
12106
12107	if (m_vertex_shader_id != 0)
12108	{
12109		gl.deleteShader(m_vertex_shader_id);
12110
12111		m_vertex_shader_id = 0;
12112	}
12113}
12114
12115/** Executes test iteration.
12116 *
12117 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12118 **/
12119tcu::TestNode::IterateResult NegativeTest7::iterate()
12120{
12121	static const GLchar* vertex_shader_with_static_recursion =
12122		"#version 400\n"
12123		"\n"
12124		"#extension GL_ARB_shader_subroutine : require\n"
12125		"\n"
12126		"precision highp float;\n"
12127		"\n"
12128		"subroutine vec4 routine_type(in vec4 data, in uint control);\n"
12129		"\n"
12130		"subroutine (routine_type) vec4 power_routine(in vec4 data, in uint control)\n"
12131		"{\n"
12132		"    if (0 != control)\n"
12133		"    {\n"
12134		"        return data * power_routine(data, control - 1);\n"
12135		"    }\n"
12136		"    else\n"
12137		"    {\n"
12138		"        return vec4(1, 1, 1, 1);\n"
12139		"    }\n"
12140		"}\n"
12141		"\n"
12142		"subroutine (routine_type) vec4 select_routine(in vec4 data, in uint control)\n"
12143		"{\n"
12144		"    if (0 == control)\n"
12145		"    {\n"
12146		"        return data.rrrr;\n"
12147		"    }\n"
12148		"    else if (1 == control)\n"
12149		"    {\n"
12150		"        return data.gggg;\n"
12151		"    }\n"
12152		"    else if (2 == control)\n"
12153		"    {\n"
12154		"        return data.bbbb;\n"
12155		"    }\n"
12156		"    else\n"
12157		"    {\n"
12158		"        return data.aaaa;\n"
12159		"    }\n"
12160		"}\n"
12161		"\n"
12162		"subroutine uniform routine_type routine;\n"
12163		"\n"
12164		"uniform vec4 uni_value;\n"
12165		"uniform uint uni_control;\n"
12166		"\n"
12167		"out vec4 out_result;\n"
12168		"\n"
12169		"void main()\n"
12170		"{\n"
12171		"    out_result = routine(uni_value, uni_control);\n"
12172		"}\n"
12173		"\n";
12174
12175	static const GLchar* vertex_shader_with_dynamic_recursion =
12176		"#version 400\n"
12177		"\n"
12178		"#extension GL_ARB_shader_subroutine : require\n"
12179		"\n"
12180		"precision highp float;\n"
12181		"\n"
12182		"subroutine vec4 routine_type(in vec4 data);\n"
12183		"\n"
12184		"subroutine uniform routine_type routine;\n"
12185		"\n"
12186		"subroutine (routine_type) vec4 div_by_2(in vec4 data)\n"
12187		"{\n"
12188		"    return data / 2;\n"
12189		"}\n"
12190		"\n"
12191		"subroutine (routine_type) vec4 div_routine_result_by_2(in vec4 data)\n"
12192		"{\n"
12193		"    return routine(data) / 2;\n"
12194		"}\n"
12195		"\n"
12196		"uniform vec4 uni_value;\n"
12197		"\n"
12198		"out vec4 out_result;\n"
12199		"\n"
12200		"void main()\n"
12201		"{\n"
12202		"    out_result = routine(uni_value);\n"
12203		"}\n"
12204		"\n";
12205
12206	static const GLchar* vertex_shader_with_subroutine_function_recursion =
12207		"#version 400\n"
12208		"\n"
12209		"#extension GL_ARB_shader_subroutine : require\n"
12210		"\n"
12211		"precision highp float;\n"
12212		"\n"
12213		"subroutine vec4 routine_type(in vec4 data);\n"
12214		"\n"
12215		"subroutine uniform routine_type routine;\n"
12216		"\n"
12217		"vec4 function(in vec4 data)\n"
12218		"{\n"
12219		"    return routine(data) + vec4(0.5, 0.5, 0.5, 0.5);\n"
12220		"}\n"
12221		"\n"
12222		"subroutine (routine_type) vec4 routine_a(in vec4 data)\n"
12223		"{\n"
12224		"    return function(data) / 2;\n"
12225		"}\n"
12226		"\n"
12227		"subroutine (routine_type) vec4 routine_b(in vec4 data)\n"
12228		"{\n"
12229		"    return routine_a(data) * 2;\n"
12230		"}\n"
12231		"\n"
12232		"uniform vec4 uni_value;\n"
12233		"\n"
12234		"out vec4 out_result;\n"
12235		"\n"
12236		"void main()\n"
12237		"{\n"
12238		"    out_result = routine(uni_value);\n"
12239		"}\n"
12240		"\n";
12241
12242	bool result = true;
12243
12244	if (false == test(vertex_shader_with_subroutine_function_recursion, "routine_a"))
12245	{
12246		result = false;
12247	}
12248
12249	if (false == test(vertex_shader_with_dynamic_recursion, "div_routine_result_by_2"))
12250	{
12251		result = false;
12252	}
12253
12254	if (false == test(vertex_shader_with_static_recursion, "power_routine"))
12255	{
12256		result = false;
12257	}
12258
12259	/* Set result */
12260	if (true == result)
12261	{
12262		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12263	}
12264	else
12265	{
12266		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12267	}
12268
12269	/* Done */
12270	return tcu::TestNode::STOP;
12271}
12272
12273/** Try to build program from vertex shader code.
12274 *
12275 * @param vertex_shader_code        Source code of vertex shader
12276 * @param name_of_recursive_routine Name of subroutine that should cause link failure due to recursion
12277 *
12278 * @return true build process failed, false otherwise
12279 **/
12280bool NegativeTest7::test(const GLchar* vertex_shader_code, const GLchar* name_of_recursive_routine)
12281{
12282	const glw::Functions& gl		   = m_context.getRenderContext().getFunctions();
12283	bool				  result	   = true;
12284	static const GLchar*  varying_name = "out_result";
12285
12286	/* Try to build program */
12287	if (true == Utils::buildProgram(gl, vertex_shader_code, "", "", "", "", &varying_name /* varying_names */,
12288									1 /* n_varyings */, &m_vertex_shader_id, 0, 0, 0, 0, &m_program_id))
12289	{
12290		/* Success is considered an error */
12291
12292		Utils::program program(m_context);
12293		GLuint		   index = 0;
12294
12295		program.build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0);
12296
12297		/* Verify that recursive subroutine is active */
12298		try
12299		{
12300			index = program.getSubroutineIndex(name_of_recursive_routine, GL_VERTEX_SHADER);
12301		}
12302		catch (const std::exception& exc)
12303		{
12304			/* Something wrong with shader or compilation */
12305			m_context.getTestContext().getLog()
12306				<< tcu::TestLog::Message << "It is expected that subroutine: \n"
12307				<< name_of_recursive_routine
12308				<< " is considered active. This subroutine is potentially recursive and should cause link failure."
12309				<< tcu::TestLog::EndMessage;
12310
12311			throw exc;
12312		}
12313
12314		/* Subsoutine is active, however linking should fail */
12315		m_context.getTestContext().getLog()
12316			<< tcu::TestLog::Message << "Error. Program with potentially recursive subroutine, "
12317			<< name_of_recursive_routine << ", which is active, index: " << index << ", has been built successfully.\n"
12318			<< vertex_shader_code << tcu::TestLog::EndMessage;
12319
12320		result = false;
12321	}
12322
12323	/* Delete program and shader */
12324	deinit();
12325
12326	/* Done */
12327	return result;
12328}
12329
12330/** Constructor.
12331 *
12332 *  @param context Rendering context.
12333 *
12334 **/
12335NegativeTest8::NegativeTest8(deqp::Context& context)
12336	: TestCase(context, "subroutine_wo_body", "Verifies that a compile- or link-time error occurs if a function "
12337											  "declared as a subroutine does not include a body.")
12338	, m_fs_id(0)
12339	, m_gs_id(0)
12340	, m_has_test_passed(true)
12341	, m_po_id(0)
12342	, m_tc_id(0)
12343	, m_te_id(0)
12344	, m_vs_id(0)
12345{
12346	/* Left blank intentionally */
12347}
12348
12349/** Deinitializes all GL objects that may have been created during test execution */
12350void NegativeTest8::deinit()
12351{
12352	deinitIteration();
12353}
12354
12355/** Deinitializes all GL objects that may have been created during a single test
12356 *  iteration.
12357 ***/
12358void NegativeTest8::deinitIteration()
12359{
12360	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12361
12362	if (m_fs_id != 0)
12363	{
12364		gl.deleteShader(m_fs_id);
12365
12366		m_fs_id = 0;
12367	}
12368
12369	if (m_gs_id != 0)
12370	{
12371		gl.deleteShader(m_gs_id);
12372
12373		m_gs_id = 0;
12374	}
12375
12376	if (m_po_id != 0)
12377	{
12378		gl.deleteProgram(m_po_id);
12379
12380		m_po_id = 0;
12381	}
12382
12383	if (m_tc_id != 0)
12384	{
12385		gl.deleteShader(m_tc_id);
12386
12387		m_tc_id = 0;
12388	}
12389
12390	if (m_te_id != 0)
12391	{
12392		gl.deleteShader(m_te_id);
12393
12394		m_te_id = 0;
12395	}
12396
12397	if (m_vs_id != 0)
12398	{
12399		gl.deleteShader(m_vs_id);
12400
12401		m_vs_id = 0;
12402	}
12403}
12404
12405/** Executes a single test iteration.
12406 *
12407 *  If the iteration fails, m_has_test_passed will be set to false.
12408 *
12409 *  @param shader_stage Shader stage, for which two duplicate functions
12410 *                      (one additionally marked as subroutine) should
12411 *                      be defined.
12412 **/
12413void NegativeTest8::executeIteration(const Utils::_shader_stage& shader_stage)
12414{
12415	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
12416	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
12417	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
12418	std::string te_body =
12419		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
12420	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
12421
12422	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
12423							DE_NULL, /* xfb_varyings */
12424							DE_NULL, /* n_xfb_varyings */
12425							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
12426	{
12427		/* None of the test programs should ever build successfully */
12428		m_testCtx.getLog() << tcu::TestLog::Message
12429						   << "A program object consisting of FS+GS+TC+TE+VS stages has linked successfully, "
12430							  "even though one of the shaders only defines a subroutine that lacks any body."
12431							  "\n"
12432							  "Vertex shader:\n"
12433							  "\n"
12434						   << vs_body << "\n"
12435										 "Tessellation control shader:\n"
12436										 "\n"
12437						   << tc_body << "\n"
12438										 "Tessellation evaluation shader:\n"
12439										 "\n"
12440						   << te_body << "\n"
12441										 "Geometry shader:\n"
12442										 "\n"
12443						   << gs_body << "\n"
12444										 "Fragment shader:\n"
12445										 "\n"
12446						   << fs_body << tcu::TestLog::EndMessage;
12447
12448		m_has_test_passed = false;
12449	}
12450}
12451
12452/** Retrieves fragment shader body.
12453 *
12454 *  @param include_invalid_declaration true if a subroutine prototype should be included in
12455 *                                     the shader, false to skip it.
12456 *
12457 *  @return Requested string.
12458 **/
12459std::string NegativeTest8::getFragmentShaderBody(bool include_invalid_declaration) const
12460{
12461	std::stringstream result_sstream;
12462
12463	result_sstream << "#version 400\n"
12464					  "\n"
12465					  "#extension GL_ARB_shader_subroutine : require\n"
12466					  "\n";
12467
12468	if (include_invalid_declaration)
12469	{
12470		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
12471						  "\n"
12472						  "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test);\n"
12473						  "\n"
12474						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
12475	}
12476
12477	result_sstream << "\n"
12478					  "out vec4 result;\n"
12479					  "\n"
12480					  "void main()\n"
12481					  "{\n";
12482
12483	if (include_invalid_declaration)
12484	{
12485		result_sstream << "    test_subroutineFS(result);\n";
12486	}
12487	else
12488	{
12489		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
12490	}
12491
12492	result_sstream << "}\n";
12493
12494	return result_sstream.str();
12495}
12496
12497/** Retrieves geometry shader body.
12498 *
12499 *  @param include_invalid_declaration true if a subroutine prototype should be included in
12500 *                                     the shader, false to skip it.
12501 *
12502 *  @return Requested string.
12503 **/
12504std::string NegativeTest8::getGeometryShaderBody(bool include_invalid_declaration) const
12505{
12506	std::stringstream result_sstream;
12507
12508	result_sstream << "#version 400\n"
12509					  "\n"
12510					  "#extension GL_ARB_shader_subroutine : require\n"
12511					  "\n"
12512					  "layout (points)                   in;\n"
12513					  "layout (points, max_vertices = 1) out;\n"
12514					  "\n";
12515
12516	if (include_invalid_declaration)
12517	{
12518		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
12519						  "\n"
12520						  "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test);\n"
12521						  "\n"
12522						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
12523	}
12524
12525	result_sstream << "\n"
12526					  "void main()\n"
12527					  "{\n";
12528
12529	if (include_invalid_declaration)
12530	{
12531		result_sstream << "    test_subroutineGS(gl_Position);\n";
12532	}
12533	else
12534	{
12535		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12536	}
12537
12538	result_sstream << "EmitVertex();\n"
12539					  "}\n";
12540
12541	return result_sstream.str();
12542}
12543
12544/** Retrieves tessellation control shader body.
12545 *
12546 *  @param include_invalid_declaration true if a subroutine prototype should be included in
12547 *                                     the shader, false to skip it.
12548 *
12549 *  @return Requested string.
12550 **/
12551std::string NegativeTest8::getTessellationControlShaderBody(bool include_invalid_declaration) const
12552{
12553	std::stringstream result_sstream;
12554
12555	result_sstream << "#version 400\n"
12556					  "\n"
12557					  "#extension GL_ARB_shader_subroutine : require\n"
12558					  "\n"
12559					  "layout (vertices = 4) out;\n"
12560					  "\n";
12561
12562	if (include_invalid_declaration)
12563	{
12564		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
12565						  "\n"
12566						  "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test);\n"
12567						  "\n"
12568						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
12569	}
12570
12571	result_sstream << "\n"
12572					  "void main()\n"
12573					  "{\n";
12574
12575	if (include_invalid_declaration)
12576	{
12577		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
12578	}
12579	else
12580	{
12581		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
12582	}
12583
12584	result_sstream << "}\n";
12585
12586	return result_sstream.str();
12587}
12588
12589/** Retrieves tessellation evaluation body.
12590 *
12591 *  @param include_invalid_declaration true if a subroutine prototype should be included in
12592 *                                     the shader, false to skip it.
12593 *
12594 *  @return Requested string.
12595 **/
12596std::string NegativeTest8::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
12597{
12598	std::stringstream result_sstream;
12599
12600	result_sstream << "#version 400\n"
12601					  "\n"
12602					  "#extension GL_ARB_shader_subroutine : require\n"
12603					  "\n"
12604					  "layout (quads) in;\n"
12605					  "\n";
12606
12607	if (include_invalid_declaration)
12608	{
12609		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
12610						  "\n"
12611						  "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test);\n"
12612						  "\n"
12613						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
12614	}
12615
12616	result_sstream << "\n"
12617					  "void main()\n"
12618					  "{\n";
12619
12620	if (include_invalid_declaration)
12621	{
12622		result_sstream << "    test_subroutineTE(gl_Position);\n";
12623	}
12624	else
12625	{
12626		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12627	}
12628
12629	result_sstream << "}\n";
12630
12631	return result_sstream.str();
12632}
12633
12634/** Retrieves vertex shader body.
12635 *
12636 *  @param include_invalid_declaration true if a subroutine prototype should be included in
12637 *                                     the shader, false to skip it.
12638 *
12639 *  @return Requested string.
12640 **/
12641std::string NegativeTest8::getVertexShaderBody(bool include_invalid_declaration) const
12642{
12643	std::stringstream result_sstream;
12644
12645	result_sstream << "#version 400\n"
12646					  "\n"
12647					  "#extension GL_ARB_shader_subroutine : require\n"
12648					  "\n";
12649
12650	if (include_invalid_declaration)
12651	{
12652		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12653						  "\n"
12654						  "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test);\n"
12655						  "\n"
12656						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12657	}
12658
12659	result_sstream << "\n"
12660					  "void main()\n"
12661					  "{\n";
12662
12663	if (include_invalid_declaration)
12664	{
12665		result_sstream << "    test_subroutineVS(gl_Position);\n";
12666	}
12667	else
12668	{
12669		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12670	}
12671
12672	result_sstream << "}\n";
12673
12674	return result_sstream.str();
12675}
12676
12677/** Executes test iteration.
12678 *
12679 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12680 */
12681tcu::TestNode::IterateResult NegativeTest8::iterate()
12682{
12683	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12684	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12685	{
12686		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12687	}
12688
12689	/* Iterate over all shader stages. For each iteration, iteration-specific shader stage
12690	 * will feature an invalid subroutine definition. Other shader stages will be assigned
12691	 * valid bodies. The test fails if a program built of such shaders links successfully.
12692	 */
12693	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12694		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12695	{
12696		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12697		deinitIteration();
12698	} /* for (all shader stages) */
12699
12700	/* All done */
12701	if (m_has_test_passed)
12702	{
12703		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12704	}
12705	else
12706	{
12707		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12708	}
12709
12710	return STOP;
12711}
12712
12713/** Constructor.
12714 *
12715 *  @param context Rendering context.
12716 **/
12717NegativeTest9::NegativeTest9(deqp::Context& context)
12718	: TestCase(context, "subroutines_cannot_be_assigned_float_int_values_or_be_compared",
12719			   "Make sure it is not possible to assign float/int to subroutine "
12720			   "uniform and that subroutine uniform values cannot be compared.")
12721	, m_has_test_passed(true)
12722	, m_po_id(0)
12723	, m_vs_id(0)
12724{
12725	/* Left blank intentionally */
12726}
12727
12728/** Deinitializes any GL objects that may have been created during
12729 *  test execution.
12730 **/
12731void NegativeTest9::deinit()
12732{
12733	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12734
12735	if (m_po_id != 0)
12736	{
12737		gl.deleteProgram(m_po_id);
12738
12739		m_po_id = 0;
12740	}
12741
12742	if (m_vs_id != 0)
12743	{
12744		gl.deleteShader(m_vs_id);
12745
12746		m_vs_id = 0;
12747	}
12748}
12749
12750/** Returns a literal corresponding to user-specified test case enum.
12751 *
12752 *  @param test_case As per description.
12753 *
12754 *  @return Requested string.
12755 **/
12756std::string NegativeTest9::getTestCaseString(const _test_case& test_case)
12757{
12758	std::string result = "?";
12759
12760	switch (test_case)
12761	{
12762	case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
12763		result = "TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
12764		break;
12765	case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
12766		result = "TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
12767		break;
12768	case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
12769		result = "TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON";
12770		break;
12771	default:
12772		break;
12773	}
12774
12775	return result;
12776}
12777
12778/** Retrieves vertex shader body for user-specified test case.
12779 *
12780 *  @param test_case As per description.
12781 *
12782 *  @return Requested string.
12783 **/
12784std::string NegativeTest9::getVertexShader(const _test_case& test_case)
12785{
12786	std::stringstream result_sstream;
12787
12788	/* Form pre-amble */
12789	result_sstream << "#version 400\n"
12790					  "\n"
12791					  "#extension GL_ARB_shader_subroutine : require\n"
12792					  "\n"
12793					  /* Define a subroutine */
12794					  "subroutine void subroutineType(inout vec4 test);\n"
12795					  "\n"
12796					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
12797					  "{\n"
12798					  "    test += vec4(0, 1, 2, 3);\n"
12799					  "}\n"
12800					  "\n"
12801					  "subroutine uniform subroutineType function;\n"
12802					  "\n";
12803
12804	/* Include case-specific implementation */
12805	switch (test_case)
12806	{
12807	case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
12808	{
12809		result_sstream << "void main()\n"
12810						  "{\n"
12811						  "    function = 1.0f;\n"
12812						  "\n"
12813						  "    function(gl_Position);\n"
12814						  "}\n";
12815
12816		break;
12817	}
12818
12819	case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
12820	{
12821		result_sstream << "void main()\n"
12822						  "{\n"
12823						  "    function = 1;\n"
12824						  "\n"
12825						  "    function(gl_Position);\n"
12826						  "}\n";
12827
12828		break;
12829	}
12830
12831	case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
12832	{
12833		result_sstream << "subroutine uniform subroutineType function2;\n"
12834						  "\n"
12835						  "void main()\n"
12836						  "{\n"
12837						  "    if (function == function2)\n"
12838						  "    {\n"
12839						  "        function(gl_Position);\n"
12840						  "    }\n"
12841						  "    else\n"
12842						  "    {\n"
12843						  "        function2(gl_Position);\n"
12844						  "    }\n"
12845						  "}\n";
12846
12847		break;
12848	}
12849
12850	default:
12851		break;
12852	} /* switch (test_case) */
12853
12854	/* Done */
12855	return result_sstream.str();
12856}
12857
12858/** Executes test iteration.
12859 *
12860 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12861 */
12862tcu::TestNode::IterateResult NegativeTest9::iterate()
12863{
12864	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12865
12866	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12867	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12868	{
12869		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12870	}
12871
12872	/* Iterate over all test cases */
12873	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
12874	{
12875		/* Try to build a program object using invalid vertex shader, specific to the
12876		 * iteration we're currently in */
12877		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
12878
12879		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
12880												  "",				 /* te_body */
12881												  "",				 /* gs_body */
12882												  "",				 /* fs_body */
12883												  DE_NULL,			 /* xfb_varyings */
12884												  0,				 /* n_xfb_varyings */
12885												  &m_vs_id, DE_NULL, /* out_tc_id */
12886												  DE_NULL,			 /* out_te_id */
12887												  DE_NULL,			 /* out_gs_id */
12888												  DE_NULL,			 /* out_fs_id */
12889												  &m_po_id))
12890		{
12891			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
12892							   << getTestCaseString(static_cast<_test_case>(test_case))
12893							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
12894
12895			m_has_test_passed = false;
12896		}
12897
12898		/* Delete any objects that may have been created */
12899		deinit();
12900	} /* for (all test cases) */
12901
12902	/** All done */
12903	if (m_has_test_passed)
12904	{
12905		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12906	}
12907	else
12908	{
12909		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12910	}
12911
12912	return STOP;
12913}
12914
12915/** Constructor.
12916 *
12917 *  @param context Rendering context.
12918 **/
12919NegativeTest10::NegativeTest10(deqp::Context& context)
12920	: TestCase(context, "function_overloading_forbidden_for_subroutines",
12921			   "Check that an overloaded function cannot be declared with subroutine and "
12922			   "a program will fail to compile or link if any shader or stage contains"
12923			   " two or more  functions with the same name if the name is associated with"
12924			   " a subroutine type.")
12925	, m_has_test_passed(true)
12926	, m_fs_id(0)
12927	, m_gs_id(0)
12928	, m_po_id(0)
12929	, m_tc_id(0)
12930	, m_te_id(0)
12931	, m_vs_id(0)
12932{
12933	/* Left blank intentionally */
12934}
12935
12936/** Deinitializes any GL objects that may have been created during
12937 *  test execution.
12938 **/
12939void NegativeTest10::deinit()
12940{
12941	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12942
12943	if (m_fs_id != 0)
12944	{
12945		gl.deleteShader(m_fs_id);
12946
12947		m_fs_id = 0;
12948	}
12949
12950	if (m_gs_id != 0)
12951	{
12952		gl.deleteShader(m_gs_id);
12953
12954		m_gs_id = 0;
12955	}
12956
12957	if (m_po_id != 0)
12958	{
12959		gl.deleteProgram(m_po_id);
12960
12961		m_po_id = 0;
12962	}
12963
12964	if (m_tc_id != 0)
12965	{
12966		gl.deleteShader(m_tc_id);
12967
12968		m_tc_id = 0;
12969	}
12970
12971	if (m_te_id != 0)
12972	{
12973		gl.deleteShader(m_te_id);
12974
12975		m_te_id = 0;
12976	}
12977
12978	if (m_vs_id != 0)
12979	{
12980		gl.deleteShader(m_vs_id);
12981
12982		m_vs_id = 0;
12983	}
12984}
12985
12986/** Retrieves fragment shader that should be used for the purpose of the test.
12987 *  An overloaded version of a subroutine function is inserted if
12988 *  @param include_duplicate_function flag is set to true.
12989 *
12990 *  @param include_duplicate_function As per description.
12991 *
12992 *  @return Requested string.
12993 **/
12994std::string NegativeTest10::getFragmentShader(bool include_duplicate_function)
12995{
12996	std::stringstream result_sstream;
12997
12998	result_sstream << "#version 400\n"
12999					  "\n"
13000					  "#extension GL_ARB_shader_subroutine : require\n"
13001					  "\n"
13002					  "subroutine void subroutineType(inout vec4 test);\n"
13003					  "\n"
13004					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13005					  "{\n"
13006					  "    test = vec4(2, 3, 4, 5);\n"
13007					  "}\n"
13008					  "\n"
13009					  "subroutine uniform subroutineType function;\n"
13010					  "out vec4 result;\n"
13011					  "\n";
13012
13013	if (include_duplicate_function)
13014	{
13015		result_sstream << "void test_function(inout vec4 test)\n"
13016						  "{\n"
13017						  "    test = vec4(3, 4, 5, 6);\n"
13018						  "}\n"
13019						  "\n";
13020	}
13021
13022	result_sstream << "void main()\n"
13023					  "{\n"
13024					  "    test_function(result);\n"
13025					  "}\n";
13026
13027	return result_sstream.str();
13028}
13029
13030/** Retrieves geometry shader that should be used for the purpose of the test.
13031 *  An overloaded version of a subroutine function is inserted if
13032 *  @param include_duplicate_function flag is set to true.
13033 *
13034 *  @param include_duplicate_function As per description.
13035 *
13036 *  @return Requested string.
13037 **/
13038std::string NegativeTest10::getGeometryShader(bool include_duplicate_function)
13039{
13040	std::stringstream result_sstream;
13041
13042	result_sstream << "#version 400\n"
13043					  "\n"
13044					  "#extension GL_ARB_shader_subroutine : require\n"
13045					  "\n"
13046					  "layout (triangles)                        in;\n"
13047					  "layout (triangle_strip, max_vertices = 4) out;\n"
13048					  "\n"
13049					  "subroutine void subroutineType(inout vec4 test);\n"
13050					  "\n"
13051					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13052					  "{\n"
13053					  "    test = vec4(2, 3, 4, 5);\n"
13054					  "}\n"
13055					  "\n"
13056					  "subroutine uniform subroutineType function;\n"
13057					  "\n";
13058
13059	if (include_duplicate_function)
13060	{
13061		result_sstream << "void test_function(inout vec4 test)\n"
13062						  "{\n"
13063						  "    test = vec4(3, 4, 5, 6);\n"
13064						  "}\n"
13065						  "\n";
13066	}
13067
13068	result_sstream << "void main()\n"
13069					  "{\n"
13070					  "    function(gl_Position);\n"
13071					  "    EmitVertex();\n"
13072					  "    EndPrimitive();\n"
13073					  "}\n";
13074
13075	return result_sstream.str();
13076}
13077
13078/** Retrieves tess control shader that should be used for the purpose of the test.
13079 *  An overloaded version of a subroutine function is inserted if
13080 *  @param include_duplicate_function flag is set to true.
13081 *
13082 *  @param include_duplicate_function As per description.
13083 *
13084 *  @return Requested string.
13085 **/
13086std::string NegativeTest10::getTessellationControlShader(bool include_duplicate_function)
13087{
13088	std::stringstream result_sstream;
13089
13090	result_sstream << "#version 400\n"
13091					  "\n"
13092					  "#extension GL_ARB_shader_subroutine : require\n"
13093					  "\n"
13094					  "layout (vertices = 4) out;\n"
13095					  "\n"
13096					  "subroutine void subroutineType(inout vec4 test);\n"
13097					  "\n"
13098					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13099					  "{\n"
13100					  "    test = vec4(2, 3, 4, 5);\n"
13101					  "}\n"
13102					  "\n"
13103					  "subroutine uniform subroutineType function;\n"
13104					  "\n";
13105
13106	if (include_duplicate_function)
13107	{
13108		result_sstream << "void test_function(inout vec4 test)\n"
13109						  "{\n"
13110						  "    test = vec4(3, 4, 5, 6);\n"
13111						  "}\n"
13112						  "\n";
13113	}
13114
13115	result_sstream << "void main()\n"
13116					  "{\n"
13117					  "    vec4 temp;\n"
13118					  "\n"
13119					  "    function(temp);\n"
13120					  "\n"
13121					  "    gl_out[gl_InvocationID].gl_Position = temp;\n"
13122					  "    gl_TessLevelInner[0]                = temp.x;\n"
13123					  "    gl_TessLevelInner[1]                = temp.y;\n"
13124					  "    gl_TessLevelOuter[0]                = temp.z;\n"
13125					  "    gl_TessLevelOuter[1]                = temp.w;\n"
13126					  "    gl_TessLevelOuter[2]                = temp.x;\n"
13127					  "    gl_TessLevelOuter[3]                = temp.y;\n"
13128					  "}\n";
13129
13130	return result_sstream.str();
13131}
13132
13133/** Retrieves tess evaluation shader that should be used for the purpose of the test.
13134 *  An overloaded version of a subroutine function is inserted if
13135 *  @param include_duplicate_function flag is set to true.
13136 *
13137 *  @param include_duplicate_function As per description.
13138 *
13139 *  @return Requested string.
13140 **/
13141std::string NegativeTest10::getTessellationEvaluationShader(bool include_duplicate_function)
13142{
13143	std::stringstream result_sstream;
13144
13145	result_sstream << "#version 400\n"
13146					  "\n"
13147					  "#extension GL_ARB_shader_subroutine : require\n"
13148					  "\n"
13149					  "layout (quads) in;\n"
13150					  "\n"
13151					  "subroutine void subroutineType(inout vec4 test);\n"
13152					  "\n"
13153					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13154					  "{\n"
13155					  "    test = vec4(2, 3, 4, 5);\n"
13156					  "}\n"
13157					  "\n"
13158					  "subroutine uniform subroutineType function;\n"
13159					  "\n";
13160
13161	if (include_duplicate_function)
13162	{
13163		result_sstream << "void test_function(inout vec4 test)\n"
13164						  "{\n"
13165						  "    test = vec4(3, 4, 5, 6);\n"
13166						  "}\n"
13167						  "\n";
13168	}
13169
13170	result_sstream << "void main()\n"
13171					  "{\n"
13172					  "    vec4 temp;\n"
13173					  "\n"
13174					  "    function(temp);\n"
13175					  "\n"
13176					  "    gl_Position = temp;\n"
13177					  "}\n";
13178
13179	return result_sstream.str();
13180}
13181
13182/** Retrieves vertex shader that should be used for the purpose of the test.
13183 *  An overloaded version of a subroutine function is inserted if
13184 *  @param include_duplicate_function flag is set to true.
13185 *
13186 *  @param include_duplicate_function As per description.
13187 *
13188 *  @return Requested string.
13189 **/
13190std::string NegativeTest10::getVertexShader(bool include_duplicate_function)
13191{
13192	std::stringstream result_sstream;
13193
13194	result_sstream << "#version 400\n"
13195					  "\n"
13196					  "#extension GL_ARB_shader_subroutine : require\n"
13197					  "\n"
13198					  "subroutine void subroutineType(inout vec4 test);\n"
13199					  "\n"
13200					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13201					  "{\n"
13202					  "    test = vec4(2, 3, 4, 5);\n"
13203					  "}\n"
13204					  "\n"
13205					  "subroutine uniform subroutineType function;\n"
13206					  "\n";
13207
13208	if (include_duplicate_function)
13209	{
13210		result_sstream << "void test_function(inout vec4 test)\n"
13211						  "{\n"
13212						  "    test = vec4(3, 4, 5, 6);\n"
13213						  "}\n"
13214						  "\n";
13215	}
13216
13217	result_sstream << "void main()\n"
13218					  "{\n"
13219					  "    function(gl_Position);\n"
13220					  "}\n";
13221
13222	return result_sstream.str();
13223}
13224
13225/** Fills m_test_cases field with test case descriptors */
13226void NegativeTest10::initTestCases()
13227{
13228	/* For each test case, only one shader stage should define a function that
13229	 * has already been defined as a subroutine. */
13230	for (int offending_shader_stage_it = static_cast<int>(Utils::SHADER_STAGE_FIRST);
13231		 offending_shader_stage_it != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++offending_shader_stage_it)
13232	{
13233		Utils::_shader_stage offending_shader_stage = static_cast<Utils::_shader_stage>(offending_shader_stage_it);
13234		/* Form the test case descriptor */
13235		std::stringstream name_sstream;
13236		_test_case		  test_case;
13237
13238		name_sstream << "Broken shader stage:" << Utils::getShaderStageString(offending_shader_stage);
13239
13240		test_case.fs_body = getFragmentShader(offending_shader_stage == Utils::SHADER_STAGE_FRAGMENT);
13241		test_case.gs_body = getGeometryShader(offending_shader_stage == Utils::SHADER_STAGE_GEOMETRY);
13242		test_case.name	= name_sstream.str();
13243		test_case.tc_body =
13244			getTessellationControlShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
13245		test_case.te_body =
13246			getTessellationEvaluationShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
13247		test_case.vs_body = getVertexShader(offending_shader_stage == Utils::SHADER_STAGE_VERTEX);
13248
13249		m_test_cases.push_back(test_case);
13250	}
13251}
13252
13253/** Executes test iteration.
13254 *
13255 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13256 */
13257tcu::TestNode::IterateResult NegativeTest10::iterate()
13258{
13259	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13260
13261	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13262	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13263	{
13264		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13265	}
13266
13267	/* Form test cases */
13268	initTestCases();
13269
13270	/* Iterate over all test cases */
13271	for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
13272		 ++test_case_iterator)
13273	{
13274		const _test_case& test_case = *test_case_iterator;
13275
13276		/* Try to build the program object */
13277		if (ShaderSubroutine::Utils::buildProgram(gl, test_case.vs_body, test_case.tc_body, test_case.te_body,
13278												  test_case.gs_body, test_case.fs_body, DE_NULL, /* xfb_varyings */
13279												  0,											 /* n_xfb_varyings */
13280												  &m_vs_id, (test_case.tc_body.length() > 0) ? &m_tc_id : DE_NULL,
13281												  (test_case.te_body.length() > 0) ? &m_te_id : DE_NULL,
13282												  (test_case.gs_body.length() > 0) ? &m_gs_id : DE_NULL,
13283												  (test_case.fs_body.length() > 0) ? &m_fs_id : DE_NULL, &m_po_id))
13284		{
13285			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13286							   << test_case.name << "] test case, even though it was invalid."
13287							   << tcu::TestLog::EndMessage;
13288
13289			m_has_test_passed = false;
13290		}
13291
13292		/* Delete any objects that may have been created */
13293		deinit();
13294	} /* for (all test cases) */
13295
13296	/** All done */
13297	if (m_has_test_passed)
13298	{
13299		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13300	}
13301	else
13302	{
13303		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13304	}
13305
13306	return STOP;
13307}
13308
13309/** Constructor.
13310 *
13311 *  @param context Rendering context.
13312 **/
13313NegativeTest11::NegativeTest11(deqp::Context& context)
13314	: TestCase(context, "subroutine_uniforms_used_for_sampling_atomic_image_functions",
13315			   "Tries to use subroutine uniforms in invalid way in sampling, "
13316			   "atomic and image functions. Verifies that compile- or link-time "
13317			   "error occurs.")
13318	, m_has_test_passed(true)
13319	, m_po_id(0)
13320	, m_vs_id(0)
13321{
13322	/* Left blank intentionally */
13323}
13324
13325/** Deinitializes any GL objects that may have been created during
13326 *  test execution.
13327 **/
13328void NegativeTest11::deinit()
13329{
13330	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13331
13332	if (m_po_id != 0)
13333	{
13334		gl.deleteProgram(m_po_id);
13335
13336		m_po_id = 0;
13337	}
13338
13339	if (m_vs_id != 0)
13340	{
13341		gl.deleteShader(m_vs_id);
13342
13343		m_vs_id = 0;
13344	}
13345}
13346
13347/** Returns a literal corresponding to user-specified test case enum.
13348 *
13349 *  @param test_case As per description.
13350 *
13351 *  @return Requested string.
13352 **/
13353std::string NegativeTest11::getTestCaseString(const _test_case& test_case)
13354{
13355	std::string result = "?";
13356
13357	switch (test_case)
13358	{
13359	case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
13360		result = "TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT";
13361		break;
13362	case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
13363		result = "TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT";
13364		break;
13365	case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
13366		result = "TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT";
13367		break;
13368	default:
13369		break;
13370	}
13371
13372	return result;
13373}
13374
13375/** Retrieves vertex shader body for user-specified test case.
13376 *
13377 *  @param test_case As per description.
13378 *
13379 *  @return Requested string.
13380 **/
13381std::string NegativeTest11::getVertexShader(const _test_case& test_case)
13382{
13383	std::stringstream result_sstream;
13384
13385	/* Form pre-amble */
13386	result_sstream << "#version 400\n"
13387					  "\n"
13388					  "#extension GL_ARB_shader_subroutine : require\n";
13389
13390	if (test_case == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT)
13391	{
13392		result_sstream << "#extension GL_ARB_shader_atomic_counters : require\n";
13393	}
13394
13395	result_sstream << "\n"
13396					  /* Define a subroutine */
13397					  "subroutine void subroutineType(inout vec4 test);\n"
13398					  "\n"
13399					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13400					  "{\n"
13401					  "    test += vec4(0, 1, 2, 3);\n"
13402					  "}\n"
13403					  "\n"
13404					  "subroutine uniform subroutineType function;\n"
13405					  "\n"
13406
13407					  /* Define main() body */
13408					  "void main()\n"
13409					  "{\n";
13410
13411	/* Implement case-specific behavior */
13412	switch (test_case)
13413	{
13414	case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
13415	{
13416		result_sstream << "if (atomicCounter(function) > 2)\n"
13417						  "{\n"
13418						  "    gl_Position = vec4(1);\n"
13419						  "}\n";
13420
13421		break;
13422	}
13423
13424	case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
13425	{
13426		result_sstream << "imageStore(function, vec2(0.0, 1.0), vec4(1.0) );\n";
13427
13428		break;
13429	}
13430
13431	case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
13432	{
13433		result_sstream << "gl_Position = texture(function, vec2(1.0) );\n";
13434
13435		break;
13436	}
13437
13438	default:
13439		break;
13440	} /* switch (test_case) */
13441
13442	/* Close main() body */
13443	result_sstream << "}\n";
13444
13445	/* Done */
13446	return result_sstream.str();
13447}
13448
13449/** Executes test iteration.
13450 *
13451 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13452 */
13453tcu::TestNode::IterateResult NegativeTest11::iterate()
13454{
13455	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13456
13457	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13458	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13459	{
13460		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13461	}
13462
13463	/* Iterate over all test cases */
13464	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
13465	{
13466		if (static_cast<_test_case>(test_case) == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT &&
13467			!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
13468		{
13469			/* This iteration requires atomic counter support that this GL implementation
13470			 * is not capable of. Skip the iteration
13471			 */
13472			continue;
13473		}
13474
13475		/* Try to build a program object using invalid vertex shader, specific to the
13476		 * iteration we're currently in */
13477		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
13478
13479		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
13480												  "",				 /* te_body */
13481												  "",				 /* gs_body */
13482												  "",				 /* fs_body */
13483												  DE_NULL,			 /* xfb_varyings */
13484												  0,				 /* n_xfb_varyings */
13485												  &m_vs_id, DE_NULL, /* out_tc_id */
13486												  DE_NULL,			 /* out_te_id */
13487												  DE_NULL,			 /* out_gs_id */
13488												  DE_NULL,			 /* out_fs_id */
13489												  &m_po_id))
13490		{
13491			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13492							   << getTestCaseString(static_cast<_test_case>(test_case))
13493							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
13494
13495			m_has_test_passed = false;
13496		}
13497
13498		/* Delete any objects that may have been created */
13499		deinit();
13500	} /* for (all test cases) */
13501
13502	/** All done */
13503	if (m_has_test_passed)
13504	{
13505		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13506	}
13507	else
13508	{
13509		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13510	}
13511
13512	return STOP;
13513}
13514
13515/** Constructor.
13516 *
13517 *  @param context Rendering context.
13518 **/
13519NegativeTest12::NegativeTest12(deqp::Context& context)
13520	: TestCase(context, "subroutines_not_allowed_as_variables_constructors_and_argument_or_return_types",
13521			   "Verifies that it is not allowed to use subroutine type for "
13522			   "local/global variables, constructors or argument/return type.")
13523	, m_has_test_passed(true)
13524	, m_po_id(0)
13525	, m_vs_id(0)
13526{
13527	/* Left blank intentionally */
13528}
13529
13530/** Deinitializes any GL objects that may have been created during
13531 *  test execution.
13532 **/
13533void NegativeTest12::deinit()
13534{
13535	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13536
13537	if (m_po_id != 0)
13538	{
13539		gl.deleteProgram(m_po_id);
13540
13541		m_po_id = 0;
13542	}
13543
13544	if (m_vs_id != 0)
13545	{
13546		gl.deleteShader(m_vs_id);
13547
13548		m_vs_id = 0;
13549	}
13550}
13551
13552/** Returns a literal corresponding to user-specified test case enum.
13553 *
13554 *  @param test_case As per description.
13555 *
13556 *  @return Requested string.
13557 **/
13558std::string NegativeTest12::getTestCaseString(const _test_case& test_case)
13559{
13560	std::string result = "?";
13561
13562	switch (test_case)
13563	{
13564	case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
13565		result = "TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE";
13566		break;
13567	case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
13568		result = "TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE";
13569		break;
13570	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
13571		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR";
13572		break;
13573	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
13574		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT";
13575		break;
13576	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
13577		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE";
13578		break;
13579	default:
13580		break;
13581	}
13582
13583	return result;
13584}
13585
13586/** Retrieves vertex shader body for user-specified test case.
13587 *
13588 *  @param test_case As per description.
13589 *
13590 *  @return Requested string.
13591 **/
13592std::string NegativeTest12::getVertexShader(const _test_case& test_case)
13593{
13594	std::stringstream result_sstream;
13595
13596	/* Form pre-amble */
13597	result_sstream << "#version 400\n"
13598					  "\n"
13599					  "#extension GL_ARB_shader_subroutine : require\n"
13600					  "\n"
13601					  /* Define a subroutine */
13602					  "subroutine void subroutineType(inout vec4 test);\n"
13603					  "\n"
13604					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13605					  "{\n"
13606					  "    test += vec4(0, 1, 2, 3);\n"
13607					  "}\n"
13608					  "\n"
13609					  "subroutine uniform subroutineType function;\n"
13610					  "\n";
13611
13612	/* Include case-specific implementation */
13613	switch (test_case)
13614	{
13615	case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
13616	{
13617		result_sstream << "void main()\n"
13618						  "{\n"
13619						  "    subroutine subroutineType function2;\n"
13620						  "    vec4                      result;\n"
13621						  "\n"
13622						  "    function2(result);\n"
13623						  "    gl_Position = result;\n"
13624						  "}\n";
13625
13626		break;
13627	}
13628
13629	case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
13630	{
13631		result_sstream << "subroutine subroutineType function2;\n"
13632						  "\n"
13633						  "void main()\n"
13634						  "{\n"
13635						  "    vec4 result;\n"
13636						  "\n"
13637						  "    function2(result);\n"
13638						  "    gl_Position = result;\n"
13639						  "}\n";
13640
13641		break;
13642	}
13643
13644	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
13645	{
13646		result_sstream << "void main()\n"
13647						  "{\n"
13648						  "    subroutineType(function);\n"
13649						  "}\n";
13650
13651		break;
13652	}
13653
13654	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
13655	{
13656		result_sstream << "vec4 test_function(subroutineType argument)\n"
13657						  "{\n"
13658						  "    vec4 result = vec4(1, 2, 3, 4);\n"
13659						  "\n"
13660						  "    argument(result);\n"
13661						  "\n"
13662						  "    return result;\n"
13663						  "}\n"
13664						  "\n"
13665						  "void main()\n"
13666						  "{\n"
13667						  "    test_function(function);\n"
13668						  "}\n";
13669
13670		break;
13671	}
13672
13673	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
13674	{
13675		result_sstream << "subroutineType test_function()\n"
13676						  "{\n"
13677						  "    return function;\n"
13678						  "}\n"
13679						  "\n"
13680						  "void main()\n"
13681						  "{\n"
13682						  "    test_function()(gl_Position);\n"
13683						  "}\n";
13684
13685		break;
13686	}
13687
13688	default:
13689		break;
13690	} /* switch (test_case) */
13691
13692	/* Done */
13693	return result_sstream.str();
13694}
13695
13696/** Executes test iteration.
13697 *
13698 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13699 */
13700tcu::TestNode::IterateResult NegativeTest12::iterate()
13701{
13702	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13703
13704	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13705	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13706	{
13707		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13708	}
13709
13710	/* Iterate over all test cases */
13711	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
13712	{
13713		/* Try to build a program object using invalid vertex shader, specific to the
13714		 * iteration we're currently in */
13715		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
13716
13717		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
13718												  "",				 /* te_body */
13719												  "",				 /* gs_body */
13720												  "",				 /* fs_body */
13721												  DE_NULL,			 /* xfb_varyings */
13722												  0,				 /* n_xfb_varyings */
13723												  &m_vs_id, DE_NULL, /* out_tc_id */
13724												  DE_NULL,			 /* out_te_id */
13725												  DE_NULL,			 /* out_gs_id */
13726												  DE_NULL,			 /* out_fs_id */
13727												  &m_po_id))
13728		{
13729			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13730							   << getTestCaseString(static_cast<_test_case>(test_case))
13731							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
13732
13733			m_has_test_passed = false;
13734		}
13735
13736		/* Delete any objects that may have been created */
13737		deinit();
13738	} /* for (all test cases) */
13739
13740	/** All done */
13741	if (m_has_test_passed)
13742	{
13743		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13744	}
13745	else
13746	{
13747		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13748	}
13749
13750	return STOP;
13751}
13752
13753} /* ShaderSubroutine */
13754
13755/** Constructor.
13756 *
13757 *  @param context Rendering context.
13758 **/
13759ShaderSubroutineTests::ShaderSubroutineTests(deqp::Context& context)
13760	: TestCaseGroup(context, "shader_subroutine", "Verifies \"shader_subroutine\" functionality")
13761{
13762	/* Left blank on purpose */
13763}
13764
13765/** Initializes a texture_storage_multisample test group.
13766 *
13767 **/
13768void ShaderSubroutineTests::init(void)
13769{
13770	addChild(new ShaderSubroutine::APITest1(m_context));
13771	addChild(new ShaderSubroutine::APITest2(m_context));
13772	addChild(new ShaderSubroutine::FunctionalTest1_2(m_context));
13773	addChild(new ShaderSubroutine::FunctionalTest3_4(m_context));
13774	addChild(new ShaderSubroutine::FunctionalTest5(m_context));
13775	addChild(new ShaderSubroutine::FunctionalTest6(m_context));
13776	addChild(new ShaderSubroutine::FunctionalTest7_8(m_context));
13777	addChild(new ShaderSubroutine::FunctionalTest9(m_context));
13778	addChild(new ShaderSubroutine::FunctionalTest10(m_context));
13779	addChild(new ShaderSubroutine::FunctionalTest11(m_context));
13780	addChild(new ShaderSubroutine::FunctionalTest12(m_context));
13781	addChild(new ShaderSubroutine::FunctionalTest13(m_context));
13782	addChild(new ShaderSubroutine::FunctionalTest14_15(m_context));
13783	addChild(new ShaderSubroutine::FunctionalTest16(m_context));
13784	addChild(new ShaderSubroutine::FunctionalTest17(m_context));
13785	addChild(new ShaderSubroutine::FunctionalTest18_19(m_context));
13786	addChild(new ShaderSubroutine::NegativeTest1(m_context));
13787	addChild(new ShaderSubroutine::NegativeTest2(m_context));
13788	addChild(new ShaderSubroutine::NegativeTest3(m_context));
13789	addChild(new ShaderSubroutine::NegativeTest4(m_context));
13790	addChild(new ShaderSubroutine::NegativeTest5(m_context));
13791	addChild(new ShaderSubroutine::NegativeTest6(m_context));
13792	addChild(new ShaderSubroutine::NegativeTest7(m_context));
13793	addChild(new ShaderSubroutine::NegativeTest8(m_context));
13794	addChild(new ShaderSubroutine::NegativeTest9(m_context));
13795	addChild(new ShaderSubroutine::NegativeTest10(m_context));
13796	addChild(new ShaderSubroutine::NegativeTest11(m_context));
13797	addChild(new ShaderSubroutine::NegativeTest12(m_context));
13798}
13799
13800} /* glcts namespace */
13801