• 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 		break;
1323 	};
1324 
1325 	return string;
1326 }
1327 
1328 /** Returns string that represents pname's name
1329  *
1330  * @param pname pname
1331  *
1332  * @return String representation of known pnames
1333  **/
pnameToStr(glw::GLenum pname)1334 const GLchar* Utils::pnameToStr(glw::GLenum pname)
1335 {
1336 	const GLchar* string = "Unknown pname";
1337 
1338 	switch (pname)
1339 	{
1340 	case GL_ACTIVE_SUBROUTINE_UNIFORMS:
1341 		string = "GL_ACTIVE_SUBROUTINE_UNIFORMS";
1342 		break;
1343 	case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS:
1344 		string = "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS";
1345 		break;
1346 	case GL_ACTIVE_SUBROUTINES:
1347 		string = "GL_ACTIVE_SUBROUTINES";
1348 		break;
1349 	case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH:
1350 		string = "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH";
1351 		break;
1352 	case GL_ACTIVE_SUBROUTINE_MAX_LENGTH:
1353 		string = "GL_ACTIVE_SUBROUTINE_MAX_LENGTH";
1354 		break;
1355 	case GL_NUM_COMPATIBLE_SUBROUTINES:
1356 		string = "GL_NUM_COMPATIBLE_SUBROUTINES";
1357 		break;
1358 	case GL_UNIFORM_SIZE:
1359 		string = "GL_UNIFORM_SIZE";
1360 		break;
1361 	case GL_COMPATIBLE_SUBROUTINES:
1362 		string = "GL_COMPATIBLE_SUBROUTINES";
1363 		break;
1364 	case GL_UNIFORM_NAME_LENGTH:
1365 		string = "GL_UNIFORM_NAME_LENGTH";
1366 		break;
1367 	case GL_ACTIVE_RESOURCES:
1368 		string = "GL_ACTIVE_RESOURCES";
1369 		break;
1370 	case GL_MAX_NAME_LENGTH:
1371 		string = "GL_MAX_NAME_LENGTH";
1372 		break;
1373 	case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
1374 		string = "GL_MAX_NUM_COMPATIBLE_SUBROUTINES";
1375 		break;
1376 	case GL_NAME_LENGTH:
1377 		string = "GL_NAME_LENGTH";
1378 		break;
1379 	case GL_ARRAY_SIZE:
1380 		string = "GL_ARRAY_SIZE";
1381 		break;
1382 	case GL_LOCATION:
1383 		string = "GL_LOCATION";
1384 		break;
1385 	default:
1386 		TCU_FAIL("Not implemented");
1387 		break;
1388 	};
1389 
1390 	return string;
1391 }
1392 
compare(const glw::GLfloat & left,const glw::GLfloat & right)1393 bool Utils::compare(const glw::GLfloat& left, const glw::GLfloat& right)
1394 {
1395 	static const glw::GLfloat m_epsilon = 0.00001f;
1396 
1397 	if (m_epsilon < std::abs(right - left))
1398 	{
1399 		return false;
1400 	}
1401 	else
1402 	{
1403 		return true;
1404 	}
1405 }
1406 
1407 /** Returns a variable type enum corresponding to user-specified base variable type
1408  *  and the number of components it should support.
1409  *
1410  *  @param base_variable_type Base variable type to use for the query.
1411  *  @param n_components       Number of components to consider for the query.
1412  *
1413  *  @return As per description.
1414  **/
getVariableTypeFromProperties(const _variable_type & base_variable_type,const unsigned int & n_components)1415 Utils::_variable_type Utils::getVariableTypeFromProperties(const _variable_type& base_variable_type,
1416 														   const unsigned int&   n_components)
1417 {
1418 	_variable_type result = VARIABLE_TYPE_UNKNOWN;
1419 
1420 	switch (base_variable_type)
1421 	{
1422 	case VARIABLE_TYPE_BOOL:
1423 	{
1424 		switch (n_components)
1425 		{
1426 		case 1:
1427 			result = VARIABLE_TYPE_BOOL;
1428 			break;
1429 		case 2:
1430 			result = VARIABLE_TYPE_BVEC2;
1431 			break;
1432 		case 3:
1433 			result = VARIABLE_TYPE_BVEC3;
1434 			break;
1435 		case 4:
1436 			result = VARIABLE_TYPE_BVEC4;
1437 			break;
1438 
1439 		default:
1440 		{
1441 			TCU_FAIL("Unsupported number of components requested");
1442 		}
1443 		} /* switch (n_components) */
1444 
1445 		break;
1446 	}
1447 
1448 	case VARIABLE_TYPE_DOUBLE:
1449 	{
1450 		switch (n_components)
1451 		{
1452 		case 1:
1453 			result = VARIABLE_TYPE_DOUBLE;
1454 			break;
1455 		case 2:
1456 			result = VARIABLE_TYPE_DVEC2;
1457 			break;
1458 		case 3:
1459 			result = VARIABLE_TYPE_DVEC3;
1460 			break;
1461 		case 4:
1462 			result = VARIABLE_TYPE_DVEC4;
1463 			break;
1464 
1465 		default:
1466 		{
1467 			TCU_FAIL("Unsupported number of components requested");
1468 		}
1469 		} /* switch (n_components) */
1470 
1471 		break;
1472 	}
1473 
1474 	case VARIABLE_TYPE_FLOAT:
1475 	{
1476 		switch (n_components)
1477 		{
1478 		case 1:
1479 			result = VARIABLE_TYPE_FLOAT;
1480 			break;
1481 		case 2:
1482 			result = VARIABLE_TYPE_VEC2;
1483 			break;
1484 		case 3:
1485 			result = VARIABLE_TYPE_VEC3;
1486 			break;
1487 		case 4:
1488 			result = VARIABLE_TYPE_VEC4;
1489 			break;
1490 
1491 		default:
1492 		{
1493 			TCU_FAIL("Unsupported number of components requested");
1494 		}
1495 		} /* switch (n_components) */
1496 
1497 		break;
1498 	}
1499 
1500 	case VARIABLE_TYPE_INT:
1501 	{
1502 		switch (n_components)
1503 		{
1504 		case 1:
1505 			result = VARIABLE_TYPE_INT;
1506 			break;
1507 		case 2:
1508 			result = VARIABLE_TYPE_IVEC2;
1509 			break;
1510 		case 3:
1511 			result = VARIABLE_TYPE_IVEC3;
1512 			break;
1513 		case 4:
1514 			result = VARIABLE_TYPE_IVEC4;
1515 			break;
1516 
1517 		default:
1518 		{
1519 			TCU_FAIL("Unsupported number of components requested");
1520 		}
1521 		} /* switch (n_components) */
1522 
1523 		break;
1524 	}
1525 
1526 	case VARIABLE_TYPE_UINT:
1527 	{
1528 		switch (n_components)
1529 		{
1530 		case 1:
1531 			result = VARIABLE_TYPE_UINT;
1532 			break;
1533 		case 2:
1534 			result = VARIABLE_TYPE_UVEC2;
1535 			break;
1536 		case 3:
1537 			result = VARIABLE_TYPE_UVEC3;
1538 			break;
1539 		case 4:
1540 			result = VARIABLE_TYPE_UVEC4;
1541 			break;
1542 
1543 		default:
1544 		{
1545 			TCU_FAIL("Unsupported number of components requested");
1546 		}
1547 		} /* switch (n_components) */
1548 
1549 		break;
1550 	}
1551 
1552 	default:
1553 	{
1554 		TCU_FAIL("Unrecognized base variable type");
1555 	}
1556 	} /* switch (base_variable_type) */
1557 
1558 	return result;
1559 }
1560 
1561 /** Returns a GLSL literal corresponding to user-specified variable type.
1562  *
1563  *  @param variable_type Variable type to use for the query.
1564  *
1565  *  @return As per description or [?] if @param variable_type was not
1566  *          recognized.
1567  **/
getVariableTypeGLSLString(const _variable_type & variable_type)1568 std::string Utils::getVariableTypeGLSLString(const _variable_type& variable_type)
1569 {
1570 	std::string result = "[?]";
1571 
1572 	switch (variable_type)
1573 	{
1574 	case VARIABLE_TYPE_BOOL:
1575 		result = "bool";
1576 		break;
1577 	case VARIABLE_TYPE_BVEC2:
1578 		result = "bvec2";
1579 		break;
1580 	case VARIABLE_TYPE_BVEC3:
1581 		result = "bvec3";
1582 		break;
1583 	case VARIABLE_TYPE_BVEC4:
1584 		result = "bvec4";
1585 		break;
1586 	case VARIABLE_TYPE_DOUBLE:
1587 		result = "double";
1588 		break;
1589 	case VARIABLE_TYPE_DVEC2:
1590 		result = "dvec2";
1591 		break;
1592 	case VARIABLE_TYPE_DVEC3:
1593 		result = "dvec3";
1594 		break;
1595 	case VARIABLE_TYPE_DVEC4:
1596 		result = "dvec4";
1597 		break;
1598 	case VARIABLE_TYPE_FLOAT:
1599 		result = "float";
1600 		break;
1601 	case VARIABLE_TYPE_INT:
1602 		result = "int";
1603 		break;
1604 	case VARIABLE_TYPE_IVEC2:
1605 		result = "ivec2";
1606 		break;
1607 	case VARIABLE_TYPE_IVEC3:
1608 		result = "ivec3";
1609 		break;
1610 	case VARIABLE_TYPE_IVEC4:
1611 		result = "ivec4";
1612 		break;
1613 	case VARIABLE_TYPE_MAT2:
1614 		result = "mat2";
1615 		break;
1616 	case VARIABLE_TYPE_MAT2X3:
1617 		result = "mat2x3";
1618 		break;
1619 	case VARIABLE_TYPE_MAT2X4:
1620 		result = "mat2x4";
1621 		break;
1622 	case VARIABLE_TYPE_MAT3:
1623 		result = "mat3";
1624 		break;
1625 	case VARIABLE_TYPE_MAT3X2:
1626 		result = "mat3x2";
1627 		break;
1628 	case VARIABLE_TYPE_MAT3X4:
1629 		result = "mat3x4";
1630 		break;
1631 	case VARIABLE_TYPE_MAT4:
1632 		result = "mat4";
1633 		break;
1634 	case VARIABLE_TYPE_MAT4X2:
1635 		result = "mat4x2";
1636 		break;
1637 	case VARIABLE_TYPE_MAT4X3:
1638 		result = "mat4x3";
1639 		break;
1640 	case VARIABLE_TYPE_UINT:
1641 		result = "uint";
1642 		break;
1643 	case VARIABLE_TYPE_UVEC2:
1644 		result = "uvec2";
1645 		break;
1646 	case VARIABLE_TYPE_UVEC3:
1647 		result = "uvec3";
1648 		break;
1649 	case VARIABLE_TYPE_UVEC4:
1650 		result = "uvec4";
1651 		break;
1652 	case VARIABLE_TYPE_VEC2:
1653 		result = "vec2";
1654 		break;
1655 	case VARIABLE_TYPE_VEC3:
1656 		result = "vec3";
1657 		break;
1658 	case VARIABLE_TYPE_VEC4:
1659 		result = "vec4";
1660 		break;
1661 
1662 	default:
1663 	{
1664 		TCU_FAIL("Unrecognized variable type");
1665 	}
1666 	} /* switch (variable_type) */
1667 
1668 	return result;
1669 }
1670 
1671 /** Constructor.
1672  *
1673  *  @param context Rendering context.
1674  *
1675  **/
APITest1(deqp::Context & context)1676 APITest1::APITest1(deqp::Context& context)
1677 	: TestCase(context, "min_maxes", "Verifies the implementation returns valid GL_MAX_SUBROUTINE* pnames "
1678 									 "which meet the minimum maximum requirements enforced by the spec.")
1679 	, m_has_test_passed(true)
1680 {
1681 	/* Left blank intentionally */
1682 }
1683 
1684 /** Executes test iteration.
1685  *
1686  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1687  */
iterate()1688 tcu::TestNode::IterateResult APITest1::iterate()
1689 {
1690 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1691 
1692 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
1693 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
1694 	{
1695 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
1696 	}
1697 
1698 	/* Iterate over all pnames */
1699 	const struct
1700 	{
1701 		glw::GLenum pname;
1702 		const char* pname_string;
1703 		glw::GLint  min_value;
1704 	} pnames[] = { { GL_MAX_SUBROUTINES, "GL_MAX_SUBROUTINES", 256 },
1705 				   { GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS", 1024 } };
1706 	const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
1707 
1708 	for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
1709 	{
1710 		glw::GLboolean	 bool_value   = GL_FALSE;
1711 		glw::GLdouble	  double_value = 0.0;
1712 		glw::GLfloat	   float_value  = 0.0f;
1713 		glw::GLint		   int_value	= 0;
1714 		glw::GLint64	   int64_value  = 0;
1715 		const glw::GLint   min_value	= pnames[n_pname].min_value;
1716 		const glw::GLenum& pname		= pnames[n_pname].pname;
1717 		const char*		   pname_string = pnames[n_pname].pname_string;
1718 
1719 		/* Retrieve the pname values */
1720 		gl.getBooleanv(pname, &bool_value);
1721 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() call failed.");
1722 
1723 		gl.getDoublev(pname, &double_value);
1724 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetDoublev() call failed.");
1725 
1726 		gl.getFloatv(pname, &float_value);
1727 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed.");
1728 
1729 		gl.getIntegerv(pname, &int_value);
1730 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
1731 
1732 		gl.getInteger64v(pname, &int64_value);
1733 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v() call failed.");
1734 
1735 		/* Make sure the value reported meets the min max requirement */
1736 		if (int_value < min_value)
1737 		{
1738 			m_testCtx.getLog() << tcu::TestLog::Message << "GL implementation reports a value of [" << int_value
1739 							   << "]"
1740 								  " for property ["
1741 							   << pname_string << "]"
1742 												  ", whereas the min max for the property is ["
1743 							   << min_value << "]." << tcu::TestLog::EndMessage;
1744 
1745 			m_has_test_passed = false;
1746 		}
1747 
1748 		/* Verify the other getters reported valid values */
1749 		const float epsilon = 1e-5f;
1750 
1751 		if (((int_value == 0) && (bool_value == GL_TRUE)) || ((int_value != 0) && (bool_value != GL_TRUE)))
1752 		{
1753 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid boolean value [" << bool_value
1754 							   << "]"
1755 								  " reported for property ["
1756 							   << pname_string << "]"
1757 												  " (int value:["
1758 							   << int_value << "])" << tcu::TestLog::EndMessage;
1759 
1760 			m_has_test_passed = false;
1761 		}
1762 
1763 		if (de::abs(double_value - (double)int_value) > epsilon)
1764 		{
1765 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid double value [" << double_value
1766 							   << "]"
1767 								  " reported for property ["
1768 							   << pname_string << "]"
1769 												  " (int value:["
1770 							   << int_value << "])" << tcu::TestLog::EndMessage;
1771 
1772 			m_has_test_passed = false;
1773 		}
1774 
1775 		if (de::abs(float_value - (float)int_value) > epsilon)
1776 		{
1777 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid float value [" << float_value
1778 							   << "]"
1779 								  " reported for property ["
1780 							   << pname_string << "]"
1781 												  " (int value:["
1782 							   << int_value << "])" << tcu::TestLog::EndMessage;
1783 
1784 			m_has_test_passed = false;
1785 		}
1786 
1787 		if (int64_value != int_value)
1788 		{
1789 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid 64-bit integer value [" << float_value
1790 							   << "]"
1791 								  " reported for property ["
1792 							   << pname_string << "]"
1793 												  " (int value:["
1794 							   << int_value << "])" << tcu::TestLog::EndMessage;
1795 
1796 			m_has_test_passed = false;
1797 		}
1798 	} /* for (all pnames) */
1799 
1800 	if (m_has_test_passed)
1801 	{
1802 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1803 	}
1804 	else
1805 	{
1806 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1807 	}
1808 
1809 	return STOP;
1810 }
1811 
1812 /** Constructor.
1813  *
1814  *  @param context Rendering context.
1815  *
1816  **/
APITest2(deqp::Context & context)1817 APITest2::APITest2(deqp::Context& context)
1818 	: TestCase(context, "name_getters", "Verifies glGetActiveSubroutineName() and glGetActiveSubroutineUniformName() "
1819 										"functions work correctly.")
1820 	, m_buffer(DE_NULL)
1821 	, m_has_test_passed(true)
1822 	, m_po_id(0)
1823 	, m_subroutine_name1("subroutine1")
1824 	, m_subroutine_name2("subroutine2")
1825 	, m_subroutine_uniform_name("data_provider")
1826 	, m_vs_id(0)
1827 {
1828 	/* Left blank intentionally */
1829 }
1830 
1831 /** Destroys all ES objects that may have been created during test initialization,
1832  *  as well as releases any buffers that may have been allocated during the process.
1833  */
deinit()1834 void APITest2::deinit()
1835 {
1836 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1837 
1838 	if (m_buffer != DE_NULL)
1839 	{
1840 		delete[] m_buffer;
1841 
1842 		m_buffer = DE_NULL;
1843 	}
1844 
1845 	if (m_po_id != 0)
1846 	{
1847 		gl.deleteProgram(m_po_id);
1848 
1849 		m_po_id = 0;
1850 	}
1851 
1852 	if (m_vs_id != 0)
1853 	{
1854 		gl.deleteShader(m_vs_id);
1855 
1856 		m_vs_id = 0;
1857 	}
1858 }
1859 
1860 /** Returns body of a vertex shader that should be used for the test.
1861  *
1862  *  @return As per description.
1863  **/
getVertexShaderBody()1864 std::string APITest2::getVertexShaderBody()
1865 {
1866 	return "#version 400\n"
1867 		   "\n"
1868 		   "#extension GL_ARB_shader_subroutine : require\n"
1869 		   "\n"
1870 		   "subroutine int ExampleSubroutineType(int example_argument);\n"
1871 		   "\n"
1872 		   "subroutine(ExampleSubroutineType) int subroutine1(int example_argument)\n"
1873 		   "{\n"
1874 		   "    return 1;\n"
1875 		   "}\n"
1876 		   "\n"
1877 		   "subroutine(ExampleSubroutineType) int subroutine2(int example_argument)\n"
1878 		   "{\n"
1879 		   "    return 2;\n"
1880 		   "}\n"
1881 		   "\n"
1882 		   "subroutine uniform ExampleSubroutineType data_provider;\n"
1883 		   "\n"
1884 		   "void main()\n"
1885 		   "{\n"
1886 		   "    gl_Position = vec4(float(data_provider(0)), vec3(1) );\n"
1887 		   "}\n";
1888 }
1889 
1890 /** Initializes all ES objects required to run the test. */
initTest()1891 void APITest2::initTest()
1892 {
1893 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1894 
1895 	/* Generate program & shader objects */
1896 	m_po_id = gl.createProgram();
1897 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1898 
1899 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call(s) failed.");
1900 
1901 	/* Attach the shader to the program object */
1902 	gl.attachShader(m_po_id, m_vs_id);
1903 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
1904 
1905 	/* Compile the shader */
1906 	glw::GLint  compile_status  = GL_FALSE;
1907 	std::string vs_body			= getVertexShaderBody();
1908 	const char* vs_body_raw_ptr = vs_body.c_str();
1909 
1910 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
1911 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1912 
1913 	gl.compileShader(m_vs_id);
1914 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1915 
1916 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1917 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1918 
1919 	if (compile_status != GL_TRUE)
1920 	{
1921 		TCU_FAIL("Shader compilation failed.");
1922 	}
1923 
1924 	/* Try to link the program object */
1925 	glw::GLint link_status = GL_FALSE;
1926 
1927 	gl.linkProgram(m_po_id);
1928 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1929 
1930 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1931 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
1932 
1933 	if (link_status != GL_TRUE)
1934 	{
1935 		TCU_FAIL("Program linking failed.");
1936 	}
1937 
1938 	/* Perform a few sanity checks */
1939 	glw::GLint n_active_subroutines			= 0;
1940 	glw::GLint n_active_subroutine_uniforms = 0;
1941 
1942 	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
1943 	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
1944 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call failed.");
1945 
1946 	if (n_active_subroutines != 2 /* subroutines declared in vertex shader */)
1947 	{
1948 		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid amount of active subroutines reported; expected: 2,"
1949 													   " reported:"
1950 						   << n_active_subroutines << tcu::TestLog::EndMessage;
1951 
1952 		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINES property value.");
1953 	}
1954 
1955 	if (n_active_subroutine_uniforms != 1)
1956 	{
1957 		m_testCtx.getLog() << tcu::TestLog::Message
1958 						   << "Invalid amount of active subroutine uniforms reported: expected: 1,"
1959 							  " reported: "
1960 						   << n_active_subroutine_uniforms << tcu::TestLog::EndMessage;
1961 
1962 		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORMS property value.");
1963 	}
1964 }
1965 
1966 /** Executes test iteration.
1967  *
1968  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1969  */
iterate()1970 tcu::TestNode::IterateResult APITest2::iterate()
1971 {
1972 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
1973 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
1974 	{
1975 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
1976 	}
1977 
1978 	/* Initialize a test program object */
1979 	initTest();
1980 
1981 	/* Verify glGetActiveSubroutineName() works correctly */
1982 	verifyGLGetActiveSubroutineNameFunctionality();
1983 
1984 	/* Verify glGetActiveSubroutineUniformName() works correctly */
1985 	verifyGLGetActiveSubroutineUniformNameFunctionality();
1986 
1987 	/* Done */
1988 	if (m_has_test_passed)
1989 	{
1990 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1991 	}
1992 	else
1993 	{
1994 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1995 	}
1996 
1997 	return STOP;
1998 }
1999 
2000 /** Verifies glGetActiveSubroutineName() behaves as per GL_ARB_shader_subroutine
2001  *  specification.
2002  **/
verifyGLGetActiveSubroutineNameFunctionality()2003 void APITest2::verifyGLGetActiveSubroutineNameFunctionality()
2004 {
2005 	GLsizei				  expected_length1 = (GLsizei)strlen(m_subroutine_name1) + 1;
2006 	GLsizei				  expected_length2 = (GLsizei)strlen(m_subroutine_name1) + 1;
2007 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
2008 	GLsizei				  reported_length  = 0;
2009 
2010 	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2011 							   0,							 /* bufsize */
2012 							   DE_NULL,						 /* length */
2013 							   DE_NULL);					 /* name */
2014 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2015 
2016 	gl.getProgramInterfaceiv(m_po_id, GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, &reported_length);
2017 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2018 
2019 	if ((reported_length != expected_length1) && (reported_length != expected_length2))
2020 	{
2021 		m_testCtx.getLog() << tcu::TestLog::Message
2022 						   << "Invalid active subroutine name length reported:" << reported_length
2023 						   << ", instead of: " << expected_length1 << " or " << expected_length2
2024 						   << tcu::TestLog::EndMessage;
2025 
2026 		TCU_FAIL("Incorrect length of active subroutine name");
2027 	}
2028 
2029 	m_buffer = new glw::GLchar[reported_length];
2030 
2031 	memset(m_buffer, 0, reported_length);
2032 
2033 	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, reported_length, DE_NULL, /* length */
2034 							   m_buffer);
2035 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2036 
2037 	if (strcmp(m_buffer, m_subroutine_name1) != 0 && strcmp(m_buffer, m_subroutine_name2) != 0)
2038 	{
2039 		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine name reported:[" << m_buffer
2040 						   << "]"
2041 							  " instead of:["
2042 						   << m_subroutine_name1 << "]"
2043 													" or:["
2044 						   << m_subroutine_name2 << "]." << tcu::TestLog::EndMessage;
2045 
2046 		TCU_FAIL("Invalid active subroutine name reported.");
2047 	}
2048 
2049 	delete[] m_buffer;
2050 	m_buffer = DE_NULL;
2051 }
2052 
2053 /** Verifies glGetActiveSubroutineUniformName() behaves as per GL_ARB_shader_subroutine
2054  *  specification.
2055  **/
verifyGLGetActiveSubroutineUniformNameFunctionality()2056 void APITest2::verifyGLGetActiveSubroutineUniformNameFunctionality()
2057 {
2058 	GLsizei				  expected_length = (GLsizei)strlen(m_subroutine_uniform_name);
2059 	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
2060 	GLsizei				  reported_length = 0;
2061 
2062 	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2063 									  0,							/* bufsize */
2064 									  DE_NULL,						/* length */
2065 									  DE_NULL);						/* name */
2066 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed.");
2067 
2068 	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2069 									  0,							/* bufsize */
2070 									  &reported_length, DE_NULL);   /* name */
2071 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed.");
2072 
2073 	// reported_length is the actual number of characters written into <name>
2074 	// If <bufSize> is 0, reported_length should be 0
2075 	if (reported_length != 0)
2076 	{
2077 		m_testCtx.getLog() << tcu::TestLog::Message
2078 						   << "Invalid active subroutine uniform name length reported:" << reported_length
2079 						   << ", instead of: " << 0 << tcu::TestLog::EndMessage;
2080 
2081 		TCU_FAIL("Incorrect length of active subroutine uniform name");
2082 	}
2083 
2084 	m_buffer = new glw::GLchar[expected_length + 1];
2085 
2086 	memset(m_buffer, 0, expected_length + 1);
2087 
2088 	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, expected_length + 1, &reported_length, m_buffer);
2089 	GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformName() call failed.");
2090 
2091 	if (reported_length != expected_length)
2092 	{
2093 		m_testCtx.getLog() << tcu::TestLog::Message
2094 						   << "Invalid active subroutine uniform name length reported:" << reported_length
2095 						   << ", instead of: " << expected_length << tcu::TestLog::EndMessage;
2096 
2097 		TCU_FAIL("Incorrect length of active subroutine uniform name");
2098 	}
2099 
2100 	if (strcmp(m_buffer, m_subroutine_uniform_name) != 0)
2101 	{
2102 		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine uniform name reported:[" << m_buffer
2103 						   << "]"
2104 							  " instead of:["
2105 						   << m_subroutine_uniform_name << "]" << tcu::TestLog::EndMessage;
2106 
2107 		TCU_FAIL("Invalid active subroutine uniform name reported.");
2108 	}
2109 
2110 	delete[] m_buffer;
2111 	m_buffer = DE_NULL;
2112 }
2113 
2114 /** Constructor.
2115  *
2116  *  @param context Rendering context.
2117  *
2118  **/
FunctionalTest1_2(deqp::Context & context)2119 FunctionalTest1_2::FunctionalTest1_2(deqp::Context& context)
2120 	: TestCase(context, "two_subroutines_single_subroutine_uniform",
2121 			   "Verifies the subroutines work correctly in a vertex shader for"
2122 			   " bool/float/int/uint/double/*vec*/*mat* argument and return types")
2123 	, m_has_test_passed(true)
2124 	, m_po_id(0)
2125 	, m_po_getter0_subroutine_index(GL_INVALID_INDEX)
2126 	, m_po_getter1_subroutine_index(GL_INVALID_INDEX)
2127 	, m_po_subroutine_uniform_index(-1)
2128 	, m_xfb_bo_id(0)
2129 	, m_vao_id(0)
2130 	, m_vs_id(0)
2131 {
2132 	/* Left blank intentionally */
2133 }
2134 
2135 /** Destroys all ES objects that may have been created during test initialization,
2136  *  as well as releases any buffers that may have been allocated during the process.
2137  */
deinit()2138 void FunctionalTest1_2::deinit()
2139 {
2140 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2141 
2142 	deinitTestIteration();
2143 
2144 	if (m_xfb_bo_id != 0)
2145 	{
2146 		gl.deleteBuffers(1, &m_xfb_bo_id);
2147 
2148 		m_xfb_bo_id = 0;
2149 	}
2150 
2151 	if (m_vao_id != 0)
2152 	{
2153 		gl.deleteVertexArrays(1, &m_vao_id);
2154 
2155 		m_vao_id = 0;
2156 	}
2157 }
2158 
2159 /** Deinitializes GL objects that are iteration-specific */
deinitTestIteration()2160 void FunctionalTest1_2::deinitTestIteration()
2161 {
2162 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2163 
2164 	if (m_po_id != 0)
2165 	{
2166 		gl.deleteProgram(m_po_id);
2167 
2168 		m_po_id = 0;
2169 	}
2170 
2171 	if (m_vs_id != 0)
2172 	{
2173 		gl.deleteShader(m_vs_id);
2174 
2175 		m_vs_id = 0;
2176 	}
2177 }
2178 
2179 /** Executes a single test iteration using user-specified test case propertiesz.
2180  *
2181  *  @param test-case Test case descriptor.
2182  *
2183  *  @return true if the test iteration passed, false otherwise.
2184  **/
executeTestIteration(const _test_case & test_case)2185 bool FunctionalTest1_2::executeTestIteration(const _test_case& test_case)
2186 {
2187 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2188 	bool				  result = true;
2189 
2190 	/* Build the test program */
2191 	std::string		   empty_body;
2192 	std::string		   vs_body		  = getVertexShaderBody(test_case.variable_type, test_case.array_size);
2193 	const glw::GLchar* xfb_varyings[] = { "result" };
2194 	const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
2195 
2196 	if (!Utils::buildProgram(gl, vs_body, empty_body, empty_body, empty_body, empty_body, xfb_varyings, n_xfb_varyings,
2197 							 &m_vs_id, NULL, /* out_tc_id */
2198 							 NULL,			 /* out_te_id */
2199 							 NULL,			 /* out_gs_id */
2200 							 NULL, &m_po_id))
2201 	{
2202 		TCU_FAIL("Test program failed to build.");
2203 	}
2204 
2205 	/* Retrieve subroutine locations */
2206 	m_po_getter0_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter0");
2207 	m_po_getter1_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter1");
2208 
2209 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
2210 
2211 	if (m_po_getter0_subroutine_index == GL_INVALID_INDEX || m_po_getter1_subroutine_index == GL_INVALID_INDEX)
2212 	{
2213 		TCU_FAIL("At least one subroutine is considered inactive which is invalid.");
2214 	}
2215 
2216 	/* Retrieve subroutine uniform location */
2217 	m_po_subroutine_uniform_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "colorGetterUniform");
2218 
2219 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call failed.");
2220 
2221 	if (m_po_subroutine_uniform_index == -1)
2222 	{
2223 		TCU_FAIL("Subroutine uniform is considered inactive which is invalid.");
2224 	}
2225 
2226 	/* Set up XFB BO storage */
2227 	const Utils::_variable_type base_variable_type	= Utils::getBaseVariableType(test_case.variable_type);
2228 	unsigned int				iteration_xfb_bo_size = Utils::getComponentSizeForVariableType(base_variable_type) *
2229 										 Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
2230 	unsigned int total_xfb_bo_size = 0;
2231 
2232 	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2233 	{
2234 		/* Boolean varyings are not supported by OpenGL. Instead, we use ints to output
2235 		 * boolean values. */
2236 		iteration_xfb_bo_size = static_cast<unsigned int>(iteration_xfb_bo_size * sizeof(int));
2237 	}
2238 
2239 	total_xfb_bo_size = iteration_xfb_bo_size * 2 /* subroutines we will be testing */;
2240 
2241 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, total_xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
2242 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2243 
2244 	/* Activate test program object */
2245 	gl.useProgram(m_po_id);
2246 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2247 
2248 	/* Run two iterations. Each iteration should invoke different subroutine. */
2249 	const glw::GLuint  subroutine_indices[] = { m_po_getter0_subroutine_index, m_po_getter1_subroutine_index };
2250 	const unsigned int n_subroutine_indices = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
2251 
2252 	for (unsigned int n_subroutine_index = 0; n_subroutine_index < n_subroutine_indices; ++n_subroutine_index)
2253 	{
2254 		/* Configure which subroutine should be used for the draw call */
2255 		glw::GLuint current_subroutine_index = subroutine_indices[n_subroutine_index];
2256 
2257 		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &current_subroutine_index);
2258 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
2259 
2260 		/* Update XFB binding so that we do not overwrite data XFBed in previous iterations */
2261 		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2262 						   m_xfb_bo_id, iteration_xfb_bo_size * n_subroutine_index, iteration_xfb_bo_size);
2263 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() call failed.");
2264 
2265 		/* Draw a single point */
2266 		gl.beginTransformFeedback(GL_POINTS);
2267 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2268 		{
2269 			gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2270 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
2271 		}
2272 		gl.endTransformFeedback();
2273 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
2274 	} /* for (all subroutine indices) */
2275 
2276 	/* Map the BO storage into process space */
2277 	const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2278 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
2279 
2280 	result &= verifyXFBData(xfb_data_ptr, test_case.variable_type);
2281 
2282 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2283 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffeR() call failed.");
2284 
2285 	return result;
2286 }
2287 
2288 /** Retrieves body of a vertex shader that should be used to verify
2289  *  subroutine support, given user-specified test iteration properties.
2290  *
2291  *  @param variable_type GLSL type that should be used for argument and
2292  *                       return type definition in a subroutine. This setting
2293  *                       also affects type of the only output variable in the shader.
2294  *  @param array_size    1 if non-arrayed arguments/return types should be tested;
2295  *                       2 if arrayed arguments/return types should be tested.
2296  *
2297  *  @return Requested string.
2298  **/
getVertexShaderBody(const Utils::_variable_type & variable_type,unsigned int array_size)2299 std::string FunctionalTest1_2::getVertexShaderBody(const Utils::_variable_type& variable_type, unsigned int array_size)
2300 {
2301 	Utils::_variable_type base_variable_type		 = Utils::getBaseVariableType(variable_type);
2302 	unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
2303 	std::stringstream	 result_sstream;
2304 	std::string			  variable_type_glsl = Utils::getVariableTypeGLSLString(variable_type);
2305 	std::stringstream	 variable_type_glsl_array_sstream;
2306 	std::stringstream	 variable_type_glsl_arrayed_sstream;
2307 
2308 	variable_type_glsl_arrayed_sstream << variable_type_glsl;
2309 
2310 	if (array_size > 1)
2311 	{
2312 		variable_type_glsl_array_sstream << "[" << array_size << "]";
2313 		variable_type_glsl_arrayed_sstream << variable_type_glsl_array_sstream.str();
2314 	}
2315 
2316 	/* Form pre-amble */
2317 	result_sstream << "#version 400\n"
2318 					  "\n"
2319 					  "#extension GL_ARB_shader_subroutine : require\n";
2320 
2321 	if (variable_type == Utils::VARIABLE_TYPE_DOUBLE)
2322 	{
2323 		result_sstream << "#extension GL_ARB_gpu_shader_fp64 : require\n";
2324 	}
2325 
2326 	/* Form subroutine type declaration */
2327 	result_sstream << "\n"
2328 					  "subroutine "
2329 				   << variable_type_glsl_arrayed_sstream.str() << " colorGetter(in " << variable_type_glsl
2330 				   << " in_value" << variable_type_glsl_array_sstream.str() << ");\n"
2331 																			   "\n";
2332 
2333 	/* Declare getter functions */
2334 	for (int n_getter = 0; n_getter < 2; ++n_getter)
2335 	{
2336 		result_sstream << "subroutine(colorGetter) " << variable_type_glsl_arrayed_sstream.str() << " getter"
2337 					   << n_getter << "(in " << variable_type_glsl << " in_value"
2338 					   << variable_type_glsl_array_sstream.str() << ")\n"
2339 																	"{\n";
2340 
2341 		if (array_size > 1)
2342 		{
2343 			result_sstream << variable_type_glsl << " temp" << variable_type_glsl_array_sstream.str() << ";\n";
2344 		}
2345 
2346 		if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2347 		{
2348 			if (array_size > 1)
2349 			{
2350 				for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2351 				{
2352 					result_sstream << "    temp[" << array_index << "]"
2353 																	" = "
2354 								   << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "")
2355 								   << "(in_value[" << array_index << "]);\n";
2356 				}
2357 
2358 				result_sstream << "    return temp;\n";
2359 			}
2360 			else
2361 			{
2362 				result_sstream << "    return "
2363 							   << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "")
2364 							   << "(in_value);\n";
2365 			}
2366 		} /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */
2367 		else
2368 		{
2369 			if (array_size > 1)
2370 			{
2371 				for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2372 				{
2373 					result_sstream << "    temp[" << array_index << "]"
2374 																	" = in_value["
2375 								   << array_index << "] + " << (n_getter + 1) << ";\n";
2376 				}
2377 
2378 				result_sstream << "    return temp;\n";
2379 			}
2380 			else
2381 			{
2382 				result_sstream << "    return (in_value + " << (n_getter + 1) << ");\n";
2383 			}
2384 		}
2385 
2386 		result_sstream << "}\n";
2387 	} /* for (both getter functions) */
2388 
2389 	/* Declare subroutine uniform */
2390 	result_sstream << "subroutine uniform colorGetter colorGetterUniform;\n"
2391 					  "\n";
2392 
2393 	/* Declare output variable */
2394 	result_sstream << "out ";
2395 
2396 	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2397 	{
2398 		Utils::_variable_type result_as_int_variable_type =
2399 			Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components);
2400 		std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type);
2401 
2402 		result_sstream << variable_type_glsl_as_int;
2403 	}
2404 	else
2405 	{
2406 		result_sstream << variable_type_glsl;
2407 	}
2408 
2409 	result_sstream << " result;\n"
2410 					  "\n";
2411 
2412 	/* Declare main(): prepare input argument for the subroutine function */
2413 	result_sstream << "void main()\n"
2414 					  "{\n"
2415 					  "    "
2416 				   << variable_type_glsl << " temp";
2417 
2418 	if (array_size > 1)
2419 	{
2420 		result_sstream << "[" << array_size << "]";
2421 	};
2422 
2423 	result_sstream << ";\n";
2424 
2425 	for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2426 	{
2427 		result_sstream << "    temp";
2428 
2429 		if (array_size > 1)
2430 		{
2431 			result_sstream << "[" << array_index << "]";
2432 		}
2433 
2434 		result_sstream << " = " << variable_type_glsl << "(";
2435 
2436 		if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2437 		{
2438 			result_sstream << "true";
2439 		}
2440 		else
2441 		{
2442 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2443 			{
2444 				result_sstream << "3";
2445 
2446 				if (n_component != (n_variable_type_components - 1))
2447 				{
2448 					result_sstream << ", ";
2449 				}
2450 			} /* for (all components) */
2451 		}
2452 
2453 		result_sstream << ");\n";
2454 	} /* for (all array indices) */
2455 
2456 	/* Declare main(): call the subroutine. Verify the input and write the result
2457 	 *                 to the output variable.
2458 	 **/
2459 	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2460 	{
2461 		Utils::_variable_type result_as_int_variable_type =
2462 			Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components);
2463 		std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type);
2464 
2465 		result_sstream << variable_type_glsl_arrayed_sstream.str() << " subroutine_result = colorGetterUniform(temp);\n"
2466 																	  "result = ";
2467 
2468 		for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2469 		{
2470 			if (variable_type_glsl == "bool")
2471 				result_sstream << "bool(subroutine_result";
2472 			else
2473 				result_sstream << "all(subroutine_result";
2474 
2475 			if (array_size > 1)
2476 			{
2477 				result_sstream << "[" << array_index << "]";
2478 			}
2479 
2480 			result_sstream << ")";
2481 
2482 			if (array_index != (array_size - 1))
2483 			{
2484 				result_sstream << "&& ";
2485 			}
2486 		}
2487 
2488 		result_sstream << " == true ? " << variable_type_glsl_as_int << "(1) : " << variable_type_glsl_as_int << "(0);";
2489 	}
2490 	else
2491 	{
2492 		if (array_size > 1)
2493 		{
2494 			DE_ASSERT(array_size == 2);
2495 
2496 			result_sstream << variable_type_glsl << " subroutine_result" << variable_type_glsl_array_sstream.str()
2497 						   << " = colorGetterUniform(temp);\n"
2498 							  "\n"
2499 							  "if (subroutine_result[0] == subroutine_result[1]) result = subroutine_result[0];\n"
2500 							  "else\n"
2501 							  "result = "
2502 						   << variable_type_glsl << "(-1);\n";
2503 		}
2504 		else
2505 		{
2506 			result_sstream << "result = colorGetterUniform(temp);\n";
2507 		}
2508 	}
2509 
2510 	/* All done */
2511 	result_sstream << "}\n";
2512 
2513 	return result_sstream.str();
2514 }
2515 
2516 /** Initializes all GL objects required to run the test. */
initTest()2517 void FunctionalTest1_2::initTest()
2518 {
2519 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2520 
2521 	/* Generate buffer object to hold result XFB data */
2522 	gl.genBuffers(1, &m_xfb_bo_id);
2523 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2524 
2525 	/* Set up XFB BO bindings */
2526 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
2527 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2528 
2529 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
2530 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
2531 
2532 	/* Generate VAO to use for the draw calls */
2533 	gl.genVertexArrays(1, &m_vao_id);
2534 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2535 
2536 	gl.bindVertexArray(m_vao_id);
2537 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2538 }
2539 
2540 /** Executes test iteration.
2541  *
2542  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2543  */
iterate()2544 tcu::TestNode::IterateResult FunctionalTest1_2::iterate()
2545 {
2546 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
2547 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
2548 	{
2549 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
2550 	}
2551 
2552 	/* Initialize a test program object */
2553 	initTest();
2554 
2555 	/* Construct test case descriptors: first, iIerate over all
2556 	 * variable types we want to cover */
2557 	const Utils::_variable_type variable_types[] = {
2558 		Utils::VARIABLE_TYPE_BOOL,   Utils::VARIABLE_TYPE_BVEC2,  Utils::VARIABLE_TYPE_BVEC3,
2559 		Utils::VARIABLE_TYPE_BVEC4,  Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT,
2560 		Utils::VARIABLE_TYPE_INT,	Utils::VARIABLE_TYPE_IVEC2,  Utils::VARIABLE_TYPE_IVEC3,
2561 		Utils::VARIABLE_TYPE_IVEC4,  Utils::VARIABLE_TYPE_MAT2,   Utils::VARIABLE_TYPE_MAT2X3,
2562 		Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_MAT3,   Utils::VARIABLE_TYPE_MAT3X2,
2563 		Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_MAT4,   Utils::VARIABLE_TYPE_MAT4X2,
2564 		Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_UINT,   Utils::VARIABLE_TYPE_UVEC2,
2565 		Utils::VARIABLE_TYPE_UVEC3,  Utils::VARIABLE_TYPE_UVEC4,  Utils::VARIABLE_TYPE_VEC2,
2566 		Utils::VARIABLE_TYPE_VEC3,   Utils::VARIABLE_TYPE_VEC4
2567 	};
2568 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
2569 
2570 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
2571 	{
2572 		Utils::_variable_type current_variable_type = variable_types[n_variable_type];
2573 
2574 		/* We need to test both arrayed and non-arrayed arguments */
2575 		for (unsigned int array_size = 1; array_size < 3; ++array_size)
2576 		{
2577 			/* Exclude double variables if the relevant extension is unavailable */
2578 			if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64") &&
2579 				current_variable_type == Utils::VARIABLE_TYPE_DOUBLE)
2580 			{
2581 				continue;
2582 			}
2583 
2584 			/* Form the descriptor */
2585 			_test_case test_case;
2586 
2587 			test_case.array_size	= array_size;
2588 			test_case.variable_type = current_variable_type;
2589 
2590 			/* Store the test case descriptor */
2591 			m_test_cases.push_back(test_case);
2592 		} /* for (both arrayed and non-arrayed arguments) */
2593 	}	 /* for (all variable types) */
2594 
2595 	/* Iterate over all test cases and execute the test */
2596 	for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
2597 		 ++test_case_iterator)
2598 	{
2599 		const _test_case& test_case = *test_case_iterator;
2600 
2601 		m_has_test_passed &= executeTestIteration(test_case);
2602 
2603 		/* Release GL objects that were created during the execution */
2604 		deinitTestIteration();
2605 	} /* for (all test cases) */
2606 
2607 	/* Done */
2608 	if (m_has_test_passed)
2609 	{
2610 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2611 	}
2612 	else
2613 	{
2614 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2615 	}
2616 
2617 	return STOP;
2618 }
2619 
2620 /** Verifies data that has been XFBed out by the vertex shader.
2621  *
2622  *  @param xfb_data      Buffer holding the data.
2623  *  @param variable_type GLSL type used for the test iteration
2624  *                       that generated the data at @param xfb_data.
2625  *
2626  *  @return true if the data was found to be valid, false if it
2627  *               was detected to be incorrect.
2628  **/
verifyXFBData(const void * xfb_data,const Utils::_variable_type & variable_type)2629 bool FunctionalTest1_2::verifyXFBData(const void* xfb_data, const Utils::_variable_type& variable_type)
2630 {
2631 	const Utils::_variable_type base_variable_type		   = Utils::getBaseVariableType(variable_type);
2632 	const float					epsilon					   = 1e-5f;
2633 	const unsigned int			n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
2634 	bool						result					   = true;
2635 	const unsigned char*		traveller_ptr			   = (const unsigned char*)xfb_data;
2636 
2637 	/* Boolean arguments/return types are tested with a slightly different shader so we
2638 	 * need to test them in a separate code-path.
2639 	 */
2640 	if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2641 	{
2642 		/* 0 should be returned when getter0 is used, 1 otherwise */
2643 		const unsigned int ref_values[] = { 0, 1 };
2644 		const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]);
2645 
2646 		for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value)
2647 		{
2648 			const unsigned int ref_value = ref_values[n_ref_value];
2649 
2650 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2651 			{
2652 				int* result_value_ptr = (int*)(traveller_ptr);
2653 
2654 				if (*result_value_ptr != (int)ref_value)
2655 				{
2656 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2657 																   "["
2658 									   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2659 									   << " argument/return types ("
2660 										  "expected:["
2661 									   << ref_value << "], found:[" << *result_value_ptr << "])"
2662 									   << tcu::TestLog::EndMessage;
2663 
2664 					result = false;
2665 					break;
2666 				}
2667 
2668 				traveller_ptr += sizeof(int);
2669 			} /* for (all components) */
2670 		}	 /* for (all reference values) */
2671 	}		  /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */
2672 	else
2673 	{
2674 		/* 4 should be returned when getter0 is used, 5 otherwise */
2675 		const unsigned int ref_values[] = { 4, 5 };
2676 		const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]);
2677 
2678 		for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value)
2679 		{
2680 			const unsigned int ref_value = ref_values[n_ref_value];
2681 
2682 			DE_ASSERT(
2683 				base_variable_type == Utils::VARIABLE_TYPE_DOUBLE || base_variable_type == Utils::VARIABLE_TYPE_FLOAT ||
2684 				base_variable_type == Utils::VARIABLE_TYPE_INT || base_variable_type == Utils::VARIABLE_TYPE_UINT);
2685 
2686 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2687 			{
2688 				const double* double_value_ptr = (double*)traveller_ptr;
2689 				const float*  float_value_ptr  = (float*)traveller_ptr;
2690 				const int*	int_value_ptr	= (int*)traveller_ptr;
2691 
2692 				switch (base_variable_type)
2693 				{
2694 				case Utils::VARIABLE_TYPE_DOUBLE:
2695 				{
2696 					if (de::abs(*double_value_ptr - (double)ref_value) > epsilon)
2697 					{
2698 						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2699 																	   "["
2700 										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2701 										   << " argument/return types ("
2702 											  "expected:["
2703 										   << ref_value << "], found:[" << *double_value_ptr << "])"
2704 										   << tcu::TestLog::EndMessage;
2705 
2706 						result = false;
2707 					}
2708 
2709 					traveller_ptr += sizeof(double);
2710 					break;
2711 				}
2712 
2713 				case Utils::VARIABLE_TYPE_FLOAT:
2714 				{
2715 					if (de::abs(*float_value_ptr - (float)ref_value) > epsilon)
2716 					{
2717 						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2718 																	   "["
2719 										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2720 										   << " argument/return types ("
2721 											  "expected:["
2722 										   << ref_value << "], found:[" << *float_value_ptr << "])"
2723 										   << tcu::TestLog::EndMessage;
2724 
2725 						result = false;
2726 					}
2727 
2728 					traveller_ptr += sizeof(float);
2729 					break;
2730 				}
2731 
2732 				case Utils::VARIABLE_TYPE_INT:
2733 				case Utils::VARIABLE_TYPE_UINT:
2734 				{
2735 					if (*int_value_ptr != (int)ref_value)
2736 					{
2737 						m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2738 																	   "["
2739 										   << Utils::getVariableTypeGLSLString(variable_type) << "]"
2740 										   << " argument/return types ("
2741 											  "expected:["
2742 										   << ref_value << "], found:[" << *int_value_ptr << "])"
2743 										   << tcu::TestLog::EndMessage;
2744 
2745 						result = false;
2746 					}
2747 
2748 					traveller_ptr += sizeof(int);
2749 					break;
2750 				}
2751 
2752 				default:
2753 					break;
2754 				} /* switch (base_variable_type) */
2755 			}	 /* for (all components) */
2756 		}		  /* for (all reference values) */
2757 	}
2758 
2759 	return result;
2760 }
2761 
2762 /** Constructor
2763  *
2764  * @param context CTS context
2765  **/
FunctionalTest3_4(deqp::Context & context)2766 FunctionalTest3_4::FunctionalTest3_4(deqp::Context& context)
2767 	: TestCase(context, "four_subroutines_with_two_uniforms", "Verify Get* API and draw calls")
2768 	, m_n_active_subroutine_uniforms(0)
2769 	, m_n_active_subroutine_uniform_locations(0)
2770 	, m_n_active_subroutines(0)
2771 	, m_n_active_subroutine_uniform_name_length(0)
2772 	, m_n_active_subroutine_name_length(0)
2773 	, m_n_active_subroutine_uniform_size(0)
2774 {
2775 	/* Nothing to be done here */
2776 }
2777 
2778 /** Execute test
2779  *
2780  * @return tcu::TestNode::STOP
2781  **/
iterate()2782 tcu::TestNode::IterateResult FunctionalTest3_4::iterate()
2783 {
2784 	static const glw::GLchar* vertex_shader_code =
2785 		"#version 400 core\n"
2786 		"#extension GL_ARB_shader_subroutine : require\n"
2787 		"\n"
2788 		"precision highp float;\n"
2789 		"\n"
2790 		"// Sub routine type declaration\n"
2791 		"subroutine vec4 routine_type(in vec4 iparam);\n"
2792 		"\n"
2793 		"// Sub routine definitions\n"
2794 		"subroutine(routine_type) vec4 inverse_order(in vec4 iparam)\n"
2795 		"{\n"
2796 		"    return iparam.wzyx;\n"
2797 		"}\n"
2798 		"\n"
2799 		"subroutine(routine_type) vec4 negate(in vec4 iparam)\n"
2800 		"{\n"
2801 		"    return -iparam;\n"
2802 		"}\n"
2803 		"\n"
2804 		"subroutine(routine_type) vec4 inverse(in vec4 iparam)\n"
2805 		"{\n"
2806 		"    return 1 / iparam;\n"
2807 		"}\n"
2808 		"\n"
2809 		"subroutine(routine_type) vec4 square(in vec4 iparam)\n"
2810 		"{\n"
2811 		"    return iparam * iparam;\n"
2812 		"}\n"
2813 		"\n"
2814 		"// Sub routine uniforms\n"
2815 		"subroutine uniform routine_type first_routine;\n"
2816 		"subroutine uniform routine_type second_routine;\n"
2817 		"\n"
2818 		"// Input data\n"
2819 		"uniform vec4 input_data;\n"
2820 		"\n"
2821 		"// Output\n"
2822 		"out vec4 out_input_data;\n"
2823 		"out vec4 out_result_from_first_routine;\n"
2824 		"out vec4 out_result_from_second_routine;\n"
2825 		"out vec4 out_result_from_combined_routines;\n"
2826 		"out vec4 out_result_from_routines_combined_in_reveresed_order;\n"
2827 		"\n"
2828 		"void main()\n"
2829 		"{\n"
2830 		"    out_input_data                                       = input_data;\n"
2831 		"    out_result_from_first_routine                        = first_routine(input_data);\n"
2832 		"    out_result_from_second_routine                       = second_routine(input_data);\n"
2833 		"    out_result_from_combined_routines                    = second_routine(first_routine(input_data));\n"
2834 		"    out_result_from_routines_combined_in_reveresed_order = first_routine(second_routine(input_data));\n"
2835 		"}\n"
2836 		"\n";
2837 
2838 	static const GLchar* varying_names[] = {
2839 		"out_input_data",
2840 		"out_result_from_first_routine",
2841 		"out_result_from_second_routine",
2842 		"out_result_from_combined_routines",
2843 		"out_result_from_routines_combined_in_reveresed_order",
2844 	};
2845 
2846 	static const GLchar* subroutine_uniform_names[] = { "first_routine", "second_routine" };
2847 
2848 	static const GLchar* subroutine_names[] = { "inverse_order", "negate", "inverse", "square" };
2849 
2850 	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
2851 	static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */;
2852 
2853 	static const GLuint inverse_order_routine_index = 0;
2854 	static const GLuint negate_routine_index		= 1;
2855 	static const GLuint inverse_routine_index		= 2;
2856 	static const GLuint square_routine_index		= 3;
2857 
2858 	/* Test data */
2859 	static const Utils::vec4<GLfloat> inverse_order_negate_data[5] = {
2860 		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2861 		Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),
2862 		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),
2863 	};
2864 
2865 	static const Utils::vec4<GLfloat> inverse_order_inverse_data[5] = {
2866 		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2867 		Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2868 		Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2869 	};
2870 
2871 	static const Utils::vec4<GLfloat> inverse_order_square_data[5] = {
2872 		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2873 		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),   Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2874 		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2875 	};
2876 
2877 	static const Utils::vec4<GLfloat> negate_inverse_data[5] = {
2878 		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2879 		Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2880 		Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2881 	};
2882 
2883 	static const Utils::vec4<GLfloat> negate_square_data[5] = {
2884 		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),   Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2885 		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),	 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2886 		Utils::vec4<GLfloat>(-4.0f, -1.0f, -1.0f, -4.0f),
2887 	};
2888 
2889 	static const Utils::vec4<GLfloat> inverse_square_data[5] = {
2890 		Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f),
2891 		Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),   Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f),
2892 		Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f),
2893 	};
2894 
2895 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
2896 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
2897 	{
2898 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
2899 	}
2900 
2901 	m_n_active_subroutine_uniforms			  = 2;
2902 	m_n_active_subroutine_uniform_locations   = 2;
2903 	m_n_active_subroutines					  = 4;
2904 	m_n_active_subroutine_uniform_name_length = 0;
2905 	m_n_active_subroutine_name_length		  = 0;
2906 	m_n_active_subroutine_uniform_size		  = 1;
2907 
2908 	/* GL objects */
2909 	Utils::program	 program(m_context);
2910 	Utils::buffer	  transform_feedback_buffer(m_context);
2911 	Utils::vertexArray vao(m_context);
2912 
2913 	bool result = true;
2914 
2915 	/* Calculate max name lengths for subroutines and subroutine uniforms */
2916 	for (GLint i = 0; i < m_n_active_subroutine_uniforms; ++i)
2917 	{
2918 		const GLsizei length = (GLsizei)strlen(subroutine_uniform_names[i]);
2919 
2920 		if (length > m_n_active_subroutine_uniform_name_length)
2921 		{
2922 			m_n_active_subroutine_uniform_name_length = length;
2923 		}
2924 	}
2925 
2926 	for (GLint i = 0; i < m_n_active_subroutines; ++i)
2927 	{
2928 		const GLsizei length = (GLsizei)strlen(subroutine_names[i]);
2929 
2930 		if (length > m_n_active_subroutine_name_length)
2931 		{
2932 			m_n_active_subroutine_name_length = length;
2933 		}
2934 	}
2935 
2936 	/* Init */
2937 	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
2938 				  n_varyings);
2939 
2940 	vao.generate();
2941 	vao.bind();
2942 
2943 	transform_feedback_buffer.generate();
2944 	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
2945 									 GL_DYNAMIC_COPY);
2946 	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
2947 
2948 	program.use();
2949 
2950 	/* Inspect Get* API */
2951 	if ((false == inspectProgramStageiv(program.m_program_object_id)) ||
2952 		(false == inspectActiveSubroutineUniformiv(program.m_program_object_id, subroutine_uniform_names)) ||
2953 		(false == inspectActiveSubroutineUniformName(program.m_program_object_id, subroutine_uniform_names)) ||
2954 		(false == inspectActiveSubroutineName(program.m_program_object_id, subroutine_names)) ||
2955 		(false ==
2956 		 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, false)))
2957 	{
2958 		result = false;
2959 	}
2960 
2961 	/* Inspect GetProgram* API */
2962 	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
2963 	{
2964 		if ((false == inspectProgramInterfaceiv(program.m_program_object_id)) ||
2965 			(false ==
2966 			 inspectProgramResourceiv(program.m_program_object_id, subroutine_names, subroutine_uniform_names)) ||
2967 			(false ==
2968 			 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, true)))
2969 		{
2970 			result = false;
2971 		}
2972 	}
2973 
2974 	/* Test shader execution */
2975 	if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2976 						   subroutine_names[negate_routine_index], subroutine_uniform_names, inverse_order_negate_data,
2977 						   false)) ||
2978 		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2979 						   subroutine_names[inverse_routine_index], subroutine_uniform_names,
2980 						   inverse_order_inverse_data, false)) ||
2981 		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2982 						   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_order_square_data,
2983 						   false)) ||
2984 		(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
2985 						   subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data,
2986 						   false)) ||
2987 		(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
2988 						   subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data,
2989 						   false)) ||
2990 		(false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index],
2991 						   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data,
2992 						   false)))
2993 	{
2994 		result = false;
2995 	}
2996 
2997 	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
2998 	{
2999 		if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3000 							   subroutine_names[negate_routine_index], subroutine_uniform_names,
3001 							   inverse_order_negate_data, true)) ||
3002 			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3003 							   subroutine_names[inverse_routine_index], subroutine_uniform_names,
3004 							   inverse_order_inverse_data, true)) ||
3005 			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3006 							   subroutine_names[square_routine_index], subroutine_uniform_names,
3007 							   inverse_order_square_data, true)) ||
3008 			(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
3009 							   subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data,
3010 							   true)) ||
3011 			(false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
3012 							   subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data,
3013 							   true)) ||
3014 			(false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index],
3015 							   subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data,
3016 							   true)))
3017 		{
3018 			result = false;
3019 		}
3020 	}
3021 
3022 	/* Done */
3023 	if (true == result)
3024 	{
3025 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3026 	}
3027 	else
3028 	{
3029 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3030 	}
3031 
3032 	return tcu::TestNode::STOP;
3033 }
3034 
3035 /** Verify result of getProgramStageiv
3036  *
3037  * @param program_id Program object id
3038  * @param pname      <pname> parameter for getProgramStageiv
3039  * @param expected   Expected value
3040  *
3041  * @return true if result is equal to expected value, flase otherwise
3042  **/
checkProgramStageiv(glw::GLuint program_id,glw::GLenum pname,glw::GLint expected) const3043 bool FunctionalTest3_4::checkProgramStageiv(glw::GLuint program_id, glw::GLenum pname, glw::GLint expected) const
3044 {
3045 	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3046 	GLint				  value = 0;
3047 
3048 	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, pname, &value);
3049 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3050 
3051 	if (expected != value)
3052 	{
3053 		m_context.getTestContext().getLog() << tcu::TestLog::Message
3054 											<< "Error. Invalid result. Function: getProgramStageiv. "
3055 											<< "pname: " << Utils::pnameToStr(pname) << ". "
3056 											<< "Result: " << value << ". "
3057 											<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3058 
3059 		return false;
3060 	}
3061 	else
3062 	{
3063 		return true;
3064 	}
3065 }
3066 
3067 /** Verify result of getProgramResourceiv
3068  *
3069  * @param program_id        Program object id
3070  * @param program_interface Program interface
3071  * @param pname             <pname> parameter for getProgramStageiv
3072  * @param resource_name     Resource name
3073  * @param expected          Expected value
3074  *
3075  * @return true if result is equal to expected value, false otherwise
3076  **/
checkProgramResourceiv(GLuint program_id,GLenum program_interface,GLenum pname,const glw::GLchar * resource_name,GLint expected) const3077 bool FunctionalTest3_4::checkProgramResourceiv(GLuint program_id, GLenum program_interface, GLenum pname,
3078 											   const glw::GLchar* resource_name, GLint expected) const
3079 {
3080 	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3081 	GLuint				  index = gl.getProgramResourceIndex(program_id, program_interface, resource_name);
3082 	GLint				  value = 0;
3083 
3084 	if (GL_INVALID_INDEX == index)
3085 	{
3086 		return false;
3087 	}
3088 
3089 	gl.getProgramResourceiv(program_id, program_interface, index, 1, &pname, 1, 0, &value);
3090 	GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceiv");
3091 
3092 	if (expected != value)
3093 	{
3094 		m_context.getTestContext().getLog()
3095 			<< tcu::TestLog::Message << "Error. Invalid result. Function: getProgramResourceiv. "
3096 			<< "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". "
3097 			<< "Resource name: " << resource_name << ". "
3098 			<< "Property: " << Utils::pnameToStr(pname) << ". "
3099 			<< "Result: " << value << ". "
3100 			<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3101 
3102 		return false;
3103 	}
3104 	else
3105 	{
3106 		return true;
3107 	}
3108 }
3109 
3110 /** Verify result of getProgramInterfaceiv
3111  *
3112  * @param program_id        Program object id
3113  * @param program_interface Program interface
3114  * @param pname             <pname> parameter for getProgramStageiv
3115  * @param expected          Expected value
3116  *
3117  * @return true if result is equal to expected value, flase otherwise
3118  **/
checkProgramInterfaceiv(GLuint program_id,GLenum program_interface,GLenum pname,GLint expected) const3119 bool FunctionalTest3_4::checkProgramInterfaceiv(GLuint program_id, GLenum program_interface, GLenum pname,
3120 												GLint expected) const
3121 {
3122 	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3123 	GLint				  value = 0;
3124 
3125 	gl.getProgramInterfaceiv(program_id, program_interface, pname, &value);
3126 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInterfaceiv");
3127 
3128 	if (expected != value)
3129 	{
3130 		m_context.getTestContext().getLog()
3131 			<< tcu::TestLog::Message << "Error. Invalid result. Function: getProgramInterfaceiv. "
3132 			<< "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". "
3133 			<< "pname: " << Utils::pnameToStr(pname) << ". "
3134 			<< "Result: " << value << ". "
3135 			<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3136 
3137 		return false;
3138 	}
3139 	else
3140 	{
3141 		return true;
3142 	}
3143 }
3144 
3145 /** Verify result of getActiveSubroutineUniformiv
3146  *
3147  * @param program_id Program object id
3148  * @param index      <index> parameter for getActiveSubroutineUniformiv
3149  * @param pname      <pname> parameter for getActiveSubroutineUniformiv
3150  * @param expected   Expected value
3151  *
3152  * @return true if result is equal to expected value, flase otherwise
3153  **/
checkActiveSubroutineUniformiv(GLuint program_id,GLuint index,GLenum pname,GLint expected) const3154 bool FunctionalTest3_4::checkActiveSubroutineUniformiv(GLuint program_id, GLuint index, GLenum pname,
3155 													   GLint expected) const
3156 {
3157 	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3158 	GLint				  value = 0;
3159 
3160 	gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, index, pname, &value);
3161 	GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv");
3162 
3163 	if (expected != value)
3164 	{
3165 		m_context.getTestContext().getLog() << tcu::TestLog::Message
3166 											<< "Error. Invalid result. Function: getActiveSubroutineUniformiv. "
3167 											<< "idnex: " << index << ". "
3168 											<< "pname: " << Utils::pnameToStr(pname) << ". "
3169 											<< "Result: " << value << ". "
3170 											<< "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3171 
3172 		return false;
3173 	}
3174 	else
3175 	{
3176 		return true;
3177 	}
3178 }
3179 
3180 /** Returns index of program resource
3181  *
3182  * @param program_id        Program object id
3183  * @param program_interface Program interface
3184  * @param resource_name     Name of resource
3185  *
3186  * @return Index of specified resource
3187  **/
getProgramResourceIndex(GLuint program_id,GLenum program_interface,const glw::GLchar * resource_name) const3188 GLuint FunctionalTest3_4::getProgramResourceIndex(GLuint program_id, GLenum program_interface,
3189 												  const glw::GLchar* resource_name) const
3190 {
3191 	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3192 	GLuint				  index = gl.getProgramResourceIndex(program_id, program_interface, resource_name);
3193 
3194 	GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceIndex");
3195 
3196 	if (GL_INVALID_INDEX == index)
3197 	{
3198 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Program resource is not available. "
3199 											<< "Program interface: " << Utils::programInterfaceToStr(program_interface)
3200 											<< ". "
3201 											<< "Resource name: " << resource_name << "." << tcu::TestLog::EndMessage;
3202 	}
3203 
3204 	return index;
3205 }
3206 
3207 /** Get subroutine index
3208  *
3209  * @param program_id        Program object id
3210  * @param subroutine_name   Subroutine name
3211  * @param use_program_query If true getProgramResourceIndex is used, otherwise getSubroutineIndex
3212  *
3213  * @return Index of subroutine
3214  **/
getSubroutineIndex(GLuint program_id,const glw::GLchar * subroutine_name,bool use_program_query) const3215 GLuint FunctionalTest3_4::getSubroutineIndex(GLuint program_id, const glw::GLchar* subroutine_name,
3216 											 bool use_program_query) const
3217 {
3218 	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
3219 	GLuint				  index = -1;
3220 
3221 	if (false == use_program_query)
3222 	{
3223 		index = gl.getSubroutineIndex(program_id, GL_VERTEX_SHADER, subroutine_name);
3224 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
3225 	}
3226 	else
3227 	{
3228 		index = gl.getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE, subroutine_name);
3229 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex");
3230 	}
3231 
3232 	if (GL_INVALID_INDEX == index)
3233 	{
3234 		TCU_FAIL("Subroutine is not available");
3235 	}
3236 
3237 	return index;
3238 }
3239 
3240 /** Get subroutine uniform location
3241  *
3242  * @param program_id        Program object id
3243  * @param uniform_name      Subroutine uniform name
3244  * @param use_program_query If true getProgramResourceLocation is used, otherwise getSubroutineUniformLocation
3245  *
3246  * @return Location of subroutine uniform
3247  **/
getSubroutineUniformLocation(GLuint program_id,const glw::GLchar * uniform_name,bool use_program_query) const3248 GLint FunctionalTest3_4::getSubroutineUniformLocation(GLuint program_id, const glw::GLchar* uniform_name,
3249 													  bool use_program_query) const
3250 {
3251 	const glw::Functions& gl	   = m_context.getRenderContext().getFunctions();
3252 	GLint				  location = -1;
3253 
3254 	if (false == use_program_query)
3255 	{
3256 		location = gl.getSubroutineUniformLocation(program_id, GL_VERTEX_SHADER, uniform_name);
3257 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
3258 	}
3259 	else
3260 	{
3261 		location = gl.getProgramResourceLocation(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name);
3262 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceLocation");
3263 	}
3264 
3265 	if (-1 == location)
3266 	{
3267 		TCU_FAIL("Subroutine uniform is not available");
3268 	}
3269 
3270 	return location;
3271 }
3272 
3273 /** Test if getProgramStageiv results are as expected
3274  *
3275  * @param program_id Program object id
3276  *
3277  * @result false in case of invalid result for any pname, true otherwise
3278  **/
inspectProgramStageiv(glw::GLuint program_id) const3279 bool FunctionalTest3_4::inspectProgramStageiv(glw::GLuint program_id) const
3280 {
3281 	bool result = true;
3282 
3283 	const inspectionDetails details[] = {
3284 		{ GL_ACTIVE_SUBROUTINE_UNIFORMS, m_n_active_subroutine_uniforms },
3285 		{ GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, m_n_active_subroutine_uniform_locations },
3286 		{ GL_ACTIVE_SUBROUTINES, m_n_active_subroutines },
3287 		{ GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH, m_n_active_subroutine_uniform_name_length + 1 },
3288 		{ GL_ACTIVE_SUBROUTINE_MAX_LENGTH, m_n_active_subroutine_name_length + 1 }
3289 	};
3290 	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3291 
3292 	for (GLuint i = 0; i < n_details; ++i)
3293 	{
3294 		if (false == checkProgramStageiv(program_id, details[i].pname, details[i].expected_value))
3295 		{
3296 			result = false;
3297 		}
3298 	}
3299 
3300 	return result;
3301 }
3302 
3303 /** Test if checkProgramInterfaceiv results are as expected
3304  *
3305  * @param program_id Program object id
3306  *
3307  * @result false in case of invalid result for any pname, true otherwise
3308  **/
inspectProgramInterfaceiv(glw::GLuint program_id) const3309 bool FunctionalTest3_4::inspectProgramInterfaceiv(glw::GLuint program_id) const
3310 {
3311 	bool result = true;
3312 
3313 	const inspectionDetailsForProgramInterface details[] = {
3314 		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, m_n_active_subroutine_uniforms },
3315 		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, m_n_active_subroutine_uniform_name_length + 1 },
3316 		{ GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3317 		{ GL_VERTEX_SUBROUTINE, GL_ACTIVE_RESOURCES, m_n_active_subroutines },
3318 		{ GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, m_n_active_subroutine_name_length + 1 }
3319 	};
3320 	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3321 
3322 	for (GLuint i = 0; i < n_details; ++i)
3323 	{
3324 		if (false == checkProgramInterfaceiv(program_id, details[i].program_interface, details[i].pname,
3325 											 details[i].expected_value))
3326 		{
3327 			result = false;
3328 		}
3329 	}
3330 
3331 	return result;
3332 }
3333 
3334 /** Test if checkProgramResourceiv results are as expected
3335  *
3336  * @param program_id       Program object id
3337  * @param subroutine_names Array of subroutine names
3338  * @param uniform_names    Array of uniform names
3339  *
3340  * @result false in case of invalid result for any pname, true otherwise
3341  **/
inspectProgramResourceiv(GLuint program_id,const GLchar ** subroutine_names,const GLchar ** uniform_names) const3342 bool FunctionalTest3_4::inspectProgramResourceiv(GLuint program_id, const GLchar** subroutine_names,
3343 												 const GLchar** uniform_names) const
3344 {
3345 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
3346 	bool				  result = true;
3347 
3348 	for (GLint subroutine = 0; subroutine < m_n_active_subroutines; ++subroutine)
3349 	{
3350 		const GLchar* subroutine_name = subroutine_names[subroutine];
3351 		const GLint   length		  = (GLint)strlen(subroutine_name) + 1;
3352 
3353 		if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE, GL_NAME_LENGTH, subroutine_name, length))
3354 		{
3355 			result = false;
3356 		}
3357 	}
3358 
3359 	inspectionDetails details[] = {
3360 		{ GL_NAME_LENGTH, 0 },
3361 		{ GL_ARRAY_SIZE, 1 },
3362 		{ GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3363 		{ GL_LOCATION, 0 },
3364 	};
3365 	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3366 
3367 	for (GLint uniform = 0; uniform < m_n_active_subroutine_uniforms; ++uniform)
3368 	{
3369 		const GLchar* uniform_name = uniform_names[uniform];
3370 		const GLint   length	   = (GLint)strlen(uniform_name) + 1;
3371 		const GLint   location	 = getSubroutineUniformLocation(program_id, uniform_name, true);
3372 
3373 		details[0].expected_value = length;
3374 		details[3].expected_value = location;
3375 
3376 		for (GLuint i = 0; i < n_details; ++i)
3377 		{
3378 			if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, details[i].pname,
3379 												uniform_name, details[i].expected_value))
3380 			{
3381 				result = false;
3382 			}
3383 		}
3384 
3385 		/* Check compatible subroutines */
3386 		GLuint index = getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name);
3387 
3388 		if (GL_INVALID_INDEX != index)
3389 		{
3390 			std::vector<GLint> compatible_subroutines;
3391 			GLint			   index_sum = 0;
3392 			GLenum			   prop		 = GL_COMPATIBLE_SUBROUTINES;
3393 
3394 			compatible_subroutines.resize(m_n_active_subroutines);
3395 
3396 			gl.getProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, index, 1, &prop, m_n_active_subroutines,
3397 									0, &compatible_subroutines[0]);
3398 
3399 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv");
3400 
3401 			/* Expected indices are 0, 1, 2, ... N */
3402 			for (GLint i = 0; i < m_n_active_subroutines; ++i)
3403 			{
3404 				index_sum += compatible_subroutines[i];
3405 			}
3406 
3407 			/* Sum of E1, ..., EN = (E1 + EN) * N / 2 */
3408 			if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum)
3409 			{
3410 				tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3411 
3412 				message << "Error. Invalid result. Function: getProgramResourceiv. "
3413 						<< "Program interface: GL_VERTEX_SUBROUTINE_UNIFORM. "
3414 						<< "Resource name: " << uniform_name << ". "
3415 						<< "Property: GL_COMPATIBLE_SUBROUTINES. "
3416 						<< "Results: ";
3417 
3418 				for (GLint i = 1; i < m_n_active_subroutines; ++i)
3419 				{
3420 					message << compatible_subroutines[i];
3421 				}
3422 
3423 				message << tcu::TestLog::EndMessage;
3424 
3425 				result = false;
3426 			}
3427 		}
3428 	}
3429 
3430 	return result;
3431 }
3432 
3433 /** Test if getActiveSubroutineUniformiv results are as expected
3434  *
3435  * @param program_id    Program object id
3436  * @param uniform_names Array of subroutine uniform names available in program
3437  *
3438  * @result false in case of invalid result for any pname, true otherwise
3439  **/
inspectActiveSubroutineUniformiv(GLuint program_id,const GLchar ** uniform_names) const3440 bool FunctionalTest3_4::inspectActiveSubroutineUniformiv(GLuint program_id, const GLchar** uniform_names) const
3441 {
3442 	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3443 	bool				  result					   = true;
3444 	GLint				  n_active_subroutine_uniforms = 0;
3445 
3446 	inspectionDetails details[] = {
3447 		{ GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3448 		{ GL_UNIFORM_SIZE, m_n_active_subroutine_uniform_size },
3449 		{ GL_UNIFORM_NAME_LENGTH, 0 },
3450 	};
3451 	const GLuint n_details = sizeof(details) / sizeof(details[0]);
3452 
3453 	/* Get amount of active subroutine uniforms */
3454 	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3455 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3456 
3457 	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3458 	{
3459 		GLint name_length = (GLint)strlen(uniform_names[uniform]);
3460 
3461 		details[2].expected_value = name_length + 1;
3462 
3463 		/* Checks from "details" */
3464 		for (GLuint i = 0; i < n_details; ++i)
3465 		{
3466 			if (false ==
3467 				checkActiveSubroutineUniformiv(program_id, uniform, details[i].pname, details[i].expected_value))
3468 			{
3469 				result = false;
3470 			}
3471 		}
3472 
3473 		/* Check compatible subroutines */
3474 		std::vector<GLint> compatible_subroutines;
3475 		compatible_subroutines.resize(m_n_active_subroutines);
3476 		GLint index_sum = 0;
3477 
3478 		gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, uniform, GL_COMPATIBLE_SUBROUTINES,
3479 										&compatible_subroutines[0]);
3480 		GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv");
3481 
3482 		/* Expected indices are 0, 1, 2, ... N */
3483 		for (GLint i = 0; i < m_n_active_subroutines; ++i)
3484 		{
3485 			index_sum += compatible_subroutines[i];
3486 		}
3487 
3488 		/* Sum of E1, ..., EN = (E1 + EN) * N / 2 */
3489 		if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum)
3490 		{
3491 			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3492 
3493 			message << "Error. Invalid result. Function: getActiveSubroutineUniformiv. idnex: " << uniform
3494 					<< ". pname: " << Utils::pnameToStr(GL_COMPATIBLE_SUBROUTINES) << ". Results: ";
3495 
3496 			for (GLint i = 1; i < m_n_active_subroutines; ++i)
3497 			{
3498 				message << compatible_subroutines[i];
3499 			}
3500 
3501 			message << tcu::TestLog::EndMessage;
3502 
3503 			result = false;
3504 		}
3505 	}
3506 
3507 	return result;
3508 }
3509 
3510 /** Test if getActiveSubroutineUniformName results are as expected
3511  *
3512  * @param program_id    Program object id
3513  * @param uniform_names Array of subroutine uniform names available in program
3514  *
3515  * @result false in case of invalid result, true otherwise
3516  **/
inspectActiveSubroutineUniformName(GLuint program_id,const GLchar ** uniform_names) const3517 bool FunctionalTest3_4::inspectActiveSubroutineUniformName(GLuint program_id, const GLchar** uniform_names) const
3518 {
3519 	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3520 	bool				  result					   = true;
3521 	GLint				  n_active_subroutine_uniforms = 0;
3522 	std::vector<GLchar>   active_uniform_name;
3523 
3524 	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3525 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3526 
3527 	active_uniform_name.resize(m_n_active_subroutine_uniform_name_length + 1);
3528 
3529 	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3530 	{
3531 		bool is_name_ok = false;
3532 
3533 		gl.getActiveSubroutineUniformName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_uniform_name.size(),
3534 										  0 /* length */, &active_uniform_name[0]);
3535 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveSubroutineUniformName");
3536 
3537 		for (GLint name = 0; name < n_active_subroutine_uniforms; ++name)
3538 		{
3539 			if (0 == strcmp(uniform_names[name], &active_uniform_name[0]))
3540 			{
3541 				is_name_ok = true;
3542 				break;
3543 			}
3544 		}
3545 
3546 		if (false == is_name_ok)
3547 		{
3548 			m_context.getTestContext().getLog()
3549 				<< tcu::TestLog::Message
3550 				<< "Error. Invalid result. Function: getActiveSubroutineUniformName. idnex: " << uniform
3551 				<< ". Result: " << &active_uniform_name[0] << tcu::TestLog::EndMessage;
3552 
3553 			result = false;
3554 			break;
3555 		}
3556 	}
3557 
3558 	return result;
3559 }
3560 
3561 /** Test if getActiveSubroutineUniformName results are as expected
3562  *
3563  * @param program_id       Program object id
3564  * @param subroutine_names Array of subroutine names available in program
3565  *
3566  * @result false in case of invalid result, true otherwise
3567  **/
inspectActiveSubroutineName(GLuint program_id,const GLchar ** subroutine_names) const3568 bool FunctionalTest3_4::inspectActiveSubroutineName(GLuint program_id, const GLchar** subroutine_names) const
3569 {
3570 	const glw::Functions& gl				   = m_context.getRenderContext().getFunctions();
3571 	bool				  result			   = true;
3572 	GLint				  n_active_subroutines = 0;
3573 	std::vector<GLchar>   active_subroutine_name;
3574 
3575 	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
3576 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3577 
3578 	active_subroutine_name.resize(m_n_active_subroutine_name_length + 1);
3579 
3580 	for (GLint uniform = 0; uniform < n_active_subroutines; ++uniform)
3581 	{
3582 		bool is_name_ok = false;
3583 
3584 		gl.getActiveSubroutineName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_subroutine_name.size(),
3585 								   0 /* length */, &active_subroutine_name[0]);
3586 		GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineName");
3587 
3588 		for (GLint name = 0; name < n_active_subroutines; ++name)
3589 		{
3590 			if (0 == strcmp(subroutine_names[name], &active_subroutine_name[0]))
3591 			{
3592 				is_name_ok = true;
3593 				break;
3594 			}
3595 		}
3596 
3597 		if (false == is_name_ok)
3598 		{
3599 			m_context.getTestContext().getLog()
3600 				<< tcu::TestLog::Message
3601 				<< "Error. Invalid result. Function: getActiveSubroutineName. idnex: " << uniform
3602 				<< ". Result: " << &active_subroutine_name[0] << tcu::TestLog::EndMessage;
3603 
3604 			result = false;
3605 			break;
3606 		}
3607 	}
3608 
3609 	return result;
3610 }
3611 
3612 /** Test if it is possible to "bind" all subroutines uniforms with all subroutines
3613  *
3614  * @param program_id       Program object id
3615  * @param subroutine_names Array of subroutine names available in program
3616  * @param uniform_names    Array of subroutine uniform names available in program
3617  *
3618  * @result false in case of invalid result, true otherwise
3619  **/
inspectSubroutineBinding(GLuint program_id,const GLchar ** subroutine_names,const GLchar ** uniform_names,bool use_program_query) const3620 bool FunctionalTest3_4::inspectSubroutineBinding(GLuint program_id, const GLchar** subroutine_names,
3621 												 const GLchar** uniform_names, bool use_program_query) const
3622 {
3623 	const glw::Functions& gl						   = m_context.getRenderContext().getFunctions();
3624 	bool				  result					   = true;
3625 	GLint				  n_active_subroutines		   = 0;
3626 	GLint				  n_active_subroutine_uniforms = 0;
3627 	std::vector<GLuint>   subroutine_uniforms;
3628 	GLuint				  queried_subroutine_index = 0;
3629 
3630 	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
3631 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3632 
3633 	gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3634 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3635 
3636 	subroutine_uniforms.resize(n_active_subroutine_uniforms);
3637 
3638 	for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3639 	{
3640 		GLuint uniform_location = getSubroutineUniformLocation(program_id, uniform_names[uniform], use_program_query);
3641 
3642 		for (GLint routine = 0; routine < n_active_subroutines; ++routine)
3643 		{
3644 			GLuint routine_index = getSubroutineIndex(program_id, subroutine_names[routine], use_program_query);
3645 
3646 			subroutine_uniforms[uniform] = routine_index;
3647 
3648 			gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_active_subroutine_uniforms, &subroutine_uniforms[0]);
3649 			GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3650 
3651 			gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, uniform_location, &queried_subroutine_index);
3652 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
3653 
3654 			if (queried_subroutine_index != routine_index)
3655 			{
3656 				m_context.getTestContext().getLog()
3657 					<< tcu::TestLog::Message << "Error. Invalid result. Function: gl.getUniformSubroutineuiv."
3658 					<< " Subroutine uniform: " << uniform << ", name: " << uniform_names[uniform]
3659 					<< ", location: " << uniform_location << ". Subroutine: " << routine
3660 					<< ", name: " << subroutine_names[routine] << ", index: " << routine_index
3661 					<< ". Result: " << queried_subroutine_index << tcu::TestLog::EndMessage;
3662 
3663 				result = false;
3664 			}
3665 		}
3666 	}
3667 
3668 	return result;
3669 }
3670 
3671 /** Execute draw call and verify results
3672  *
3673  * @param program_id                   Program object id
3674  * @param first_routine_name           Name of subroutine that shall be used aas first_routine
3675  * @param second_routine_name          Name of subroutine that shall be used aas second_routine
3676  * @param uniform_names                Name of uniforms
3677  * @param expected_results             Test data. [0] is used as input data. All are used as expected_results
3678  * @param use_program_query            If true GetProgram* API will be used
3679  *
3680  * @return false in case of invalid result, true otherwise
3681  **/
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) const3682 bool FunctionalTest3_4::testDraw(GLuint program_id, const GLchar* first_routine_name, const GLchar* second_routine_name,
3683 								 const GLchar** uniform_names, const Utils::vec4<GLfloat> expected_results[5],
3684 								 bool use_program_query) const
3685 {
3686 	static const GLuint   n_varyings			 = 5;
3687 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3688 	bool				  result				 = true;
3689 	GLuint				  subroutine_uniforms[2] = { 0 };
3690 
3691 	/* Get subroutine uniform locations */
3692 	GLint first_routine_location = getSubroutineUniformLocation(program_id, uniform_names[0], use_program_query);
3693 
3694 	GLint second_routine_location = getSubroutineUniformLocation(program_id, uniform_names[1], use_program_query);
3695 
3696 	/* Get subroutine indices */
3697 	GLuint first_routine_index = getSubroutineIndex(program_id, first_routine_name, use_program_query);
3698 
3699 	GLuint second_routine_index = getSubroutineIndex(program_id, second_routine_name, use_program_query);
3700 
3701 	/* Map uniforms with subroutines */
3702 	subroutine_uniforms[first_routine_location]  = first_routine_index;
3703 	subroutine_uniforms[second_routine_location] = second_routine_index;
3704 
3705 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 2 /* number of uniforms */, &subroutine_uniforms[0]);
3706 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3707 
3708 	/* Get location of input_data */
3709 	GLint input_data_location = gl.getUniformLocation(program_id, "input_data");
3710 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
3711 
3712 	if (-1 == input_data_location)
3713 	{
3714 		TCU_FAIL("Uniform is not available");
3715 	}
3716 
3717 	/* Set up input_data */
3718 	gl.uniform4f(input_data_location, expected_results[0].m_x, expected_results[0].m_y, expected_results[0].m_z,
3719 				 expected_results[0].m_w);
3720 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
3721 
3722 	/* Execute draw call with transform feedback */
3723 	gl.beginTransformFeedback(GL_POINTS);
3724 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
3725 
3726 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
3727 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
3728 
3729 	gl.endTransformFeedback();
3730 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
3731 
3732 	/* Verify results */
3733 	GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3734 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3735 
3736 	Utils::vec4<GLfloat> results[5];
3737 
3738 	results[0].m_x = feedback_data[0];
3739 	results[0].m_y = feedback_data[1];
3740 	results[0].m_z = feedback_data[2];
3741 	results[0].m_w = feedback_data[3];
3742 
3743 	results[1].m_x = feedback_data[4];
3744 	results[1].m_y = feedback_data[5];
3745 	results[1].m_z = feedback_data[6];
3746 	results[1].m_w = feedback_data[7];
3747 
3748 	results[2].m_x = feedback_data[8];
3749 	results[2].m_y = feedback_data[9];
3750 	results[2].m_z = feedback_data[10];
3751 	results[2].m_w = feedback_data[11];
3752 
3753 	results[3].m_x = feedback_data[12];
3754 	results[3].m_y = feedback_data[13];
3755 	results[3].m_z = feedback_data[14];
3756 	results[3].m_w = feedback_data[15];
3757 
3758 	results[4].m_x = feedback_data[16];
3759 	results[4].m_y = feedback_data[17];
3760 	results[4].m_z = feedback_data[18];
3761 	results[4].m_w = feedback_data[19];
3762 
3763 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3764 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3765 
3766 	for (GLuint i = 0; i < n_varyings; ++i)
3767 	{
3768 		result = result && (results[i] == expected_results[i]);
3769 	}
3770 
3771 	if (false == result)
3772 	{
3773 		m_context.getTestContext().getLog() << tcu::TestLog::Message
3774 											<< "Error. Invalid result. First routine: " << first_routine_name
3775 											<< ". Second routine: " << second_routine_name << tcu::TestLog::EndMessage;
3776 
3777 		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3778 
3779 		message << "Results:";
3780 
3781 		for (GLuint i = 0; i < n_varyings; ++i)
3782 		{
3783 			results[i].log(message);
3784 		}
3785 
3786 		message << tcu::TestLog::EndMessage;
3787 
3788 		message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3789 
3790 		message << "Expected:";
3791 
3792 		for (GLuint i = 0; i < n_varyings; ++i)
3793 		{
3794 			expected_results[i].log(message);
3795 		}
3796 
3797 		message << tcu::TestLog::EndMessage;
3798 	}
3799 
3800 	return result;
3801 }
3802 
3803 /** Constructor
3804  *
3805  * @param context CTS context
3806  **/
FunctionalTest5(deqp::Context & context)3807 FunctionalTest5::FunctionalTest5(deqp::Context& context)
3808 	: TestCase(context, "eight_subroutines_four_uniforms", "Verify multiple subroutine sets")
3809 {
3810 }
3811 
3812 /** Execute test
3813  *
3814  * @return tcu::TestNode::STOP
3815  **/
iterate()3816 tcu::TestNode::IterateResult FunctionalTest5::iterate()
3817 {
3818 	static const GLchar* vertex_shader_code =
3819 		"#version 400 core\n"
3820 		"#extension GL_ARB_shader_subroutine : require\n"
3821 		"\n"
3822 		"precision highp float;\n"
3823 		"\n"
3824 		"// Subroutine types\n"
3825 		"subroutine vec4  routine_type_1(in vec4 left, in vec4 right);\n"
3826 		"subroutine vec4  routine_type_2(in vec4 iparam);\n"
3827 		"subroutine vec4  routine_type_3(in vec4 a,    in vec4 b,    in vec4 c);\n"
3828 		"subroutine bvec4 routine_type_4(in vec4 left, in vec4 right);\n"
3829 		"\n"
3830 		"// Subroutine definitions\n"
3831 		"// 1st type\n"
3832 		"subroutine(routine_type_1) vec4 add(in vec4 left, in vec4 right)\n"
3833 		"{\n"
3834 		"    return left + right;\n"
3835 		"}\n"
3836 		"\n"
3837 		"subroutine(routine_type_1) vec4 subtract(in vec4 left, in vec4 right)\n"
3838 		"{\n"
3839 		"    return left - right;\n"
3840 		"}\n"
3841 		"\n"
3842 		"// 2nd type\n"
3843 		"subroutine(routine_type_2) vec4 square(in vec4 iparam)\n"
3844 		"{\n"
3845 		"    return iparam * iparam;\n"
3846 		"}\n"
3847 		"\n"
3848 		"subroutine(routine_type_2) vec4 square_root(in vec4 iparam)\n"
3849 		"{\n"
3850 		"    return sqrt(iparam);\n"
3851 		"}\n"
3852 		"\n"
3853 		"// 3rd type\n"
3854 		"subroutine(routine_type_3) vec4 do_fma(in vec4 a, in vec4 b, in vec4 c)\n"
3855 		"{\n"
3856 		"    return fma(a, b, c);\n"
3857 		"}\n"
3858 		"\n"
3859 		"subroutine(routine_type_3) vec4 blend(in vec4 a, in vec4 b, in vec4 c)\n"
3860 		"{\n"
3861 		"    return c * a + (vec4(1) - c) * b;\n"
3862 		"}\n"
3863 		"\n"
3864 		"// 4th type\n"
3865 		"subroutine(routine_type_4) bvec4 are_equal(in vec4 left, in vec4 right)\n"
3866 		"{\n"
3867 		"    return equal(left, right);\n"
3868 		"}\n"
3869 		"\n"
3870 		"subroutine(routine_type_4) bvec4 are_greater(in vec4 left, in vec4 right)\n"
3871 		"{\n"
3872 		"    return greaterThan(left, right);\n"
3873 		"}\n"
3874 		"\n"
3875 		"// Sub routine uniforms\n"
3876 		"subroutine uniform routine_type_1 first_routine;\n"
3877 		"subroutine uniform routine_type_2 second_routine;\n"
3878 		"subroutine uniform routine_type_3 third_routine;\n"
3879 		"subroutine uniform routine_type_4 fourth_routine;\n"
3880 		"\n"
3881 		"// Input data\n"
3882 		"uniform vec4 first_input;\n"
3883 		"uniform vec4 second_input;\n"
3884 		"uniform vec4 third_input;\n"
3885 		"\n"
3886 		"// Output\n"
3887 		"out  vec4 out_result_from_first_routine;\n"
3888 		"out  vec4 out_result_from_second_routine;\n"
3889 		"out  vec4 out_result_from_third_routine;\n"
3890 		"out uvec4 out_result_from_fourth_routine;\n"
3891 		"\n"
3892 		"void main()\n"
3893 		"{\n"
3894 		"    out_result_from_first_routine  =       first_routine (first_input, second_input);\n"
3895 		"    out_result_from_second_routine =       second_routine(first_input);\n"
3896 		"    out_result_from_third_routine  =       third_routine (first_input, second_input, third_input);\n"
3897 		"    out_result_from_fourth_routine = uvec4(fourth_routine(first_input, second_input));\n"
3898 		"}\n"
3899 		"\n";
3900 
3901 	static const GLchar* subroutine_names[4][2] = {
3902 		{ "add", "subtract" }, { "square", "square_root" }, { "do_fma", "blend" }, { "are_equal", "are_greater" }
3903 	};
3904 
3905 	static const GLchar* subroutine_uniform_names[4][1] = {
3906 		{ "first_routine" }, { "second_routine" }, { "third_routine" }, { "fourth_routine" }
3907 	};
3908 
3909 	static const GLuint n_subroutine_types	 = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
3910 	static const GLuint n_subroutines_per_type = sizeof(subroutine_names[0]) / sizeof(subroutine_names[0][0]);
3911 	static const GLuint n_subroutine_uniforms_per_type =
3912 		sizeof(subroutine_uniform_names[0]) / sizeof(subroutine_uniform_names[0][0]);
3913 
3914 	static const GLchar* uniform_names[] = { "first_input", "second_input", "third_input" };
3915 	static const GLuint  n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
3916 
3917 	static const GLchar* varying_names[] = { "out_result_from_first_routine", "out_result_from_second_routine",
3918 											 "out_result_from_third_routine", "out_result_from_fourth_routine" };
3919 	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
3920 	static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */;
3921 
3922 	/* Test data */
3923 	static const Utils::vec4<GLfloat> input_data[3] = { Utils::vec4<GLfloat>(1.0f, 4.0f, 9.0f, 16.0f),
3924 														Utils::vec4<GLfloat>(16.0f, 9.0f, 4.0f, 1.0f),
3925 														Utils::vec4<GLfloat>(0.25f, 0.5f, 0.75f, 1.0f) };
3926 
3927 	static const Utils::vec4<GLfloat> expected_result_from_first_routine[2] = {
3928 		Utils::vec4<GLfloat>(17.0f, 13.0f, 13.0f, 17.0f), Utils::vec4<GLfloat>(-15.0f, -5.0f, 5.0f, 15.0f)
3929 	};
3930 
3931 	static const Utils::vec4<GLfloat> expected_result_from_second_routine[2] = {
3932 		Utils::vec4<GLfloat>(1.0f, 16.0f, 81.0f, 256.0f), Utils::vec4<GLfloat>(1.0f, 2.0f, 3.0f, 4.0f)
3933 	};
3934 
3935 	static const Utils::vec4<GLfloat> expected_result_from_third_routine[2] = {
3936 		Utils::vec4<GLfloat>(16.25f, 36.5f, 36.75f, 17.0f), Utils::vec4<GLfloat>(12.25f, 6.5f, 7.75f, 16.0f)
3937 	};
3938 
3939 	static const Utils::vec4<GLuint> expected_result_from_fourth_routine[2] = { Utils::vec4<GLuint>(0, 0, 0, 0),
3940 																				Utils::vec4<GLuint>(0, 0, 1, 1) };
3941 
3942 	/* All combinations of subroutines */
3943 	static const GLuint subroutine_combinations[][4] = {
3944 		{ 0, 0, 0, 0 }, { 0, 0, 0, 1 }, { 0, 0, 1, 0 }, { 0, 0, 1, 1 }, { 0, 1, 0, 0 }, { 0, 1, 0, 1 },
3945 		{ 0, 1, 1, 0 }, { 0, 1, 1, 1 }, { 1, 0, 0, 0 }, { 1, 0, 0, 1 }, { 1, 0, 1, 0 }, { 1, 0, 1, 1 },
3946 		{ 1, 1, 0, 0 }, { 1, 1, 0, 1 }, { 1, 1, 1, 0 }, { 1, 1, 1, 1 }
3947 	};
3948 	static const GLuint n_subroutine_combinations =
3949 		sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]);
3950 
3951 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
3952 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
3953 	{
3954 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
3955 	}
3956 
3957 	/* Result */
3958 	bool result = true;
3959 
3960 	/* GL objects */
3961 	Utils::program	 program(m_context);
3962 	Utils::buffer	  transform_feedback_buffer(m_context);
3963 	Utils::vertexArray vao(m_context);
3964 
3965 	/* Init GL objects */
3966 	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
3967 				  n_varyings);
3968 
3969 	program.use();
3970 
3971 	vao.generate();
3972 	vao.bind();
3973 
3974 	transform_feedback_buffer.generate();
3975 	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
3976 									 GL_DYNAMIC_COPY);
3977 	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
3978 
3979 	/* Get subroutine uniform locations and subroutine indices */
3980 	for (GLuint type = 0; type < n_subroutine_types; ++type)
3981 	{
3982 		for (GLuint uniform = 0; uniform < n_subroutine_uniforms_per_type; ++uniform)
3983 		{
3984 			m_subroutine_uniform_locations[type][uniform] =
3985 				program.getSubroutineUniformLocation(subroutine_uniform_names[type][uniform], GL_VERTEX_SHADER);
3986 		}
3987 
3988 		for (GLuint routine = 0; routine < n_subroutines_per_type; ++routine)
3989 		{
3990 			m_subroutine_indices[type][routine] =
3991 				program.getSubroutineIndex(subroutine_names[type][routine], GL_VERTEX_SHADER);
3992 		}
3993 	}
3994 
3995 	/* Get uniform locations */
3996 	for (GLuint i = 0; i < n_uniform_names; ++i)
3997 	{
3998 		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
3999 	}
4000 
4001 	/* Draw with each routine combination */
4002 	for (GLuint i = 0; i < n_subroutine_combinations; ++i)
4003 	{
4004 		Utils::vec4<GLfloat> first_routine_result;
4005 		Utils::vec4<GLfloat> second_routine_result;
4006 		Utils::vec4<GLfloat> third_routine_result;
4007 		Utils::vec4<GLuint>  fourth_routine_result;
4008 
4009 		testDraw(subroutine_combinations[i], input_data, first_routine_result, second_routine_result,
4010 				 third_routine_result, fourth_routine_result);
4011 
4012 		if (false == verify(first_routine_result, second_routine_result, third_routine_result, fourth_routine_result,
4013 							expected_result_from_first_routine[subroutine_combinations[i][0]],
4014 							expected_result_from_second_routine[subroutine_combinations[i][1]],
4015 							expected_result_from_third_routine[subroutine_combinations[i][2]],
4016 							expected_result_from_fourth_routine[subroutine_combinations[i][3]]))
4017 		{
4018 			logError(subroutine_names, subroutine_combinations[i], input_data, first_routine_result,
4019 					 second_routine_result, third_routine_result, fourth_routine_result,
4020 					 expected_result_from_first_routine[subroutine_combinations[i][0]],
4021 					 expected_result_from_second_routine[subroutine_combinations[i][1]],
4022 					 expected_result_from_third_routine[subroutine_combinations[i][2]],
4023 					 expected_result_from_fourth_routine[subroutine_combinations[i][3]]);
4024 
4025 			result = false;
4026 		}
4027 	}
4028 
4029 	/* Done */
4030 	if (true == result)
4031 	{
4032 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4033 	}
4034 	else
4035 	{
4036 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4037 	}
4038 
4039 	return tcu::TestNode::STOP;
4040 }
4041 
4042 /** Log error message
4043  *
4044  * @param subroutine_names               Array of subroutine names
4045  * @param subroutine_combination         Combination of subroutines
4046  * @param input_data                     Input data
4047  * @param first_routine_result           Result of first routine
4048  * @param second_routine_result          Result of second routine
4049  * @param third_routine_result           Result of third routine
4050  * @param fourth_routine_result          Result of fourth routine
4051  * @param first_routine_expected_result  Expected result of first routine
4052  * @param second_routine_expected_result Expected result of second routine
4053  * @param third_routine_expected_result  Expected result of third routine
4054  * @param fourth_routine_expected_result Expected result of fourth routine
4055  **/
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) const4056 void FunctionalTest5::logError(const glw::GLchar* subroutine_names[4][2], const glw::GLuint subroutine_combination[4],
4057 							   const Utils::vec4<glw::GLfloat>  input_data[3],
4058 							   const Utils::vec4<glw::GLfloat>& first_routine_result,
4059 							   const Utils::vec4<glw::GLfloat>& second_routine_result,
4060 							   const Utils::vec4<glw::GLfloat>& third_routine_result,
4061 							   const Utils::vec4<glw::GLuint>&  fourth_routine_result,
4062 							   const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
4063 							   const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
4064 							   const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
4065 							   const Utils::vec4<glw::GLuint>&  fourth_routine_expected_result) const
4066 {
4067 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4068 										<< tcu::TestLog::EndMessage;
4069 
4070 	tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4071 
4072 	message << "Function: " << subroutine_names[0][subroutine_combination[0]] << "( ";
4073 	input_data[0].log(message);
4074 	message << ", ";
4075 	input_data[1].log(message);
4076 	message << " ). Result: ";
4077 	first_routine_result.log(message);
4078 	message << ". Expected: ";
4079 	first_routine_expected_result.log(message);
4080 
4081 	message << tcu::TestLog::EndMessage;
4082 
4083 	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4084 
4085 	message << "Function: " << subroutine_names[1][subroutine_combination[1]] << "( ";
4086 	input_data[0].log(message);
4087 	message << " ). Result: ";
4088 	second_routine_result.log(message);
4089 	message << ". Expected: ";
4090 	second_routine_expected_result.log(message);
4091 
4092 	message << tcu::TestLog::EndMessage;
4093 
4094 	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4095 
4096 	message << "Function: " << subroutine_names[2][subroutine_combination[2]] << "( ";
4097 	input_data[0].log(message);
4098 	message << ", ";
4099 	input_data[1].log(message);
4100 	message << ", ";
4101 	input_data[2].log(message);
4102 	message << "). Result: ";
4103 	third_routine_result.log(message);
4104 	message << ". Expected: ";
4105 	third_routine_expected_result.log(message);
4106 
4107 	message << tcu::TestLog::EndMessage;
4108 
4109 	message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4110 
4111 	message << "Function: " << subroutine_names[3][subroutine_combination[3]] << "( ";
4112 	input_data[0].log(message);
4113 	message << ", ";
4114 	input_data[1].log(message);
4115 	message << ", ";
4116 	message << " ). Result: ";
4117 	fourth_routine_result.log(message);
4118 	message << ". Expected: ";
4119 	fourth_routine_expected_result.log(message);
4120 
4121 	message << tcu::TestLog::EndMessage;
4122 }
4123 
4124 /** Execute draw call and capture results
4125  *
4126  * @param subroutine_combination    Combination of subroutines
4127  * @param input_data                Input data
4128  * @param out_first_routine_result  Result of first routine
4129  * @param out_second_routine_result Result of second routine
4130  * @param out_third_routine_result  Result of third routine
4131  * @param out_fourth_routine_result Result of fourth routine
4132  **/
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) const4133 void FunctionalTest5::testDraw(const glw::GLuint			   subroutine_combination[4],
4134 							   const Utils::vec4<glw::GLfloat> input_data[3],
4135 							   Utils::vec4<glw::GLfloat>&	  out_first_routine_result,
4136 							   Utils::vec4<glw::GLfloat>&	  out_second_routine_result,
4137 							   Utils::vec4<glw::GLfloat>&	  out_third_routine_result,
4138 							   Utils::vec4<glw::GLuint>&	   out_fourth_routine_result) const
4139 {
4140 	static const GLuint   n_uniforms = sizeof(m_uniform_locations) / sizeof(m_uniform_locations[0]);
4141 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
4142 	GLuint				  subroutine_indices[4];
4143 	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
4144 
4145 	/* Prepare subroutine uniform data */
4146 	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
4147 	{
4148 		const GLuint location = m_subroutine_uniform_locations[i][0];
4149 
4150 		subroutine_indices[location] = m_subroutine_indices[i][subroutine_combination[i]];
4151 	}
4152 
4153 	/* Set up subroutine uniforms */
4154 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
4155 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
4156 
4157 	/* Set up input data uniforms */
4158 	for (GLuint i = 0; i < n_uniforms; ++i)
4159 	{
4160 		gl.uniform4f(m_uniform_locations[i], input_data[i].m_x, input_data[i].m_y, input_data[i].m_z,
4161 					 input_data[i].m_w);
4162 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4163 	}
4164 
4165 	/* Execute draw call with transform feedback */
4166 	gl.beginTransformFeedback(GL_POINTS);
4167 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4168 
4169 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4170 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4171 
4172 	gl.endTransformFeedback();
4173 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4174 
4175 	/* Capture results */
4176 	GLvoid* feedback_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4177 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4178 
4179 	GLfloat* float_ptr = (GLfloat*)feedback_data;
4180 
4181 	/* First result */
4182 	out_first_routine_result.m_x = float_ptr[0];
4183 	out_first_routine_result.m_y = float_ptr[1];
4184 	out_first_routine_result.m_z = float_ptr[2];
4185 	out_first_routine_result.m_w = float_ptr[3];
4186 
4187 	/* Second result */
4188 	out_second_routine_result.m_x = float_ptr[4];
4189 	out_second_routine_result.m_y = float_ptr[5];
4190 	out_second_routine_result.m_z = float_ptr[6];
4191 	out_second_routine_result.m_w = float_ptr[7];
4192 
4193 	/* Third result */
4194 	out_third_routine_result.m_x = float_ptr[8];
4195 	out_third_routine_result.m_y = float_ptr[9];
4196 	out_third_routine_result.m_z = float_ptr[10];
4197 	out_third_routine_result.m_w = float_ptr[11];
4198 
4199 	/* Fourth result */
4200 	GLuint* uint_ptr			  = (GLuint*)(float_ptr + 12);
4201 	out_fourth_routine_result.m_x = uint_ptr[0];
4202 	out_fourth_routine_result.m_y = uint_ptr[1];
4203 	out_fourth_routine_result.m_z = uint_ptr[2];
4204 	out_fourth_routine_result.m_w = uint_ptr[3];
4205 
4206 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4207 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4208 }
4209 
4210 /** Verify if results match expected results
4211  *
4212  * @param first_routine_result           Result of first routine
4213  * @param second_routine_result          Result of second routine
4214  * @param third_routine_result           Result of third routine
4215  * @param fourth_routine_result          Result of fourth routine
4216  * @param first_routine_expected_result  Expected result of first routine
4217  * @param second_routine_expected_result Expected result of second routine
4218  * @param third_routine_expected_result  Expected result of third routine
4219  * @param fourth_routine_expected_result Expected result of fourth routine
4220  **/
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) const4221 bool FunctionalTest5::verify(const Utils::vec4<glw::GLfloat>& first_routine_result,
4222 							 const Utils::vec4<glw::GLfloat>& second_routine_result,
4223 							 const Utils::vec4<glw::GLfloat>& third_routine_result,
4224 							 const Utils::vec4<glw::GLuint>&  fourth_routine_result,
4225 							 const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
4226 							 const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
4227 							 const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
4228 							 const Utils::vec4<glw::GLuint>&  fourth_routine_expected_result) const
4229 {
4230 	bool result = true;
4231 
4232 	result = result && (first_routine_result == first_routine_expected_result);
4233 	result = result && (second_routine_result == second_routine_expected_result);
4234 	result = result && (third_routine_result == third_routine_expected_result);
4235 	result = result && (fourth_routine_result == fourth_routine_expected_result);
4236 
4237 	return result;
4238 }
4239 
4240 /** Constructor
4241  *
4242  * @param context CTS context
4243  **/
FunctionalTest6(deqp::Context & context)4244 FunctionalTest6::FunctionalTest6(deqp::Context& context)
4245 	: TestCase(context, "static_subroutine_call", "Verify that subroutine can be called in a static manner")
4246 {
4247 }
4248 
4249 /** Execute test
4250  *
4251  * @return tcu::TestNode::STOP
4252  **/
iterate()4253 tcu::TestNode::IterateResult FunctionalTest6::iterate()
4254 {
4255 	static const GLchar* vertex_shader_code = "#version 400 core\n"
4256 											  "#extension GL_ARB_shader_subroutine : require\n"
4257 											  "\n"
4258 											  "precision highp float;\n"
4259 											  "\n"
4260 											  "// Subroutine type\n"
4261 											  "subroutine vec4 routine_type(in vec4 iparam);\n"
4262 											  "\n"
4263 											  "// Subroutine definition\n"
4264 											  "subroutine(routine_type) vec4 square(in vec4 iparam)\n"
4265 											  "{\n"
4266 											  "    return iparam * iparam;\n"
4267 											  "}\n"
4268 											  "\n"
4269 											  "// Sub routine uniform\n"
4270 											  "subroutine uniform routine_type routine;\n"
4271 											  "\n"
4272 											  "// Input data\n"
4273 											  "uniform vec4 input_data;\n"
4274 											  "\n"
4275 											  "// Output\n"
4276 											  "out  vec4 out_result;\n"
4277 											  "\n"
4278 											  "void main()\n"
4279 											  "{\n"
4280 											  "    out_result  = square(input_data);\n"
4281 											  "}\n"
4282 											  "\n";
4283 
4284 	static const GLchar* varying_name = "out_result";
4285 
4286 	/* Test data */
4287 	static const Utils::vec4<GLfloat> input_data(1.0f, 4.0f, 9.0f, 16.0f);
4288 
4289 	static const Utils::vec4<GLfloat> expected_result(1.0f, 16.0f, 81.0f, 256.0f);
4290 
4291 	static const GLuint transform_feedback_buffer_size = 4 * sizeof(GLfloat);
4292 
4293 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
4294 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
4295 	{
4296 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
4297 	}
4298 
4299 	/* GL objects */
4300 	Utils::program	 program(m_context);
4301 	Utils::buffer	  transform_feedback_buffer(m_context);
4302 	Utils::vertexArray vao(m_context);
4303 
4304 	/* Init GL objects */
4305 	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name,
4306 				  1 /* n_varyings */);
4307 
4308 	program.use();
4309 
4310 	vao.generate();
4311 	vao.bind();
4312 
4313 	transform_feedback_buffer.generate();
4314 	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
4315 									 GL_DYNAMIC_COPY);
4316 	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
4317 
4318 	/* Test */
4319 	{
4320 		const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
4321 		const GLint			  uniform_location = gl.getUniformLocation(program.m_program_object_id, "input_data");
4322 
4323 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
4324 
4325 		if (-1 == uniform_location)
4326 		{
4327 			TCU_FAIL("Uniform is not available");
4328 		}
4329 
4330 		/* Set up input data uniforms */
4331 		gl.uniform4f(uniform_location, input_data.m_x, input_data.m_y, input_data.m_z, input_data.m_w);
4332 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4333 
4334 		/* Execute draw call with transform feedback */
4335 		gl.beginTransformFeedback(GL_POINTS);
4336 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4337 
4338 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4339 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4340 
4341 		gl.endTransformFeedback();
4342 		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4343 
4344 		/* Capture results */
4345 		GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4346 		GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4347 
4348 		Utils::vec4<GLfloat> result(feedback_data[0], feedback_data[1], feedback_data[2], feedback_data[3]);
4349 
4350 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4351 		GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4352 
4353 		/* Verify */
4354 		if (expected_result == result)
4355 		{
4356 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4357 		}
4358 		else
4359 		{
4360 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4361 												<< tcu::TestLog::EndMessage;
4362 
4363 			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4364 
4365 			message << "Function: square( ";
4366 			input_data.log(message);
4367 			message << " ). Result: ";
4368 			result.log(message);
4369 			message << ". Expected: ";
4370 			expected_result.log(message);
4371 
4372 			message << tcu::TestLog::EndMessage;
4373 
4374 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4375 		}
4376 	}
4377 
4378 	/* Done */
4379 	return tcu::TestNode::STOP;
4380 }
4381 
4382 /** Constructor
4383  *
4384  * @param context CTS context
4385  **/
FunctionalTest7_8(deqp::Context & context)4386 FunctionalTest7_8::FunctionalTest7_8(deqp::Context& context)
4387 	: TestCase(context, "arrayed_subroutine_uniforms", "Verify that subroutine can be called in a static manner")
4388 {
4389 }
4390 
4391 /** Execute test
4392  *
4393  * @return tcu::TestNode::STOP
4394  **/
iterate()4395 tcu::TestNode::IterateResult FunctionalTest7_8::iterate()
4396 {
4397 	static const GLchar* vertex_shader_code =
4398 		"#version 400 core\n"
4399 		"#extension GL_ARB_shader_subroutine : require\n"
4400 		"\n"
4401 		"precision highp float;\n"
4402 		"\n"
4403 		"// Subroutine type\n"
4404 		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
4405 		"\n"
4406 		"// Subroutine definitions\n"
4407 		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
4408 		"{\n"
4409 		"    return left + right;\n"
4410 		"}\n"
4411 		"\n"
4412 		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
4413 		"{\n"
4414 		"    return left * right;\n"
4415 		"}\n"
4416 		"\n"
4417 		"// Sub routine uniform\n"
4418 		"subroutine uniform routine_type routine[4];\n"
4419 		"\n"
4420 		"// Input data\n"
4421 		"uniform vec4  uni_left;\n"
4422 		"uniform vec4  uni_right;\n"
4423 		"uniform uvec4 uni_indices;\n"
4424 		"\n"
4425 		"// Output\n"
4426 		"out vec4 out_combined;\n"
4427 		"out vec4 out_combined_inverted;\n"
4428 		"out vec4 out_constant;\n"
4429 		"out vec4 out_constant_inverted;\n"
4430 		"out vec4 out_dynamic;\n"
4431 		"out vec4 out_dynamic_inverted;\n"
4432 		"out vec4 out_loop;\n"
4433 		"out uint out_array_length;\n"
4434 		"\n"
4435 		"void main()\n"
4436 		"{\n"
4437 		"    out_combined          = routine[3](routine[2](routine[1](routine[0](uni_left, uni_right), uni_right), "
4438 		"uni_right), uni_right);\n"
4439 		"    out_combined_inverted = routine[0](routine[1](routine[2](routine[3](uni_left, uni_right), uni_right), "
4440 		"uni_right), uni_right);\n"
4441 		"    \n"
4442 		"    out_constant          = routine[3](routine[2](routine[1](routine[0](vec4(1, 2, 3, 4), vec4(-5, -6, -7, "
4443 		"-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n"
4444 		"    out_constant_inverted = routine[0](routine[1](routine[2](routine[3](vec4(1, 2, 3, 4), vec4(-5, -6, -7, "
4445 		"-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n"
4446 		"    \n"
4447 		"    out_dynamic           = "
4448 		"routine[uni_indices.w](routine[uni_indices.z](routine[uni_indices.y](routine[uni_indices.x](uni_left, "
4449 		"uni_right), uni_right), uni_right), uni_right);\n"
4450 		"    out_dynamic_inverted  = "
4451 		"routine[uni_indices.x](routine[uni_indices.y](routine[uni_indices.z](routine[uni_indices.w](uni_left, "
4452 		"uni_right), uni_right), uni_right), uni_right);\n"
4453 		"    \n"
4454 		"    out_loop              = uni_left;\n"
4455 		"    for (uint i = 0u; i < routine.length(); ++i)\n"
4456 		"    {\n"
4457 		"        out_loop          = routine[i](out_loop, uni_right);\n"
4458 		"    }\n"
4459 		"    \n"
4460 		"    out_array_length      = routine.length() + 6 - (uni_indices.x + uni_indices.y + uni_indices.z + "
4461 		"uni_indices.w);\n"
4462 		"}\n"
4463 		"\n";
4464 
4465 	static const GLchar* subroutine_names[] = {
4466 		"add", "multiply",
4467 	};
4468 	static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
4469 
4470 	static const GLchar* subroutine_uniform_names[] = { "routine[0]", "routine[1]", "routine[2]", "routine[3]" };
4471 	static const GLuint  n_subroutine_uniform_names =
4472 		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
4473 
4474 	static const GLchar* uniform_names[] = {
4475 		"uni_left", "uni_right", "uni_indices",
4476 	};
4477 	static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
4478 
4479 	static const GLchar* varying_names[] = { "out_combined", "out_combined_inverted",
4480 											 "out_constant", "out_constant_inverted",
4481 											 "out_dynamic",  "out_dynamic_inverted",
4482 											 "out_loop",	 "out_array_length" };
4483 
4484 	static const GLuint n_varyings					   = sizeof(varying_names) / sizeof(varying_names[0]);
4485 	static const GLuint transform_feedback_buffer_size = n_varyings * 4 * sizeof(GLfloat);
4486 
4487 	/* Test data */
4488 	static const Utils::vec4<GLfloat> uni_left(-1.0f, 0.75f, -0.5f, 0.25f);
4489 	static const Utils::vec4<GLfloat> uni_right(1.0f, -0.75f, 0.5f, -0.25f);
4490 	static const Utils::vec4<GLuint>  uni_indices(1, 2, 0, 3);
4491 
4492 	static const GLuint subroutine_combinations[][4] = {
4493 		{ 0, 0, 0, 0 }, /* + + + + */
4494 		{ 0, 0, 0, 1 }, /* + + + * */
4495 		{ 0, 0, 1, 0 }, /* + + * + */
4496 		{ 0, 0, 1, 1 }, /* + + * * */
4497 		{ 0, 1, 0, 0 }, /* + * + + */
4498 		{ 0, 1, 0, 1 }, /* + * + * */
4499 		{ 0, 1, 1, 0 }, /* + * * + */
4500 		{ 0, 1, 1, 1 }, /* + * * * */
4501 		{ 1, 0, 0, 0 }, /* * + + + */
4502 		{ 1, 0, 0, 1 }, /* * + + * */
4503 		{ 1, 0, 1, 0 }, /* * + * + */
4504 		{ 1, 0, 1, 1 }, /* * + * * */
4505 		{ 1, 1, 0, 0 }, /* * * + + */
4506 		{ 1, 1, 0, 1 }, /* * * + * */
4507 		{ 1, 1, 1, 0 }, /* * * * + */
4508 		{ 1, 1, 1, 1 }  /* * * * * */
4509 	};
4510 	static const GLuint n_subroutine_combinations =
4511 		sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]);
4512 
4513 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
4514 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
4515 	{
4516 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
4517 	}
4518 
4519 	/* GL objects */
4520 	Utils::program	 program(m_context);
4521 	Utils::buffer	  transform_feedback_buffer(m_context);
4522 	Utils::vertexArray vao(m_context);
4523 
4524 	bool result = true;
4525 
4526 	/* Init GL objects */
4527 	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
4528 				  n_varyings);
4529 
4530 	program.use();
4531 
4532 	vao.generate();
4533 	vao.bind();
4534 
4535 	transform_feedback_buffer.generate();
4536 
4537 	/* Get subroutine indices */
4538 	for (GLuint routine = 0; routine < n_subroutine_names; ++routine)
4539 	{
4540 		m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER);
4541 	}
4542 
4543 	/* Get subroutine uniform locations */
4544 	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
4545 	{
4546 		m_subroutine_uniform_locations[uniform] =
4547 			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
4548 	}
4549 
4550 	/* Get uniform locations */
4551 	for (GLuint i = 0; i < n_uniform_names; ++i)
4552 	{
4553 		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
4554 	}
4555 
4556 	/* Test */
4557 	for (GLuint i = 0; i < n_subroutine_combinations; ++i)
4558 	{
4559 		/* Clean */
4560 		transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
4561 										 GL_DYNAMIC_COPY);
4562 		transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
4563 
4564 		/* Verify */
4565 		if (false == testDraw(subroutine_combinations[i], uni_left, uni_right, uni_indices))
4566 		{
4567 			result = false;
4568 		}
4569 	}
4570 
4571 	if (true == result)
4572 	{
4573 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4574 	}
4575 	else
4576 	{
4577 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4578 	}
4579 
4580 	/* Done */
4581 	return tcu::TestNode::STOP;
4582 }
4583 
4584 /* Calculate result of function applied to operands
4585  *
4586  * @param function Function id, 0 is sum, 1 is multiplication
4587  * @param left     Left operand
4588  * @param right    Right operand
4589  * @param out      Function result
4590  **/
calculate(glw::GLuint function,const Utils::vec4<glw::GLfloat> & left,const Utils::vec4<glw::GLfloat> & right,Utils::vec4<glw::GLfloat> & out) const4591 void FunctionalTest7_8::calculate(glw::GLuint function, const Utils::vec4<glw::GLfloat>& left,
4592 								  const Utils::vec4<glw::GLfloat>& right, Utils::vec4<glw::GLfloat>& out) const
4593 {
4594 	if (0 == function)
4595 	{
4596 		out.m_x = left.m_x + right.m_x;
4597 		out.m_y = left.m_y + right.m_y;
4598 		out.m_z = left.m_z + right.m_z;
4599 		out.m_w = left.m_w + right.m_w;
4600 	}
4601 	else
4602 	{
4603 		out.m_x = left.m_x * right.m_x;
4604 		out.m_y = left.m_y * right.m_y;
4605 		out.m_z = left.m_z * right.m_z;
4606 		out.m_w = left.m_w * right.m_w;
4607 	}
4608 }
4609 
4610 /** Calculate expected values for all operations
4611  *
4612  * @param combination           Function combination, first applied function is at index [0]
4613  * @param left                  Left operand
4614  * @param right                 Right operand
4615  * @param indices               Indices used by dynamic calls
4616  * @param out_combined          Expected result of "combined" operation
4617  * @param out_combined_inverted Expected result of "combined_inverted" operation
4618  * @param out_constant          Expected result of "constant" operation
4619  * @param out_constant_inverted Expected result of "constant_inverted" operation
4620  * @param out_dynamic           Expected result of "dynamic" operation
4621  * @param out_dynamic_inverted  Expected result of "out_dynamic_inverted" operation
4622  * @param out_loop              Expected result of "loop" operation
4623  **/
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) const4624 void FunctionalTest7_8::calculate(
4625 	const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, const Utils::vec4<glw::GLfloat>& right,
4626 	const Utils::vec4<glw::GLuint>& indices, Utils::vec4<glw::GLfloat>& out_combined,
4627 	Utils::vec4<glw::GLfloat>& out_combined_inverted, Utils::vec4<glw::GLfloat>& out_constant,
4628 	Utils::vec4<glw::GLfloat>& out_constant_inverted, Utils::vec4<glw::GLfloat>& out_dynamic,
4629 	Utils::vec4<glw::GLfloat>& out_dynamic_inverted, Utils::vec4<glw::GLfloat>& out_loop) const
4630 {
4631 	/* Indices used by "dynamic" operations, range <0..4> */
4632 	const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y],
4633 											combination[indices.m_z], combination[indices.m_w] };
4634 
4635 	/* Values used by "constant" operations, come from shader code */
4636 	const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4),
4637 														  Utils::vec4<glw::GLfloat>(-5, -6, -7, -8),
4638 														  Utils::vec4<glw::GLfloat>(-1, -2, -3, -4),
4639 														  Utils::vec4<glw::GLfloat>(5, 6, 7, 8),
4640 														  Utils::vec4<glw::GLfloat>(1, 2, 3, 4) };
4641 
4642 	/* Start values */
4643 	Utils::vec4<glw::GLfloat> combined			= left;
4644 	Utils::vec4<glw::GLfloat> combined_inverted = left;
4645 	Utils::vec4<glw::GLfloat> constant			= constant_values[0];
4646 	Utils::vec4<glw::GLfloat> constant_inverted = constant_values[0];
4647 	Utils::vec4<glw::GLfloat> dynamic			= left;
4648 	Utils::vec4<glw::GLfloat> dynamic_inverted  = left;
4649 
4650 	/* Calculate expected results */
4651 	for (GLuint i = 0; i < 4; ++i)
4652 	{
4653 		GLuint function					 = combination[i];
4654 		GLuint function_inverted		 = combination[3 - i];
4655 		GLuint dynamic_function			 = dynamic_combination[i];
4656 		GLuint dynamic_function_inverted = dynamic_combination[3 - i];
4657 
4658 		calculate(function, combined, right, combined);
4659 		calculate(function_inverted, combined_inverted, right, combined_inverted);
4660 		calculate(function, constant, constant_values[i + 1], constant);
4661 		calculate(function_inverted, constant_inverted, constant_values[i + 1], constant_inverted);
4662 		calculate(dynamic_function, dynamic, right, dynamic);
4663 		calculate(dynamic_function_inverted, dynamic_inverted, right, dynamic_inverted);
4664 	}
4665 
4666 	/* Store results */
4667 	out_combined		  = combined;
4668 	out_combined_inverted = combined_inverted;
4669 	out_constant		  = constant;
4670 	out_constant_inverted = constant_inverted;
4671 	out_dynamic			  = dynamic;
4672 	out_dynamic_inverted  = dynamic_inverted;
4673 	out_loop			  = combined;
4674 }
4675 
4676 /** Log error
4677  *
4678  * @param combination   Operations combination
4679  * @param left          Left operand
4680  * @param right         Right operand
4681  * @param indices       Inidices used by "dynamic" calls
4682  * @param vec4_expected Expected results
4683  * @param vec4_result   Results
4684  * @param array_length  Length of array
4685  * @param result        Comparison results
4686  **/
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]) const4687 void FunctionalTest7_8::logError(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
4688 								 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices,
4689 								 const Utils::vec4<glw::GLfloat> vec4_expected[7],
4690 								 const Utils::vec4<glw::GLfloat> vec4_result[7], glw::GLuint array_length,
4691 								 bool result[7]) const
4692 {
4693 	static const GLuint n_functions  = 4;
4694 	static const GLuint n_operations = 7;
4695 
4696 	/* Indices used by "dynamic" operations, range <0..4> */
4697 	const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y],
4698 											combination[indices.m_z], combination[indices.m_w] };
4699 
4700 	/* Function symbols */
4701 	GLchar functions[4];
4702 	GLchar functions_inverted[4];
4703 	GLchar functions_dynamic[4];
4704 	GLchar functions_dynamic_inverted[4];
4705 
4706 	for (GLuint i = 0; i < n_functions; ++i)
4707 	{
4708 		GLchar function			= (0 == combination[i]) ? '+' : '*';
4709 		GLchar dynamic_function = (0 == dynamic_combination[i]) ? '+' : '*';
4710 
4711 		functions[i]									= function;
4712 		functions_inverted[n_functions - i - 1]			= function;
4713 		functions_dynamic[i]							= dynamic_function;
4714 		functions_dynamic_inverted[n_functions - i - 1] = dynamic_function;
4715 	}
4716 
4717 	/* Values used by "constant" operations, come from shader code */
4718 	const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4),
4719 														  Utils::vec4<glw::GLfloat>(-5, -6, -7, -8),
4720 														  Utils::vec4<glw::GLfloat>(-1, -2, -3, -4),
4721 														  Utils::vec4<glw::GLfloat>(5, 6, 7, 8),
4722 														  Utils::vec4<glw::GLfloat>(1, 2, 3, 4) };
4723 
4724 	/* Values used by non-"constant" operations */
4725 	Utils::vec4<glw::GLfloat> dynamic_values[5];
4726 	dynamic_values[0] = left;
4727 	dynamic_values[1] = right;
4728 	dynamic_values[2] = right;
4729 	dynamic_values[3] = right;
4730 	dynamic_values[4] = right;
4731 
4732 	/* For each operation */
4733 	for (GLuint i = 0; i < n_operations; ++i)
4734 	{
4735 		/* If result is failure */
4736 		if (false == result[i])
4737 		{
4738 			const GLchar*					 description = 0;
4739 			const Utils::vec4<glw::GLfloat>* input		 = 0;
4740 			const GLchar*					 operation   = 0;
4741 
4742 			switch (i)
4743 			{
4744 			case 0:
4745 				description = "Call made with predefined array indices";
4746 				input		= dynamic_values;
4747 				operation   = functions;
4748 				break;
4749 			case 1:
4750 				description = "Call made with predefined array indices in inverted order";
4751 				input		= dynamic_values;
4752 				operation   = functions_inverted;
4753 				break;
4754 			case 2:
4755 				description = "Call made with predefined array indices, for constant values";
4756 				input		= constant_values;
4757 				operation   = functions;
4758 				break;
4759 			case 3:
4760 				description = "Call made with predefined array indices in inverted order, for constant values";
4761 				input		= constant_values;
4762 				operation   = functions_inverted;
4763 				break;
4764 			case 4:
4765 				description = "Call made with dynamic array indices";
4766 				input		= dynamic_values;
4767 				operation   = functions_dynamic;
4768 				break;
4769 			case 5:
4770 				description = "Call made with dynamic array indices in inverted order";
4771 				input		= dynamic_values;
4772 				operation   = functions_dynamic_inverted;
4773 				break;
4774 			case 6:
4775 				description = "Call made with loop";
4776 				input		= dynamic_values;
4777 				operation   = functions;
4778 				break;
4779 			}
4780 
4781 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4782 												<< tcu::TestLog::EndMessage;
4783 
4784 			m_context.getTestContext().getLog() << tcu::TestLog::Message << description << tcu::TestLog::EndMessage;
4785 
4786 			tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4787 
4788 			message << "Operation: ((((";
4789 			input[0].log(message);
4790 			for (GLuint function = 0; function < n_functions; ++function)
4791 			{
4792 				message << " " << operation[function] << " ";
4793 
4794 				input[function + 1].log(message);
4795 
4796 				message << ")";
4797 			}
4798 
4799 			message << tcu::TestLog::EndMessage;
4800 
4801 			message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4802 
4803 			message << "Result: ";
4804 			vec4_result[i].log(message);
4805 
4806 			message << tcu::TestLog::EndMessage;
4807 
4808 			message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4809 
4810 			message << "Expected: ";
4811 			vec4_expected[i].log(message);
4812 
4813 			message << tcu::TestLog::EndMessage;
4814 		}
4815 
4816 		/* Check array length, it should be 4 */
4817 		if (4 != array_length)
4818 		{
4819 			m_context.getTestContext().getLog() << tcu::TestLog::Message
4820 												<< "Error. Invalid array length: " << array_length << ". Expected 4."
4821 												<< tcu::TestLog::EndMessage;
4822 		}
4823 	}
4824 }
4825 
4826 /** Execute draw call and verifies captrued varyings
4827  *
4828  * @param combination           Function combination, first applied function is at index [0]
4829  * @param left                  Left operand
4830  * @param right                 Right operand
4831  * @param indices               Indices used by dynamic calls
4832  *
4833  * @return true if all results match expected values, false otherwise
4834  **/
testDraw(const glw::GLuint combination[4],const Utils::vec4<glw::GLfloat> & left,const Utils::vec4<glw::GLfloat> & right,const Utils::vec4<glw::GLuint> & indices) const4835 bool FunctionalTest7_8::testDraw(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
4836 								 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices) const
4837 {
4838 	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
4839 	static const GLuint   n_vec4_varyings = 7;
4840 	bool				  result		  = true;
4841 	GLuint				  subroutine_indices[4];
4842 	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
4843 
4844 	/* Prepare expected results */
4845 	Utils::vec4<glw::GLfloat> expected_results[7];
4846 	calculate(combination, left, right, indices, expected_results[0], expected_results[1], expected_results[2],
4847 			  expected_results[3], expected_results[4], expected_results[5], expected_results[6]);
4848 
4849 	/* Set up input data uniforms */
4850 	gl.uniform4f(m_uniform_locations[0], left.m_x, left.m_y, left.m_z, left.m_w);
4851 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4852 
4853 	gl.uniform4f(m_uniform_locations[1], right.m_x, right.m_y, right.m_z, right.m_w);
4854 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4855 
4856 	gl.uniform4ui(m_uniform_locations[2], indices.m_x, indices.m_y, indices.m_z, indices.m_w);
4857 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4ui");
4858 
4859 	/* Prepare subroutine uniform data */
4860 	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
4861 	{
4862 		const GLuint location = m_subroutine_uniform_locations[i];
4863 
4864 		subroutine_indices[location] = m_subroutine_indices[combination[i]];
4865 	}
4866 
4867 	/* Set up subroutine uniforms */
4868 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
4869 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
4870 
4871 	/* Execute draw call with transform feedback */
4872 	gl.beginTransformFeedback(GL_POINTS);
4873 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4874 
4875 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4876 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4877 
4878 	gl.endTransformFeedback();
4879 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4880 
4881 	/* Capture results */
4882 	GLvoid* feedback_data = (GLvoid*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4883 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4884 
4885 	Utils::vec4<GLfloat> vec4_results[7];
4886 	bool				 results[7];
4887 	GLfloat*			 float_data = (GLfloat*)feedback_data;
4888 	for (GLuint i = 0; i < n_vec4_varyings; ++i)
4889 	{
4890 		vec4_results[i].m_x = float_data[i * 4 + 0];
4891 		vec4_results[i].m_y = float_data[i * 4 + 1];
4892 		vec4_results[i].m_z = float_data[i * 4 + 2];
4893 		vec4_results[i].m_w = float_data[i * 4 + 3];
4894 	}
4895 
4896 	GLuint* uint_data	= (GLuint*)(float_data + (n_vec4_varyings)*4);
4897 	GLuint  array_length = uint_data[0];
4898 
4899 	/* Unmap buffer */
4900 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4901 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4902 
4903 	/* Verification */
4904 	for (GLuint i = 0; i < n_vec4_varyings; ++i)
4905 	{
4906 		results[i] = (vec4_results[i] == expected_results[i]);
4907 		result	 = result && results[i];
4908 	}
4909 
4910 	result = result && (4 == array_length);
4911 
4912 	/* Log error if any */
4913 	if (false == result)
4914 	{
4915 		logError(combination, left, right, indices, expected_results, vec4_results, array_length, results);
4916 	}
4917 
4918 	/* Done */
4919 	return result;
4920 }
4921 
4922 /** Constructor.
4923  *
4924  *  @param context Rendering context.
4925  *
4926  **/
FunctionalTest9(deqp::Context & context)4927 FunctionalTest9::FunctionalTest9(deqp::Context& context)
4928 	: TestCase(context, "subroutines_3_subroutine_types_and_subroutine_uniforms_one_function",
4929 			   "Makes sure that program with one function associated with 3 different "
4930 			   "subroutine types and 3 subroutine uniforms using that function compiles "
4931 			   "and works as expected")
4932 	, m_has_test_passed(true)
4933 	, m_n_points_to_draw(16) /* arbitrary value */
4934 	, m_po_id(0)
4935 	, m_vao_id(0)
4936 	, m_vs_id(0)
4937 	, m_xfb_bo_id(0)
4938 {
4939 	/* Left blank intentionally */
4940 }
4941 
4942 /** De-initializes GL objects that may have been created during test execution. */
deinit()4943 void FunctionalTest9::deinit()
4944 {
4945 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4946 
4947 	if (m_po_id != 0)
4948 	{
4949 		gl.deleteProgram(m_po_id);
4950 
4951 		m_po_id = 0;
4952 	}
4953 
4954 	if (m_vao_id != 0)
4955 	{
4956 		gl.deleteVertexArrays(1, &m_vao_id);
4957 
4958 		m_vao_id = 0;
4959 	}
4960 
4961 	if (m_vs_id != 0)
4962 	{
4963 		gl.deleteShader(m_vs_id);
4964 
4965 		m_vs_id = 0;
4966 	}
4967 
4968 	if (m_xfb_bo_id != 0)
4969 	{
4970 		gl.deleteBuffers(1, &m_xfb_bo_id);
4971 
4972 		m_xfb_bo_id = 0;
4973 	}
4974 }
4975 
4976 /** Retrieves body of a vertex shader that should be used
4977  *  for the testing purposes.
4978  **/
getVertexShaderBody() const4979 std::string FunctionalTest9::getVertexShaderBody() const
4980 {
4981 	return "#version 400\n"
4982 		   "\n"
4983 		   "#extension GL_ARB_shader_subroutine : require\n"
4984 		   "\n"
4985 		   "subroutine void subroutineType1(inout float);\n"
4986 		   "subroutine void subroutineType2(inout float);\n"
4987 		   "subroutine void subroutineType3(inout float);\n"
4988 		   "\n"
4989 		   "subroutine(subroutineType1, subroutineType2, subroutineType3) void function(inout float result)\n"
4990 		   "{\n"
4991 		   "    result += float(0.123) + float(gl_VertexID);\n"
4992 		   "}\n"
4993 		   "\n"
4994 		   "subroutine uniform subroutineType1 subroutine_uniform1;\n"
4995 		   "subroutine uniform subroutineType2 subroutine_uniform2;\n"
4996 		   "subroutine uniform subroutineType3 subroutine_uniform3;\n"
4997 		   "\n"
4998 		   "out vec4 result;\n"
4999 		   "\n"
5000 		   "void main()\n"
5001 		   "{\n"
5002 		   "    result = vec4(0, 1, 2, 3);\n"
5003 		   "\n"
5004 		   "    subroutine_uniform1(result.x);\n"
5005 		   "    subroutine_uniform2(result.y);\n"
5006 		   "    subroutine_uniform3(result.z);\n"
5007 		   "\n"
5008 		   "    result.w += result.x + result.y + result.z;\n"
5009 		   "}\n";
5010 }
5011 
5012 /** Initializes all GL objects required to run the test. */
initTest()5013 void FunctionalTest9::initTest()
5014 {
5015 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5016 
5017 	/* Set up program object */
5018 	const char* xfb_varyings[] = { "result" };
5019 
5020 	const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
5021 	if (!Utils::buildProgram(gl, getVertexShaderBody(), "",					  /* tc_body */
5022 							 "",											  /* te_body */
5023 							 "",											  /* gs_body */
5024 							 "",											  /* fs_body */
5025 							 xfb_varyings, n_xfb_varyings, &m_vs_id, DE_NULL, /* out_tc_id */
5026 							 DE_NULL,										  /* out_te_id */
5027 							 DE_NULL,										  /* out_gs_id */
5028 							 DE_NULL,										  /* out_fs_id */
5029 							 &m_po_id))
5030 	{
5031 		TCU_FAIL("Program failed to link successfully");
5032 	}
5033 
5034 	/* Set up a buffer object we will use to hold XFB data */
5035 	const unsigned int xfb_bo_size = static_cast<unsigned int>(sizeof(float) * 4 /* components */ * m_n_points_to_draw);
5036 
5037 	gl.genBuffers(1, &m_xfb_bo_id);
5038 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
5039 
5040 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
5041 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
5042 
5043 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
5044 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
5045 
5046 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL, /* data */
5047 				  GL_STATIC_COPY);
5048 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
5049 
5050 	/* Generate & bind a VAO */
5051 	gl.genVertexArrays(1, &m_vao_id);
5052 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
5053 
5054 	gl.bindVertexArray(m_vao_id);
5055 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
5056 }
5057 
5058 /** Executes test iteration.
5059  *
5060  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
5061  */
iterate()5062 tcu::TestNode::IterateResult FunctionalTest9::iterate()
5063 {
5064 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5065 
5066 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5067 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5068 	{
5069 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5070 	}
5071 	initTest();
5072 
5073 	/* Issue a draw call to make use of the three subroutine uniforms that we've defined */
5074 	gl.useProgram(m_po_id);
5075 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
5076 
5077 	gl.beginTransformFeedback(GL_POINTS);
5078 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
5079 	{
5080 		gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw);
5081 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
5082 	}
5083 	gl.endTransformFeedback();
5084 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
5085 
5086 	/* Map the XFB BO storage into process space */
5087 	const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5088 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
5089 
5090 	verifyXFBData(xfb_data_ptr);
5091 
5092 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5093 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
5094 
5095 	/* All done */
5096 	if (m_has_test_passed)
5097 	{
5098 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5099 	}
5100 	else
5101 	{
5102 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5103 	}
5104 
5105 	return STOP;
5106 }
5107 
5108 /** Verifies the data XFBed out by the vertex shader. Should the data
5109  *  be found invalid, m_has_test_passed will be set to false.
5110  *
5111  *  @param data_ptr XFB data.
5112  **/
verifyXFBData(const glw::GLvoid * data_ptr)5113 void FunctionalTest9::verifyXFBData(const glw::GLvoid* data_ptr)
5114 {
5115 	const float			epsilon			= 1e-5f;
5116 	bool				should_continue = true;
5117 	const glw::GLfloat* traveller_ptr   = (const glw::GLfloat*)data_ptr;
5118 
5119 	for (unsigned int n_point = 0; n_point < m_n_points_to_draw && should_continue; ++n_point)
5120 	{
5121 		tcu::Vec4 expected_result(0, 1, 2, 3);
5122 
5123 		for (unsigned int n_component = 0; n_component < 3 /* xyz */; ++n_component)
5124 		{
5125 			expected_result[n_component] += 0.123f + float(n_point);
5126 		}
5127 
5128 		expected_result[3 /* w */] += expected_result[0] + expected_result[1] + expected_result[2];
5129 
5130 		if (de::abs(expected_result[0] - traveller_ptr[0]) > epsilon ||
5131 			de::abs(expected_result[1] - traveller_ptr[1]) > epsilon ||
5132 			de::abs(expected_result[2] - traveller_ptr[2]) > epsilon ||
5133 			de::abs(expected_result[3] - traveller_ptr[3]) > epsilon)
5134 		{
5135 			m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data is invalid. Expected:"
5136 														   "("
5137 							   << expected_result[0] << ", " << expected_result[1] << ", " << expected_result[2] << ", "
5138 							   << expected_result[3] << "), found:(" << traveller_ptr[0] << ", " << traveller_ptr[1]
5139 							   << ", " << traveller_ptr[2] << ", " << traveller_ptr[3] << ")."
5140 							   << tcu::TestLog::EndMessage;
5141 
5142 			m_has_test_passed = false;
5143 			should_continue   = false;
5144 		}
5145 
5146 		traveller_ptr += 4; /* xyzw */
5147 	}						/* for (all rendered points) */
5148 }
5149 
5150 /** Constructor
5151  *
5152  * @param context CTS context
5153  **/
FunctionalTest10(deqp::Context & context)5154 FunctionalTest10::FunctionalTest10(deqp::Context& context)
5155 	: TestCase(context, "arrays_of_arrays_of_uniforms", "Verify that arrays of arrays of uniforms works as expected")
5156 {
5157 }
5158 
5159 /** Execute test
5160  *
5161  * @return tcu::TestNode::STOP
5162  **/
iterate()5163 tcu::TestNode::IterateResult FunctionalTest10::iterate()
5164 {
5165 	static const GLchar* vertex_shader_code = "#version 400 core\n"
5166 											  "#extension GL_ARB_arrays_of_arrays  : require\n"
5167 											  "#extension GL_ARB_shader_subroutine : require\n"
5168 											  "\n"
5169 											  "precision highp float;\n"
5170 											  "\n"
5171 											  "// Subroutine type\n"
5172 											  "subroutine int routine_type(in int iparam);\n"
5173 											  "\n"
5174 											  "// Subroutine definitions\n"
5175 											  "subroutine(routine_type) int increment(in int iparam)\n"
5176 											  "{\n"
5177 											  "    return iparam + 1;\n"
5178 											  "}\n"
5179 											  "\n"
5180 											  "subroutine(routine_type) int decrement(in int iparam)\n"
5181 											  "{\n"
5182 											  "    return iparam - 1;\n"
5183 											  "}\n"
5184 											  "\n"
5185 											  "// Sub routine uniform\n"
5186 											  "subroutine uniform routine_type routine[4][4];\n"
5187 											  "\n"
5188 											  "// Output\n"
5189 											  "out int out_result;\n"
5190 											  "\n"
5191 											  "void main()\n"
5192 											  "{\n"
5193 											  "    int result = 0;\n"
5194 											  "    \n"
5195 											  "    for (uint j = 0; j < routine.length(); ++j)\n"
5196 											  "    {\n"
5197 											  "        for (uint i = 0; i < routine[j].length(); ++i)\n"
5198 											  "        {\n"
5199 											  "            result = routine[j][i](result);\n"
5200 											  "        }\n"
5201 											  "    }\n"
5202 											  "    \n"
5203 											  "    out_result = result;\n"
5204 											  "}\n"
5205 											  "\n";
5206 
5207 	static const GLchar* subroutine_names[] = {
5208 		"increment", "decrement",
5209 	};
5210 	static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
5211 
5212 	static const GLchar* subroutine_uniform_names[] = {
5213 		"routine[0][0]", "routine[1][0]", "routine[2][0]", "routine[3][0]", "routine[0][1]", "routine[1][1]",
5214 		"routine[2][1]", "routine[3][1]", "routine[0][2]", "routine[1][2]", "routine[2][2]", "routine[3][2]",
5215 		"routine[0][3]", "routine[1][3]", "routine[2][3]", "routine[3][3]"
5216 	};
5217 	static const GLuint n_subroutine_uniform_names =
5218 		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
5219 
5220 	static const GLchar* varying_name					= "out_result";
5221 	static const GLuint  transform_feedback_buffer_size = sizeof(GLint);
5222 
5223 	static const GLuint configuration_increment[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5224 
5225 	static const GLuint configuration_decrement[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
5226 
5227 	static const GLuint configuration_mix[16] = { 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1 };
5228 
5229 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5230 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5231 	{
5232 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5233 	}
5234 
5235 	/* Do not execute the test if GL_ARB_arrays_of_arrays is not supported */
5236 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_arrays_of_arrays"))
5237 	{
5238 		throw tcu::NotSupportedError("GL_ARB_arrays_of_arrays is not supported.");
5239 	}
5240 
5241 	bool result = true;
5242 
5243 	/* GL objects */
5244 	Utils::program	 program(m_context);
5245 	Utils::buffer	  transform_feedback_buffer(m_context);
5246 	Utils::vertexArray vao(m_context);
5247 
5248 	/* Init GL objects */
5249 	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name,
5250 				  1 /* n_varyings */);
5251 
5252 	program.use();
5253 
5254 	vao.generate();
5255 	vao.bind();
5256 
5257 	transform_feedback_buffer.generate();
5258 	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
5259 									 GL_DYNAMIC_COPY);
5260 	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
5261 
5262 	/* Get subroutine indices */
5263 	for (GLuint routine = 0; routine < n_subroutine_names; ++routine)
5264 	{
5265 		m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER);
5266 	}
5267 
5268 	/* Get subroutine uniform locations */
5269 	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
5270 	{
5271 		m_subroutine_uniform_locations[uniform] =
5272 			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
5273 	}
5274 
5275 	/* Test */
5276 	GLint increment_result = testDraw(configuration_increment);
5277 	GLint decrement_result = testDraw(configuration_decrement);
5278 	GLint mix_result	   = testDraw(configuration_mix);
5279 
5280 	/* Verify */
5281 	if (16 != increment_result)
5282 	{
5283 		result = false;
5284 	}
5285 
5286 	if (-16 != decrement_result)
5287 	{
5288 		result = false;
5289 	}
5290 	if (0 != mix_result)
5291 	{
5292 		result = false;
5293 	}
5294 
5295 	/* Set test result */
5296 	if (true == result)
5297 	{
5298 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5299 	}
5300 	else
5301 	{
5302 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
5303 											<< " Incrementation applied 16 times: " << increment_result
5304 											<< ". Decrementation applied 16 times: " << decrement_result
5305 											<< ". Incrementation and decrementation applied 8 times: " << mix_result
5306 											<< tcu::TestLog::EndMessage;
5307 
5308 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5309 	}
5310 
5311 	/* Done */
5312 	return tcu::TestNode::STOP;
5313 }
5314 
5315 /** Execute draw call and return captured varying
5316  *
5317  * @param routine_indices Configuration of subroutine uniforms
5318  *
5319  * @return Value of varying captured with transform feedback
5320  **/
testDraw(const GLuint routine_indices[16]) const5321 GLint FunctionalTest10::testDraw(const GLuint routine_indices[16]) const
5322 {
5323 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5324 	GLuint				  subroutine_indices[16];
5325 	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
5326 
5327 	/* Prepare subroutine uniform data */
5328 	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
5329 	{
5330 		const GLuint location = m_subroutine_uniform_locations[i];
5331 
5332 		subroutine_indices[location] = m_subroutine_indices[routine_indices[i]];
5333 	}
5334 
5335 	/* Set up subroutine uniforms */
5336 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
5337 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
5338 
5339 	/* Execute draw call with transform feedback */
5340 	gl.beginTransformFeedback(GL_POINTS);
5341 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5342 
5343 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5344 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5345 
5346 	gl.endTransformFeedback();
5347 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5348 
5349 	/* Capture results */
5350 	GLint* feedback_data = (GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5351 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5352 
5353 	GLint result = feedback_data[0];
5354 
5355 	/* Unmap buffer */
5356 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5357 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5358 
5359 	return result;
5360 }
5361 
5362 /* Definitions of constants used by FunctionalTest11 */
5363 const GLuint FunctionalTest11::m_texture_height = 32;
5364 const GLuint FunctionalTest11::m_texture_width  = 32;
5365 
5366 /** Constructor
5367  *
5368  * @param context CTS context
5369  **/
FunctionalTest11(deqp::Context & context)5370 FunctionalTest11::FunctionalTest11(deqp::Context& context)
5371 	: TestCase(context, "globals_sampling_output_discard_function_calls", "Verify that global variables, texture "
5372 																		  "sampling, fragment output, fragment discard "
5373 																		  "and function calls work as expected")
5374 {
5375 }
5376 
5377 /** Execute test
5378  *
5379  * @return tcu::TestNode::STOP
5380  **/
iterate()5381 tcu::TestNode::IterateResult FunctionalTest11::iterate()
5382 {
5383 	static const GLchar* fragment_shader_code =
5384 		"#version 400 core\n"
5385 		"#extension GL_ARB_shader_subroutine : require\n"
5386 		"\n"
5387 		"precision highp float;\n"
5388 		"\n"
5389 		"// Output\n"
5390 		"layout(location = 0) out vec4 out_color;\n"
5391 		"\n"
5392 		"// Global variables\n"
5393 		"vec4 success_color;\n"
5394 		"vec4 failure_color;\n"
5395 		"\n"
5396 		"// Samplers\n"
5397 		"uniform sampler2D sampler_1;\n"
5398 		"uniform sampler2D sampler_2;\n"
5399 		"\n"
5400 		"// Functions\n"
5401 		"bool are_same(in vec4 left, in vec4 right)\n"
5402 		"{\n"
5403 		"    bvec4 result;\n"
5404 		"\n"
5405 		"    result.x = (left.x == right.x);\n"
5406 		"    result.y = (left.y == right.y);\n"
5407 		"    result.z = (left.z == right.z);\n"
5408 		"    result.w = (left.w == right.w);\n"
5409 		"\n"
5410 		"    return all(result);\n"
5411 		"}\n"
5412 		"\n"
5413 		"bool are_different(in vec4 left, in vec4 right)\n"
5414 		"{\n"
5415 		"    bvec4 result;\n"
5416 		"\n"
5417 		"    result.x = (left.x != right.x);\n"
5418 		"    result.y = (left.y != right.y);\n"
5419 		"    result.z = (left.z != right.z);\n"
5420 		"    result.w = (left.w != right.w);\n"
5421 		"\n"
5422 		"    return any(result);\n"
5423 		"}\n"
5424 		"\n"
5425 		"// Subroutine types\n"
5426 		"subroutine void discard_fragment_type(void);\n"
5427 		"subroutine void set_global_colors_type(void);\n"
5428 		"subroutine vec4 sample_texture_type(in vec2);\n"
5429 		"subroutine bool comparison_type(in vec4 left, in vec4 right);\n"
5430 		"subroutine void test_type(void);\n"
5431 		"\n"
5432 		"// Subroutine definitions\n"
5433 		"// discard_fragment_type\n"
5434 		"subroutine(discard_fragment_type) void discard_yes(void)\n"
5435 		"{\n"
5436 		"    discard;\n"
5437 		"}\n"
5438 		"\n"
5439 		"subroutine(discard_fragment_type) void discard_no(void)\n"
5440 		"{\n"
5441 		"}\n"
5442 		"\n"
5443 		"// set_global_colors_type\n"
5444 		"subroutine(set_global_colors_type) void red_pass_blue_fail(void)\n"
5445 		"{\n"
5446 		"    success_color = vec4(1, 0, 0, 1);\n"
5447 		"    failure_color = vec4(0, 0, 1, 1);\n"
5448 		"}\n"
5449 		"\n"
5450 		"subroutine(set_global_colors_type) void blue_pass_red_fail(void)\n"
5451 		"{\n"
5452 		"    success_color = vec4(0, 0, 1, 1);\n"
5453 		"    failure_color = vec4(1, 0, 0, 1);\n"
5454 		"}\n"
5455 		"\n"
5456 		"// sample_texture_type\n"
5457 		"subroutine(sample_texture_type) vec4 first_sampler(in vec2 coord)\n"
5458 		"{\n"
5459 		"    return texture(sampler_1, coord);\n"
5460 		"}\n"
5461 		"\n"
5462 		"subroutine(sample_texture_type) vec4 second_sampler(in vec2 coord)\n"
5463 		"{\n"
5464 		"    return texture(sampler_2, coord);\n"
5465 		"}\n"
5466 		"\n"
5467 		"// comparison_type\n"
5468 		"subroutine(comparison_type) bool check_equal(in vec4 left, in vec4 right)\n"
5469 		"{\n"
5470 		"    return are_same(left, right);\n"
5471 		"}\n"
5472 		"\n"
5473 		"subroutine(comparison_type) bool check_not_equal(in vec4 left, in vec4 right)\n"
5474 		"{\n"
5475 		"    return are_different(left, right);\n"
5476 		"}\n"
5477 		"\n"
5478 		"// Subroutine uniforms\n"
5479 		"subroutine uniform discard_fragment_type  discard_fragment;\n"
5480 		"subroutine uniform set_global_colors_type set_global_colors;\n"
5481 		"subroutine uniform sample_texture_type    sample_texture;\n"
5482 		"subroutine uniform comparison_type        compare;\n"
5483 		"\n"
5484 		"// Subroutine definitions\n"
5485 		"// test_type\n"
5486 		"subroutine(test_type) void test_with_discard(void)\n"
5487 		"{\n"
5488 		"    discard_fragment();"
5489 		"\n"
5490 		"    out_color = failure_color;\n"
5491 		"\n"
5492 		"    set_global_colors();\n"
5493 		"\n"
5494 		"    vec4 sampled_color = sample_texture(gl_PointCoord);\n"
5495 		"\n"
5496 		"    bool comparison_result = compare(success_color, sampled_color);\n"
5497 		"\n"
5498 		"    if (true == comparison_result)\n"
5499 		"    {\n"
5500 		"        out_color = success_color;\n"
5501 		"    }\n"
5502 		"    else\n"
5503 		"    {\n"
5504 		"        out_color = failure_color;\n"
5505 		"    }\n"
5506 		"}\n"
5507 		"\n"
5508 		"subroutine(test_type) void test_without_discard(void)\n"
5509 		"{\n"
5510 		"    set_global_colors();\n"
5511 		"\n"
5512 		"    vec4 sampled_color = sample_texture(gl_PointCoord);\n"
5513 		"\n"
5514 		"    bool comparison_result = compare(success_color, sampled_color);\n"
5515 		"\n"
5516 		"    if (true == comparison_result)\n"
5517 		"    {\n"
5518 		"        out_color = success_color;\n"
5519 		"    }\n"
5520 		"    else\n"
5521 		"    {\n"
5522 		"        out_color = failure_color;\n"
5523 		"    }\n"
5524 		"}\n"
5525 		"\n"
5526 		"// Subroutine uniforms\n"
5527 		"subroutine uniform test_type test;\n"
5528 		"\n"
5529 		"void main()\n"
5530 		"{\n"
5531 		"    // Set colors\n"
5532 		"    success_color = vec4(0.5, 0.5, 0.5, 0.5);\n"
5533 		"    failure_color = vec4(0.5, 0.5, 0.5, 0.5);\n"
5534 		"\n"
5535 		"    test();\n"
5536 		"}\n"
5537 		"\n";
5538 
5539 	static const GLchar* geometry_shader_code = "#version 400 core\n"
5540 												"#extension GL_ARB_shader_subroutine : require\n"
5541 												"\n"
5542 												"precision highp float;\n"
5543 												"\n"
5544 												"layout(points)                           in;\n"
5545 												"layout(triangle_strip, max_vertices = 4) out;\n"
5546 												"\n"
5547 												"void main()\n"
5548 												"{\n"
5549 												"    gl_Position = vec4(-1, -1, 0, 1);\n"
5550 												"    EmitVertex();\n"
5551 												"    \n"
5552 												"    gl_Position = vec4(-1,  1, 0, 1);\n"
5553 												"    EmitVertex();\n"
5554 												"    \n"
5555 												"    gl_Position = vec4( 1, -1, 0, 1);\n"
5556 												"    EmitVertex();\n"
5557 												"    \n"
5558 												"    gl_Position = vec4( 1,  1, 0, 1);\n"
5559 												"    EmitVertex();\n"
5560 												"    \n"
5561 												"    EndPrimitive();\n"
5562 												"}\n"
5563 												"\n";
5564 
5565 	static const GLchar* vertex_shader_code = "#version 400 core\n"
5566 											  "#extension GL_ARB_shader_subroutine : require\n"
5567 											  "\n"
5568 											  "precision highp float;\n"
5569 											  "\n"
5570 											  "void main()\n"
5571 											  "{\n"
5572 											  "}\n"
5573 											  "\n";
5574 
5575 	static const GLchar* subroutine_names[][2] = { { "discard_yes", "discard_no" },
5576 												   { "red_pass_blue_fail", "blue_pass_red_fail" },
5577 												   { "first_sampler", "second_sampler" },
5578 												   { "check_equal", "check_not_equal" },
5579 												   { "test_with_discard", "test_without_discard" } };
5580 	static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
5581 
5582 	static const GLchar* subroutine_uniform_names[] = { "discard_fragment", "set_global_colors", "sample_texture",
5583 														"compare", "test" };
5584 	static const GLuint n_subroutine_uniform_names =
5585 		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
5586 
5587 	static const GLchar* uniform_names[] = {
5588 		"sampler_1", "sampler_2",
5589 	};
5590 	static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
5591 
5592 	/* Colors */
5593 	static const GLubyte blue_color[4]  = { 0, 0, 255, 255 };
5594 	static const GLubyte clean_color[4] = { 0, 0, 0, 0 };
5595 	static const GLubyte red_color[4]   = { 255, 0, 0, 255 };
5596 
5597 	/* Configurations */
5598 	static const testConfiguration test_configurations[] = {
5599 		testConfiguration(
5600 			"Expect red color from 1st sampler", red_color, 1 /* discard_fragment  : discard_no         */,
5601 			0 /* set_global_colors : red_pass_blue_fail */, 0 /* sample_texture    : first_sampler      */,
5602 			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */, 1 /* red */,
5603 			0 /* blue */),
5604 
5605 		testConfiguration(
5606 			"Test \"without discard\" option, expect no blue color from 2nd sampler", blue_color,
5607 			0 /* discard_fragment  : discard_yes           */, 1 /* set_global_colors : blue_pass_red_fail    */,
5608 			1 /* sample_texture    : second_sampler        */, 1 /* compare           : check_not_equal       */,
5609 			1 /* test              : test_without_discard  */, 0 /* blue */, 1 /* red */),
5610 
5611 		testConfiguration("Fragment shoud be discarded", clean_color, 0 /* discard_fragment  : discard_yes        */,
5612 						  0 /* set_global_colors : red_pass_blue_fail */,
5613 						  0 /* sample_texture    : first_sampler      */,
5614 						  0 /* compare           : check_equal        */,
5615 						  0 /* test              : test_with_discard  */, 1 /* red */, 0 /* blue */),
5616 
5617 		testConfiguration(
5618 			"Expect blue color from 1st sampler", blue_color, 1 /* discard_fragment  : discard_no         */,
5619 			1 /* set_global_colors : blue_pass_red_fail */, 0 /* sample_texture    : first_sampler      */,
5620 			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */,
5621 			0 /* blue */, 1 /* red */),
5622 
5623 		testConfiguration(
5624 			"Expect red color from 2nd sampler", red_color, 1 /* discard_fragment  : discard_no         */,
5625 			0 /* set_global_colors : red_pass_blue_fail */, 1 /* sample_texture    : second_sampler     */,
5626 			0 /* compare           : check_equal        */, 0 /* test              : test_with_discard  */,
5627 			0 /* blue */, 1 /* red */),
5628 
5629 		testConfiguration(
5630 			"Expect no blue color from 2nd sampler", blue_color, 1 /* discard_fragment  : discard_no         */,
5631 			1 /* set_global_colors : blue_pass_red_fail */, 1 /* sample_texture    : second_sampler     */,
5632 			1 /* compare           : check_not_equal    */, 0 /* test              : test_with_discard  */,
5633 			0 /* blue */, 1 /* red */),
5634 	};
5635 	static const GLuint n_test_cases = sizeof(test_configurations) / sizeof(test_configurations[0]);
5636 
5637 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5638 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5639 	{
5640 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5641 	}
5642 
5643 	/* GL objects */
5644 	Utils::texture	 blue_texture(m_context);
5645 	Utils::texture	 color_texture(m_context);
5646 	Utils::framebuffer framebuffer(m_context);
5647 	Utils::program	 program(m_context);
5648 	Utils::texture	 red_texture(m_context);
5649 	Utils::vertexArray vao(m_context);
5650 
5651 	/* Init GL objects */
5652 	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
5653 				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
5654 
5655 	program.use();
5656 
5657 	vao.generate();
5658 	vao.bind();
5659 
5660 	blue_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5661 	color_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5662 	red_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5663 
5664 	framebuffer.generate();
5665 	framebuffer.bind();
5666 	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
5667 
5668 	/* Get subroutine indices */
5669 	for (GLuint type = 0; type < n_subroutine_types; ++type)
5670 	{
5671 		m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_FRAGMENT_SHADER);
5672 		m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_FRAGMENT_SHADER);
5673 	}
5674 
5675 	/* Get subroutine uniform locations */
5676 	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
5677 	{
5678 		m_subroutine_uniform_locations[uniform] =
5679 			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_FRAGMENT_SHADER);
5680 	}
5681 
5682 	/* Get uniform locations */
5683 	for (GLuint i = 0; i < n_uniform_names; ++i)
5684 	{
5685 		m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
5686 	}
5687 
5688 	/* Prepare textures */
5689 	fillTexture(blue_texture, blue_color);
5690 	fillTexture(color_texture, clean_color);
5691 	fillTexture(red_texture, red_color);
5692 
5693 	m_source_textures[0] = blue_texture.m_id;
5694 	m_source_textures[1] = red_texture.m_id;
5695 
5696 	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
5697 
5698 	/* Test */
5699 	bool result = true;
5700 	for (GLuint i = 0; i < n_test_cases; ++i)
5701 	{
5702 		/* Clean output texture */
5703 		framebuffer.clear(GL_COLOR_BUFFER_BIT);
5704 
5705 		/* Execute test */
5706 		if (false == testDraw(test_configurations[i].m_routines, test_configurations[i].m_samplers,
5707 							  test_configurations[i].m_expected_color, color_texture))
5708 		{
5709 			m_context.getTestContext().getLog()
5710 				<< tcu::TestLog::Message << "Error. Failure for configuration: " << test_configurations[i].m_description
5711 				<< tcu::TestLog::EndMessage;
5712 
5713 			result = false;
5714 		}
5715 	}
5716 
5717 	/* Set result */
5718 	if (true == result)
5719 	{
5720 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5721 	}
5722 	else
5723 	{
5724 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5725 	}
5726 
5727 	/* Done */
5728 	return tcu::TestNode::STOP;
5729 }
5730 
5731 /** Fill texture with specified color
5732  *
5733  * @param texture Texture instance
5734  * @param color   Color
5735  **/
fillTexture(Utils::texture & texture,const glw::GLubyte color[4]) const5736 void FunctionalTest11::fillTexture(Utils::texture& texture, const glw::GLubyte color[4]) const
5737 {
5738 	std::vector<GLubyte> texture_data;
5739 
5740 	/* Prepare texture data */
5741 	texture_data.resize(m_texture_width * m_texture_height * 4);
5742 
5743 	for (GLuint y = 0; y < m_texture_height; ++y)
5744 	{
5745 		const GLuint line_offset = y * m_texture_width * 4;
5746 
5747 		for (GLuint x = 0; x < m_texture_width; ++x)
5748 		{
5749 			const GLuint point_offset = x * 4 + line_offset;
5750 
5751 			texture_data[point_offset + 0] = color[0]; /* red */
5752 			texture_data[point_offset + 1] = color[1]; /* green */
5753 			texture_data[point_offset + 2] = color[2]; /* blue */
5754 			texture_data[point_offset + 3] = color[3]; /* alpha */
5755 		}
5756 	}
5757 
5758 	texture.update(m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
5759 }
5760 
5761 /** Execute draw call and verify results
5762  *
5763  * @param routine_configuration Configurations of routines to be used
5764  * @param sampler_configuration Configuration of textures to be bound to samplers
5765  * @param expected_color        Expected color of result image
5766  *
5767  * @return true if result image is filled with expected color, false otherwise
5768  **/
testDraw(const glw::GLuint routine_configuration[5],const glw::GLuint sampler_configuration[2],const glw::GLubyte expected_color[4],Utils::texture & color_texture) const5769 bool FunctionalTest11::testDraw(const glw::GLuint routine_configuration[5], const glw::GLuint sampler_configuration[2],
5770 								const glw::GLubyte expected_color[4], Utils::texture& color_texture) const
5771 {
5772 	const glw::Functions& gl					= m_context.getRenderContext().getFunctions();
5773 	static const GLint	n_samplers			= 2;
5774 	static const GLint	n_subroutine_uniforms = 5;
5775 	GLuint				  subroutine_indices[5];
5776 
5777 	/* Set samplers */
5778 	for (GLuint i = 0; i < n_samplers; ++i)
5779 	{
5780 		const GLuint location = m_uniform_locations[i];
5781 		const GLuint texture  = m_source_textures[sampler_configuration[i]];
5782 
5783 		gl.activeTexture(GL_TEXTURE0 + i);
5784 		GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
5785 
5786 		gl.bindTexture(GL_TEXTURE_2D, texture);
5787 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5788 
5789 		gl.uniform1i(location, i);
5790 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
5791 	}
5792 
5793 	gl.activeTexture(GL_TEXTURE0 + 0);
5794 
5795 	/* Set subroutine uniforms */
5796 	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
5797 	{
5798 		const GLuint location = m_subroutine_uniform_locations[i];
5799 		const GLuint routine  = routine_configuration[i];
5800 
5801 		subroutine_indices[location] = m_subroutine_indices[i][routine];
5802 	}
5803 
5804 	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 5, subroutine_indices);
5805 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
5806 
5807 	/* Draw */
5808 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5809 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5810 
5811 	/* Capture result */
5812 	std::vector<GLubyte> captured_data;
5813 	captured_data.resize(m_texture_width * m_texture_height * 4);
5814 
5815 	color_texture.get(GL_RGBA, GL_UNSIGNED_BYTE, &captured_data[0]);
5816 
5817 	/* Verify result */
5818 	for (GLuint y = 0; y < m_texture_height; ++y)
5819 	{
5820 		const GLuint line_offset = y * m_texture_width * 4;
5821 
5822 		for (GLuint x = 0; x < m_texture_width; ++x)
5823 		{
5824 			const GLuint point_offset   = x * 4 + line_offset;
5825 			bool		 is_as_expected = true;
5826 
5827 			is_as_expected = is_as_expected && (expected_color[0] == captured_data[point_offset + 0]); /* red */
5828 			is_as_expected = is_as_expected && (expected_color[1] == captured_data[point_offset + 1]); /* green */
5829 			is_as_expected = is_as_expected && (expected_color[2] == captured_data[point_offset + 2]); /* blue */
5830 			is_as_expected = is_as_expected && (expected_color[3] == captured_data[point_offset + 3]); /* alpha */
5831 
5832 			if (false == is_as_expected)
5833 			{
5834 				return false;
5835 			}
5836 		}
5837 	}
5838 
5839 	/* Done */
5840 	return true;
5841 }
5842 
5843 /* Constatns used by FunctionalTest12 */
5844 const glw::GLuint FunctionalTest12::m_texture_height = 16;
5845 const glw::GLuint FunctionalTest12::m_texture_width  = 16;
5846 
5847 /** Constructor
5848  *
5849  * @param context CTS context
5850  **/
FunctionalTest12(deqp::Context & context)5851 FunctionalTest12::FunctionalTest12(deqp::Context& context)
5852 	: TestCase(context, "ssbo_atomic_image_load_store",
5853 			   "Verify that SSBO, atomic counters and image load store work as expected")
5854 	, m_left_image(0)
5855 	, m_right_image(0)
5856 {
5857 }
5858 
5859 /** Execute test
5860  *
5861  * @return tcu::TestNode::STOP
5862  **/
iterate()5863 tcu::TestNode::IterateResult FunctionalTest12::iterate()
5864 {
5865 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5866 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5867 	{
5868 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5869 	}
5870 
5871 	bool result = true;
5872 
5873 	/* Test atomic counters */
5874 	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
5875 	{
5876 		if (false == testAtomic())
5877 		{
5878 			result = false;
5879 		}
5880 	}
5881 
5882 	/* Test shader storage buffer */
5883 	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_storage_buffer_object"))
5884 	{
5885 		if (false == testSSBO())
5886 		{
5887 			result = false;
5888 		}
5889 	}
5890 
5891 	/* Test image load store */
5892 	if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_image_load_store"))
5893 	{
5894 		if (false == testImage())
5895 		{
5896 			result = false;
5897 		}
5898 	}
5899 
5900 	/* Set result */
5901 	if (true == result)
5902 	{
5903 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5904 	}
5905 	else
5906 	{
5907 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5908 	}
5909 
5910 	/* Done */
5911 	return tcu::TestNode::STOP;
5912 }
5913 
5914 /** Fill texture with specified color
5915  *
5916  * @param texture Texture instance
5917  * @param color   Color
5918  **/
fillTexture(Utils::texture & texture,const glw::GLuint color[4]) const5919 void FunctionalTest12::fillTexture(Utils::texture& texture, const glw::GLuint color[4]) const
5920 {
5921 	std::vector<GLuint> texture_data;
5922 
5923 	/* Prepare texture data */
5924 	texture_data.resize(m_texture_width * m_texture_height * 4);
5925 
5926 	for (GLuint y = 0; y < m_texture_height; ++y)
5927 	{
5928 		const GLuint line_offset = y * m_texture_width * 4;
5929 
5930 		for (GLuint x = 0; x < m_texture_width; ++x)
5931 		{
5932 			const GLuint point_offset = x * 4 + line_offset;
5933 
5934 			texture_data[point_offset + 0] = color[0]; /* red */
5935 			texture_data[point_offset + 1] = color[1]; /* green */
5936 			texture_data[point_offset + 2] = color[2]; /* blue */
5937 			texture_data[point_offset + 3] = color[3]; /* alpha */
5938 		}
5939 	}
5940 
5941 	texture.update(m_texture_width, m_texture_height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &texture_data[0]);
5942 }
5943 
5944 /** Test atomic counters
5945  *
5946  * @return true if test pass, false otherwise
5947  **/
testAtomic()5948 bool FunctionalTest12::testAtomic()
5949 {
5950 	static const GLchar* fragment_shader_code = "#version 400 core\n"
5951 												"#extension GL_ARB_shader_atomic_counters : require\n"
5952 												"#extension GL_ARB_shader_subroutine      : require\n"
5953 												"\n"
5954 												"precision highp float;\n"
5955 												"\n"
5956 												"layout(location = 0) out uint out_color;\n"
5957 												"\n"
5958 												"layout(binding = 0, offset = 8) uniform atomic_uint one;\n"
5959 												"layout(binding = 0, offset = 4) uniform atomic_uint two;\n"
5960 												"layout(binding = 0, offset = 0) uniform atomic_uint three;\n"
5961 												"\n"
5962 												"subroutine void atomic_routine(void)\n;"
5963 												"\n"
5964 												"subroutine(atomic_routine) void increment_two(void)\n"
5965 												"{\n"
5966 												"    out_color = atomicCounterIncrement(two);\n"
5967 												"}\n"
5968 												"\n"
5969 												"subroutine(atomic_routine) void decrement_three(void)\n"
5970 												"{\n"
5971 												"    out_color = atomicCounterDecrement(three);\n"
5972 												"}\n"
5973 												"\n"
5974 												"subroutine(atomic_routine) void read_one(void)\n"
5975 												"{\n"
5976 												"    out_color = atomicCounter(one);\n"
5977 												"}\n"
5978 												"\n"
5979 												"subroutine uniform atomic_routine routine;\n"
5980 												"\n"
5981 												"void main()\n"
5982 												"{\n"
5983 												"    routine();\n"
5984 												"}\n"
5985 												"\n";
5986 
5987 	static const GLchar* geometry_shader_code = "#version 400 core\n"
5988 												"#extension GL_ARB_shader_subroutine : require\n"
5989 												"\n"
5990 												"precision highp float;\n"
5991 												"\n"
5992 												"layout(points)                           in;\n"
5993 												"layout(triangle_strip, max_vertices = 4) out;\n"
5994 												"\n"
5995 												"void main()\n"
5996 												"{\n"
5997 												"    gl_Position = vec4(-1, -1, 0, 1);\n"
5998 												"    EmitVertex();\n"
5999 												"    \n"
6000 												"    gl_Position = vec4(-1,  1, 0, 1);\n"
6001 												"    EmitVertex();\n"
6002 												"    \n"
6003 												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6004 												"    EmitVertex();\n"
6005 												"    \n"
6006 												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6007 												"    EmitVertex();\n"
6008 												"    \n"
6009 												"    EndPrimitive();\n"
6010 												"}\n"
6011 												"\n";
6012 
6013 	static const GLchar* vertex_shader_code = "#version 400 core\n"
6014 											  "#extension GL_ARB_shader_subroutine : require\n"
6015 											  "\n"
6016 											  "precision highp float;\n"
6017 											  "\n"
6018 											  "void main()\n"
6019 											  "{\n"
6020 											  "}\n"
6021 											  "\n";
6022 
6023 	static const GLchar* subroutine_names[] = { "increment_two", "decrement_three", "read_one" };
6024 
6025 	/* Test data */
6026 	static const glw::GLuint atomic_buffer_data[] = { m_texture_width * m_texture_height,
6027 													  m_texture_width * m_texture_height,
6028 													  m_texture_width * m_texture_height };
6029 
6030 	static const glw::GLuint expected_incremented_two[] = { atomic_buffer_data[0], 2 * atomic_buffer_data[1],
6031 															atomic_buffer_data[2] };
6032 
6033 	static const glw::GLuint expected_decremented_three[] = { 0, expected_incremented_two[1],
6034 															  expected_incremented_two[2] };
6035 
6036 	static const glw::GLuint expected_read_one[] = { expected_decremented_three[0], expected_decremented_three[1],
6037 													 expected_decremented_three[2] };
6038 
6039 	/* GL objects */
6040 	Utils::buffer	  atomic_buffer(m_context);
6041 	Utils::texture	 color_texture(m_context);
6042 	Utils::framebuffer framebuffer(m_context);
6043 	Utils::program	 program(m_context);
6044 	Utils::vertexArray vao(m_context);
6045 
6046 	/* Init GL objects */
6047 	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6048 				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6049 
6050 	program.use();
6051 
6052 	vao.generate();
6053 	vao.bind();
6054 
6055 	color_texture.create(m_texture_width, m_texture_height, GL_R32UI);
6056 
6057 	atomic_buffer.generate();
6058 	atomic_buffer.update(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomic_buffer_data), (GLvoid*)atomic_buffer_data,
6059 						 GL_STATIC_DRAW);
6060 	atomic_buffer.bindRange(GL_ATOMIC_COUNTER_BUFFER, 0 /* index */, 0 /* offset */, sizeof(atomic_buffer_data));
6061 
6062 	framebuffer.generate();
6063 	framebuffer.bind();
6064 	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6065 	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6066 	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6067 
6068 	/* Subroutine indices */
6069 	GLuint increment_two   = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6070 	GLuint decrement_three = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6071 	GLuint read_one		   = program.getSubroutineIndex(subroutine_names[2], GL_FRAGMENT_SHADER);
6072 
6073 	/* Test */
6074 	bool result = true;
6075 
6076 	if (false == testAtomicDraw(increment_two, expected_incremented_two))
6077 	{
6078 		result = false;
6079 	}
6080 
6081 	if (false == testAtomicDraw(decrement_three, expected_decremented_three))
6082 	{
6083 		result = false;
6084 	}
6085 
6086 	if (false == testAtomicDraw(read_one, expected_read_one))
6087 	{
6088 		result = false;
6089 	}
6090 
6091 	/* Done */
6092 	return result;
6093 }
6094 
6095 /** Execture draw call and verify results
6096  *
6097  * @param subroutine_index Index of subroutine that shall be used during draw call
6098  * @param expected_results Expected results
6099  *
6100  * @return true if results are as expected, false otherwise
6101  **/
testAtomicDraw(GLuint subroutine_index,const GLuint expected_results[3]) const6102 bool FunctionalTest12::testAtomicDraw(GLuint subroutine_index, const GLuint expected_results[3]) const
6103 {
6104 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6105 
6106 	/* Set subroutine uniforms */
6107 	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6108 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6109 
6110 	/* Draw */
6111 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6112 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6113 
6114 	/* Capture results */
6115 	GLuint* atomic_results = (GLuint*)gl.mapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY);
6116 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
6117 
6118 	/* Verify */
6119 	bool result = (0 == memcmp(expected_results, atomic_results, 3 * sizeof(GLuint)));
6120 
6121 	if (false == result)
6122 	{
6123 		m_context.getTestContext().getLog()
6124 			<< tcu::TestLog::Message << "Error. Invalid result. "
6125 			<< "Result: [ " << atomic_results[0] << ", " << atomic_results[1] << ", " << atomic_results[2] << " ] "
6126 			<< "Expected: [ " << expected_results[0] << ", " << expected_results[1] << ", " << expected_results[2]
6127 			<< " ]" << tcu::TestLog::EndMessage;
6128 	}
6129 
6130 	/* Unmap buffer */
6131 	gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
6132 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
6133 
6134 	/* Done */
6135 	return result;
6136 }
6137 
6138 /** Test image load store
6139  *
6140  * @return true if test pass, false otherwise
6141  **/
testImage()6142 bool FunctionalTest12::testImage()
6143 {
6144 	static const GLchar* fragment_shader_code =
6145 		"#version 400 core\n"
6146 		"#extension GL_ARB_shader_image_load_store : require\n"
6147 		"#extension GL_ARB_shader_subroutine       : require\n"
6148 		"\n"
6149 		"precision highp float;\n"
6150 		"\n"
6151 		"layout(location = 0) out uvec4 out_color;\n"
6152 		"\n"
6153 		"layout(rgba32ui) uniform uimage2D left_image;\n"
6154 		"layout(rgba32ui) uniform uimage2D right_image;\n"
6155 		"\n"
6156 		"subroutine void image_routine(void);\n"
6157 		"\n"
6158 		"subroutine(image_routine) void left_to_right(void)\n"
6159 		"{\n"
6160 		"    out_color = imageLoad (left_image,  ivec2(gl_FragCoord.xy));\n"
6161 		"                imageStore(right_image, ivec2(gl_FragCoord.xy), out_color);\n"
6162 		"}\n"
6163 		"\n"
6164 		"subroutine(image_routine) void right_to_left(void)\n"
6165 		"{\n"
6166 		"    out_color = imageLoad (right_image, ivec2(gl_FragCoord.xy));\n"
6167 		"                imageStore(left_image,  ivec2(gl_FragCoord.xy), out_color);\n"
6168 		"}\n"
6169 		"\n"
6170 		"subroutine uniform image_routine routine;\n"
6171 		"\n"
6172 		"void main()\n"
6173 		"{\n"
6174 		"    routine();\n"
6175 		"}\n"
6176 		"\n";
6177 
6178 	static const GLchar* geometry_shader_code = "#version 400 core\n"
6179 												"#extension GL_ARB_shader_subroutine : require\n"
6180 												"\n"
6181 												"precision highp float;\n"
6182 												"\n"
6183 												"layout(points)                           in;\n"
6184 												"layout(triangle_strip, max_vertices = 4) out;\n"
6185 												"\n"
6186 												"void main()\n"
6187 												"{\n"
6188 												"    gl_Position = vec4(-1, -1, 0, 1);\n"
6189 												"    EmitVertex();\n"
6190 												"    \n"
6191 												"    gl_Position = vec4(-1,  1, 0, 1);\n"
6192 												"    EmitVertex();\n"
6193 												"    \n"
6194 												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6195 												"    EmitVertex();\n"
6196 												"    \n"
6197 												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6198 												"    EmitVertex();\n"
6199 												"    \n"
6200 												"    EndPrimitive();\n"
6201 												"}\n"
6202 												"\n";
6203 
6204 	static const GLchar* vertex_shader_code = "#version 400 core\n"
6205 											  "#extension GL_ARB_shader_subroutine : require\n"
6206 											  "\n"
6207 											  "precision highp float;\n"
6208 											  "\n"
6209 											  "void main()\n"
6210 											  "{\n"
6211 											  "}\n"
6212 											  "\n";
6213 
6214 	static const GLchar* subroutine_names[] = { "left_to_right", "right_to_left" };
6215 
6216 	static const GLchar* uniform_names[] = { "left_image", "right_image" };
6217 
6218 	/* Test data */
6219 	static const GLuint blue_color[4]  = { 0, 0, 255, 255 };
6220 	static const GLuint clean_color[4] = { 16, 32, 64, 128 };
6221 	static const GLuint red_color[4]   = { 255, 0, 0, 255 };
6222 
6223 	/* GL objects */
6224 	Utils::texture	 blue_texture(m_context);
6225 	Utils::texture	 destination_texture(m_context);
6226 	Utils::texture	 color_texture(m_context);
6227 	Utils::framebuffer framebuffer(m_context);
6228 	Utils::program	 program(m_context);
6229 	Utils::texture	 red_texture(m_context);
6230 	Utils::vertexArray vao(m_context);
6231 
6232 	/* Init GL objects */
6233 	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6234 				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6235 
6236 	program.use();
6237 
6238 	vao.generate();
6239 	vao.bind();
6240 
6241 	blue_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6242 	destination_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6243 	color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6244 	red_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6245 
6246 	fillTexture(blue_texture, blue_color);
6247 	fillTexture(destination_texture, clean_color);
6248 	fillTexture(red_texture, red_color);
6249 
6250 	framebuffer.generate();
6251 	framebuffer.bind();
6252 	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6253 	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6254 	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6255 
6256 	/* Subroutine indices */
6257 	GLuint left_to_right = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6258 	GLuint right_to_left = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6259 
6260 	/* Uniform locations */
6261 	m_left_image  = program.getUniformLocation(uniform_names[0]);
6262 	m_right_image = program.getUniformLocation(uniform_names[1]);
6263 
6264 	/* Test */
6265 	bool result = true;
6266 
6267 	if (false == testImageDraw(left_to_right, blue_texture, destination_texture, blue_color, blue_color))
6268 	{
6269 		result = false;
6270 	}
6271 
6272 	if (false == testImageDraw(left_to_right, red_texture, destination_texture, red_color, red_color))
6273 	{
6274 		result = false;
6275 	}
6276 
6277 	if (false == testImageDraw(right_to_left, destination_texture, blue_texture, blue_color, blue_color))
6278 	{
6279 		result = false;
6280 	}
6281 
6282 	if (false == testImageDraw(right_to_left, destination_texture, red_texture, red_color, red_color))
6283 	{
6284 		result = false;
6285 	}
6286 
6287 	if (false == testImageDraw(left_to_right, blue_texture, red_texture, blue_color, blue_color))
6288 	{
6289 		result = false;
6290 	}
6291 
6292 	/* Done */
6293 	return result;
6294 }
6295 
6296 /** Execute draw call and verifies results
6297  *
6298  * @param subroutine_index     Index of subroutine that shall be used during draw call
6299  * @param left                 "Left" texture
6300  * @param right                "Right" texture
6301  * @param expected_left_color  Expected color of "left" texture
6302  * @param expected_right_color Expected color of "right" texture
6303  *
6304  * @return true if verification result is positive, false otherwise
6305  **/
testImageDraw(GLuint subroutine_index,Utils::texture & left,Utils::texture & right,const GLuint expected_left_color[4],const GLuint expected_right_color[4]) const6306 bool FunctionalTest12::testImageDraw(GLuint subroutine_index, Utils::texture& left, Utils::texture& right,
6307 									 const GLuint expected_left_color[4], const GLuint expected_right_color[4]) const
6308 {
6309 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6310 
6311 	/* Set subroutine uniforms */
6312 	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6313 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6314 
6315 	/* Set up image units */
6316 	gl.uniform1i(m_left_image, 0);
6317 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
6318 
6319 	gl.uniform1i(m_right_image, 1);
6320 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
6321 
6322 	gl.bindImageTexture(0, left.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
6323 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6324 
6325 	gl.bindImageTexture(1, right.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
6326 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6327 
6328 	/* Draw */
6329 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6330 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6331 
6332 	/* Verify results */
6333 	bool result = true;
6334 
6335 	if (false == verifyTexture(left, expected_left_color))
6336 	{
6337 		m_context.getTestContext().getLog() << tcu::TestLog::Message
6338 											<< "Error. Invalid result. Left texture is filled with wrong color."
6339 											<< tcu::TestLog::EndMessage;
6340 		result = false;
6341 	}
6342 
6343 	if (false == verifyTexture(right, expected_right_color))
6344 	{
6345 		m_context.getTestContext().getLog() << tcu::TestLog::Message
6346 											<< "Error. Invalid result. Right texture is filled with wrong color."
6347 											<< tcu::TestLog::EndMessage;
6348 		result = false;
6349 	}
6350 
6351 	/* Done */
6352 	return result;
6353 }
6354 
6355 /** Test shader storage buffer
6356  *
6357  * @return true if test pass, false otherwise
6358  **/
testSSBO()6359 bool FunctionalTest12::testSSBO()
6360 {
6361 	static const GLchar* fragment_shader_code = "#version 400 core\n"
6362 												"#extension GL_ARB_shader_storage_buffer_object : require\n"
6363 												"#extension GL_ARB_shader_subroutine            : require\n"
6364 												"\n"
6365 												"precision highp float;\n"
6366 												"\n"
6367 												"layout(location = 0) out uvec4 out_color;\n"
6368 												"\n"
6369 												"layout(std140, binding = 0) buffer Buffer\n"
6370 												"{\n"
6371 												"    uvec4 entry;\n"
6372 												"};\n"
6373 												"\n"
6374 												"subroutine void ssbo_routine(void)\n;"
6375 												"\n"
6376 												"subroutine(ssbo_routine) void increment(void)\n"
6377 												"{\n"
6378 												"    out_color.x = atomicAdd(entry.x, 1);\n"
6379 												"    out_color.y = atomicAdd(entry.y, 1);\n"
6380 												"    out_color.z = atomicAdd(entry.z, 1);\n"
6381 												"    out_color.w = atomicAdd(entry.w, 1);\n"
6382 												"}\n"
6383 												"\n"
6384 												"subroutine(ssbo_routine) void decrement(void)\n"
6385 												"{\n"
6386 												"    out_color.x = atomicAdd(entry.x, -1);\n"
6387 												"    out_color.y = atomicAdd(entry.y, -1);\n"
6388 												"    out_color.z = atomicAdd(entry.z, -1);\n"
6389 												"    out_color.w = atomicAdd(entry.w, -1);\n"
6390 												"}\n"
6391 												"\n"
6392 												"subroutine uniform ssbo_routine routine;\n"
6393 												"\n"
6394 												"void main()\n"
6395 												"{\n"
6396 												"    routine();\n"
6397 												"}\n"
6398 												"\n";
6399 
6400 	static const GLchar* geometry_shader_code = "#version 400 core\n"
6401 												"#extension GL_ARB_shader_subroutine : require\n"
6402 												"\n"
6403 												"precision highp float;\n"
6404 												"\n"
6405 												"layout(points)                           in;\n"
6406 												"layout(triangle_strip, max_vertices = 4) out;\n"
6407 												"\n"
6408 												"void main()\n"
6409 												"{\n"
6410 												"    gl_Position = vec4(-1, -1, 0, 1);\n"
6411 												"    EmitVertex();\n"
6412 												"    \n"
6413 												"    gl_Position = vec4(-1,  1, 0, 1);\n"
6414 												"    EmitVertex();\n"
6415 												"    \n"
6416 												"    gl_Position = vec4( 1, -1, 0, 1);\n"
6417 												"    EmitVertex();\n"
6418 												"    \n"
6419 												"    gl_Position = vec4( 1,  1, 0, 1);\n"
6420 												"    EmitVertex();\n"
6421 												"    \n"
6422 												"    EndPrimitive();\n"
6423 												"}\n"
6424 												"\n";
6425 
6426 	static const GLchar* vertex_shader_code = "#version 400 core\n"
6427 											  "#extension GL_ARB_shader_subroutine : require\n"
6428 											  "\n"
6429 											  "precision highp float;\n"
6430 											  "\n"
6431 											  "void main()\n"
6432 											  "{\n"
6433 											  "}\n"
6434 											  "\n";
6435 
6436 	static const GLchar* subroutine_names[] = { "increment", "decrement" };
6437 
6438 	/* Test data */
6439 	static const glw::GLuint buffer_data[] = { m_texture_width * m_texture_height + 1,
6440 											   m_texture_width * m_texture_height + 2,
6441 											   m_texture_width * m_texture_height + 3,
6442 											   m_texture_width * m_texture_height + 4 };
6443 
6444 	static const glw::GLuint expected_incremented[] = { m_texture_width * m_texture_height + buffer_data[0],
6445 														m_texture_width * m_texture_height + buffer_data[1],
6446 														m_texture_width * m_texture_height + buffer_data[2],
6447 														m_texture_width * m_texture_height + buffer_data[3] };
6448 
6449 	static const glw::GLuint expected_decremented[] = { buffer_data[0], buffer_data[1], buffer_data[2],
6450 														buffer_data[3] };
6451 
6452 	/* GL objects */
6453 	Utils::buffer	  buffer(m_context);
6454 	Utils::texture	 color_texture(m_context);
6455 	Utils::framebuffer framebuffer(m_context);
6456 	Utils::program	 program(m_context);
6457 	Utils::vertexArray vao(m_context);
6458 
6459 	/* Init GL objects */
6460 	program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6461 				  vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6462 
6463 	program.use();
6464 
6465 	vao.generate();
6466 	vao.bind();
6467 
6468 	color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6469 
6470 	buffer.generate();
6471 	buffer.update(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), (GLvoid*)buffer_data, GL_STATIC_DRAW);
6472 	buffer.bindRange(GL_SHADER_STORAGE_BUFFER, 0 /* index */, 0 /* offset */, sizeof(buffer_data));
6473 
6474 	framebuffer.generate();
6475 	framebuffer.bind();
6476 	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6477 	framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6478 	framebuffer.clear(GL_COLOR_BUFFER_BIT);
6479 
6480 	/* Subroutine indices */
6481 	GLuint increment = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6482 	GLuint decrement = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6483 
6484 	/* Test */
6485 	bool result = true;
6486 
6487 	if (false == testSSBODraw(increment, expected_incremented))
6488 	{
6489 		result = false;
6490 	}
6491 
6492 	if (false == testSSBODraw(decrement, expected_decremented))
6493 	{
6494 		result = false;
6495 	}
6496 
6497 	/* Done */
6498 	return result;
6499 }
6500 
6501 /** Execute draw call and verify results
6502  *
6503  * @param subroutine_index Index of subroutine that shall be used by draw call
6504  * @param expected_results Expected results
6505  *
6506  *
6507  **/
testSSBODraw(GLuint subroutine_index,const GLuint expected_results[4]) const6508 bool FunctionalTest12::testSSBODraw(GLuint subroutine_index, const GLuint expected_results[4]) const
6509 {
6510 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6511 
6512 	/* Set subroutine uniforms */
6513 	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6514 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6515 
6516 	/* Draw */
6517 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6518 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6519 
6520 	/* Capture results */
6521 	GLuint* ssbo_results = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
6522 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
6523 
6524 	/* Verify */
6525 	bool result = (0 == memcmp(expected_results, ssbo_results, 4 * sizeof(GLuint)));
6526 
6527 	if (false == result)
6528 	{
6529 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result. "
6530 											<< "Result: [ " << ssbo_results[0] << ", " << ssbo_results[1] << ", "
6531 											<< ssbo_results[2] << ", " << ssbo_results[3] << " ] "
6532 											<< "Expected: [ " << expected_results[0] << ", " << expected_results[1]
6533 											<< ", " << expected_results[2] << ", " << expected_results[3] << " ]"
6534 											<< tcu::TestLog::EndMessage;
6535 	}
6536 
6537 	/* Unmap buffer */
6538 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
6539 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
6540 
6541 	/* Done */
6542 	return result;
6543 }
6544 
6545 /** Check if texture is filled with expected color
6546  *
6547  * @param texture        Texture instance
6548  * @param expected_color Expected color
6549  *
6550  * @return true if texture is filled with specified color, false otherwise
6551  **/
verifyTexture(Utils::texture & texture,const GLuint expected_color[4]) const6552 bool FunctionalTest12::verifyTexture(Utils::texture& texture, const GLuint expected_color[4]) const
6553 {
6554 	std::vector<GLuint> results;
6555 	results.resize(m_texture_width * m_texture_height * 4);
6556 
6557 	texture.get(GL_RGBA_INTEGER, GL_UNSIGNED_INT, &results[0]);
6558 
6559 	for (GLuint y = 0; y < m_texture_height; ++y)
6560 	{
6561 		const GLuint line_offset = y * m_texture_width * 4;
6562 
6563 		for (GLuint x = 0; x < m_texture_width; ++x)
6564 		{
6565 			const GLuint point_offset = line_offset + x * 4;
6566 			bool		 result		  = true;
6567 
6568 			result = result && (results[point_offset + 0] == expected_color[0]);
6569 			result = result && (results[point_offset + 1] == expected_color[1]);
6570 			result = result && (results[point_offset + 2] == expected_color[2]);
6571 			result = result && (results[point_offset + 3] == expected_color[3]);
6572 
6573 			if (false == result)
6574 			{
6575 				return false;
6576 			}
6577 		}
6578 	}
6579 
6580 	return true;
6581 }
6582 
6583 /** Constructor.
6584  *
6585  *  @param context Rendering context.
6586  *
6587  **/
FunctionalTest13(deqp::Context & context)6588 FunctionalTest13::FunctionalTest13(deqp::Context& context)
6589 	: TestCase(context, "subroutines_with_separate_shader_objects",
6590 			   "Verifies that subroutines work correctly when used in separate "
6591 			   "shader objects")
6592 	, m_fbo_id(0)
6593 	, m_pipeline_id(0)
6594 	, m_read_buffer(DE_NULL)
6595 	, m_to_height(4)
6596 	, m_to_id(0)
6597 	, m_to_width(4)
6598 	, m_vao_id(0)
6599 	, m_has_test_passed(true)
6600 {
6601 	memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids));
6602 	memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids));
6603 	memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids));
6604 	memset(m_te_po_ids, 0, sizeof(m_te_po_ids));
6605 	memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids));
6606 }
6607 
6608 /** Deinitializes all GL objects that may have been created during test
6609  *  execution, as well as releases all process-side buffers that may have
6610  *  been allocated during the process.
6611  *  The function also restores default GL state configuration.
6612  **/
deinit()6613 void FunctionalTest13::deinit()
6614 {
6615 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6616 
6617 	if (m_fbo_id != 0)
6618 	{
6619 		gl.deleteFramebuffers(1, &m_fbo_id);
6620 
6621 		m_fbo_id = 0;
6622 	}
6623 
6624 	if (m_pipeline_id != 0)
6625 	{
6626 		gl.deleteProgramPipelines(1, &m_pipeline_id);
6627 
6628 		m_pipeline_id = 0;
6629 	}
6630 
6631 	if (m_read_buffer != DE_NULL)
6632 	{
6633 		delete[] m_read_buffer;
6634 
6635 		m_read_buffer = DE_NULL;
6636 	}
6637 
6638 	for (unsigned int n_id = 0; n_id < 2 /* po id variants */; ++n_id)
6639 	{
6640 		if (m_fs_po_ids[n_id] != 0)
6641 		{
6642 			gl.deleteProgram(m_fs_po_ids[n_id]);
6643 
6644 			m_fs_po_ids[n_id] = 0;
6645 		}
6646 
6647 		if (m_gs_po_ids[n_id] != 0)
6648 		{
6649 			gl.deleteProgram(m_gs_po_ids[n_id]);
6650 
6651 			m_gs_po_ids[n_id] = 0;
6652 		}
6653 
6654 		if (m_tc_po_ids[n_id] != 0)
6655 		{
6656 			gl.deleteProgram(m_tc_po_ids[n_id]);
6657 
6658 			m_tc_po_ids[n_id] = 0;
6659 		}
6660 
6661 		if (m_te_po_ids[n_id] != 0)
6662 		{
6663 			gl.deleteProgram(m_te_po_ids[n_id]);
6664 
6665 			m_te_po_ids[n_id] = 0;
6666 		}
6667 
6668 		if (m_vs_po_ids[n_id] != 0)
6669 		{
6670 			gl.deleteProgram(m_vs_po_ids[n_id]);
6671 
6672 			m_vs_po_ids[n_id] = 0;
6673 		}
6674 	} /* for (both shader program object variants) */
6675 
6676 	if (m_to_id != 0)
6677 	{
6678 		gl.deleteTextures(1, &m_to_id);
6679 
6680 		m_to_id = 0;
6681 	}
6682 
6683 	if (m_vao_id != 0)
6684 	{
6685 		gl.deleteVertexArrays(1, &m_vao_id);
6686 
6687 		m_vao_id = 0;
6688 	}
6689 
6690 	/* Restore default GL_PATCH_VERTICES setting value */
6691 	gl.patchParameteri(GL_PATCH_VERTICES, 3);
6692 
6693 	/* Restore default GL_PACK_ALIGNMENT setting value */
6694 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
6695 }
6696 
6697 /** Retrieves body of a fragment shader that should be used for the test.
6698  *  The subroutine implementations are slightly changed, depending on the
6699  *  index of the shader, as specified by the caller.
6700  *
6701  *  @param n_id Index of the shader.
6702  *
6703  *  @return Requested string.
6704  **/
getFragmentShaderBody(unsigned int n_id)6705 std::string FunctionalTest13::getFragmentShaderBody(unsigned int n_id)
6706 {
6707 	std::stringstream result_sstream;
6708 
6709 	/* Pre-amble */
6710 	result_sstream << "#version 400\n"
6711 					  "\n"
6712 					  "#extension GL_ARB_shader_subroutine : require\n"
6713 					  "\n"
6714 					  /* Sub-routine */
6715 					  "subroutine void SubroutineFSType(inout vec4 result);\n"
6716 					  "\n"
6717 					  "subroutine(SubroutineFSType) void SubroutineFS1(inout vec4 result)\n"
6718 					  "{\n"
6719 					  "    result += vec4("
6720 				   << float(n_id + 1) / 10.0f << ", " << float(n_id + 2) / 10.0f << ", " << float(n_id + 3) / 10.0f
6721 				   << ", " << float(n_id + 4) / 10.0f
6722 				   << ");\n"
6723 					  "}\n"
6724 					  "subroutine(SubroutineFSType) void SubroutineFS2(inout vec4 result)\n"
6725 					  "{\n"
6726 					  "    result += vec4("
6727 				   << float(n_id + 1) / 20.0f << ", " << float(n_id + 2) / 20.0f << ", " << float(n_id + 3) / 20.0f
6728 				   << ", " << float(n_id + 4) / 20.0f << ");\n"
6729 														 "}\n"
6730 														 "\n"
6731 														 "subroutine uniform SubroutineFSType function;\n"
6732 														 "\n"
6733 														 /* Input block */
6734 														 "in GS_DATA\n"
6735 														 "{\n"
6736 														 "    vec4 data;\n"
6737 														 "} in_gs;\n"
6738 														 "\n"
6739 														 "out vec4 result;\n"
6740 														 /* main() declaration */
6741 														 "void main()\n"
6742 														 "{\n"
6743 														 "    vec4 data = in_gs.data;\n"
6744 														 "    function(data);\n"
6745 														 "\n"
6746 														 "    result = data;\n"
6747 														 "}\n";
6748 
6749 	return result_sstream.str();
6750 }
6751 
6752 /** Retrieves body of a geometry shader that should be used for the test.
6753  *  The subroutine implementations are slightly changed, depending on the
6754  *  index of the shader, as specified by the caller.
6755  *
6756  *  @param n_id Index of the shader.
6757  *
6758  *  @return Requested string.
6759  **/
getGeometryShaderBody(unsigned int n_id)6760 std::string FunctionalTest13::getGeometryShaderBody(unsigned int n_id)
6761 {
6762 	std::stringstream result_sstream;
6763 
6764 	/* Pre-amble */
6765 	result_sstream << "#version 400\n"
6766 					  "\n"
6767 					  "#extension GL_ARB_shader_subroutine : require\n"
6768 					  "\n"
6769 					  "layout(points)                           in;\n"
6770 					  "layout(triangle_strip, max_vertices = 4) out;\n"
6771 					  /* Sub-routine */
6772 					  "subroutine void SubroutineGSType(inout vec4 result);\n"
6773 					  "\n"
6774 					  "subroutine(SubroutineGSType) void SubroutineGS1(inout vec4 result)\n"
6775 					  "{\n"
6776 					  "    result += vec4(0, 0, 0, "
6777 				   << float(n_id + 1) * 0.425f << ");\n"
6778 												  "}\n"
6779 												  "subroutine(SubroutineGSType) void SubroutineGS2(inout vec4 result)\n"
6780 												  "{\n"
6781 												  "    result += vec4(0, 0, 0, "
6782 				   << float(n_id + 1) * 0.0425f << ");\n"
6783 												   "}\n"
6784 												   "\n"
6785 												   "subroutine uniform SubroutineGSType function;\n"
6786 												   "\n"
6787 												   /* Input block */
6788 												   "in TE_DATA\n"
6789 												   "{\n"
6790 												   "    vec4 data;\n"
6791 												   "} in_te[];\n"
6792 												   "\n"
6793 												   /* Output block */
6794 												   "out GS_DATA\n"
6795 												   "{\n"
6796 												   "    vec4 data;\n"
6797 												   "} out_gs;\n"
6798 												   "\n"
6799 												   "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6800 												   "out gl_PerVertex { vec4 gl_Position; };\n"
6801 												   /* main() declaration */
6802 												   "void main()\n"
6803 												   "{\n"
6804 												   "    vec4 data = in_te[0].data;\n"
6805 												   "\n"
6806 												   "    function(data);\n"
6807 												   "\n"
6808 												   "    gl_Position = vec4(1, -1, 0, 1);\n"
6809 												   "    out_gs.data = data;\n"
6810 												   "    EmitVertex();\n"
6811 												   "\n"
6812 												   "    gl_Position = vec4(-1, -1, 0, 1);\n"
6813 												   "    out_gs.data = data;\n"
6814 												   "    EmitVertex();\n"
6815 												   "\n"
6816 												   "    gl_Position = vec4(1, 1, 0, 1);\n"
6817 												   "    out_gs.data = data;\n"
6818 												   "    EmitVertex();\n"
6819 												   "\n"
6820 												   "    gl_Position = vec4(-1, 1, 0, 1);\n"
6821 												   "    out_gs.data = data;\n"
6822 												   "    EmitVertex();\n"
6823 												   "    EndPrimitive();\n"
6824 												   "}\n";
6825 
6826 	return result_sstream.str();
6827 }
6828 
6829 /** Retrieves body of a tessellation control shader that should be used for the test.
6830  *  The subroutine implementations are slightly changed, depending on the
6831  *  index of the shader, as specified by the caller.
6832  *
6833  *  @param n_id Index of the shader.
6834  *
6835  *  @return Requested string.
6836  **/
getTessellationControlShaderBody(unsigned int n_id)6837 std::string FunctionalTest13::getTessellationControlShaderBody(unsigned int n_id)
6838 {
6839 	std::stringstream result_sstream;
6840 
6841 	/* Pre-amble */
6842 	result_sstream << "#version 400\n"
6843 					  "\n"
6844 					  "#extension GL_ARB_shader_subroutine : require\n"
6845 					  "\n"
6846 					  "layout(vertices = 4) out;\n"
6847 					  /* Sub-routine */
6848 					  "subroutine void SubroutineTCType(inout vec4 result);\n"
6849 					  "\n"
6850 					  "subroutine(SubroutineTCType) void SubroutineTC1(inout vec4 result)\n"
6851 					  "{\n"
6852 					  "    result += vec4(0, "
6853 				   << float(n_id + 1) * 0.25f << ", 0, 0);\n"
6854 												 "}\n"
6855 												 "subroutine(SubroutineTCType) void SubroutineTC2(inout vec4 result)\n"
6856 												 "{\n"
6857 												 "    result += vec4(0, "
6858 				   << float(n_id + 1) * 0.025f
6859 				   << ", 0, 0);\n"
6860 					  "}\n"
6861 					  "\n"
6862 					  "subroutine uniform SubroutineTCType function;\n"
6863 					  "\n"
6864 					  /* Input block */
6865 					  "in VS_DATA\n"
6866 					  "{\n"
6867 					  "    vec4 data;\n"
6868 					  "} in_vs[];\n"
6869 					  "\n"
6870 					  /* Output block */
6871 					  "out TC_DATA\n"
6872 					  "{\n"
6873 					  "    vec4 data;\n"
6874 					  "} out_tc[];\n"
6875 					  "\n"
6876 					  "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6877 					  "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"
6878 					  /* main() declaration */
6879 					  "void main()\n"
6880 					  "{\n"
6881 					  "    gl_TessLevelOuter[0]                = 1.0;\n"
6882 					  "    gl_TessLevelOuter[1]                = 1.0;\n"
6883 					  "    gl_TessLevelOuter[2]                = 1.0;\n"
6884 					  "    gl_TessLevelOuter[3]                = 1.0;\n"
6885 					  "    gl_TessLevelInner[0]                = 1.0;\n"
6886 					  "    gl_TessLevelInner[1]                = 1.0;\n"
6887 					  "    gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n"
6888 					  "    out_tc[gl_InvocationID].data        = in_vs[0].data;\n"
6889 					  "\n"
6890 					  "    function(out_tc[gl_InvocationID].data);\n"
6891 					  "}\n";
6892 
6893 	return result_sstream.str();
6894 }
6895 
6896 /** Retrieves body of a tessellation evaluation shader that should be used for the test.
6897  *  The subroutine implementations are slightly changed, depending on the
6898  *  index of the shader, as specified by the caller.
6899  *
6900  *  @param n_id Index of the shader.
6901  *
6902  *  @return Requested string.
6903  **/
getTessellationEvaluationShaderBody(unsigned int n_id)6904 std::string FunctionalTest13::getTessellationEvaluationShaderBody(unsigned int n_id)
6905 {
6906 	std::stringstream result_sstream;
6907 
6908 	/* Pre-amble */
6909 	result_sstream << "#version 400\n"
6910 					  "\n"
6911 					  "#extension GL_ARB_shader_subroutine : require\n"
6912 					  "\n"
6913 					  "layout(quads, point_mode) in;\n"
6914 					  /* Sub-routine */
6915 					  "subroutine void SubroutineTEType(inout vec4 result);\n"
6916 					  "\n"
6917 					  "subroutine(SubroutineTEType) void SubroutineTE1(inout vec4 result)\n"
6918 					  "{\n"
6919 					  "    result += vec4(0, 0, "
6920 				   << float(n_id + 1) * 0.325f << ", 0);\n"
6921 												  "}\n"
6922 												  "subroutine(SubroutineTEType) void SubroutineTE2(inout vec4 result)\n"
6923 												  "{\n"
6924 												  "    result += vec4(0, 0, "
6925 				   << float(n_id + 1) * 0.0325f << ", 0);\n"
6926 												   "}\n"
6927 												   "\n"
6928 												   "subroutine uniform SubroutineTEType function;\n"
6929 												   "\n"
6930 												   /* Input block */
6931 												   "in TC_DATA\n"
6932 												   "{\n"
6933 												   "    vec4 data;\n"
6934 												   "} in_tc[];\n"
6935 												   "\n"
6936 												   /* Output block */
6937 												   "out TE_DATA\n"
6938 												   "{\n"
6939 												   "    vec4 data;\n"
6940 												   "} out_te;\n"
6941 												   "\n"
6942 												   "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6943 												   "out gl_PerVertex { vec4 gl_Position; };\n"
6944 												   /* main() declaration */
6945 												   "void main()\n"
6946 												   "{\n"
6947 												   "    gl_Position = gl_in[0].gl_Position;\n"
6948 												   "    out_te.data = in_tc[0].data;\n"
6949 												   "\n"
6950 												   "    function(out_te.data);\n"
6951 												   "}\n";
6952 
6953 	return result_sstream.str();
6954 }
6955 
6956 /** Retrieves body of a vertex shader that should be used for the test.
6957  *  The subroutine implementations are slightly changed, depending on the
6958  *  index of the shader, as specified by the caller.
6959  *
6960  *  @param n_id Index of the shader.
6961  *
6962  *  @return Requested string.
6963  **/
getVertexShaderBody(unsigned int n_id)6964 std::string FunctionalTest13::getVertexShaderBody(unsigned int n_id)
6965 {
6966 	std::stringstream result_sstream;
6967 
6968 	/* Pre-amble */
6969 	result_sstream << "#version 400\n"
6970 					  "\n"
6971 					  "#extension GL_ARB_shader_subroutine : require\n"
6972 					  "\n"
6973 					  /* Sub-routine */
6974 					  "subroutine void SubroutineVSType(inout vec4 result);\n"
6975 					  "\n"
6976 					  "subroutine(SubroutineVSType) void SubroutineVS1(inout vec4 result)\n"
6977 					  "{\n"
6978 					  "    result += vec4("
6979 				   << float(n_id + 1) * 0.125f << ", 0, 0, 0);\n"
6980 												  "}\n"
6981 												  "subroutine(SubroutineVSType) void SubroutineVS2(inout vec4 result)\n"
6982 												  "{\n"
6983 												  "    result += vec4("
6984 				   << float(n_id + 1) * 0.0125f << ", 0, 0, 0);\n"
6985 												   "}\n"
6986 												   "\n"
6987 												   "subroutine uniform SubroutineVSType function;\n"
6988 												   "\n"
6989 												   /* Output block */
6990 												   "out VS_DATA\n"
6991 												   "{\n"
6992 												   "    vec4 data;\n"
6993 												   "} out_vs;\n"
6994 												   "\n"
6995 												   "out gl_PerVertex { vec4 gl_Position; };\n"
6996 												   /* main() declaration */
6997 												   "void main()\n"
6998 												   "{\n"
6999 												   "    gl_Position = vec4(0, 0, 0, 1);\n"
7000 												   "    out_vs.data = vec4(0);\n"
7001 												   "\n"
7002 												   "    function(out_vs.data);\n"
7003 												   "\n"
7004 												   "}\n";
7005 
7006 	return result_sstream.str();
7007 }
7008 
7009 /** Initializes all GL objects required to run the test. Also modifies a few
7010  *  GL states in order for the test to run correctly.
7011  **/
initTest()7012 void FunctionalTest13::initTest()
7013 {
7014 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7015 
7016 	/* Set up viewport */
7017 	gl.viewport(0 /* x */, 0 /* y */, m_to_width, m_to_height);
7018 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
7019 
7020 	/* Make sure no program is used */
7021 	gl.useProgram(0);
7022 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7023 
7024 	/* Generate a pipeline object */
7025 	gl.genProgramPipelines(1, &m_pipeline_id);
7026 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
7027 
7028 	gl.bindProgramPipeline(m_pipeline_id);
7029 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
7030 
7031 	/* Initialize all shader programs */
7032 	for (unsigned int n_id = 0; n_id < 2 /* variants for each shader type */; ++n_id)
7033 	{
7034 		std::string fs_body			= getFragmentShaderBody(n_id);
7035 		const char* fs_body_raw_ptr = fs_body.c_str();
7036 		std::string gs_body			= getGeometryShaderBody(n_id);
7037 		const char* gs_body_raw_ptr = gs_body.c_str();
7038 		std::string tc_body			= getTessellationControlShaderBody(n_id);
7039 		const char* tc_body_raw_ptr = tc_body.c_str();
7040 		std::string te_body			= getTessellationEvaluationShaderBody(n_id);
7041 		const char* te_body_raw_ptr = te_body.c_str();
7042 		std::string vs_body			= getVertexShaderBody(n_id);
7043 		const char* vs_body_raw_ptr = vs_body.c_str();
7044 
7045 		m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr);
7046 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7047 
7048 		m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr);
7049 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7050 
7051 		m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr);
7052 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7053 
7054 		m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr);
7055 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7056 
7057 		m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr);
7058 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7059 
7060 		/* Verify that all shader program objects have been linked successfully */
7061 		const glw::GLuint po_ids[] = {
7062 			m_fs_po_ids[n_id], m_gs_po_ids[n_id], m_tc_po_ids[n_id], m_te_po_ids[n_id], m_vs_po_ids[n_id],
7063 		};
7064 		const unsigned int n_po_ids = sizeof(po_ids) / sizeof(po_ids[0]);
7065 
7066 		for (unsigned int n_po_id = 0; n_po_id < n_po_ids; ++n_po_id)
7067 		{
7068 			glw::GLint  link_status = GL_FALSE;
7069 			glw::GLuint po_id		= po_ids[n_po_id];
7070 
7071 			gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
7072 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7073 
7074 			if (link_status != GL_TRUE)
7075 			{
7076 				TCU_FAIL("Shader program object linking failed.");
7077 			}
7078 		} /* for (all shader program objects) */
7079 	}	 /* for (both shader program object variants) */
7080 
7081 	/* Generate a texture object. We will use the base mip-map as a render-target */
7082 	gl.genTextures(1, &m_to_id);
7083 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
7084 
7085 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
7086 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7087 
7088 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA32F, m_to_width, m_to_height);
7089 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
7090 
7091 	/* Generate and configure a FBO we will use for the draw call */
7092 	gl.genFramebuffers(1, &m_fbo_id);
7093 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
7094 
7095 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
7096 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
7097 
7098 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
7099 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
7100 
7101 	/* Generate & bind a VAO */
7102 	gl.genVertexArrays(1, &m_vao_id);
7103 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7104 
7105 	gl.bindVertexArray(m_vao_id);
7106 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7107 
7108 	/* Set up tessellation */
7109 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
7110 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
7111 
7112 	/* Set up pixel storage alignment */
7113 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
7114 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
7115 
7116 	/* Allocate enough space to hold color attachment data */
7117 	m_read_buffer = (unsigned char*)new float[m_to_width * m_to_height * 4 /* rgba */];
7118 }
7119 
7120 /** Executes test iteration.
7121  *
7122  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7123  */
iterate()7124 tcu::TestNode::IterateResult FunctionalTest13::iterate()
7125 {
7126 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7127 
7128 	/* Do not execute the test if GL_ARB_shader_subroutine and GL_ARB_separate_shader_objects
7129 	 * are not supported */
7130 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
7131 	{
7132 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
7133 	}
7134 
7135 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
7136 	{
7137 		throw tcu::NotSupportedError("GL_ARB_separate_shader_objects is not supported");
7138 	}
7139 
7140 	/* Initialize all GL objects before we continue */
7141 	initTest();
7142 
7143 	/* Iterate over all possible FS/GS/TC/TE/VS permutations */
7144 	for (int n_shader_permutation = 0; n_shader_permutation < 32 /* 2^5 */; ++n_shader_permutation)
7145 	{
7146 		const unsigned int n_fs_idx = ((n_shader_permutation & (1 << 0)) != 0) ? 1 : 0;
7147 		const unsigned int n_gs_idx = ((n_shader_permutation & (1 << 1)) != 0) ? 1 : 0;
7148 		const unsigned int n_tc_idx = ((n_shader_permutation & (1 << 2)) != 0) ? 1 : 0;
7149 		const unsigned int n_te_idx = ((n_shader_permutation & (1 << 3)) != 0) ? 1 : 0;
7150 		const unsigned int n_vs_idx = ((n_shader_permutation & (1 << 4)) != 0) ? 1 : 0;
7151 		const unsigned int fs_po_id = m_fs_po_ids[n_fs_idx];
7152 		const unsigned int gs_po_id = m_gs_po_ids[n_gs_idx];
7153 		const unsigned int tc_po_id = m_tc_po_ids[n_tc_idx];
7154 		const unsigned int te_po_id = m_te_po_ids[n_te_idx];
7155 		const unsigned int vs_po_id = m_vs_po_ids[n_vs_idx];
7156 
7157 		/* Configure fragment shader stage */
7158 		gl.useProgramStages(m_pipeline_id, GL_FRAGMENT_SHADER_BIT, fs_po_id);
7159 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_FRAGMENT_SHADER_BIT bit");
7160 
7161 		/* Configure geometry shader stage */
7162 		gl.useProgramStages(m_pipeline_id, GL_GEOMETRY_SHADER_BIT, gs_po_id);
7163 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_GEOMETRY_SHADER_BIT bit");
7164 
7165 		/* Configure tessellation control shader stage */
7166 		gl.useProgramStages(m_pipeline_id, GL_TESS_CONTROL_SHADER_BIT, tc_po_id);
7167 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_CONTROL_SHADER_BIT bit");
7168 
7169 		/* Configure tessellation evaluation shader stage */
7170 		gl.useProgramStages(m_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT, te_po_id);
7171 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_EVALUATION_SHADER_BIT bit");
7172 
7173 		/* Configure vertex shader stage */
7174 		gl.useProgramStages(m_pipeline_id, GL_VERTEX_SHADER_BIT, vs_po_id);
7175 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_VERTEX_SHADER_BIT bit");
7176 
7177 		/* Validate the pipeline */
7178 		glw::GLint validate_status = GL_FALSE;
7179 
7180 		gl.validateProgramPipeline(m_pipeline_id);
7181 		GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed.");
7182 
7183 		gl.getProgramPipelineiv(m_pipeline_id, GL_VALIDATE_STATUS, &validate_status);
7184 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed.");
7185 
7186 		if (validate_status != GL_TRUE)
7187 		{
7188 			TCU_FAIL("Program pipeline has not been validated successfully.");
7189 		}
7190 
7191 		/* Retrieve subroutine indices */
7192 		GLuint fs_subroutine_indices[2]	= { (GLuint)-1 };
7193 		GLint  fs_subroutine_uniform_index = 0;
7194 		GLuint gs_subroutine_indices[2]	= { (GLuint)-1 };
7195 		GLint  gs_subroutine_uniform_index = 0;
7196 		GLuint tc_subroutine_indices[2]	= { (GLuint)-1 };
7197 		GLint  tc_subroutine_uniform_index = 0;
7198 		GLuint te_subroutine_indices[2]	= { (GLuint)-1 };
7199 		GLint  te_subroutine_uniform_index = 0;
7200 		GLuint vs_subroutine_indices[2]	= { (GLuint)-1 };
7201 		GLint  vs_subroutine_uniform_index = 0;
7202 
7203 		for (unsigned int n_subroutine = 0; n_subroutine < 2; ++n_subroutine)
7204 		{
7205 			std::stringstream fs_subroutine_name_sstream;
7206 			std::stringstream gs_subroutine_name_sstream;
7207 			std::stringstream tc_subroutine_name_sstream;
7208 			std::stringstream te_subroutine_name_sstream;
7209 			std::stringstream vs_subroutine_name_sstream;
7210 
7211 			fs_subroutine_name_sstream << "SubroutineFS" << (n_subroutine + 1);
7212 			gs_subroutine_name_sstream << "SubroutineGS" << (n_subroutine + 1);
7213 			tc_subroutine_name_sstream << "SubroutineTC" << (n_subroutine + 1);
7214 			te_subroutine_name_sstream << "SubroutineTE" << (n_subroutine + 1);
7215 			vs_subroutine_name_sstream << "SubroutineVS" << (n_subroutine + 1);
7216 
7217 			fs_subroutine_indices[n_subroutine] =
7218 				gl.getSubroutineIndex(fs_po_id, GL_FRAGMENT_SHADER, fs_subroutine_name_sstream.str().c_str());
7219 			gs_subroutine_indices[n_subroutine] =
7220 				gl.getSubroutineIndex(gs_po_id, GL_GEOMETRY_SHADER, gs_subroutine_name_sstream.str().c_str());
7221 			tc_subroutine_indices[n_subroutine] =
7222 				gl.getSubroutineIndex(tc_po_id, GL_TESS_CONTROL_SHADER, tc_subroutine_name_sstream.str().c_str());
7223 			te_subroutine_indices[n_subroutine] =
7224 				gl.getSubroutineIndex(te_po_id, GL_TESS_EVALUATION_SHADER, te_subroutine_name_sstream.str().c_str());
7225 			vs_subroutine_indices[n_subroutine] =
7226 				gl.getSubroutineIndex(vs_po_id, GL_VERTEX_SHADER, vs_subroutine_name_sstream.str().c_str());
7227 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
7228 
7229 			if (fs_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7230 				gs_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7231 				tc_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7232 				te_subroutine_indices[n_subroutine] == (GLuint)-1 || vs_subroutine_indices[n_subroutine] == (GLuint)-1)
7233 			{
7234 				m_testCtx.getLog() << tcu::TestLog::Message
7235 								   << "At least one subroutine was not recognized by glGetSubroutineIndex() call. "
7236 									  "(fs:"
7237 								   << fs_subroutine_indices[n_subroutine]
7238 								   << ", gs:" << gs_subroutine_indices[n_subroutine]
7239 								   << ", tc:" << tc_subroutine_indices[n_subroutine]
7240 								   << ", te:" << te_subroutine_indices[n_subroutine]
7241 								   << ", vs:" << vs_subroutine_indices[n_subroutine] << ")."
7242 								   << tcu::TestLog::EndMessage;
7243 
7244 				TCU_FAIL("At least one subroutine was not recognized");
7245 			}
7246 		} /* for (both subroutines) */
7247 
7248 		/* Retrieve subroutine uniform indices */
7249 		fs_subroutine_uniform_index = gl.getSubroutineUniformLocation(fs_po_id, GL_FRAGMENT_SHADER, "function");
7250 		gs_subroutine_uniform_index = gl.getSubroutineUniformLocation(gs_po_id, GL_GEOMETRY_SHADER, "function");
7251 		tc_subroutine_uniform_index = gl.getSubroutineUniformLocation(tc_po_id, GL_TESS_CONTROL_SHADER, "function");
7252 		te_subroutine_uniform_index = gl.getSubroutineUniformLocation(te_po_id, GL_TESS_EVALUATION_SHADER, "function");
7253 		vs_subroutine_uniform_index = gl.getSubroutineUniformLocation(vs_po_id, GL_VERTEX_SHADER, "function");
7254 
7255 		if (fs_subroutine_uniform_index == -1 || gs_subroutine_uniform_index == -1 ||
7256 			tc_subroutine_uniform_index == -1 || te_subroutine_uniform_index == -1 || vs_subroutine_uniform_index == -1)
7257 		{
7258 			m_testCtx.getLog() << tcu::TestLog::Message << "At least one subroutine uniform is considered inactive by "
7259 														   "glGetSubroutineUniformLocation ("
7260 														   "fs:"
7261 							   << fs_subroutine_uniform_index << ", gs:" << gs_subroutine_uniform_index
7262 							   << ", tc:" << tc_subroutine_uniform_index << ", te:" << te_subroutine_uniform_index
7263 							   << ", vs:" << vs_subroutine_uniform_index << ")." << tcu::TestLog::EndMessage;
7264 
7265 			TCU_FAIL("At least one subroutine uniform is considered inactive");
7266 		}
7267 
7268 		/* Check if both subroutines work correctly in each stage */
7269 		for (int n_subroutine_permutation = 0; n_subroutine_permutation < 32; /* 2^5 */
7270 			 ++n_subroutine_permutation)
7271 		{
7272 			unsigned int n_fs_subroutine = ((n_subroutine_permutation & (1 << 0)) != 0) ? 1 : 0;
7273 			unsigned int n_gs_subroutine = ((n_subroutine_permutation & (1 << 1)) != 0) ? 1 : 0;
7274 			unsigned int n_tc_subroutine = ((n_subroutine_permutation & (1 << 2)) != 0) ? 1 : 0;
7275 			unsigned int n_te_subroutine = ((n_subroutine_permutation & (1 << 3)) != 0) ? 1 : 0;
7276 			unsigned int n_vs_subroutine = ((n_subroutine_permutation & (1 << 4)) != 0) ? 1 : 0;
7277 
7278 			/* Configure subroutine uniforms */
7279 			struct
7280 			{
7281 				glw::GLenum  stage;
7282 				glw::GLuint  po_id;
7283 				glw::GLuint* indices;
7284 			} configurations[] = {
7285 				{ GL_FRAGMENT_SHADER, fs_po_id, fs_subroutine_indices + n_fs_subroutine },
7286 				{ GL_GEOMETRY_SHADER, gs_po_id, gs_subroutine_indices + n_gs_subroutine },
7287 				{ GL_TESS_CONTROL_SHADER, tc_po_id, tc_subroutine_indices + n_tc_subroutine },
7288 				{ GL_TESS_EVALUATION_SHADER, te_po_id, te_subroutine_indices + n_te_subroutine },
7289 				{ GL_VERTEX_SHADER, vs_po_id, vs_subroutine_indices + n_vs_subroutine },
7290 			};
7291 
7292 			for (int i = 0; i < 5; ++i)
7293 			{
7294 				gl.activeShaderProgram(m_pipeline_id, configurations[i].po_id);
7295 				GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveShaderProgram() call failed.");
7296 
7297 				gl.uniformSubroutinesuiv(configurations[i].stage, 1 /* count */, configurations[i].indices);
7298 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
7299 			}
7300 
7301 			/* Render a full-screen quad with the pipeline */
7302 			gl.clear(GL_COLOR_BUFFER_BIT);
7303 			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
7304 
7305 			gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
7306 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7307 
7308 			/* Read color attachment's contents */
7309 			gl.readPixels(0, /* x */
7310 						  0, /* y */
7311 						  m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_read_buffer);
7312 			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
7313 
7314 			/* Verify the contents */
7315 			verifyReadBuffer(n_fs_idx, n_fs_subroutine, n_gs_idx, n_gs_subroutine, n_tc_idx, n_tc_subroutine, n_te_idx,
7316 							 n_te_subroutine, n_vs_idx, n_vs_subroutine);
7317 		} /* for (all subroutine permutations) */
7318 	}	 /* for (all program shader object permutations) */
7319 
7320 	/** All done */
7321 	if (m_has_test_passed)
7322 	{
7323 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7324 	}
7325 	else
7326 	{
7327 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7328 	}
7329 
7330 	return STOP;
7331 }
7332 
7333 /** Verifies the data that have been rendered using a pipeline object.
7334  *  Contents of the data depends on indices of the shaders, as well as
7335  *  on the subroutines that have been activated for particular iteration.
7336  *
7337  *  @param n_fs_id         Index of the fragment shader used for the iteration;
7338  *  @param n_fs_subroutine Index of the subroutine used in the fragment shader
7339  *                         for the iteration;
7340  *  @param n_gs_id         Index of the geometry shader used for the iteration;
7341  *  @param n_gs_subroutine Index of the subroutine used in the geometry shader
7342  *                         for the iteration;
7343  *  @param n_tc_id         Index of the tessellation control shader used for the iteration;
7344  *  @param n_tc_subroutine Index of the subroutine used in the tessellation control
7345  *                         shader for the iteration;
7346  *  @param n_te_id         Index of the tessellation evaluation shader used for the iteration;
7347  *  @param n_te_subroutine Index of the subroutine used in the tessellation evaluation
7348  *                         shader for the iteration;
7349  *  @param n_vs_id         Index of the vertex shader used for the iteration;
7350  *  @param n_vs_subroutine Index of the subroutine used in the vertex shader for
7351  *                         the iteration.
7352  */
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)7353 void FunctionalTest13::verifyReadBuffer(unsigned int n_fs_id, unsigned int n_fs_subroutine, unsigned int n_gs_id,
7354 										unsigned int n_gs_subroutine, unsigned int n_tc_id,
7355 										unsigned int n_tc_subroutine, unsigned int n_te_id,
7356 										unsigned int n_te_subroutine, unsigned int n_vs_id,
7357 										unsigned int n_vs_subroutine)
7358 {
7359 	float expected_color[4] = { 0 };
7360 	float fs_modifier[4]	= { 0 };
7361 	float gs_modifier[4]	= { 0 };
7362 	float tc_modifier[4]	= { 0 };
7363 	float te_modifier[4]	= { 0 };
7364 	float vs_modifier[4]	= { 0 };
7365 
7366 	if (n_fs_subroutine == 0)
7367 	{
7368 		for (unsigned int n_component = 0; n_component < 4; ++n_component)
7369 		{
7370 			fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 10.0f;
7371 		}
7372 	}
7373 	else
7374 	{
7375 		for (unsigned int n_component = 0; n_component < 4; ++n_component)
7376 		{
7377 			fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 20.0f;
7378 		}
7379 	}
7380 
7381 	if (n_gs_subroutine == 0)
7382 	{
7383 		gs_modifier[3] = float(n_gs_id + 1) * 0.425f;
7384 	}
7385 	else
7386 	{
7387 		gs_modifier[3] = float(n_gs_id + 1) * 0.0425f;
7388 	}
7389 
7390 	if (n_tc_subroutine == 0)
7391 	{
7392 		tc_modifier[1] = float(n_tc_id + 1) * 0.25f;
7393 	}
7394 	else
7395 	{
7396 		tc_modifier[1] = float(n_tc_id + 1) * 0.025f;
7397 	}
7398 
7399 	if (n_te_subroutine == 0)
7400 	{
7401 		te_modifier[2] = float(n_te_id + 1) * 0.325f;
7402 	}
7403 	else
7404 	{
7405 		te_modifier[2] = float(n_te_id + 1) * 0.0325f;
7406 	}
7407 
7408 	if (n_vs_subroutine == 0)
7409 	{
7410 		vs_modifier[0] = float(n_vs_id + 1) * 0.125f;
7411 	}
7412 	else
7413 	{
7414 		vs_modifier[0] = float(n_vs_id + 1) * 0.0125f;
7415 	}
7416 
7417 	/* Determine the expected color */
7418 	for (unsigned int n_component = 0; n_component < 4 /* rgba */; ++n_component)
7419 	{
7420 		expected_color[n_component] = fs_modifier[n_component] + gs_modifier[n_component] + tc_modifier[n_component] +
7421 									  te_modifier[n_component] + vs_modifier[n_component];
7422 	}
7423 
7424 	/* Verify all read texels are valid */
7425 	const float epsilon			= 1e-5f;
7426 	bool		should_continue = true;
7427 
7428 	for (unsigned int y = 0; y < m_to_height && should_continue; ++y)
7429 	{
7430 		const float* row_ptr = (const float*)m_read_buffer + y * m_to_width * 4; /* rgba */
7431 
7432 		for (unsigned int x = 0; x < m_to_width && should_continue; ++x)
7433 		{
7434 			const float* texel_ptr = row_ptr + x * 4; /* rgba */
7435 
7436 			if (de::abs(texel_ptr[0] - expected_color[0]) > epsilon ||
7437 				de::abs(texel_ptr[1] - expected_color[1]) > epsilon ||
7438 				de::abs(texel_ptr[2] - expected_color[2]) > epsilon ||
7439 				de::abs(texel_ptr[3] - expected_color[3]) > epsilon)
7440 			{
7441 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel rendered at (" << x << ", " << y
7442 								   << ") for "
7443 									  "the following configuration: "
7444 									  "n_fs_id:"
7445 								   << n_fs_id << " n_fs_subroutine:" << n_fs_subroutine << " n_gs_id:" << n_gs_id
7446 								   << " n_gs_subroutine:" << n_gs_subroutine << " n_tc_id:" << n_tc_id
7447 								   << " n_tc_subroutine:" << n_tc_subroutine << " n_te_id:" << n_te_id
7448 								   << " n_te_subroutine:" << n_te_subroutine << " n_vs_id:" << n_vs_id
7449 								   << " n_vs_subroutine:" << n_vs_subroutine << "; expected:"
7450 																				"("
7451 								   << expected_color[0] << ", " << expected_color[1] << ", " << expected_color[2]
7452 								   << ", " << expected_color[3] << "), found:"
7453 																   "("
7454 								   << texel_ptr[0] << ", " << texel_ptr[1] << ", " << texel_ptr[2] << ", "
7455 								   << texel_ptr[3] << ")." << tcu::TestLog::EndMessage;
7456 
7457 				m_has_test_passed = false;
7458 				should_continue   = false;
7459 			}
7460 		} /* for (all columns) */
7461 	}	 /* for (all rows) */
7462 }
7463 
7464 /** Constructor
7465  *
7466  * @param context CTS context
7467  **/
FunctionalTest14_15(deqp::Context & context)7468 FunctionalTest14_15::FunctionalTest14_15(deqp::Context& context)
7469 	: TestCase(context, "structure_parameters_program_binary", "Verify structures can be used as parameters")
7470 	, m_uniform_location(0)
7471 {
7472 }
7473 
7474 /** Execute test
7475  *
7476  * @return tcu::TestNode::STOP
7477  **/
iterate()7478 tcu::TestNode::IterateResult FunctionalTest14_15::iterate()
7479 {
7480 	static const GLchar* vertex_shader_code =
7481 		"#version 400 core\n"
7482 		"#extension GL_ARB_shader_subroutine : require\n"
7483 		"\n"
7484 		"precision highp float;\n"
7485 		"\n"
7486 		"struct data\n"
7487 		"{\n"
7488 		"    uint r;\n"
7489 		"    uint g;\n"
7490 		"    uint b;\n"
7491 		"    uint a;\n"
7492 		"};\n"
7493 		"\n"
7494 		"subroutine void routine_type_1(in data iparam, out data oparam);\n"
7495 		"subroutine void routine_type_2(inout data arg);\n"
7496 		"\n"
7497 		"subroutine (routine_type_1) void invert(in data iparam, out data oparam)\n"
7498 		"{\n"
7499 		"    oparam.r = iparam.a;\n"
7500 		"    oparam.g = iparam.b;\n"
7501 		"    oparam.b = iparam.g;\n"
7502 		"    oparam.a = iparam.r;\n"
7503 		"}\n"
7504 		"\n"
7505 		"subroutine (routine_type_1) void increment(in data iparam, out data oparam)\n"
7506 		"{\n"
7507 		"    oparam.r = 1 + iparam.r;\n"
7508 		"    oparam.g = 1 + iparam.g;\n"
7509 		"    oparam.b = 1 + iparam.b;\n"
7510 		"    oparam.a = 1 + iparam.a;\n"
7511 		"}\n"
7512 		"\n"
7513 		"subroutine (routine_type_2) void div_by_2(inout data arg)\n"
7514 		"{\n"
7515 		"    arg.r = arg.r / 2;\n"
7516 		"    arg.g = arg.g / 2;\n"
7517 		"    arg.b = arg.b / 2;\n"
7518 		"    arg.a = arg.a / 2;\n"
7519 		"}\n"
7520 		"\n"
7521 		"subroutine (routine_type_2) void decrement(inout data arg)\n"
7522 		"{\n"
7523 		"    arg.r = arg.r - 1;\n"
7524 		"    arg.g = arg.g - 1;\n"
7525 		"    arg.b = arg.b - 1;\n"
7526 		"    arg.a = arg.a - 1;\n"
7527 		"}\n"
7528 		"\n"
7529 		"subroutine uniform routine_type_1 routine_1;\n"
7530 		"subroutine uniform routine_type_2 routine_2;\n"
7531 		"\n"
7532 		"uniform uvec4 uni_input;\n"
7533 		"\n"
7534 		"out uvec4 out_routine_1;\n"
7535 		"out uvec4 out_routine_2;\n"
7536 		"\n"
7537 		"\n"
7538 		"void main()\n"
7539 		"{\n"
7540 		"    data routine_1_input;\n"
7541 		"    data routine_1_output;\n"
7542 		"    data routine_2_arg;\n"
7543 		"\n"
7544 		"    routine_1_input.r = uni_input.r;\n"
7545 		"    routine_1_input.g = uni_input.g;\n"
7546 		"    routine_1_input.b = uni_input.b;\n"
7547 		"    routine_1_input.a = uni_input.a;\n"
7548 		"\n"
7549 		"    routine_2_arg.r = uni_input.r;\n"
7550 		"    routine_2_arg.g = uni_input.g;\n"
7551 		"    routine_2_arg.b = uni_input.b;\n"
7552 		"    routine_2_arg.a = uni_input.a;\n"
7553 		"\n"
7554 		"    routine_1(routine_1_input, routine_1_output);\n"
7555 		"    routine_2(routine_2_arg);\n"
7556 		"\n"
7557 		"    out_routine_1.r = routine_1_output.r;\n"
7558 		"    out_routine_1.g = routine_1_output.g;\n"
7559 		"    out_routine_1.b = routine_1_output.b;\n"
7560 		"    out_routine_1.a = routine_1_output.a;\n"
7561 		"\n"
7562 		"    out_routine_2.r = routine_2_arg.r;\n"
7563 		"    out_routine_2.g = routine_2_arg.g;\n"
7564 		"    out_routine_2.b = routine_2_arg.b;\n"
7565 		"    out_routine_2.a = routine_2_arg.a;\n"
7566 		"}\n"
7567 		"\n";
7568 
7569 	static const GLchar* subroutine_names[][2] = { { "invert", "increment" }, { "div_by_2", "decrement" } };
7570 	static const GLuint  n_subroutine_types	= sizeof(subroutine_names) / sizeof(subroutine_names[0]);
7571 
7572 	static const GLchar* subroutine_uniform_names[] = { "routine_1", "routine_2" };
7573 	static const GLuint  n_subroutine_uniform_names =
7574 		sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
7575 
7576 	static const GLchar* uniform_name	= "uni_input";
7577 	static const GLchar* varying_names[] = { "out_routine_1", "out_routine_2" };
7578 
7579 	static const GLuint n_varying_names				   = sizeof(varying_names) / sizeof(varying_names[0]);
7580 	static const GLuint transform_feedback_buffer_size = n_varying_names * 4 * sizeof(GLuint);
7581 
7582 	/* Test data */
7583 	static const Utils::vec4<GLuint> uni_input[] = { Utils::vec4<GLuint>(8, 64, 4096, 16777216),
7584 													 Utils::vec4<GLuint>(8, 64, 4096, 16777216) };
7585 
7586 	static const Utils::vec4<GLuint> out_routine_1[] = { Utils::vec4<GLuint>(16777216, 4096, 64, 8),
7587 														 Utils::vec4<GLuint>(9, 65, 4097, 16777217) };
7588 
7589 	static const Utils::vec4<GLuint> out_routine_2[] = { Utils::vec4<GLuint>(4, 32, 2048, 8388608),
7590 														 Utils::vec4<GLuint>(7, 63, 4095, 16777215) };
7591 
7592 	static const GLuint n_test_cases = 2;
7593 
7594 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
7595 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
7596 	{
7597 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
7598 	}
7599 
7600 	/* GL objects */
7601 	Utils::program	 program(m_context);
7602 	Utils::buffer	  transform_feedback_buffer(m_context);
7603 	Utils::vertexArray vao(m_context);
7604 
7605 	bool is_program_binary_supported = program.isProgramBinarySupported();
7606 
7607 	/* Init GL objects */
7608 	program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code,
7609 				  varying_names /* varying_names */, n_varying_names /* n_varyings */);
7610 
7611 	/* Do not execute the test if GL_ARB_get_program_binary is not supported */
7612 	if (true == is_program_binary_supported)
7613 	{
7614 		/* Get subroutine indices */
7615 		for (GLuint type = 0; type < n_subroutine_types; ++type)
7616 		{
7617 			m_initial_subroutine_indices[type][0] =
7618 				program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER);
7619 
7620 			m_initial_subroutine_indices[type][1] =
7621 				program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER);
7622 		}
7623 
7624 		/* Get subroutine uniform locations */
7625 		for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7626 		{
7627 			m_initial_subroutine_uniform_locations[uniform] =
7628 				program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
7629 		}
7630 
7631 		/* Delete program and recreate it from binary */
7632 		std::vector<GLubyte> program_binary;
7633 		GLenum				 binary_format;
7634 
7635 		program.getBinary(program_binary, binary_format);
7636 		program.remove();
7637 		program.createFromBinary(program_binary, binary_format);
7638 	}
7639 
7640 	program.use();
7641 
7642 	vao.generate();
7643 	vao.bind();
7644 
7645 	transform_feedback_buffer.generate();
7646 	transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
7647 									 GL_DYNAMIC_COPY);
7648 	transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
7649 
7650 	/* Get subroutine indices */
7651 	for (GLuint type = 0; type < n_subroutine_types; ++type)
7652 	{
7653 		m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER);
7654 		m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER);
7655 	}
7656 
7657 	/* Get subroutine uniform locations */
7658 	for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7659 	{
7660 		m_subroutine_uniform_locations[uniform] =
7661 			program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
7662 	}
7663 
7664 	/* Get uniform locations */
7665 	m_uniform_location = program.getUniformLocation(uniform_name);
7666 
7667 	/* Test */
7668 	bool result = true;
7669 
7670 	/* Test program binary */
7671 	if (true == is_program_binary_supported)
7672 	{
7673 		/* Test indices and locations */
7674 		if (false == testIndicesAndLocations())
7675 		{
7676 			static const GLuint n_subroutines_per_type = 2;
7677 
7678 			m_context.getTestContext().getLog() << tcu::TestLog::Message
7679 												<< "Error. Subroutine indices or subroutine uniform location changed."
7680 												<< tcu::TestLog::EndMessage;
7681 
7682 			for (GLuint type = 0; type < n_subroutine_types; ++type)
7683 			{
7684 				for (GLuint i = 0; i < n_subroutines_per_type; ++i)
7685 				{
7686 					m_context.getTestContext().getLog()
7687 						<< tcu::TestLog::Message << "Subroutine: " << subroutine_names[type][i]
7688 						<< " index: " << m_subroutine_indices[type][i]
7689 						<< " initial index: " << m_initial_subroutine_indices[type][i] << tcu::TestLog::EndMessage;
7690 				}
7691 			}
7692 
7693 			for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7694 			{
7695 				m_context.getTestContext().getLog()
7696 					<< tcu::TestLog::Message << "Subroutine uniform: " << subroutine_uniform_names[uniform]
7697 					<< " location: " << m_subroutine_uniform_locations[uniform]
7698 					<< " initial location: " << m_initial_subroutine_uniform_locations[uniform]
7699 					<< tcu::TestLog::EndMessage;
7700 			}
7701 
7702 			result = false;
7703 		}
7704 
7705 		/* Test draw with deafult set of subroutines */
7706 		if (false == testDefaultSubroutineSet(uni_input[0], out_routine_1, out_routine_2))
7707 		{
7708 			result = false;
7709 		}
7710 	}
7711 
7712 	for (GLuint i = 0; i < n_test_cases; ++i)
7713 	{
7714 		if (false == testDraw(i, uni_input[i], out_routine_1[i], out_routine_2[i]))
7715 		{
7716 			result = false;
7717 		}
7718 	}
7719 
7720 	/* Set result */
7721 	if (true == result)
7722 	{
7723 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7724 	}
7725 	else
7726 	{
7727 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7728 	}
7729 
7730 	/* Done */
7731 	return tcu::TestNode::STOP;
7732 }
7733 
7734 /** Execute draw call and verify results
7735  *
7736  * @param uni_input                 Input data
7737  * @param expected_routine_1_result Set of expected results of "routine_1"
7738  * @param expected_routine_2_result Set of expected results of "routine_2"
7739  *
7740  * @return true if test pass, false otherwise
7741  **/
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]) const7742 bool FunctionalTest14_15::testDefaultSubroutineSet(const Utils::vec4<glw::GLuint>& uni_input,
7743 												   const Utils::vec4<glw::GLuint>  expected_routine_1_result[2],
7744 												   const Utils::vec4<glw::GLuint>  expected_routine_2_result[2]) const
7745 {
7746 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
7747 	bool				  result = true;
7748 
7749 	/* Set up input data uniforms */
7750 	gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w);
7751 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
7752 
7753 	/* Execute draw call with transform feedback */
7754 	gl.beginTransformFeedback(GL_POINTS);
7755 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
7756 
7757 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
7758 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
7759 
7760 	gl.endTransformFeedback();
7761 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
7762 
7763 	/* Capture results */
7764 	GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7765 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
7766 
7767 	Utils::vec4<GLuint> routine_1_result;
7768 	Utils::vec4<GLuint> routine_2_result;
7769 
7770 	routine_1_result.m_x = feedback_data[0 + 0];
7771 	routine_1_result.m_y = feedback_data[0 + 1];
7772 	routine_1_result.m_z = feedback_data[0 + 2];
7773 	routine_1_result.m_w = feedback_data[0 + 3];
7774 
7775 	routine_2_result.m_x = feedback_data[4 + 0];
7776 	routine_2_result.m_y = feedback_data[4 + 1];
7777 	routine_2_result.m_z = feedback_data[4 + 2];
7778 	routine_2_result.m_w = feedback_data[4 + 3];
7779 
7780 	/* Unmap buffer */
7781 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7782 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
7783 
7784 	/* Verifiy */
7785 	result = result &&
7786 			 ((routine_1_result == expected_routine_1_result[0]) || (routine_1_result == expected_routine_1_result[1]));
7787 
7788 	result = result &&
7789 			 ((routine_2_result == expected_routine_2_result[0]) || (routine_2_result == expected_routine_2_result[1]));
7790 
7791 	/* Log error if any */
7792 	if (false == result)
7793 	{
7794 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
7795 											<< tcu::TestLog::EndMessage;
7796 
7797 		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
7798 
7799 		message << "Routine_1, result: ";
7800 
7801 		routine_1_result.log(message);
7802 
7803 		message << "Routine_2, result: ";
7804 
7805 		routine_2_result.log(message);
7806 
7807 		message << tcu::TestLog::EndMessage;
7808 	}
7809 
7810 	/* Done */
7811 	return result;
7812 }
7813 
7814 /** Execute draw call and verify results
7815  *
7816  * @param routine_configuration     Subroutine "type" ordinal
7817  * @param uni_input                 Input data
7818  * @param expected_routine_1_result Expected results of "routine_1"
7819  * @param expected_routine_2_result Expected results of "routine_2"
7820  *
7821  * @return true if test pass, false otherwise
7822  **/
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) const7823 bool FunctionalTest14_15::testDraw(glw::GLuint routine_configuration, const Utils::vec4<glw::GLuint>& uni_input,
7824 								   const Utils::vec4<glw::GLuint>& expected_routine_1_result,
7825 								   const Utils::vec4<glw::GLuint>& expected_routine_2_result) const
7826 {
7827 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
7828 	bool				  result = true;
7829 	GLuint				  subroutine_indices[2];
7830 	static const GLuint   n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
7831 
7832 	/* Set up input data uniforms */
7833 	gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w);
7834 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
7835 
7836 	/* Prepare subroutine uniform data */
7837 	for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
7838 	{
7839 		const GLuint location = m_subroutine_uniform_locations[i];
7840 
7841 		subroutine_indices[location] = m_subroutine_indices[i][routine_configuration];
7842 	}
7843 
7844 	/* Set up subroutine uniforms */
7845 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
7846 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
7847 
7848 	/* Execute draw call with transform feedback */
7849 	gl.beginTransformFeedback(GL_POINTS);
7850 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
7851 
7852 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
7853 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
7854 
7855 	gl.endTransformFeedback();
7856 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
7857 
7858 	/* Capture results */
7859 	GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7860 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
7861 
7862 	Utils::vec4<GLuint> routine_1_result;
7863 	Utils::vec4<GLuint> routine_2_result;
7864 
7865 	routine_1_result.m_x = feedback_data[0 + 0];
7866 	routine_1_result.m_y = feedback_data[0 + 1];
7867 	routine_1_result.m_z = feedback_data[0 + 2];
7868 	routine_1_result.m_w = feedback_data[0 + 3];
7869 
7870 	routine_2_result.m_x = feedback_data[4 + 0];
7871 	routine_2_result.m_y = feedback_data[4 + 1];
7872 	routine_2_result.m_z = feedback_data[4 + 2];
7873 	routine_2_result.m_w = feedback_data[4 + 3];
7874 
7875 	/* Unmap buffer */
7876 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7877 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
7878 
7879 	/* Verifiy */
7880 	result = result && (routine_1_result == expected_routine_1_result);
7881 	result = result && (routine_2_result == expected_routine_2_result);
7882 
7883 	/* Log error if any */
7884 	if (false == result)
7885 	{
7886 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
7887 											<< tcu::TestLog::EndMessage;
7888 
7889 		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
7890 
7891 		message << "Routine_1, result: ";
7892 
7893 		routine_1_result.log(message);
7894 
7895 		message << ", expected: ";
7896 
7897 		expected_routine_1_result.log(message);
7898 
7899 		message << "Routine_2, result: ";
7900 
7901 		routine_2_result.log(message);
7902 
7903 		message << ", expected: ";
7904 
7905 		expected_routine_2_result.log(message);
7906 
7907 		message << tcu::TestLog::EndMessage;
7908 	}
7909 
7910 	/* Done */
7911 	return result;
7912 }
7913 
7914 /** Verify initial and current values of subroutine indices and subroutines uniform locations
7915  *
7916  * @return true if test pass, false otherwise
7917  **/
testIndicesAndLocations() const7918 bool FunctionalTest14_15::testIndicesAndLocations() const
7919 {
7920 	static const GLuint n_subroutine_types = 2;
7921 	bool				result			   = true;
7922 
7923 	/* Verify subroutine indices */
7924 	for (GLuint type = 0; type < n_subroutine_types; ++type)
7925 	{
7926 		result = result && (m_subroutine_indices[type][0] == m_initial_subroutine_indices[type][0]);
7927 		result = result && (m_subroutine_indices[type][1] == m_initial_subroutine_indices[type][1]);
7928 	}
7929 
7930 	/* Verify subroutine uniform locations */
7931 	for (GLuint uniform = 0; uniform < n_subroutine_types; ++uniform)
7932 	{
7933 		result = result && (m_subroutine_uniform_locations[uniform] == m_initial_subroutine_uniform_locations[uniform]);
7934 	}
7935 
7936 	return result;
7937 }
7938 
7939 /** Constructor.
7940  *
7941  *  @param context Rendering context.
7942  *
7943  **/
FunctionalTest16(deqp::Context & context)7944 FunctionalTest16::FunctionalTest16(deqp::Context& context)
7945 	: TestCase(context, "subroutine_uniform_reset",
7946 			   "Checks that when the active program for a shader stage is re-linke or "
7947 			   "changed by a call to UseProgram, BindProgramPipeline, or UseProgramStages,"
7948 			   " subroutine uniforms for that stage are reset to arbitrarily chosen default "
7949 			   "functions with compatible subroutine types.")
7950 	, m_are_pipeline_objects_supported(false)
7951 	, m_has_test_passed(true)
7952 {
7953 	memset(m_fs_ids, 0, sizeof(m_fs_ids));
7954 	memset(m_gs_ids, 0, sizeof(m_gs_ids));
7955 	memset(m_po_ids, 0, sizeof(m_po_ids));
7956 	memset(m_tc_ids, 0, sizeof(m_tc_ids));
7957 	memset(m_te_ids, 0, sizeof(m_te_ids));
7958 	memset(m_vs_ids, 0, sizeof(m_vs_ids));
7959 
7960 	memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids));
7961 	memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids));
7962 	memset(m_pipeline_object_ids, 0, sizeof(m_pipeline_object_ids));
7963 	memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids));
7964 	memset(m_te_po_ids, 0, sizeof(m_te_po_ids));
7965 	memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids));
7966 }
7967 
7968 /** Deinitializes all GL objects that may have been created during test execution. */
deinit()7969 void FunctionalTest16::deinit()
7970 {
7971 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7972 
7973 	for (unsigned int n_id = 0; n_id < 2; ++n_id)
7974 	{
7975 		if (m_fs_ids[n_id] != 0)
7976 		{
7977 			gl.deleteShader(m_fs_ids[n_id]);
7978 
7979 			m_fs_ids[n_id] = 0;
7980 		}
7981 
7982 		if (m_fs_po_ids[n_id] != 0)
7983 		{
7984 			gl.deleteProgram(m_fs_po_ids[n_id]);
7985 
7986 			m_fs_po_ids[n_id] = 0;
7987 		}
7988 
7989 		if (m_gs_ids[n_id] != 0)
7990 		{
7991 			gl.deleteShader(m_gs_ids[n_id]);
7992 
7993 			m_gs_ids[n_id] = 0;
7994 		}
7995 
7996 		if (m_gs_po_ids[n_id] != 0)
7997 		{
7998 			gl.deleteProgram(m_gs_po_ids[n_id]);
7999 
8000 			m_gs_po_ids[n_id] = 0;
8001 		}
8002 
8003 		if (m_pipeline_object_ids[n_id] != 0)
8004 		{
8005 			gl.deleteProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id);
8006 		}
8007 
8008 		if (m_po_ids[n_id] != 0)
8009 		{
8010 			gl.deleteProgram(m_po_ids[n_id]);
8011 
8012 			m_po_ids[n_id] = 0;
8013 		}
8014 
8015 		if (m_tc_ids[n_id] != 0)
8016 		{
8017 			gl.deleteShader(m_tc_ids[n_id]);
8018 
8019 			m_tc_ids[n_id] = 0;
8020 		}
8021 
8022 		if (m_tc_po_ids[n_id] != 0)
8023 		{
8024 			gl.deleteProgram(m_tc_po_ids[n_id]);
8025 
8026 			m_tc_po_ids[n_id] = 0;
8027 		}
8028 
8029 		if (m_te_ids[n_id] != 0)
8030 		{
8031 			gl.deleteShader(m_te_ids[n_id]);
8032 
8033 			m_te_ids[n_id] = 0;
8034 		}
8035 
8036 		if (m_te_po_ids[n_id] != 0)
8037 		{
8038 			gl.deleteProgram(m_te_po_ids[n_id]);
8039 
8040 			m_te_po_ids[n_id] = 0;
8041 		}
8042 
8043 		if (m_vs_ids[n_id] != 0)
8044 		{
8045 			gl.deleteShader(m_vs_ids[n_id]);
8046 
8047 			m_vs_ids[n_id] = 0;
8048 		}
8049 
8050 		if (m_vs_po_ids[n_id] != 0)
8051 		{
8052 			gl.deleteProgram(m_vs_po_ids[n_id]);
8053 
8054 			m_vs_po_ids[n_id] = 0;
8055 		}
8056 	} /* for (both IDs) */
8057 }
8058 
8059 /** Retrieves body of a shader that should be used for user-specified shader stage.
8060  *  This function returns slightly different implementations, depending on index of
8061  *  the program/pipeline object the shader will be used for.
8062  *
8063  *  @param shader_stage Stage the shader body is to be returned for.
8064  *  @param n_id         Index of the shader (as per description).
8065  *
8066  *  @return Requested string.
8067  **/
getShaderBody(const Utils::_shader_stage & shader_stage,const unsigned int & n_id) const8068 std::string FunctionalTest16::getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_id) const
8069 {
8070 	std::stringstream result_sstream;
8071 
8072 	result_sstream << "#version 400\n"
8073 					  "\n"
8074 					  "#extension GL_ARB_shader_subroutine : require\n"
8075 					  "\n";
8076 
8077 	switch (shader_stage)
8078 	{
8079 	case Utils::SHADER_STAGE_VERTEX:
8080 	{
8081 		result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n";
8082 		break;
8083 	}
8084 	case Utils::SHADER_STAGE_GEOMETRY:
8085 	{
8086 		result_sstream << "layout(points)                   in;\n"
8087 						  "layout(points, max_vertices = 1) out;\n";
8088 		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8089 		result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n";
8090 		break;
8091 	}
8092 
8093 	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
8094 	{
8095 		result_sstream << "layout(vertices = 4) out;\n";
8096 		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8097 		result_sstream << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n";
8098 		break;
8099 	}
8100 
8101 	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
8102 	{
8103 		result_sstream << "layout(quads) in;\n";
8104 		result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8105 		result_sstream << "out gl_PerVertex { vec4 gl_Position; };\n";
8106 		break;
8107 	}
8108 
8109 	default:
8110 		break;
8111 	} /* switch (shader_stage) */
8112 
8113 	result_sstream << "\n"
8114 					  "subroutine void subroutineType (inout vec4 result);\n"
8115 					  "subroutine vec4 subroutineType2(in    vec4 data);\n"
8116 					  "\n"
8117 					  "subroutine(subroutineType) void function1(inout vec4 result)\n"
8118 					  "{\n"
8119 					  "    result += vec4("
8120 				   << (n_id + 1) << ", " << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4)
8121 				   << ");\n"
8122 					  "}\n"
8123 					  "subroutine(subroutineType) void function2(inout vec4 result)\n"
8124 					  "{\n"
8125 					  "    result += vec4("
8126 				   << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4) << ", " << (n_id + 5)
8127 				   << ");\n"
8128 					  "}\n"
8129 					  "\n"
8130 					  "subroutine(subroutineType2) vec4 function3(in vec4 data)\n"
8131 					  "{\n"
8132 					  "    return data * data;\n"
8133 					  "}\n"
8134 					  "subroutine(subroutineType2) vec4 function4(in vec4 data)\n"
8135 					  "{\n"
8136 					  "    return data + data;\n"
8137 					  "}\n"
8138 					  "\n"
8139 					  "subroutine uniform subroutineType  subroutine1;\n"
8140 					  "subroutine uniform subroutineType  subroutine2;\n"
8141 					  "subroutine uniform subroutineType2 subroutine3;\n"
8142 					  "subroutine uniform subroutineType2 subroutine4;\n"
8143 					  "\n";
8144 
8145 	if (shader_stage == Utils::SHADER_STAGE_FRAGMENT)
8146 	{
8147 		result_sstream << "out vec4 result;\n";
8148 	}
8149 
8150 	result_sstream << "void main()\n"
8151 					  "{\n";
8152 
8153 	switch (shader_stage)
8154 	{
8155 	case Utils::SHADER_STAGE_FRAGMENT:
8156 	{
8157 		result_sstream << "    result = vec4(0);\n"
8158 					   << "    subroutine1(result);\n"
8159 						  "    subroutine2(result);\n"
8160 						  "    result = subroutine3(result) + subroutine4(result);\n";
8161 
8162 		break;
8163 	}
8164 
8165 	case Utils::SHADER_STAGE_GEOMETRY:
8166 	{
8167 		result_sstream << "    gl_Position = vec4(0);\n"
8168 						  "    subroutine1(gl_Position);\n"
8169 						  "    subroutine2(gl_Position);\n"
8170 						  "    gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n"
8171 						  "    EmitVertex();\n";
8172 
8173 		break;
8174 	}
8175 
8176 	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
8177 	{
8178 		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0);\n"
8179 						  "    subroutine1(gl_out[gl_InvocationID].gl_Position);\n"
8180 						  "    subroutine2(gl_out[gl_InvocationID].gl_Position);\n"
8181 						  "    gl_out[gl_InvocationID].gl_Position = subroutine3(gl_in[0].gl_Position) + "
8182 						  "subroutine4(gl_in[0].gl_Position);\n";
8183 
8184 		break;
8185 	}
8186 
8187 	case Utils::SHADER_STAGE_VERTEX:
8188 	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
8189 	{
8190 		result_sstream << "    gl_Position = vec4(0);\n"
8191 						  "    subroutine1(gl_Position);\n"
8192 						  "    subroutine2(gl_Position);\n"
8193 						  "    gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n";
8194 
8195 		break;
8196 	}
8197 
8198 	default:
8199 		break;
8200 	} /* switch (shader_stage) */
8201 
8202 	result_sstream << "}\n";
8203 
8204 	return result_sstream.str();
8205 }
8206 
8207 /** Initializes all objects required to run the test. */
initTest()8208 void FunctionalTest16::initTest()
8209 {
8210 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8211 
8212 	for (unsigned int n_id = 0; n_id < 2 /* test program/shader objects */; ++n_id)
8213 	{
8214 		const std::string fs_body = getShaderBody(Utils::SHADER_STAGE_FRAGMENT, n_id);
8215 		const std::string gs_body = getShaderBody(Utils::SHADER_STAGE_GEOMETRY, n_id);
8216 		const std::string tc_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_CONTROL, n_id);
8217 		const std::string te_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_EVALUATION, n_id);
8218 		const std::string vs_body = getShaderBody(Utils::SHADER_STAGE_VERTEX, n_id);
8219 
8220 		if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */
8221 								 DE_NULL,												   /* n_xfb_varyings */
8222 								 m_vs_ids + n_id, m_tc_ids + n_id, m_te_ids + n_id, m_gs_ids + n_id, m_fs_ids + n_id,
8223 								 m_po_ids + n_id))
8224 		{
8225 			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build test program object, index:"
8226 														   "["
8227 							   << n_id << "]" << tcu::TestLog::EndMessage;
8228 
8229 			TCU_FAIL("Failed to build a test program");
8230 		}
8231 
8232 		if (m_are_pipeline_objects_supported)
8233 		{
8234 			/* Initialize shader program objects */
8235 			const char* fs_body_raw_ptr = fs_body.c_str();
8236 			const char* gs_body_raw_ptr = gs_body.c_str();
8237 			glw::GLint  link_status[5]  = { GL_FALSE };
8238 			const char* tc_body_raw_ptr = tc_body.c_str();
8239 			const char* te_body_raw_ptr = te_body.c_str();
8240 			const char* vs_body_raw_ptr = vs_body.c_str();
8241 
8242 			m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr);
8243 			m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr);
8244 			m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr);
8245 			m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr);
8246 			m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr);
8247 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
8248 
8249 			gl.getProgramiv(m_fs_po_ids[n_id], GL_LINK_STATUS, link_status + 0);
8250 			gl.getProgramiv(m_gs_po_ids[n_id], GL_LINK_STATUS, link_status + 1);
8251 			gl.getProgramiv(m_tc_po_ids[n_id], GL_LINK_STATUS, link_status + 2);
8252 			gl.getProgramiv(m_te_po_ids[n_id], GL_LINK_STATUS, link_status + 3);
8253 			gl.getProgramiv(m_vs_po_ids[n_id], GL_LINK_STATUS, link_status + 4);
8254 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8255 
8256 			if (link_status[0] == GL_FALSE)
8257 				TCU_FAIL("Fragment shader program failed to link");
8258 			if (link_status[1] == GL_FALSE)
8259 				TCU_FAIL("Geometry shader program failed to link");
8260 			if (link_status[2] == GL_FALSE)
8261 				TCU_FAIL("Tessellation control shader program failed to link");
8262 			if (link_status[3] == GL_FALSE)
8263 				TCU_FAIL("Tessellation evaluation shader program failed to link");
8264 			if (link_status[4] == GL_FALSE)
8265 				TCU_FAIL("Vertex shader program failed to link");
8266 
8267 			/* Initialize pipeline program object */
8268 			gl.genProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id);
8269 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
8270 
8271 			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_FRAGMENT_SHADER_BIT, m_fs_po_ids[n_id]);
8272 			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_GEOMETRY_SHADER_BIT, m_gs_po_ids[n_id]);
8273 			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_CONTROL_SHADER_BIT, m_tc_po_ids[n_id]);
8274 			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_EVALUATION_SHADER_BIT, m_te_po_ids[n_id]);
8275 			gl.useProgramStages(m_pipeline_object_ids[n_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_id]);
8276 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8277 		}
8278 
8279 		/* Retrieve subroutine locations */
8280 		struct _item
8281 		{
8282 			glw::GLuint	po_id;
8283 			_shader_stage& stage;
8284 			glw::GLuint	so_id;
8285 			glw::GLenum	so_type;
8286 		} items[] = {
8287 			{ m_po_ids[n_id], m_po_descriptors[n_id].fragment, m_fs_ids[n_id], GL_FRAGMENT_SHADER },
8288 			{ m_po_ids[n_id], m_po_descriptors[n_id].geometry, m_gs_ids[n_id], GL_GEOMETRY_SHADER },
8289 			{ m_po_ids[n_id], m_po_descriptors[n_id].tess_control, m_tc_ids[n_id], GL_TESS_CONTROL_SHADER },
8290 			{ m_po_ids[n_id], m_po_descriptors[n_id].tess_evaluation, m_te_ids[n_id], GL_TESS_EVALUATION_SHADER },
8291 			{ m_po_ids[n_id], m_po_descriptors[n_id].vertex, m_vs_ids[n_id], GL_VERTEX_SHADER },
8292 
8293 			{ m_fs_po_ids[n_id], m_fs_po_descriptors[n_id], m_fs_po_ids[n_id], GL_FRAGMENT_SHADER },
8294 			{ m_gs_po_ids[n_id], m_gs_po_descriptors[n_id], m_gs_po_ids[n_id], GL_GEOMETRY_SHADER },
8295 			{ m_tc_po_ids[n_id], m_tc_po_descriptors[n_id], m_tc_po_ids[n_id], GL_TESS_CONTROL_SHADER },
8296 			{ m_te_po_ids[n_id], m_te_po_descriptors[n_id], m_te_po_ids[n_id], GL_TESS_EVALUATION_SHADER },
8297 			{ m_vs_po_ids[n_id], m_vs_po_descriptors[n_id], m_vs_po_ids[n_id], GL_VERTEX_SHADER },
8298 		};
8299 		const unsigned int n_items = sizeof(items) / sizeof(items[0]);
8300 
8301 		for (unsigned int n_item = 0; n_item < n_items; ++n_item)
8302 		{
8303 			_item& current_item = items[n_item];
8304 
8305 			current_item.stage.function1_index =
8306 				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function1");
8307 			current_item.stage.function2_index =
8308 				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function2");
8309 			current_item.stage.function3_index =
8310 				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function3");
8311 			current_item.stage.function4_index =
8312 				gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function4");
8313 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
8314 
8315 			if (current_item.stage.function1_index == GL_INVALID_INDEX ||
8316 				current_item.stage.function2_index == GL_INVALID_INDEX ||
8317 				current_item.stage.function3_index == GL_INVALID_INDEX ||
8318 				current_item.stage.function4_index == GL_INVALID_INDEX)
8319 			{
8320 				TCU_FAIL("Subroutine name was not recognized.");
8321 			}
8322 
8323 			current_item.stage.subroutine1_uniform_location =
8324 				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine1");
8325 			current_item.stage.subroutine2_uniform_location =
8326 				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine2");
8327 			current_item.stage.subroutine3_uniform_location =
8328 				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine3");
8329 			current_item.stage.subroutine4_uniform_location =
8330 				gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine4");
8331 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
8332 
8333 			if (current_item.stage.subroutine1_uniform_location == -1 ||
8334 				current_item.stage.subroutine2_uniform_location == -1 ||
8335 				current_item.stage.subroutine3_uniform_location == -1 ||
8336 				current_item.stage.subroutine4_uniform_location == -1)
8337 			{
8338 				TCU_FAIL("Subroutine uniform name was not recognized.");
8339 			}
8340 
8341 			if (m_po_ids[n_id] == current_item.po_id)
8342 			{
8343 				gl.useProgram(current_item.po_id);
8344 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8345 			}
8346 			else
8347 			{
8348 				/* Temporarily bind the program pipeline. */
8349 				gl.bindProgramPipeline(m_pipeline_object_ids[n_id]);
8350 				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8351 			}
8352 
8353 			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine1_uniform_location,
8354 									   &current_item.stage.default_subroutine1_value);
8355 			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine2_uniform_location,
8356 									   &current_item.stage.default_subroutine2_value);
8357 			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine3_uniform_location,
8358 									   &current_item.stage.default_subroutine3_value);
8359 			gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine4_uniform_location,
8360 									   &current_item.stage.default_subroutine4_value);
8361 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed.");
8362 
8363 			current_item.stage.gl_stage = current_item.so_type;
8364 
8365 			if (m_po_ids[n_id] != current_item.po_id)
8366 			{
8367 				/* Unbind the program pipeline object */
8368 				gl.bindProgramPipeline(0);
8369 				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8370 			}
8371 		} /* for (all items) */
8372 
8373 		/* Make sure the default subroutine choices are valid. */
8374 		verifySubroutineUniformValues(
8375 			TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, /* makes the verification routine use program object descriptor */
8376 			n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES);
8377 
8378 		if (m_are_pipeline_objects_supported)
8379 		{
8380 			gl.useProgram(0);
8381 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8382 
8383 			gl.bindProgramPipeline(m_pipeline_object_ids[n_id]);
8384 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8385 			{
8386 				verifySubroutineUniformValues(
8387 					TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT, /* makes the verification routine use pipeline object descriptor */
8388 					n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES);
8389 			}
8390 			gl.bindProgramPipeline(0);
8391 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8392 		}
8393 	} /* for (both program descriptors) */
8394 }
8395 
8396 /** Retrieves IDs of shaders OR shader program objects, depending on which of the two
8397  *  the caller requests for.
8398  *
8399  *  @param retrieve_program_object_shader_ids true if the caller wishes to retrieve shader object IDs,
8400  *                                            false to return shader program IDs.
8401  *  @param n_id                               Index of the program/pipeline object the shaders
8402  *                                            are a part of.
8403  *  @param out_shader_stages                  Deref will be used to store exactly five IDs. Must not
8404  *                                            be NULL.
8405  **/
getShaderStages(bool retrieve_program_object_shader_ids,const unsigned int & n_id,const _shader_stage ** out_shader_stages) const8406 void FunctionalTest16::getShaderStages(bool retrieve_program_object_shader_ids, const unsigned int& n_id,
8407 									   const _shader_stage** out_shader_stages) const
8408 {
8409 	if (retrieve_program_object_shader_ids)
8410 	{
8411 		out_shader_stages[0] = &m_po_descriptors[n_id].vertex;
8412 		out_shader_stages[1] = &m_po_descriptors[n_id].tess_control;
8413 		out_shader_stages[2] = &m_po_descriptors[n_id].tess_evaluation;
8414 		out_shader_stages[3] = &m_po_descriptors[n_id].geometry;
8415 		out_shader_stages[4] = &m_po_descriptors[n_id].fragment;
8416 	}
8417 	else
8418 	{
8419 		out_shader_stages[0] = m_vs_po_descriptors + n_id;
8420 		out_shader_stages[1] = m_tc_po_descriptors + n_id;
8421 		out_shader_stages[2] = m_te_po_descriptors + n_id;
8422 		out_shader_stages[3] = m_gs_po_descriptors + n_id;
8423 		out_shader_stages[4] = m_fs_po_descriptors + n_id;
8424 	}
8425 }
8426 
8427 /** Executes test iteration.
8428  *
8429  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8430  */
iterate()8431 tcu::TestNode::IterateResult FunctionalTest16::iterate()
8432 {
8433 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8434 
8435 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
8436 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
8437 	{
8438 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
8439 	}
8440 
8441 	m_are_pipeline_objects_supported =
8442 		m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects");
8443 
8444 	/* Initialize GL objects required to run the test */
8445 	initTest();
8446 
8447 	/* Iterate over both pipelines/programs and verify that calling glUseProgram() /
8448 	 * glBindProgramPipeline() / glUseProgramStages() resets subroutine uniform configuration.
8449 	 */
8450 	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
8451 	{
8452 		if (static_cast<_test_case>(test_case) != TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT &&
8453 			!m_are_pipeline_objects_supported)
8454 		{
8455 			/* Current test case requires GL_ARB_separate_shader_objects support which is
8456 			 * unavaiable on the platform that we're testing
8457 			 */
8458 			continue;
8459 		}
8460 
8461 		for (unsigned int n_object_id = 0; n_object_id < 2; /* pipeline/program objects allocated for the test */
8462 			 ++n_object_id)
8463 		{
8464 			/* Verify that currently reported subroutine uniform values are equal to default values */
8465 			if (test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT)
8466 			{
8467 				gl.useProgram(m_po_ids[n_object_id]);
8468 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
8469 			}
8470 			else
8471 			{
8472 				gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]);
8473 				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed");
8474 			}
8475 
8476 			verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8477 										  SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8478 
8479 			/* Re-configure subroutine uniforms so that they point to different subroutines than
8480 			 * the default ones.
8481 			 */
8482 			const _shader_stage* stages[5 /* fs+gs+tc+te+vs */] = { DE_NULL };
8483 
8484 			getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT,
8485 							n_object_id, stages);
8486 
8487 			for (unsigned int n_stage = 0; n_stage < 5 /* fs+gs+tc+te+vs stages */; ++n_stage)
8488 			{
8489 				const _shader_stage& current_stage				 = *(stages[n_stage]);
8490 				glw::GLuint			 subroutine_configuration[4] = { GL_INVALID_INDEX };
8491 
8492 				subroutine_configuration[0] =
8493 					(current_stage.default_subroutine1_value == current_stage.function1_index) ?
8494 						current_stage.function2_index :
8495 						current_stage.function1_index;
8496 				subroutine_configuration[1] =
8497 					(current_stage.default_subroutine2_value == current_stage.function1_index) ?
8498 						current_stage.function2_index :
8499 						current_stage.function1_index;
8500 				subroutine_configuration[2] =
8501 					(current_stage.default_subroutine3_value == current_stage.function3_index) ?
8502 						current_stage.function4_index :
8503 						current_stage.function3_index;
8504 				subroutine_configuration[3] =
8505 					(current_stage.default_subroutine4_value == current_stage.function3_index) ?
8506 						current_stage.function4_index :
8507 						current_stage.function3_index;
8508 
8509 				gl.uniformSubroutinesuiv(current_stage.gl_stage, 4 /* count */, subroutine_configuration);
8510 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
8511 			} /* for (all stages) */
8512 
8513 			verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8514 										  SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8515 
8516 			/* Execute test case-specific code */
8517 			_shader_stage cached_shader_stage_data;
8518 			bool		  stage_reset_status[Utils::SHADER_STAGE_COUNT] = { false, false, false, false, false };
8519 			bool		  uses_stage_reset_status						= false;
8520 
8521 			switch (test_case)
8522 			{
8523 			case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT:
8524 			{
8525 				/* Switch to a different program object and then back to current PO.
8526 				 * Subroutine uniforms should be back at their default settings, instead of
8527 				 * the ones we've just set.
8528 				 */
8529 				gl.useProgram(m_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8530 				gl.useProgram(m_po_ids[n_object_id]);
8531 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
8532 
8533 				break;
8534 			}
8535 
8536 			case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT:
8537 			{
8538 				/* Switch to a different pipeline object and then back to the current one.
8539 				 * Subroutine uniforms should be back at their default settings, instead of
8540 				 * the ones we've just set.
8541 				 */
8542 				gl.bindProgramPipeline(
8543 					m_pipeline_object_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8544 				gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]);
8545 				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
8546 
8547 				break;
8548 			}
8549 
8550 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE:
8551 			{
8552 				/* Change the fragment shader stage to a different one.
8553 				 *
8554 				 * Note: We also need to update internal descriptor since the subroutine/uniform
8555 				 *       locations may be different between the two programs.
8556 				 */
8557 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT,
8558 									m_fs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8559 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8560 
8561 				cached_shader_stage_data		 = m_fs_po_descriptors[n_object_id];
8562 				m_fs_po_descriptors[n_object_id] = m_fs_po_descriptors[(n_object_id + 1) % 2];
8563 
8564 				stage_reset_status[Utils::SHADER_STAGE_FRAGMENT] = true;
8565 				uses_stage_reset_status							 = true;
8566 
8567 				break;
8568 			}
8569 
8570 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE:
8571 			{
8572 				/* Change the geometry shader stage to a different one.
8573 				 *
8574 				 * Note: We also need to update internal descriptor since the subroutine/uniform
8575 				 *       locations may be different between the two programs.
8576 				 */
8577 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT,
8578 									m_gs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8579 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8580 
8581 				cached_shader_stage_data		 = m_gs_po_descriptors[n_object_id];
8582 				m_gs_po_descriptors[n_object_id] = m_gs_po_descriptors[(n_object_id + 1) % 2];
8583 
8584 				stage_reset_status[Utils::SHADER_STAGE_GEOMETRY] = true;
8585 				uses_stage_reset_status							 = true;
8586 
8587 				break;
8588 			}
8589 
8590 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE:
8591 			{
8592 				/* Change the tessellation control shader stage to a different one.
8593 				 *
8594 				 * Note: We also need to update internal descriptor since the subroutine/uniform
8595 				 *       locations may be different between the two programs.
8596 				 */
8597 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT,
8598 									m_tc_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8599 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8600 
8601 				cached_shader_stage_data		 = m_tc_po_descriptors[n_object_id];
8602 				m_tc_po_descriptors[n_object_id] = m_tc_po_descriptors[(n_object_id + 1) % 2];
8603 
8604 				stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_CONTROL] = true;
8605 				uses_stage_reset_status										 = true;
8606 
8607 				break;
8608 			}
8609 
8610 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE:
8611 			{
8612 				/* Change the tessellation evaluation shader stage to a different one.
8613 				 *
8614 				 * Note: We also need to update internal descriptor since the subroutine/uniform
8615 				 *       locations may be different between the two programs.
8616 				 */
8617 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT,
8618 									m_te_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8619 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8620 
8621 				cached_shader_stage_data		 = m_te_po_descriptors[n_object_id];
8622 				m_te_po_descriptors[n_object_id] = m_te_po_descriptors[(n_object_id + 1) % 2];
8623 
8624 				stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_EVALUATION] = true;
8625 				uses_stage_reset_status											= true;
8626 
8627 				break;
8628 			}
8629 
8630 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE:
8631 			{
8632 				/* Change the vertex shader stage to a different one.
8633 				 *
8634 				 * Note: We also need to update internal descriptor since the subroutine/uniform
8635 				 *       locations may be different between the two programs.
8636 				 */
8637 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT,
8638 									m_vs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8639 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8640 
8641 				cached_shader_stage_data		 = m_vs_po_descriptors[n_object_id];
8642 				m_vs_po_descriptors[n_object_id] = m_vs_po_descriptors[(n_object_id + 1) % 2];
8643 
8644 				stage_reset_status[Utils::SHADER_STAGE_VERTEX] = true;
8645 				uses_stage_reset_status						   = true;
8646 
8647 				break;
8648 			}
8649 
8650 			default:
8651 			{
8652 				TCU_FAIL("Unrecognized test case");
8653 			}
8654 			} /* switch (test_case) */
8655 
8656 			/* Verify the subroutine uniform values are valid */
8657 			if (!uses_stage_reset_status)
8658 			{
8659 				verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8660 											  SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8661 			}
8662 			else
8663 			{
8664 				const _shader_stage* shader_stages[Utils::SHADER_STAGE_COUNT] = { DE_NULL };
8665 
8666 				getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT,
8667 								n_object_id, shader_stages);
8668 
8669 				for (unsigned int n_shader_stage = 0; n_shader_stage < Utils::SHADER_STAGE_COUNT; ++n_shader_stage)
8670 				{
8671 					const _shader_stage& current_shader_stage = *(shader_stages[n_shader_stage]);
8672 
8673 					if (stage_reset_status[n_shader_stage])
8674 					{
8675 						verifySubroutineUniformValuesForShaderStage(current_shader_stage,
8676 																	SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8677 					}
8678 					else
8679 					{
8680 						verifySubroutineUniformValuesForShaderStage(current_shader_stage,
8681 																	SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8682 					}
8683 				} /* for (all shader stages) */
8684 			}
8685 
8686 			/* Revert the changes some of the test cases appied */
8687 			switch (test_case)
8688 			{
8689 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE:
8690 			{
8691 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT,
8692 									m_fs_po_ids[n_object_id]);
8693 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8694 
8695 				m_fs_po_descriptors[n_object_id] = cached_shader_stage_data;
8696 
8697 				break;
8698 			}
8699 
8700 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE:
8701 			{
8702 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT,
8703 									m_gs_po_ids[n_object_id]);
8704 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8705 
8706 				m_gs_po_descriptors[n_object_id] = cached_shader_stage_data;
8707 
8708 				break;
8709 			}
8710 
8711 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE:
8712 			{
8713 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT,
8714 									m_tc_po_ids[n_object_id]);
8715 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8716 
8717 				m_tc_po_descriptors[n_object_id] = cached_shader_stage_data;
8718 
8719 				break;
8720 			}
8721 
8722 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE:
8723 			{
8724 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT,
8725 									m_te_po_ids[n_object_id]);
8726 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8727 
8728 				m_te_po_descriptors[n_object_id] = cached_shader_stage_data;
8729 
8730 				break;
8731 			}
8732 
8733 			case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE:
8734 			{
8735 				gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_object_id]);
8736 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8737 
8738 				m_vs_po_descriptors[n_object_id] = cached_shader_stage_data;
8739 
8740 				break;
8741 			}
8742 
8743 			default:
8744 				break;
8745 			} /* switch (test_case) */
8746 
8747 		} /* for (all program object descriptors) */
8748 
8749 		/* Unbind the program object */
8750 		gl.useProgram(0);
8751 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8752 	} /* for (all test cases) */
8753 
8754 	if (m_has_test_passed)
8755 	{
8756 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8757 	}
8758 	else
8759 	{
8760 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8761 	}
8762 
8763 	return STOP;
8764 }
8765 
8766 /** Verifies the subroutine uniform values reported by GL implementation. Depending on the test case,
8767  *  it will either query program object stages or separate shader objects.
8768  *
8769  *  @param test_case    Test case the verification is to be performed for.
8770  *  @param n_id         Index of the program/pipeline object to use for the verification
8771  *  @param verification Verification method.
8772  */
verifySubroutineUniformValues(const _test_case & test_case,const unsigned int & n_id,const _subroutine_uniform_value_verification & verification)8773 void FunctionalTest16::verifySubroutineUniformValues(const _test_case& test_case, const unsigned int& n_id,
8774 													 const _subroutine_uniform_value_verification& verification)
8775 {
8776 	const _shader_stage* stages[] = {
8777 		DE_NULL, /* fragment shader     stage slot */
8778 		DE_NULL, /* geometry shader     stage slot */
8779 		DE_NULL, /* tess control shader stage slot */
8780 		DE_NULL, /* tess eval shader    stage slot */
8781 		DE_NULL  /* vertex shader       stage slot */
8782 	};
8783 	const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
8784 
8785 	/* Verify that currently reported subroutine uniform values are equal to default values */
8786 	getShaderStages(test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, n_id, stages);
8787 
8788 	for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
8789 	{
8790 		const _shader_stage& current_stage = *(stages[n_stage]);
8791 
8792 		verifySubroutineUniformValuesForShaderStage(current_stage, verification);
8793 	} /* for (all items) */
8794 }
8795 
8796 /** Verifies the subroutine uniform values reported by GL implementation for user-specified
8797  *  shader stage. If the verification fails, m_has_test_passed will be set to false.
8798  *
8799  *  @param shader_stage Descriptor of a shader stage that should be used for the process.
8800  *  @param verification Type of verification that should be performed.
8801  *
8802  **/
verifySubroutineUniformValuesForShaderStage(const _shader_stage & shader_stage,const _subroutine_uniform_value_verification & verification)8803 void FunctionalTest16::verifySubroutineUniformValuesForShaderStage(
8804 	const _shader_stage& shader_stage, const _subroutine_uniform_value_verification& verification)
8805 {
8806 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
8807 	glw::GLuint			  result_values[4] = { 0 };
8808 
8809 	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine1_uniform_location, result_values + 0);
8810 	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine2_uniform_location, result_values + 1);
8811 	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine3_uniform_location, result_values + 2);
8812 	gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine4_uniform_location, result_values + 3);
8813 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed.");
8814 
8815 	if (verification == SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES)
8816 	{
8817 		if (!((result_values[0] == (GLuint)shader_stage.subroutine1_uniform_location ||
8818 			   result_values[0] == (GLuint)shader_stage.subroutine2_uniform_location) &&
8819 			  (result_values[1] == (GLuint)shader_stage.subroutine1_uniform_location ||
8820 			   result_values[1] == (GLuint)shader_stage.subroutine2_uniform_location) &&
8821 			  (result_values[2] == (GLuint)shader_stage.subroutine3_uniform_location ||
8822 			   result_values[2] == (GLuint)shader_stage.subroutine4_uniform_location) &&
8823 			  (result_values[3] == (GLuint)shader_stage.subroutine3_uniform_location ||
8824 			   result_values[3] == (GLuint)shader_stage.subroutine4_uniform_location)))
8825 		{
8826 			m_testCtx.getLog() << tcu::TestLog::Message << "SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES validation failed. "
8827 														   "Shader stage:["
8828 							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8829 																								  "expected data:["
8830 							   << shader_stage.subroutine1_uniform_location << " OR "
8831 							   << shader_stage.subroutine2_uniform_location << " x 2, "
8832 							   << shader_stage.subroutine3_uniform_location << " OR "
8833 							   << shader_stage.subroutine4_uniform_location << " x 2], "
8834 																			   "found data:["
8835 							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8836 							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8837 
8838 			m_has_test_passed = false;
8839 		}
8840 	}
8841 	else if (verification == SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES)
8842 	{
8843 		if (result_values[0] != shader_stage.default_subroutine1_value ||
8844 			result_values[1] != shader_stage.default_subroutine2_value ||
8845 			result_values[2] != shader_stage.default_subroutine3_value ||
8846 			result_values[3] != shader_stage.default_subroutine4_value)
8847 		{
8848 			m_testCtx.getLog() << tcu::TestLog::Message
8849 							   << "SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES validation failed. "
8850 								  "Shader stage:["
8851 							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8852 																								  "expected data:["
8853 							   << shader_stage.default_subroutine1_value << ", "
8854 							   << shader_stage.default_subroutine2_value << ", "
8855 							   << shader_stage.default_subroutine3_value << ", "
8856 							   << shader_stage.default_subroutine4_value << "], "
8857 																			"found data:["
8858 							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8859 							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8860 
8861 			m_has_test_passed = false;
8862 		}
8863 	}
8864 	else
8865 	{
8866 		DE_ASSERT(verification == SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8867 
8868 		if (result_values[0] == shader_stage.default_subroutine1_value ||
8869 			result_values[1] == shader_stage.default_subroutine2_value ||
8870 			result_values[2] == shader_stage.default_subroutine3_value ||
8871 			result_values[3] == shader_stage.default_subroutine4_value)
8872 		{
8873 			m_testCtx.getLog() << tcu::TestLog::Message
8874 							   << "SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES validation failed. "
8875 								  "Shader stage:["
8876 							   << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8877 																								  "expected data:!["
8878 							   << shader_stage.default_subroutine1_value << ", "
8879 							   << shader_stage.default_subroutine2_value << ", "
8880 							   << shader_stage.default_subroutine3_value << ", "
8881 							   << shader_stage.default_subroutine4_value << "], "
8882 																			"found data:["
8883 							   << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8884 							   << result_values[3] << "]." << tcu::TestLog::EndMessage;
8885 
8886 			m_has_test_passed = false;
8887 		}
8888 	}
8889 }
8890 
8891 /** Constructor.
8892  *
8893  *  @param context Rendering context.
8894  *
8895  **/
FunctionalTest17(deqp::Context & context)8896 FunctionalTest17::FunctionalTest17(deqp::Context& context)
8897 	: TestCase(context, "same_subroutine_and_subroutine_uniform_but_different_type_used_in_all_stages",
8898 			   "Creates a program which uses the same subroutine and subroutine uniform "
8899 			   "names for every stage (types of subroutines are different in each stage) "
8900 			   "and then makes sure that such program compiles and works as expected.")
8901 	, m_fbo_id(0)
8902 	, m_fs_id(0)
8903 	, m_gs_id(0)
8904 	, m_has_test_passed(true)
8905 	, m_po_id(0)
8906 	, m_tc_id(0)
8907 	, m_te_id(0)
8908 	, m_to_data(DE_NULL)
8909 	, m_to_height(4) /* arbitrary value */
8910 	, m_to_id(0)
8911 	, m_to_width(4) /* arbitrary value */
8912 	, m_vao_id(0)
8913 	, m_vs_id(0)
8914 {
8915 	/* Left blank intentionally */
8916 }
8917 
8918 /** Deinitializes all GL objects that may have been created during test execution. */
deinit()8919 void FunctionalTest17::deinit()
8920 {
8921 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8922 
8923 	if (m_fbo_id != 0)
8924 	{
8925 		gl.deleteFramebuffers(1, &m_fbo_id);
8926 
8927 		m_fbo_id = 0;
8928 	}
8929 
8930 	if (m_fs_id != 0)
8931 	{
8932 		gl.deleteShader(m_fs_id);
8933 
8934 		m_fs_id = 0;
8935 	}
8936 
8937 	if (m_gs_id != 0)
8938 	{
8939 		gl.deleteShader(m_gs_id);
8940 
8941 		m_gs_id = 0;
8942 	}
8943 
8944 	if (m_po_id != 0)
8945 	{
8946 		gl.deleteProgram(m_po_id);
8947 
8948 		m_po_id = 0;
8949 	}
8950 
8951 	if (m_tc_id != 0)
8952 	{
8953 		gl.deleteShader(m_tc_id);
8954 
8955 		m_tc_id = 0;
8956 	}
8957 
8958 	if (m_te_id != 0)
8959 	{
8960 		gl.deleteShader(m_te_id);
8961 
8962 		m_te_id = 0;
8963 	}
8964 
8965 	if (m_to_data != DE_NULL)
8966 	{
8967 		delete[] m_to_data;
8968 
8969 		m_to_data = DE_NULL;
8970 	}
8971 
8972 	if (m_to_id != 0)
8973 	{
8974 		gl.deleteTextures(1, &m_to_id);
8975 
8976 		m_to_id = 0;
8977 	}
8978 
8979 	if (m_vao_id != 0)
8980 	{
8981 		gl.deleteVertexArrays(1, &m_vao_id);
8982 
8983 		m_vao_id = 0;
8984 	}
8985 
8986 	if (m_vs_id != 0)
8987 	{
8988 		gl.deleteShader(m_vs_id);
8989 
8990 		m_vs_id = 0;
8991 	}
8992 
8993 	/* Restore original GL configuration */
8994 	gl.patchParameteri(GL_PATCH_VERTICES, 3);
8995 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
8996 
8997 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
8998 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
8999 }
9000 
9001 /** Retrieves body of a fragment shader that should be used by the test program.
9002  *
9003  *  @return Requested string.
9004  **/
getFragmentShaderBody() const9005 std::string FunctionalTest17::getFragmentShaderBody() const
9006 {
9007 	return "#version 400\n"
9008 		   "\n"
9009 		   "#extension GL_ARB_shader_subroutine : require\n"
9010 		   "\n"
9011 		   "in GS_DATA\n"
9012 		   "{\n"
9013 		   "    vec4 gs_data;\n"
9014 		   "    vec4 tc_data;\n"
9015 		   "    vec4 te_data;\n"
9016 		   "    vec4 vs_data;\n"
9017 		   "} gs;\n"
9018 		   "\n"
9019 		   "out vec4 result;\n"
9020 		   "\n"
9021 		   "subroutine void subroutineTypeFS(out vec4 result);\n"
9022 		   "\n"
9023 		   "subroutine(subroutineTypeFS) void subroutine1(out vec4 result)\n"
9024 		   "{\n"
9025 		   "    result = vec4(5, 6, 7, 8);\n"
9026 		   "}\n"
9027 		   "\n"
9028 		   "subroutine uniform subroutineTypeFS function;\n"
9029 		   "\n"
9030 		   "void main()\n"
9031 		   "{\n"
9032 		   "    vec4 fs_data;\n"
9033 		   "\n"
9034 		   "    function(fs_data);\n"
9035 		   "    result = gs.gs_data + gs.tc_data + gs.te_data + gs.vs_data + fs_data;\n"
9036 		   "}\n";
9037 }
9038 
9039 /** Retrieves body of a geometry shader that should be used by the test program.
9040  *
9041  *  @return Requested string.
9042  **/
getGeometryShaderBody() const9043 std::string FunctionalTest17::getGeometryShaderBody() const
9044 {
9045 	return "#version 400\n"
9046 		   "\n"
9047 		   "#extension GL_ARB_shader_subroutine : require\n"
9048 		   "\n"
9049 		   "layout(points)                           in;\n"
9050 		   "layout(triangle_strip, max_vertices = 4) out;\n"
9051 		   "\n"
9052 		   "subroutine void subroutineTypeGS(out vec4 result);\n"
9053 		   "\n"
9054 		   "subroutine(subroutineTypeGS) void subroutine1(out vec4 result)\n"
9055 		   "{\n"
9056 		   "    result = vec4(4, 5, 6, 7);\n"
9057 		   "}\n"
9058 		   "\n"
9059 		   "subroutine uniform subroutineTypeGS function;\n"
9060 		   "\n"
9061 		   "in TE_DATA\n"
9062 		   "{\n"
9063 		   "    vec4 tc_data;\n"
9064 		   "    vec4 te_data;\n"
9065 		   "    vec4 vs_data;\n"
9066 		   "} te[];\n"
9067 		   "\n"
9068 		   "out GS_DATA\n"
9069 		   "{\n"
9070 		   "    vec4 gs_data;\n"
9071 		   "    vec4 tc_data;\n"
9072 		   "    vec4 te_data;\n"
9073 		   "    vec4 vs_data;\n"
9074 		   "} result;\n"
9075 		   "\n"
9076 		   "void main()\n"
9077 		   "{\n"
9078 		   "    function(result.gs_data);\n"
9079 		   "    gl_Position    = vec4(1, -1, 0, 1);\n"
9080 		   "    result.tc_data = te[0].tc_data;\n"
9081 		   "    result.te_data = te[0].te_data;\n"
9082 		   "    result.vs_data = te[0].vs_data;\n"
9083 		   "    EmitVertex();\n"
9084 		   "\n"
9085 		   "    function(result.gs_data);\n"
9086 		   "    gl_Position    = vec4(-1, -1, 0, 1);\n"
9087 		   "    result.tc_data = te[0].tc_data;\n"
9088 		   "    result.te_data = te[0].te_data;\n"
9089 		   "    result.vs_data = te[0].vs_data;\n"
9090 		   "    EmitVertex();\n"
9091 		   "\n"
9092 		   "    function(result.gs_data);\n"
9093 		   "    gl_Position    = vec4(1, 1, 0, 1);\n"
9094 		   "    result.tc_data = te[0].tc_data;\n"
9095 		   "    result.te_data = te[0].te_data;\n"
9096 		   "    result.vs_data = te[0].vs_data;\n"
9097 		   "    EmitVertex();\n"
9098 		   "\n"
9099 		   "    function(result.gs_data);\n"
9100 		   "    gl_Position    = vec4(-1, 1, 0, 1);\n"
9101 		   "    result.tc_data = te[0].tc_data;\n"
9102 		   "    result.te_data = te[0].te_data;\n"
9103 		   "    result.vs_data = te[0].vs_data;\n"
9104 		   "    EmitVertex();\n"
9105 		   "    EndPrimitive();\n"
9106 		   "}\n";
9107 }
9108 
9109 /** Retrieves body of a tessellation control shader that should be used by the test program.
9110  *
9111  *  @return Requested string.
9112  **/
getTessellationControlShaderBody() const9113 std::string FunctionalTest17::getTessellationControlShaderBody() const
9114 {
9115 	return "#version 400\n"
9116 		   "\n"
9117 		   "#extension GL_ARB_shader_subroutine : require\n"
9118 		   "\n"
9119 		   "layout (vertices = 4) out;\n"
9120 		   "\n"
9121 		   "subroutine void subroutineTypeTC(out vec4 result);\n"
9122 		   "\n"
9123 		   "subroutine(subroutineTypeTC) void subroutine1(out vec4 result)\n"
9124 		   "{\n"
9125 		   "    result = vec4(2, 3, 4, 5);\n"
9126 		   "}\n"
9127 		   "\n"
9128 		   "subroutine uniform subroutineTypeTC function;\n"
9129 		   "\n"
9130 		   "in VS_DATA\n"
9131 		   "{\n"
9132 		   "    vec4 vs_data;\n"
9133 		   "} vs[];\n"
9134 		   "\n"
9135 		   "out TC_DATA\n"
9136 		   "{\n"
9137 		   "    vec4 tc_data;\n"
9138 		   "    vec4 vs_data;\n"
9139 		   "} result[];\n"
9140 		   "\n"
9141 		   "void main()\n"
9142 		   "{\n"
9143 		   "    gl_TessLevelInner[0] = 1.0;\n"
9144 		   "    gl_TessLevelInner[1] = 1.0;\n"
9145 		   "    gl_TessLevelOuter[0] = 1.0;\n"
9146 		   "    gl_TessLevelOuter[1] = 1.0;\n"
9147 		   "    gl_TessLevelOuter[2] = 1.0;\n"
9148 		   "    gl_TessLevelOuter[3] = 1.0;\n"
9149 		   "\n"
9150 		   "    function(result[gl_InvocationID].tc_data);\n"
9151 		   "    result[gl_InvocationID].vs_data = vs[gl_InvocationID].vs_data;\n"
9152 		   "}\n";
9153 }
9154 
9155 /** Retrieves body of a tessellation evaluation shader that should be used
9156  *  by the test program.
9157  *
9158  *  @return Requested string.
9159  **/
getTessellationEvaluationShaderBody() const9160 std::string FunctionalTest17::getTessellationEvaluationShaderBody() const
9161 {
9162 	return "#version 400\n"
9163 		   "\n"
9164 		   "#extension GL_ARB_shader_subroutine : require\n"
9165 		   "\n"
9166 		   "layout (quads, point_mode) in;\n"
9167 		   "\n"
9168 		   "subroutine void subroutineTypeTE(out vec4 result);\n"
9169 		   "\n"
9170 		   "subroutine(subroutineTypeTE) void subroutine1(out vec4 result)\n"
9171 		   "{\n"
9172 		   "    result = vec4(3, 4, 5, 6);\n"
9173 		   "}\n"
9174 		   "\n"
9175 		   "subroutine uniform subroutineTypeTE function;\n"
9176 		   "\n"
9177 		   "in TC_DATA\n"
9178 		   "{\n"
9179 		   "    vec4 tc_data;\n"
9180 		   "    vec4 vs_data;\n"
9181 		   "} tc[];\n"
9182 		   "\n"
9183 		   "out TE_DATA\n"
9184 		   "{\n"
9185 		   "    vec4 tc_data;\n"
9186 		   "    vec4 te_data;\n"
9187 		   "    vec4 vs_data;\n"
9188 		   "} result;\n"
9189 		   "\n"
9190 		   "void main()\n"
9191 		   "{\n"
9192 		   "    result.vs_data = tc[0].vs_data;\n"
9193 		   "    result.tc_data = tc[0].tc_data;\n"
9194 		   "    function(result.te_data);\n"
9195 		   "}\n";
9196 }
9197 
9198 /** Retrieves body of a vertex shader that should be used by the test program.
9199  *
9200  *  @return Requested string.
9201  **/
getVertexShaderBody() const9202 std::string FunctionalTest17::getVertexShaderBody() const
9203 {
9204 	return "#version 400\n"
9205 		   "\n"
9206 		   "#extension GL_ARB_shader_subroutine : require\n"
9207 		   "\n"
9208 		   "out VS_DATA\n"
9209 		   "{\n"
9210 		   "    vec4 vs_data;\n"
9211 		   "} result;\n"
9212 		   "\n"
9213 		   "subroutine void subroutineTypeVS(out vec4 result);\n"
9214 		   "\n"
9215 		   "subroutine(subroutineTypeVS) void subroutine1(out vec4 result)\n"
9216 		   "{\n"
9217 		   "    result = vec4(1, 2, 3, 4);\n"
9218 		   "}\n"
9219 		   "\n"
9220 		   "subroutine uniform subroutineTypeVS function;\n"
9221 		   "\n"
9222 		   "void main()\n"
9223 		   "{\n"
9224 		   "    function(result.vs_data);\n"
9225 		   "}\n";
9226 }
9227 
9228 /** Initializes all buffers and GL objects required to run the test. */
initTest()9229 void FunctionalTest17::initTest()
9230 {
9231 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9232 
9233 	/* Configure GL_PATCH_VERTICES so that TC only takes a single patch vertex */
9234 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
9235 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
9236 
9237 	/* Generate & bind a VAO */
9238 	gl.genVertexArrays(1, &m_vao_id);
9239 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9240 
9241 	gl.bindVertexArray(m_vao_id);
9242 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9243 
9244 	/* Set up test program object */
9245 	std::string fs_body = getFragmentShaderBody();
9246 	std::string gs_body = getGeometryShaderBody();
9247 	std::string tc_body = getTessellationControlShaderBody();
9248 	std::string te_body = getTessellationEvaluationShaderBody();
9249 	std::string vs_body = getVertexShaderBody();
9250 
9251 	if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */
9252 							 DE_NULL,												   /* n_xfb_varyings */
9253 							 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
9254 	{
9255 		TCU_FAIL("Failed to link test program object");
9256 	}
9257 
9258 	/* Set up a texture object that will be used as a color attachment */
9259 	gl.genTextures(1, &m_to_id);
9260 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
9261 
9262 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9263 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9264 
9265 	gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
9266 					GL_RGBA32F, m_to_width, m_to_height);
9267 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9268 
9269 	/* Set up FBO */
9270 	gl.genFramebuffers(1, &m_fbo_id);
9271 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9272 
9273 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9274 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
9275 
9276 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
9277 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
9278 
9279 	/* Make sure glReadPixels() does not return misaligned data */
9280 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
9281 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
9282 
9283 	/* Initialize a buffer that will be used to store rendered data */
9284 	m_to_data = new float[m_to_width * m_to_height * 4 /* rgba */];
9285 }
9286 
9287 /** Executes test iteration.
9288  *
9289  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9290  */
iterate()9291 tcu::TestNode::IterateResult FunctionalTest17::iterate()
9292 {
9293 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9294 
9295 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9296 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9297 	{
9298 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9299 	}
9300 
9301 	initTest();
9302 
9303 	/* Use the test program to render a full-screen test quad */
9304 	gl.useProgram(m_po_id);
9305 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9306 
9307 	gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
9308 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9309 
9310 	/* Read back the data that was rendered */
9311 	gl.readPixels(0, /* x */
9312 				  0, /* y */
9313 				  m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_to_data);
9314 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReaDPixels() call failed.");
9315 
9316 	/* Verify the data */
9317 	verifyRenderedData();
9318 
9319 	/** All done */
9320 	if (m_has_test_passed)
9321 	{
9322 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9323 	}
9324 	else
9325 	{
9326 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
9327 	}
9328 
9329 	return STOP;
9330 }
9331 
9332 /** Verifies the data that have been rendered by the test program.
9333  *
9334  *  It is assumed the rendered data have already been copied to
9335  *  m_to_data.
9336  *
9337  *  If the rendered data is found to be invalid, m_has_test_passed
9338  *  will be set to false.
9339  **/
verifyRenderedData()9340 void FunctionalTest17::verifyRenderedData()
9341 {
9342 	const float epsilon			 = 1e-5f;
9343 	const float expected_data[4] = { 15.0f, 20.0f, 25.0f, 30.0f };
9344 
9345 	for (unsigned int y = 0; y < m_to_height && m_has_test_passed; ++y)
9346 	{
9347 		const float* row_ptr = m_to_data + y * 4 /* rgba */ * m_to_width;
9348 
9349 		for (unsigned int x = 0; x < m_to_width && m_has_test_passed; ++x)
9350 		{
9351 			const float* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9352 
9353 			if (de::abs(pixel_ptr[0] - expected_data[0]) > epsilon ||
9354 				de::abs(pixel_ptr[1] - expected_data[1]) > epsilon ||
9355 				de::abs(pixel_ptr[2] - expected_data[2]) > epsilon ||
9356 				de::abs(pixel_ptr[3] - expected_data[3]) > epsilon)
9357 			{
9358 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel found at (" << x << ", " << y
9359 								   << "): "
9360 									  "expected:("
9361 								   << expected_data[0] << ", " << expected_data[1] << ", " << expected_data[2] << ", "
9362 								   << expected_data[3] << "), found:(" << pixel_ptr[0] << ", " << pixel_ptr[1] << ", "
9363 								   << pixel_ptr[2] << ", " << pixel_ptr[3] << ")." << tcu::TestLog::EndMessage;
9364 
9365 				m_has_test_passed = false;
9366 			}
9367 		} /* for (all columns) */
9368 	}	 /* for (all rows) */
9369 }
9370 
9371 /** Constructor.
9372  *
9373  *  @param context Rendering context.
9374  *
9375  **/
FunctionalTest18_19(deqp::Context & context)9376 FunctionalTest18_19::FunctionalTest18_19(deqp::Context& context)
9377 	: TestCase(context, "control_flow_and_returned_subroutine_values_used_as_subroutine_input",
9378 			   "Makes sure that calling a subroutine with argument value returned by "
9379 			   "another subroutine works correctly. Also checks that subroutine and "
9380 			   "subroutine uniforms work as expected when used in connection with control "
9381 			   "flow functions.")
9382 	, m_has_test_passed(true)
9383 	, m_n_points_to_draw(16) /* arbitrary value */
9384 	, m_po_id(0)
9385 	, m_po_subroutine_divide_by_two_location(GL_INVALID_INDEX)
9386 	, m_po_subroutine_multiply_by_four_location(GL_INVALID_INDEX)
9387 	, m_po_subroutine_returns_false_location(GL_INVALID_INDEX)
9388 	, m_po_subroutine_returns_true_location(GL_INVALID_INDEX)
9389 	, m_po_subroutine_uniform_bool_operator1(-1)
9390 	, m_po_subroutine_uniform_bool_operator2(-1)
9391 	, m_po_subroutine_uniform_vec4_processor1(-1)
9392 	, m_po_subroutine_uniform_vec4_processor2(-1)
9393 	, m_xfb_bo_id(0)
9394 	, m_vao_id(0)
9395 	, m_vs_id(0)
9396 {
9397 	/* Left blank intentionally */
9398 }
9399 
9400 /** De-initializes all GL objects that may have been created during test execution */
deinit()9401 void FunctionalTest18_19::deinit()
9402 {
9403 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9404 
9405 	if (m_po_id != 0)
9406 	{
9407 		gl.deleteProgram(m_po_id);
9408 
9409 		m_po_id = 0;
9410 	}
9411 
9412 	if (m_vao_id != 0)
9413 	{
9414 		gl.deleteVertexArrays(1, &m_vao_id);
9415 
9416 		m_vao_id = 0;
9417 	}
9418 
9419 	if (m_vs_id != 0)
9420 	{
9421 		gl.deleteShader(m_vs_id);
9422 
9423 		m_vs_id = 0;
9424 	}
9425 
9426 	if (m_xfb_bo_id != 0)
9427 	{
9428 		gl.deleteBuffers(1, &m_xfb_bo_id);
9429 
9430 		m_xfb_bo_id = 0;
9431 	}
9432 }
9433 
9434 /** Executes a single test iteration using user-specified properties. If the
9435  *  iterations fails, m_has_test_passed is set to false.
9436  *
9437  *  @param bool_operator1_subroutine_location Location of a subroutine to be assigned to
9438  *                                            bool_operator1 subroutine uniform.
9439  *  @param bool_operator2_subroutine_location Location of a subroutine to be assigned to
9440  *                                            bool_operator2 subroutine uniform.
9441  *  @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to
9442  *                                            vec4_operator1 subroutine uniform.
9443  *  @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to
9444  *                                            vec4_operator2 subroutine uniform.
9445  &**/
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)9446 void FunctionalTest18_19::executeTest(glw::GLuint bool_operator1_subroutine_location,
9447 									  glw::GLuint bool_operator2_subroutine_location,
9448 									  glw::GLuint vec4_operator1_subroutine_location,
9449 									  glw::GLuint vec4_operator2_subroutine_location)
9450 {
9451 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9452 
9453 	/* Set up subroutines */
9454 	glw::GLuint subroutine_configuration[4 /* total number of subroutines */] = { 0 };
9455 
9456 	subroutine_configuration[m_po_subroutine_uniform_bool_operator1]  = bool_operator1_subroutine_location;
9457 	subroutine_configuration[m_po_subroutine_uniform_bool_operator2]  = bool_operator2_subroutine_location;
9458 	subroutine_configuration[m_po_subroutine_uniform_vec4_processor1] = vec4_operator1_subroutine_location;
9459 	subroutine_configuration[m_po_subroutine_uniform_vec4_processor2] = vec4_operator2_subroutine_location;
9460 
9461 	gl.useProgram(m_po_id);
9462 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
9463 
9464 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 4 /* count */, subroutine_configuration);
9465 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed");
9466 
9467 	/* Draw test-specific number of points */
9468 	gl.beginTransformFeedback(GL_POINTS);
9469 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
9470 	{
9471 		gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw);
9472 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
9473 	}
9474 	gl.endTransformFeedback();
9475 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
9476 
9477 	/* Map the BO storage into process space */
9478 	const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
9479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
9480 
9481 	verifyXFBData(xfb_data_ptr, bool_operator1_subroutine_location, bool_operator2_subroutine_location,
9482 				  vec4_operator1_subroutine_location, vec4_operator2_subroutine_location);
9483 
9484 	/* Unmap BO storage */
9485 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
9486 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
9487 }
9488 
9489 /** Retrieves body of a vertex shader to be used by the test. */
getVertexShaderBody() const9490 std::string FunctionalTest18_19::getVertexShaderBody() const
9491 {
9492 	return "#version 400\n"
9493 		   "\n"
9494 		   "subroutine bool bool_processor();\n"
9495 		   "subroutine vec4 vec4_processor(in vec4 iparam);\n"
9496 		   "\n"
9497 		   "subroutine(bool_processor) bool returnsFalse()\n"
9498 		   "{\n"
9499 		   "    return false;\n"
9500 		   "}\n"
9501 		   "\n"
9502 		   "subroutine(bool_processor) bool returnsTrue()\n"
9503 		   "{\n"
9504 		   "    return true;\n"
9505 		   "}\n"
9506 		   "\n"
9507 		   "subroutine(vec4_processor) vec4 divideByTwo(in vec4 iparam)\n"
9508 		   "{\n"
9509 		   "    return iparam * vec4(0.5);\n"
9510 		   "}\n"
9511 		   "\n"
9512 		   "subroutine(vec4_processor) vec4 multiplyByFour(in vec4 iparam)\n"
9513 		   "{\n"
9514 		   "    return iparam * vec4(4.0);\n"
9515 		   "}\n"
9516 		   "\n"
9517 		   "subroutine uniform bool_processor bool_operator1;\n"
9518 		   "subroutine uniform bool_processor bool_operator2;\n"
9519 		   "subroutine uniform vec4_processor vec4_operator1;\n"
9520 		   "subroutine uniform vec4_processor vec4_operator2;\n"
9521 		   "\n"
9522 		   "out float result;\n"
9523 		   "\n"
9524 		   "void main()\n"
9525 		   "{\n"
9526 		   "    if (bool_operator1() )\n"
9527 		   "    {\n"
9528 		   "        float value = float( (3 * gl_VertexID + 1) * 2);\n"
9529 		   "\n"
9530 		   "        while (bool_operator1() )\n"
9531 		   "        {\n"
9532 		   "            value /= float(gl_VertexID + 2);\n"
9533 		   "\n"
9534 		   "            if (value <= 1.0f) break;\n"
9535 		   "        }\n"
9536 		   "\n"
9537 		   "        result = value;\n"
9538 		   "    }\n"
9539 		   "    else\n"
9540 		   "    {\n"
9541 		   "        vec4 value = vec4(gl_VertexID,     gl_VertexID + 1,\n"
9542 		   "                          gl_VertexID + 2, gl_VertexID + 3);\n"
9543 		   "\n"
9544 		   "        switch (gl_VertexID % 2)\n"
9545 		   "        {\n"
9546 		   "            case 0:\n"
9547 		   "            {\n"
9548 		   "                for (int iteration = 0; iteration < gl_VertexID && bool_operator2(); ++iteration)\n"
9549 		   "                {\n"
9550 		   "                    value = vec4_operator2(vec4_operator1(value));\n"
9551 		   "                }\n"
9552 		   "\n"
9553 		   "                break;\n"
9554 		   "            }\n"
9555 		   "\n"
9556 		   "            case 1:\n"
9557 		   "            {\n"
9558 		   "                for (int iteration = 0; iteration < gl_VertexID * 2; ++iteration)\n"
9559 		   "                {\n"
9560 		   "                    value = vec4_operator1(vec4_operator2(value));\n"
9561 		   "                }\n"
9562 		   "\n"
9563 		   "                break;\n"
9564 		   "            }\n"
9565 		   "        }\n"
9566 		   "\n"
9567 		   "        result = value.x + value.y + value.z + value.w;\n"
9568 		   "\n"
9569 		   "    }\n"
9570 		   "}\n";
9571 }
9572 
9573 /** Initializes all GL objects required to run the test. */
initTest()9574 void FunctionalTest18_19::initTest()
9575 {
9576 	const glw::Functions& gl		  = m_context.getRenderContext().getFunctions();
9577 	const char*			  varyings[1] = { "result" };
9578 	std::string			  vs_body	 = getVertexShaderBody();
9579 	const unsigned int	n_varyings  = sizeof(varyings) / sizeof(varyings[0]);
9580 
9581 	if (!Utils::buildProgram(gl, vs_body, "",						  /* tc_body */
9582 							 "",									  /* te_body */
9583 							 "",									  /* gs_body */
9584 							 "",									  /* fs_body */
9585 							 varyings, n_varyings, &m_vs_id, DE_NULL, /* out_tc_id */
9586 							 DE_NULL,								  /* out_te_id */
9587 							 DE_NULL,								  /* out_gs_id */
9588 							 DE_NULL,								  /* out_fs_id */
9589 							 &m_po_id))
9590 	{
9591 		TCU_FAIL("Failed to build test program object");
9592 	}
9593 
9594 	/* Retrieve subroutine & subroutine uniform locations */
9595 	m_po_subroutine_divide_by_two_location	= gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "divideByTwo");
9596 	m_po_subroutine_multiply_by_four_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "multiplyByFour");
9597 	m_po_subroutine_returns_false_location	= gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsFalse");
9598 	m_po_subroutine_returns_true_location	 = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsTrue");
9599 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed");
9600 
9601 	if (m_po_subroutine_divide_by_two_location == GL_INVALID_INDEX ||
9602 		m_po_subroutine_multiply_by_four_location == GL_INVALID_INDEX ||
9603 		m_po_subroutine_returns_false_location == GL_INVALID_INDEX ||
9604 		m_po_subroutine_returns_true_location == GL_INVALID_INDEX)
9605 	{
9606 		TCU_FAIL("glGetSubroutineIndex() returned GL_INVALID_INDEX for a valid subroutine");
9607 	}
9608 
9609 	m_po_subroutine_uniform_bool_operator1 =
9610 		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator1");
9611 	m_po_subroutine_uniform_bool_operator2 =
9612 		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator2");
9613 	m_po_subroutine_uniform_vec4_processor1 =
9614 		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator1");
9615 	m_po_subroutine_uniform_vec4_processor2 =
9616 		gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator2");
9617 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed");
9618 
9619 	if (m_po_subroutine_uniform_bool_operator1 == -1 || m_po_subroutine_uniform_bool_operator2 == -1 ||
9620 		m_po_subroutine_uniform_vec4_processor1 == -1 || m_po_subroutine_uniform_vec4_processor2 == -1)
9621 	{
9622 		TCU_FAIL("glGetSubroutineUniformLocation() returned -1 for an active subroutine uniform");
9623 	}
9624 
9625 	/* Set up XFB BO */
9626 	const unsigned int bo_size = static_cast<unsigned int>(sizeof(float) * m_n_points_to_draw);
9627 
9628 	gl.genBuffers(1, &m_xfb_bo_id);
9629 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
9630 
9631 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
9632 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
9633 
9634 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
9635 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
9636 
9637 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_COPY);
9638 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9639 
9640 	/* Set up a VAO */
9641 	gl.genVertexArrays(1, &m_vao_id);
9642 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9643 
9644 	gl.bindVertexArray(m_vao_id);
9645 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9646 }
9647 
9648 /** Executes test iteration.
9649  *
9650  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9651  */
iterate()9652 tcu::TestNode::IterateResult FunctionalTest18_19::iterate()
9653 {
9654 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9655 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9656 	{
9657 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9658 	}
9659 
9660 	/* Initialize all GL objects required to run the test */
9661 	initTest();
9662 
9663 	/* Iterate over all subroutine permutations */
9664 	const glw::GLuint subroutine_bool_operators[] = { m_po_subroutine_returns_false_location,
9665 													  m_po_subroutine_returns_true_location };
9666 	const unsigned int n_subroutine_bool_operators =
9667 		sizeof(subroutine_bool_operators) / sizeof(subroutine_bool_operators[0]);
9668 
9669 	const glw::GLuint subroutine_vec4_operators[] = { m_po_subroutine_divide_by_two_location,
9670 													  m_po_subroutine_multiply_by_four_location };
9671 	const unsigned int n_subroutine_vec4_operators =
9672 		sizeof(subroutine_vec4_operators) / sizeof(subroutine_vec4_operators[0]);
9673 
9674 	for (unsigned int n_subroutine_uniform_bool_operator1 = 0;
9675 		 n_subroutine_uniform_bool_operator1 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator1)
9676 	{
9677 		for (unsigned int n_subroutine_uniform_bool_operator2 = 0;
9678 			 n_subroutine_uniform_bool_operator2 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator2)
9679 		{
9680 			for (unsigned int n_subroutine_uniform_vec4_operator1 = 0;
9681 				 n_subroutine_uniform_vec4_operator1 < n_subroutine_vec4_operators;
9682 				 ++n_subroutine_uniform_vec4_operator1)
9683 			{
9684 				for (unsigned int n_subroutine_uniform_vec4_operator2 = 0;
9685 					 n_subroutine_uniform_vec4_operator2 < n_subroutine_vec4_operators;
9686 					 ++n_subroutine_uniform_vec4_operator2)
9687 				{
9688 					executeTest(subroutine_bool_operators[n_subroutine_uniform_bool_operator1],
9689 								subroutine_bool_operators[n_subroutine_uniform_bool_operator2],
9690 								subroutine_vec4_operators[n_subroutine_uniform_vec4_operator1],
9691 								subroutine_vec4_operators[n_subroutine_uniform_vec4_operator2]);
9692 				} /* for (all subroutine vec4 operator subroutines used for processor2) */
9693 			}	 /* for (all subroutine vec4 operator subroutines used for processor1) */
9694 		}		  /* for (all subroutine bool operator subroutines used for operator2) */
9695 	}			  /* for (all subroutine bool operator subroutines used for operator1) */
9696 
9697 	/* All done */
9698 	if (m_has_test_passed)
9699 	{
9700 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9701 	}
9702 	else
9703 	{
9704 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
9705 	}
9706 
9707 	return STOP;
9708 }
9709 
9710 /** Divides input argument by two. The result value is returned to the
9711  *  caller.
9712  *
9713  *  @param data Input value.
9714  *
9715  *  @return As per description.
9716  **/
vec4operator_div2(tcu::Vec4 data)9717 tcu::Vec4 FunctionalTest18_19::vec4operator_div2(tcu::Vec4 data)
9718 {
9719 	return data * 0.5f;
9720 }
9721 
9722 /** Multiplies input argument by four. The result value is returned to the
9723  *  caller.
9724  *
9725  *  @param data Input value.
9726  *
9727  *  @return As per description.
9728  **/
vec4operator_mul4(tcu::Vec4 data)9729 tcu::Vec4 FunctionalTest18_19::vec4operator_mul4(tcu::Vec4 data)
9730 {
9731 	return data * 4.0f;
9732 }
9733 
9734 /** Verifies data XFBed out by the vertex shader. It is assumed the subroutines were configured
9735  *  as per passed arguments, prior to the draw call.
9736  *
9737  *  If the result data is found to be invalid, m_has_test_passed is set to false.
9738  *
9739  *  @param data                               XFBed data.
9740  *  @param bool_operator1_subroutine_location Location of a subroutine to be assigned to
9741  *                                            bool_operator1 subroutine uniform.
9742  *  @param bool_operator2_subroutine_location Location of a subroutine to be assigned to
9743  *                                            bool_operator2 subroutine uniform.
9744  *  @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to
9745  *                                            vec4_operator1 subroutine uniform.
9746  *  @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to
9747  *                                            vec4_operator2 subroutine uniform.
9748  */
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)9749 void FunctionalTest18_19::verifyXFBData(const glw::GLvoid* data, glw::GLuint bool_operator1_subroutine_location,
9750 										glw::GLuint bool_operator2_subroutine_location,
9751 										glw::GLuint vec4_operator1_subroutine_location,
9752 										glw::GLuint vec4_operator2_subroutine_location)
9753 {
9754 	bool				bool_operator1_result = false;
9755 	bool				bool_operator2_result = false;
9756 	const float			epsilon				  = 1e-5f;
9757 	PFNVEC4OPERATORPROC pVec4Operator1		  = NULL;
9758 	PFNVEC4OPERATORPROC pVec4Operator2		  = NULL;
9759 	const glw::GLfloat* traveller_ptr		  = (const glw::GLfloat*)data;
9760 
9761 	bool_operator1_result = (bool_operator1_subroutine_location == m_po_subroutine_returns_true_location);
9762 	bool_operator2_result = (bool_operator2_subroutine_location == m_po_subroutine_returns_true_location);
9763 	pVec4Operator1		  = (vec4_operator1_subroutine_location == m_po_subroutine_divide_by_two_location) ?
9764 						 vec4operator_div2 :
9765 						 vec4operator_mul4;
9766 	pVec4Operator2 = (vec4_operator2_subroutine_location == m_po_subroutine_divide_by_two_location) ?
9767 						 vec4operator_div2 :
9768 						 vec4operator_mul4;
9769 
9770 	for (unsigned int n_vertex = 0; n_vertex < m_n_points_to_draw; ++n_vertex)
9771 	{
9772 		float expected_value = 0.0f;
9773 
9774 		if (bool_operator1_result)
9775 		{
9776 			float value = float((3 * n_vertex + 1) * 2);
9777 
9778 			while (bool_operator1_result)
9779 			{
9780 				value /= float(n_vertex + 2);
9781 
9782 				if (value <= 1.0f)
9783 					break;
9784 			}
9785 
9786 			expected_value = value;
9787 		}
9788 		else
9789 		{
9790 			tcu::Vec4 value((float)n_vertex, (float)n_vertex + 1, (float)n_vertex + 2, (float)n_vertex + 3);
9791 
9792 			switch (n_vertex % 2)
9793 			{
9794 			case 0:
9795 			{
9796 				for (unsigned int iteration = 0; iteration < n_vertex && bool_operator2_result; ++iteration)
9797 				{
9798 					value = pVec4Operator2(pVec4Operator1(value));
9799 				}
9800 
9801 				break;
9802 			}
9803 
9804 			case 1:
9805 			{
9806 				for (unsigned int iteration = 0; iteration < n_vertex * 2; ++iteration)
9807 				{
9808 					value = pVec4Operator1(pVec4Operator2(value));
9809 				}
9810 
9811 				break;
9812 			}
9813 			} /* switch (n_vertex % 2) */
9814 
9815 			expected_value = value.x() + value.y() + value.z() + value.w();
9816 		}
9817 
9818 		if (de::abs(expected_value - *traveller_ptr) > epsilon)
9819 		{
9820 			m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data was found to be invalid at index [" << n_vertex
9821 							   << "]"
9822 								  "for the following subroutine location configuration:"
9823 								  " bool_operator1_subroutine_location:["
9824 							   << bool_operator1_subroutine_location << "]"
9825 																		" bool_operator2_subroutine_location:["
9826 							   << bool_operator2_subroutine_location << "]"
9827 																		" vec4_operator1_subroutine_location:["
9828 							   << vec4_operator1_subroutine_location << "]"
9829 																		" vec4_operator2_subroutine_location:["
9830 							   << vec4_operator2_subroutine_location << "];"
9831 																		" expected data:"
9832 							   << expected_value << ", found:" << *traveller_ptr << tcu::TestLog::EndMessage;
9833 
9834 			m_has_test_passed = false;
9835 		}
9836 
9837 		++traveller_ptr;
9838 	} /* for (all drawn points) */
9839 }
9840 
9841 /** Constructor.
9842  *
9843  *  @param context Rendering context.
9844  *
9845  **/
NegativeTest1(deqp::Context & context)9846 NegativeTest1::NegativeTest1(deqp::Context& context)
9847 	: TestCase(context, "subroutine_errors", "Verifies all GL_INVALID_OPERATION, GL_INVALID_VALUE, GL_INVALID ENUM "
9848 											 "errors related to subroutine usage are properly generated.")
9849 	, m_has_test_passed(true)
9850 	, m_po_active_subroutine_uniform_locations(0)
9851 	, m_po_active_subroutine_uniforms(0)
9852 	, m_po_active_subroutines(0)
9853 	, m_po_subroutine_uniform_function_index(-1)
9854 	, m_po_subroutine_uniform_function2_index(-1)
9855 	, m_po_subroutine_test1_index(GL_INVALID_INDEX)
9856 	, m_po_subroutine_test2_index(GL_INVALID_INDEX)
9857 	, m_po_subroutine_test3_index(GL_INVALID_INDEX)
9858 	, m_po_not_linked_id(0)
9859 	, m_po_id(0)
9860 	, m_vs_id(0)
9861 {
9862 	/* Left blank intentionally */
9863 }
9864 
9865 /** Deinitializes all GL objects that may have been created during
9866  *  test execution.
9867  **/
deinit()9868 void NegativeTest1::deinit()
9869 {
9870 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9871 
9872 	if (m_po_id != 0)
9873 	{
9874 		gl.deleteProgram(m_po_id);
9875 
9876 		m_po_id = 0;
9877 	}
9878 
9879 	if (m_po_not_linked_id != 0)
9880 	{
9881 		gl.deleteProgram(m_po_not_linked_id);
9882 
9883 		m_po_not_linked_id = 0;
9884 	}
9885 
9886 	if (m_vs_id != 0)
9887 	{
9888 		gl.deleteShader(m_vs_id);
9889 
9890 		m_vs_id = 0;
9891 	}
9892 }
9893 
9894 /** Initializes all GL objects required to run the test.  */
initTest()9895 void NegativeTest1::initTest()
9896 {
9897 	glw::GLint			  compile_status = GL_FALSE;
9898 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
9899 
9900 	/* Create program objects */
9901 	m_po_not_linked_id = gl.createProgram();
9902 	m_po_id			   = gl.createProgram();
9903 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
9904 
9905 	/* Create vertex shader object */
9906 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
9907 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
9908 
9909 	/* Set up vertex shader */
9910 	const char* vs_body = "#version 400\n"
9911 						  "\n"
9912 						  "#extension GL_ARB_shader_subroutine : require\n"
9913 						  "\n"
9914 						  "subroutine void subroutineType (out ivec2 arg);\n"
9915 						  "subroutine void subroutineType2(out ivec4 arg);\n"
9916 						  "\n"
9917 						  "subroutine(subroutineType) void test1(out ivec2 arg)\n"
9918 						  "{\n"
9919 						  "    arg = ivec2(1, 2);\n"
9920 						  "}\n"
9921 						  "subroutine(subroutineType) void test2(out ivec2 arg)\n"
9922 						  "{\n"
9923 						  "    arg = ivec2(3,4);\n"
9924 						  "}\n"
9925 						  "subroutine(subroutineType2) void test3(out ivec4 arg)\n"
9926 						  "{\n"
9927 						  "    arg = ivec4(1, 2, 3, 4);\n"
9928 						  "}\n"
9929 						  "\n"
9930 						  "subroutine uniform subroutineType  function;\n"
9931 						  "subroutine uniform subroutineType2 function2;\n"
9932 						  "\n"
9933 						  "void main()\n"
9934 						  "{\n"
9935 						  "    ivec2 test;\n"
9936 						  "    ivec4 test2;\n"
9937 						  "\n"
9938 						  "    function(test);\n"
9939 						  "\n"
9940 						  "    if (test.x > 2)\n"
9941 						  "    {\n"
9942 						  "        gl_Position = vec4(1);\n"
9943 						  "    }\n"
9944 						  "    else\n"
9945 						  "    {\n"
9946 						  "        function2(test2);\n"
9947 						  "\n"
9948 						  "        gl_Position = vec4(float(test2.x) );\n"
9949 						  "    }\n"
9950 						  "}\n";
9951 
9952 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
9953 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
9954 
9955 	gl.compileShader(m_vs_id);
9956 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
9957 
9958 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
9959 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
9960 
9961 	if (compile_status == GL_FALSE)
9962 	{
9963 		TCU_FAIL("Shader compilation failed");
9964 	}
9965 
9966 	/* Set up & link the test program object */
9967 	glw::GLint link_status = GL_FALSE;
9968 
9969 	gl.attachShader(m_po_id, m_vs_id);
9970 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
9971 
9972 	gl.linkProgram(m_po_id);
9973 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
9974 
9975 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
9976 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
9977 
9978 	if (link_status == GL_FALSE)
9979 	{
9980 		TCU_FAIL("Program linking failed");
9981 	}
9982 
9983 	/* Query test program object's properties */
9984 	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
9985 						 &m_po_active_subroutine_uniform_locations);
9986 	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &m_po_active_subroutine_uniforms);
9987 	gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &m_po_active_subroutines);
9988 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call(s) failed.");
9989 
9990 	if (m_po_active_subroutine_uniform_locations != 2)
9991 	{
9992 		TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS value returned");
9993 	}
9994 
9995 	m_po_subroutine_test1_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test1");
9996 	m_po_subroutine_test2_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test2");
9997 	m_po_subroutine_test3_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test3");
9998 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
9999 
10000 	if (m_po_subroutine_test1_index == GL_INVALID_INDEX || m_po_subroutine_test2_index == GL_INVALID_INDEX ||
10001 		m_po_subroutine_test3_index == GL_INVALID_INDEX)
10002 	{
10003 		TCU_FAIL("Invalid subroutine index returned");
10004 	}
10005 
10006 	m_po_subroutine_uniform_function_index  = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function");
10007 	m_po_subroutine_uniform_function2_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function2");
10008 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
10009 
10010 	if (m_po_subroutine_uniform_function_index == -1 || m_po_subroutine_uniform_function2_index == -1)
10011 	{
10012 		TCU_FAIL("Invalid subroutine uniform index returned");
10013 	}
10014 }
10015 
10016 /** Executes test iteration.
10017  *
10018  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10019  */
iterate()10020 tcu::TestNode::IterateResult NegativeTest1::iterate()
10021 {
10022 	glw::GLenum			  error_code = GL_NO_ERROR;
10023 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
10024 
10025 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10026 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10027 	{
10028 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10029 	}
10030 
10031 	/* Initialize GL objects required to run the test */
10032 	initTest();
10033 
10034 	/* The error INVALID_OPERATION is generated by GetSubroutineUniformLocation
10035 	 * if the program object identified by <program> has not been successfully
10036 	 * linked.
10037 	 */
10038 	gl.getSubroutineUniformLocation(m_po_not_linked_id, GL_FRAGMENT_SHADER, "subroutine_uniform_name");
10039 
10040 	error_code = gl.getError();
10041 
10042 	if (error_code != GL_INVALID_OPERATION)
10043 	{
10044 		m_testCtx.getLog() << tcu::TestLog::Message
10045 						   << "glGetSubroutineUniformLocation() does not generate GL_INVALID_OPERATION "
10046 							  "error code when called for a non-linked program object."
10047 						   << tcu::TestLog::EndMessage;
10048 
10049 		m_has_test_passed = false;
10050 	}
10051 
10052 	/* The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or
10053 	 * GetActiveSubroutineUniformName if <index> is greater than or equal to the
10054 	 * value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage.
10055 	 */
10056 	glw::GLint temp_length = 0;
10057 	glw::GLint temp_values = 0;
10058 
10059 	gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms,
10060 									GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10061 	error_code = gl.getError();
10062 
10063 	if (error_code == GL_INVALID_VALUE)
10064 	{
10065 		gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10066 										GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10067 
10068 		error_code = gl.getError();
10069 	}
10070 
10071 	if (error_code != GL_INVALID_VALUE)
10072 	{
10073 		m_testCtx.getLog() << tcu::TestLog::Message
10074 						   << "glGetActiveSubroutineUniformiv() does not generate GL_INVALID_VALUE "
10075 							  "when passed <index> argument that is greater than or equal to "
10076 							  "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10077 						   << tcu::TestLog::EndMessage;
10078 
10079 		m_has_test_passed = false;
10080 	}
10081 
10082 	gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 0, /* bufsize */
10083 									  &temp_length, DE_NULL);										 /* name */
10084 	error_code = gl.getError();
10085 
10086 	if (error_code == GL_INVALID_VALUE)
10087 	{
10088 		gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10089 										  0,					  /* bufsize */
10090 										  &temp_length, DE_NULL); /* name */
10091 
10092 		error_code = gl.getError();
10093 	}
10094 
10095 	if (error_code != GL_INVALID_VALUE)
10096 	{
10097 		m_testCtx.getLog() << tcu::TestLog::Message
10098 						   << "glGetActiveSubroutineUniformName() does not generate GL_INVALID_VALUE "
10099 							  "when passed <index> argument that is greater than or equal to "
10100 							  "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10101 						   << tcu::TestLog::EndMessage;
10102 
10103 		m_has_test_passed = false;
10104 	}
10105 
10106 	/* The error INVALID_VALUE is generated by GetActiveSubroutineName if <index>
10107 	 * is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader
10108 	 * stage.
10109 	 */
10110 	gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines, 0, /* bufsize */
10111 							   &temp_length, DE_NULL);								  /* name */
10112 	error_code = gl.getError();
10113 
10114 	if (error_code == GL_INVALID_VALUE)
10115 	{
10116 		gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines + 1, 0, /* bufsize */
10117 								   &temp_length, DE_NULL);									  /* name */
10118 
10119 		error_code = gl.getError();
10120 	}
10121 
10122 	if (error_code != GL_INVALID_VALUE)
10123 	{
10124 		m_testCtx.getLog() << tcu::TestLog::Message << "glGetActiveSubroutineName() does not generate GL_INVALID_VALUE "
10125 													   "when passed <index> argument that is greater than or equal to "
10126 													   "the value of GL_ACTIVE_SUBROUTINES."
10127 						   << tcu::TestLog::EndMessage;
10128 
10129 		m_has_test_passed = false;
10130 	}
10131 
10132 	/* The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count>
10133 	 * is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the
10134 	 * shader stage <shadertype>.
10135 	 */
10136 	glw::GLuint index = 0;
10137 
10138 	gl.useProgram(m_po_id);
10139 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10140 
10141 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations - 1, &index);
10142 	error_code = gl.getError();
10143 
10144 	if (error_code == GL_INVALID_VALUE)
10145 	{
10146 		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &index);
10147 
10148 		error_code = gl.getError();
10149 	}
10150 
10151 	if (error_code != GL_INVALID_VALUE)
10152 	{
10153 		m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesiv() does not generate GL_INVALID_VALUE "
10154 													   "when passed <count> argument that is not equal to the value of "
10155 													   "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10156 						   << tcu::TestLog::EndMessage;
10157 
10158 		m_has_test_passed = false;
10159 	}
10160 
10161 	/* The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value
10162 	 * in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES
10163 	 * for the shader stage.
10164 	 */
10165 	glw::GLuint invalid_subroutine_indices[4] = { (GLuint)m_po_active_subroutines, (GLuint)m_po_active_subroutines,
10166 												  (GLuint)m_po_active_subroutines + 1,
10167 												  (GLuint)m_po_active_subroutines + 1 };
10168 
10169 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, /* count */
10170 							 invalid_subroutine_indices + 0);
10171 	error_code = gl.getError();
10172 
10173 	if (error_code == GL_INVALID_VALUE)
10174 	{
10175 		gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations,
10176 								 invalid_subroutine_indices + 2);
10177 
10178 		error_code = gl.getError();
10179 	}
10180 
10181 	if (error_code != GL_INVALID_VALUE)
10182 	{
10183 		m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesuiv() does not generate GL_INVALID_VALUE "
10184 													   "when the value passed via <indices> argument is greater than "
10185 													   "or equal to the value of GL_ACTIVE_SUBROUTINES."
10186 						   << tcu::TestLog::EndMessage;
10187 
10188 		m_has_test_passed = false;
10189 	}
10190 
10191 	/* The error INVALID_OPERATION is generated by UniformSubroutinesuiv() if any
10192 	 * subroutine index in <indices> identifies a subroutine not associated with
10193 	 * the type of the subroutine uniform variable assigned to the corresponding
10194 	 * location.
10195 	 */
10196 	glw::GLuint invalid_subroutine_indices2[2] = { m_po_subroutine_test1_index, m_po_subroutine_test1_index };
10197 
10198 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, invalid_subroutine_indices2);
10199 	error_code = gl.getError();
10200 
10201 	if (error_code != GL_INVALID_OPERATION)
10202 	{
10203 		m_testCtx.getLog() << tcu::TestLog::Message
10204 						   << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10205 							  "when the subroutine index passed via <indices> argument identifies"
10206 							  "a subroutine not associated with the type of the subroutine uniform "
10207 							  "assigned to the corresponding location."
10208 						   << tcu::TestLog::EndMessage;
10209 
10210 		m_has_test_passed = false;
10211 	}
10212 
10213 	/* The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no
10214 	 * program is active.
10215 	 */
10216 	glw::GLuint valid_subroutine_locations[2] = { 0 };
10217 
10218 	valid_subroutine_locations[m_po_subroutine_uniform_function_index]  = m_po_subroutine_test1_index;
10219 	valid_subroutine_locations[m_po_subroutine_uniform_function2_index] = m_po_subroutine_test3_index;
10220 
10221 	gl.useProgram(0);
10222 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10223 
10224 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, valid_subroutine_locations);
10225 	error_code = gl.getError();
10226 
10227 	if (error_code != GL_INVALID_OPERATION)
10228 	{
10229 		m_testCtx.getLog() << tcu::TestLog::Message
10230 						   << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10231 							  "when called without an active program object."
10232 						   << tcu::TestLog::EndMessage;
10233 
10234 		m_has_test_passed = false;
10235 	}
10236 
10237 	/* The error INVALID_VALUE is generated by GetUniformSubroutineuiv if
10238 	 * <location> is greater than or equal to the value of
10239 	 * ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage.
10240 	 */
10241 	glw::GLuint temp_value = 0;
10242 
10243 	gl.useProgram(m_po_id);
10244 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10245 
10246 	gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, &temp_value);
10247 	error_code = gl.getError();
10248 
10249 	if (error_code == GL_INVALID_VALUE)
10250 	{
10251 		gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &temp_value);
10252 		error_code = gl.getError();
10253 	}
10254 
10255 	if (error_code != GL_INVALID_VALUE)
10256 	{
10257 		m_testCtx.getLog() << tcu::TestLog::Message
10258 						   << "glGetUniformSubroutineuiv() does not generate GL_INVALID_VALUE "
10259 							  "when called for location that is greater than or equal to the value "
10260 							  "of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10261 						   << tcu::TestLog::EndMessage;
10262 
10263 		m_has_test_passed = false;
10264 	}
10265 
10266 	/* The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no
10267 	 * program is active for the shader stage identified by <shadertype>.
10268 	 */
10269 	const glw::GLenum undefined_shader_stages[] = { GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER,
10270 													GL_TESS_EVALUATION_SHADER };
10271 	const unsigned int n_undefined_shader_stages = sizeof(undefined_shader_stages) / sizeof(undefined_shader_stages[0]);
10272 
10273 	for (unsigned int n_undefined_shader_stage = 0; n_undefined_shader_stage < n_undefined_shader_stages;
10274 		 ++n_undefined_shader_stage)
10275 	{
10276 		glw::GLenum shader_stage = undefined_shader_stages[n_undefined_shader_stage];
10277 
10278 		gl.getUniformSubroutineuiv(shader_stage, 0, /* location */
10279 								   &temp_value);
10280 		error_code = gl.getError();
10281 
10282 		if (error_code != GL_INVALID_OPERATION)
10283 		{
10284 			m_testCtx.getLog() << tcu::TestLog::Message
10285 							   << "glGetUniformSubroutineuiv() does not generate GL_INVALID_OPERATION "
10286 								  "when called for a shader stage that is not defined for active "
10287 								  "program object."
10288 							   << tcu::TestLog::EndMessage;
10289 
10290 			m_has_test_passed = false;
10291 		}
10292 	} /* for (all undefined shader stages) */
10293 
10294 	/* All done */
10295 	if (m_has_test_passed)
10296 	{
10297 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10298 	}
10299 	else
10300 	{
10301 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10302 	}
10303 
10304 	return STOP;
10305 }
10306 
10307 /** Constructor
10308  *
10309  *  @param context Rendering context.
10310  *
10311  **/
NegativeTest2(deqp::Context & context)10312 NegativeTest2::NegativeTest2(deqp::Context& context)
10313 	: TestCase(context, "subroutine_uniform_scope", "Verifies subroutine uniforms declared in shader stage A"
10314 													"cannot be accessed from a different stage.")
10315 	, m_fs_id(0)
10316 	, m_gs_id(0)
10317 	, m_has_test_passed(true)
10318 	, m_po_id(0)
10319 	, m_tc_id(0)
10320 	, m_te_id(0)
10321 	, m_vs_id(0)
10322 {
10323 	/* Left blank intentionally */
10324 }
10325 
10326 /** Deinitializes all GL objects that may have been created during test execution */
deinit()10327 void NegativeTest2::deinit()
10328 {
10329 	deinitGLObjects();
10330 }
10331 
10332 /** Deinitializes all GL objects that may have been created during test execution */
deinitGLObjects()10333 void NegativeTest2::deinitGLObjects()
10334 {
10335 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10336 
10337 	if (m_fs_id != 0)
10338 	{
10339 		gl.deleteShader(m_fs_id);
10340 
10341 		m_fs_id = 0;
10342 	}
10343 
10344 	if (m_gs_id != 0)
10345 	{
10346 		gl.deleteShader(m_gs_id);
10347 
10348 		m_gs_id = 0;
10349 	}
10350 
10351 	if (m_tc_id != 0)
10352 	{
10353 		gl.deleteShader(m_tc_id);
10354 
10355 		m_tc_id = 0;
10356 	}
10357 
10358 	if (m_te_id != 0)
10359 	{
10360 		gl.deleteShader(m_te_id);
10361 
10362 		m_te_id = 0;
10363 	}
10364 
10365 	if (m_vs_id != 0)
10366 	{
10367 		gl.deleteShader(m_vs_id);
10368 
10369 		m_vs_id = 0;
10370 	}
10371 
10372 	if (m_po_id != 0)
10373 	{
10374 		gl.deleteProgram(m_po_id);
10375 
10376 		m_po_id = 0;
10377 	}
10378 }
10379 
10380 /** Builds an offending program object and tries to link it. We're either expecting
10381  *  a compile-time or link-time error here.
10382  *
10383  *  If the program object builds successfully, the test has failed.
10384  *
10385  *  @param referencing_stage Shader stage which defines a subroutine uniform that
10386  *                           should be called from fragment/geometry/tess control/
10387  *                           tess evaluation/vertex shader stages.
10388  *
10389  **/
executeTestCase(const Utils::_shader_stage & referencing_stage)10390 void NegativeTest2::executeTestCase(const Utils::_shader_stage& referencing_stage)
10391 {
10392 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10393 
10394 	const std::string fs_body = getFragmentShaderBody(referencing_stage);
10395 	const std::string gs_body = getGeometryShaderBody(referencing_stage);
10396 	const std::string tc_body = getTessellationControlShaderBody(referencing_stage);
10397 	const std::string te_body = getTessellationEvaluationShaderBody(referencing_stage);
10398 	const std::string vs_body = getVertexShaderBody(referencing_stage);
10399 
10400 	if (Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, NULL, /* xfb_varyings */
10401 							0,													   /* n_xfb_varyings */
10402 							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
10403 	{
10404 		/* Test program should not have built correctly ! */
10405 		m_testCtx.getLog() << tcu::TestLog::Message << "In the following program, one of the stages references "
10406 													   "a subroutine that is defined in another stage. This "
10407 													   "is forbidden by the specification.\n"
10408 													   "\n"
10409 													   "Vertex shader:\n\n"
10410 						   << vs_body.c_str() << "\n\nTessellation control shader:\n\n"
10411 						   << tc_body.c_str() << "\n\nTessellation evaluation shader:\n\n"
10412 						   << te_body.c_str() << "\n\nGeometry shader:\n\n"
10413 						   << gs_body.c_str() << "\n\nFragment shader:\n\n"
10414 						   << fs_body.c_str() << tcu::TestLog::EndMessage;
10415 
10416 		m_has_test_passed = false;
10417 	} /* if (test program was built successfully) */
10418 
10419 	/* Release the shaders & the program object that buildProgram() created */
10420 	deinitGLObjects();
10421 }
10422 
10423 /** Retrieves an offending fragment shader body.
10424  *
10425  *  @param referencing_stage Shader stage which defines the subroutine uniform that
10426  *                           will be called from fragment shader.
10427  *
10428  *  @return Requested string.
10429  **/
getFragmentShaderBody(const Utils::_shader_stage & referencing_stage) const10430 std::string NegativeTest2::getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const
10431 {
10432 	std::stringstream result;
10433 
10434 	/* Form the pre-amble */
10435 	result << "#version 400\n"
10436 			  "\n"
10437 			  "#extension GL_ARB_shader_subroutine : require\n"
10438 			  "\n"
10439 			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10440 			  "\n"
10441 			  /* Define a subroutine */
10442 			  "subroutine(testSubroutineType) void fs_subroutine(out vec4 test_argument)\n"
10443 			  "{\n"
10444 			  "    test_argument = vec4(1, 0, 0, 0);\n"
10445 			  "}\n"
10446 			  "\n"
10447 			  /* Define output variables */
10448 			  "out vec4 result;\n"
10449 			  "\n"
10450 			  /* Define uniforms */
10451 			  "subroutine uniform testSubroutineType test_fs_subroutine;\n"
10452 			  "\n"
10453 			  /* Define main() */
10454 			  "void main()\n"
10455 			  "{\n"
10456 			  "    "
10457 		   << getSubroutineUniformName(referencing_stage) << "(result);\n"
10458 															 "}\n";
10459 
10460 	return result.str();
10461 }
10462 
10463 /** Retrieves an offending geometry shader body.
10464  *
10465  *  @param referencing_stage Shader stage which defines the subroutine uniform that
10466  *                           will be called from geometry shader.
10467  *
10468  *  @return Requested string.
10469  **/
getGeometryShaderBody(const Utils::_shader_stage & referencing_stage) const10470 std::string NegativeTest2::getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const
10471 {
10472 	std::stringstream result;
10473 
10474 	/* Form the pre-amble */
10475 	result << "#version 400\n"
10476 			  "\n"
10477 			  "#extension GL_ARB_shader_subroutine : require\n"
10478 			  "\n"
10479 			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10480 			  "\n"
10481 			  "layout(points)                   in;\n"
10482 			  "layout(points, max_vertices = 1) out;\n"
10483 			  "\n"
10484 			  /* Define a subroutine */
10485 			  "subroutine(testSubroutineType) void gs_subroutine(out vec4 test_argument)\n"
10486 			  "{\n"
10487 			  "    test_argument = vec4(0, 1, 1, 1);\n"
10488 			  "}\n"
10489 			  "\n"
10490 			  /* Define output variables */
10491 			  "out vec4 result;\n"
10492 			  "\n"
10493 			  /* Define uniforms */
10494 			  "subroutine uniform testSubroutineType test_gs_subroutine;\n"
10495 			  "\n"
10496 			  /* Define main() */
10497 			  "void main()\n"
10498 			  "{\n"
10499 			  "    "
10500 		   << getSubroutineUniformName(referencing_stage) << "(result);\n"
10501 															 "}\n";
10502 
10503 	return result.str();
10504 }
10505 
10506 /** Retrieves name of the subroutine uniform that is defined in user-specified
10507  *  shader stage.
10508  *
10509  *  @param stage Shader stage to retrieve the subroutine uniform name for.
10510  *
10511  *  @return As per description.
10512  **/
getSubroutineUniformName(const Utils::_shader_stage & stage) const10513 std::string NegativeTest2::getSubroutineUniformName(const Utils::_shader_stage& stage) const
10514 {
10515 	std::string result = "?";
10516 
10517 	switch (stage)
10518 	{
10519 	case Utils::SHADER_STAGE_FRAGMENT:
10520 	{
10521 		result = "test_fs_subroutine";
10522 
10523 		break;
10524 	}
10525 
10526 	case Utils::SHADER_STAGE_GEOMETRY:
10527 	{
10528 		result = "test_gs_subroutine";
10529 
10530 		break;
10531 	}
10532 
10533 	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
10534 	{
10535 		result = "test_tc_subroutine";
10536 
10537 		break;
10538 	}
10539 
10540 	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
10541 	{
10542 		result = "test_te_subroutine";
10543 
10544 		break;
10545 	}
10546 
10547 	case Utils::SHADER_STAGE_VERTEX:
10548 	{
10549 		result = "test_vs_subroutine";
10550 
10551 		break;
10552 	}
10553 
10554 	default:
10555 	{
10556 		TCU_FAIL("Unrecognized shader stage requested");
10557 	}
10558 	} /* switch (stage) */
10559 
10560 	return result;
10561 }
10562 
10563 /** Retrieves an offending tessellation control shader body.
10564  *
10565  *  @param referencing_stage Shader stage which defines the subroutine uniform that
10566  *                           will be called from tessellation control shader.
10567  *
10568  *  @return Requested string.
10569  **/
getTessellationControlShaderBody(const Utils::_shader_stage & referencing_stage) const10570 std::string NegativeTest2::getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const
10571 {
10572 	std::stringstream result;
10573 
10574 	/* Form the pre-amble */
10575 	result << "#version 400\n"
10576 			  "\n"
10577 			  "#extension GL_ARB_shader_subroutine : require\n"
10578 			  "\n"
10579 			  "layout(vertices = 4) out;\n"
10580 			  "\n"
10581 			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10582 			  "\n"
10583 			  /* Define a subroutine */
10584 			  "subroutine(testSubroutineType) void tc_subroutine(out vec4 test_argument)\n"
10585 			  "{\n"
10586 			  "    test_argument = vec4(0, 0, 1, 0);\n"
10587 			  "}\n"
10588 			  "\n"
10589 			  /* Define uniforms */
10590 			  "subroutine uniform testSubroutineType test_tc_subroutine;\n"
10591 			  "\n"
10592 			  /* Define main() */
10593 			  "void main()\n"
10594 			  "{\n"
10595 			  "    "
10596 		   << getSubroutineUniformName(referencing_stage) << "(gl_out[gl_InvocationID].gl_Position);\n"
10597 															 "}\n";
10598 
10599 	return result.str();
10600 }
10601 
10602 /** Retrieves an offending tessellation evaluation shader body.
10603  *
10604  *  @param referencing_stage Shader stage which defines the subroutine uniform that
10605  *                           will be called from tessellation evaluation shader.
10606  *
10607  *  @return Requested string.
10608  **/
getTessellationEvaluationShaderBody(const Utils::_shader_stage & referencing_stage) const10609 std::string NegativeTest2::getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const
10610 {
10611 	std::stringstream result;
10612 
10613 	/* Form the pre-amble */
10614 	result << "#version 400\n"
10615 			  "\n"
10616 			  "#extension GL_ARB_shader_subroutine : require\n"
10617 			  "\n"
10618 			  "layout(quads) in;\n"
10619 			  "\n"
10620 			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10621 			  "\n"
10622 			  /* Define a subroutine */
10623 			  "subroutine(testSubroutineType) void te_subroutine(out vec4 test_argument)\n"
10624 			  "{\n"
10625 			  "    test_argument = vec4(1, 1, 1, 1);\n"
10626 			  "}\n"
10627 			  "\n"
10628 			  /* Define uniforms */
10629 			  "subroutine uniform testSubroutineType test_te_subroutine;\n"
10630 			  "\n"
10631 			  /* Define main() */
10632 			  "void main()\n"
10633 			  "{\n"
10634 			  "    "
10635 		   << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
10636 															 "}\n";
10637 
10638 	return result.str();
10639 }
10640 
10641 /** Retrieves an offending vertex shader body.
10642  *
10643  *  @param referencing_stage Shader stage which defines the subroutine uniform that
10644  *                           will be called from vertex shader.
10645  *
10646  *  @return Requested string.
10647  **/
getVertexShaderBody(const Utils::_shader_stage & referencing_stage) const10648 std::string NegativeTest2::getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const
10649 {
10650 	std::stringstream result;
10651 
10652 	/* Form the pre-amble */
10653 	result << "#version 400\n"
10654 			  "\n"
10655 			  "#extension GL_ARB_shader_subroutine : require\n"
10656 			  "\n"
10657 			  "subroutine void testSubroutineType(out vec4 test_argument);\n"
10658 			  "\n"
10659 			  /* Define a subroutine */
10660 			  "subroutine(testSubroutineType) void vs_subroutine(out vec4 test_argument)\n"
10661 			  "{\n"
10662 			  "    test_argument = vec4(0, 1, 0, 0);\n"
10663 			  "}\n"
10664 			  "\n"
10665 			  /* Define uniforms */
10666 			  "subroutine uniform testSubroutineType test_vs_subroutine;\n"
10667 			  "\n"
10668 			  /* Define main() */
10669 			  "void main()\n"
10670 			  "{\n"
10671 			  "    "
10672 		   << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
10673 															 "}\n";
10674 
10675 	return result.str();
10676 }
10677 
10678 /** Executes test iteration.
10679  *
10680  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10681  */
iterate()10682 tcu::TestNode::IterateResult NegativeTest2::iterate()
10683 {
10684 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10685 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10686 	{
10687 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10688 	}
10689 
10690 	/* Iterate over all shader stages and execute the checks */
10691 	for (int referencing_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
10692 		 referencing_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++referencing_stage)
10693 	{
10694 		executeTestCase(static_cast<Utils::_shader_stage>(referencing_stage));
10695 	} /* for (all test cases) */
10696 
10697 	/* All done */
10698 	if (m_has_test_passed)
10699 	{
10700 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10701 	}
10702 	else
10703 	{
10704 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10705 	}
10706 
10707 	return STOP;
10708 }
10709 
10710 /** Constructor.
10711  *
10712  *  @param context Rendering context.
10713  *
10714  **/
NegativeTest3(deqp::Context & context)10715 NegativeTest3::NegativeTest3(deqp::Context& context)
10716 	: TestCase(context, "missing_subroutine_keyword", "Verifies that subroutine keyword is necessary when declaring a "
10717 													  "subroutine uniforn and a compilation error occurs without it.")
10718 	, m_has_test_passed(true)
10719 	, m_so_id(0)
10720 {
10721 	/* Left blank intentionally */
10722 }
10723 
10724 /** Deinitializes all GL objects that may have been created during test execution */
deinit()10725 void NegativeTest3::deinit()
10726 {
10727 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10728 
10729 	if (m_so_id != 0)
10730 	{
10731 		gl.deleteShader(m_so_id);
10732 
10733 		m_so_id = 0;
10734 	}
10735 }
10736 
10737 /** Verifies that broken shader (for user-specified shader stage) does not compile.
10738  *
10739  *  @param shader_stage Shader stage to use for the test.
10740  **/
executeTest(const Utils::_shader_stage & shader_stage)10741 void NegativeTest3::executeTest(const Utils::_shader_stage& shader_stage)
10742 {
10743 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10744 
10745 	/* Generate a new shader object */
10746 	m_so_id = gl.createShader(Utils::getGLenumForShaderStage(shader_stage));
10747 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
10748 
10749 	/* Assign body to the shader */
10750 	std::string body;
10751 	const char* body_raw_ptr = DE_NULL;
10752 
10753 	switch (shader_stage)
10754 	{
10755 	case Utils::SHADER_STAGE_VERTEX:
10756 		body = getVertexShaderBody();
10757 		break;
10758 	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
10759 		body = getTessellationControlShaderBody();
10760 		break;
10761 	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
10762 		body = getTessellationEvaluationShaderBody();
10763 		break;
10764 	case Utils::SHADER_STAGE_GEOMETRY:
10765 		body = getGeometryShaderBody();
10766 		break;
10767 	case Utils::SHADER_STAGE_FRAGMENT:
10768 		body = getFragmentShaderBody();
10769 		break;
10770 
10771 	default:
10772 	{
10773 		TCU_FAIL("Unrecognized shader stage requested");
10774 	}
10775 	} /* switch (shader_stage) */
10776 
10777 	body_raw_ptr = body.c_str();
10778 
10779 	gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
10780 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
10781 
10782 	/* Try to compile the shader */
10783 	glw::GLint compile_status = 0;
10784 
10785 	gl.compileShader(m_so_id);
10786 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10787 
10788 	gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
10789 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10790 
10791 	if (compile_status == GL_TRUE)
10792 	{
10793 		m_testCtx.getLog() << tcu::TestLog::Message << "The following shader was expected to fail to compile but was "
10794 													   "accepted by the compiler:\n"
10795 													   "\n"
10796 						   << body.c_str() << tcu::TestLog::EndMessage;
10797 
10798 		m_has_test_passed = false;
10799 	}
10800 
10801 	/* Good to release the shader at this point */
10802 	gl.deleteShader(m_so_id);
10803 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
10804 }
10805 
10806 /** Retrieves body of a broken fragment shader.
10807  *
10808  *  @return Requested string.
10809  **/
getFragmentShaderBody() const10810 std::string NegativeTest3::getFragmentShaderBody() const
10811 {
10812 	return "#version 400\n"
10813 		   "\n"
10814 		   "#extension GL_ARB_shader_subroutine : require\n"
10815 		   "\n"
10816 		   "subroutine void testSubroutineType(inout vec4 test);\n"
10817 		   "\n"
10818 		   "void testSubroutine1(inout vec4 test)\n"
10819 		   "{\n"
10820 		   "    test += vec4(3, 4, 5, 6);\n"
10821 		   "}\n"
10822 		   "\n"
10823 		   "uniform testSubroutineType subroutineFunction;\n"
10824 		   "out     vec4               result;\n"
10825 		   "\n"
10826 		   "void main()\n"
10827 		   "{\n"
10828 		   "    vec4 test = vec4(2, 3, 4, 5);\n"
10829 		   "\n"
10830 		   "    subroutineFunction(test);\n"
10831 		   "\n"
10832 		   "    result = test;\n"
10833 		   "}\n";
10834 }
10835 
10836 /** Retrieves body of a broken geometry shader.
10837  *
10838  *  @return Requested string.
10839  **/
getGeometryShaderBody() const10840 std::string NegativeTest3::getGeometryShaderBody() const
10841 {
10842 	return "#version 400\n"
10843 		   "\n"
10844 		   "#extension GL_ARB_shader_subroutine : require\n"
10845 		   "\n"
10846 		   "layout(points)                   in;\n"
10847 		   "layout(points, max_vertices = 1) out;\n"
10848 		   "\n"
10849 		   "subroutine void testSubroutineType(inout vec4 test);\n"
10850 		   "\n"
10851 		   "void testSubroutine1(inout vec4 test)\n"
10852 		   "{\n"
10853 		   "    test += vec4(3, 4, 5, 6);\n"
10854 		   "}\n"
10855 		   "\n"
10856 		   "uniform testSubroutineType subroutineFunction;\n"
10857 		   "\n"
10858 		   "void main()\n"
10859 		   "{\n"
10860 		   "    vec4 test = vec4(2, 3, 4, 5);\n"
10861 		   "\n"
10862 		   "    subroutineFunction(test);\n"
10863 		   "\n"
10864 		   "    gl_Position = test;\n"
10865 		   "    EmitVertex();\n"
10866 		   "}\n";
10867 }
10868 
10869 /** Retrieves body of a broken tessellation control shader.
10870  *
10871  *  @return Requested string.
10872  **/
getTessellationControlShaderBody() const10873 std::string NegativeTest3::getTessellationControlShaderBody() const
10874 {
10875 	return "#version 400\n"
10876 		   "\n"
10877 		   "#extension GL_ARB_shader_subroutine : require\n"
10878 		   "\n"
10879 		   "layout(vertices=4) out;\n"
10880 		   "\n"
10881 		   "subroutine void testSubroutineType(inout vec4 test);\n"
10882 		   "\n"
10883 		   "void testSubroutine1(inout vec4 test)\n"
10884 		   "{\n"
10885 		   "    test += vec4(1, 2, 3, 4);\n"
10886 		   "}\n"
10887 		   "\n"
10888 		   "uniform testSubroutineType subroutineFunction;\n"
10889 		   "\n"
10890 		   "void main()\n"
10891 		   "{\n"
10892 		   "    vec4 test = vec4(0, 1, 2, 3);\n"
10893 		   "\n"
10894 		   "    subroutineFunction(test);\n"
10895 		   "\n"
10896 		   "    gl_out[gl_InvocationID].gl_Position = test;\n"
10897 		   "}\n";
10898 }
10899 
10900 /** Retrieves body of a broken tessellation evaluation shader.
10901  *
10902  *  @return Requested string.
10903  **/
getTessellationEvaluationShaderBody() const10904 std::string NegativeTest3::getTessellationEvaluationShaderBody() const
10905 {
10906 	return "#version 400\n"
10907 		   "\n"
10908 		   "#extension GL_ARB_shader_subroutine : require\n"
10909 		   "\n"
10910 		   "layout(quads) in;\n"
10911 		   "\n"
10912 		   "subroutine void testSubroutineType(inout vec4 test);\n"
10913 		   "\n"
10914 		   "void testSubroutine1(inout vec4 test)\n"
10915 		   "{\n"
10916 		   "    test += vec4(2, 3, 4, 5);\n"
10917 		   "}\n"
10918 		   "\n"
10919 		   "uniform testSubroutineType subroutineFunction;\n"
10920 		   "\n"
10921 		   "void main()\n"
10922 		   "{\n"
10923 		   "    vec4 test = vec4(1, 2, 3, 4);\n"
10924 		   "\n"
10925 		   "    subroutineFunction(test);\n"
10926 		   "\n"
10927 		   "    gl_Position = test;\n"
10928 		   "}\n";
10929 }
10930 
10931 /** Retrieves body of a broken vertex shader.
10932  *
10933  *  @return Requested string.
10934  **/
getVertexShaderBody() const10935 std::string NegativeTest3::getVertexShaderBody() const
10936 {
10937 	return "#version 400\n"
10938 		   "\n"
10939 		   "#extension GL_ARB_shader_subroutine : require\n"
10940 		   "\n"
10941 		   "subroutine void testSubroutineType(inout vec4 test);\n"
10942 		   "\n"
10943 		   "void testSubroutine1(inout vec4 test)\n"
10944 		   "{\n"
10945 		   "    test += vec4(0, 1, 2, 3);\n"
10946 		   "}\n"
10947 		   "\n"
10948 		   "uniform testSubroutineType subroutineFunction;\n"
10949 		   "\n"
10950 		   "void main()\n"
10951 		   "{\n"
10952 		   "    subroutineFunction(gl_Position);\n"
10953 		   "}\n";
10954 }
10955 
10956 /** Executes test iteration.
10957  *
10958  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10959  */
iterate()10960 tcu::TestNode::IterateResult NegativeTest3::iterate()
10961 {
10962 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10963 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10964 	{
10965 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10966 	}
10967 
10968 	/* Iterate over all shader stages */
10969 	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
10970 		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
10971 	{
10972 		executeTest(static_cast<Utils::_shader_stage>(shader_stage));
10973 	} /* for (all shader stages) */
10974 
10975 	/* Done */
10976 	if (m_has_test_passed)
10977 	{
10978 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10979 	}
10980 	else
10981 	{
10982 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10983 	}
10984 
10985 	return STOP;
10986 }
10987 
10988 /** Constructor.
10989  *
10990  *  @param context Rendering context.
10991  *
10992  **/
NegativeTest4(deqp::Context & context)10993 NegativeTest4::NegativeTest4(deqp::Context& context)
10994 	: TestCase(context, "subroutines_incompatible_with_subroutine_type",
10995 			   "Verifies that a compile-time error is generated when arguments and "
10996 			   "return type do not match beween the function and each associated "
10997 			   "subroutine type.")
10998 	, m_has_test_passed(true)
10999 	, m_so_id(0)
11000 {
11001 	/* Left blank intentionally */
11002 }
11003 
11004 /** Deinitializes GL objects that may have been created during test
11005  *  execution.
11006  **/
deinit()11007 void NegativeTest4::deinit()
11008 {
11009 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11010 
11011 	if (m_so_id != 0)
11012 	{
11013 		gl.deleteShader(m_so_id);
11014 
11015 		m_so_id = 0;
11016 	}
11017 }
11018 
11019 /** Retrieves body of a shader of user-specified type that should be used
11020  *  for a single test iteration. The shader will define user-specified number
11021  *  of subroutine types, with the last type either defining an additional argument
11022  *  or using a different return type.
11023  *  A subroutine (claimed compatible with *all* subroutine types) will also be
11024  *  defined in the shader.
11025  *
11026  *  @param shader_stage       Shader stage to use for the query.
11027  *  @param n_subroutine_types Overall number of subroutine types that will be
11028  *                            declared & used in the shader. Please see description
11029  *                            for more details.
11030  *
11031  *  @return Requested string.
11032  **/
getShaderBody(const Utils::_shader_stage & shader_stage,const unsigned int & n_subroutine_types,const _test_case & test_case) const11033 std::string NegativeTest4::getShaderBody(const Utils::_shader_stage& shader_stage,
11034 										 const unsigned int& n_subroutine_types, const _test_case& test_case) const
11035 {
11036 	std::stringstream result_sstream;
11037 
11038 	/* Form the pre-amble */
11039 	result_sstream << "#version 400\n"
11040 					  "\n"
11041 					  "#extension GL_ARB_shader_subroutine : require\n"
11042 					  "\n";
11043 
11044 	/* Inject stage-specific code */
11045 	switch (shader_stage)
11046 	{
11047 	case Utils::SHADER_STAGE_GEOMETRY:
11048 	{
11049 		result_sstream << "layout (points) in;\n"
11050 						  "layout (points, max_vertices = 1) out;\n"
11051 						  "\n";
11052 
11053 		break;
11054 	}
11055 
11056 	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11057 	{
11058 		result_sstream << "layout (vertices = 4) out;\n"
11059 						  "\n";
11060 
11061 		break;
11062 	}
11063 
11064 	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11065 	{
11066 		result_sstream << "layout (quads) in;\n"
11067 						  "\n";
11068 
11069 		break;
11070 	}
11071 
11072 	default:
11073 		break;
11074 	} /* switch (shader_stage) */
11075 
11076 	/* Insert subroutine type declarations */
11077 	for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types - 1; ++n_subroutine_type)
11078 	{
11079 		result_sstream << "subroutine void subroutineType" << n_subroutine_type << "(inout vec3 argument);\n";
11080 	} /* for (all subroutine types) */
11081 
11082 	switch (test_case)
11083 	{
11084 	case TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST:
11085 	{
11086 		result_sstream << "subroutine void subroutineType" << (n_subroutine_types - 1)
11087 					   << "(inout vec3 argument, out vec4 argument2);\n";
11088 
11089 		break;
11090 	}
11091 
11092 	case TEST_CASE_INCOMPATIBLE_RETURN_TYPE:
11093 	{
11094 		result_sstream << "subroutine int subroutineType" << (n_subroutine_types - 1) << "(inout vec3 argument);\n";
11095 
11096 		break;
11097 	}
11098 
11099 	default:
11100 	{
11101 		TCU_FAIL("Unrecognized test case");
11102 	}
11103 	} /* switch (test_case) */
11104 
11105 	/* Insert subroutine declarations */
11106 	result_sstream << "subroutine(";
11107 
11108 	for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types; ++n_subroutine_type)
11109 	{
11110 		result_sstream << "subroutineType" << n_subroutine_type;
11111 
11112 		if (n_subroutine_type != (n_subroutine_types - 1))
11113 		{
11114 			result_sstream << ", ";
11115 		}
11116 	} /* for (all subroutine types) */
11117 
11118 	result_sstream << ") void function(inout vec3 argument)\n"
11119 					  "{\n"
11120 					  "    argument = vec3(1, 2, 3);\n"
11121 					  "}\n"
11122 					  "\n";
11123 
11124 	/* Insert remaining required stage-specific bits */
11125 	switch (shader_stage)
11126 	{
11127 	case Utils::SHADER_STAGE_FRAGMENT:
11128 	{
11129 		result_sstream << "out vec4 result;\n"
11130 						  "\n"
11131 						  "void main()\n"
11132 						  "{\n"
11133 						  "    result = vec4(1, 2, 3, 4);\n"
11134 						  "}\n";
11135 
11136 		break;
11137 	}
11138 
11139 	case Utils::SHADER_STAGE_GEOMETRY:
11140 	{
11141 		result_sstream << "void main()\n"
11142 						  "{\n"
11143 						  "    gl_Position = vec4(1, 2, 3, 4);\n"
11144 						  "    EmitVertex();\n"
11145 						  "}\n";
11146 
11147 		break;
11148 	}
11149 
11150 	case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11151 	{
11152 		result_sstream << "void main()\n"
11153 						  "{\n"
11154 						  "    gl_TessLevelInner[0]                = 1;\n"
11155 						  "    gl_TessLevelInner[1]                = 1;\n"
11156 						  "    gl_TessLevelOuter[0]                = 1;\n"
11157 						  "    gl_TessLevelOuter[1]                = 1;\n"
11158 						  "    gl_TessLevelOuter[2]                = 1;\n"
11159 						  "    gl_TessLevelOuter[3]                = 1;\n"
11160 						  "    gl_out[gl_InvocationID].gl_Position = vec4(2, 3, 4, 5);\n"
11161 						  "}\n";
11162 
11163 		break;
11164 	}
11165 
11166 	case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11167 	case Utils::SHADER_STAGE_VERTEX:
11168 	{
11169 		result_sstream << "void main()\n"
11170 						  "{\n"
11171 						  "    gl_Position = vec4(1, 2, 3, 4);\n"
11172 						  "}\n";
11173 
11174 		break;
11175 	}
11176 
11177 	default:
11178 	{
11179 		TCU_FAIL("Unrecognized shader stage");
11180 	}
11181 	} /* switch (shader_stage) */
11182 
11183 	return result_sstream.str();
11184 }
11185 
11186 /** Executes test iteration.
11187  *
11188  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11189  */
iterate()11190 tcu::TestNode::IterateResult NegativeTest4::iterate()
11191 {
11192 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11193 
11194 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11195 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11196 	{
11197 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11198 	}
11199 
11200 	/* Iterate over all shader stages.. */
11201 	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11202 		 shader_stage != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11203 	{
11204 		/* For each shader stage, we will be trying to compile a number of invalid shaders.
11205 		 * Each shader defines N different subroutine types. (N-1) of them are compatible
11206 		 * with a subroutine, but exactly 1 will be mismatched. The test passes if GLSL
11207 		 * compiler correctly detects that all shaders we will be trying to compile are
11208 		 * broken.
11209 		 */
11210 		const glw::GLenum shader_type = Utils::getGLenumForShaderStage(static_cast<Utils::_shader_stage>(shader_stage));
11211 
11212 		for (unsigned int n_subroutine_types = 1; n_subroutine_types < 6; /* arbitrary number */
11213 			 ++n_subroutine_types)
11214 		{
11215 			for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT);
11216 				 ++test_case)
11217 			{
11218 				std::string body;
11219 				const char* body_raw_ptr   = NULL;
11220 				glw::GLint  compile_status = GL_FALSE;
11221 
11222 				body = getShaderBody(static_cast<Utils::_shader_stage>(shader_stage), n_subroutine_types,
11223 									 static_cast<_test_case>(test_case));
11224 				body_raw_ptr = body.c_str();
11225 
11226 				/* Try to compile the shader */
11227 				m_so_id = gl.createShader(shader_type);
11228 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
11229 
11230 				gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL);
11231 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
11232 
11233 				gl.compileShader(m_so_id);
11234 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
11235 
11236 				gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
11237 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11238 
11239 				if (compile_status == GL_TRUE)
11240 				{
11241 					m_testCtx.getLog() << tcu::TestLog::Message << "A malformed "
11242 									   << Utils::getShaderStageString(static_cast<Utils::_shader_stage>(shader_stage))
11243 									   << " compiled successfully "
11244 										  "("
11245 									   << n_subroutine_types << " subroutine types "
11246 																"were defined)."
11247 									   << tcu::TestLog::EndMessage;
11248 
11249 					m_has_test_passed = false;
11250 				}
11251 
11252 				/* Release the object */
11253 				gl.deleteShader(m_so_id);
11254 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
11255 			} /* for (all test cases) */
11256 		}	 /* for (a number of different subroutine type declarations) */
11257 	}		  /* for (all shader stages) */
11258 
11259 	/* Done */
11260 	if (m_has_test_passed)
11261 	{
11262 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11263 	}
11264 	else
11265 	{
11266 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11267 	}
11268 
11269 	return STOP;
11270 }
11271 
11272 /** Constructor.
11273  *
11274  *  @param context Rendering context.
11275  *
11276  **/
NegativeTest5(deqp::Context & context)11277 NegativeTest5::NegativeTest5(deqp::Context& context)
11278 	: TestCase(context, "subroutine_uniform_wo_matching_subroutines",
11279 			   "Verifies that a link- or compile-time error occurs when "
11280 			   "trying to link a program with no subroutine for subroutine "
11281 			   "uniform variable.")
11282 	, m_fs_id(0)
11283 	, m_gs_id(0)
11284 	, m_has_test_passed(true)
11285 	, m_po_id(0)
11286 	, m_tc_id(0)
11287 	, m_te_id(0)
11288 	, m_vs_id(0)
11289 {
11290 	/* Left blank intentionally */
11291 }
11292 
11293 /** Deinitializes all GL objects that may have been created during test execution */
deinit()11294 void NegativeTest5::deinit()
11295 {
11296 	deinitIteration();
11297 }
11298 
11299 /** Deinitializes all GL objects that may have been created during a single test
11300  *  iteration.
11301  ***/
deinitIteration()11302 void NegativeTest5::deinitIteration()
11303 {
11304 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11305 
11306 	if (m_fs_id != 0)
11307 	{
11308 		gl.deleteShader(m_fs_id);
11309 
11310 		m_fs_id = 0;
11311 	}
11312 
11313 	if (m_gs_id != 0)
11314 	{
11315 		gl.deleteShader(m_gs_id);
11316 
11317 		m_gs_id = 0;
11318 	}
11319 
11320 	if (m_po_id != 0)
11321 	{
11322 		gl.deleteProgram(m_po_id);
11323 
11324 		m_po_id = 0;
11325 	}
11326 
11327 	if (m_tc_id != 0)
11328 	{
11329 		gl.deleteShader(m_tc_id);
11330 
11331 		m_tc_id = 0;
11332 	}
11333 
11334 	if (m_te_id != 0)
11335 	{
11336 		gl.deleteShader(m_te_id);
11337 
11338 		m_te_id = 0;
11339 	}
11340 
11341 	if (m_vs_id != 0)
11342 	{
11343 		gl.deleteShader(m_vs_id);
11344 
11345 		m_vs_id = 0;
11346 	}
11347 }
11348 
11349 /** Executes a single test iteration.
11350  *
11351  *  If the iteration fails, m_has_test_passed will be set to false.
11352  *
11353  *  @param shader_stage Shader stage, for which a subroutine uniform should be
11354  *                      declared in the shader without a matching subroutine.
11355  **/
executeIteration(const Utils::_shader_stage & shader_stage)11356 void NegativeTest5::executeIteration(const Utils::_shader_stage& shader_stage)
11357 {
11358 	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
11359 	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
11360 	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
11361 	std::string te_body =
11362 		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
11363 	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
11364 
11365 	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
11366 							DE_NULL, /* xfb_varyings */
11367 							DE_NULL, /* n_xfb_varyings */
11368 							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
11369 	{
11370 		/* None of the test programs should ever build successfully */
11371 		m_testCtx.getLog() << tcu::TestLog::Message
11372 						   << "A program object, consisting of the following shaders, has linked"
11373 							  " correctly. One of the shaders defines a subroutine uniform but does "
11374 							  "not implement any function that matches subroutine type of the uniform."
11375 							  " This should have resulted in a compilation/link-time error.\n"
11376 							  "\n"
11377 							  "Vertex shader:\n"
11378 							  "\n"
11379 						   << vs_body << "\n"
11380 										 "Tessellation control shader:\n"
11381 										 "\n"
11382 						   << tc_body << "\n"
11383 										 "Tessellation evaluation shader:\n"
11384 										 "\n"
11385 						   << te_body << "\n"
11386 										 "Geometry shader:\n"
11387 										 "\n"
11388 						   << gs_body << "\n"
11389 										 "Fragment shader:\n"
11390 										 "\n"
11391 						   << fs_body << tcu::TestLog::EndMessage;
11392 
11393 		m_has_test_passed = false;
11394 	}
11395 }
11396 
11397 /** Retrieves fragment shader body.
11398  *
11399  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11400  *                                                        a subroutine uniform without
11401  *                                                        a matching subroutine, false otherwise.
11402  *
11403  *  @return Requested string.
11404  **/
getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const11405 std::string NegativeTest5::getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const
11406 {
11407 	std::stringstream result_sstream;
11408 
11409 	result_sstream << "#version 400\n"
11410 					  "\n"
11411 					  "#extension GL_ARB_shader_subroutine : require\n"
11412 					  "\n";
11413 
11414 	if (include_invalid_subroutine_uniform_declaration)
11415 	{
11416 		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
11417 						  "\n"
11418 						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
11419 	};
11420 
11421 	result_sstream << "\n"
11422 					  "out vec4 result;\n"
11423 					  "\n"
11424 					  "void main()\n"
11425 					  "{\n";
11426 
11427 	if (include_invalid_subroutine_uniform_declaration)
11428 	{
11429 		result_sstream << "    test_subroutineFS(result);\n";
11430 	}
11431 	else
11432 	{
11433 		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
11434 	}
11435 
11436 	result_sstream << "}\n";
11437 
11438 	return result_sstream.str();
11439 }
11440 
11441 /** Retrieves geometry shader body.
11442  *
11443  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11444  *                                                        a subroutine uniform without
11445  *                                                        a matching subroutine, false otherwise.
11446  *
11447  *  @return Requested string.
11448  **/
getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const11449 std::string NegativeTest5::getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const
11450 {
11451 	std::stringstream result_sstream;
11452 
11453 	result_sstream << "#version 400\n"
11454 					  "\n"
11455 					  "#extension GL_ARB_shader_subroutine : require\n"
11456 					  "\n"
11457 					  "layout (points)                   in;\n"
11458 					  "layout (points, max_vertices = 1) out;\n"
11459 					  "\n";
11460 
11461 	if (include_invalid_subroutine_uniform_declaration)
11462 	{
11463 		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
11464 						  "\n"
11465 						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
11466 	};
11467 
11468 	result_sstream << "\n"
11469 					  "void main()\n"
11470 					  "{\n";
11471 
11472 	if (include_invalid_subroutine_uniform_declaration)
11473 	{
11474 		result_sstream << "    test_subroutineGS(gl_Position);\n";
11475 	}
11476 	else
11477 	{
11478 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11479 	}
11480 
11481 	result_sstream << "EmitVertex();\n"
11482 					  "}\n";
11483 
11484 	return result_sstream.str();
11485 }
11486 
11487 /** Retrieves tessellation control shader body.
11488  *
11489  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11490  *                                                        a subroutine uniform without
11491  *                                                        a matching subroutine, false otherwise.
11492  *
11493  *  @return Requested string.
11494  **/
getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const11495 std::string NegativeTest5::getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const
11496 {
11497 	std::stringstream result_sstream;
11498 
11499 	result_sstream << "#version 400\n"
11500 					  "\n"
11501 					  "#extension GL_ARB_shader_subroutine : require\n"
11502 					  "\n"
11503 					  "layout (vertices = 4) out;\n"
11504 					  "\n";
11505 
11506 	if (include_invalid_subroutine_uniform_declaration)
11507 	{
11508 		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
11509 						  "\n"
11510 						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
11511 	};
11512 
11513 	result_sstream << "\n"
11514 					  "void main()\n"
11515 					  "{\n";
11516 
11517 	if (include_invalid_subroutine_uniform_declaration)
11518 	{
11519 		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
11520 	}
11521 	else
11522 	{
11523 		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
11524 	}
11525 
11526 	result_sstream << "}\n";
11527 
11528 	return result_sstream.str();
11529 }
11530 
11531 /** Retrieves tessellation evaluation body.
11532  *
11533  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11534  *                                                        a subroutine uniform without
11535  *                                                        a matching subroutine, false otherwise.
11536  *
11537  *  @return Requested string.
11538  **/
getTessellationEvaluationShaderBody(bool include_invalid_subroutine_uniform_declaration) const11539 std::string NegativeTest5::getTessellationEvaluationShaderBody(
11540 	bool include_invalid_subroutine_uniform_declaration) const
11541 {
11542 	std::stringstream result_sstream;
11543 
11544 	result_sstream << "#version 400\n"
11545 					  "\n"
11546 					  "#extension GL_ARB_shader_subroutine : require\n"
11547 					  "\n"
11548 					  "layout (quads) in;\n"
11549 					  "\n";
11550 
11551 	if (include_invalid_subroutine_uniform_declaration)
11552 	{
11553 		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
11554 						  "\n"
11555 						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
11556 	};
11557 
11558 	result_sstream << "\n"
11559 					  "void main()\n"
11560 					  "{\n";
11561 
11562 	if (include_invalid_subroutine_uniform_declaration)
11563 	{
11564 		result_sstream << "    test_subroutineTE(gl_Position);\n";
11565 	}
11566 	else
11567 	{
11568 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11569 	}
11570 
11571 	result_sstream << "}\n";
11572 
11573 	return result_sstream.str();
11574 }
11575 
11576 /** Retrieves vertex shader body.
11577  *
11578  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
11579  *                                                        a subroutine uniform without
11580  *                                                        a matching subroutine, false otherwise.
11581  *
11582  *  @return Requested string.
11583  **/
getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const11584 std::string NegativeTest5::getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const
11585 {
11586 	std::stringstream result_sstream;
11587 
11588 	result_sstream << "#version 400\n"
11589 					  "\n"
11590 					  "#extension GL_ARB_shader_subroutine : require\n"
11591 					  "\n";
11592 
11593 	if (include_invalid_subroutine_uniform_declaration)
11594 	{
11595 		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
11596 						  "\n"
11597 						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
11598 	};
11599 
11600 	result_sstream << "\n"
11601 					  "void main()\n"
11602 					  "{\n";
11603 
11604 	if (include_invalid_subroutine_uniform_declaration)
11605 	{
11606 		result_sstream << "    test_subroutineVS(gl_Position);\n";
11607 	}
11608 	else
11609 	{
11610 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11611 	}
11612 
11613 	result_sstream << "}\n";
11614 
11615 	return result_sstream.str();
11616 }
11617 
11618 /** Executes test iteration.
11619  *
11620  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11621  */
iterate()11622 tcu::TestNode::IterateResult NegativeTest5::iterate()
11623 {
11624 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11625 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11626 	{
11627 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11628 	}
11629 
11630 	/* Iterate over all shader stages. Iteration-specific shader stage defines a subroutine type &
11631 	 * a corresponding subroutine uniform, for which no compatible subroutines are available. All
11632 	 * other shader stages are defined correctly.
11633 	 */
11634 	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11635 		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11636 	{
11637 		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
11638 		deinitIteration();
11639 	} /* for (all shader stages) */
11640 
11641 	/* All done */
11642 	if (m_has_test_passed)
11643 	{
11644 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11645 	}
11646 	else
11647 	{
11648 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11649 	}
11650 
11651 	return STOP;
11652 }
11653 
11654 /** Constructor.
11655  *
11656  *  @param context Rendering context.
11657  *
11658  **/
NegativeTest6(deqp::Context & context)11659 NegativeTest6::NegativeTest6(deqp::Context& context)
11660 	: TestCase(context, "two_duplicate_functions_one_being_a_subroutine",
11661 			   "Verifies that a link- or compile-time error occurs if any shader in "
11662 			   "a program object includes two functions with the same name and one "
11663 			   "of which is associated with a subroutine type.")
11664 	, m_fs_id(0)
11665 	, m_gs_id(0)
11666 	, m_has_test_passed(true)
11667 	, m_po_id(0)
11668 	, m_tc_id(0)
11669 	, m_te_id(0)
11670 	, m_vs_id(0)
11671 {
11672 	/* Left blank intentionally */
11673 }
11674 
11675 /** Deinitializes all GL objects that may have been created during test execution */
deinit()11676 void NegativeTest6::deinit()
11677 {
11678 	deinitIteration();
11679 }
11680 
11681 /** Deinitializes all GL objects that may have been created during a single test
11682  *  iteration.
11683  ***/
deinitIteration()11684 void NegativeTest6::deinitIteration()
11685 {
11686 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11687 
11688 	if (m_fs_id != 0)
11689 	{
11690 		gl.deleteShader(m_fs_id);
11691 
11692 		m_fs_id = 0;
11693 	}
11694 
11695 	if (m_gs_id != 0)
11696 	{
11697 		gl.deleteShader(m_gs_id);
11698 
11699 		m_gs_id = 0;
11700 	}
11701 
11702 	if (m_po_id != 0)
11703 	{
11704 		gl.deleteProgram(m_po_id);
11705 
11706 		m_po_id = 0;
11707 	}
11708 
11709 	if (m_tc_id != 0)
11710 	{
11711 		gl.deleteShader(m_tc_id);
11712 
11713 		m_tc_id = 0;
11714 	}
11715 
11716 	if (m_te_id != 0)
11717 	{
11718 		gl.deleteShader(m_te_id);
11719 
11720 		m_te_id = 0;
11721 	}
11722 
11723 	if (m_vs_id != 0)
11724 	{
11725 		gl.deleteShader(m_vs_id);
11726 
11727 		m_vs_id = 0;
11728 	}
11729 }
11730 
11731 /** Executes a single test iteration.
11732  *
11733  *  If the iteration fails, m_has_test_passed will be set to false.
11734  *
11735  *  @param shader_stage Shader stage, for which two duplicate functions
11736  *                      (one additionally marked as subroutine) should
11737  *                      be defined.
11738  **/
executeIteration(const Utils::_shader_stage & shader_stage)11739 void NegativeTest6::executeIteration(const Utils::_shader_stage& shader_stage)
11740 {
11741 	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
11742 	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
11743 	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
11744 	std::string te_body =
11745 		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
11746 	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
11747 
11748 	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
11749 							DE_NULL, /* xfb_varyings */
11750 							DE_NULL, /* n_xfb_varyings */
11751 							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
11752 	{
11753 		/* None of the test programs should ever build successfully */
11754 		m_testCtx.getLog() << tcu::TestLog::Message
11755 						   << "A program object, consisting of the following shaders, has linked"
11756 							  " correctly. This is invalid, because one of the shaders defines two"
11757 							  " functions with the same name, with an exception that one of the"
11758 							  " functions is marked as a subroutine.\n"
11759 							  "\n"
11760 							  "Vertex shader:\n"
11761 							  "\n"
11762 						   << vs_body << "\n"
11763 										 "Tessellation control shader:\n"
11764 										 "\n"
11765 						   << tc_body << "\n"
11766 										 "Tessellation evaluation shader:\n"
11767 										 "\n"
11768 						   << te_body << "\n"
11769 										 "Geometry shader:\n"
11770 										 "\n"
11771 						   << gs_body << "\n"
11772 										 "Fragment shader:\n"
11773 										 "\n"
11774 						   << fs_body << tcu::TestLog::EndMessage;
11775 
11776 		m_has_test_passed = false;
11777 	}
11778 }
11779 
11780 /** Retrieves fragment shader body.
11781  *
11782  *  @param include_invalid_declaration true if the shader should include duplicate function
11783  *                                     declaration.
11784  *
11785  *  @return Requested string.
11786  **/
getFragmentShaderBody(bool include_invalid_declaration) const11787 std::string NegativeTest6::getFragmentShaderBody(bool include_invalid_declaration) const
11788 {
11789 	std::stringstream result_sstream;
11790 
11791 	result_sstream << "#version 400\n"
11792 					  "\n"
11793 					  "#extension GL_ARB_shader_subroutine : require\n"
11794 					  "\n";
11795 
11796 	if (include_invalid_declaration)
11797 	{
11798 		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
11799 						  "\n"
11800 						  "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test)\n"
11801 						  "{\n"
11802 						  "    test = vec4(1, 2, 3, 4);\n"
11803 						  "}\n"
11804 						  "\n"
11805 						  "void test_impl1(out vec4 test)\n"
11806 						  "{\n"
11807 						  "    test = vec4(2, 3, 4, 5);\n"
11808 						  "}\n"
11809 						  "\n"
11810 						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
11811 	};
11812 
11813 	result_sstream << "\n"
11814 					  "out vec4 result;\n"
11815 					  "\n"
11816 					  "void main()\n"
11817 					  "{\n";
11818 
11819 	if (include_invalid_declaration)
11820 	{
11821 		result_sstream << "    test_subroutineFS(result);\n";
11822 	}
11823 	else
11824 	{
11825 		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
11826 	}
11827 
11828 	result_sstream << "}\n";
11829 
11830 	return result_sstream.str();
11831 }
11832 
11833 /** Retrieves geometry shader body.
11834  *
11835  *  @param include_invalid_declaration true if the shader should include duplicate function
11836  *                                     declaration.
11837  *
11838  *  @return Requested string.
11839  **/
getGeometryShaderBody(bool include_invalid_declaration) const11840 std::string NegativeTest6::getGeometryShaderBody(bool include_invalid_declaration) const
11841 {
11842 	std::stringstream result_sstream;
11843 
11844 	result_sstream << "#version 400\n"
11845 					  "\n"
11846 					  "#extension GL_ARB_shader_subroutine : require\n"
11847 					  "\n"
11848 					  "layout (points)                   in;\n"
11849 					  "layout (points, max_vertices = 1) out;\n"
11850 					  "\n";
11851 
11852 	if (include_invalid_declaration)
11853 	{
11854 		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
11855 						  "\n"
11856 						  "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test)\n"
11857 						  "{\n"
11858 						  "    test = vec4(1, 2, 3, 4);\n"
11859 						  "}\n"
11860 						  "\n"
11861 						  "void test_impl1(out vec4 test)\n"
11862 						  "{\n"
11863 						  "    test = vec4(2, 3, 4, 5);\n"
11864 						  "}\n"
11865 						  "\n"
11866 						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
11867 	};
11868 
11869 	result_sstream << "\n"
11870 					  "void main()\n"
11871 					  "{\n";
11872 
11873 	if (include_invalid_declaration)
11874 	{
11875 		result_sstream << "    test_subroutineGS(gl_Position);\n";
11876 	}
11877 	else
11878 	{
11879 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11880 	}
11881 
11882 	result_sstream << "EmitVertex();\n"
11883 					  "}\n";
11884 
11885 	return result_sstream.str();
11886 }
11887 
11888 /** Retrieves tessellation control shader body.
11889  *
11890  *  @param include_invalid_declaration true if the shader should include duplicate function
11891  *                                     declaration.
11892  *
11893  *  @return Requested string.
11894  **/
getTessellationControlShaderBody(bool include_invalid_declaration) const11895 std::string NegativeTest6::getTessellationControlShaderBody(bool include_invalid_declaration) const
11896 {
11897 	std::stringstream result_sstream;
11898 
11899 	result_sstream << "#version 400\n"
11900 					  "\n"
11901 					  "#extension GL_ARB_shader_subroutine : require\n"
11902 					  "\n"
11903 					  "layout (vertices = 4) out;\n"
11904 					  "\n";
11905 
11906 	if (include_invalid_declaration)
11907 	{
11908 		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
11909 						  "\n"
11910 						  "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test)\n"
11911 						  "{\n"
11912 						  "    test = vec4(1, 2, 3, 4);\n"
11913 						  "}\n"
11914 						  "\n"
11915 						  "void test_impl1(out vec4 test)\n"
11916 						  "{\n"
11917 						  "    test = vec4(2, 3, 4, 5);\n"
11918 						  "}\n"
11919 						  "\n"
11920 						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
11921 	};
11922 
11923 	result_sstream << "\n"
11924 					  "void main()\n"
11925 					  "{\n";
11926 
11927 	if (include_invalid_declaration)
11928 	{
11929 		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
11930 	}
11931 	else
11932 	{
11933 		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
11934 	}
11935 
11936 	result_sstream << "}\n";
11937 
11938 	return result_sstream.str();
11939 }
11940 
11941 /** Retrieves tessellation evaluation body.
11942  *
11943  *  @param include_invalid_declaration true if the shader should include duplicate function
11944  *                                     declaration.
11945  *
11946  *  @return Requested string.
11947  **/
getTessellationEvaluationShaderBody(bool include_invalid_declaration) const11948 std::string NegativeTest6::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
11949 {
11950 	std::stringstream result_sstream;
11951 
11952 	result_sstream << "#version 400\n"
11953 					  "\n"
11954 					  "#extension GL_ARB_shader_subroutine : require\n"
11955 					  "\n"
11956 					  "layout (quads) in;\n"
11957 					  "\n";
11958 
11959 	if (include_invalid_declaration)
11960 	{
11961 		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
11962 						  "\n"
11963 						  "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test)\n"
11964 						  "{\n"
11965 						  "    test = vec4(1, 2, 3, 4);\n"
11966 						  "}\n"
11967 						  "\n"
11968 						  "void test_impl1(out vec4 test)\n"
11969 						  "{\n"
11970 						  "    test = vec4(2, 3, 4, 5);\n"
11971 						  "}\n"
11972 						  "\n"
11973 						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
11974 	};
11975 
11976 	result_sstream << "\n"
11977 					  "void main()\n"
11978 					  "{\n";
11979 
11980 	if (include_invalid_declaration)
11981 	{
11982 		result_sstream << "    test_subroutineTE(gl_Position);\n";
11983 	}
11984 	else
11985 	{
11986 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
11987 	}
11988 
11989 	result_sstream << "}\n";
11990 
11991 	return result_sstream.str();
11992 }
11993 
11994 /** Retrieves vertex shader body.
11995  *
11996  *  @param include_invalid_declaration true if the shader should include duplicate function
11997  *                                     declaration.
11998  *
11999  *  @return Requested string.
12000  **/
getVertexShaderBody(bool include_invalid_declaration) const12001 std::string NegativeTest6::getVertexShaderBody(bool include_invalid_declaration) const
12002 {
12003 	std::stringstream result_sstream;
12004 
12005 	result_sstream << "#version 400\n"
12006 					  "\n"
12007 					  "#extension GL_ARB_shader_subroutine : require\n"
12008 					  "\n";
12009 
12010 	if (include_invalid_declaration)
12011 	{
12012 		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12013 						  "\n"
12014 						  "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test)\n"
12015 						  "{\n"
12016 						  "    test = vec4(1, 2, 3, 4);\n"
12017 						  "}\n"
12018 						  "\n"
12019 						  "void test_impl1(out vec4 test)\n"
12020 						  "{\n"
12021 						  "    test = vec4(2, 3, 4, 5);\n"
12022 						  "}\n"
12023 						  "\n"
12024 						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12025 	};
12026 
12027 	result_sstream << "\n"
12028 					  "void main()\n"
12029 					  "{\n";
12030 
12031 	if (include_invalid_declaration)
12032 	{
12033 		result_sstream << "    test_subroutineVS(gl_Position);\n";
12034 	}
12035 	else
12036 	{
12037 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12038 	}
12039 
12040 	result_sstream << "}\n";
12041 
12042 	return result_sstream.str();
12043 }
12044 
12045 /** Executes test iteration.
12046  *
12047  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12048  */
iterate()12049 tcu::TestNode::IterateResult NegativeTest6::iterate()
12050 {
12051 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12052 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12053 	{
12054 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12055 	}
12056 
12057 	/* Iterate over all shader stages. In each iteration, we will inject invalid
12058 	 * duplicate function declarations to iteration-specific shader stage. All other
12059 	 * shader stages will be assigned valid bodies. Test should fail if the program
12060 	 * links successfully.
12061 	 */
12062 	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12063 		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12064 	{
12065 		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12066 		deinitIteration();
12067 	} /* for (all shader stages) */
12068 
12069 	/* All done */
12070 	if (m_has_test_passed)
12071 	{
12072 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12073 	}
12074 	else
12075 	{
12076 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12077 	}
12078 
12079 	return STOP;
12080 }
12081 
12082 /** Constructor
12083  *
12084  * @param context CTS context
12085  **/
NegativeTest7(deqp::Context & context)12086 NegativeTest7::NegativeTest7(deqp::Context& context)
12087 	: TestCase(context, "recursion", "Verify that it is not possible to build program with recursing subroutines")
12088 	, m_program_id(0)
12089 	, m_vertex_shader_id(0)
12090 {
12091 	/* Nothing to be done here */
12092 }
12093 
12094 /** Deinitializes all GL objects that may have been created during test execution
12095  *
12096  **/
deinit()12097 void NegativeTest7::deinit()
12098 {
12099 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12100 
12101 	if (m_program_id != 0)
12102 	{
12103 		gl.deleteProgram(m_program_id);
12104 
12105 		m_program_id = 0;
12106 	}
12107 
12108 	if (m_vertex_shader_id != 0)
12109 	{
12110 		gl.deleteShader(m_vertex_shader_id);
12111 
12112 		m_vertex_shader_id = 0;
12113 	}
12114 }
12115 
12116 /** Executes test iteration.
12117  *
12118  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12119  **/
iterate()12120 tcu::TestNode::IterateResult NegativeTest7::iterate()
12121 {
12122 	static const GLchar* vertex_shader_with_static_recursion =
12123 		"#version 400\n"
12124 		"\n"
12125 		"#extension GL_ARB_shader_subroutine : require\n"
12126 		"\n"
12127 		"precision highp float;\n"
12128 		"\n"
12129 		"subroutine vec4 routine_type(in vec4 data, in uint control);\n"
12130 		"\n"
12131 		"subroutine (routine_type) vec4 power_routine(in vec4 data, in uint control)\n"
12132 		"{\n"
12133 		"    if (0 != control)\n"
12134 		"    {\n"
12135 		"        return data * power_routine(data, control - 1);\n"
12136 		"    }\n"
12137 		"    else\n"
12138 		"    {\n"
12139 		"        return vec4(1, 1, 1, 1);\n"
12140 		"    }\n"
12141 		"}\n"
12142 		"\n"
12143 		"subroutine (routine_type) vec4 select_routine(in vec4 data, in uint control)\n"
12144 		"{\n"
12145 		"    if (0 == control)\n"
12146 		"    {\n"
12147 		"        return data.rrrr;\n"
12148 		"    }\n"
12149 		"    else if (1 == control)\n"
12150 		"    {\n"
12151 		"        return data.gggg;\n"
12152 		"    }\n"
12153 		"    else if (2 == control)\n"
12154 		"    {\n"
12155 		"        return data.bbbb;\n"
12156 		"    }\n"
12157 		"    else\n"
12158 		"    {\n"
12159 		"        return data.aaaa;\n"
12160 		"    }\n"
12161 		"}\n"
12162 		"\n"
12163 		"subroutine uniform routine_type routine;\n"
12164 		"\n"
12165 		"uniform vec4 uni_value;\n"
12166 		"uniform uint uni_control;\n"
12167 		"\n"
12168 		"out vec4 out_result;\n"
12169 		"\n"
12170 		"void main()\n"
12171 		"{\n"
12172 		"    out_result = routine(uni_value, uni_control);\n"
12173 		"}\n"
12174 		"\n";
12175 
12176 	static const GLchar* vertex_shader_with_dynamic_recursion =
12177 		"#version 400\n"
12178 		"\n"
12179 		"#extension GL_ARB_shader_subroutine : require\n"
12180 		"\n"
12181 		"precision highp float;\n"
12182 		"\n"
12183 		"subroutine vec4 routine_type(in vec4 data);\n"
12184 		"\n"
12185 		"subroutine uniform routine_type routine;\n"
12186 		"\n"
12187 		"subroutine (routine_type) vec4 div_by_2(in vec4 data)\n"
12188 		"{\n"
12189 		"    return data / 2;\n"
12190 		"}\n"
12191 		"\n"
12192 		"subroutine (routine_type) vec4 div_routine_result_by_2(in vec4 data)\n"
12193 		"{\n"
12194 		"    return routine(data) / 2;\n"
12195 		"}\n"
12196 		"\n"
12197 		"uniform vec4 uni_value;\n"
12198 		"\n"
12199 		"out vec4 out_result;\n"
12200 		"\n"
12201 		"void main()\n"
12202 		"{\n"
12203 		"    out_result = routine(uni_value);\n"
12204 		"}\n"
12205 		"\n";
12206 
12207 	static const GLchar* vertex_shader_with_subroutine_function_recursion =
12208 		"#version 400\n"
12209 		"\n"
12210 		"#extension GL_ARB_shader_subroutine : require\n"
12211 		"\n"
12212 		"precision highp float;\n"
12213 		"\n"
12214 		"subroutine vec4 routine_type(in vec4 data);\n"
12215 		"\n"
12216 		"subroutine uniform routine_type routine;\n"
12217 		"\n"
12218 		"vec4 function(in vec4 data)\n"
12219 		"{\n"
12220 		"    return routine(data) + vec4(0.5, 0.5, 0.5, 0.5);\n"
12221 		"}\n"
12222 		"\n"
12223 		"subroutine (routine_type) vec4 routine_a(in vec4 data)\n"
12224 		"{\n"
12225 		"    return function(data) / 2;\n"
12226 		"}\n"
12227 		"\n"
12228 		"subroutine (routine_type) vec4 routine_b(in vec4 data)\n"
12229 		"{\n"
12230 		"    return routine_a(data) * 2;\n"
12231 		"}\n"
12232 		"\n"
12233 		"uniform vec4 uni_value;\n"
12234 		"\n"
12235 		"out vec4 out_result;\n"
12236 		"\n"
12237 		"void main()\n"
12238 		"{\n"
12239 		"    out_result = routine(uni_value);\n"
12240 		"}\n"
12241 		"\n";
12242 
12243 	bool result = true;
12244 
12245 	if (false == test(vertex_shader_with_subroutine_function_recursion, "routine_a"))
12246 	{
12247 		result = false;
12248 	}
12249 
12250 	if (false == test(vertex_shader_with_dynamic_recursion, "div_routine_result_by_2"))
12251 	{
12252 		result = false;
12253 	}
12254 
12255 	if (false == test(vertex_shader_with_static_recursion, "power_routine"))
12256 	{
12257 		result = false;
12258 	}
12259 
12260 	/* Set result */
12261 	if (true == result)
12262 	{
12263 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12264 	}
12265 	else
12266 	{
12267 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12268 	}
12269 
12270 	/* Done */
12271 	return tcu::TestNode::STOP;
12272 }
12273 
12274 /** Try to build program from vertex shader code.
12275  *
12276  * @param vertex_shader_code        Source code of vertex shader
12277  * @param name_of_recursive_routine Name of subroutine that should cause link failure due to recursion
12278  *
12279  * @return true build process failed, false otherwise
12280  **/
test(const GLchar * vertex_shader_code,const GLchar * name_of_recursive_routine)12281 bool NegativeTest7::test(const GLchar* vertex_shader_code, const GLchar* name_of_recursive_routine)
12282 {
12283 	const glw::Functions& gl		   = m_context.getRenderContext().getFunctions();
12284 	bool				  result	   = true;
12285 	static const GLchar*  varying_name = "out_result";
12286 
12287 	/* Try to build program */
12288 	if (true == Utils::buildProgram(gl, vertex_shader_code, "", "", "", "", &varying_name /* varying_names */,
12289 									1 /* n_varyings */, &m_vertex_shader_id, 0, 0, 0, 0, &m_program_id))
12290 	{
12291 		/* Success is considered an error */
12292 
12293 		Utils::program program(m_context);
12294 		GLuint		   index = 0;
12295 
12296 		program.build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0);
12297 
12298 		/* Verify that recursive subroutine is active */
12299 		try
12300 		{
12301 			index = program.getSubroutineIndex(name_of_recursive_routine, GL_VERTEX_SHADER);
12302 		}
12303 		catch (const std::exception& exc)
12304 		{
12305 			/* Something wrong with shader or compilation */
12306 			m_context.getTestContext().getLog()
12307 				<< tcu::TestLog::Message << "It is expected that subroutine: \n"
12308 				<< name_of_recursive_routine
12309 				<< " is considered active. This subroutine is potentially recursive and should cause link failure."
12310 				<< tcu::TestLog::EndMessage;
12311 
12312 			throw exc;
12313 		}
12314 
12315 		/* Subsoutine is active, however linking should fail */
12316 		m_context.getTestContext().getLog()
12317 			<< tcu::TestLog::Message << "Error. Program with potentially recursive subroutine, "
12318 			<< name_of_recursive_routine << ", which is active, index: " << index << ", has been built successfully.\n"
12319 			<< vertex_shader_code << tcu::TestLog::EndMessage;
12320 
12321 		result = false;
12322 	}
12323 
12324 	/* Delete program and shader */
12325 	deinit();
12326 
12327 	/* Done */
12328 	return result;
12329 }
12330 
12331 /** Constructor.
12332  *
12333  *  @param context Rendering context.
12334  *
12335  **/
NegativeTest8(deqp::Context & context)12336 NegativeTest8::NegativeTest8(deqp::Context& context)
12337 	: TestCase(context, "subroutine_wo_body", "Verifies that a compile- or link-time error occurs if a function "
12338 											  "declared as a subroutine does not include a body.")
12339 	, m_fs_id(0)
12340 	, m_gs_id(0)
12341 	, m_has_test_passed(true)
12342 	, m_po_id(0)
12343 	, m_tc_id(0)
12344 	, m_te_id(0)
12345 	, m_vs_id(0)
12346 {
12347 	/* Left blank intentionally */
12348 }
12349 
12350 /** Deinitializes all GL objects that may have been created during test execution */
deinit()12351 void NegativeTest8::deinit()
12352 {
12353 	deinitIteration();
12354 }
12355 
12356 /** Deinitializes all GL objects that may have been created during a single test
12357  *  iteration.
12358  ***/
deinitIteration()12359 void NegativeTest8::deinitIteration()
12360 {
12361 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12362 
12363 	if (m_fs_id != 0)
12364 	{
12365 		gl.deleteShader(m_fs_id);
12366 
12367 		m_fs_id = 0;
12368 	}
12369 
12370 	if (m_gs_id != 0)
12371 	{
12372 		gl.deleteShader(m_gs_id);
12373 
12374 		m_gs_id = 0;
12375 	}
12376 
12377 	if (m_po_id != 0)
12378 	{
12379 		gl.deleteProgram(m_po_id);
12380 
12381 		m_po_id = 0;
12382 	}
12383 
12384 	if (m_tc_id != 0)
12385 	{
12386 		gl.deleteShader(m_tc_id);
12387 
12388 		m_tc_id = 0;
12389 	}
12390 
12391 	if (m_te_id != 0)
12392 	{
12393 		gl.deleteShader(m_te_id);
12394 
12395 		m_te_id = 0;
12396 	}
12397 
12398 	if (m_vs_id != 0)
12399 	{
12400 		gl.deleteShader(m_vs_id);
12401 
12402 		m_vs_id = 0;
12403 	}
12404 }
12405 
12406 /** Executes a single test iteration.
12407  *
12408  *  If the iteration fails, m_has_test_passed will be set to false.
12409  *
12410  *  @param shader_stage Shader stage, for which two duplicate functions
12411  *                      (one additionally marked as subroutine) should
12412  *                      be defined.
12413  **/
executeIteration(const Utils::_shader_stage & shader_stage)12414 void NegativeTest8::executeIteration(const Utils::_shader_stage& shader_stage)
12415 {
12416 	std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
12417 	std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
12418 	std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
12419 	std::string te_body =
12420 		getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
12421 	std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
12422 
12423 	if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
12424 							DE_NULL, /* xfb_varyings */
12425 							DE_NULL, /* n_xfb_varyings */
12426 							&m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
12427 	{
12428 		/* None of the test programs should ever build successfully */
12429 		m_testCtx.getLog() << tcu::TestLog::Message
12430 						   << "A program object consisting of FS+GS+TC+TE+VS stages has linked successfully, "
12431 							  "even though one of the shaders only defines a subroutine that lacks any body."
12432 							  "\n"
12433 							  "Vertex shader:\n"
12434 							  "\n"
12435 						   << vs_body << "\n"
12436 										 "Tessellation control shader:\n"
12437 										 "\n"
12438 						   << tc_body << "\n"
12439 										 "Tessellation evaluation shader:\n"
12440 										 "\n"
12441 						   << te_body << "\n"
12442 										 "Geometry shader:\n"
12443 										 "\n"
12444 						   << gs_body << "\n"
12445 										 "Fragment shader:\n"
12446 										 "\n"
12447 						   << fs_body << tcu::TestLog::EndMessage;
12448 
12449 		m_has_test_passed = false;
12450 	}
12451 }
12452 
12453 /** Retrieves fragment shader body.
12454  *
12455  *  @param include_invalid_declaration true if a subroutine prototype should be included in
12456  *                                     the shader, false to skip it.
12457  *
12458  *  @return Requested string.
12459  **/
getFragmentShaderBody(bool include_invalid_declaration) const12460 std::string NegativeTest8::getFragmentShaderBody(bool include_invalid_declaration) const
12461 {
12462 	std::stringstream result_sstream;
12463 
12464 	result_sstream << "#version 400\n"
12465 					  "\n"
12466 					  "#extension GL_ARB_shader_subroutine : require\n"
12467 					  "\n";
12468 
12469 	if (include_invalid_declaration)
12470 	{
12471 		result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
12472 						  "\n"
12473 						  "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test);\n"
12474 						  "\n"
12475 						  "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
12476 	};
12477 
12478 	result_sstream << "\n"
12479 					  "out vec4 result;\n"
12480 					  "\n"
12481 					  "void main()\n"
12482 					  "{\n";
12483 
12484 	if (include_invalid_declaration)
12485 	{
12486 		result_sstream << "    test_subroutineFS(result);\n";
12487 	}
12488 	else
12489 	{
12490 		result_sstream << "    result = vec4(0, 1, 2, 3);\n";
12491 	}
12492 
12493 	result_sstream << "}\n";
12494 
12495 	return result_sstream.str();
12496 }
12497 
12498 /** Retrieves geometry shader body.
12499  *
12500  *  @param include_invalid_declaration true if a subroutine prototype should be included in
12501  *                                     the shader, false to skip it.
12502  *
12503  *  @return Requested string.
12504  **/
getGeometryShaderBody(bool include_invalid_declaration) const12505 std::string NegativeTest8::getGeometryShaderBody(bool include_invalid_declaration) const
12506 {
12507 	std::stringstream result_sstream;
12508 
12509 	result_sstream << "#version 400\n"
12510 					  "\n"
12511 					  "#extension GL_ARB_shader_subroutine : require\n"
12512 					  "\n"
12513 					  "layout (points)                   in;\n"
12514 					  "layout (points, max_vertices = 1) out;\n"
12515 					  "\n";
12516 
12517 	if (include_invalid_declaration)
12518 	{
12519 		result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
12520 						  "\n"
12521 						  "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test);\n"
12522 						  "\n"
12523 						  "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
12524 	};
12525 
12526 	result_sstream << "\n"
12527 					  "void main()\n"
12528 					  "{\n";
12529 
12530 	if (include_invalid_declaration)
12531 	{
12532 		result_sstream << "    test_subroutineGS(gl_Position);\n";
12533 	}
12534 	else
12535 	{
12536 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12537 	}
12538 
12539 	result_sstream << "EmitVertex();\n"
12540 					  "}\n";
12541 
12542 	return result_sstream.str();
12543 }
12544 
12545 /** Retrieves tessellation control shader body.
12546  *
12547  *  @param include_invalid_declaration true if a subroutine prototype should be included in
12548  *                                     the shader, false to skip it.
12549  *
12550  *  @return Requested string.
12551  **/
getTessellationControlShaderBody(bool include_invalid_declaration) const12552 std::string NegativeTest8::getTessellationControlShaderBody(bool include_invalid_declaration) const
12553 {
12554 	std::stringstream result_sstream;
12555 
12556 	result_sstream << "#version 400\n"
12557 					  "\n"
12558 					  "#extension GL_ARB_shader_subroutine : require\n"
12559 					  "\n"
12560 					  "layout (vertices = 4) out;\n"
12561 					  "\n";
12562 
12563 	if (include_invalid_declaration)
12564 	{
12565 		result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
12566 						  "\n"
12567 						  "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test);\n"
12568 						  "\n"
12569 						  "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
12570 	};
12571 
12572 	result_sstream << "\n"
12573 					  "void main()\n"
12574 					  "{\n";
12575 
12576 	if (include_invalid_declaration)
12577 	{
12578 		result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
12579 	}
12580 	else
12581 	{
12582 		result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
12583 	}
12584 
12585 	result_sstream << "}\n";
12586 
12587 	return result_sstream.str();
12588 }
12589 
12590 /** Retrieves tessellation evaluation body.
12591  *
12592  *  @param include_invalid_declaration true if a subroutine prototype should be included in
12593  *                                     the shader, false to skip it.
12594  *
12595  *  @return Requested string.
12596  **/
getTessellationEvaluationShaderBody(bool include_invalid_declaration) const12597 std::string NegativeTest8::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
12598 {
12599 	std::stringstream result_sstream;
12600 
12601 	result_sstream << "#version 400\n"
12602 					  "\n"
12603 					  "#extension GL_ARB_shader_subroutine : require\n"
12604 					  "\n"
12605 					  "layout (quads) in;\n"
12606 					  "\n";
12607 
12608 	if (include_invalid_declaration)
12609 	{
12610 		result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
12611 						  "\n"
12612 						  "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test);\n"
12613 						  "\n"
12614 						  "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
12615 	};
12616 
12617 	result_sstream << "\n"
12618 					  "void main()\n"
12619 					  "{\n";
12620 
12621 	if (include_invalid_declaration)
12622 	{
12623 		result_sstream << "    test_subroutineTE(gl_Position);\n";
12624 	}
12625 	else
12626 	{
12627 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12628 	}
12629 
12630 	result_sstream << "}\n";
12631 
12632 	return result_sstream.str();
12633 }
12634 
12635 /** Retrieves vertex shader body.
12636  *
12637  *  @param include_invalid_declaration true if a subroutine prototype should be included in
12638  *                                     the shader, false to skip it.
12639  *
12640  *  @return Requested string.
12641  **/
getVertexShaderBody(bool include_invalid_declaration) const12642 std::string NegativeTest8::getVertexShaderBody(bool include_invalid_declaration) const
12643 {
12644 	std::stringstream result_sstream;
12645 
12646 	result_sstream << "#version 400\n"
12647 					  "\n"
12648 					  "#extension GL_ARB_shader_subroutine : require\n"
12649 					  "\n";
12650 
12651 	if (include_invalid_declaration)
12652 	{
12653 		result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12654 						  "\n"
12655 						  "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test);\n"
12656 						  "\n"
12657 						  "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12658 	};
12659 
12660 	result_sstream << "\n"
12661 					  "void main()\n"
12662 					  "{\n";
12663 
12664 	if (include_invalid_declaration)
12665 	{
12666 		result_sstream << "    test_subroutineVS(gl_Position);\n";
12667 	}
12668 	else
12669 	{
12670 		result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12671 	}
12672 
12673 	result_sstream << "}\n";
12674 
12675 	return result_sstream.str();
12676 }
12677 
12678 /** Executes test iteration.
12679  *
12680  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12681  */
iterate()12682 tcu::TestNode::IterateResult NegativeTest8::iterate()
12683 {
12684 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12685 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12686 	{
12687 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12688 	}
12689 
12690 	/* Iterate over all shader stages. For each iteration, iteration-specific shader stage
12691 	 * will feature an invalid subroutine definition. Other shader stages will be assigned
12692 	 * valid bodies. The test fails if a program built of such shaders links successfully.
12693 	 */
12694 	for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12695 		 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12696 	{
12697 		executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12698 		deinitIteration();
12699 	} /* for (all shader stages) */
12700 
12701 	/* All done */
12702 	if (m_has_test_passed)
12703 	{
12704 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12705 	}
12706 	else
12707 	{
12708 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12709 	}
12710 
12711 	return STOP;
12712 }
12713 
12714 /** Constructor.
12715  *
12716  *  @param context Rendering context.
12717  **/
NegativeTest9(deqp::Context & context)12718 NegativeTest9::NegativeTest9(deqp::Context& context)
12719 	: TestCase(context, "subroutines_cannot_be_assigned_float_int_values_or_be_compared",
12720 			   "Make sure it is not possible to assign float/int to subroutine "
12721 			   "uniform and that subroutine uniform values cannot be compared.")
12722 	, m_has_test_passed(true)
12723 	, m_po_id(0)
12724 	, m_vs_id(0)
12725 {
12726 	/* Left blank intentionally */
12727 }
12728 
12729 /** Deinitializes any GL objects that may have been created during
12730  *  test execution.
12731  **/
deinit()12732 void NegativeTest9::deinit()
12733 {
12734 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12735 
12736 	if (m_po_id != 0)
12737 	{
12738 		gl.deleteProgram(m_po_id);
12739 
12740 		m_po_id = 0;
12741 	}
12742 
12743 	if (m_vs_id != 0)
12744 	{
12745 		gl.deleteShader(m_vs_id);
12746 
12747 		m_vs_id = 0;
12748 	}
12749 }
12750 
12751 /** Returns a literal corresponding to user-specified test case enum.
12752  *
12753  *  @param test_case As per description.
12754  *
12755  *  @return Requested string.
12756  **/
getTestCaseString(const _test_case & test_case)12757 std::string NegativeTest9::getTestCaseString(const _test_case& test_case)
12758 {
12759 	std::string result = "?";
12760 
12761 	switch (test_case)
12762 	{
12763 	case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
12764 		result = "TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
12765 		break;
12766 	case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
12767 		result = "TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
12768 		break;
12769 	case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
12770 		result = "TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON";
12771 		break;
12772 	default:
12773 		break;
12774 	}
12775 
12776 	return result;
12777 }
12778 
12779 /** Retrieves vertex shader body for user-specified test case.
12780  *
12781  *  @param test_case As per description.
12782  *
12783  *  @return Requested string.
12784  **/
getVertexShader(const _test_case & test_case)12785 std::string NegativeTest9::getVertexShader(const _test_case& test_case)
12786 {
12787 	std::stringstream result_sstream;
12788 
12789 	/* Form pre-amble */
12790 	result_sstream << "#version 400\n"
12791 					  "\n"
12792 					  "#extension GL_ARB_shader_subroutine : require\n"
12793 					  "\n"
12794 					  /* Define a subroutine */
12795 					  "subroutine void subroutineType(inout vec4 test);\n"
12796 					  "\n"
12797 					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
12798 					  "{\n"
12799 					  "    test += vec4(0, 1, 2, 3);\n"
12800 					  "}\n"
12801 					  "\n"
12802 					  "subroutine uniform subroutineType function;\n"
12803 					  "\n";
12804 
12805 	/* Include case-specific implementation */
12806 	switch (test_case)
12807 	{
12808 	case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
12809 	{
12810 		result_sstream << "void main()\n"
12811 						  "{\n"
12812 						  "    function = 1.0f;\n"
12813 						  "\n"
12814 						  "    function(gl_Position);\n"
12815 						  "}\n";
12816 
12817 		break;
12818 	}
12819 
12820 	case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
12821 	{
12822 		result_sstream << "void main()\n"
12823 						  "{\n"
12824 						  "    function = 1;\n"
12825 						  "\n"
12826 						  "    function(gl_Position);\n"
12827 						  "}\n";
12828 
12829 		break;
12830 	}
12831 
12832 	case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
12833 	{
12834 		result_sstream << "subroutine uniform subroutineType function2;\n"
12835 						  "\n"
12836 						  "void main()\n"
12837 						  "{\n"
12838 						  "    if (function == function2)\n"
12839 						  "    {\n"
12840 						  "        function(gl_Position);\n"
12841 						  "    }\n"
12842 						  "    else\n"
12843 						  "    {\n"
12844 						  "        function2(gl_Position);\n"
12845 						  "    }\n"
12846 						  "}\n";
12847 
12848 		break;
12849 	}
12850 
12851 	default:
12852 		break;
12853 	} /* switch (test_case) */
12854 
12855 	/* Done */
12856 	return result_sstream.str();
12857 }
12858 
12859 /** Executes test iteration.
12860  *
12861  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12862  */
iterate()12863 tcu::TestNode::IterateResult NegativeTest9::iterate()
12864 {
12865 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12866 
12867 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12868 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12869 	{
12870 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12871 	}
12872 
12873 	/* Iterate over all test cases */
12874 	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
12875 	{
12876 		/* Try to build a program object using invalid vertex shader, specific to the
12877 		 * iteration we're currently in */
12878 		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
12879 
12880 		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
12881 												  "",				 /* te_body */
12882 												  "",				 /* gs_body */
12883 												  "",				 /* fs_body */
12884 												  DE_NULL,			 /* xfb_varyings */
12885 												  0,				 /* n_xfb_varyings */
12886 												  &m_vs_id, DE_NULL, /* out_tc_id */
12887 												  DE_NULL,			 /* out_te_id */
12888 												  DE_NULL,			 /* out_gs_id */
12889 												  DE_NULL,			 /* out_fs_id */
12890 												  &m_po_id))
12891 		{
12892 			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
12893 							   << getTestCaseString(static_cast<_test_case>(test_case))
12894 							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
12895 
12896 			m_has_test_passed = false;
12897 		}
12898 
12899 		/* Delete any objects that may have been created */
12900 		deinit();
12901 	} /* for (all test cases) */
12902 
12903 	/** All done */
12904 	if (m_has_test_passed)
12905 	{
12906 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12907 	}
12908 	else
12909 	{
12910 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12911 	}
12912 
12913 	return STOP;
12914 }
12915 
12916 /** Constructor.
12917  *
12918  *  @param context Rendering context.
12919  **/
NegativeTest10(deqp::Context & context)12920 NegativeTest10::NegativeTest10(deqp::Context& context)
12921 	: TestCase(context, "function_overloading_forbidden_for_subroutines",
12922 			   "Check that an overloaded function cannot be declared with subroutine and "
12923 			   "a program will fail to compile or link if any shader or stage contains"
12924 			   " two or more  functions with the same name if the name is associated with"
12925 			   " a subroutine type.")
12926 	, m_has_test_passed(true)
12927 	, m_fs_id(0)
12928 	, m_gs_id(0)
12929 	, m_po_id(0)
12930 	, m_tc_id(0)
12931 	, m_te_id(0)
12932 	, m_vs_id(0)
12933 {
12934 	/* Left blank intentionally */
12935 }
12936 
12937 /** Deinitializes any GL objects that may have been created during
12938  *  test execution.
12939  **/
deinit()12940 void NegativeTest10::deinit()
12941 {
12942 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12943 
12944 	if (m_fs_id != 0)
12945 	{
12946 		gl.deleteShader(m_fs_id);
12947 
12948 		m_fs_id = 0;
12949 	}
12950 
12951 	if (m_gs_id != 0)
12952 	{
12953 		gl.deleteShader(m_gs_id);
12954 
12955 		m_gs_id = 0;
12956 	}
12957 
12958 	if (m_po_id != 0)
12959 	{
12960 		gl.deleteProgram(m_po_id);
12961 
12962 		m_po_id = 0;
12963 	}
12964 
12965 	if (m_tc_id != 0)
12966 	{
12967 		gl.deleteShader(m_tc_id);
12968 
12969 		m_tc_id = 0;
12970 	}
12971 
12972 	if (m_te_id != 0)
12973 	{
12974 		gl.deleteShader(m_te_id);
12975 
12976 		m_te_id = 0;
12977 	}
12978 
12979 	if (m_vs_id != 0)
12980 	{
12981 		gl.deleteShader(m_vs_id);
12982 
12983 		m_vs_id = 0;
12984 	}
12985 }
12986 
12987 /** Retrieves fragment shader that should be used for the purpose of the test.
12988  *  An overloaded version of a subroutine function is inserted if
12989  *  @param include_duplicate_function flag is set to true.
12990  *
12991  *  @param include_duplicate_function As per description.
12992  *
12993  *  @return Requested string.
12994  **/
getFragmentShader(bool include_duplicate_function)12995 std::string NegativeTest10::getFragmentShader(bool include_duplicate_function)
12996 {
12997 	std::stringstream result_sstream;
12998 
12999 	result_sstream << "#version 400\n"
13000 					  "\n"
13001 					  "#extension GL_ARB_shader_subroutine : require\n"
13002 					  "\n"
13003 					  "subroutine void subroutineType(inout vec4 test);\n"
13004 					  "\n"
13005 					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13006 					  "{\n"
13007 					  "    test = vec4(2, 3, 4, 5);\n"
13008 					  "}\n"
13009 					  "\n"
13010 					  "subroutine uniform subroutineType function;\n"
13011 					  "out vec4 result;\n"
13012 					  "\n";
13013 
13014 	if (include_duplicate_function)
13015 	{
13016 		result_sstream << "void test_function(inout vec4 test)\n"
13017 						  "{\n"
13018 						  "    test = vec4(3, 4, 5, 6);\n"
13019 						  "}\n"
13020 						  "\n";
13021 	}
13022 
13023 	result_sstream << "void main()\n"
13024 					  "{\n"
13025 					  "    test_function(result);\n"
13026 					  "}\n";
13027 
13028 	return result_sstream.str();
13029 }
13030 
13031 /** Retrieves geometry shader that should be used for the purpose of the test.
13032  *  An overloaded version of a subroutine function is inserted if
13033  *  @param include_duplicate_function flag is set to true.
13034  *
13035  *  @param include_duplicate_function As per description.
13036  *
13037  *  @return Requested string.
13038  **/
getGeometryShader(bool include_duplicate_function)13039 std::string NegativeTest10::getGeometryShader(bool include_duplicate_function)
13040 {
13041 	std::stringstream result_sstream;
13042 
13043 	result_sstream << "#version 400\n"
13044 					  "\n"
13045 					  "#extension GL_ARB_shader_subroutine : require\n"
13046 					  "\n"
13047 					  "layout (triangles)                        in;\n"
13048 					  "layout (triangle_strip, max_vertices = 4) out;\n"
13049 					  "\n"
13050 					  "subroutine void subroutineType(inout vec4 test);\n"
13051 					  "\n"
13052 					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13053 					  "{\n"
13054 					  "    test = vec4(2, 3, 4, 5);\n"
13055 					  "}\n"
13056 					  "\n"
13057 					  "subroutine uniform subroutineType function;\n"
13058 					  "\n";
13059 
13060 	if (include_duplicate_function)
13061 	{
13062 		result_sstream << "void test_function(inout vec4 test)\n"
13063 						  "{\n"
13064 						  "    test = vec4(3, 4, 5, 6);\n"
13065 						  "}\n"
13066 						  "\n";
13067 	}
13068 
13069 	result_sstream << "void main()\n"
13070 					  "{\n"
13071 					  "    function(gl_Position);\n"
13072 					  "    EmitVertex();\n"
13073 					  "    EndPrimitive();\n"
13074 					  "}\n";
13075 
13076 	return result_sstream.str();
13077 }
13078 
13079 /** Retrieves tess control shader that should be used for the purpose of the test.
13080  *  An overloaded version of a subroutine function is inserted if
13081  *  @param include_duplicate_function flag is set to true.
13082  *
13083  *  @param include_duplicate_function As per description.
13084  *
13085  *  @return Requested string.
13086  **/
getTessellationControlShader(bool include_duplicate_function)13087 std::string NegativeTest10::getTessellationControlShader(bool include_duplicate_function)
13088 {
13089 	std::stringstream result_sstream;
13090 
13091 	result_sstream << "#version 400\n"
13092 					  "\n"
13093 					  "#extension GL_ARB_shader_subroutine : require\n"
13094 					  "\n"
13095 					  "layout (vertices = 4) out;\n"
13096 					  "\n"
13097 					  "subroutine void subroutineType(inout vec4 test);\n"
13098 					  "\n"
13099 					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13100 					  "{\n"
13101 					  "    test = vec4(2, 3, 4, 5);\n"
13102 					  "}\n"
13103 					  "\n"
13104 					  "subroutine uniform subroutineType function;\n"
13105 					  "\n";
13106 
13107 	if (include_duplicate_function)
13108 	{
13109 		result_sstream << "void test_function(inout vec4 test)\n"
13110 						  "{\n"
13111 						  "    test = vec4(3, 4, 5, 6);\n"
13112 						  "}\n"
13113 						  "\n";
13114 	}
13115 
13116 	result_sstream << "void main()\n"
13117 					  "{\n"
13118 					  "    vec4 temp;\n"
13119 					  "\n"
13120 					  "    function(temp);\n"
13121 					  "\n"
13122 					  "    gl_out[gl_InvocationID].gl_Position = temp;\n"
13123 					  "    gl_TessLevelInner[0]                = temp.x;\n"
13124 					  "    gl_TessLevelInner[1]                = temp.y;\n"
13125 					  "    gl_TessLevelOuter[0]                = temp.z;\n"
13126 					  "    gl_TessLevelOuter[1]                = temp.w;\n"
13127 					  "    gl_TessLevelOuter[2]                = temp.x;\n"
13128 					  "    gl_TessLevelOuter[3]                = temp.y;\n"
13129 					  "}\n";
13130 
13131 	return result_sstream.str();
13132 }
13133 
13134 /** Retrieves tess evaluation shader that should be used for the purpose of the test.
13135  *  An overloaded version of a subroutine function is inserted if
13136  *  @param include_duplicate_function flag is set to true.
13137  *
13138  *  @param include_duplicate_function As per description.
13139  *
13140  *  @return Requested string.
13141  **/
getTessellationEvaluationShader(bool include_duplicate_function)13142 std::string NegativeTest10::getTessellationEvaluationShader(bool include_duplicate_function)
13143 {
13144 	std::stringstream result_sstream;
13145 
13146 	result_sstream << "#version 400\n"
13147 					  "\n"
13148 					  "#extension GL_ARB_shader_subroutine : require\n"
13149 					  "\n"
13150 					  "layout (quads) in;\n"
13151 					  "\n"
13152 					  "subroutine void subroutineType(inout vec4 test);\n"
13153 					  "\n"
13154 					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13155 					  "{\n"
13156 					  "    test = vec4(2, 3, 4, 5);\n"
13157 					  "}\n"
13158 					  "\n"
13159 					  "subroutine uniform subroutineType function;\n"
13160 					  "\n";
13161 
13162 	if (include_duplicate_function)
13163 	{
13164 		result_sstream << "void test_function(inout vec4 test)\n"
13165 						  "{\n"
13166 						  "    test = vec4(3, 4, 5, 6);\n"
13167 						  "}\n"
13168 						  "\n";
13169 	}
13170 
13171 	result_sstream << "void main()\n"
13172 					  "{\n"
13173 					  "    vec4 temp;\n"
13174 					  "\n"
13175 					  "    function(temp);\n"
13176 					  "\n"
13177 					  "    gl_Position = temp;\n"
13178 					  "}\n";
13179 
13180 	return result_sstream.str();
13181 }
13182 
13183 /** Retrieves vertex shader that should be used for the purpose of the test.
13184  *  An overloaded version of a subroutine function is inserted if
13185  *  @param include_duplicate_function flag is set to true.
13186  *
13187  *  @param include_duplicate_function As per description.
13188  *
13189  *  @return Requested string.
13190  **/
getVertexShader(bool include_duplicate_function)13191 std::string NegativeTest10::getVertexShader(bool include_duplicate_function)
13192 {
13193 	std::stringstream result_sstream;
13194 
13195 	result_sstream << "#version 400\n"
13196 					  "\n"
13197 					  "#extension GL_ARB_shader_subroutine : require\n"
13198 					  "\n"
13199 					  "subroutine void subroutineType(inout vec4 test);\n"
13200 					  "\n"
13201 					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13202 					  "{\n"
13203 					  "    test = vec4(2, 3, 4, 5);\n"
13204 					  "}\n"
13205 					  "\n"
13206 					  "subroutine uniform subroutineType function;\n"
13207 					  "\n";
13208 
13209 	if (include_duplicate_function)
13210 	{
13211 		result_sstream << "void test_function(inout vec4 test)\n"
13212 						  "{\n"
13213 						  "    test = vec4(3, 4, 5, 6);\n"
13214 						  "}\n"
13215 						  "\n";
13216 	}
13217 
13218 	result_sstream << "void main()\n"
13219 					  "{\n"
13220 					  "    function(gl_Position);\n"
13221 					  "}\n";
13222 
13223 	return result_sstream.str();
13224 }
13225 
13226 /** Fills m_test_cases field with test case descriptors */
initTestCases()13227 void NegativeTest10::initTestCases()
13228 {
13229 	/* For each test case, only one shader stage should define a function that
13230 	 * has already been defined as a subroutine. */
13231 	for (int offending_shader_stage_it = static_cast<int>(Utils::SHADER_STAGE_FIRST);
13232 		 offending_shader_stage_it != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++offending_shader_stage_it)
13233 	{
13234 		Utils::_shader_stage offending_shader_stage = static_cast<Utils::_shader_stage>(offending_shader_stage_it);
13235 		/* Form the test case descriptor */
13236 		std::stringstream name_sstream;
13237 		_test_case		  test_case;
13238 
13239 		name_sstream << "Broken shader stage:" << Utils::getShaderStageString(offending_shader_stage);
13240 
13241 		test_case.fs_body = getFragmentShader(offending_shader_stage == Utils::SHADER_STAGE_FRAGMENT);
13242 		test_case.gs_body = getGeometryShader(offending_shader_stage == Utils::SHADER_STAGE_GEOMETRY);
13243 		test_case.name	= name_sstream.str();
13244 		test_case.tc_body =
13245 			getTessellationControlShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
13246 		test_case.te_body =
13247 			getTessellationEvaluationShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
13248 		test_case.vs_body = getVertexShader(offending_shader_stage == Utils::SHADER_STAGE_VERTEX);
13249 
13250 		m_test_cases.push_back(test_case);
13251 	}
13252 }
13253 
13254 /** Executes test iteration.
13255  *
13256  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13257  */
iterate()13258 tcu::TestNode::IterateResult NegativeTest10::iterate()
13259 {
13260 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13261 
13262 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13263 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13264 	{
13265 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13266 	}
13267 
13268 	/* Form test cases */
13269 	initTestCases();
13270 
13271 	/* Iterate over all test cases */
13272 	for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
13273 		 ++test_case_iterator)
13274 	{
13275 		const _test_case& test_case = *test_case_iterator;
13276 
13277 		/* Try to build the program object */
13278 		if (ShaderSubroutine::Utils::buildProgram(gl, test_case.vs_body, test_case.tc_body, test_case.te_body,
13279 												  test_case.gs_body, test_case.fs_body, DE_NULL, /* xfb_varyings */
13280 												  0,											 /* n_xfb_varyings */
13281 												  &m_vs_id, (test_case.tc_body.length() > 0) ? &m_tc_id : DE_NULL,
13282 												  (test_case.te_body.length() > 0) ? &m_te_id : DE_NULL,
13283 												  (test_case.gs_body.length() > 0) ? &m_gs_id : DE_NULL,
13284 												  (test_case.fs_body.length() > 0) ? &m_fs_id : DE_NULL, &m_po_id))
13285 		{
13286 			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13287 							   << test_case.name << "] test case, even though it was invalid."
13288 							   << tcu::TestLog::EndMessage;
13289 
13290 			m_has_test_passed = false;
13291 		}
13292 
13293 		/* Delete any objects that may have been created */
13294 		deinit();
13295 	} /* for (all test cases) */
13296 
13297 	/** All done */
13298 	if (m_has_test_passed)
13299 	{
13300 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13301 	}
13302 	else
13303 	{
13304 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13305 	}
13306 
13307 	return STOP;
13308 }
13309 
13310 /** Constructor.
13311  *
13312  *  @param context Rendering context.
13313  **/
NegativeTest11(deqp::Context & context)13314 NegativeTest11::NegativeTest11(deqp::Context& context)
13315 	: TestCase(context, "subroutine_uniforms_used_for_sampling_atomic_image_functions",
13316 			   "Tries to use subroutine uniforms in invalid way in sampling, "
13317 			   "atomic and image functions. Verifies that compile- or link-time "
13318 			   "error occurs.")
13319 	, m_has_test_passed(true)
13320 	, m_po_id(0)
13321 	, m_vs_id(0)
13322 {
13323 	/* Left blank intentionally */
13324 }
13325 
13326 /** Deinitializes any GL objects that may have been created during
13327  *  test execution.
13328  **/
deinit()13329 void NegativeTest11::deinit()
13330 {
13331 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13332 
13333 	if (m_po_id != 0)
13334 	{
13335 		gl.deleteProgram(m_po_id);
13336 
13337 		m_po_id = 0;
13338 	}
13339 
13340 	if (m_vs_id != 0)
13341 	{
13342 		gl.deleteShader(m_vs_id);
13343 
13344 		m_vs_id = 0;
13345 	}
13346 }
13347 
13348 /** Returns a literal corresponding to user-specified test case enum.
13349  *
13350  *  @param test_case As per description.
13351  *
13352  *  @return Requested string.
13353  **/
getTestCaseString(const _test_case & test_case)13354 std::string NegativeTest11::getTestCaseString(const _test_case& test_case)
13355 {
13356 	std::string result = "?";
13357 
13358 	switch (test_case)
13359 	{
13360 	case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
13361 		result = "TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT";
13362 		break;
13363 	case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
13364 		result = "TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT";
13365 		break;
13366 	case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
13367 		result = "TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT";
13368 		break;
13369 	default:
13370 		break;
13371 	}
13372 
13373 	return result;
13374 }
13375 
13376 /** Retrieves vertex shader body for user-specified test case.
13377  *
13378  *  @param test_case As per description.
13379  *
13380  *  @return Requested string.
13381  **/
getVertexShader(const _test_case & test_case)13382 std::string NegativeTest11::getVertexShader(const _test_case& test_case)
13383 {
13384 	std::stringstream result_sstream;
13385 
13386 	/* Form pre-amble */
13387 	result_sstream << "#version 400\n"
13388 					  "\n"
13389 					  "#extension GL_ARB_shader_subroutine : require\n";
13390 
13391 	if (test_case == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT)
13392 	{
13393 		result_sstream << "#extension GL_ARB_shader_atomic_counters : require\n";
13394 	}
13395 
13396 	result_sstream << "\n"
13397 					  /* Define a subroutine */
13398 					  "subroutine void subroutineType(inout vec4 test);\n"
13399 					  "\n"
13400 					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13401 					  "{\n"
13402 					  "    test += vec4(0, 1, 2, 3);\n"
13403 					  "}\n"
13404 					  "\n"
13405 					  "subroutine uniform subroutineType function;\n"
13406 					  "\n"
13407 
13408 					  /* Define main() body */
13409 					  "void main()\n"
13410 					  "{\n";
13411 
13412 	/* Implement case-specific behavior */
13413 	switch (test_case)
13414 	{
13415 	case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
13416 	{
13417 		result_sstream << "if (atomicCounter(function) > 2)\n"
13418 						  "{\n"
13419 						  "    gl_Position = vec4(1);\n"
13420 						  "}\n";
13421 
13422 		break;
13423 	}
13424 
13425 	case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
13426 	{
13427 		result_sstream << "imageStore(function, vec2(0.0, 1.0), vec4(1.0) );\n";
13428 
13429 		break;
13430 	}
13431 
13432 	case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
13433 	{
13434 		result_sstream << "gl_Position = texture(function, vec2(1.0) );\n";
13435 
13436 		break;
13437 	}
13438 
13439 	default:
13440 		break;
13441 	} /* switch (test_case) */
13442 
13443 	/* Close main() body */
13444 	result_sstream << "}\n";
13445 
13446 	/* Done */
13447 	return result_sstream.str();
13448 }
13449 
13450 /** Executes test iteration.
13451  *
13452  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13453  */
iterate()13454 tcu::TestNode::IterateResult NegativeTest11::iterate()
13455 {
13456 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13457 
13458 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13459 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13460 	{
13461 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13462 	}
13463 
13464 	/* Iterate over all test cases */
13465 	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
13466 	{
13467 		if (static_cast<_test_case>(test_case) == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT &&
13468 			!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
13469 		{
13470 			/* This iteration requires atomic counter support that this GL implementation
13471 			 * is not capable of. Skip the iteration
13472 			 */
13473 			continue;
13474 		}
13475 
13476 		/* Try to build a program object using invalid vertex shader, specific to the
13477 		 * iteration we're currently in */
13478 		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
13479 
13480 		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
13481 												  "",				 /* te_body */
13482 												  "",				 /* gs_body */
13483 												  "",				 /* fs_body */
13484 												  DE_NULL,			 /* xfb_varyings */
13485 												  0,				 /* n_xfb_varyings */
13486 												  &m_vs_id, DE_NULL, /* out_tc_id */
13487 												  DE_NULL,			 /* out_te_id */
13488 												  DE_NULL,			 /* out_gs_id */
13489 												  DE_NULL,			 /* out_fs_id */
13490 												  &m_po_id))
13491 		{
13492 			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13493 							   << getTestCaseString(static_cast<_test_case>(test_case))
13494 							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
13495 
13496 			m_has_test_passed = false;
13497 		}
13498 
13499 		/* Delete any objects that may have been created */
13500 		deinit();
13501 	} /* for (all test cases) */
13502 
13503 	/** All done */
13504 	if (m_has_test_passed)
13505 	{
13506 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13507 	}
13508 	else
13509 	{
13510 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13511 	}
13512 
13513 	return STOP;
13514 }
13515 
13516 /** Constructor.
13517  *
13518  *  @param context Rendering context.
13519  **/
NegativeTest12(deqp::Context & context)13520 NegativeTest12::NegativeTest12(deqp::Context& context)
13521 	: TestCase(context, "subroutines_not_allowed_as_variables_constructors_and_argument_or_return_types",
13522 			   "Verifies that it is not allowed to use subroutine type for "
13523 			   "local/global variables, constructors or argument/return type.")
13524 	, m_has_test_passed(true)
13525 	, m_po_id(0)
13526 	, m_vs_id(0)
13527 {
13528 	/* Left blank intentionally */
13529 }
13530 
13531 /** Deinitializes any GL objects that may have been created during
13532  *  test execution.
13533  **/
deinit()13534 void NegativeTest12::deinit()
13535 {
13536 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13537 
13538 	if (m_po_id != 0)
13539 	{
13540 		gl.deleteProgram(m_po_id);
13541 
13542 		m_po_id = 0;
13543 	}
13544 
13545 	if (m_vs_id != 0)
13546 	{
13547 		gl.deleteShader(m_vs_id);
13548 
13549 		m_vs_id = 0;
13550 	}
13551 }
13552 
13553 /** Returns a literal corresponding to user-specified test case enum.
13554  *
13555  *  @param test_case As per description.
13556  *
13557  *  @return Requested string.
13558  **/
getTestCaseString(const _test_case & test_case)13559 std::string NegativeTest12::getTestCaseString(const _test_case& test_case)
13560 {
13561 	std::string result = "?";
13562 
13563 	switch (test_case)
13564 	{
13565 	case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
13566 		result = "TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE";
13567 		break;
13568 	case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
13569 		result = "TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE";
13570 		break;
13571 	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
13572 		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR";
13573 		break;
13574 	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
13575 		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT";
13576 		break;
13577 	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
13578 		result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE";
13579 		break;
13580 	default:
13581 		break;
13582 	}
13583 
13584 	return result;
13585 }
13586 
13587 /** Retrieves vertex shader body for user-specified test case.
13588  *
13589  *  @param test_case As per description.
13590  *
13591  *  @return Requested string.
13592  **/
getVertexShader(const _test_case & test_case)13593 std::string NegativeTest12::getVertexShader(const _test_case& test_case)
13594 {
13595 	std::stringstream result_sstream;
13596 
13597 	/* Form pre-amble */
13598 	result_sstream << "#version 400\n"
13599 					  "\n"
13600 					  "#extension GL_ARB_shader_subroutine : require\n"
13601 					  "\n"
13602 					  /* Define a subroutine */
13603 					  "subroutine void subroutineType(inout vec4 test);\n"
13604 					  "\n"
13605 					  "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13606 					  "{\n"
13607 					  "    test += vec4(0, 1, 2, 3);\n"
13608 					  "}\n"
13609 					  "\n"
13610 					  "subroutine uniform subroutineType function;\n"
13611 					  "\n";
13612 
13613 	/* Include case-specific implementation */
13614 	switch (test_case)
13615 	{
13616 	case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
13617 	{
13618 		result_sstream << "void main()\n"
13619 						  "{\n"
13620 						  "    subroutine subroutineType function2;\n"
13621 						  "    vec4                      result;\n"
13622 						  "\n"
13623 						  "    function2(result);\n"
13624 						  "    gl_Position = result;\n"
13625 						  "}\n";
13626 
13627 		break;
13628 	}
13629 
13630 	case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
13631 	{
13632 		result_sstream << "subroutine subroutineType function2;\n"
13633 						  "\n"
13634 						  "void main()\n"
13635 						  "{\n"
13636 						  "    vec4 result;\n"
13637 						  "\n"
13638 						  "    function2(result);\n"
13639 						  "    gl_Position = result;\n"
13640 						  "}\n";
13641 
13642 		break;
13643 	}
13644 
13645 	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
13646 	{
13647 		result_sstream << "void main()\n"
13648 						  "{\n"
13649 						  "    subroutineType(function);\n"
13650 						  "}\n";
13651 
13652 		break;
13653 	}
13654 
13655 	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
13656 	{
13657 		result_sstream << "vec4 test_function(subroutineType argument)\n"
13658 						  "{\n"
13659 						  "    vec4 result = vec4(1, 2, 3, 4);\n"
13660 						  "\n"
13661 						  "    argument(result);\n"
13662 						  "\n"
13663 						  "    return result;\n"
13664 						  "}\n"
13665 						  "\n"
13666 						  "void main()\n"
13667 						  "{\n"
13668 						  "    test_function(function);\n"
13669 						  "}\n";
13670 
13671 		break;
13672 	}
13673 
13674 	case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
13675 	{
13676 		result_sstream << "subroutineType test_function()\n"
13677 						  "{\n"
13678 						  "    return function;\n"
13679 						  "}\n"
13680 						  "\n"
13681 						  "void main()\n"
13682 						  "{\n"
13683 						  "    test_function()(gl_Position);\n"
13684 						  "}\n";
13685 
13686 		break;
13687 	}
13688 
13689 	default:
13690 		break;
13691 	} /* switch (test_case) */
13692 
13693 	/* Done */
13694 	return result_sstream.str();
13695 }
13696 
13697 /** Executes test iteration.
13698  *
13699  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13700  */
iterate()13701 tcu::TestNode::IterateResult NegativeTest12::iterate()
13702 {
13703 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13704 
13705 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13706 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13707 	{
13708 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13709 	}
13710 
13711 	/* Iterate over all test cases */
13712 	for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
13713 	{
13714 		/* Try to build a program object using invalid vertex shader, specific to the
13715 		 * iteration we're currently in */
13716 		std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
13717 
13718 		if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
13719 												  "",				 /* te_body */
13720 												  "",				 /* gs_body */
13721 												  "",				 /* fs_body */
13722 												  DE_NULL,			 /* xfb_varyings */
13723 												  0,				 /* n_xfb_varyings */
13724 												  &m_vs_id, DE_NULL, /* out_tc_id */
13725 												  DE_NULL,			 /* out_te_id */
13726 												  DE_NULL,			 /* out_gs_id */
13727 												  DE_NULL,			 /* out_fs_id */
13728 												  &m_po_id))
13729 		{
13730 			m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13731 							   << getTestCaseString(static_cast<_test_case>(test_case))
13732 							   << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
13733 
13734 			m_has_test_passed = false;
13735 		}
13736 
13737 		/* Delete any objects that may have been created */
13738 		deinit();
13739 	} /* for (all test cases) */
13740 
13741 	/** All done */
13742 	if (m_has_test_passed)
13743 	{
13744 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13745 	}
13746 	else
13747 	{
13748 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13749 	}
13750 
13751 	return STOP;
13752 }
13753 
13754 } /* ShaderSubroutine */
13755 
13756 /** Constructor.
13757  *
13758  *  @param context Rendering context.
13759  **/
ShaderSubroutineTests(deqp::Context & context)13760 ShaderSubroutineTests::ShaderSubroutineTests(deqp::Context& context)
13761 	: TestCaseGroup(context, "shader_subroutine", "Verifies \"shader_subroutine\" functionality")
13762 {
13763 	/* Left blank on purpose */
13764 }
13765 
13766 /** Initializes a texture_storage_multisample test group.
13767  *
13768  **/
init(void)13769 void ShaderSubroutineTests::init(void)
13770 {
13771 	addChild(new ShaderSubroutine::APITest1(m_context));
13772 	addChild(new ShaderSubroutine::APITest2(m_context));
13773 	addChild(new ShaderSubroutine::FunctionalTest1_2(m_context));
13774 	addChild(new ShaderSubroutine::FunctionalTest3_4(m_context));
13775 	addChild(new ShaderSubroutine::FunctionalTest5(m_context));
13776 	addChild(new ShaderSubroutine::FunctionalTest6(m_context));
13777 	addChild(new ShaderSubroutine::FunctionalTest7_8(m_context));
13778 	addChild(new ShaderSubroutine::FunctionalTest9(m_context));
13779 	addChild(new ShaderSubroutine::FunctionalTest10(m_context));
13780 	addChild(new ShaderSubroutine::FunctionalTest11(m_context));
13781 	addChild(new ShaderSubroutine::FunctionalTest12(m_context));
13782 	addChild(new ShaderSubroutine::FunctionalTest13(m_context));
13783 	addChild(new ShaderSubroutine::FunctionalTest14_15(m_context));
13784 	addChild(new ShaderSubroutine::FunctionalTest16(m_context));
13785 	addChild(new ShaderSubroutine::FunctionalTest17(m_context));
13786 	addChild(new ShaderSubroutine::FunctionalTest18_19(m_context));
13787 	addChild(new ShaderSubroutine::NegativeTest1(m_context));
13788 	addChild(new ShaderSubroutine::NegativeTest2(m_context));
13789 	addChild(new ShaderSubroutine::NegativeTest3(m_context));
13790 	addChild(new ShaderSubroutine::NegativeTest4(m_context));
13791 	addChild(new ShaderSubroutine::NegativeTest5(m_context));
13792 	addChild(new ShaderSubroutine::NegativeTest6(m_context));
13793 	addChild(new ShaderSubroutine::NegativeTest7(m_context));
13794 	addChild(new ShaderSubroutine::NegativeTest8(m_context));
13795 	addChild(new ShaderSubroutine::NegativeTest9(m_context));
13796 	addChild(new ShaderSubroutine::NegativeTest10(m_context));
13797 	addChild(new ShaderSubroutine::NegativeTest11(m_context));
13798 	addChild(new ShaderSubroutine::NegativeTest12(m_context));
13799 }
13800 
13801 } /* glcts namespace */
13802