Raise glsl version to 410 core for shaders with GL_ARB_shader_atomic_counters
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl4cShaderSubroutineTests.cpp
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  **/
48 Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context)
49 {
50 }
51
52 /** Destructor
53  *
54  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
330 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  **/
380 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  **/
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  **/
418 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  **/
442 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  **/
467 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  **/
492 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  **/
514 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  **/
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  **/
650 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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
750 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
751 {
752 }
753
754 /** Destructor
755  *
756  **/
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  **/
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  **/
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  *  */
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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
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  **/
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  **/
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  **/
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  */
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  **/
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  */
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  **/
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. */
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  */
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  **/
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  **/
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  **/
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  */
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 */
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  **/
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  **/
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. */
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  */
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  **/
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  **/
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  **/
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  **/
3043 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  **/
3077 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  **/
3119 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  **/
3154 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  **/
3188 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  **/
3215 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  **/
3248 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  **/
3279 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  **/
3309 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  **/
3342 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  **/
3440 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  **/
3517 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  **/
3568 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  **/
3620 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  **/
3682 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  **/
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  **/
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  **/
4056 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  **/
4133 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  **/
4221 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  **/
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  **/
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  **/
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  **/
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  **/
4591 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  **/
4624 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  **/
4687 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  **/
4835 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  **/
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. */
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  **/
4979 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. */
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  */
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  **/
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  **/
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  **/
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  **/
5321 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  **/
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  **/
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  **/
5736 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  **/
5769 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  **/
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  **/
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  **/
5919 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  **/
5948 bool FunctionalTest12::testAtomic()
5949 {
5950         static const GLchar* fragment_shader_code = "#version 410 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  **/
6102 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  **/
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  **/
6306 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  **/
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  **/
6508 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  **/
6552 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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  */
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  */
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  **/
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  **/
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  **/
7742 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  **/
7823 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  **/
7918 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  **/
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. */
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  **/
8068 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. */
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  **/
8406 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  */
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  */
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  **/
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  **/
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. */
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  **/
9005 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  **/
9043 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  **/
9113 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  **/
9160 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  **/
9202 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. */
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  */
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  **/
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  **/
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 */
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  &**/
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. */
9490 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. */
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  */
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  **/
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  **/
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  */
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  **/
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  **/
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.  */
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  */
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  **/
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 */
10327 void NegativeTest2::deinit()
10328 {
10329         deinitGLObjects();
10330 }
10331
10332 /** Deinitializes all GL objects that may have been created during test execution */
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  **/
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  **/
10430 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  **/
10470 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  **/
10513 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  **/
10570 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  **/
10609 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  **/
10648 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  */
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  **/
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 */
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  **/
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  **/
10810 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  **/
10840 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  **/
10873 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  **/
10904 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  **/
10935 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  */
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  **/
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  **/
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  **/
11033 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  */
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  **/
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 */
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  ***/
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  **/
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  **/
11405 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  **/
11449 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  **/
11495 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  **/
11539 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  **/
11584 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  */
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  **/
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 */
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  ***/
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  **/
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  **/
11787 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  **/
11840 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  **/
11895 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  **/
11948 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  **/
12001 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  */
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  **/
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  **/
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  **/
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  **/
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  **/
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 */
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  ***/
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  **/
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  **/
12460 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  **/
12505 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  **/
12552 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  **/
12597 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  **/
12642 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  */
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  **/
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  **/
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  **/
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  **/
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  */
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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  **/
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 */
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  */
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  **/
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  **/
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  **/
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  **/
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  */
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  **/
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  **/
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  **/
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  **/
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  */
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  **/
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  **/
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 */