Add RENDERBUFFER_VALID bit to R8, RG8 definition am: 1d7c8df82e
[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 400 core\n"
5951                                                                                                 "#extension GL_ARB_shader_atomic_counters : require\n"
5952                                                                                                 "#extension GL_ARB_shader_subroutine      : require\n"
5953                                                                                                 "\n"
5954                                                                                                 "precision highp float;\n"
5955                                                                                                 "\n"
5956                                                                                                 "layout(location = 0) out uint out_color;\n"
5957                                                                                                 "\n"
5958                                                                                                 "layout(binding = 0, offset = 8) uniform atomic_uint one;\n"
5959                                                                                                 "layout(binding = 0, offset = 4) uniform atomic_uint two;\n"
5960                                                                                                 "layout(binding = 0, offset = 0) uniform atomic_uint three;\n"
5961                                                                                                 "\n"
5962                                                                                                 "subroutine void atomic_routine(void)\n;"
5963                                                                                                 "\n"
5964                                                                                                 "subroutine(atomic_routine) void increment_two(void)\n"
5965                                                                                                 "{\n"
5966                                                                                                 "    out_color = atomicCounterIncrement(two);\n"
5967                                                                                                 "}\n"
5968                                                                                                 "\n"
5969                                                                                                 "subroutine(atomic_routine) void decrement_three(void)\n"
5970                                                                                                 "{\n"
5971                                                                                                 "    out_color = atomicCounterDecrement(three);\n"
5972                                                                                                 "}\n"
5973                                                                                                 "\n"
5974                                                                                                 "subroutine(atomic_routine) void read_one(void)\n"
5975                                                                                                 "{\n"
5976                                                                                                 "    out_color = atomicCounter(one);\n"
5977                                                                                                 "}\n"
5978                                                                                                 "\n"
5979                                                                                                 "subroutine uniform atomic_routine routine;\n"
5980                                                                                                 "\n"
5981                                                                                                 "void main()\n"
5982                                                                                                 "{\n"
5983                                                                                                 "    routine();\n"
5984                                                                                                 "}\n"
5985                                                                                                 "\n";
5986
5987         static const GLchar* geometry_shader_code = "#version 400 core\n"
5988                                                                                                 "#extension GL_ARB_shader_subroutine : require\n"
5989                                                                                                 "\n"
5990                                                                                                 "precision highp float;\n"
5991                                                                                                 "\n"
5992                                                                                                 "layout(points)                           in;\n"
5993                                                                                                 "layout(triangle_strip, max_vertices = 4) out;\n"
5994                                                                                                 "\n"
5995                                                                                                 "void main()\n"
5996                                                                                                 "{\n"
5997                                                                                                 "    gl_Position = vec4(-1, -1, 0, 1);\n"
5998                                                                                                 "    EmitVertex();\n"
5999                                                                                                 "    \n"
6000                                                                                                 "    gl_Position = vec4(-1,  1, 0, 1);\n"
6001                                                                                                 "    EmitVertex();\n"
6002                                                                                                 "    \n"
6003                                                                                                 "    gl_Position = vec4( 1, -1, 0, 1);\n"
6004                                                                                                 "    EmitVertex();\n"
6005                                                                                                 "    \n"
6006                                                                                                 "    gl_Position = vec4( 1,  1, 0, 1);\n"
6007                                                                                                 "    EmitVertex();\n"
6008                                                                                                 "    \n"
6009                                                                                                 "    EndPrimitive();\n"
6010                                                                                                 "}\n"
6011                                                                                                 "\n";
6012
6013         static const GLchar* vertex_shader_code = "#version 400 core\n"
6014                                                                                           "#extension GL_ARB_shader_subroutine : require\n"
6015                                                                                           "\n"
6016                                                                                           "precision highp float;\n"
6017                                                                                           "\n"
6018                                                                                           "void main()\n"
6019                                                                                           "{\n"
6020                                                                                           "}\n"
6021                                                                                           "\n";
6022
6023         static const GLchar* subroutine_names[] = { "increment_two", "decrement_three", "read_one" };
6024
6025         /* Test data */
6026         static const glw::GLuint atomic_buffer_data[] = { m_texture_width * m_texture_height,
6027                                                                                                           m_texture_width * m_texture_height,
6028                                                                                                           m_texture_width * m_texture_height };
6029
6030         static const glw::GLuint expected_incremented_two[] = { atomic_buffer_data[0], 2 * atomic_buffer_data[1],
6031                                                                                                                         atomic_buffer_data[2] };
6032
6033         static const glw::GLuint expected_decremented_three[] = { 0, expected_incremented_two[1],
6034                                                                                                                           expected_incremented_two[2] };
6035
6036         static const glw::GLuint expected_read_one[] = { expected_decremented_three[0], expected_decremented_three[1],
6037                                                                                                          expected_decremented_three[2] };
6038
6039         /* GL objects */
6040         Utils::buffer     atomic_buffer(m_context);
6041         Utils::texture   color_texture(m_context);
6042         Utils::framebuffer framebuffer(m_context);
6043         Utils::program   program(m_context);
6044         Utils::vertexArray vao(m_context);
6045
6046         /* Init GL objects */
6047         program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6048                                   vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6049
6050         program.use();
6051
6052         vao.generate();
6053         vao.bind();
6054
6055         color_texture.create(m_texture_width, m_texture_height, GL_R32UI);
6056
6057         atomic_buffer.generate();
6058         atomic_buffer.update(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomic_buffer_data), (GLvoid*)atomic_buffer_data,
6059                                                  GL_STATIC_DRAW);
6060         atomic_buffer.bindRange(GL_ATOMIC_COUNTER_BUFFER, 0 /* index */, 0 /* offset */, sizeof(atomic_buffer_data));
6061
6062         framebuffer.generate();
6063         framebuffer.bind();
6064         framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6065         framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6066         framebuffer.clear(GL_COLOR_BUFFER_BIT);
6067
6068         /* Subroutine indices */
6069         GLuint increment_two   = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6070         GLuint decrement_three = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6071         GLuint read_one            = program.getSubroutineIndex(subroutine_names[2], GL_FRAGMENT_SHADER);
6072
6073         /* Test */
6074         bool result = true;
6075
6076         if (false == testAtomicDraw(increment_two, expected_incremented_two))
6077         {
6078                 result = false;
6079         }
6080
6081         if (false == testAtomicDraw(decrement_three, expected_decremented_three))
6082         {
6083                 result = false;
6084         }
6085
6086         if (false == testAtomicDraw(read_one, expected_read_one))
6087         {
6088                 result = false;
6089         }
6090
6091         /* Done */
6092         return result;
6093 }
6094
6095 /** Execture draw call and verify results
6096  *
6097  * @param subroutine_index Index of subroutine that shall be used during draw call
6098  * @param expected_results Expected results
6099  *
6100  * @return true if results are as expected, false otherwise
6101  **/
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 /* Constants used by FunctionalTest20_21 */
9842 const GLuint FunctionalTest20_21::m_n_shared_contexts                              = 4;
9843 const GLuint FunctionalTest20_21::m_fragment_stage_index                           = 0;
9844 const GLuint FunctionalTest20_21::m_geometry_stage_index                           = 1;
9845 const GLuint FunctionalTest20_21::m_tesselation_control_stage_index     = 2;
9846 const GLuint FunctionalTest20_21::m_tesselation_evaluation_stage_index = 3;
9847 const GLuint FunctionalTest20_21::m_vertex_stage_index                             = 4;
9848
9849 /** Set subroutine indices, indices are taken from one of two sets according to provided <bit_field>
9850  *
9851  * @param bit_field          Selects source of of index for each stage
9852  * @param subroutine_indices Array of two indices sets
9853  **/
9854 void FunctionalTest20_21::subroutineUniformSet::set(GLuint bit_field, const subroutineUniformSet subroutine_indices[2])
9855 {
9856         GLuint vertex_stage                                     = ((bit_field & (0x01 << 0)) >> 0);
9857         GLuint tesselation_control_stage        = ((bit_field & (0x01 << 1)) >> 1);
9858         GLuint tesselation_evaluation_stage = ((bit_field & (0x01 << 2)) >> 2);
9859         GLuint geometry_stage                           = ((bit_field & (0x01 << 3)) >> 3);
9860         GLuint fragment_stage                           = ((bit_field & (0x01 << 4)) >> 4);
9861
9862         m_vertex_shader_stage = subroutine_indices[vertex_stage].m_vertex_shader_stage;
9863         m_tesselation_control_shader_stage =
9864                 subroutine_indices[tesselation_control_stage].m_tesselation_control_shader_stage;
9865         m_tesselation_evaluation_shader_stage =
9866                 subroutine_indices[tesselation_evaluation_stage].m_tesselation_evaluation_shader_stage;
9867         m_geometry_shader_stage = subroutine_indices[geometry_stage].m_geometry_shader_stage;
9868         m_fragment_shader_stage = subroutine_indices[fragment_stage].m_fragment_shader_stage;
9869 }
9870
9871 /** Negated comparison of two sets
9872  *
9873  * @param arg Instance that will be compared to this
9874  *
9875  * @return false when both objects are equal, true otherwise
9876  **/
9877 bool FunctionalTest20_21::subroutineUniformSet::operator!=(const subroutineUniformSet& arg) const
9878 {
9879         if ((arg.m_vertex_shader_stage != m_vertex_shader_stage) ||
9880                 (arg.m_tesselation_control_shader_stage != m_tesselation_control_shader_stage) ||
9881                 (arg.m_tesselation_evaluation_shader_stage != m_tesselation_evaluation_shader_stage) ||
9882                 (arg.m_geometry_shader_stage != m_geometry_shader_stage) ||
9883                 (arg.m_fragment_shader_stage != m_fragment_shader_stage))
9884         {
9885                 return true;
9886         }
9887
9888         return false;
9889 }
9890
9891 /** Constructor.
9892  *
9893  *  @param context Rendering context.
9894  *
9895  **/
9896 FunctionalTest20_21::FunctionalTest20_21(deqp::Context& context)
9897         : TestCase(context, "multiple_contexts",
9898                            "Verifies that shader uniforms are preserved when rendering context is switched.")
9899 {
9900         for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
9901         {
9902                 m_program_pipelines[i] = 0;
9903         }
9904
9905         for (GLuint i = 0; i < m_n_shared_contexts; ++i)
9906         {
9907                 m_shared_contexts[i] = 0;
9908         }
9909 }
9910
9911 /** Deinitializes all GL objects that may have been created during
9912  *  test execution.
9913  **/
9914 void FunctionalTest20_21::deinit()
9915 {
9916         /* GL entry points */
9917         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9918
9919         for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
9920         {
9921                 if (0 != m_program_pipelines[i])
9922                 {
9923                         gl.deleteProgramPipelines(1, &m_program_pipelines[i]);
9924                         m_program_pipelines[i] = 0;
9925                 }
9926         }
9927
9928         for (GLuint i = 0; i < m_n_shared_contexts; ++i)
9929         {
9930                 if (0 != m_shared_contexts[i])
9931                 {
9932                         delete m_shared_contexts[i];
9933                         m_shared_contexts[i] = 0;
9934                 }
9935         }
9936
9937         m_context.getRenderContext().makeCurrent();
9938 }
9939
9940 /** Executes test iteration.
9941  *
9942  *  @return Returns STOP
9943  */
9944 tcu::TestNode::IterateResult FunctionalTest20_21::iterate()
9945 {
9946         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9947         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9948         {
9949                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9950         }
9951
9952         /* Test cases, values stored here are used as bit fields */
9953         static const GLuint test_cases[][m_n_shared_contexts + 1] = {
9954                 { 0, 1, 2, 3, 4 },              { 1, 2, 3, 4, 0 },              { 2, 3, 4, 0, 1 },              { 3, 4, 0, 1, 2 },
9955                 { 4, 0, 1, 2, 3 },              { 27, 28, 29, 30, 31 }, { 28, 29, 30, 31, 27 }, { 29, 30, 31, 27, 28 },
9956                 { 30, 31, 27, 28, 29 }, { 31, 27, 28, 29, 30 },
9957         };
9958         static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
9959
9960         /* Prepare contexts */
9961         initSharedContexts();
9962
9963         /* Test result */
9964         bool result = true;
9965
9966         /* Program pointers */
9967         Utils::program* program_pointers[5];
9968
9969         /* Test monolithic program */
9970         {
9971                 /* Prepare program */
9972                 Utils::program program(m_context);
9973
9974                 program_pointers[m_fragment_stage_index] = &program;
9975
9976                 prepareProgram(program_pointers, false);
9977
9978                 /* Execute test */
9979                 if (false == testProgram(program_pointers, false, test_cases, n_test_cases))
9980                 {
9981                         m_context.getTestContext().getLog() << tcu::TestLog::Message
9982                                                                                                 << "Last error message was caused by monolithic program."
9983                                                                                                 << tcu::TestLog::EndMessage;
9984
9985                         result = false;
9986                 }
9987         }
9988
9989         /* Test separable programs */
9990         if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
9991         {
9992                 /* Prepare programs */
9993                 Utils::program vertex_program(m_context);
9994                 Utils::program tesselation_control_program(m_context);
9995                 Utils::program tesselation_evaluation_program(m_context);
9996                 Utils::program geometry_program(m_context);
9997                 Utils::program fragment_program(m_context);
9998
9999                 program_pointers[m_fragment_stage_index]                           = &fragment_program;
10000                 program_pointers[m_geometry_stage_index]                           = &geometry_program;
10001                 program_pointers[m_tesselation_control_stage_index]     = &tesselation_control_program;
10002                 program_pointers[m_tesselation_evaluation_stage_index] = &tesselation_evaluation_program;
10003                 program_pointers[m_vertex_stage_index]                             = &vertex_program;
10004
10005                 prepareProgram(program_pointers, true);
10006
10007                 /* Execute test */
10008                 if (false == testProgram(program_pointers, true, test_cases, n_test_cases))
10009                 {
10010                         m_context.getTestContext().getLog() << tcu::TestLog::Message
10011                                                                                                 << "Last error message was caused by separable program."
10012                                                                                                 << tcu::TestLog::EndMessage;
10013                         result = false;
10014                 }
10015         }
10016
10017         /* All done */
10018         if (true == result)
10019         {
10020                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10021         }
10022         else
10023         {
10024                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10025         }
10026
10027         return tcu::TestNode::STOP;
10028 }
10029
10030 /** Query state of subroutine uniforms of current program/pipeline
10031  *
10032  * @param set Storage for results
10033  **/
10034 void FunctionalTest20_21::captureCurrentSubroutineSet(subroutineUniformSet& set)
10035 {
10036         /* GL entry points */
10037         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10038
10039         /* Fragment */
10040         gl.getUniformSubroutineuiv(GL_FRAGMENT_SHADER, m_subroutine_uniform_locations.m_fragment_shader_stage,
10041                                                            &set.m_fragment_shader_stage);
10042         GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10043
10044         /* Geometry */
10045         gl.getUniformSubroutineuiv(GL_GEOMETRY_SHADER, m_subroutine_uniform_locations.m_geometry_shader_stage,
10046                                                            &set.m_geometry_shader_stage);
10047         GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10048
10049         /* Tess ctrl */
10050         gl.getUniformSubroutineuiv(GL_TESS_CONTROL_SHADER,
10051                                                            m_subroutine_uniform_locations.m_tesselation_control_shader_stage,
10052                                                            &set.m_tesselation_control_shader_stage);
10053         GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10054
10055         /* Tess eval */
10056         gl.getUniformSubroutineuiv(GL_TESS_EVALUATION_SHADER,
10057                                                            m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage,
10058                                                            &set.m_tesselation_evaluation_shader_stage);
10059         GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10060
10061         /* Vertex */
10062         gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_subroutine_uniform_locations.m_vertex_shader_stage,
10063                                                            &set.m_vertex_shader_stage);
10064         GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10065 }
10066
10067 /** Get shaders' source code
10068  *
10069  * @param out_vertex_shader_code                 Vertex source code
10070  * @param out_tesselation_control_shader_code    Tess ctrl source code
10071  * @param out_tesselation_evaluation_shader_code Tess eval source code
10072  * @param out_geometry_shader_code               Geometry source code
10073  * @param out_fragment_shader_code               Fragment source code
10074  **/
10075 void FunctionalTest20_21::getShaders(const glw::GLchar*& out_vertex_shader_code,
10076                                                                          const glw::GLchar*& out_tesselation_control_shader_code,
10077                                                                          const glw::GLchar*& out_tesselation_evaluation_shader_code,
10078                                                                          const glw::GLchar*& out_geometry_shader_code,
10079                                                                          const glw::GLchar*& out_fragment_shader_code)
10080 {
10081         static const GLchar* vertex_shader_code = "#version 400 core\n"
10082                                                                                           "#extension GL_ARB_shader_subroutine : require\n"
10083                                                                                           "\n"
10084                                                                                           "precision highp float;\n"
10085                                                                                           "\n"
10086                                                                                           "// Subroutine type\n"
10087                                                                                           "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10088                                                                                           "\n"
10089                                                                                           "// Subroutine definition\n"
10090                                                                                           "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10091                                                                                           "{\n"
10092                                                                                           "    return left + right;\n"
10093                                                                                           "}\n"
10094                                                                                           "\n"
10095                                                                                           "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10096                                                                                           "{\n"
10097                                                                                           "    return left * right;\n"
10098                                                                                           "}\n"
10099                                                                                           "\n"
10100                                                                                           "// Sub routine uniform\n"
10101                                                                                           "subroutine uniform routine_type routine;\n"
10102                                                                                           "\n"
10103                                                                                           "// Input data\n"
10104                                                                                           "uniform vec4 uni_vs_left;\n"
10105                                                                                           "uniform vec4 uni_vs_right;\n"
10106                                                                                           "\n"
10107                                                                                           "// Output\n"
10108                                                                                           "out vec4 vs_tcs_result;\n"
10109                                                                                           "\n"
10110                                                                                           "void main()\n"
10111                                                                                           "{\n"
10112                                                                                           "    vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n"
10113                                                                                           "}\n"
10114                                                                                           "\n";
10115
10116         static const GLchar* tesselation_control_shader_code =
10117                 "#version 400 core\n"
10118                 "#extension GL_ARB_shader_subroutine : require\n"
10119                 "\n"
10120                 "precision highp float;\n"
10121                 "\n"
10122                 "layout(vertices = 1) out;\n"
10123                 "\n"
10124                 "// Subroutine type\n"
10125                 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10126                 "\n"
10127                 "// Subroutine definition\n"
10128                 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10129                 "{\n"
10130                 "    return left + right;\n"
10131                 "}\n"
10132                 "\n"
10133                 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10134                 "{\n"
10135                 "    return left * right;\n"
10136                 "}\n"
10137                 "\n"
10138                 "// Sub routine uniform\n"
10139                 "subroutine uniform routine_type routine;\n"
10140                 "\n"
10141                 "// Input data\n"
10142                 "uniform vec4 uni_tcs_left;\n"
10143                 "uniform vec4 uni_tcs_right;\n"
10144                 "\n"
10145                 "in vec4 vs_tcs_result[];\n"
10146                 "\n"
10147                 "// Output\n"
10148                 "out vec4 tcs_tes_result[];\n"
10149                 "\n"
10150                 "void main()\n"
10151                 "{\n"
10152                 "    gl_TessLevelOuter[0] = 1.0;\n"
10153                 "    gl_TessLevelOuter[1] = 1.0;\n"
10154                 "    gl_TessLevelOuter[2] = 1.0;\n"
10155                 "    gl_TessLevelOuter[3] = 1.0;\n"
10156                 "    gl_TessLevelInner[0] = 1.0;\n"
10157                 "    gl_TessLevelInner[1] = 1.0;\n"
10158                 "\n"
10159                 "    tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n"
10160                 "}\n"
10161                 "\n";
10162
10163         static const GLchar* tesselation_evaluation_shader_code =
10164                 "#version 400 core\n"
10165                 "#extension GL_ARB_shader_subroutine : require\n"
10166                 "\n"
10167                 "precision highp float;\n"
10168                 "\n"
10169                 "layout(isolines, point_mode) in;\n"
10170                 "\n"
10171                 "// Subroutine type\n"
10172                 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10173                 "\n"
10174                 "// Subroutine definition\n"
10175                 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10176                 "{\n"
10177                 "    return left + right;\n"
10178                 "}\n"
10179                 "\n"
10180                 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10181                 "{\n"
10182                 "    return left * right;\n"
10183                 "}\n"
10184                 "\n"
10185                 "// Sub routine uniform\n"
10186                 "subroutine uniform routine_type routine;\n"
10187                 "\n"
10188                 "// Input data\n"
10189                 "uniform vec4 uni_tes_left;\n"
10190                 "uniform vec4 uni_tes_right;\n"
10191                 "\n"
10192                 "in vec4 tcs_tes_result[];\n"
10193                 "\n"
10194                 "// Output\n"
10195                 "out vec4 tes_gs_result;\n"
10196                 "\n"
10197                 "void main()\n"
10198                 "{\n"
10199                 "    tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n"
10200                 "}\n"
10201                 "\n";
10202
10203         static const GLchar* geometry_shader_code =
10204                 "#version 400 core\n"
10205                 "#extension GL_ARB_shader_subroutine : require\n"
10206                 "\n"
10207                 "precision highp float;\n"
10208                 "\n"
10209                 "layout(points)                   in;\n"
10210                 "layout(points, max_vertices = 1) out;\n"
10211                 "\n"
10212                 "// Subroutine type\n"
10213                 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10214                 "\n"
10215                 "// Subroutine definition\n"
10216                 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10217                 "{\n"
10218                 "    return left + right;\n"
10219                 "}\n"
10220                 "\n"
10221                 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10222                 "{\n"
10223                 "    return left * right;\n"
10224                 "}\n"
10225                 "\n"
10226                 "// Sub routine uniform\n"
10227                 "subroutine uniform routine_type routine;\n"
10228                 "\n"
10229                 "// Input data\n"
10230                 "uniform vec4 uni_gs_left;\n"
10231                 "uniform vec4 uni_gs_right;\n"
10232                 "\n"
10233                 "in vec4 tes_gs_result[];\n"
10234                 "\n"
10235                 "// Output\n"
10236                 "out vec4 gs_fs_result;\n"
10237                 "\n"
10238                 "void main()\n"
10239                 "{\n"
10240                 "    gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n"
10241                 "}\n"
10242                 "\n";
10243
10244         static const GLchar* fragmenty_shader_code =
10245                 "#version 400 core\n"
10246                 "#extension GL_ARB_shader_subroutine : require\n"
10247                 "\n"
10248                 "precision highp float;\n"
10249                 "\n"
10250                 "// Subroutine type\n"
10251                 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10252                 "\n"
10253                 "// Subroutine definition\n"
10254                 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10255                 "{\n"
10256                 "    return left + right;\n"
10257                 "}\n"
10258                 "\n"
10259                 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10260                 "{\n"
10261                 "    return left * right;\n"
10262                 "}\n"
10263                 "\n"
10264                 "// Sub routine uniform\n"
10265                 "subroutine uniform routine_type routine;\n"
10266                 "\n"
10267                 "// Input data\n"
10268                 "uniform vec4 uni_fs_left;\n"
10269                 "uniform vec4 uni_fs_right;\n"
10270                 "\n"
10271                 "in vec4 gs_fs_result;\n"
10272                 "\n"
10273                 "// Output\n"
10274                 "out vec4 fs_out_result;\n"
10275                 "\n"
10276                 "void main()\n"
10277                 "{\n"
10278                 "    fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n"
10279                 "}\n"
10280                 "\n";
10281
10282         out_vertex_shader_code                             = vertex_shader_code;
10283         out_tesselation_control_shader_code     = tesselation_control_shader_code;
10284         out_tesselation_evaluation_shader_code = tesselation_evaluation_shader_code;
10285         out_geometry_shader_code                           = geometry_shader_code;
10286         out_fragment_shader_code                           = fragmenty_shader_code;
10287 }
10288
10289 /** Create <m_n_shared_contexts> shared contexts
10290  *
10291  **/
10292 void FunctionalTest20_21::initSharedContexts()
10293 {
10294         for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10295         {
10296                 m_shared_contexts[i] = m_context.createSharedContext();
10297         }
10298 }
10299
10300 /** Prepare program(s)
10301  *
10302  * @param programs     An array of 5 programs' pointers. If monolithic program is prepared that only index m_fragment_stage_index should be initialized, otherwise all 5
10303  * @param is_separable Select if monolithic or separable programs should be prepared
10304  **/
10305 void FunctionalTest20_21::prepareProgram(Utils::program** programs, bool is_separable)
10306 {
10307         /* Get shader sources */
10308         const GLchar* vertex_shader_code;
10309         const GLchar* tesselation_control_shader_code;
10310         const GLchar* tesselation_evaluation_shader_code;
10311         const GLchar* geometry_shader_code;
10312         const GLchar* fragmenty_shader_code;
10313
10314         getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
10315                            geometry_shader_code, fragmenty_shader_code);
10316
10317         /* Subroutines and uniform names */
10318         static const GLchar* subroutine_names[] = { "add", "multiply" };
10319         static const GLuint  n_subroutines              = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
10320
10321         static const GLchar* subroutine_uniform_name = "routine";
10322
10323         /* Build program */
10324         if (false == is_separable)
10325         {
10326                 programs[0]->build(0 /* compute shader source */, fragmenty_shader_code, geometry_shader_code,
10327                                                    tesselation_control_shader_code, tesselation_evaluation_shader_code, vertex_shader_code,
10328                                                    0 /* varying_names */, 0 /* n_varying_names */);
10329
10330                 programs[m_geometry_stage_index]                           = programs[m_fragment_stage_index];
10331                 programs[m_tesselation_control_stage_index]     = programs[m_fragment_stage_index];
10332                 programs[m_tesselation_evaluation_stage_index] = programs[m_fragment_stage_index];
10333                 programs[m_vertex_stage_index]                             = programs[m_fragment_stage_index];
10334         }
10335         else
10336         {
10337                 programs[m_fragment_stage_index]->build(0, fragmenty_shader_code, 0, 0, 0, 0, 0, 0, true);
10338                 programs[m_geometry_stage_index]->build(0, 0, geometry_shader_code, 0, 0, 0, 0, 0, true);
10339                 programs[m_tesselation_control_stage_index]->build(0, 0, 0, tesselation_control_shader_code, 0, 0, 0, 0, true);
10340                 programs[m_tesselation_evaluation_stage_index]->build(0, 0, 0, 0, tesselation_evaluation_shader_code, 0, 0, 0,
10341                                                                                                                           true);
10342                 programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true);
10343         }
10344
10345         /* Get subroutine indices */
10346         for (GLuint i = 0; i < n_subroutines; ++i)
10347         {
10348                 m_subroutine_indices[i].m_fragment_shader_stage =
10349                         programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER);
10350
10351                 m_subroutine_indices[i].m_geometry_shader_stage =
10352                         programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER);
10353
10354                 m_subroutine_indices[i].m_tesselation_control_shader_stage =
10355                         programs[m_tesselation_control_stage_index]->getSubroutineIndex(subroutine_names[i],
10356                                                                                                                                                         GL_TESS_CONTROL_SHADER);
10357
10358                 m_subroutine_indices[i].m_tesselation_evaluation_shader_stage =
10359                         programs[m_tesselation_evaluation_stage_index]->getSubroutineIndex(subroutine_names[i],
10360                                                                                                                                                            GL_TESS_EVALUATION_SHADER);
10361
10362                 m_subroutine_indices[i].m_vertex_shader_stage =
10363                         programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER);
10364         }
10365
10366         /* Get subroutine uniform locations */
10367         m_subroutine_uniform_locations.m_fragment_shader_stage =
10368                 programs[m_fragment_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_FRAGMENT_SHADER);
10369
10370         m_subroutine_uniform_locations.m_geometry_shader_stage =
10371                 programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER);
10372
10373         m_subroutine_uniform_locations.m_tesselation_control_shader_stage =
10374                 programs[m_tesselation_control_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
10375                                                                                                                                                                   GL_TESS_CONTROL_SHADER);
10376
10377         m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage =
10378                 programs[m_tesselation_evaluation_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
10379                                                                                                                                                                          GL_TESS_EVALUATION_SHADER);
10380
10381         m_subroutine_uniform_locations.m_vertex_shader_stage =
10382                 programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER);
10383 }
10384
10385 /** Generate program pipeline for current context and attach separable programs
10386  *
10387  * @param out_pipeline_id Id of generated pipeline
10388  * @param programs        Collection of separable programs
10389  **/
10390 void FunctionalTest20_21::prepareProgramPipeline(glw::GLuint& out_pipeline_id, Utils::program** programs)
10391 {
10392         /* GL entry points */
10393         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10394
10395         /* Generate */
10396         gl.genProgramPipelines(1, &out_pipeline_id);
10397         GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
10398
10399         /* Bind */
10400         gl.bindProgramPipeline(out_pipeline_id);
10401         GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
10402
10403         /* Set up programs */
10404         gl.useProgramStages(out_pipeline_id, GL_FRAGMENT_SHADER_BIT, programs[m_fragment_stage_index]->m_program_object_id);
10405         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10406
10407         gl.useProgramStages(out_pipeline_id, GL_GEOMETRY_SHADER_BIT, programs[m_geometry_stage_index]->m_program_object_id);
10408         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10409
10410         gl.useProgramStages(out_pipeline_id, GL_TESS_CONTROL_SHADER_BIT,
10411                                                 programs[m_tesselation_control_stage_index]->m_program_object_id);
10412         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10413
10414         gl.useProgramStages(out_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT,
10415                                                 programs[m_tesselation_evaluation_stage_index]->m_program_object_id);
10416         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10417
10418         gl.useProgramStages(out_pipeline_id, GL_VERTEX_SHADER_BIT, programs[m_vertex_stage_index]->m_program_object_id);
10419         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10420 }
10421
10422 /** Test specific case
10423  *
10424  * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context
10425  *
10426  * @return True if test pass, false otherwise
10427  **/
10428 bool FunctionalTest20_21::testCase(const glw::GLuint bit_field[5])
10429 {
10430         /* Storage for subroutine indices */
10431         subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1];
10432         subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1];
10433
10434         /* Prepare subroutine_indices with bit fields */
10435         for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
10436         {
10437                 subroutine_indices[i].set(bit_field[i], m_subroutine_indices);
10438         };
10439
10440         /* Update subroutine uniforms, each context gets different set */
10441         for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10442         {
10443                 m_shared_contexts[i]->makeCurrent();
10444                 updateCurrentSubroutineSet(subroutine_indices[i]);
10445         }
10446
10447         m_context.getRenderContext().makeCurrent();
10448         updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]);
10449
10450         /* Capture subroutine uniforms */
10451         for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10452         {
10453                 m_shared_contexts[i]->makeCurrent();
10454                 captureCurrentSubroutineSet(captured_subroutine_indices[i]);
10455         }
10456
10457         m_context.getRenderContext().makeCurrent();
10458         captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]);
10459
10460         /* Verify that captured uniforms match expected values */
10461         for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
10462         {
10463                 if (subroutine_indices[i] != captured_subroutine_indices[i])
10464                 {
10465                         m_context.getTestContext().getLog()
10466                                 << tcu::TestLog::Message << "Error."
10467                                 << " Context: " << i << " VS, expected: " << subroutine_indices[i].m_vertex_shader_stage
10468                                 << " captured: " << captured_subroutine_indices[i].m_vertex_shader_stage
10469                                 << " TCS, expected: " << subroutine_indices[i].m_tesselation_control_shader_stage
10470                                 << " captured: " << captured_subroutine_indices[i].m_tesselation_control_shader_stage
10471                                 << " TES, expected: " << subroutine_indices[i].m_tesselation_evaluation_shader_stage
10472                                 << " captured: " << captured_subroutine_indices[i].m_tesselation_evaluation_shader_stage
10473                                 << " GS, expected: " << subroutine_indices[i].m_geometry_shader_stage
10474                                 << " captured: " << captured_subroutine_indices[i].m_geometry_shader_stage
10475                                 << " FS, expected: " << subroutine_indices[i].m_fragment_shader_stage
10476                                 << " captured: " << captured_subroutine_indices[i].m_fragment_shader_stage << tcu::TestLog::EndMessage;
10477
10478                         return false;
10479                 }
10480         }
10481
10482         return true;
10483 }
10484
10485 /** Test a program or pipeline
10486  *
10487  * @param programs     An array of 5 programs\ pointers, as in preparePrograms
10488  * @param is_separable Selects if monolithic or separable programs should be used
10489  * @param test_cases   Collection of test cases
10490  * @param n_test_cases Number of test cases
10491  *
10492  * @return True if all cases pass, false otherwise
10493  **/
10494 bool FunctionalTest20_21::testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
10495                                                                           glw::GLuint n_test_cases)
10496 {
10497         /* Set program/pipeline as current for all contexts */
10498         if (false == is_separable)
10499         {
10500                 programs[0]->use();
10501
10502                 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10503                 {
10504                         m_shared_contexts[i]->makeCurrent();
10505                         programs[0]->use();
10506                 }
10507         }
10508         else
10509         {
10510                 /* GL entry points */
10511                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10512
10513                 /* Make sure that program pipeline will be used */
10514                 gl.useProgram(0);
10515                 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
10516
10517                 prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs);
10518
10519                 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10520                 {
10521                         m_shared_contexts[i]->makeCurrent();
10522
10523                         /* Make sure that program pipeline will be used */
10524                         gl.useProgram(0);
10525                         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
10526
10527                         prepareProgramPipeline(m_program_pipelines[i], programs);
10528                 }
10529         }
10530
10531         /* Execute test */
10532         bool result = true;
10533         for (GLuint i = 0; i < n_test_cases; ++i)
10534         {
10535                 if (false == testCase(test_cases[i]))
10536                 {
10537                         result = false;
10538                         break;
10539                 }
10540         }
10541
10542         return result;
10543 }
10544
10545 /** Set up subroutine uniforms for current program or pipeline
10546  *
10547  * @param set Set of subroutine indices
10548  **/
10549 void FunctionalTest20_21::updateCurrentSubroutineSet(const subroutineUniformSet& set)
10550 {
10551         /* GL entry points */
10552         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10553
10554         /* Fragment */
10555         gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage);
10556         GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10557
10558         /* Geometry */
10559         gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage);
10560         GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10561
10562         /* Tess ctrl */
10563         gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage);
10564         GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10565
10566         /* Tess eval */
10567         gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage);
10568         GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10569
10570         /* Vertex */
10571         gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage);
10572         GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10573 }
10574
10575 /** Constructor.
10576  *
10577  *  @param context Rendering context.
10578  *
10579  **/
10580 NegativeTest1::NegativeTest1(deqp::Context& context)
10581         : TestCase(context, "subroutine_errors", "Verifies all GL_INVALID_OPERATION, GL_INVALID_VALUE, GL_INVALID ENUM "
10582                                                                                          "errors related to subroutine usage are properly generated.")
10583         , m_has_test_passed(true)
10584         , m_po_active_subroutine_uniform_locations(0)
10585         , m_po_active_subroutine_uniforms(0)
10586         , m_po_active_subroutines(0)
10587         , m_po_subroutine_uniform_function_index(-1)
10588         , m_po_subroutine_uniform_function2_index(-1)
10589         , m_po_subroutine_test1_index(GL_INVALID_INDEX)
10590         , m_po_subroutine_test2_index(GL_INVALID_INDEX)
10591         , m_po_subroutine_test3_index(GL_INVALID_INDEX)
10592         , m_po_not_linked_id(0)
10593         , m_po_id(0)
10594         , m_vs_id(0)
10595 {
10596         /* Left blank intentionally */
10597 }
10598
10599 /** Deinitializes all GL objects that may have been created during
10600  *  test execution.
10601  **/
10602 void NegativeTest1::deinit()
10603 {
10604         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10605
10606         if (m_po_id != 0)
10607         {
10608                 gl.deleteProgram(m_po_id);
10609
10610                 m_po_id = 0;
10611         }
10612
10613         if (m_po_not_linked_id != 0)
10614         {
10615                 gl.deleteProgram(m_po_not_linked_id);
10616
10617                 m_po_not_linked_id = 0;
10618         }
10619
10620         if (m_vs_id != 0)
10621         {
10622                 gl.deleteShader(m_vs_id);
10623
10624                 m_vs_id = 0;
10625         }
10626 }
10627
10628 /** Initializes all GL objects required to run the test.  */
10629 void NegativeTest1::initTest()
10630 {
10631         glw::GLint                        compile_status = GL_FALSE;
10632         const glw::Functions& gl                         = m_context.getRenderContext().getFunctions();
10633
10634         /* Create program objects */
10635         m_po_not_linked_id = gl.createProgram();
10636         m_po_id                    = gl.createProgram();
10637         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
10638
10639         /* Create vertex shader object */
10640         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10641         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
10642
10643         /* Set up vertex shader */
10644         const char* vs_body = "#version 400\n"
10645                                                   "\n"
10646                                                   "#extension GL_ARB_shader_subroutine : require\n"
10647                                                   "\n"
10648                                                   "subroutine void subroutineType (out ivec2 arg);\n"
10649                                                   "subroutine void subroutineType2(out ivec4 arg);\n"
10650                                                   "\n"
10651                                                   "subroutine(subroutineType) void test1(out ivec2 arg)\n"
10652                                                   "{\n"
10653                                                   "    arg = ivec2(1, 2);\n"
10654                                                   "}\n"
10655                                                   "subroutine(subroutineType) void test2(out ivec2 arg)\n"
10656                                                   "{\n"
10657                                                   "    arg = ivec2(3,4);\n"
10658                                                   "}\n"
10659                                                   "subroutine(subroutineType2) void test3(out ivec4 arg)\n"
10660                                                   "{\n"
10661                                                   "    arg = ivec4(1, 2, 3, 4);\n"
10662                                                   "}\n"
10663                                                   "\n"
10664                                                   "subroutine uniform subroutineType  function;\n"
10665                                                   "subroutine uniform subroutineType2 function2;\n"
10666                                                   "\n"
10667                                                   "void main()\n"
10668                                                   "{\n"
10669                                                   "    ivec2 test;\n"
10670                                                   "    ivec4 test2;\n"
10671                                                   "\n"
10672                                                   "    function(test);\n"
10673                                                   "\n"
10674                                                   "    if (test.x > 2)\n"
10675                                                   "    {\n"
10676                                                   "        gl_Position = vec4(1);\n"
10677                                                   "    }\n"
10678                                                   "    else\n"
10679                                                   "    {\n"
10680                                                   "        function2(test2);\n"
10681                                                   "\n"
10682                                                   "        gl_Position = vec4(float(test2.x) );\n"
10683                                                   "    }\n"
10684                                                   "}\n";
10685
10686         gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
10687         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
10688
10689         gl.compileShader(m_vs_id);
10690         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
10691
10692         gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
10693         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
10694
10695         if (compile_status == GL_FALSE)
10696         {
10697                 TCU_FAIL("Shader compilation failed");
10698         }
10699
10700         /* Set up & link the test program object */
10701         glw::GLint link_status = GL_FALSE;
10702
10703         gl.attachShader(m_po_id, m_vs_id);
10704         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
10705
10706         gl.linkProgram(m_po_id);
10707         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
10708
10709         gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
10710         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
10711
10712         if (link_status == GL_FALSE)
10713         {
10714                 TCU_FAIL("Program linking failed");
10715         }
10716
10717         /* Query test program object's properties */
10718         gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
10719                                                  &m_po_active_subroutine_uniform_locations);
10720         gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &m_po_active_subroutine_uniforms);
10721         gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &m_po_active_subroutines);
10722         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call(s) failed.");
10723
10724         if (m_po_active_subroutine_uniform_locations != 2)
10725         {
10726                 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS value returned");
10727         }
10728
10729         m_po_subroutine_test1_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test1");
10730         m_po_subroutine_test2_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test2");
10731         m_po_subroutine_test3_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test3");
10732         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
10733
10734         if (m_po_subroutine_test1_index == GL_INVALID_INDEX || m_po_subroutine_test2_index == GL_INVALID_INDEX ||
10735                 m_po_subroutine_test3_index == GL_INVALID_INDEX)
10736         {
10737                 TCU_FAIL("Invalid subroutine index returned");
10738         }
10739
10740         m_po_subroutine_uniform_function_index  = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function");
10741         m_po_subroutine_uniform_function2_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function2");
10742         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
10743
10744         if (m_po_subroutine_uniform_function_index == -1 || m_po_subroutine_uniform_function2_index == -1)
10745         {
10746                 TCU_FAIL("Invalid subroutine uniform index returned");
10747         }
10748 }
10749
10750 /** Executes test iteration.
10751  *
10752  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10753  */
10754 tcu::TestNode::IterateResult NegativeTest1::iterate()
10755 {
10756         glw::GLenum                       error_code = GL_NO_ERROR;
10757         const glw::Functions& gl                 = m_context.getRenderContext().getFunctions();
10758
10759         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10760         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10761         {
10762                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10763         }
10764
10765         /* Initialize GL objects required to run the test */
10766         initTest();
10767
10768         /* The error INVALID_OPERATION is generated by GetSubroutineUniformLocation
10769          * if the program object identified by <program> has not been successfully
10770          * linked.
10771          */
10772         gl.getSubroutineUniformLocation(m_po_not_linked_id, GL_FRAGMENT_SHADER, "subroutine_uniform_name");
10773
10774         error_code = gl.getError();
10775
10776         if (error_code != GL_INVALID_OPERATION)
10777         {
10778                 m_testCtx.getLog() << tcu::TestLog::Message
10779                                                    << "glGetSubroutineUniformLocation() does not generate GL_INVALID_OPERATION "
10780                                                           "error code when called for a non-linked program object."
10781                                                    << tcu::TestLog::EndMessage;
10782
10783                 m_has_test_passed = false;
10784         }
10785
10786         /* The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or
10787          * GetActiveSubroutineUniformName if <index> is greater than or equal to the
10788          * value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage.
10789          */
10790         glw::GLint temp_length = 0;
10791         glw::GLint temp_values = 0;
10792
10793         gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms,
10794                                                                         GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10795         error_code = gl.getError();
10796
10797         if (error_code == GL_INVALID_VALUE)
10798         {
10799                 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10800                                                                                 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10801
10802                 error_code = gl.getError();
10803         }
10804
10805         if (error_code != GL_INVALID_VALUE)
10806         {
10807                 m_testCtx.getLog() << tcu::TestLog::Message
10808                                                    << "glGetActiveSubroutineUniformiv() does not generate GL_INVALID_VALUE "
10809                                                           "when passed <index> argument that is greater than or equal to "
10810                                                           "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10811                                                    << tcu::TestLog::EndMessage;
10812
10813                 m_has_test_passed = false;
10814         }
10815
10816         gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 0, /* bufsize */
10817                                                                           &temp_length, DE_NULL);                                                                                /* name */
10818         error_code = gl.getError();
10819
10820         if (error_code == GL_INVALID_VALUE)
10821         {
10822                 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10823                                                                                   0,                                      /* bufsize */
10824                                                                                   &temp_length, DE_NULL); /* name */
10825
10826                 error_code = gl.getError();
10827         }
10828
10829         if (error_code != GL_INVALID_VALUE)
10830         {
10831                 m_testCtx.getLog() << tcu::TestLog::Message
10832                                                    << "glGetActiveSubroutineUniformName() does not generate GL_INVALID_VALUE "
10833                                                           "when passed <index> argument that is greater than or equal to "
10834                                                           "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10835                                                    << tcu::TestLog::EndMessage;
10836
10837                 m_has_test_passed = false;
10838         }
10839
10840         /* The error INVALID_VALUE is generated by GetActiveSubroutineName if <index>
10841          * is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader
10842          * stage.
10843          */
10844         gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines, 0, /* bufsize */
10845                                                            &temp_length, DE_NULL);                                                                /* name */
10846         error_code = gl.getError();
10847
10848         if (error_code == GL_INVALID_VALUE)
10849         {
10850                 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines + 1, 0, /* bufsize */
10851                                                                    &temp_length, DE_NULL);                                                                        /* name */
10852
10853                 error_code = gl.getError();
10854         }
10855
10856         if (error_code != GL_INVALID_VALUE)
10857         {
10858                 m_testCtx.getLog() << tcu::TestLog::Message << "glGetActiveSubroutineName() does not generate GL_INVALID_VALUE "
10859                                                                                                            "when passed <index> argument that is greater than or equal to "
10860                                                                                                            "the value of GL_ACTIVE_SUBROUTINES."
10861                                                    << tcu::TestLog::EndMessage;
10862
10863                 m_has_test_passed = false;
10864         }
10865
10866         /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count>
10867          * is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the
10868          * shader stage <shadertype>.
10869          */
10870         glw::GLuint index = 0;
10871
10872         gl.useProgram(m_po_id);
10873         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10874
10875         gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations - 1, &index);
10876         error_code = gl.getError();
10877
10878         if (error_code == GL_INVALID_VALUE)
10879         {
10880                 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &index);
10881
10882                 error_code = gl.getError();
10883         }
10884
10885         if (error_code != GL_INVALID_VALUE)
10886         {
10887                 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesiv() does not generate GL_INVALID_VALUE "
10888                                                                                                            "when passed <count> argument that is not equal to the value of "
10889                                                                                                            "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10890                                                    << tcu::TestLog::EndMessage;
10891
10892                 m_has_test_passed = false;
10893         }
10894
10895         /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value
10896          * in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES
10897          * for the shader stage.
10898          */
10899         glw::GLuint invalid_subroutine_indices[4] = { (GLuint)m_po_active_subroutines, (GLuint)m_po_active_subroutines,
10900                                                                                                   (GLuint)m_po_active_subroutines + 1,
10901                                                                                                   (GLuint)m_po_active_subroutines + 1 };
10902
10903         gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, /* count */
10904                                                          invalid_subroutine_indices + 0);
10905         error_code = gl.getError();
10906
10907         if (error_code == GL_INVALID_VALUE)
10908         {
10909                 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations,
10910                                                                  invalid_subroutine_indices + 2);
10911
10912                 error_code = gl.getError();
10913         }
10914
10915         if (error_code != GL_INVALID_VALUE)
10916         {
10917                 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesuiv() does not generate GL_INVALID_VALUE "
10918                                                                                                            "when the value passed via <indices> argument is greater than "
10919                                                                                                            "or equal to the value of GL_ACTIVE_SUBROUTINES."
10920                                                    << tcu::TestLog::EndMessage;
10921
10922                 m_has_test_passed = false;
10923         }
10924
10925         /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv() if any
10926          * subroutine index in <indices> identifies a subroutine not associated with
10927          * the type of the subroutine uniform variable assigned to the corresponding
10928          * location.
10929          */
10930         glw::GLuint invalid_subroutine_indices2[2] = { m_po_subroutine_test1_index, m_po_subroutine_test1_index };
10931
10932         gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, invalid_subroutine_indices2);
10933         error_code = gl.getError();
10934
10935         if (error_code != GL_INVALID_OPERATION)
10936         {
10937                 m_testCtx.getLog() << tcu::TestLog::Message
10938                                                    << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10939                                                           "when the subroutine index passed via <indices> argument identifies"
10940                                                           "a subroutine not associated with the type of the subroutine uniform "
10941                                                           "assigned to the corresponding location."
10942                                                    << tcu::TestLog::EndMessage;
10943
10944                 m_has_test_passed = false;
10945         }
10946
10947         /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no
10948          * program is active.
10949          */
10950         glw::GLuint valid_subroutine_locations[2] = { 0 };
10951
10952         valid_subroutine_locations[m_po_subroutine_uniform_function_index]  = m_po_subroutine_test1_index;
10953         valid_subroutine_locations[m_po_subroutine_uniform_function2_index] = m_po_subroutine_test3_index;
10954
10955         gl.useProgram(0);
10956         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10957
10958         gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, valid_subroutine_locations);
10959         error_code = gl.getError();
10960
10961         if (error_code != GL_INVALID_OPERATION)
10962         {
10963                 m_testCtx.getLog() << tcu::TestLog::Message
10964                                                    << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10965                                                           "when called without an active program object."
10966                                                    << tcu::TestLog::EndMessage;
10967
10968                 m_has_test_passed = false;
10969         }
10970
10971         /* The error INVALID_VALUE is generated by GetUniformSubroutineuiv if
10972          * <location> is greater than or equal to the value of
10973          * ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage.
10974          */
10975         glw::GLuint temp_value = 0;
10976
10977         gl.useProgram(m_po_id);
10978         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10979
10980         gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, &temp_value);
10981         error_code = gl.getError();
10982
10983         if (error_code == GL_INVALID_VALUE)
10984         {
10985                 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &temp_value);
10986                 error_code = gl.getError();
10987         }
10988
10989         if (error_code != GL_INVALID_VALUE)
10990         {
10991                 m_testCtx.getLog() << tcu::TestLog::Message
10992                                                    << "glGetUniformSubroutineuiv() does not generate GL_INVALID_VALUE "
10993                                                           "when called for location that is greater than or equal to the value "
10994                                                           "of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10995                                                    << tcu::TestLog::EndMessage;
10996
10997                 m_has_test_passed = false;
10998         }
10999
11000         /* The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no
11001          * program is active for the shader stage identified by <shadertype>.
11002          */
11003         const glw::GLenum undefined_shader_stages[] = { GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER,
11004                                                                                                         GL_TESS_EVALUATION_SHADER };
11005         const unsigned int n_undefined_shader_stages = sizeof(undefined_shader_stages) / sizeof(undefined_shader_stages[0]);
11006
11007         for (unsigned int n_undefined_shader_stage = 0; n_undefined_shader_stage < n_undefined_shader_stages;
11008                  ++n_undefined_shader_stage)
11009         {
11010                 glw::GLenum shader_stage = undefined_shader_stages[n_undefined_shader_stage];
11011
11012                 gl.getUniformSubroutineuiv(shader_stage, 0, /* location */
11013                                                                    &temp_value);
11014                 error_code = gl.getError();
11015
11016                 if (error_code != GL_INVALID_OPERATION)
11017                 {
11018                         m_testCtx.getLog() << tcu::TestLog::Message
11019                                                            << "glGetUniformSubroutineuiv() does not generate GL_INVALID_OPERATION "
11020                                                                   "when called for a shader stage that is not defined for active "
11021                                                                   "program object."
11022                                                            << tcu::TestLog::EndMessage;
11023
11024                         m_has_test_passed = false;
11025                 }
11026         } /* for (all undefined shader stages) */
11027
11028         /* All done */
11029         if (m_has_test_passed)
11030         {
11031                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11032         }
11033         else
11034         {
11035                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11036         }
11037
11038         return STOP;
11039 }
11040
11041 /** Constructor
11042  *
11043  *  @param context Rendering context.
11044  *
11045  **/
11046 NegativeTest2::NegativeTest2(deqp::Context& context)
11047         : TestCase(context, "subroutine_uniform_scope", "Verifies subroutine uniforms declared in shader stage A"
11048                                                                                                         "cannot be accessed from a different stage.")
11049         , m_fs_id(0)
11050         , m_gs_id(0)
11051         , m_has_test_passed(true)
11052         , m_po_id(0)
11053         , m_tc_id(0)
11054         , m_te_id(0)
11055         , m_vs_id(0)
11056 {
11057         /* Left blank intentionally */
11058 }
11059
11060 /** Deinitializes all GL objects that may have been created during test execution */
11061 void NegativeTest2::deinit()
11062 {
11063         deinitGLObjects();
11064 }
11065
11066 /** Deinitializes all GL objects that may have been created during test execution */
11067 void NegativeTest2::deinitGLObjects()
11068 {
11069         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11070
11071         if (m_fs_id != 0)
11072         {
11073                 gl.deleteShader(m_fs_id);
11074
11075                 m_fs_id = 0;
11076         }
11077
11078         if (m_gs_id != 0)
11079         {
11080                 gl.deleteShader(m_gs_id);
11081
11082                 m_gs_id = 0;
11083         }
11084
11085         if (m_tc_id != 0)
11086         {
11087                 gl.deleteShader(m_tc_id);
11088
11089                 m_tc_id = 0;
11090         }
11091
11092         if (m_te_id != 0)
11093         {
11094                 gl.deleteShader(m_te_id);
11095
11096                 m_te_id = 0;
11097         }
11098
11099         if (m_vs_id != 0)
11100         {
11101                 gl.deleteShader(m_vs_id);
11102
11103                 m_vs_id = 0;
11104         }
11105
11106         if (m_po_id != 0)
11107         {
11108                 gl.deleteProgram(m_po_id);
11109
11110                 m_po_id = 0;
11111         }
11112 }
11113
11114 /** Builds an offending program object and tries to link it. We're either expecting
11115  *  a compile-time or link-time error here.
11116  *
11117  *  If the program object builds successfully, the test has failed.
11118  *
11119  *  @param referencing_stage Shader stage which defines a subroutine uniform that
11120  *                           should be called from fragment/geometry/tess control/
11121  *                           tess evaluation/vertex shader stages.
11122  *
11123  **/
11124 void NegativeTest2::executeTestCase(const Utils::_shader_stage& referencing_stage)
11125 {
11126         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11127
11128         const std::string fs_body = getFragmentShaderBody(referencing_stage);
11129         const std::string gs_body = getGeometryShaderBody(referencing_stage);
11130         const std::string tc_body = getTessellationControlShaderBody(referencing_stage);
11131         const std::string te_body = getTessellationEvaluationShaderBody(referencing_stage);
11132         const std::string vs_body = getVertexShaderBody(referencing_stage);
11133
11134         if (Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, NULL, /* xfb_varyings */
11135                                                         0,                                                                                                         /* n_xfb_varyings */
11136                                                         &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
11137         {
11138                 /* Test program should not have built correctly ! */
11139                 m_testCtx.getLog() << tcu::TestLog::Message << "In the following program, one of the stages references "
11140                                                                                                            "a subroutine that is defined in another stage. This "
11141                                                                                                            "is forbidden by the specification.\n"
11142                                                                                                            "\n"
11143                                                                                                            "Vertex shader:\n\n"
11144                                                    << vs_body.c_str() << "\n\nTessellation control shader:\n\n"
11145                                                    << tc_body.c_str() << "\n\nTessellation evaluation shader:\n\n"
11146                                                    << te_body.c_str() << "\n\nGeometry shader:\n\n"
11147                                                    << gs_body.c_str() << "\n\nFragment shader:\n\n"
11148                                                    << fs_body.c_str() << tcu::TestLog::EndMessage;
11149
11150                 m_has_test_passed = false;
11151         } /* if (test program was built successfully) */
11152
11153         /* Release the shaders & the program object that buildProgram() created */
11154         deinitGLObjects();
11155 }
11156
11157 /** Retrieves an offending fragment shader body.
11158  *
11159  *  @param referencing_stage Shader stage which defines the subroutine uniform that
11160  *                           will be called from fragment shader.
11161  *
11162  *  @return Requested string.
11163  **/
11164 std::string NegativeTest2::getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const
11165 {
11166         std::stringstream result;
11167
11168         /* Form the pre-amble */
11169         result << "#version 400\n"
11170                           "\n"
11171                           "#extension GL_ARB_shader_subroutine : require\n"
11172                           "\n"
11173                           "subroutine void testSubroutineType(out vec4 test_argument);\n"
11174                           "\n"
11175                           /* Define a subroutine */
11176                           "subroutine(testSubroutineType) void fs_subroutine(out vec4 test_argument)\n"
11177                           "{\n"
11178                           "    test_argument = vec4(1, 0, 0, 0);\n"
11179                           "}\n"
11180                           "\n"
11181                           /* Define output variables */
11182                           "out vec4 result;\n"
11183                           "\n"
11184                           /* Define uniforms */
11185                           "subroutine uniform testSubroutineType test_fs_subroutine;\n"
11186                           "\n"
11187                           /* Define main() */
11188                           "void main()\n"
11189                           "{\n"
11190                           "    "
11191                    << getSubroutineUniformName(referencing_stage) << "(result);\n"
11192                                                                                                                          "}\n";
11193
11194         return result.str();
11195 }
11196
11197 /** Retrieves an offending geometry shader body.
11198  *
11199  *  @param referencing_stage Shader stage which defines the subroutine uniform that
11200  *                           will be called from geometry shader.
11201  *
11202  *  @return Requested string.
11203  **/
11204 std::string NegativeTest2::getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const
11205 {
11206         std::stringstream result;
11207
11208         /* Form the pre-amble */
11209         result << "#version 400\n"
11210                           "\n"
11211                           "#extension GL_ARB_shader_subroutine : require\n"
11212                           "\n"
11213                           "subroutine void testSubroutineType(out vec4 test_argument);\n"
11214                           "\n"
11215                           "layout(points)                   in;\n"
11216                           "layout(points, max_vertices = 1) out;\n"
11217                           "\n"
11218                           /* Define a subroutine */
11219                           "subroutine(testSubroutineType) void gs_subroutine(out vec4 test_argument)\n"
11220                           "{\n"
11221                           "    test_argument = vec4(0, 1, 1, 1);\n"
11222                           "}\n"
11223                           "\n"
11224                           /* Define output variables */
11225                           "out vec4 result;\n"
11226                           "\n"
11227                           /* Define uniforms */
11228                           "subroutine uniform testSubroutineType test_gs_subroutine;\n"
11229                           "\n"
11230                           /* Define main() */
11231                           "void main()\n"
11232                           "{\n"
11233                           "    "
11234                    << getSubroutineUniformName(referencing_stage) << "(result);\n"
11235                                                                                                                          "}\n";
11236
11237         return result.str();
11238 }
11239
11240 /** Retrieves name of the subroutine uniform that is defined in user-specified
11241  *  shader stage.
11242  *
11243  *  @param stage Shader stage to retrieve the subroutine uniform name for.
11244  *
11245  *  @return As per description.
11246  **/
11247 std::string NegativeTest2::getSubroutineUniformName(const Utils::_shader_stage& stage) const
11248 {
11249         std::string result = "?";
11250
11251         switch (stage)
11252         {
11253         case Utils::SHADER_STAGE_FRAGMENT:
11254         {
11255                 result = "test_fs_subroutine";
11256
11257                 break;
11258         }
11259
11260         case Utils::SHADER_STAGE_GEOMETRY:
11261         {
11262                 result = "test_gs_subroutine";
11263
11264                 break;
11265         }
11266
11267         case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11268         {
11269                 result = "test_tc_subroutine";
11270
11271                 break;
11272         }
11273
11274         case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11275         {
11276                 result = "test_te_subroutine";
11277
11278                 break;
11279         }
11280
11281         case Utils::SHADER_STAGE_VERTEX:
11282         {
11283                 result = "test_vs_subroutine";
11284
11285                 break;
11286         }
11287
11288         default:
11289         {
11290                 TCU_FAIL("Unrecognized shader stage requested");
11291         }
11292         } /* switch (stage) */
11293
11294         return result;
11295 }
11296
11297 /** Retrieves an offending tessellation control shader body.
11298  *
11299  *  @param referencing_stage Shader stage which defines the subroutine uniform that
11300  *                           will be called from tessellation control shader.
11301  *
11302  *  @return Requested string.
11303  **/
11304 std::string NegativeTest2::getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const
11305 {
11306         std::stringstream result;
11307
11308         /* Form the pre-amble */
11309         result << "#version 400\n"
11310                           "\n"
11311                           "#extension GL_ARB_shader_subroutine : require\n"
11312                           "\n"
11313                           "layout(vertices = 4) out;\n"
11314                           "\n"
11315                           "subroutine void testSubroutineType(out vec4 test_argument);\n"
11316                           "\n"
11317                           /* Define a subroutine */
11318                           "subroutine(testSubroutineType) void tc_subroutine(out vec4 test_argument)\n"
11319                           "{\n"
11320                           "    test_argument = vec4(0, 0, 1, 0);\n"
11321                           "}\n"
11322                           "\n"
11323                           /* Define uniforms */
11324                           "subroutine uniform testSubroutineType test_tc_subroutine;\n"
11325                           "\n"
11326                           /* Define main() */
11327                           "void main()\n"
11328                           "{\n"
11329                           "    "
11330                    << getSubroutineUniformName(referencing_stage) << "(gl_out[gl_InvocationID].gl_Position);\n"
11331                                                                                                                          "}\n";
11332
11333         return result.str();
11334 }
11335
11336 /** Retrieves an offending tessellation evaluation shader body.
11337  *
11338  *  @param referencing_stage Shader stage which defines the subroutine uniform that
11339  *                           will be called from tessellation evaluation shader.
11340  *
11341  *  @return Requested string.
11342  **/
11343 std::string NegativeTest2::getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const
11344 {
11345         std::stringstream result;
11346
11347         /* Form the pre-amble */
11348         result << "#version 400\n"
11349                           "\n"
11350                           "#extension GL_ARB_shader_subroutine : require\n"
11351                           "\n"
11352                           "layout(quads) in;\n"
11353                           "\n"
11354                           "subroutine void testSubroutineType(out vec4 test_argument);\n"
11355                           "\n"
11356                           /* Define a subroutine */
11357                           "subroutine(testSubroutineType) void te_subroutine(out vec4 test_argument)\n"
11358                           "{\n"
11359                           "    test_argument = vec4(1, 1, 1, 1);\n"
11360                           "}\n"
11361                           "\n"
11362                           /* Define uniforms */
11363                           "subroutine uniform testSubroutineType test_te_subroutine;\n"
11364                           "\n"
11365                           /* Define main() */
11366                           "void main()\n"
11367                           "{\n"
11368                           "    "
11369                    << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
11370                                                                                                                          "}\n";
11371
11372         return result.str();
11373 }
11374
11375 /** Retrieves an offending vertex shader body.
11376  *
11377  *  @param referencing_stage Shader stage which defines the subroutine uniform that
11378  *                           will be called from vertex shader.
11379  *
11380  *  @return Requested string.
11381  **/
11382 std::string NegativeTest2::getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const
11383 {
11384         std::stringstream result;
11385
11386         /* Form the pre-amble */
11387         result << "#version 400\n"
11388                           "\n"
11389                           "#extension GL_ARB_shader_subroutine : require\n"
11390                           "\n"
11391                           "subroutine void testSubroutineType(out vec4 test_argument);\n"
11392                           "\n"
11393                           /* Define a subroutine */
11394                           "subroutine(testSubroutineType) void vs_subroutine(out vec4 test_argument)\n"
11395                           "{\n"
11396                           "    test_argument = vec4(0, 1, 0, 0);\n"
11397                           "}\n"
11398                           "\n"
11399                           /* Define uniforms */
11400                           "subroutine uniform testSubroutineType test_vs_subroutine;\n"
11401                           "\n"
11402                           /* Define main() */
11403                           "void main()\n"
11404                           "{\n"
11405                           "    "
11406                    << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
11407                                                                                                                          "}\n";
11408
11409         return result.str();
11410 }
11411
11412 /** Executes test iteration.
11413  *
11414  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11415  */
11416 tcu::TestNode::IterateResult NegativeTest2::iterate()
11417 {
11418         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11419         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11420         {
11421                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11422         }
11423
11424         /* Iterate over all shader stages and execute the checks */
11425         for (int referencing_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11426                  referencing_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++referencing_stage)
11427         {
11428                 executeTestCase(static_cast<Utils::_shader_stage>(referencing_stage));
11429         } /* for (all test cases) */
11430
11431         /* All done */
11432         if (m_has_test_passed)
11433         {
11434                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11435         }
11436         else
11437         {
11438                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11439         }
11440
11441         return STOP;
11442 }
11443
11444 /** Constructor.
11445  *
11446  *  @param context Rendering context.
11447  *
11448  **/
11449 NegativeTest3::NegativeTest3(deqp::Context& context)
11450         : TestCase(context, "missing_subroutine_keyword", "Verifies that subroutine keyword is necessary when declaring a "
11451                                                                                                           "subroutine uniforn and a compilation error occurs without it.")
11452         , m_has_test_passed(true)
11453         , m_so_id(0)
11454 {
11455         /* Left blank intentionally */
11456 }
11457
11458 /** Deinitializes all GL objects that may have been created during test execution */
11459 void NegativeTest3::deinit()
11460 {
11461         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11462
11463         if (m_so_id != 0)
11464         {
11465                 gl.deleteShader(m_so_id);
11466
11467                 m_so_id = 0;
11468         }
11469 }
11470
11471 /** Verifies that broken shader (for user-specified shader stage) does not compile.
11472  *
11473  *  @param shader_stage Shader stage to use for the test.
11474  **/
11475 void NegativeTest3::executeTest(const Utils::_shader_stage& shader_stage)
11476 {
11477         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11478
11479         /* Generate a new shader object */
11480         m_so_id = gl.createShader(Utils::getGLenumForShaderStage(shader_stage));
11481         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
11482
11483         /* Assign body to the shader */
11484         std::string body;
11485         const char* body_raw_ptr = DE_NULL;
11486
11487         switch (shader_stage)
11488         {
11489         case Utils::SHADER_STAGE_VERTEX:
11490                 body = getVertexShaderBody();
11491                 break;
11492         case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11493                 body = getTessellationControlShaderBody();
11494                 break;
11495         case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11496                 body = getTessellationEvaluationShaderBody();
11497                 break;
11498         case Utils::SHADER_STAGE_GEOMETRY:
11499                 body = getGeometryShaderBody();
11500                 break;
11501         case Utils::SHADER_STAGE_FRAGMENT:
11502                 body = getFragmentShaderBody();
11503                 break;
11504
11505         default:
11506         {
11507                 TCU_FAIL("Unrecognized shader stage requested");
11508         }
11509         } /* switch (shader_stage) */
11510
11511         body_raw_ptr = body.c_str();
11512
11513         gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
11514         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11515
11516         /* Try to compile the shader */
11517         glw::GLint compile_status = 0;
11518
11519         gl.compileShader(m_so_id);
11520         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11521
11522         gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
11523         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11524
11525         if (compile_status == GL_TRUE)
11526         {
11527                 m_testCtx.getLog() << tcu::TestLog::Message << "The following shader was expected to fail to compile but was "
11528                                                                                                            "accepted by the compiler:\n"
11529                                                                                                            "\n"
11530                                                    << body.c_str() << tcu::TestLog::EndMessage;
11531
11532                 m_has_test_passed = false;
11533         }
11534
11535         /* Good to release the shader at this point */
11536         gl.deleteShader(m_so_id);
11537         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
11538 }
11539
11540 /** Retrieves body of a broken fragment shader.
11541  *
11542  *  @return Requested string.
11543  **/
11544 std::string NegativeTest3::getFragmentShaderBody() const
11545 {
11546         return "#version 400\n"
11547                    "\n"
11548                    "#extension GL_ARB_shader_subroutine : require\n"
11549                    "\n"
11550                    "subroutine void testSubroutineType(inout vec4 test);\n"
11551                    "\n"
11552                    "void testSubroutine1(inout vec4 test)\n"
11553                    "{\n"
11554                    "    test += vec4(3, 4, 5, 6);\n"
11555                    "}\n"
11556                    "\n"
11557                    "uniform testSubroutineType subroutineFunction;\n"
11558                    "out     vec4               result;\n"
11559                    "\n"
11560                    "void main()\n"
11561                    "{\n"
11562                    "    vec4 test = vec4(2, 3, 4, 5);\n"
11563                    "\n"
11564                    "    subroutineFunction(test);\n"
11565                    "\n"
11566                    "    result = test;\n"
11567                    "}\n";
11568 }
11569
11570 /** Retrieves body of a broken geometry shader.
11571  *
11572  *  @return Requested string.
11573  **/
11574 std::string NegativeTest3::getGeometryShaderBody() const
11575 {
11576         return "#version 400\n"
11577                    "\n"
11578                    "#extension GL_ARB_shader_subroutine : require\n"
11579                    "\n"
11580                    "layout(points)                   in;\n"
11581                    "layout(points, max_vertices = 1) out;\n"
11582                    "\n"
11583                    "subroutine void testSubroutineType(inout vec4 test);\n"
11584                    "\n"
11585                    "void testSubroutine1(inout vec4 test)\n"
11586                    "{\n"
11587                    "    test += vec4(3, 4, 5, 6);\n"
11588                    "}\n"
11589                    "\n"
11590                    "uniform testSubroutineType subroutineFunction;\n"
11591                    "\n"
11592                    "void main()\n"
11593                    "{\n"
11594                    "    vec4 test = vec4(2, 3, 4, 5);\n"
11595                    "\n"
11596                    "    subroutineFunction(test);\n"
11597                    "\n"
11598                    "    gl_Position = test;\n"
11599                    "    EmitVertex();\n"
11600                    "}\n";
11601 }
11602
11603 /** Retrieves body of a broken tessellation control shader.
11604  *
11605  *  @return Requested string.
11606  **/
11607 std::string NegativeTest3::getTessellationControlShaderBody() const
11608 {
11609         return "#version 400\n"
11610                    "\n"
11611                    "#extension GL_ARB_shader_subroutine : require\n"
11612                    "\n"
11613                    "layout(vertices=4) out;\n"
11614                    "\n"
11615                    "subroutine void testSubroutineType(inout vec4 test);\n"
11616                    "\n"
11617                    "void testSubroutine1(inout vec4 test)\n"
11618                    "{\n"
11619                    "    test += vec4(1, 2, 3, 4);\n"
11620                    "}\n"
11621                    "\n"
11622                    "uniform testSubroutineType subroutineFunction;\n"
11623                    "\n"
11624                    "void main()\n"
11625                    "{\n"
11626                    "    vec4 test = vec4(0, 1, 2, 3);\n"
11627                    "\n"
11628                    "    subroutineFunction(test);\n"
11629                    "\n"
11630                    "    gl_out[gl_InvocationID].gl_Position = test;\n"
11631                    "}\n";
11632 }
11633
11634 /** Retrieves body of a broken tessellation evaluation shader.
11635  *
11636  *  @return Requested string.
11637  **/
11638 std::string NegativeTest3::getTessellationEvaluationShaderBody() const
11639 {
11640         return "#version 400\n"
11641                    "\n"
11642                    "#extension GL_ARB_shader_subroutine : require\n"
11643                    "\n"
11644                    "layout(quads) in;\n"
11645                    "\n"
11646                    "subroutine void testSubroutineType(inout vec4 test);\n"
11647                    "\n"
11648                    "void testSubroutine1(inout vec4 test)\n"
11649                    "{\n"
11650                    "    test += vec4(2, 3, 4, 5);\n"
11651                    "}\n"
11652                    "\n"
11653                    "uniform testSubroutineType subroutineFunction;\n"
11654                    "\n"
11655                    "void main()\n"
11656                    "{\n"
11657                    "    vec4 test = vec4(1, 2, 3, 4);\n"
11658                    "\n"
11659                    "    subroutineFunction(test);\n"
11660                    "\n"
11661                    "    gl_Position = test;\n"
11662                    "}\n";
11663 }
11664
11665 /** Retrieves body of a broken vertex shader.
11666  *
11667  *  @return Requested string.
11668  **/
11669 std::string NegativeTest3::getVertexShaderBody() const
11670 {
11671         return "#version 400\n"
11672                    "\n"
11673                    "#extension GL_ARB_shader_subroutine : require\n"
11674                    "\n"
11675                    "subroutine void testSubroutineType(inout vec4 test);\n"
11676                    "\n"
11677                    "void testSubroutine1(inout vec4 test)\n"
11678                    "{\n"
11679                    "    test += vec4(0, 1, 2, 3);\n"
11680                    "}\n"
11681                    "\n"
11682                    "uniform testSubroutineType subroutineFunction;\n"
11683                    "\n"
11684                    "void main()\n"
11685                    "{\n"
11686                    "    subroutineFunction(gl_Position);\n"
11687                    "}\n";
11688 }
11689
11690 /** Executes test iteration.
11691  *
11692  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11693  */
11694 tcu::TestNode::IterateResult NegativeTest3::iterate()
11695 {
11696         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11697         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11698         {
11699                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11700         }
11701
11702         /* Iterate over all shader stages */
11703         for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11704                  shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11705         {
11706                 executeTest(static_cast<Utils::_shader_stage>(shader_stage));
11707         } /* for (all shader stages) */
11708
11709         /* Done */
11710         if (m_has_test_passed)
11711         {
11712                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11713         }
11714         else
11715         {
11716                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11717         }
11718
11719         return STOP;
11720 }
11721
11722 /** Constructor.
11723  *
11724  *  @param context Rendering context.
11725  *
11726  **/
11727 NegativeTest4::NegativeTest4(deqp::Context& context)
11728         : TestCase(context, "subroutines_incompatible_with_subroutine_type",
11729                            "Verifies that a compile-time error is generated when arguments and "
11730                            "return type do not match beween the function and each associated "
11731                            "subroutine type.")
11732         , m_has_test_passed(true)
11733         , m_so_id(0)
11734 {
11735         /* Left blank intentionally */
11736 }
11737
11738 /** Deinitializes GL objects that may have been created during test
11739  *  execution.
11740  **/
11741 void NegativeTest4::deinit()
11742 {
11743         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11744
11745         if (m_so_id != 0)
11746         {
11747                 gl.deleteShader(m_so_id);
11748
11749                 m_so_id = 0;
11750         }
11751 }
11752
11753 /** Retrieves body of a shader of user-specified type that should be used
11754  *  for a single test iteration. The shader will define user-specified number
11755  *  of subroutine types, with the last type either defining an additional argument
11756  *  or using a different return type.
11757  *  A subroutine (claimed compatible with *all* subroutine types) will also be
11758  *  defined in the shader.
11759  *
11760  *  @param shader_stage       Shader stage to use for the query.
11761  *  @param n_subroutine_types Overall number of subroutine types that will be
11762  *                            declared & used in the shader. Please see description
11763  *                            for more details.
11764  *
11765  *  @return Requested string.
11766  **/
11767 std::string NegativeTest4::getShaderBody(const Utils::_shader_stage& shader_stage,
11768                                                                                  const unsigned int& n_subroutine_types, const _test_case& test_case) const
11769 {
11770         std::stringstream result_sstream;
11771
11772         /* Form the pre-amble */
11773         result_sstream << "#version 400\n"
11774                                           "\n"
11775                                           "#extension GL_ARB_shader_subroutine : require\n"
11776                                           "\n";
11777
11778         /* Inject stage-specific code */
11779         switch (shader_stage)
11780         {
11781         case Utils::SHADER_STAGE_GEOMETRY:
11782         {
11783                 result_sstream << "layout (points) in;\n"
11784                                                   "layout (points, max_vertices = 1) out;\n"
11785                                                   "\n";
11786
11787                 break;
11788         }
11789
11790         case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11791         {
11792                 result_sstream << "layout (vertices = 4) out;\n"
11793                                                   "\n";
11794
11795                 break;
11796         }
11797
11798         case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11799         {
11800                 result_sstream << "layout (quads) in;\n"
11801                                                   "\n";
11802
11803                 break;
11804         }
11805
11806         default:
11807                 break;
11808         } /* switch (shader_stage) */
11809
11810         /* Insert subroutine type declarations */
11811         for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types - 1; ++n_subroutine_type)
11812         {
11813                 result_sstream << "subroutine void subroutineType" << n_subroutine_type << "(inout vec3 argument);\n";
11814         } /* for (all subroutine types) */
11815
11816         switch (test_case)
11817         {
11818         case TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST:
11819         {
11820                 result_sstream << "subroutine void subroutineType" << (n_subroutine_types - 1)
11821                                            << "(inout vec3 argument, out vec4 argument2);\n";
11822
11823                 break;
11824         }
11825
11826         case TEST_CASE_INCOMPATIBLE_RETURN_TYPE:
11827         {
11828                 result_sstream << "subroutine int subroutineType" << (n_subroutine_types - 1) << "(inout vec3 argument);\n";
11829
11830                 break;
11831         }
11832
11833         default:
11834         {
11835                 TCU_FAIL("Unrecognized test case");
11836         }
11837         } /* switch (test_case) */
11838
11839         /* Insert subroutine declarations */
11840         result_sstream << "subroutine(";
11841
11842         for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types; ++n_subroutine_type)
11843         {
11844                 result_sstream << "subroutineType" << n_subroutine_type;
11845
11846                 if (n_subroutine_type != (n_subroutine_types - 1))
11847                 {
11848                         result_sstream << ", ";
11849                 }
11850         } /* for (all subroutine types) */
11851
11852         result_sstream << ") void function(inout vec3 argument)\n"
11853                                           "{\n"
11854                                           "    argument = vec3(1, 2, 3);\n"
11855                                           "}\n"
11856                                           "\n";
11857
11858         /* Insert remaining required stage-specific bits */
11859         switch (shader_stage)
11860         {
11861         case Utils::SHADER_STAGE_FRAGMENT:
11862         {
11863                 result_sstream << "out vec4 result;\n"
11864                                                   "\n"
11865                                                   "void main()\n"
11866                                                   "{\n"
11867                                                   "    result = vec4(1, 2, 3, 4);\n"
11868                                                   "}\n";
11869
11870                 break;
11871         }
11872
11873         case Utils::SHADER_STAGE_GEOMETRY:
11874         {
11875                 result_sstream << "void main()\n"
11876                                                   "{\n"
11877                                                   "    gl_Position = vec4(1, 2, 3, 4);\n"
11878                                                   "    EmitVertex();\n"
11879                                                   "}\n";
11880
11881                 break;
11882         }
11883
11884         case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11885         {
11886                 result_sstream << "void main()\n"
11887                                                   "{\n"
11888                                                   "    gl_TessLevelInner[0]                = 1;\n"
11889                                                   "    gl_TessLevelInner[1]                = 1;\n"
11890                                                   "    gl_TessLevelOuter[0]                = 1;\n"
11891                                                   "    gl_TessLevelOuter[1]                = 1;\n"
11892                                                   "    gl_TessLevelOuter[2]                = 1;\n"
11893                                                   "    gl_TessLevelOuter[3]                = 1;\n"
11894                                                   "    gl_out[gl_InvocationID].gl_Position = vec4(2, 3, 4, 5);\n"
11895                                                   "}\n";
11896
11897                 break;
11898         }
11899
11900         case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11901         case Utils::SHADER_STAGE_VERTEX:
11902         {
11903                 result_sstream << "void main()\n"
11904                                                   "{\n"
11905                                                   "    gl_Position = vec4(1, 2, 3, 4);\n"
11906                                                   "}\n";
11907
11908                 break;
11909         }
11910
11911         default:
11912         {
11913                 TCU_FAIL("Unrecognized shader stage");
11914         }
11915         } /* switch (shader_stage) */
11916
11917         return result_sstream.str();
11918 }
11919
11920 /** Executes test iteration.
11921  *
11922  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11923  */
11924 tcu::TestNode::IterateResult NegativeTest4::iterate()
11925 {
11926         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11927
11928         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11929         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11930         {
11931                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11932         }
11933
11934         /* Iterate over all shader stages.. */
11935         for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11936                  shader_stage != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11937         {
11938                 /* For each shader stage, we will be trying to compile a number of invalid shaders.
11939                  * Each shader defines N different subroutine types. (N-1) of them are compatible
11940                  * with a subroutine, but exactly 1 will be mismatched. The test passes if GLSL
11941                  * compiler correctly detects that all shaders we will be trying to compile are
11942                  * broken.
11943                  */
11944                 const glw::GLenum shader_type = Utils::getGLenumForShaderStage(static_cast<Utils::_shader_stage>(shader_stage));
11945
11946                 for (unsigned int n_subroutine_types = 1; n_subroutine_types < 6; /* arbitrary number */
11947                          ++n_subroutine_types)
11948                 {
11949                         for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT);
11950                                  ++test_case)
11951                         {
11952                                 std::string body;
11953                                 const char* body_raw_ptr   = NULL;
11954                                 glw::GLint  compile_status = GL_FALSE;
11955
11956                                 body = getShaderBody(static_cast<Utils::_shader_stage>(shader_stage), n_subroutine_types,
11957                                                                          static_cast<_test_case>(test_case));
11958                                 body_raw_ptr = body.c_str();
11959
11960                                 /* Try to compile the shader */
11961                                 m_so_id = gl.createShader(shader_type);
11962                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
11963
11964                                 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL);
11965                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
11966
11967                                 gl.compileShader(m_so_id);
11968                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
11969
11970                                 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
11971                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11972
11973                                 if (compile_status == GL_TRUE)
11974                                 {
11975                                         m_testCtx.getLog() << tcu::TestLog::Message << "A malformed "
11976                                                                            << Utils::getShaderStageString(static_cast<Utils::_shader_stage>(shader_stage))
11977                                                                            << " compiled successfully "
11978                                                                                   "("
11979                                                                            << n_subroutine_types << " subroutine types "
11980                                                                                                                                 "were defined)."
11981                                                                            << tcu::TestLog::EndMessage;
11982
11983                                         m_has_test_passed = false;
11984                                 }
11985
11986                                 /* Release the object */
11987                                 gl.deleteShader(m_so_id);
11988                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
11989                         } /* for (all test cases) */
11990                 }        /* for (a number of different subroutine type declarations) */
11991         }                 /* for (all shader stages) */
11992
11993         /* Done */
11994         if (m_has_test_passed)
11995         {
11996                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11997         }
11998         else
11999         {
12000                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12001         }
12002
12003         return STOP;
12004 }
12005
12006 /** Constructor.
12007  *
12008  *  @param context Rendering context.
12009  *
12010  **/
12011 NegativeTest5::NegativeTest5(deqp::Context& context)
12012         : TestCase(context, "subroutine_uniform_wo_matching_subroutines",
12013                            "Verifies that a link- or compile-time error occurs when "
12014                            "trying to link a program with no subroutine for subroutine "
12015                            "uniform variable.")
12016         , m_fs_id(0)
12017         , m_gs_id(0)
12018         , m_has_test_passed(true)
12019         , m_po_id(0)
12020         , m_tc_id(0)
12021         , m_te_id(0)
12022         , m_vs_id(0)
12023 {
12024         /* Left blank intentionally */
12025 }
12026
12027 /** Deinitializes all GL objects that may have been created during test execution */
12028 void NegativeTest5::deinit()
12029 {
12030         deinitIteration();
12031 }
12032
12033 /** Deinitializes all GL objects that may have been created during a single test
12034  *  iteration.
12035  ***/
12036 void NegativeTest5::deinitIteration()
12037 {
12038         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12039
12040         if (m_fs_id != 0)
12041         {
12042                 gl.deleteShader(m_fs_id);
12043
12044                 m_fs_id = 0;
12045         }
12046
12047         if (m_gs_id != 0)
12048         {
12049                 gl.deleteShader(m_gs_id);
12050
12051                 m_gs_id = 0;
12052         }
12053
12054         if (m_po_id != 0)
12055         {
12056                 gl.deleteProgram(m_po_id);
12057
12058                 m_po_id = 0;
12059         }
12060
12061         if (m_tc_id != 0)
12062         {
12063                 gl.deleteShader(m_tc_id);
12064
12065                 m_tc_id = 0;
12066         }
12067
12068         if (m_te_id != 0)
12069         {
12070                 gl.deleteShader(m_te_id);
12071
12072                 m_te_id = 0;
12073         }
12074
12075         if (m_vs_id != 0)
12076         {
12077                 gl.deleteShader(m_vs_id);
12078
12079                 m_vs_id = 0;
12080         }
12081 }
12082
12083 /** Executes a single test iteration.
12084  *
12085  *  If the iteration fails, m_has_test_passed will be set to false.
12086  *
12087  *  @param shader_stage Shader stage, for which a subroutine uniform should be
12088  *                      declared in the shader without a matching subroutine.
12089  **/
12090 void NegativeTest5::executeIteration(const Utils::_shader_stage& shader_stage)
12091 {
12092         std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
12093         std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
12094         std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
12095         std::string te_body =
12096                 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
12097         std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
12098
12099         if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
12100                                                         DE_NULL, /* xfb_varyings */
12101                                                         DE_NULL, /* n_xfb_varyings */
12102                                                         &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
12103         {
12104                 /* None of the test programs should ever build successfully */
12105                 m_testCtx.getLog() << tcu::TestLog::Message
12106                                                    << "A program object, consisting of the following shaders, has linked"
12107                                                           " correctly. One of the shaders defines a subroutine uniform but does "
12108                                                           "not implement any function that matches subroutine type of the uniform."
12109                                                           " This should have resulted in a compilation/link-time error.\n"
12110                                                           "\n"
12111                                                           "Vertex shader:\n"
12112                                                           "\n"
12113                                                    << vs_body << "\n"
12114                                                                                  "Tessellation control shader:\n"
12115                                                                                  "\n"
12116                                                    << tc_body << "\n"
12117                                                                                  "Tessellation evaluation shader:\n"
12118                                                                                  "\n"
12119                                                    << te_body << "\n"
12120                                                                                  "Geometry shader:\n"
12121                                                                                  "\n"
12122                                                    << gs_body << "\n"
12123                                                                                  "Fragment shader:\n"
12124                                                                                  "\n"
12125                                                    << fs_body << tcu::TestLog::EndMessage;
12126
12127                 m_has_test_passed = false;
12128         }
12129 }
12130
12131 /** Retrieves fragment shader body.
12132  *
12133  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12134  *                                                        a subroutine uniform without
12135  *                                                        a matching subroutine, false otherwise.
12136  *
12137  *  @return Requested string.
12138  **/
12139 std::string NegativeTest5::getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12140 {
12141         std::stringstream result_sstream;
12142
12143         result_sstream << "#version 400\n"
12144                                           "\n"
12145                                           "#extension GL_ARB_shader_subroutine : require\n"
12146                                           "\n";
12147
12148         if (include_invalid_subroutine_uniform_declaration)
12149         {
12150                 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
12151                                                   "\n"
12152                                                   "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
12153         };
12154
12155         result_sstream << "\n"
12156                                           "out vec4 result;\n"
12157                                           "\n"
12158                                           "void main()\n"
12159                                           "{\n";
12160
12161         if (include_invalid_subroutine_uniform_declaration)
12162         {
12163                 result_sstream << "    test_subroutineFS(result);\n";
12164         }
12165         else
12166         {
12167                 result_sstream << "    result = vec4(0, 1, 2, 3);\n";
12168         }
12169
12170         result_sstream << "}\n";
12171
12172         return result_sstream.str();
12173 }
12174
12175 /** Retrieves geometry shader body.
12176  *
12177  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12178  *                                                        a subroutine uniform without
12179  *                                                        a matching subroutine, false otherwise.
12180  *
12181  *  @return Requested string.
12182  **/
12183 std::string NegativeTest5::getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12184 {
12185         std::stringstream result_sstream;
12186
12187         result_sstream << "#version 400\n"
12188                                           "\n"
12189                                           "#extension GL_ARB_shader_subroutine : require\n"
12190                                           "\n"
12191                                           "layout (points)                   in;\n"
12192                                           "layout (points, max_vertices = 1) out;\n"
12193                                           "\n";
12194
12195         if (include_invalid_subroutine_uniform_declaration)
12196         {
12197                 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
12198                                                   "\n"
12199                                                   "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
12200         };
12201
12202         result_sstream << "\n"
12203                                           "void main()\n"
12204                                           "{\n";
12205
12206         if (include_invalid_subroutine_uniform_declaration)
12207         {
12208                 result_sstream << "    test_subroutineGS(gl_Position);\n";
12209         }
12210         else
12211         {
12212                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12213         }
12214
12215         result_sstream << "EmitVertex();\n"
12216                                           "}\n";
12217
12218         return result_sstream.str();
12219 }
12220
12221 /** Retrieves tessellation control shader body.
12222  *
12223  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12224  *                                                        a subroutine uniform without
12225  *                                                        a matching subroutine, false otherwise.
12226  *
12227  *  @return Requested string.
12228  **/
12229 std::string NegativeTest5::getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12230 {
12231         std::stringstream result_sstream;
12232
12233         result_sstream << "#version 400\n"
12234                                           "\n"
12235                                           "#extension GL_ARB_shader_subroutine : require\n"
12236                                           "\n"
12237                                           "layout (vertices = 4) out;\n"
12238                                           "\n";
12239
12240         if (include_invalid_subroutine_uniform_declaration)
12241         {
12242                 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
12243                                                   "\n"
12244                                                   "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
12245         };
12246
12247         result_sstream << "\n"
12248                                           "void main()\n"
12249                                           "{\n";
12250
12251         if (include_invalid_subroutine_uniform_declaration)
12252         {
12253                 result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
12254         }
12255         else
12256         {
12257                 result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
12258         }
12259
12260         result_sstream << "}\n";
12261
12262         return result_sstream.str();
12263 }
12264
12265 /** Retrieves tessellation evaluation body.
12266  *
12267  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12268  *                                                        a subroutine uniform without
12269  *                                                        a matching subroutine, false otherwise.
12270  *
12271  *  @return Requested string.
12272  **/
12273 std::string NegativeTest5::getTessellationEvaluationShaderBody(
12274         bool include_invalid_subroutine_uniform_declaration) const
12275 {
12276         std::stringstream result_sstream;
12277
12278         result_sstream << "#version 400\n"
12279                                           "\n"
12280                                           "#extension GL_ARB_shader_subroutine : require\n"
12281                                           "\n"
12282                                           "layout (quads) in;\n"
12283                                           "\n";
12284
12285         if (include_invalid_subroutine_uniform_declaration)
12286         {
12287                 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
12288                                                   "\n"
12289                                                   "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
12290         };
12291
12292         result_sstream << "\n"
12293                                           "void main()\n"
12294                                           "{\n";
12295
12296         if (include_invalid_subroutine_uniform_declaration)
12297         {
12298                 result_sstream << "    test_subroutineTE(gl_Position);\n";
12299         }
12300         else
12301         {
12302                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12303         }
12304
12305         result_sstream << "}\n";
12306
12307         return result_sstream.str();
12308 }
12309
12310 /** Retrieves vertex shader body.
12311  *
12312  *  @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12313  *                                                        a subroutine uniform without
12314  *                                                        a matching subroutine, false otherwise.
12315  *
12316  *  @return Requested string.
12317  **/
12318 std::string NegativeTest5::getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12319 {
12320         std::stringstream result_sstream;
12321
12322         result_sstream << "#version 400\n"
12323                                           "\n"
12324                                           "#extension GL_ARB_shader_subroutine : require\n"
12325                                           "\n";
12326
12327         if (include_invalid_subroutine_uniform_declaration)
12328         {
12329                 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12330                                                   "\n"
12331                                                   "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12332         };
12333
12334         result_sstream << "\n"
12335                                           "void main()\n"
12336                                           "{\n";
12337
12338         if (include_invalid_subroutine_uniform_declaration)
12339         {
12340                 result_sstream << "    test_subroutineVS(gl_Position);\n";
12341         }
12342         else
12343         {
12344                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12345         }
12346
12347         result_sstream << "}\n";
12348
12349         return result_sstream.str();
12350 }
12351
12352 /** Executes test iteration.
12353  *
12354  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12355  */
12356 tcu::TestNode::IterateResult NegativeTest5::iterate()
12357 {
12358         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12359         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12360         {
12361                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12362         }
12363
12364         /* Iterate over all shader stages. Iteration-specific shader stage defines a subroutine type &
12365          * a corresponding subroutine uniform, for which no compatible subroutines are available. All
12366          * other shader stages are defined correctly.
12367          */
12368         for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12369                  shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12370         {
12371                 executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12372                 deinitIteration();
12373         } /* for (all shader stages) */
12374
12375         /* All done */
12376         if (m_has_test_passed)
12377         {
12378                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12379         }
12380         else
12381         {
12382                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12383         }
12384
12385         return STOP;
12386 }
12387
12388 /** Constructor.
12389  *
12390  *  @param context Rendering context.
12391  *
12392  **/
12393 NegativeTest6::NegativeTest6(deqp::Context& context)
12394         : TestCase(context, "two_duplicate_functions_one_being_a_subroutine",
12395                            "Verifies that a link- or compile-time error occurs if any shader in "
12396                            "a program object includes two functions with the same name and one "
12397                            "of which is associated with a subroutine type.")
12398         , m_fs_id(0)
12399         , m_gs_id(0)
12400         , m_has_test_passed(true)
12401         , m_po_id(0)
12402         , m_tc_id(0)
12403         , m_te_id(0)
12404         , m_vs_id(0)
12405 {
12406         /* Left blank intentionally */
12407 }
12408
12409 /** Deinitializes all GL objects that may have been created during test execution */
12410 void NegativeTest6::deinit()
12411 {
12412         deinitIteration();
12413 }
12414
12415 /** Deinitializes all GL objects that may have been created during a single test
12416  *  iteration.
12417  ***/
12418 void NegativeTest6::deinitIteration()
12419 {
12420         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12421
12422         if (m_fs_id != 0)
12423         {
12424                 gl.deleteShader(m_fs_id);
12425
12426                 m_fs_id = 0;
12427         }
12428
12429         if (m_gs_id != 0)
12430         {
12431                 gl.deleteShader(m_gs_id);
12432
12433                 m_gs_id = 0;
12434         }
12435
12436         if (m_po_id != 0)
12437         {
12438                 gl.deleteProgram(m_po_id);
12439
12440                 m_po_id = 0;
12441         }
12442
12443         if (m_tc_id != 0)
12444         {
12445                 gl.deleteShader(m_tc_id);
12446
12447                 m_tc_id = 0;
12448         }
12449
12450         if (m_te_id != 0)
12451         {
12452                 gl.deleteShader(m_te_id);
12453
12454                 m_te_id = 0;
12455         }
12456
12457         if (m_vs_id != 0)
12458         {
12459                 gl.deleteShader(m_vs_id);
12460
12461                 m_vs_id = 0;
12462         }
12463 }
12464
12465 /** Executes a single test iteration.
12466  *
12467  *  If the iteration fails, m_has_test_passed will be set to false.
12468  *
12469  *  @param shader_stage Shader stage, for which two duplicate functions
12470  *                      (one additionally marked as subroutine) should
12471  *                      be defined.
12472  **/
12473 void NegativeTest6::executeIteration(const Utils::_shader_stage& shader_stage)
12474 {
12475         std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
12476         std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
12477         std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
12478         std::string te_body =
12479                 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
12480         std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
12481
12482         if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
12483                                                         DE_NULL, /* xfb_varyings */
12484                                                         DE_NULL, /* n_xfb_varyings */
12485                                                         &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
12486         {
12487                 /* None of the test programs should ever build successfully */
12488                 m_testCtx.getLog() << tcu::TestLog::Message
12489                                                    << "A program object, consisting of the following shaders, has linked"
12490                                                           " correctly. This is invalid, because one of the shaders defines two"
12491                                                           " functions with the same name, with an exception that one of the"
12492                                                           " functions is marked as a subroutine.\n"
12493                                                           "\n"
12494                                                           "Vertex shader:\n"
12495                                                           "\n"
12496                                                    << vs_body << "\n"
12497                                                                                  "Tessellation control shader:\n"
12498                                                                                  "\n"
12499                                                    << tc_body << "\n"
12500                                                                                  "Tessellation evaluation shader:\n"
12501                                                                                  "\n"
12502                                                    << te_body << "\n"
12503                                                                                  "Geometry shader:\n"
12504                                                                                  "\n"
12505                                                    << gs_body << "\n"
12506                                                                                  "Fragment shader:\n"
12507                                                                                  "\n"
12508                                                    << fs_body << tcu::TestLog::EndMessage;
12509
12510                 m_has_test_passed = false;
12511         }
12512 }
12513
12514 /** Retrieves fragment shader body.
12515  *
12516  *  @param include_invalid_declaration true if the shader should include duplicate function
12517  *                                     declaration.
12518  *
12519  *  @return Requested string.
12520  **/
12521 std::string NegativeTest6::getFragmentShaderBody(bool include_invalid_declaration) const
12522 {
12523         std::stringstream result_sstream;
12524
12525         result_sstream << "#version 400\n"
12526                                           "\n"
12527                                           "#extension GL_ARB_shader_subroutine : require\n"
12528                                           "\n";
12529
12530         if (include_invalid_declaration)
12531         {
12532                 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
12533                                                   "\n"
12534                                                   "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test)\n"
12535                                                   "{\n"
12536                                                   "    test = vec4(1, 2, 3, 4);\n"
12537                                                   "}\n"
12538                                                   "\n"
12539                                                   "void test_impl1(out vec4 test)\n"
12540                                                   "{\n"
12541                                                   "    test = vec4(2, 3, 4, 5);\n"
12542                                                   "}\n"
12543                                                   "\n"
12544                                                   "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
12545         };
12546
12547         result_sstream << "\n"
12548                                           "out vec4 result;\n"
12549                                           "\n"
12550                                           "void main()\n"
12551                                           "{\n";
12552
12553         if (include_invalid_declaration)
12554         {
12555                 result_sstream << "    test_subroutineFS(result);\n";
12556         }
12557         else
12558         {
12559                 result_sstream << "    result = vec4(0, 1, 2, 3);\n";
12560         }
12561
12562         result_sstream << "}\n";
12563
12564         return result_sstream.str();
12565 }
12566
12567 /** Retrieves geometry shader body.
12568  *
12569  *  @param include_invalid_declaration true if the shader should include duplicate function
12570  *                                     declaration.
12571  *
12572  *  @return Requested string.
12573  **/
12574 std::string NegativeTest6::getGeometryShaderBody(bool include_invalid_declaration) const
12575 {
12576         std::stringstream result_sstream;
12577
12578         result_sstream << "#version 400\n"
12579                                           "\n"
12580                                           "#extension GL_ARB_shader_subroutine : require\n"
12581                                           "\n"
12582                                           "layout (points)                   in;\n"
12583                                           "layout (points, max_vertices = 1) out;\n"
12584                                           "\n";
12585
12586         if (include_invalid_declaration)
12587         {
12588                 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
12589                                                   "\n"
12590                                                   "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test)\n"
12591                                                   "{\n"
12592                                                   "    test = vec4(1, 2, 3, 4);\n"
12593                                                   "}\n"
12594                                                   "\n"
12595                                                   "void test_impl1(out vec4 test)\n"
12596                                                   "{\n"
12597                                                   "    test = vec4(2, 3, 4, 5);\n"
12598                                                   "}\n"
12599                                                   "\n"
12600                                                   "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
12601         };
12602
12603         result_sstream << "\n"
12604                                           "void main()\n"
12605                                           "{\n";
12606
12607         if (include_invalid_declaration)
12608         {
12609                 result_sstream << "    test_subroutineGS(gl_Position);\n";
12610         }
12611         else
12612         {
12613                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12614         }
12615
12616         result_sstream << "EmitVertex();\n"
12617                                           "}\n";
12618
12619         return result_sstream.str();
12620 }
12621
12622 /** Retrieves tessellation control shader body.
12623  *
12624  *  @param include_invalid_declaration true if the shader should include duplicate function
12625  *                                     declaration.
12626  *
12627  *  @return Requested string.
12628  **/
12629 std::string NegativeTest6::getTessellationControlShaderBody(bool include_invalid_declaration) const
12630 {
12631         std::stringstream result_sstream;
12632
12633         result_sstream << "#version 400\n"
12634                                           "\n"
12635                                           "#extension GL_ARB_shader_subroutine : require\n"
12636                                           "\n"
12637                                           "layout (vertices = 4) out;\n"
12638                                           "\n";
12639
12640         if (include_invalid_declaration)
12641         {
12642                 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
12643                                                   "\n"
12644                                                   "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test)\n"
12645                                                   "{\n"
12646                                                   "    test = vec4(1, 2, 3, 4);\n"
12647                                                   "}\n"
12648                                                   "\n"
12649                                                   "void test_impl1(out vec4 test)\n"
12650                                                   "{\n"
12651                                                   "    test = vec4(2, 3, 4, 5);\n"
12652                                                   "}\n"
12653                                                   "\n"
12654                                                   "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
12655         };
12656
12657         result_sstream << "\n"
12658                                           "void main()\n"
12659                                           "{\n";
12660
12661         if (include_invalid_declaration)
12662         {
12663                 result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
12664         }
12665         else
12666         {
12667                 result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
12668         }
12669
12670         result_sstream << "}\n";
12671
12672         return result_sstream.str();
12673 }
12674
12675 /** Retrieves tessellation evaluation body.
12676  *
12677  *  @param include_invalid_declaration true if the shader should include duplicate function
12678  *                                     declaration.
12679  *
12680  *  @return Requested string.
12681  **/
12682 std::string NegativeTest6::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
12683 {
12684         std::stringstream result_sstream;
12685
12686         result_sstream << "#version 400\n"
12687                                           "\n"
12688                                           "#extension GL_ARB_shader_subroutine : require\n"
12689                                           "\n"
12690                                           "layout (quads) in;\n"
12691                                           "\n";
12692
12693         if (include_invalid_declaration)
12694         {
12695                 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
12696                                                   "\n"
12697                                                   "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test)\n"
12698                                                   "{\n"
12699                                                   "    test = vec4(1, 2, 3, 4);\n"
12700                                                   "}\n"
12701                                                   "\n"
12702                                                   "void test_impl1(out vec4 test)\n"
12703                                                   "{\n"
12704                                                   "    test = vec4(2, 3, 4, 5);\n"
12705                                                   "}\n"
12706                                                   "\n"
12707                                                   "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
12708         };
12709
12710         result_sstream << "\n"
12711                                           "void main()\n"
12712                                           "{\n";
12713
12714         if (include_invalid_declaration)
12715         {
12716                 result_sstream << "    test_subroutineTE(gl_Position);\n";
12717         }
12718         else
12719         {
12720                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12721         }
12722
12723         result_sstream << "}\n";
12724
12725         return result_sstream.str();
12726 }
12727
12728 /** Retrieves vertex shader body.
12729  *
12730  *  @param include_invalid_declaration true if the shader should include duplicate function
12731  *                                     declaration.
12732  *
12733  *  @return Requested string.
12734  **/
12735 std::string NegativeTest6::getVertexShaderBody(bool include_invalid_declaration) const
12736 {
12737         std::stringstream result_sstream;
12738
12739         result_sstream << "#version 400\n"
12740                                           "\n"
12741                                           "#extension GL_ARB_shader_subroutine : require\n"
12742                                           "\n";
12743
12744         if (include_invalid_declaration)
12745         {
12746                 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12747                                                   "\n"
12748                                                   "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test)\n"
12749                                                   "{\n"
12750                                                   "    test = vec4(1, 2, 3, 4);\n"
12751                                                   "}\n"
12752                                                   "\n"
12753                                                   "void test_impl1(out vec4 test)\n"
12754                                                   "{\n"
12755                                                   "    test = vec4(2, 3, 4, 5);\n"
12756                                                   "}\n"
12757                                                   "\n"
12758                                                   "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12759         };
12760
12761         result_sstream << "\n"
12762                                           "void main()\n"
12763                                           "{\n";
12764
12765         if (include_invalid_declaration)
12766         {
12767                 result_sstream << "    test_subroutineVS(gl_Position);\n";
12768         }
12769         else
12770         {
12771                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
12772         }
12773
12774         result_sstream << "}\n";
12775
12776         return result_sstream.str();
12777 }
12778
12779 /** Executes test iteration.
12780  *
12781  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12782  */
12783 tcu::TestNode::IterateResult NegativeTest6::iterate()
12784 {
12785         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12786         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12787         {
12788                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12789         }
12790
12791         /* Iterate over all shader stages. In each iteration, we will inject invalid
12792          * duplicate function declarations to iteration-specific shader stage. All other
12793          * shader stages will be assigned valid bodies. Test should fail if the program
12794          * links successfully.
12795          */
12796         for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12797                  shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12798         {
12799                 executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12800                 deinitIteration();
12801         } /* for (all shader stages) */
12802
12803         /* All done */
12804         if (m_has_test_passed)
12805         {
12806                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12807         }
12808         else
12809         {
12810                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12811         }
12812
12813         return STOP;
12814 }
12815
12816 /** Constructor
12817  *
12818  * @param context CTS context
12819  **/
12820 NegativeTest7::NegativeTest7(deqp::Context& context)
12821         : TestCase(context, "recursion", "Verify that it is not possible to build program with recursing subroutines")
12822         , m_program_id(0)
12823         , m_vertex_shader_id(0)
12824 {
12825         /* Nothing to be done here */
12826 }
12827
12828 /** Deinitializes all GL objects that may have been created during test execution
12829  *
12830  **/
12831 void NegativeTest7::deinit()
12832 {
12833         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12834
12835         if (m_program_id != 0)
12836         {
12837                 gl.deleteProgram(m_program_id);
12838
12839                 m_program_id = 0;
12840         }
12841
12842         if (m_vertex_shader_id != 0)
12843         {
12844                 gl.deleteShader(m_vertex_shader_id);
12845
12846                 m_vertex_shader_id = 0;
12847         }
12848 }
12849
12850 /** Executes test iteration.
12851  *
12852  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12853  **/
12854 tcu::TestNode::IterateResult NegativeTest7::iterate()
12855 {
12856         static const GLchar* vertex_shader_with_static_recursion =
12857                 "#version 400\n"
12858                 "\n"
12859                 "#extension GL_ARB_shader_subroutine : require\n"
12860                 "\n"
12861                 "precision highp float;\n"
12862                 "\n"
12863                 "subroutine vec4 routine_type(in vec4 data, in uint control);\n"
12864                 "\n"
12865                 "subroutine (routine_type) vec4 power_routine(in vec4 data, in uint control)\n"
12866                 "{\n"
12867                 "    if (0 != control)\n"
12868                 "    {\n"
12869                 "        return data * power_routine(data, control - 1);\n"
12870                 "    }\n"
12871                 "    else\n"
12872                 "    {\n"
12873                 "        return vec4(1, 1, 1, 1);\n"
12874                 "    }\n"
12875                 "}\n"
12876                 "\n"
12877                 "subroutine (routine_type) vec4 select_routine(in vec4 data, in uint control)\n"
12878                 "{\n"
12879                 "    if (0 == control)\n"
12880                 "    {\n"
12881                 "        return data.rrrr;\n"
12882                 "    }\n"
12883                 "    else if (1 == control)\n"
12884                 "    {\n"
12885                 "        return data.gggg;\n"
12886                 "    }\n"
12887                 "    else if (2 == control)\n"
12888                 "    {\n"
12889                 "        return data.bbbb;\n"
12890                 "    }\n"
12891                 "    else\n"
12892                 "    {\n"
12893                 "        return data.aaaa;\n"
12894                 "    }\n"
12895                 "}\n"
12896                 "\n"
12897                 "subroutine uniform routine_type routine;\n"
12898                 "\n"
12899                 "uniform vec4 uni_value;\n"
12900                 "uniform uint uni_control;\n"
12901                 "\n"
12902                 "out vec4 out_result;\n"
12903                 "\n"
12904                 "void main()\n"
12905                 "{\n"
12906                 "    out_result = routine(uni_value, uni_control);\n"
12907                 "}\n"
12908                 "\n";
12909
12910         static const GLchar* vertex_shader_with_dynamic_recursion =
12911                 "#version 400\n"
12912                 "\n"
12913                 "#extension GL_ARB_shader_subroutine : require\n"
12914                 "\n"
12915                 "precision highp float;\n"
12916                 "\n"
12917                 "subroutine vec4 routine_type(in vec4 data);\n"
12918                 "\n"
12919                 "subroutine uniform routine_type routine;\n"
12920                 "\n"
12921                 "subroutine (routine_type) vec4 div_by_2(in vec4 data)\n"
12922                 "{\n"
12923                 "    return data / 2;\n"
12924                 "}\n"
12925                 "\n"
12926                 "subroutine (routine_type) vec4 div_routine_result_by_2(in vec4 data)\n"
12927                 "{\n"
12928                 "    return routine(data) / 2;\n"
12929                 "}\n"
12930                 "\n"
12931                 "uniform vec4 uni_value;\n"
12932                 "\n"
12933                 "out vec4 out_result;\n"
12934                 "\n"
12935                 "void main()\n"
12936                 "{\n"
12937                 "    out_result = routine(uni_value);\n"
12938                 "}\n"
12939                 "\n";
12940
12941         static const GLchar* vertex_shader_with_subroutine_function_recursion =
12942                 "#version 400\n"
12943                 "\n"
12944                 "#extension GL_ARB_shader_subroutine : require\n"
12945                 "\n"
12946                 "precision highp float;\n"
12947                 "\n"
12948                 "subroutine vec4 routine_type(in vec4 data);\n"
12949                 "\n"
12950                 "subroutine uniform routine_type routine;\n"
12951                 "\n"
12952                 "vec4 function(in vec4 data)\n"
12953                 "{\n"
12954                 "    return routine(data) + vec4(0.5, 0.5, 0.5, 0.5);\n"
12955                 "}\n"
12956                 "\n"
12957                 "subroutine (routine_type) vec4 routine_a(in vec4 data)\n"
12958                 "{\n"
12959                 "    return function(data) / 2;\n"
12960                 "}\n"
12961                 "\n"
12962                 "subroutine (routine_type) vec4 routine_b(in vec4 data)\n"
12963                 "{\n"
12964                 "    return routine_a(data) * 2;\n"
12965                 "}\n"
12966                 "\n"
12967                 "uniform vec4 uni_value;\n"
12968                 "\n"
12969                 "out vec4 out_result;\n"
12970                 "\n"
12971                 "void main()\n"
12972                 "{\n"
12973                 "    out_result = routine(uni_value);\n"
12974                 "}\n"
12975                 "\n";
12976
12977         bool result = true;
12978
12979         if (false == test(vertex_shader_with_subroutine_function_recursion, "routine_a"))
12980         {
12981                 result = false;
12982         }
12983
12984         if (false == test(vertex_shader_with_dynamic_recursion, "div_routine_result_by_2"))
12985         {
12986                 result = false;
12987         }
12988
12989         if (false == test(vertex_shader_with_static_recursion, "power_routine"))
12990         {
12991                 result = false;
12992         }
12993
12994         /* Set result */
12995         if (true == result)
12996         {
12997                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12998         }
12999         else
13000         {
13001                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13002         }
13003
13004         /* Done */
13005         return tcu::TestNode::STOP;
13006 }
13007
13008 /** Try to build program from vertex shader code.
13009  *
13010  * @param vertex_shader_code        Source code of vertex shader
13011  * @param name_of_recursive_routine Name of subroutine that should cause link failure due to recursion
13012  *
13013  * @return true build process failed, false otherwise
13014  **/
13015 bool NegativeTest7::test(const GLchar* vertex_shader_code, const GLchar* name_of_recursive_routine)
13016 {
13017         const glw::Functions& gl                   = m_context.getRenderContext().getFunctions();
13018         bool                              result           = true;
13019         static const GLchar*  varying_name = "out_result";
13020
13021         /* Try to build program */
13022         if (true == Utils::buildProgram(gl, vertex_shader_code, "", "", "", "", &varying_name /* varying_names */,
13023                                                                         1 /* n_varyings */, &m_vertex_shader_id, 0, 0, 0, 0, &m_program_id))
13024         {
13025                 /* Success is considered an error */
13026
13027                 Utils::program program(m_context);
13028                 GLuint             index = 0;
13029
13030                 program.build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0);
13031
13032                 /* Verify that recursive subroutine is active */
13033                 try
13034                 {
13035                         index = program.getSubroutineIndex(name_of_recursive_routine, GL_VERTEX_SHADER);
13036                 }
13037                 catch (const std::exception& exc)
13038                 {
13039                         /* Something wrong with shader or compilation */
13040                         m_context.getTestContext().getLog()
13041                                 << tcu::TestLog::Message << "It is expected that subroutine: \n"
13042                                 << name_of_recursive_routine
13043                                 << " is considered active. This subroutine is potentially recursive and should cause link failure."
13044                                 << tcu::TestLog::EndMessage;
13045
13046                         throw exc;
13047                 }
13048
13049                 /* Subsoutine is active, however linking should fail */
13050                 m_context.getTestContext().getLog()
13051                         << tcu::TestLog::Message << "Error. Program with potentially recursive subroutine, "
13052                         << name_of_recursive_routine << ", which is active, index: " << index << ", has been built successfully.\n"
13053                         << vertex_shader_code << tcu::TestLog::EndMessage;
13054
13055                 result = false;
13056         }
13057
13058         /* Delete program and shader */
13059         deinit();
13060
13061         /* Done */
13062         return result;
13063 }
13064
13065 /** Constructor.
13066  *
13067  *  @param context Rendering context.
13068  *
13069  **/
13070 NegativeTest8::NegativeTest8(deqp::Context& context)
13071         : TestCase(context, "subroutine_wo_body", "Verifies that a compile- or link-time error occurs if a function "
13072                                                                                           "declared as a subroutine does not include a body.")
13073         , m_fs_id(0)
13074         , m_gs_id(0)
13075         , m_has_test_passed(true)
13076         , m_po_id(0)
13077         , m_tc_id(0)
13078         , m_te_id(0)
13079         , m_vs_id(0)
13080 {
13081         /* Left blank intentionally */
13082 }
13083
13084 /** Deinitializes all GL objects that may have been created during test execution */
13085 void NegativeTest8::deinit()
13086 {
13087         deinitIteration();
13088 }
13089
13090 /** Deinitializes all GL objects that may have been created during a single test
13091  *  iteration.
13092  ***/
13093 void NegativeTest8::deinitIteration()
13094 {
13095         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13096
13097         if (m_fs_id != 0)
13098         {
13099                 gl.deleteShader(m_fs_id);
13100
13101                 m_fs_id = 0;
13102         }
13103
13104         if (m_gs_id != 0)
13105         {
13106                 gl.deleteShader(m_gs_id);
13107
13108                 m_gs_id = 0;
13109         }
13110
13111         if (m_po_id != 0)
13112         {
13113                 gl.deleteProgram(m_po_id);
13114
13115                 m_po_id = 0;
13116         }
13117
13118         if (m_tc_id != 0)
13119         {
13120                 gl.deleteShader(m_tc_id);
13121
13122                 m_tc_id = 0;
13123         }
13124
13125         if (m_te_id != 0)
13126         {
13127                 gl.deleteShader(m_te_id);
13128
13129                 m_te_id = 0;
13130         }
13131
13132         if (m_vs_id != 0)
13133         {
13134                 gl.deleteShader(m_vs_id);
13135
13136                 m_vs_id = 0;
13137         }
13138 }
13139
13140 /** Executes a single test iteration.
13141  *
13142  *  If the iteration fails, m_has_test_passed will be set to false.
13143  *
13144  *  @param shader_stage Shader stage, for which two duplicate functions
13145  *                      (one additionally marked as subroutine) should
13146  *                      be defined.
13147  **/
13148 void NegativeTest8::executeIteration(const Utils::_shader_stage& shader_stage)
13149 {
13150         std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
13151         std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
13152         std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
13153         std::string te_body =
13154                 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
13155         std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
13156
13157         if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
13158                                                         DE_NULL, /* xfb_varyings */
13159                                                         DE_NULL, /* n_xfb_varyings */
13160                                                         &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
13161         {
13162                 /* None of the test programs should ever build successfully */
13163                 m_testCtx.getLog() << tcu::TestLog::Message
13164                                                    << "A program object consisting of FS+GS+TC+TE+VS stages has linked successfully, "
13165                                                           "even though one of the shaders only defines a subroutine that lacks any body."
13166                                                           "\n"
13167                                                           "Vertex shader:\n"
13168                                                           "\n"
13169                                                    << vs_body << "\n"
13170                                                                                  "Tessellation control shader:\n"
13171                                                                                  "\n"
13172                                                    << tc_body << "\n"
13173                                                                                  "Tessellation evaluation shader:\n"
13174                                                                                  "\n"
13175                                                    << te_body << "\n"
13176                                                                                  "Geometry shader:\n"
13177                                                                                  "\n"
13178                                                    << gs_body << "\n"
13179                                                                                  "Fragment shader:\n"
13180                                                                                  "\n"
13181                                                    << fs_body << tcu::TestLog::EndMessage;
13182
13183                 m_has_test_passed = false;
13184         }
13185 }
13186
13187 /** Retrieves fragment shader body.
13188  *
13189  *  @param include_invalid_declaration true if a subroutine prototype should be included in
13190  *                                     the shader, false to skip it.
13191  *
13192  *  @return Requested string.
13193  **/
13194 std::string NegativeTest8::getFragmentShaderBody(bool include_invalid_declaration) const
13195 {
13196         std::stringstream result_sstream;
13197
13198         result_sstream << "#version 400\n"
13199                                           "\n"
13200                                           "#extension GL_ARB_shader_subroutine : require\n"
13201                                           "\n";
13202
13203         if (include_invalid_declaration)
13204         {
13205                 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
13206                                                   "\n"
13207                                                   "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test);\n"
13208                                                   "\n"
13209                                                   "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
13210         };
13211
13212         result_sstream << "\n"
13213                                           "out vec4 result;\n"
13214                                           "\n"
13215                                           "void main()\n"
13216                                           "{\n";
13217
13218         if (include_invalid_declaration)
13219         {
13220                 result_sstream << "    test_subroutineFS(result);\n";
13221         }
13222         else
13223         {
13224                 result_sstream << "    result = vec4(0, 1, 2, 3);\n";
13225         }
13226
13227         result_sstream << "}\n";
13228
13229         return result_sstream.str();
13230 }
13231
13232 /** Retrieves geometry shader body.
13233  *
13234  *  @param include_invalid_declaration true if a subroutine prototype should be included in
13235  *                                     the shader, false to skip it.
13236  *
13237  *  @return Requested string.
13238  **/
13239 std::string NegativeTest8::getGeometryShaderBody(bool include_invalid_declaration) const
13240 {
13241         std::stringstream result_sstream;
13242
13243         result_sstream << "#version 400\n"
13244                                           "\n"
13245                                           "#extension GL_ARB_shader_subroutine : require\n"
13246                                           "\n"
13247                                           "layout (points)                   in;\n"
13248                                           "layout (points, max_vertices = 1) out;\n"
13249                                           "\n";
13250
13251         if (include_invalid_declaration)
13252         {
13253                 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
13254                                                   "\n"
13255                                                   "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test);\n"
13256                                                   "\n"
13257                                                   "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
13258         };
13259
13260         result_sstream << "\n"
13261                                           "void main()\n"
13262                                           "{\n";
13263
13264         if (include_invalid_declaration)
13265         {
13266                 result_sstream << "    test_subroutineGS(gl_Position);\n";
13267         }
13268         else
13269         {
13270                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
13271         }
13272
13273         result_sstream << "EmitVertex();\n"
13274                                           "}\n";
13275
13276         return result_sstream.str();
13277 }
13278
13279 /** Retrieves tessellation control shader body.
13280  *
13281  *  @param include_invalid_declaration true if a subroutine prototype should be included in
13282  *                                     the shader, false to skip it.
13283  *
13284  *  @return Requested string.
13285  **/
13286 std::string NegativeTest8::getTessellationControlShaderBody(bool include_invalid_declaration) const
13287 {
13288         std::stringstream result_sstream;
13289
13290         result_sstream << "#version 400\n"
13291                                           "\n"
13292                                           "#extension GL_ARB_shader_subroutine : require\n"
13293                                           "\n"
13294                                           "layout (vertices = 4) out;\n"
13295                                           "\n";
13296
13297         if (include_invalid_declaration)
13298         {
13299                 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
13300                                                   "\n"
13301                                                   "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test);\n"
13302                                                   "\n"
13303                                                   "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
13304         };
13305
13306         result_sstream << "\n"
13307                                           "void main()\n"
13308                                           "{\n";
13309
13310         if (include_invalid_declaration)
13311         {
13312                 result_sstream << "    test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
13313         }
13314         else
13315         {
13316                 result_sstream << "    gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
13317         }
13318
13319         result_sstream << "}\n";
13320
13321         return result_sstream.str();
13322 }
13323
13324 /** Retrieves tessellation evaluation body.
13325  *
13326  *  @param include_invalid_declaration true if a subroutine prototype should be included in
13327  *                                     the shader, false to skip it.
13328  *
13329  *  @return Requested string.
13330  **/
13331 std::string NegativeTest8::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
13332 {
13333         std::stringstream result_sstream;
13334
13335         result_sstream << "#version 400\n"
13336                                           "\n"
13337                                           "#extension GL_ARB_shader_subroutine : require\n"
13338                                           "\n"
13339                                           "layout (quads) in;\n"
13340                                           "\n";
13341
13342         if (include_invalid_declaration)
13343         {
13344                 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
13345                                                   "\n"
13346                                                   "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test);\n"
13347                                                   "\n"
13348                                                   "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
13349         };
13350
13351         result_sstream << "\n"
13352                                           "void main()\n"
13353                                           "{\n";
13354
13355         if (include_invalid_declaration)
13356         {
13357                 result_sstream << "    test_subroutineTE(gl_Position);\n";
13358         }
13359         else
13360         {
13361                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
13362         }
13363
13364         result_sstream << "}\n";
13365
13366         return result_sstream.str();
13367 }
13368
13369 /** Retrieves vertex shader body.
13370  *
13371  *  @param include_invalid_declaration true if a subroutine prototype should be included in
13372  *                                     the shader, false to skip it.
13373  *
13374  *  @return Requested string.
13375  **/
13376 std::string NegativeTest8::getVertexShaderBody(bool include_invalid_declaration) const
13377 {
13378         std::stringstream result_sstream;
13379
13380         result_sstream << "#version 400\n"
13381                                           "\n"
13382                                           "#extension GL_ARB_shader_subroutine : require\n"
13383                                           "\n";
13384
13385         if (include_invalid_declaration)
13386         {
13387                 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
13388                                                   "\n"
13389                                                   "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test);\n"
13390                                                   "\n"
13391                                                   "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
13392         };
13393
13394         result_sstream << "\n"
13395                                           "void main()\n"
13396                                           "{\n";
13397
13398         if (include_invalid_declaration)
13399         {
13400                 result_sstream << "    test_subroutineVS(gl_Position);\n";
13401         }
13402         else
13403         {
13404                 result_sstream << "    gl_Position = vec4(0, 1, 2, 3);\n";
13405         }
13406
13407         result_sstream << "}\n";
13408
13409         return result_sstream.str();
13410 }
13411
13412 /** Executes test iteration.
13413  *
13414  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13415  */
13416 tcu::TestNode::IterateResult NegativeTest8::iterate()
13417 {
13418         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13419         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13420         {
13421                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13422         }
13423
13424         /* Iterate over all shader stages. For each iteration, iteration-specific shader stage
13425          * will feature an invalid subroutine definition. Other shader stages will be assigned
13426          * valid bodies. The test fails if a program built of such shaders links successfully.
13427          */
13428         for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
13429                  shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
13430         {
13431                 executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
13432                 deinitIteration();
13433         } /* for (all shader stages) */
13434
13435         /* All done */
13436         if (m_has_test_passed)
13437         {
13438                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13439         }
13440         else
13441         {
13442                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13443         }
13444
13445         return STOP;
13446 }
13447
13448 /** Constructor.
13449  *
13450  *  @param context Rendering context.
13451  **/
13452 NegativeTest9::NegativeTest9(deqp::Context& context)
13453         : TestCase(context, "subroutines_cannot_be_assigned_float_int_values_or_be_compared",
13454                            "Make sure it is not possible to assign float/int to subroutine "
13455                            "uniform and that subroutine uniform values cannot be compared.")
13456         , m_has_test_passed(true)
13457         , m_po_id(0)
13458         , m_vs_id(0)
13459 {
13460         /* Left blank intentionally */
13461 }
13462
13463 /** Deinitializes any GL objects that may have been created during
13464  *  test execution.
13465  **/
13466 void NegativeTest9::deinit()
13467 {
13468         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13469
13470         if (m_po_id != 0)
13471         {
13472                 gl.deleteProgram(m_po_id);
13473
13474                 m_po_id = 0;
13475         }
13476
13477         if (m_vs_id != 0)
13478         {
13479                 gl.deleteShader(m_vs_id);
13480
13481                 m_vs_id = 0;
13482         }
13483 }
13484
13485 /** Returns a literal corresponding to user-specified test case enum.
13486  *
13487  *  @param test_case As per description.
13488  *
13489  *  @return Requested string.
13490  **/
13491 std::string NegativeTest9::getTestCaseString(const _test_case& test_case)
13492 {
13493         std::string result = "?";
13494
13495         switch (test_case)
13496         {
13497         case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13498                 result = "TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
13499                 break;
13500         case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13501                 result = "TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
13502                 break;
13503         case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
13504                 result = "TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON";
13505                 break;
13506         default:
13507                 break;
13508         }
13509
13510         return result;
13511 }
13512
13513 /** Retrieves vertex shader body for user-specified test case.
13514  *
13515  *  @param test_case As per description.
13516  *
13517  *  @return Requested string.
13518  **/
13519 std::string NegativeTest9::getVertexShader(const _test_case& test_case)
13520 {
13521         std::stringstream result_sstream;
13522
13523         /* Form pre-amble */
13524         result_sstream << "#version 400\n"
13525                                           "\n"
13526                                           "#extension GL_ARB_shader_subroutine : require\n"
13527                                           "\n"
13528                                           /* Define a subroutine */
13529                                           "subroutine void subroutineType(inout vec4 test);\n"
13530                                           "\n"
13531                                           "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13532                                           "{\n"
13533                                           "    test += vec4(0, 1, 2, 3);\n"
13534                                           "}\n"
13535                                           "\n"
13536                                           "subroutine uniform subroutineType function;\n"
13537                                           "\n";
13538
13539         /* Include case-specific implementation */
13540         switch (test_case)
13541         {
13542         case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13543         {
13544                 result_sstream << "void main()\n"
13545                                                   "{\n"
13546                                                   "    function = 1.0f;\n"
13547                                                   "\n"
13548                                                   "    function(gl_Position);\n"
13549                                                   "}\n";
13550
13551                 break;
13552         }
13553
13554         case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13555         {
13556                 result_sstream << "void main()\n"
13557                                                   "{\n"
13558                                                   "    function = 1;\n"
13559                                                   "\n"
13560                                                   "    function(gl_Position);\n"
13561                                                   "}\n";
13562
13563                 break;
13564         }
13565
13566         case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
13567         {
13568                 result_sstream << "subroutine uniform subroutineType function2;\n"
13569                                                   "\n"
13570                                                   "void main()\n"
13571                                                   "{\n"
13572                                                   "    if (function == function2)\n"
13573                                                   "    {\n"
13574                                                   "        function(gl_Position);\n"
13575                                                   "    }\n"
13576                                                   "    else\n"
13577                                                   "    {\n"
13578                                                   "        function2(gl_Position);\n"
13579                                                   "    }\n"
13580                                                   "}\n";
13581
13582                 break;
13583         }
13584
13585         default:
13586                 break;
13587         } /* switch (test_case) */
13588
13589         /* Done */
13590         return result_sstream.str();
13591 }
13592
13593 /** Executes test iteration.
13594  *
13595  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13596  */
13597 tcu::TestNode::IterateResult NegativeTest9::iterate()
13598 {
13599         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13600
13601         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13602         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13603         {
13604                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13605         }
13606
13607         /* Iterate over all test cases */
13608         for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
13609         {
13610                 /* Try to build a program object using invalid vertex shader, specific to the
13611                  * iteration we're currently in */
13612                 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
13613
13614                 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
13615                                                                                                   "",                            /* te_body */
13616                                                                                                   "",                            /* gs_body */
13617                                                                                                   "",                            /* fs_body */
13618                                                                                                   DE_NULL,                       /* xfb_varyings */
13619                                                                                                   0,                             /* n_xfb_varyings */
13620                                                                                                   &m_vs_id, DE_NULL, /* out_tc_id */
13621                                                                                                   DE_NULL,                       /* out_te_id */
13622                                                                                                   DE_NULL,                       /* out_gs_id */
13623                                                                                                   DE_NULL,                       /* out_fs_id */
13624                                                                                                   &m_po_id))
13625                 {
13626                         m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13627                                                            << getTestCaseString(static_cast<_test_case>(test_case))
13628                                                            << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
13629
13630                         m_has_test_passed = false;
13631                 }
13632
13633                 /* Delete any objects that may have been created */
13634                 deinit();
13635         } /* for (all test cases) */
13636
13637         /** All done */
13638         if (m_has_test_passed)
13639         {
13640                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13641         }
13642         else
13643         {
13644                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13645         }
13646
13647         return STOP;
13648 }
13649
13650 /** Constructor.
13651  *
13652  *  @param context Rendering context.
13653  **/
13654 NegativeTest10::NegativeTest10(deqp::Context& context)
13655         : TestCase(context, "function_overloading_forbidden_for_subroutines",
13656                            "Check that an overloaded function cannot be declared with subroutine and "
13657                            "a program will fail to compile or link if any shader or stage contains"
13658                            " two or more  functions with the same name if the name is associated with"
13659                            " a subroutine type.")
13660         , m_has_test_passed(true)
13661         , m_fs_id(0)
13662         , m_gs_id(0)
13663         , m_po_id(0)
13664         , m_tc_id(0)
13665         , m_te_id(0)
13666         , m_vs_id(0)
13667 {
13668         /* Left blank intentionally */
13669 }
13670
13671 /** Deinitializes any GL objects that may have been created during
13672  *  test execution.
13673  **/
13674 void NegativeTest10::deinit()
13675 {
13676         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13677
13678         if (m_fs_id != 0)
13679         {
13680                 gl.deleteShader(m_fs_id);
13681
13682                 m_fs_id = 0;
13683         }
13684
13685         if (m_gs_id != 0)
13686         {
13687                 gl.deleteShader(m_gs_id);
13688
13689                 m_gs_id = 0;
13690         }
13691
13692         if (m_po_id != 0)
13693         {
13694                 gl.deleteProgram(m_po_id);
13695
13696                 m_po_id = 0;
13697         }
13698
13699         if (m_tc_id != 0)
13700         {
13701                 gl.deleteShader(m_tc_id);
13702
13703                 m_tc_id = 0;
13704         }
13705
13706         if (m_te_id != 0)
13707         {
13708                 gl.deleteShader(m_te_id);
13709
13710                 m_te_id = 0;
13711         }
13712
13713         if (m_vs_id != 0)
13714         {
13715                 gl.deleteShader(m_vs_id);
13716
13717                 m_vs_id = 0;
13718         }
13719 }
13720
13721 /** Retrieves fragment shader that should be used for the purpose of the test.
13722  *  An overloaded version of a subroutine function is inserted if
13723  *  @param include_duplicate_function flag is set to true.
13724  *
13725  *  @param include_duplicate_function As per description.
13726  *
13727  *  @return Requested string.
13728  **/
13729 std::string NegativeTest10::getFragmentShader(bool include_duplicate_function)
13730 {
13731         std::stringstream result_sstream;
13732
13733         result_sstream << "#version 400\n"
13734                                           "\n"
13735                                           "#extension GL_ARB_shader_subroutine : require\n"
13736                                           "\n"
13737                                           "subroutine void subroutineType(inout vec4 test);\n"
13738                                           "\n"
13739                                           "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13740                                           "{\n"
13741                                           "    test = vec4(2, 3, 4, 5);\n"
13742                                           "}\n"
13743                                           "\n"
13744                                           "subroutine uniform subroutineType function;\n"
13745                                           "out vec4 result;\n"
13746                                           "\n";
13747
13748         if (include_duplicate_function)
13749         {
13750                 result_sstream << "void test_function(inout vec4 test)\n"
13751                                                   "{\n"
13752                                                   "    test = vec4(3, 4, 5, 6);\n"
13753                                                   "}\n"
13754                                                   "\n";
13755         }
13756
13757         result_sstream << "void main()\n"
13758                                           "{\n"
13759                                           "    test_function(result);\n"
13760                                           "}\n";
13761
13762         return result_sstream.str();
13763 }
13764
13765 /** Retrieves geometry shader that should be used for the purpose of the test.
13766  *  An overloaded version of a subroutine function is inserted if
13767  *  @param include_duplicate_function flag is set to true.
13768  *
13769  *  @param include_duplicate_function As per description.
13770  *
13771  *  @return Requested string.
13772  **/
13773 std::string NegativeTest10::getGeometryShader(bool include_duplicate_function)
13774 {
13775         std::stringstream result_sstream;
13776
13777         result_sstream << "#version 400\n"
13778                                           "\n"
13779                                           "#extension GL_ARB_shader_subroutine : require\n"
13780                                           "\n"
13781                                           "layout (triangles)                        in;\n"
13782                                           "layout (triangle_strip, max_vertices = 4) out;\n"
13783                                           "\n"
13784                                           "subroutine void subroutineType(inout vec4 test);\n"
13785                                           "\n"
13786                                           "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13787                                           "{\n"
13788                                           "    test = vec4(2, 3, 4, 5);\n"
13789                                           "}\n"
13790                                           "\n"
13791                                           "subroutine uniform subroutineType function;\n"
13792                                           "\n";
13793
13794         if (include_duplicate_function)
13795         {
13796                 result_sstream << "void test_function(inout vec4 test)\n"
13797                                                   "{\n"
13798                                                   "    test = vec4(3, 4, 5, 6);\n"
13799                                                   "}\n"
13800                                                   "\n";
13801         }
13802
13803         result_sstream << "void main()\n"
13804                                           "{\n"
13805                                           "    function(gl_Position);\n"
13806                                           "    EmitVertex();\n"
13807                                           "    EndPrimitive();\n"
13808                                           "}\n";
13809
13810         return result_sstream.str();
13811 }
13812
13813 /** Retrieves tess control shader that should be used for the purpose of the test.
13814  *  An overloaded version of a subroutine function is inserted if
13815  *  @param include_duplicate_function flag is set to true.
13816  *
13817  *  @param include_duplicate_function As per description.
13818  *
13819  *  @return Requested string.
13820  **/
13821 std::string NegativeTest10::getTessellationControlShader(bool include_duplicate_function)
13822 {
13823         std::stringstream result_sstream;
13824
13825         result_sstream << "#version 400\n"
13826                                           "\n"
13827                                           "#extension GL_ARB_shader_subroutine : require\n"
13828                                           "\n"
13829                                           "layout (vertices = 4) out;\n"
13830                                           "\n"
13831                                           "subroutine void subroutineType(inout vec4 test);\n"
13832                                           "\n"
13833                                           "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13834                                           "{\n"
13835                                           "    test = vec4(2, 3, 4, 5);\n"
13836                                           "}\n"
13837                                           "\n"
13838                                           "subroutine uniform subroutineType function;\n"
13839                                           "\n";
13840
13841         if (include_duplicate_function)
13842         {
13843                 result_sstream << "void test_function(inout vec4 test)\n"
13844                                                   "{\n"
13845                                                   "    test = vec4(3, 4, 5, 6);\n"
13846                                                   "}\n"
13847                                                   "\n";
13848         }
13849
13850         result_sstream << "void main()\n"
13851                                           "{\n"
13852                                           "    vec4 temp;\n"
13853                                           "\n"
13854                                           "    function(temp);\n"
13855                                           "\n"
13856                                           "    gl_out[gl_InvocationID].gl_Position = temp;\n"
13857                                           "    gl_TessLevelInner[0]                = temp.x;\n"
13858                                           "    gl_TessLevelInner[1]                = temp.y;\n"
13859                                           "    gl_TessLevelOuter[0]                = temp.z;\n"
13860                                           "    gl_TessLevelOuter[1]                = temp.w;\n"
13861                                           "    gl_TessLevelOuter[2]                = temp.x;\n"
13862                                           "    gl_TessLevelOuter[3]                = temp.y;\n"
13863                                           "}\n";
13864
13865         return result_sstream.str();
13866 }
13867
13868 /** Retrieves tess evaluation shader that should be used for the purpose of the test.
13869  *  An overloaded version of a subroutine function is inserted if
13870  *  @param include_duplicate_function flag is set to true.
13871  *
13872  *  @param include_duplicate_function As per description.
13873  *
13874  *  @return Requested string.
13875  **/
13876 std::string NegativeTest10::getTessellationEvaluationShader(bool include_duplicate_function)
13877 {
13878         std::stringstream result_sstream;
13879
13880         result_sstream << "#version 400\n"
13881                                           "\n"
13882                                           "#extension GL_ARB_shader_subroutine : require\n"
13883                                           "\n"
13884                                           "layout (quads) in;\n"
13885                                           "\n"
13886                                           "subroutine void subroutineType(inout vec4 test);\n"
13887                                           "\n"
13888                                           "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13889                                           "{\n"
13890                                           "    test = vec4(2, 3, 4, 5);\n"
13891                                           "}\n"
13892                                           "\n"
13893                                           "subroutine uniform subroutineType function;\n"
13894                                           "\n";
13895
13896         if (include_duplicate_function)
13897         {
13898                 result_sstream << "void test_function(inout vec4 test)\n"
13899                                                   "{\n"
13900                                                   "    test = vec4(3, 4, 5, 6);\n"
13901                                                   "}\n"
13902                                                   "\n";
13903         }
13904
13905         result_sstream << "void main()\n"
13906                                           "{\n"
13907                                           "    vec4 temp;\n"
13908                                           "\n"
13909                                           "    function(temp);\n"
13910                                           "\n"
13911                                           "    gl_Position = temp;\n"
13912                                           "}\n";
13913
13914         return result_sstream.str();
13915 }
13916
13917 /** Retrieves vertex shader that should be used for the purpose of the test.
13918  *  An overloaded version of a subroutine function is inserted if
13919  *  @param include_duplicate_function flag is set to true.
13920  *
13921  *  @param include_duplicate_function As per description.
13922  *
13923  *  @return Requested string.
13924  **/
13925 std::string NegativeTest10::getVertexShader(bool include_duplicate_function)
13926 {
13927         std::stringstream result_sstream;
13928
13929         result_sstream << "#version 400\n"
13930                                           "\n"
13931                                           "#extension GL_ARB_shader_subroutine : require\n"
13932                                           "\n"
13933                                           "subroutine void subroutineType(inout vec4 test);\n"
13934                                           "\n"
13935                                           "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13936                                           "{\n"
13937                                           "    test = vec4(2, 3, 4, 5);\n"
13938                                           "}\n"
13939                                           "\n"
13940                                           "subroutine uniform subroutineType function;\n"
13941                                           "\n";
13942
13943         if (include_duplicate_function)
13944         {
13945                 result_sstream << "void test_function(inout vec4 test)\n"
13946                                                   "{\n"
13947                                                   "    test = vec4(3, 4, 5, 6);\n"
13948                                                   "}\n"
13949                                                   "\n";
13950         }
13951
13952         result_sstream << "void main()\n"
13953                                           "{\n"
13954                                           "    function(gl_Position);\n"
13955                                           "}\n";
13956
13957         return result_sstream.str();
13958 }
13959
13960 /** Fills m_test_cases field with test case descriptors */
13961 void NegativeTest10::initTestCases()
13962 {
13963         /* For each test case, only one shader stage should define a function that
13964          * has already been defined as a subroutine. */
13965         for (int offending_shader_stage_it = static_cast<int>(Utils::SHADER_STAGE_FIRST);
13966                  offending_shader_stage_it != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++offending_shader_stage_it)
13967         {
13968                 Utils::_shader_stage offending_shader_stage = static_cast<Utils::_shader_stage>(offending_shader_stage_it);
13969                 /* Form the test case descriptor */
13970                 std::stringstream name_sstream;
13971                 _test_case                test_case;
13972
13973                 name_sstream << "Broken shader stage:" << Utils::getShaderStageString(offending_shader_stage);
13974
13975                 test_case.fs_body = getFragmentShader(offending_shader_stage == Utils::SHADER_STAGE_FRAGMENT);
13976                 test_case.gs_body = getGeometryShader(offending_shader_stage == Utils::SHADER_STAGE_GEOMETRY);
13977                 test_case.name  = name_sstream.str();
13978                 test_case.tc_body =
13979                         getTessellationControlShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
13980                 test_case.te_body =
13981                         getTessellationEvaluationShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
13982                 test_case.vs_body = getVertexShader(offending_shader_stage == Utils::SHADER_STAGE_VERTEX);
13983
13984                 m_test_cases.push_back(test_case);
13985         }
13986 }
13987
13988 /** Executes test iteration.
13989  *
13990  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13991  */
13992 tcu::TestNode::IterateResult NegativeTest10::iterate()
13993 {
13994         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13995
13996         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13997         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13998         {
13999                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14000         }
14001
14002         /* Form test cases */
14003         initTestCases();
14004
14005         /* Iterate over all test cases */
14006         for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
14007                  ++test_case_iterator)
14008         {
14009                 const _test_case& test_case = *test_case_iterator;
14010
14011                 /* Try to build the program object */
14012                 if (ShaderSubroutine::Utils::buildProgram(gl, test_case.vs_body, test_case.tc_body, test_case.te_body,
14013                                                                                                   test_case.gs_body, test_case.fs_body, DE_NULL, /* xfb_varyings */
14014                                                                                                   0,                                                                                     /* n_xfb_varyings */
14015                                                                                                   &m_vs_id, (test_case.tc_body.length() > 0) ? &m_tc_id : DE_NULL,
14016                                                                                                   (test_case.te_body.length() > 0) ? &m_te_id : DE_NULL,
14017                                                                                                   (test_case.gs_body.length() > 0) ? &m_gs_id : DE_NULL,
14018                                                                                                   (test_case.fs_body.length() > 0) ? &m_fs_id : DE_NULL, &m_po_id))
14019                 {
14020                         m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14021                                                            << test_case.name << "] test case, even though it was invalid."
14022                                                            << tcu::TestLog::EndMessage;
14023
14024                         m_has_test_passed = false;
14025                 }
14026
14027                 /* Delete any objects that may have been created */
14028                 deinit();
14029         } /* for (all test cases) */
14030
14031         /** All done */
14032         if (m_has_test_passed)
14033         {
14034                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14035         }
14036         else
14037         {
14038                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14039         }
14040
14041         return STOP;
14042 }
14043
14044 /** Constructor.
14045  *
14046  *  @param context Rendering context.
14047  **/
14048 NegativeTest11::NegativeTest11(deqp::Context& context)
14049         : TestCase(context, "subroutine_uniforms_used_for_sampling_atomic_image_functions",
14050                            "Tries to use subroutine uniforms in invalid way in sampling, "
14051                            "atomic and image functions. Verifies that compile- or link-time "
14052                            "error occurs.")
14053         , m_has_test_passed(true)
14054         , m_po_id(0)
14055         , m_vs_id(0)
14056 {
14057         /* Left blank intentionally */
14058 }
14059
14060 /** Deinitializes any GL objects that may have been created during
14061  *  test execution.
14062  **/
14063 void NegativeTest11::deinit()
14064 {
14065         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14066
14067         if (m_po_id != 0)
14068         {
14069                 gl.deleteProgram(m_po_id);
14070
14071                 m_po_id = 0;
14072         }
14073
14074         if (m_vs_id != 0)
14075         {
14076                 gl.deleteShader(m_vs_id);
14077
14078                 m_vs_id = 0;
14079         }
14080 }
14081
14082 /** Returns a literal corresponding to user-specified test case enum.
14083  *
14084  *  @param test_case As per description.
14085  *
14086  *  @return Requested string.
14087  **/
14088 std::string NegativeTest11::getTestCaseString(const _test_case& test_case)
14089 {
14090         std::string result = "?";
14091
14092         switch (test_case)
14093         {
14094         case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
14095                 result = "TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT";
14096                 break;
14097         case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
14098                 result = "TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT";
14099                 break;
14100         case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
14101                 result = "TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT";
14102                 break;
14103         default:
14104                 break;
14105         }
14106
14107         return result;
14108 }
14109
14110 /** Retrieves vertex shader body for user-specified test case.
14111  *
14112  *  @param test_case As per description.
14113  *
14114  *  @return Requested string.
14115  **/
14116 std::string NegativeTest11::getVertexShader(const _test_case& test_case)
14117 {
14118         std::stringstream result_sstream;
14119
14120         /* Form pre-amble */
14121         result_sstream << "#version 400\n"
14122                                           "\n"
14123                                           "#extension GL_ARB_shader_subroutine : require\n";
14124
14125         if (test_case == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT)
14126         {
14127                 result_sstream << "#extension GL_ARB_shader_atomic_counters : require\n";
14128         }
14129
14130         result_sstream << "\n"
14131                                           /* Define a subroutine */
14132                                           "subroutine void subroutineType(inout vec4 test);\n"
14133                                           "\n"
14134                                           "subroutine(subroutineType) void test_function(inout vec4 test)\n"
14135                                           "{\n"
14136                                           "    test += vec4(0, 1, 2, 3);\n"
14137                                           "}\n"
14138                                           "\n"
14139                                           "subroutine uniform subroutineType function;\n"
14140                                           "\n"
14141
14142                                           /* Define main() body */
14143                                           "void main()\n"
14144                                           "{\n";
14145
14146         /* Implement case-specific behavior */
14147         switch (test_case)
14148         {
14149         case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
14150         {
14151                 result_sstream << "if (atomicCounter(function) > 2)\n"
14152                                                   "{\n"
14153                                                   "    gl_Position = vec4(1);\n"
14154                                                   "}\n";
14155
14156                 break;
14157         }
14158
14159         case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
14160         {
14161                 result_sstream << "imageStore(function, vec2(0.0, 1.0), vec4(1.0) );\n";
14162
14163                 break;
14164         }
14165
14166         case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
14167         {
14168                 result_sstream << "gl_Position = texture(function, vec2(1.0) );\n";
14169
14170                 break;
14171         }
14172
14173         default:
14174                 break;
14175         } /* switch (test_case) */
14176
14177         /* Close main() body */
14178         result_sstream << "}\n";
14179
14180         /* Done */
14181         return result_sstream.str();
14182 }
14183
14184 /** Executes test iteration.
14185  *
14186  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
14187  */
14188 tcu::TestNode::IterateResult NegativeTest11::iterate()
14189 {
14190         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14191
14192         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
14193         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
14194         {
14195                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14196         }
14197
14198         /* Iterate over all test cases */
14199         for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
14200         {
14201                 if (static_cast<_test_case>(test_case) == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT &&
14202                         !m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
14203                 {
14204                         /* This iteration requires atomic counter support that this GL implementation
14205                          * is not capable of. Skip the iteration
14206                          */
14207                         continue;
14208                 }
14209
14210                 /* Try to build a program object using invalid vertex shader, specific to the
14211                  * iteration we're currently in */
14212                 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
14213
14214                 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
14215                                                                                                   "",                            /* te_body */
14216                                                                                                   "",                            /* gs_body */
14217                                                                                                   "",                            /* fs_body */
14218                                                                                                   DE_NULL,                       /* xfb_varyings */
14219                                                                                                   0,                             /* n_xfb_varyings */
14220                                                                                                   &m_vs_id, DE_NULL, /* out_tc_id */
14221                                                                                                   DE_NULL,                       /* out_te_id */
14222                                                                                                   DE_NULL,                       /* out_gs_id */
14223                                                                                                   DE_NULL,                       /* out_fs_id */
14224                                                                                                   &m_po_id))
14225                 {
14226                         m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14227                                                            << getTestCaseString(static_cast<_test_case>(test_case))
14228                                                            << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
14229
14230                         m_has_test_passed = false;
14231                 }
14232
14233                 /* Delete any objects that may have been created */
14234                 deinit();
14235         } /* for (all test cases) */
14236
14237         /** All done */
14238         if (m_has_test_passed)
14239         {
14240                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14241         }
14242         else
14243         {
14244                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14245         }
14246
14247         return STOP;
14248 }
14249
14250 /** Constructor.
14251  *
14252  *  @param context Rendering context.
14253  **/
14254 NegativeTest12::NegativeTest12(deqp::Context& context)
14255         : TestCase(context, "subroutines_not_allowed_as_variables_constructors_and_argument_or_return_types",
14256                            "Verifies that it is not allowed to use subroutine type for "
14257                            "local/global variables, constructors or argument/return type.")
14258         , m_has_test_passed(true)
14259         , m_po_id(0)
14260         , m_vs_id(0)
14261 {
14262         /* Left blank intentionally */
14263 }
14264
14265 /** Deinitializes any GL objects that may have been created during
14266  *  test execution.
14267  **/
14268 void NegativeTest12::deinit()
14269 {
14270         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14271
14272         if (m_po_id != 0)
14273         {
14274                 gl.deleteProgram(m_po_id);
14275
14276                 m_po_id = 0;
14277         }
14278
14279         if (m_vs_id != 0)
14280         {
14281                 gl.deleteShader(m_vs_id);
14282
14283                 m_vs_id = 0;
14284         }
14285 }
14286
14287 /** Returns a literal corresponding to user-specified test case enum.
14288  *
14289  *  @param test_case As per description.
14290  *
14291  *  @return Requested string.
14292  **/
14293 std::string NegativeTest12::getTestCaseString(const _test_case& test_case)
14294 {
14295         std::string result = "?";
14296
14297         switch (test_case)
14298         {
14299         case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
14300                 result = "TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE";
14301                 break;
14302         case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
14303                 result = "TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE";
14304                 break;
14305         case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
14306                 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR";
14307                 break;
14308         case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
14309                 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT";
14310                 break;
14311         case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
14312                 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE";
14313                 break;
14314         default:
14315                 break;
14316         }
14317
14318         return result;
14319 }
14320
14321 /** Retrieves vertex shader body for user-specified test case.
14322  *
14323  *  @param test_case As per description.
14324  *
14325  *  @return Requested string.
14326  **/
14327 std::string NegativeTest12::getVertexShader(const _test_case& test_case)
14328 {
14329         std::stringstream result_sstream;
14330
14331         /* Form pre-amble */
14332         result_sstream << "#version 400\n"
14333                                           "\n"
14334                                           "#extension GL_ARB_shader_subroutine : require\n"
14335                                           "\n"
14336                                           /* Define a subroutine */
14337                                           "subroutine void subroutineType(inout vec4 test);\n"
14338                                           "\n"
14339                                           "subroutine(subroutineType) void test_function(inout vec4 test)\n"
14340                                           "{\n"
14341                                           "    test += vec4(0, 1, 2, 3);\n"
14342                                           "}\n"
14343                                           "\n"
14344                                           "subroutine uniform subroutineType function;\n"
14345                                           "\n";
14346
14347         /* Include case-specific implementation */
14348         switch (test_case)
14349         {
14350         case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
14351         {
14352                 result_sstream << "void main()\n"
14353                                                   "{\n"
14354                                                   "    subroutine subroutineType function2;\n"
14355                                                   "    vec4                      result;\n"
14356                                                   "\n"
14357                                                   "    function2(result);\n"
14358                                                   "    gl_Position = result;\n"
14359                                                   "}\n";
14360
14361                 break;
14362         }
14363
14364         case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
14365         {
14366                 result_sstream << "subroutine subroutineType function2;\n"
14367                                                   "\n"
14368                                                   "void main()\n"
14369                                                   "{\n"
14370                                                   "    vec4 result;\n"
14371                                                   "\n"
14372                                                   "    function2(result);\n"
14373                                                   "    gl_Position = result;\n"
14374                                                   "}\n";
14375
14376                 break;
14377         }
14378
14379         case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
14380         {
14381                 result_sstream << "void main()\n"
14382                                                   "{\n"
14383                                                   "    subroutineType(function);\n"
14384                                                   "}\n";
14385
14386                 break;
14387         }
14388
14389         case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
14390         {
14391                 result_sstream << "vec4 test_function(subroutineType argument)\n"
14392                                                   "{\n"
14393                                                   "    vec4 result = vec4(1, 2, 3, 4);\n"
14394                                                   "\n"
14395                                                   "    argument(result);\n"
14396                                                   "\n"
14397                                                   "    return result;\n"
14398                                                   "}\n"
14399                                                   "\n"
14400                                                   "void main()\n"
14401                                                   "{\n"
14402                                                   "    test_function(function);\n"
14403                                                   "}\n";
14404
14405                 break;
14406         }
14407
14408         case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
14409         {
14410                 result_sstream << "subroutineType test_function()\n"
14411                                                   "{\n"
14412                                                   "    return function;\n"
14413                                                   "}\n"
14414                                                   "\n"
14415                                                   "void main()\n"
14416                                                   "{\n"
14417                                                   "    test_function()(gl_Position);\n"
14418                                                   "}\n";
14419
14420                 break;
14421         }
14422
14423         default:
14424                 break;
14425         } /* switch (test_case) */
14426
14427         /* Done */
14428         return result_sstream.str();
14429 }
14430
14431 /** Executes test iteration.
14432  *
14433  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
14434  */
14435 tcu::TestNode::IterateResult NegativeTest12::iterate()
14436 {
14437         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14438
14439         /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
14440         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
14441         {
14442                 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14443         }
14444
14445         /* Iterate over all test cases */
14446         for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
14447         {
14448                 /* Try to build a program object using invalid vertex shader, specific to the
14449                  * iteration we're currently in */
14450                 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
14451
14452                 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "",   /* tc_body */
14453                                                                                                   "",                            /* te_body */
14454                                                                                                   "",                            /* gs_body */
14455                                                                                                   "",                            /* fs_body */
14456                                                                                                   DE_NULL,                       /* xfb_varyings */
14457                                                                                                   0,                             /* n_xfb_varyings */
14458                                                                                                   &m_vs_id, DE_NULL, /* out_tc_id */
14459                                                                                                   DE_NULL,                       /* out_te_id */
14460                                                                                                   DE_NULL,                       /* out_gs_id */
14461                                                                                                   DE_NULL,                       /* out_fs_id */
14462                                                                                                   &m_po_id))
14463                 {
14464                         m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14465                                                            << getTestCaseString(static_cast<_test_case>(test_case))
14466                                                            << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
14467
14468                         m_has_test_passed = false;
14469                 }
14470
14471                 /* Delete any objects that may have been created */
14472                 deinit();
14473         } /* for (all test cases) */
14474
14475         /** All done */
14476         if (m_has_test_passed)
14477         {
14478                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14479         }
14480         else
14481         {
14482                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14483         }
14484
14485         return STOP;
14486 }
14487
14488 } /* ShaderSubroutine */
14489
14490 /** Constructor.
14491  *
14492  *  @param context Rendering context.
14493  **/
14494 ShaderSubroutineTests::ShaderSubroutineTests(deqp::Context& context)
14495         : TestCaseGroup(context, "shader_subroutine", "Verifies \"shader_subroutine\" functionality")
14496 {
14497         /* Left blank on purpose */
14498 }
14499
14500 /** Initializes a texture_storage_multisample test group.
14501  *
14502  **/
14503 void ShaderSubroutineTests::init(void)
14504 {
14505         addChild(new ShaderSubroutine::APITest1(m_context));
14506         addChild(new ShaderSubroutine::APITest2(m_context));
14507         addChild(new ShaderSubroutine::FunctionalTest1_2(m_context));
14508         addChild(new ShaderSubroutine::FunctionalTest3_4(m_context));
14509         addChild(new ShaderSubroutine::FunctionalTest5(m_context));
14510         addChild(new ShaderSubroutine::FunctionalTest6(m_context));
14511         addChild(new ShaderSubroutine::FunctionalTest7_8(m_context));
14512         addChild(new ShaderSubroutine::FunctionalTest9(m_context));
14513         addChild(new ShaderSubroutine::FunctionalTest10(m_context));
14514         addChild(new ShaderSubroutine::FunctionalTest11(m_context));
14515         addChild(new ShaderSubroutine::FunctionalTest12(m_context));
14516         addChild(new ShaderSubroutine::FunctionalTest13(m_context));
14517         addChild(new ShaderSubroutine::FunctionalTest14_15(m_context));
14518         addChild(new ShaderSubroutine::FunctionalTest16(m_context));
14519         addChild(new ShaderSubroutine::FunctionalTest17(m_context));
14520         addChild(new ShaderSubroutine::FunctionalTest18_19(m_context));
14521         addChild(new ShaderSubroutine::FunctionalTest20_21(m_context));
14522         addChild(new ShaderSubroutine::NegativeTest1(m_context));
14523         addChild(new ShaderSubroutine::NegativeTest2(m_context));
14524         addChild(new ShaderSubroutine::NegativeTest3(m_context));
14525         addChild(new ShaderSubroutine::NegativeTest4(m_context));
14526         addChild(new ShaderSubroutine::NegativeTest5(m_context));
14527         addChild(new ShaderSubroutine::NegativeTest6(m_context));
14528         addChild(new ShaderSubroutine::NegativeTest7(m_context));
14529         addChild(new ShaderSubroutine::NegativeTest8(m_context));
14530         addChild(new ShaderSubroutine::NegativeTest9(m_context));
14531         addChild(new ShaderSubroutine::NegativeTest10(m_context));
14532         addChild(new ShaderSubroutine::NegativeTest11(m_context));
14533         addChild(new ShaderSubroutine::NegativeTest12(m_context));
14534 }
14535
14536 } /* glcts namespace */