• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 using namespace glw;
39 
40 namespace gl4cts
41 {
42 namespace ShaderSubroutine
43 {
44 /** Constructor.
45  *
46  * @param context CTS context.
47  **/
buffer(deqp::Context & context)48 Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context)
49 {
50 }
51 
52 /** Destructor
53  *
54  **/
~buffer()55 Utils::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  **/
bindRange(glw::GLenum target,glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size)73 void 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  **/
generate()84 void 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  **/
update(glw::GLenum target,glw::GLsizeiptr size,glw::GLvoid * data,glw::GLenum usage)99 void 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  **/
framebuffer(deqp::Context & context)114 Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context)
115 {
116 	/* Nothing to be done here */
117 }
118 
119 /** Destructor
120  *
121  **/
~framebuffer()122 Utils::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  **/
attachTexture(glw::GLenum attachment,glw::GLuint texture_id,glw::GLuint width,glw::GLuint height)140 void 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  **/
bind()161 void 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  **/
clear(glw::GLenum mask)173 void 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  **/
clearColor(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)188 void 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  **/
generate()199 void 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 
207 const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9;
208 
209 /** Constructor.
210  *
211  * @param context CTS context.
212  **/
program(deqp::Context & context)213 Utils::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  **/
~program()229 Utils::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  **/
build(const glw::GLchar * compute_shader_code,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code,const glw::GLchar * const * varying_names,glw::GLuint n_varying_names,bool is_separable)246 void 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  **/
compile(glw::GLuint shader_id,const glw::GLchar * shader_code) const330 void 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  **/
isProgramBinarySupported() const380 bool 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  **/
createFromBinary(const std::vector<GLubyte> & binary,GLenum binary_format)400 void 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  **/
getBinary(std::vector<GLubyte> & binary,GLenum & binary_format) const418 void 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  **/
getSubroutineIndex(const glw::GLchar * subroutine_name,glw::GLenum shader_stage) const442 GLuint 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  **/
getSubroutineUniformLocation(const glw::GLchar * uniform_name,glw::GLenum shader_stage) const467 GLint 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  **/
getUniformLocation(const glw::GLchar * uniform_name) const492 GLint 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  **/
link() const514 void 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  **/
remove()594 void 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  **/
use() const650 void 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  **/
texture(deqp::Context & context)662 Utils::texture::texture(deqp::Context& context) : m_id(0), m_context(context)
663 {
664 	/* Nothing to done here */
665 }
666 
667 /** Destructor
668  *
669  **/
~texture()670 Utils::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  **/
bind()684 void 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  **/
create(glw::GLuint width,glw::GLuint height,glw::GLenum internal_format)698 void 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  **/
get(glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)717 void 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  **/
update(glw::GLuint width,glw::GLuint height,glw::GLenum format,glw::GLenum type,glw::GLvoid * data)735 void 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  **/
vertexArray(deqp::Context & context)750 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
751 {
752 }
753 
754 /** Destructor
755  *
756  **/
~vertexArray()757 Utils::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  **/
bind()772 void 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  **/
generate()783 void 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  *  */
buildProgram(const glw::Functions & gl,const std::string & vs_body,const std::string & tc_body,const std::string & te_body,const std::string & gs_body,const std::string & fs_body,const glw::GLchar ** xfb_varyings,const unsigned int & n_xfb_varyings,glw::GLuint * out_vs_id,glw::GLuint * out_tc_id,glw::GLuint * out_te_id,glw::GLuint * out_gs_id,glw::GLuint * out_fs_id,glw::GLuint * out_po_id)831 bool 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 
964 end:
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  **/
getBaseVariableType(const _variable_type & variable_type)975 Utils::_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  **/
getComponentSizeForVariableType(const _variable_type & variable_type)1056 unsigned 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  **/
getGLenumForShaderStage(const _shader_stage & shader_stage)1095 glw::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  **/
getNumberOfComponentsForVariableType(const _variable_type & variable_type)1132 unsigned 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  **/
getShaderStageString(const _shader_stage & shader_stage)1234 std::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  **/
getShaderStageStringFromGLEnum(const glw::GLenum shader_stage_glenum)1271 std::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  **/
programInterfaceToStr(glw::GLenum program_interface)1308 const 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  **/
pnameToStr(glw::GLenum pname)1333 const 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 
compare(const glw::GLfloat & left,const glw::GLfloat & right)1391 bool 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  **/
getVariableTypeFromProperties(const _variable_type & base_variable_type,const unsigned int & n_components)1413 Utils::_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  **/
getVariableTypeGLSLString(const _variable_type & variable_type)1566 std::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  **/
APITest1(deqp::Context & context)1674 APITest1::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  */
iterate()1686 tcu::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  **/
APITest2(deqp::Context & context)1815 APITest2::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  */
deinit()1832 void 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  **/
getVertexShaderBody()1862 std::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. */
initTest()1889 void 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 sanity 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  */
iterate()1968 tcu::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  **/
verifyGLGetActiveSubroutineNameFunctionality()2001 void 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  **/
verifyGLGetActiveSubroutineUniformNameFunctionality()2054 void 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  **/
FunctionalTest1_2(deqp::Context & context)2117 FunctionalTest1_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  */
deinit()2136 void 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 */
deinitTestIteration()2158 void 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  **/
executeTestIteration(const _test_case & test_case)2183 bool 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  **/
getVertexShaderBody(const Utils::_variable_type & variable_type,unsigned int array_size)2297 std::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. */
initTest()2515 void 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  */
iterate()2542 tcu::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  **/
verifyXFBData(const void * xfb_data,const Utils::_variable_type & variable_type)2627 bool 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  **/
FunctionalTest3_4(deqp::Context & context)2764 FunctionalTest3_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  **/
iterate()2780 tcu::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  **/
checkProgramStageiv(glw::GLuint program_id,glw::GLenum pname,glw::GLint expected) const3041 bool 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  **/
checkProgramResourceiv(GLuint program_id,GLenum program_interface,GLenum pname,const glw::GLchar * resource_name,GLint expected) const3075 bool 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  **/
checkProgramInterfaceiv(GLuint program_id,GLenum program_interface,GLenum pname,GLint expected) const3117 bool 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  **/
checkActiveSubroutineUniformiv(GLuint program_id,GLuint index,GLenum pname,GLint expected) const3152 bool 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  **/
getProgramResourceIndex(GLuint program_id,GLenum program_interface,const glw::GLchar * resource_name) const3186 GLuint 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  **/
getSubroutineIndex(GLuint program_id,const glw::GLchar * subroutine_name,bool use_program_query) const3213 GLuint 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  **/
getSubroutineUniformLocation(GLuint program_id,const glw::GLchar * uniform_name,bool use_program_query) const3246 GLint 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  **/
inspectProgramStageiv(glw::GLuint program_id) const3277 bool 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  **/
inspectProgramInterfaceiv(glw::GLuint program_id) const3307 bool 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  **/
inspectProgramResourceiv(GLuint program_id,const GLchar ** subroutine_names,const GLchar ** uniform_names) const3340 bool 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  **/
inspectActiveSubroutineUniformiv(GLuint program_id,const GLchar ** uniform_names) const3438 bool 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  **/
inspectActiveSubroutineUniformName(GLuint program_id,const GLchar ** uniform_names) const3515 bool 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  **/
inspectActiveSubroutineName(GLuint program_id,const GLchar ** subroutine_names) const3566 bool 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  **/
inspectSubroutineBinding(GLuint program_id,const GLchar ** subroutine_names,const GLchar ** uniform_names,bool use_program_query) const3618 bool 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  **/
testDraw(GLuint program_id,const GLchar * first_routine_name,const GLchar * second_routine_name,const GLchar ** uniform_names,const Utils::vec4<GLfloat> expected_results[5],bool use_program_query) const3680 bool 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  **/
FunctionalTest5(deqp::Context & context)3805 FunctionalTest5::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  **/
iterate()3814 tcu::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  **/
logError(const glw::GLchar * subroutine_names[4][2],const glw::GLuint subroutine_combination[4],const Utils::vec4<glw::GLfloat> input_data[3],const Utils::vec4<glw::GLfloat> & first_routine_result,const Utils::vec4<glw::GLfloat> & second_routine_result,const Utils::vec4<glw::GLfloat> & third_routine_result,const Utils::vec4<glw::GLuint> & fourth_routine_result,const Utils::vec4<glw::GLfloat> & first_routine_expected_result,const Utils::vec4<glw::GLfloat> & second_routine_expected_result,const Utils::vec4<glw::GLfloat> & third_routine_expected_result,const Utils::vec4<glw::GLuint> & fourth_routine_expected_result) const4054 void 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  **/
testDraw(const glw::GLuint subroutine_combination[4],const Utils::vec4<glw::GLfloat> input_data[3],Utils::vec4<glw::GLfloat> & out_first_routine_result,Utils::vec4<glw::GLfloat> & out_second_routine_result,Utils::vec4<glw::GLfloat> & out_third_routine_result,Utils::vec4<glw::GLuint> & out_fourth_routine_result) const4131 void 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  **/
verify(const Utils::vec4<glw::GLfloat> & first_routine_result,const Utils::vec4<glw::GLfloat> & second_routine_result,const Utils::vec4<glw::GLfloat> & third_routine_result,const Utils::vec4<glw::GLuint> & fourth_routine_result,const Utils::vec4<glw::GLfloat> & first_routine_expected_result,const Utils::vec4<glw::GLfloat> & second_routine_expected_result,const Utils::vec4<glw::GLfloat> & third_routine_expected_result,const Utils::vec4<glw::GLuint> & fourth_routine_expected_result) const4219 bool 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  **/
FunctionalTest6(deqp::Context & context)4242 FunctionalTest6::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  **/
iterate()4251 tcu::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  **/
FunctionalTest7_8(deqp::Context & context)4384 FunctionalTest7_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  **/
iterate()4393 tcu::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  **/
calculate(glw::GLuint function,const Utils::vec4<glw::GLfloat> & left,const Utils::vec4<glw::GLfloat> & right,Utils::vec4<glw::GLfloat> & out) const4589 void 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  **/
calculate(const glw::GLuint combination[4],const Utils::vec4<glw::GLfloat> & left,const Utils::vec4<glw::GLfloat> & right,const Utils::vec4<glw::GLuint> & indices,Utils::vec4<glw::GLfloat> & out_combined,Utils::vec4<glw::GLfloat> & out_combined_inverted,Utils::vec4<glw::GLfloat> & out_constant,Utils::vec4<glw::GLfloat> & out_constant_inverted,Utils::vec4<glw::GLfloat> & out_dynamic,Utils::vec4<glw::GLfloat> & out_dynamic_inverted,Utils::vec4<glw::GLfloat> & out_loop) const4622 void 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  **/
logError(const glw::GLuint combination[4],const Utils::vec4<glw::GLfloat> & left,const Utils::vec4<glw::GLfloat> & right,const Utils::vec4<glw::GLuint> & indices,const Utils::vec4<glw::GLfloat> vec4_expected[7],const Utils::vec4<glw::GLfloat> vec4_result[7],glw::GLuint array_length,bool result[7]) const4685 void 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  **/
testDraw(const glw::GLuint combination[4],const Utils::vec4<glw::GLfloat> & left,const Utils::vec4<glw::GLfloat> & right,const Utils::vec4<glw::GLuint> & indices) const4833 bool 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  **/
FunctionalTest9(deqp::Context & context)4925 FunctionalTest9::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. */
deinit()4941 void 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  **/
getVertexShaderBody() const4977 std::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. */
initTest()5011 void 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  */
iterate()5060 tcu::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  **/
verifyXFBData(const glw::GLvoid * data_ptr)5111 void 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  **/
FunctionalTest10(deqp::Context & context)5152 FunctionalTest10::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  **/
iterate()5161 tcu::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  **/
testDraw(const GLuint routine_indices[16]) const5319 GLint 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 */
5361 const GLuint FunctionalTest11::m_texture_height = 32;
5362 const GLuint FunctionalTest11::m_texture_width  = 32;
5363 
5364 /** Constructor
5365  *
5366  * @param context CTS context
5367  **/
FunctionalTest11(deqp::Context & context)5368 FunctionalTest11::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  **/
iterate()5379 tcu::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  **/
fillTexture(Utils::texture & texture,const glw::GLubyte color[4]) const5734 void 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  **/
testDraw(const glw::GLuint routine_configuration[5],const glw::GLuint sampler_configuration[2],const glw::GLubyte expected_color[4],Utils::texture & color_texture) const5767 bool 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 */
5842 const glw::GLuint FunctionalTest12::m_texture_height = 16;
5843 const glw::GLuint FunctionalTest12::m_texture_width  = 16;
5844 
5845 /** Constructor
5846  *
5847  * @param context CTS context
5848  **/
FunctionalTest12(deqp::Context & context)5849 FunctionalTest12::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  **/
iterate()5861 tcu::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  **/
fillTexture(Utils::texture & texture,const glw::GLuint color[4]) const5917 void 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  **/
testAtomic()5946 bool 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  **/
testAtomicDraw(GLuint subroutine_index,const GLuint expected_results[3]) const6100 bool 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  **/
testImage()6140 bool 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  **/
testImageDraw(GLuint subroutine_index,Utils::texture & left,Utils::texture & right,const GLuint expected_left_color[4],const GLuint expected_right_color[4]) const6304 bool 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  **/
testSSBO()6357 bool 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  **/
testSSBODraw(GLuint subroutine_index,const GLuint expected_results[4]) const6506 bool 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  **/
verifyTexture(Utils::texture & texture,const GLuint expected_color[4]) const6550 bool 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  **/
FunctionalTest13(deqp::Context & context)6586 FunctionalTest13::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  **/
deinit()6611 void 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  **/
getFragmentShaderBody(unsigned int n_id)6703 std::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  **/
getGeometryShaderBody(unsigned int n_id)6758 std::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  **/
getTessellationControlShaderBody(unsigned int n_id)6835 std::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  **/
getTessellationEvaluationShaderBody(unsigned int n_id)6902 std::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  **/
getVertexShaderBody(unsigned int n_id)6962 std::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  **/
initTest()7011 void 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  */
iterate()7123 tcu::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  */
verifyReadBuffer(unsigned int n_fs_id,unsigned int n_fs_subroutine,unsigned int n_gs_id,unsigned int n_gs_subroutine,unsigned int n_tc_id,unsigned int n_tc_subroutine,unsigned int n_te_id,unsigned int n_te_subroutine,unsigned int n_vs_id,unsigned int n_vs_subroutine)7352 void 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  **/
FunctionalTest14_15(deqp::Context & context)7467 FunctionalTest14_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  **/
iterate()7477 tcu::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  **/
testDefaultSubroutineSet(const Utils::vec4<glw::GLuint> & uni_input,const Utils::vec4<glw::GLuint> expected_routine_1_result[2],const Utils::vec4<glw::GLuint> expected_routine_2_result[2]) const7741 bool 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  **/
testDraw(glw::GLuint routine_configuration,const Utils::vec4<glw::GLuint> & uni_input,const Utils::vec4<glw::GLuint> & expected_routine_1_result,const Utils::vec4<glw::GLuint> & expected_routine_2_result) const7822 bool 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  **/
testIndicesAndLocations() const7917 bool 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  **/
FunctionalTest16(deqp::Context & context)7943 FunctionalTest16::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. */
deinit()7968 void 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  **/
getShaderBody(const Utils::_shader_stage & shader_stage,const unsigned int & n_id) const8067 std::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. */
initTest()8207 void 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  **/
getShaderStages(bool retrieve_program_object_shader_ids,const unsigned int & n_id,const _shader_stage ** out_shader_stages) const8405 void 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  */
iterate()8430 tcu::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  */
verifySubroutineUniformValues(const _test_case & test_case,const unsigned int & n_id,const _subroutine_uniform_value_verification & verification)8772 void 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  **/
verifySubroutineUniformValuesForShaderStage(const _shader_stage & shader_stage,const _subroutine_uniform_value_verification & verification)8802 void 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  **/
FunctionalTest17(deqp::Context & context)8895 FunctionalTest17::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. */
deinit()8918 void 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  **/
getFragmentShaderBody() const9004 std::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  **/
getGeometryShaderBody() const9042 std::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  **/
getTessellationControlShaderBody() const9112 std::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  **/
getTessellationEvaluationShaderBody() const9159 std::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  **/
getVertexShaderBody() const9201 std::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. */
initTest()9228 void 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  */
iterate()9290 tcu::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  **/
verifyRenderedData()9339 void 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  **/
FunctionalTest18_19(deqp::Context & context)9375 FunctionalTest18_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 */
deinit()9400 void 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  &**/
executeTest(glw::GLuint bool_operator1_subroutine_location,glw::GLuint bool_operator2_subroutine_location,glw::GLuint vec4_operator1_subroutine_location,glw::GLuint vec4_operator2_subroutine_location)9445 void 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. */
getVertexShaderBody() const9489 std::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. */
initTest()9573 void 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  */
iterate()9651 tcu::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  **/
vec4operator_div2(tcu::Vec4 data)9716 tcu::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  **/
vec4operator_mul4(tcu::Vec4 data)9728 tcu::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  */
verifyXFBData(const glw::GLvoid * data,glw::GLuint bool_operator1_subroutine_location,glw::GLuint bool_operator2_subroutine_location,glw::GLuint vec4_operator1_subroutine_location,glw::GLuint vec4_operator2_subroutine_location)9748 void 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  **/
NegativeTest1(deqp::Context & context)9845 NegativeTest1::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  **/
deinit()9867 void 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.  */
initTest()9894 void 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  */
iterate()10019 tcu::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  **/
NegativeTest2(deqp::Context & context)10311 NegativeTest2::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 */
deinit()10326 void NegativeTest2::deinit()
10327 {
10328 	deinitGLObjects();
10329 }
10330 
10331 /** Deinitializes all GL objects that may have been created during test execution */
deinitGLObjects()10332 void 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  **/
executeTestCase(const Utils::_shader_stage & referencing_stage)10389 void 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  **/
getFragmentShaderBody(const Utils::_shader_stage & referencing_stage) const10429 std::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  **/
getGeometryShaderBody(const Utils::_shader_stage & referencing_stage) const10469 std::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  **/
getSubroutineUniformName(const Utils::_shader_stage & stage) const10512 std::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  **/
getTessellationControlShaderBody(const Utils::_shader_stage & referencing_stage) const10569 std::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  **/
getTessellationEvaluationShaderBody(const Utils::_shader_stage & referencing_stage) const10608 std::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  **/
getVertexShaderBody(const Utils::_shader_stage & referencing_stage) const10647 std::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  */
iterate()10681 tcu::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  **/
NegativeTest3(deqp::Context & context)10714 NegativeTest3::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 */
deinit()10724 void 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  **/
executeTest(const Utils::_shader_stage & shader_stage)10740 void 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  **/
getFragmentShaderBody() const10809 std::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  **/
getGeometryShaderBody() const10839 std::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  **/
getTessellationControlShaderBody() const10872 std::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  **/
getTessellationEvaluationShaderBody() const10903 std::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  **/
getVertexShaderBody() const10934 std::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  */
iterate()10959 tcu::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  **/
NegativeTest4(deqp::Context & context)10992 NegativeTest4::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  **/
deinit()11006 void 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  **/
getShaderBody(const Utils::_shader_stage & shader_stage,const unsigned int & n_subroutine_types,const _test_case & test_case) const11032 std::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  */
iterate()11189 tcu::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  **/
NegativeTest5(deqp::Context & context)11276 NegativeTest5::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 */
deinit()11293 void NegativeTest5::deinit()
11294 {
11295 	deinitIteration();
11296 }
11297 
11298 /** Deinitializes all GL objects that may have been created during a single test
11299  *  iteration.
11300  ***/
deinitIteration()11301 void 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  **/
executeIteration(const Utils::_shader_stage & shader_stage)11355 void 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  **/
getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const11404 std::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  **/
getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const11448 std::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  **/
getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const11494 std::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  **/
getTessellationEvaluationShaderBody(bool include_invalid_subroutine_uniform_declaration) const11538 std::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  **/
getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const11583 std::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  */
iterate()11621 tcu::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  **/
NegativeTest6(deqp::Context & context)11658 NegativeTest6::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 */
deinit()11675 void NegativeTest6::deinit()
11676 {
11677 	deinitIteration();
11678 }
11679 
11680 /** Deinitializes all GL objects that may have been created during a single test
11681  *  iteration.
11682  ***/
deinitIteration()11683 void 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  **/
executeIteration(const Utils::_shader_stage & shader_stage)11738 void 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  **/
getFragmentShaderBody(bool include_invalid_declaration) const11786 std::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  **/
getGeometryShaderBody(bool include_invalid_declaration) const11839 std::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  **/
getTessellationControlShaderBody(bool include_invalid_declaration) const11894 std::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  **/
getTessellationEvaluationShaderBody(bool include_invalid_declaration) const11947 std::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  **/
getVertexShaderBody(bool include_invalid_declaration) const12000 std::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  */
iterate()12048 tcu::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  **/
NegativeTest7(deqp::Context & context)12085 NegativeTest7::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  **/
deinit()12096 void 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  **/
iterate()12119 tcu::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  **/
test(const GLchar * vertex_shader_code,const GLchar * name_of_recursive_routine)12280 bool 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  **/
NegativeTest8(deqp::Context & context)12335 NegativeTest8::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 */
deinit()12350 void NegativeTest8::deinit()
12351 {
12352 	deinitIteration();
12353 }
12354 
12355 /** Deinitializes all GL objects that may have been created during a single test
12356  *  iteration.
12357  ***/
deinitIteration()12358 void 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  **/
executeIteration(const Utils::_shader_stage & shader_stage)12413 void 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  **/
getFragmentShaderBody(bool include_invalid_declaration) const12459 std::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  **/
getGeometryShaderBody(bool include_invalid_declaration) const12504 std::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  **/
getTessellationControlShaderBody(bool include_invalid_declaration) const12551 std::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  **/
getTessellationEvaluationShaderBody(bool include_invalid_declaration) const12596 std::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  **/
getVertexShaderBody(bool include_invalid_declaration) const12641 std::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  */
iterate()12681 tcu::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  **/
NegativeTest9(deqp::Context & context)12717 NegativeTest9::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  **/
deinit()12731 void 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  **/
getTestCaseString(const _test_case & test_case)12756 std::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  **/
getVertexShader(const _test_case & test_case)12784 std::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  */
iterate()12862 tcu::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  **/
NegativeTest10(deqp::Context & context)12919 NegativeTest10::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  **/
deinit()12939 void 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  **/
getFragmentShader(bool include_duplicate_function)12994 std::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  **/
getGeometryShader(bool include_duplicate_function)13038 std::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  **/
getTessellationControlShader(bool include_duplicate_function)13086 std::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  **/
getTessellationEvaluationShader(bool include_duplicate_function)13141 std::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  **/
getVertexShader(bool include_duplicate_function)13190 std::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 */
initTestCases()13226 void 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  */
iterate()13257 tcu::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  **/
NegativeTest11(deqp::Context & context)13313 NegativeTest11::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  **/
deinit()13328 void 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  **/
getTestCaseString(const _test_case & test_case)13353 std::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  **/
getVertexShader(const _test_case & test_case)13381 std::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  */
iterate()13453 tcu::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  **/
NegativeTest12(deqp::Context & context)13519 NegativeTest12::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  **/
deinit()13533 void 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  **/
getTestCaseString(const _test_case & test_case)13558 std::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  **/
getVertexShader(const _test_case & test_case)13592 std::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  */
iterate()13700 tcu::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  **/
ShaderSubroutineTests(deqp::Context & context)13759 ShaderSubroutineTests::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  **/
init(void)13768 void 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