xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cShaderSubroutineTests.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 #ifndef _GL4CSHADERSUBROUTINETESTS_HPP
2 #define _GL4CSHADERSUBROUTINETESTS_HPP
3 /*-------------------------------------------------------------------------
4  * OpenGL Conformance Test Suite
5  * -----------------------------
6  *
7  * Copyright (c) 2014-2016 The Khronos Group Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */ /*!
22  * \file
23  * \brief
24  */ /*-------------------------------------------------------------------*/
25 
26 /**
27  * \file  gl4cShaderSubroutineTests.hpp
28  * \brief Declares test classes for "Shader Subroutine" functionality.
29  */ /*-------------------------------------------------------------------*/
30 
31 #include "glcTestCase.hpp"
32 #include "glwDefs.hpp"
33 #include <queue>
34 
35 #include "tcuTestLog.hpp"
36 
37 namespace gl4cts
38 {
39 namespace ShaderSubroutine
40 {
41 class Utils
42 {
43 public:
44     /* Public type definitions */
45 
46     struct buffer
47     {
48         buffer(deqp::Context &context);
49         ~buffer();
50 
51         void bindRange(glw::GLenum target, glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size);
52 
53         void generate();
54 
55         void update(glw::GLenum target, glw::GLsizeiptr size, glw::GLvoid *data, glw::GLenum usage);
56 
57         glw::GLuint m_id;
58 
59     private:
60         deqp::Context &m_context;
61     };
62 
63     struct framebuffer
64     {
65         framebuffer(deqp::Context &context);
66         ~framebuffer();
67 
68         void attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width, glw::GLuint height);
69 
70         void bind();
71         void clear(glw::GLenum mask);
72 
73         void clearColor(glw::GLfloat red, glw::GLfloat green, glw::GLfloat blue, glw::GLfloat alpha);
74         void generate();
75 
76         glw::GLuint m_id;
77 
78     private:
79         deqp::Context &m_context;
80     };
81 
82     /** Store information about program object
83      *
84      **/
85     struct program
86     {
87         program(deqp::Context &context);
88         ~program();
89 
90         void build(const glw::GLchar *compute_shader_code, const glw::GLchar *fragment_shader_code,
91                    const glw::GLchar *geometry_shader_code, const glw::GLchar *tesselation_control_shader_code,
92                    const glw::GLchar *tesselation_evaluation_shader_code, const glw::GLchar *vertex_shader_code,
93                    const glw::GLchar *const *varying_names, glw::GLuint n_varying_names, bool is_separable = false);
94 
95         void compile(glw::GLuint shader_id, const glw::GLchar *shader_code) const;
96 
97         bool isProgramBinarySupported() const;
98 
99         void createFromBinary(const std::vector<glw::GLubyte> &binary, glw::GLenum binary_format);
100 
101         void getBinary(std::vector<glw::GLubyte> &binary, glw::GLenum &binary_format) const;
102 
103         glw::GLuint getSubroutineIndex(const glw::GLchar *subroutine_name, glw::GLenum shader_stage) const;
104 
105         glw::GLint getSubroutineUniformLocation(const glw::GLchar *uniform_name, glw::GLenum shader_stage) const;
106 
107         glw::GLint getUniformLocation(const glw::GLchar *uniform_name) const;
108         void link() const;
109         void remove();
110         void use() const;
111 
112         static const glw::GLenum ARB_COMPUTE_SHADER;
113 
114         glw::GLuint m_compute_shader_id;
115         glw::GLuint m_fragment_shader_id;
116         glw::GLuint m_geometry_shader_id;
117         glw::GLuint m_program_object_id;
118         glw::GLuint m_tesselation_control_shader_id;
119         glw::GLuint m_tesselation_evaluation_shader_id;
120         glw::GLuint m_vertex_shader_id;
121 
122     private:
123         deqp::Context &m_context;
124     };
125 
126     struct texture
127     {
128         texture(deqp::Context &context);
129         ~texture();
130 
131         void bind();
132 
133         void create(glw::GLuint width, glw::GLuint height, glw::GLenum internal_format);
134 
135         void get(glw::GLenum format, glw::GLenum type, glw::GLvoid *out_data);
136 
137         void update(glw::GLuint width, glw::GLuint height, glw::GLenum format, glw::GLenum type, glw::GLvoid *data);
138 
139         glw::GLuint m_id;
140 
141     private:
142         deqp::Context &m_context;
143     };
144 
145     struct vertexArray
146     {
147         vertexArray(deqp::Context &Context);
148         ~vertexArray();
149 
150         void generate();
151         void bind();
152 
153         glw::GLuint m_id;
154 
155     private:
156         deqp::Context &m_context;
157     };
158 
159     /** Storage for 4 element vector of T
160      *
161      **/
162     template <typename T>
163     struct vec4
164     {
vec4gl4cts::ShaderSubroutine::Utils::vec4165         vec4()
166         {
167         }
168 
vec4gl4cts::ShaderSubroutine::Utils::vec4169         vec4(T x, T y, T z, T w) : m_x(x), m_y(y), m_z(z), m_w(w)
170         {
171         }
172 
operator ==gl4cts::ShaderSubroutine::Utils::vec4173         bool operator==(const vec4 &val) const
174         {
175             bool result = true;
176 
177             result = result && compare(m_x, val.m_x);
178             result = result && compare(m_y, val.m_y);
179             result = result && compare(m_z, val.m_z);
180             result = result && compare(m_w, val.m_w);
181 
182             return result;
183         }
184 
loggl4cts::ShaderSubroutine::Utils::vec4185         void log(tcu::MessageBuilder &message) const
186         {
187             message << "[ " << m_x << ", " << m_y << ", " << m_z << ", " << m_w << " ]";
188         }
189 
190         T m_x;
191         T m_y;
192         T m_z;
193         T m_w;
194     };
195 
196     enum _shader_stage
197     {
198         SHADER_STAGE_FIRST,
199 
200         SHADER_STAGE_VERTEX = SHADER_STAGE_FIRST,
201         SHADER_STAGE_TESSELLATION_CONTROL,
202         SHADER_STAGE_TESSELLATION_EVALUATION,
203         SHADER_STAGE_GEOMETRY,
204         SHADER_STAGE_FRAGMENT,
205 
206         SHADER_STAGE_COUNT
207     };
208 
209     enum _variable_type
210     {
211         VARIABLE_TYPE_BOOL,
212         VARIABLE_TYPE_BVEC2,
213         VARIABLE_TYPE_BVEC3,
214         VARIABLE_TYPE_BVEC4,
215         VARIABLE_TYPE_DOUBLE,
216         VARIABLE_TYPE_DVEC2,
217         VARIABLE_TYPE_DVEC3,
218         VARIABLE_TYPE_DVEC4,
219         VARIABLE_TYPE_FLOAT,
220         VARIABLE_TYPE_INT,
221         VARIABLE_TYPE_IVEC2,
222         VARIABLE_TYPE_IVEC3,
223         VARIABLE_TYPE_IVEC4,
224         VARIABLE_TYPE_MAT2,
225         VARIABLE_TYPE_MAT2X3,
226         VARIABLE_TYPE_MAT2X4,
227         VARIABLE_TYPE_MAT3,
228         VARIABLE_TYPE_MAT3X2,
229         VARIABLE_TYPE_MAT3X4,
230         VARIABLE_TYPE_MAT4,
231         VARIABLE_TYPE_MAT4X2,
232         VARIABLE_TYPE_MAT4X3,
233         VARIABLE_TYPE_UINT,
234         VARIABLE_TYPE_UVEC2,
235         VARIABLE_TYPE_UVEC3,
236         VARIABLE_TYPE_UVEC4,
237         VARIABLE_TYPE_VEC2,
238         VARIABLE_TYPE_VEC3,
239         VARIABLE_TYPE_VEC4,
240 
241         /* Always last */
242         VARIABLE_TYPE_UNKNOWN
243     };
244 
245     /* Public methods */
246     static bool buildProgram(const glw::Functions &gl, const std::string &vs_body, const std::string &tc_body,
247                              const std::string &te_body, const std::string &gs_body, const std::string &fs_body,
248                              const glw::GLchar **xfb_varyings, const unsigned int &n_xfb_varyings,
249                              glw::GLuint *out_vs_id, glw::GLuint *out_tc_id, glw::GLuint *out_te_id,
250                              glw::GLuint *out_gs_id, glw::GLuint *out_fs_id, glw::GLuint *out_po_id);
251 
252     static _variable_type getBaseVariableType(const _variable_type &variable_type);
253 
254     static unsigned int getComponentSizeForVariableType(const _variable_type &variable_type);
255 
256     static glw::GLenum getGLenumForShaderStage(const _shader_stage &shader_stage);
257 
258     static unsigned int getNumberOfComponentsForVariableType(const _variable_type &variable_type);
259 
260     static std::string getShaderStageString(const _shader_stage &shader_stage);
261 
262     static std::string getShaderStageStringFromGLEnum(const glw::GLenum shader_stage_glenum);
263 
264     static _variable_type getVariableTypeFromProperties(const _variable_type &base_variable_type,
265                                                         const unsigned int &n_components);
266 
267     static std::string getVariableTypeGLSLString(const _variable_type &variable_type);
268 
269     static const glw::GLchar *programInterfaceToStr(glw::GLenum program_interface);
270     static const glw::GLchar *pnameToStr(glw::GLenum pname);
271 
272 private:
273     /* Private methods */
274     template <typename T>
compare(const T & left,const T & right)275     static bool compare(const T &left, const T &right)
276     {
277         return left == right;
278     }
279 
280     static bool compare(const glw::GLfloat &left, const glw::GLfloat &right);
281 };
282 
283 /** Verify that Get* commands accept MAX_SUBROUTINES and
284  *  MAX_SUBROUTINE_UNIFORM_LOCATIONS tokens and that the returned values
285  *  are not lower than required by the specification.
286  **/
287 class APITest1 : public deqp::TestCase
288 {
289 public:
290     /* Public methods */
291     APITest1(deqp::Context &context);
292 
293     virtual tcu::TestNode::IterateResult iterate();
294 
295 private:
296     /* Private type definitions */
297     /* Private methods */
298 
299     /* Private fields */
300     bool m_has_test_passed;
301 };
302 
303 /** Check if <bufsize> and <length> parameters behave correctly in
304  *  GetActiveSubroutineName and GetActiveSubroutineUniformName functions.
305  **/
306 class APITest2 : public deqp::TestCase
307 {
308 public:
309     /* Public methods */
310     APITest2(deqp::Context &context);
311 
312     virtual void deinit();
313     virtual tcu::TestNode::IterateResult iterate();
314 
315 private:
316     /* Private type definitions */
317 
318     /* Private methods */
319     std::string getVertexShaderBody();
320     void initTest();
321     void verifyGLGetActiveSubroutineNameFunctionality();
322     void verifyGLGetActiveSubroutineUniformNameFunctionality();
323 
324     /* Private fields */
325     glw::GLchar *m_buffer;
326     bool m_has_test_passed;
327     glw::GLuint m_po_id;
328     const char *m_subroutine_name1;
329     const char *m_subroutine_name2;
330     const char *m_subroutine_uniform_name;
331     glw::GLuint m_vs_id;
332 };
333 
334 /** * Create program with 2 subroutines taking one parameter and 1 subroutine
335  *    uniform. Select the first subroutine and make a draw. Verify the result
336  *    and draw again with second subroutine selected then verify result again.
337  *    Repeat for following subroutines return and argument types: bool, float,
338  *    int, uint, double, *vec*, *mat*.
339  *
340  *  * Same as above, but with return and argument types as arrays.
341  *
342  ***/
343 class FunctionalTest1_2 : public deqp::TestCase
344 {
345 public:
346     /* Public methods */
347     FunctionalTest1_2(deqp::Context &context);
348 
349     virtual void deinit();
350     virtual tcu::TestNode::IterateResult iterate();
351 
352 private:
353     /* Private type definitions */
354     struct _test_case
355     {
356         unsigned int array_size;
357         Utils::_variable_type variable_type;
358     };
359 
360     typedef std::vector<_test_case> _test_cases;
361     typedef _test_cases::const_iterator _test_cases_const_iterator;
362 
363     /* Private methods */
364     void deinitTestIteration();
365     bool executeTestIteration(const _test_case &test_case);
366 
367     std::string getVertexShaderBody(const Utils::_variable_type &variable_type, unsigned int array_size);
368 
369     void initTest();
370 
371     bool verifyXFBData(const void *xfb_data, const Utils::_variable_type &variable_type);
372 
373     /* Private fields */
374     bool m_has_test_passed;
375     glw::GLuint m_po_id;
376     glw::GLuint m_po_getter0_subroutine_index;
377     glw::GLuint m_po_getter1_subroutine_index;
378     glw::GLint m_po_subroutine_uniform_index;
379     _test_cases m_test_cases;
380     glw::GLuint m_xfb_bo_id;
381     glw::GLuint m_vao_id;
382     glw::GLuint m_vs_id;
383 };
384 
385 /** * Create a program with 4 subroutines and 2 subroutine uniforms and query
386  *    it using: GetProgramStageiv, GetActiveSubroutineUniformiv,
387  *    GetActiveSubroutineUniformName, GetActiveSubroutineName,
388  *    GetUniformSubroutineuiv, GetSubroutineIndex and
389  *    GetSubroutineUniformLocation. Verify the results and use them to select
390  *    subroutines, then make a draw and select different set of subroutines.
391  *    Draw again and verify the results.
392  *
393  *  OpenGL 4.3 or ARB_program_interface_query support required
394  *  * Same as above, but query the program using calls introduced in
395  *    ARB_program_interface_query extension.
396  **/
397 class FunctionalTest3_4 : public deqp::TestCase
398 {
399 public:
400     /* Public methods */
401     FunctionalTest3_4(deqp::Context &context);
402 
403     virtual tcu::TestNode::IterateResult iterate();
404 
405 private:
406     /* Private types */
407     /** Connect pname with expected value. Used to check Get* API.
408      *
409      **/
410     struct inspectionDetails
411     {
412         glw::GLenum pname;
413         glw::GLint expected_value;
414     };
415 
416     /* Private types */
417     /** Connect program_interface, pname and expected value. Used to check GetProgramInterface.
418      *
419      **/
420     struct inspectionDetailsForProgramInterface
421     {
422         glw::GLenum program_interface;
423         glw::GLenum pname;
424         glw::GLint expected_value;
425     };
426 
427     /* Private methods */
428     bool checkProgramStageiv(glw::GLuint program_id, glw::GLenum pname, glw::GLint expected) const;
429 
430     bool checkProgramResourceiv(glw::GLuint program_id, glw::GLenum program_interface, glw::GLenum prop,
431                                 const glw::GLchar *resource_name, glw::GLint expected) const;
432 
433     bool checkProgramInterfaceiv(glw::GLuint program_id, glw::GLenum program_interface, glw::GLenum pname,
434                                  glw::GLint expected) const;
435 
436     bool checkActiveSubroutineUniformiv(glw::GLuint program_id, glw::GLuint index, glw::GLenum pname,
437                                         glw::GLint expected) const;
438 
439     glw::GLuint getProgramResourceIndex(glw::GLuint program_id, glw::GLenum program_interface,
440                                         const glw::GLchar *resource_name) const;
441 
442     glw::GLuint getSubroutineIndex(glw::GLuint program_id, const glw::GLchar *subroutine_name,
443                                    bool use_program_query) const;
444 
445     glw::GLint getSubroutineUniformLocation(glw::GLuint program_id, const glw::GLchar *uniform_name,
446                                             bool use_program_query) const;
447 
448     bool inspectProgramStageiv(glw::GLuint program_id) const;
449     bool inspectProgramInterfaceiv(glw::GLuint program_id) const;
450 
451     bool inspectProgramResourceiv(glw::GLuint program_id, const glw::GLchar **subroutine_names,
452                                   const glw::GLchar **uniform_names) const;
453 
454     bool inspectActiveSubroutineUniformiv(glw::GLuint program_id, const glw::GLchar **uniform_names) const;
455 
456     bool inspectActiveSubroutineUniformName(glw::GLuint program_id, const glw::GLchar **uniform_names) const;
457 
458     bool inspectActiveSubroutineName(glw::GLuint program_id, const glw::GLchar **subroutine_names) const;
459 
460     bool inspectSubroutineBinding(glw::GLuint program_id, const glw::GLchar **subroutine_names,
461                                   const glw::GLchar **uniform_names, bool use_program_query) const;
462 
463     bool testDraw(glw::GLuint program_id, const glw::GLchar *first_routine_name, const glw::GLchar *second_routine_name,
464                   const glw::GLchar **uniform_names, const Utils::vec4<glw::GLfloat> data[5],
465                   bool use_program_query) const;
466 
467     /* Private fields */
468     glw::GLint m_n_active_subroutine_uniforms;
469     glw::GLint m_n_active_subroutine_uniform_locations;
470     glw::GLint m_n_active_subroutines;
471     glw::GLint m_n_active_subroutine_uniform_name_length;
472     glw::GLint m_n_active_subroutine_name_length;
473     glw::GLint m_n_active_subroutine_uniform_size;
474 };
475 
476 /**
477  * * Create a program with 8 subroutines and 4 subroutine uniforms. Each
478  *   subroutine uniform should have different signature that should match 2
479  *   subroutines. Go through all possible combinations of subroutine uniforms
480  *   values and for each combination verify that it works as expected.
481  **/
482 class FunctionalTest5 : public deqp::TestCase
483 {
484 public:
485     /* Public methods */
486     FunctionalTest5(deqp::Context &context);
487 
488     virtual tcu::TestNode::IterateResult iterate();
489 
490 private:
491     /* Private methods */
492     void logError(const glw::GLchar *subroutine_names[4][2], const glw::GLuint subroutine_combination[4],
493                   const Utils::vec4<glw::GLfloat> input_data[3], const Utils::vec4<glw::GLfloat> &first_routine_result,
494                   const Utils::vec4<glw::GLfloat> &second_routine_result,
495                   const Utils::vec4<glw::GLfloat> &third_routine_result,
496                   const Utils::vec4<glw::GLuint> &fourth_routine_result,
497                   const Utils::vec4<glw::GLfloat> &first_routine_expected_result,
498                   const Utils::vec4<glw::GLfloat> &second_routine_expected_result,
499                   const Utils::vec4<glw::GLfloat> &third_routine_expected_result,
500                   const Utils::vec4<glw::GLuint> &fourth_routine_expected_result) const;
501 
502     void testDraw(const glw::GLuint subroutine_combination[4], const Utils::vec4<glw::GLfloat> input_data[3],
503                   Utils::vec4<glw::GLfloat> &out_first_routine_result,
504                   Utils::vec4<glw::GLfloat> &out_second_routine_result,
505                   Utils::vec4<glw::GLfloat> &out_third_routine_result,
506                   Utils::vec4<glw::GLuint> &out_fourth_routine_result) const;
507 
508     bool verify(const Utils::vec4<glw::GLfloat> &first_routine_result,
509                 const Utils::vec4<glw::GLfloat> &second_routine_result,
510                 const Utils::vec4<glw::GLfloat> &third_routine_result,
511                 const Utils::vec4<glw::GLuint> &fourth_routine_result,
512                 const Utils::vec4<glw::GLfloat> &first_routine_expected_result,
513                 const Utils::vec4<glw::GLfloat> &second_routine_expected_result,
514                 const Utils::vec4<glw::GLfloat> &third_routine_expected_result,
515                 const Utils::vec4<glw::GLuint> &fourth_routine_expected_result) const;
516 
517     /* Private fields */
518     glw::GLuint m_subroutine_uniform_locations[4][1];
519     glw::GLuint m_subroutine_indices[4][2];
520     glw::GLuint m_uniform_locations[3];
521 };
522 
523 /**
524  * * Create a program with a subroutine and a subroutine uniform. Verify that
525  *   subroutine can be called directly with a static use of subroutine's
526  *   function name, as is done with non-subroutine function declarations and
527  *   calls.
528  **/
529 class FunctionalTest6 : public deqp::TestCase
530 {
531 public:
532     /* Public methods */
533     FunctionalTest6(deqp::Context &context);
534 
535     virtual tcu::TestNode::IterateResult iterate();
536 };
537 
538 /**
539  * * Create a program with 2 subroutines and an array of 4 subroutine
540  *   uniforms. Go through all possible combinations of subroutine uniforms
541  *   values and for each combination verify that it works as expected by
542  *   performing draw or dispatch call. Also verify that length() function
543  *   works correctly when used on array of subroutine uniforms.
544  *
545  * * Verify that program which uses uniforms, constant expressions and
546  *   dynamically uniform loop index to access subroutine uniform array
547  *   compiles and works as expected.
548  **/
549 class FunctionalTest7_8 : public deqp::TestCase
550 {
551 public:
552     /* Public methods */
553     FunctionalTest7_8(deqp::Context &context);
554 
555     virtual tcu::TestNode::IterateResult iterate();
556 
557 private:
558     /* Private methods */
559     void calculate(glw::GLuint function, const Utils::vec4<glw::GLfloat> &left, const Utils::vec4<glw::GLfloat> &right,
560                    Utils::vec4<glw::GLfloat> &out) const;
561 
562     void calculate(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat> &left,
563                    const Utils::vec4<glw::GLfloat> &right, const Utils::vec4<glw::GLuint> &indices,
564                    Utils::vec4<glw::GLfloat> &out_combined, Utils::vec4<glw::GLfloat> &out_combined_inversed,
565                    Utils::vec4<glw::GLfloat> &out_constant, Utils::vec4<glw::GLfloat> &out_constant_inversed,
566                    Utils::vec4<glw::GLfloat> &out_dynamic, Utils::vec4<glw::GLfloat> &out_dynamic_inversed,
567                    Utils::vec4<glw::GLfloat> &out_loop) const;
568 
569     void logError(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat> &left,
570                   const Utils::vec4<glw::GLfloat> &right, const Utils::vec4<glw::GLuint> &indices,
571                   const Utils::vec4<glw::GLfloat> vec4_expected[7], const Utils::vec4<glw::GLfloat> vec4_result[7],
572                   glw::GLuint array_length, bool result[7]) const;
573 
574     bool testDraw(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat> &left,
575                   const Utils::vec4<glw::GLfloat> &right, const Utils::vec4<glw::GLuint> &indices) const;
576 
577     /* Private fields */
578     glw::GLuint m_subroutine_uniform_locations[4];
579     glw::GLuint m_subroutine_indices[2];
580     glw::GLuint m_uniform_locations[3];
581 };
582 
583 /**
584  *  Make sure that program with one function associated with 3 different
585  *  subroutine types and 3 subroutine uniforms using that function compiles
586  *  and works as expected.
587  *
588  **/
589 class FunctionalTest9 : public deqp::TestCase
590 {
591 public:
592     /* Public methods */
593     FunctionalTest9(deqp::Context &context);
594 
595     virtual void deinit();
596     virtual tcu::TestNode::IterateResult iterate();
597 
598 private:
599     /* Private methods */
600     std::string getVertexShaderBody() const;
601     void initTest();
602     void verifyXFBData(const glw::GLvoid *data_ptr);
603 
604     /* Private fields */
605     bool m_has_test_passed;
606     const unsigned int m_n_points_to_draw;
607     glw::GLuint m_po_id;
608     glw::GLuint m_vao_id;
609     glw::GLuint m_vs_id;
610     glw::GLuint m_xfb_bo_id;
611 };
612 
613 /**
614  * OpenGL 4.3 or ARB_arrays_of_arrays support required
615  * * Create a program that uses array of arrays for subroutine uniform type
616  *   and verify that it works as expected.
617  **/
618 class FunctionalTest10 : public deqp::TestCase
619 {
620 public:
621     FunctionalTest10(deqp::Context &context);
622 
623     virtual tcu::TestNode::IterateResult iterate();
624 
625 private:
626     /* Private methods */
627     glw::GLint testDraw(const glw::GLuint routine_indices[16]) const;
628 
629     /* Private fields */
630     glw::GLuint m_subroutine_uniform_locations[16];
631     glw::GLuint m_subroutine_indices[2];
632 };
633 
634 /**
635  * * Verify that following operations work correctly when performed inside
636  *   subroutine body: setting global variable, texture sampling, writing
637  *   to fragment shader outputs, using discard function (fragment shader
638  *   only), calling other functions and subroutines.
639  **/
640 class FunctionalTest11 : public deqp::TestCase
641 {
642 public:
643     /* Public methods */
644     FunctionalTest11(deqp::Context &context);
645 
646     virtual tcu::TestNode::IterateResult iterate();
647 
648 private:
649     /* Private types */
650     struct testConfiguration
651     {
testConfigurationgl4cts::ShaderSubroutine::FunctionalTest11::testConfiguration652         testConfiguration(const glw::GLchar *description, const glw::GLubyte expected_color[4],
653                           glw::GLuint discard_fragment, glw::GLuint set_global_colors, glw::GLuint sample_texture,
654                           glw::GLuint compare, glw::GLuint test, glw::GLuint first_sampler, glw::GLuint second_sampler)
655         {
656             m_description = description;
657 
658             m_expected_color[0] = expected_color[0];
659             m_expected_color[1] = expected_color[1];
660             m_expected_color[2] = expected_color[2];
661             m_expected_color[3] = expected_color[3];
662 
663             m_routines[0] = discard_fragment;
664             m_routines[1] = set_global_colors;
665             m_routines[2] = sample_texture;
666             m_routines[3] = compare;
667             m_routines[4] = test;
668 
669             m_samplers[0] = first_sampler;
670             m_samplers[1] = second_sampler;
671         }
672 
673         const glw::GLchar *m_description;
674         glw::GLubyte m_expected_color[4];
675         glw::GLuint m_routines[5];
676         glw::GLuint m_samplers[2];
677     };
678 
679     /* Private methods */
680     void fillTexture(Utils::texture &texture, const glw::GLubyte color[4]) const;
681 
682     bool testDraw(const glw::GLuint routine_configuration[5], const glw::GLuint sampler_configuration[2],
683                   const glw::GLubyte expected_color[4], Utils::texture &color_texture) const;
684 
685     /* Private fields */
686     /* Constants */
687     static const glw::GLuint m_texture_height;
688     static const glw::GLuint m_texture_width;
689 
690     /* Locations and indices */
691     glw::GLuint m_subroutine_uniform_locations[5];
692     glw::GLuint m_subroutine_indices[5][2];
693     glw::GLuint m_uniform_locations[2];
694     glw::GLuint m_source_textures[2];
695 };
696 
697 /**
698  * OpenGL 4.3 or ARB_shader_storage_buffer_object, ARB_atomic_counters
699  * and ARB_shader_image_load_store support required
700  * * Same as above, but check writing/reading from storage buffer, performing
701  *   operations on atomic counters and writing/reading from an image. This
702  *   should be tested in a program stage which supports operations of these
703  *   kind.
704  **/
705 class FunctionalTest12 : public deqp::TestCase
706 {
707 public:
708     FunctionalTest12(deqp::Context &context);
709 
710     virtual tcu::TestNode::IterateResult iterate();
711 
712 private:
713     /* Private methods */
714     void fillTexture(Utils::texture &texture, const glw::GLuint color[4]) const;
715 
716     bool verifyTexture(Utils::texture &texture, const glw::GLuint color[4]) const;
717 
718     bool testAtomic();
719 
720     bool testAtomicDraw(glw::GLuint subourinte_index, const glw::GLuint expected_results[3]) const;
721 
722     bool testImage();
723 
724     bool testImageDraw(glw::GLuint subroutine_index, Utils::texture &left, Utils::texture &right,
725                        const glw::GLuint expected_left_color[4], const glw::GLuint expected_right_color[4]) const;
726 
727     bool testSSBO();
728 
729     bool testSSBODraw(glw::GLuint subourinte_index, const glw::GLuint expected_results[4]) const;
730 
731     /* Private fields */
732     /* Constatnts */
733     static const glw::GLuint m_texture_height;
734     static const glw::GLuint m_texture_width;
735 
736     /* Locations */
737     glw::GLuint m_left_image;
738     glw::GLuint m_right_image;
739 };
740 
741 /**
742  *  Verify that subroutines work correctly when used in separate shader
743  *  objects.
744  *
745  **/
746 class FunctionalTest13 : public deqp::TestCase
747 {
748 public:
749     /* Public methods */
750     FunctionalTest13(deqp::Context &context);
751 
752     virtual void deinit();
753     virtual tcu::TestNode::IterateResult iterate();
754 
755 private:
756     /* Private methods */
757     std::string getFragmentShaderBody(unsigned int n_id);
758     std::string getGeometryShaderBody(unsigned int n_id);
759     std::string getTessellationControlShaderBody(unsigned int n_id);
760     std::string getTessellationEvaluationShaderBody(unsigned int n_id);
761     std::string getVertexShaderBody(unsigned int n_id);
762     void initTest();
763 
764     void verifyReadBuffer(unsigned int n_fs_id, unsigned int n_fs_subroutine, unsigned int n_gs_id,
765                           unsigned int n_gs_subroutine, unsigned int n_tc_id, unsigned int n_tc_subroutine,
766                           unsigned int n_te_id, unsigned int n_te_subroutine, unsigned int n_vs_id,
767                           unsigned int n_vs_subroutine);
768 
769     /* Private fields */
770     glw::GLuint m_fbo_id;
771     glw::GLuint m_fs_po_ids[2];
772     glw::GLuint m_gs_po_ids[2];
773     glw::GLuint m_pipeline_id;
774     unsigned char *m_read_buffer;
775     glw::GLuint m_tc_po_ids[2];
776     glw::GLuint m_te_po_ids[2];
777     const unsigned int m_to_height;
778     glw::GLuint m_to_id;
779     const unsigned int m_to_width;
780     glw::GLuint m_vao_id;
781     glw::GLuint m_vs_po_ids[2];
782 
783     bool m_has_test_passed;
784 };
785 
786 /**
787  * * Create program with subroutines that use structures as parameters and
788  *   make sure it works correctly.
789  *
790  * OpenGL 4.1 or ARB_get_program_binary support required
791  * * Create a program with 4 subroutines and 2 subroutine uniforms. Query
792  *   names and indices of all active subroutines and query names and
793  *   locations of all active subroutine uniforms. Call GetProgramBinary on
794  *   this program and delete it. Create new program from the binary using
795  *   ProgramBinary. Verify that all active subroutine names and indices in
796  *   this program match ones from the original program. Also verify that
797  *   all active subroutine uniform names and locations match ones from
798  *   original program. Make a draw, expect random but valid set of selected
799  *   subroutines, then select arbitrary set of subroutines, make a draw and
800  *   verify the results.
801  **/
802 class FunctionalTest14_15 : public deqp::TestCase
803 {
804 public:
805     FunctionalTest14_15(deqp::Context &context);
806 
807     virtual tcu::TestNode::IterateResult iterate();
808 
809 private:
810     /* Private methods */
811     bool testDefaultSubroutineSet(const Utils::vec4<glw::GLuint> &uni_input,
812                                   const Utils::vec4<glw::GLuint> expected_routine_1_result[2],
813                                   const Utils::vec4<glw::GLuint> expected_routine_2_result[2]) const;
814 
815     bool testDraw(glw::GLuint routine_configuration, const Utils::vec4<glw::GLuint> &uni_input,
816                   const Utils::vec4<glw::GLuint> &expected_routine_1_result,
817                   const Utils::vec4<glw::GLuint> &expected_routine_2_result) const;
818 
819     bool testIndicesAndLocations() const;
820 
821     /* Private fields */
822     /* Locations and indices */
823     glw::GLuint m_subroutine_uniform_locations[2];
824     glw::GLuint m_subroutine_indices[2][2];
825     glw::GLuint m_uniform_location;
826     glw::GLuint m_initial_subroutine_uniform_locations[2];
827     glw::GLuint m_initial_subroutine_indices[2][2];
828 };
829 
830 /**
831  * Check that when the active program for a shader stage is re-linked or
832  * changed by a call to UseProgram, BindProgramPipeline, or
833  * UseProgramStages, subroutine uniforms for that stage are reset to
834  * arbitrarily chosen default functions with compatible subroutine types.
835  *
836  **/
837 class FunctionalTest16 : public deqp::TestCase
838 {
839 public:
840     /* Public methods */
841     FunctionalTest16(deqp::Context &context);
842 
843     virtual void deinit();
844     virtual tcu::TestNode::IterateResult iterate();
845 
846 private:
847     /* Private type definitions */
848     /* Defines a specific use case that should be checked during particular
849      * test iteration.
850      */
851     enum _test_case
852     {
853         TEST_CASE_FIRST,
854 
855         TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT = TEST_CASE_FIRST,
856         TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT,
857         TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE,
858         TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE,
859         TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE,
860         TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE,
861         TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE,
862 
863         /* Always last */
864         TEST_CASE_COUNT
865     };
866 
867     /** Defines a number of different subroutine-specific properties
868      *  for a single shader stage.
869      **/
870     struct _shader_stage
871     {
872         glw::GLuint default_subroutine1_value;
873         glw::GLuint default_subroutine2_value;
874         glw::GLuint default_subroutine3_value;
875         glw::GLuint default_subroutine4_value;
876         glw::GLint subroutine1_uniform_location;
877         glw::GLint subroutine2_uniform_location;
878         glw::GLint subroutine3_uniform_location;
879         glw::GLint subroutine4_uniform_location;
880         glw::GLuint function1_index;
881         glw::GLuint function2_index;
882         glw::GLuint function3_index;
883         glw::GLuint function4_index;
884 
885         glw::GLenum gl_stage;
886     };
887 
888     /** Describes subroutine-specific properties for a program object */
889     struct _program
890     {
891         _shader_stage fragment;
892         _shader_stage geometry;
893         _shader_stage tess_control;
894         _shader_stage tess_evaluation;
895         _shader_stage vertex;
896     };
897 
898     /** Describes modes that verify*() functions can run in */
899     enum _subroutine_uniform_value_verification
900     {
901         SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES,
902         SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES,
903         SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES,
904     };
905 
906     /* Private methods */
907     std::string getShaderBody(const Utils::_shader_stage &shader_stage, const unsigned int &n_id) const;
908 
909     void getShaderStages(bool retrieve_program_object_shader_ids, const unsigned int &n_id,
910                          const _shader_stage **out_shader_stages) const;
911 
912     void initTest();
913 
914     void verifySubroutineUniformValues(const _test_case &test_case, const unsigned int &n_id,
915                                        const _subroutine_uniform_value_verification &verification);
916 
917     void verifySubroutineUniformValuesForShaderStage(const _shader_stage &shader_stage,
918                                                      const _subroutine_uniform_value_verification &verification);
919 
920     /* Private fields */
921     bool m_are_pipeline_objects_supported;
922     bool m_has_test_passed;
923 
924     glw::GLuint m_fs_ids[2];
925     glw::GLuint m_gs_ids[2];
926     glw::GLuint m_po_ids[2];
927     glw::GLuint m_tc_ids[2];
928     glw::GLuint m_te_ids[2];
929     glw::GLuint m_vs_ids[2];
930 
931     glw::GLuint m_fs_po_ids[2];
932     glw::GLuint m_gs_po_ids[2];
933     glw::GLuint m_pipeline_object_ids[2];
934     glw::GLuint m_tc_po_ids[2];
935     glw::GLuint m_te_po_ids[2];
936     glw::GLuint m_vs_po_ids[2];
937 
938     _shader_stage m_fs_po_descriptors[2];
939     _shader_stage m_gs_po_descriptors[2];
940     _shader_stage m_tc_po_descriptors[2];
941     _shader_stage m_te_po_descriptors[2];
942     _shader_stage m_vs_po_descriptors[2];
943 
944     _program m_po_descriptors[2];
945 };
946 
947 /**
948  *  Create a program which uses the same subroutine and subroutine uniform
949  *  names for every stage. Types of subroutines should be different in each
950  *  stage. Make sure that such program compiles and works as expected.
951  **/
952 class FunctionalTest17 : public deqp::TestCase
953 {
954 public:
955     /* Public methods */
956     FunctionalTest17(deqp::Context &context);
957 
958     virtual void deinit();
959     virtual tcu::TestNode::IterateResult iterate();
960 
961 private:
962     /* Private methods */
963     std::string getFragmentShaderBody() const;
964     std::string getGeometryShaderBody() const;
965     std::string getTessellationControlShaderBody() const;
966     std::string getTessellationEvaluationShaderBody() const;
967     std::string getVertexShaderBody() const;
968     void initTest();
969     void verifyRenderedData();
970 
971     /* Private fields */
972     glw::GLuint m_fbo_id;
973     glw::GLuint m_fs_id;
974     glw::GLuint m_gs_id;
975     bool m_has_test_passed;
976     glw::GLuint m_po_id;
977     glw::GLuint m_tc_id;
978     glw::GLuint m_te_id;
979     float *m_to_data;
980     const unsigned int m_to_height;
981     glw::GLuint m_to_id;
982     const unsigned int m_to_width;
983     glw::GLuint m_vao_id;
984     glw::GLuint m_vs_id;
985 };
986 
987 /**
988  *  Make sure that calling a subroutine with argument value returned by
989  *  another subroutine works correctly.
990  *
991  *  Verify that subroutines and subroutine uniforms work as expected when
992  *  they are used in connection with control flow functions
993  *  (if/else/case/while/for/break/continue).
994  *
995  **/
996 class FunctionalTest18_19 : public deqp::TestCase
997 {
998 public:
999     /* Public methods */
1000     FunctionalTest18_19(deqp::Context &context);
1001 
1002     virtual void deinit();
1003     virtual tcu::TestNode::IterateResult iterate();
1004 
1005 private:
1006     /* Private type definitions */
1007     typedef tcu::Vec4 (*PFNVEC4OPERATORPROC)(tcu::Vec4);
1008 
1009     /* Private methods */
1010     void executeTest(glw::GLuint bool_operator1_subroutine_location, glw::GLuint bool_operator2_subroutine_location,
1011                      glw::GLuint vec4_operator1_subroutine_location, glw::GLuint vec4_operator2_subroutine_location);
1012 
1013     std::string getVertexShaderBody() const;
1014 
1015     void initTest();
1016     void verifyXFBData(const glw::GLvoid *data, glw::GLuint bool_operator1_subroutine_location,
1017                        glw::GLuint bool_operator2_subroutine_location, glw::GLuint vec4_operator1_subroutine_location,
1018                        glw::GLuint vec4_operator2_subroutine_location);
1019 
1020     static tcu::Vec4 vec4operator_div2(tcu::Vec4 data);
1021     static tcu::Vec4 vec4operator_mul4(tcu::Vec4 data);
1022 
1023     /* Private fields */
1024     bool m_has_test_passed;
1025     const unsigned int m_n_points_to_draw;
1026     glw::GLuint m_po_id;
1027     glw::GLuint m_po_subroutine_divide_by_two_location;
1028     glw::GLuint m_po_subroutine_multiply_by_four_location;
1029     glw::GLuint m_po_subroutine_returns_false_location;
1030     glw::GLuint m_po_subroutine_returns_true_location;
1031     glw::GLint m_po_subroutine_uniform_bool_operator1;
1032     glw::GLint m_po_subroutine_uniform_bool_operator2;
1033     glw::GLint m_po_subroutine_uniform_vec4_processor1;
1034     glw::GLint m_po_subroutine_uniform_vec4_processor2;
1035     glw::GLuint m_xfb_bo_id;
1036     glw::GLuint m_vao_id;
1037     glw::GLuint m_vs_id;
1038 };
1039 
1040 /**
1041  *  Test whether all INVALID_OPERATION, INVALID_VALUE and INVALID_ENUM
1042  *  errors related to subroutines usage are properly generated.
1043  **/
1044 class NegativeTest1 : public deqp::TestCase
1045 {
1046 public:
1047     /* Public methods */
1048     NegativeTest1(deqp::Context &context);
1049 
1050     virtual void deinit();
1051     virtual tcu::TestNode::IterateResult iterate();
1052 
1053 private:
1054     /* Private methods */
1055     void initTest();
1056 
1057     /* Private fields */
1058     bool m_has_test_passed;
1059     glw::GLint m_po_active_subroutine_uniform_locations;
1060     glw::GLint m_po_active_subroutine_uniforms;
1061     glw::GLint m_po_active_subroutines;
1062     glw::GLint m_po_subroutine_uniform_function_index;
1063     glw::GLint m_po_subroutine_uniform_function2_index;
1064     glw::GLuint m_po_subroutine_test1_index;
1065     glw::GLuint m_po_subroutine_test2_index;
1066     glw::GLuint m_po_subroutine_test3_index;
1067     glw::GLuint m_po_not_linked_id;
1068     glw::GLuint m_po_id;
1069     glw::GLuint m_vs_id;
1070 };
1071 
1072 /** Make sure that subroutine uniform variables are scoped to the shader
1073  *  execution stage the variable is declared in. Referencing subroutine
1074  *  uniform from different stage should cause compile or link error
1075  **/
1076 class NegativeTest2 : public deqp::TestCase
1077 {
1078 public:
1079     /* Public methods */
1080     NegativeTest2(deqp::Context &context);
1081 
1082     virtual void deinit();
1083     virtual tcu::TestNode::IterateResult iterate();
1084 
1085 private:
1086     /* Private type definitions */
1087 
1088     /* Private methods */
1089     void deinitGLObjects();
1090     void executeTestCase(const Utils::_shader_stage &referencing_stage);
1091     std::string getFragmentShaderBody(const Utils::_shader_stage &referencing_stage) const;
1092     std::string getGeometryShaderBody(const Utils::_shader_stage &referencing_stage) const;
1093     std::string getSubroutineUniformName(const Utils::_shader_stage &stage) const;
1094     std::string getTessellationControlShaderBody(const Utils::_shader_stage &referencing_stage) const;
1095     std::string getTessellationEvaluationShaderBody(const Utils::_shader_stage &referencing_stage) const;
1096     std::string getVertexShaderBody(const Utils::_shader_stage &referencing_stage) const;
1097 
1098     /* Private fields */
1099     glw::GLuint m_fs_id;
1100     glw::GLuint m_gs_id;
1101     bool m_has_test_passed;
1102     glw::GLuint m_po_id;
1103     glw::GLuint m_tc_id;
1104     glw::GLuint m_te_id;
1105     glw::GLuint m_vs_id;
1106 };
1107 
1108 /** Verify that "subroutine" keyword is necessary when declaring a
1109  *  subroutine uniform and a compilation error occurs without it.
1110  **/
1111 class NegativeTest3 : public deqp::TestCase
1112 {
1113 public:
1114     /* Public methods */
1115     NegativeTest3(deqp::Context &context);
1116 
1117     virtual void deinit();
1118     virtual tcu::TestNode::IterateResult iterate();
1119 
1120 private:
1121     /* Private methods */
1122     void executeTest(const Utils::_shader_stage &shader_stage);
1123     std::string getFragmentShaderBody() const;
1124     std::string getGeometryShaderBody() const;
1125     std::string getTessellationControlShaderBody() const;
1126     std::string getTessellationEvaluationShaderBody() const;
1127     std::string getVertexShaderBody() const;
1128 
1129     /* Private fields */
1130     bool m_has_test_passed;
1131     glw::GLuint m_so_id;
1132 };
1133 
1134 /**
1135  *  Verify that compile-time error is present when arguments and return type
1136  *  do not match between the function and each associated subroutine type.
1137  *  In particular make sure that applies when there are multiple associated
1138  *  subroutine types and only one of them does not match.
1139  *
1140  **/
1141 class NegativeTest4 : public deqp::TestCase
1142 {
1143 public:
1144     /* Public methods */
1145     NegativeTest4(deqp::Context &context);
1146 
1147     virtual void deinit();
1148     virtual tcu::TestNode::IterateResult iterate();
1149 
1150 private:
1151     /* Private type declarations */
1152     enum _test_case
1153     {
1154         TEST_CASE_FIRST,
1155 
1156         TEST_CASE_INCOMPATIBLE_RETURN_TYPE = TEST_CASE_FIRST,
1157         TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST,
1158 
1159         /* Always last */
1160         TEST_CASE_COUNT
1161     };
1162 
1163     /* Private methods */
1164     std::string getShaderBody(const Utils::_shader_stage &shader_stage, const unsigned int &n_subroutine_types,
1165                               const _test_case &test_case) const;
1166 
1167     /* Private fields */
1168     bool m_has_test_passed;
1169     glw::GLint m_so_id;
1170 };
1171 
1172 /** Verify that link or compile error occurs when trying to link a program
1173  *  with no subroutine for subroutine uniform variable.
1174  **/
1175 class NegativeTest5 : public deqp::TestCase
1176 {
1177 public:
1178     /* Public methods */
1179     NegativeTest5(deqp::Context &context);
1180 
1181     virtual void deinit();
1182     virtual tcu::TestNode::IterateResult iterate();
1183 
1184 private:
1185     /* Private type definitions */
1186     /* Private methods */
1187     void deinitIteration();
1188     void executeIteration(const Utils::_shader_stage &shader_stage);
1189     std::string getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1190     std::string getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1191     std::string getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1192     std::string getTessellationEvaluationShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1193     std::string getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1194 
1195     /* Private fields */
1196     glw::GLuint m_fs_id;
1197     glw::GLuint m_gs_id;
1198     bool m_has_test_passed;
1199     glw::GLuint m_po_id;
1200     glw::GLuint m_tc_id;
1201     glw::GLuint m_te_id;
1202     glw::GLuint m_vs_id;
1203 };
1204 
1205 /** Check that link or compile error occurs if any shader in a program
1206  *  includes two or more functions with the same name and at least one of
1207  *  which is associated with a subroutine type.
1208  **/
1209 class NegativeTest6 : public deqp::TestCase
1210 {
1211 public:
1212     /* Public methods */
1213     NegativeTest6(deqp::Context &context);
1214 
1215     virtual void deinit();
1216     virtual tcu::TestNode::IterateResult iterate();
1217 
1218 private:
1219     /* Private type definitions */
1220     /* Private methods */
1221     void deinitIteration();
1222     void executeIteration(const Utils::_shader_stage &shader_stage);
1223     std::string getFragmentShaderBody(bool include_invalid_declaration) const;
1224     std::string getGeometryShaderBody(bool include_invalid_declaration) const;
1225     std::string getTessellationControlShaderBody(bool include_invalid_declaration) const;
1226     std::string getTessellationEvaluationShaderBody(bool include_invalid_declaration) const;
1227     std::string getVertexShaderBody(bool include_invalid_declaration) const;
1228 
1229     /* Private fields */
1230     glw::GLuint m_fs_id;
1231     glw::GLuint m_gs_id;
1232     bool m_has_test_passed;
1233     glw::GLuint m_po_id;
1234     glw::GLuint m_tc_id;
1235     glw::GLuint m_te_id;
1236     glw::GLuint m_vs_id;
1237 };
1238 
1239 /**
1240  * * Verify that program fails to link if there is any possible combination
1241  *   of subroutine uniform values that would result in recursion.
1242  **/
1243 class NegativeTest7 : public deqp::TestCase
1244 {
1245 public:
1246     NegativeTest7(deqp::Context &contex);
1247 
1248     virtual void deinit();
1249     virtual tcu::TestNode::IterateResult iterate();
1250 
1251 private:
1252     /* Private methods */
1253     bool test(const glw::GLchar *vertex_shader_code, const glw::GLchar *name_of_recursive_routine);
1254 
1255     /* Private fields */
1256     glw::GLuint m_program_id;
1257     glw::GLuint m_vertex_shader_id;
1258 };
1259 
1260 /** Test that either compile or link error occurs when function declared
1261  *  with subroutine does not include a body.
1262  **/
1263 class NegativeTest8 : public deqp::TestCase
1264 {
1265 public:
1266     /* Public methods */
1267     NegativeTest8(deqp::Context &context);
1268 
1269     virtual void deinit();
1270     virtual tcu::TestNode::IterateResult iterate();
1271 
1272 private:
1273     /* Private type definitions */
1274     /* Private methods */
1275     void deinitIteration();
1276     void executeIteration(const Utils::_shader_stage &shader_stage);
1277     std::string getFragmentShaderBody(bool include_invalid_declaration) const;
1278     std::string getGeometryShaderBody(bool include_invalid_declaration) const;
1279     std::string getTessellationControlShaderBody(bool include_invalid_declaration) const;
1280     std::string getTessellationEvaluationShaderBody(bool include_invalid_declaration) const;
1281     std::string getVertexShaderBody(bool include_invalid_declaration) const;
1282 
1283     /* Private fields */
1284     glw::GLuint m_fs_id;
1285     glw::GLuint m_gs_id;
1286     bool m_has_test_passed;
1287     glw::GLuint m_po_id;
1288     glw::GLuint m_tc_id;
1289     glw::GLuint m_te_id;
1290     glw::GLuint m_vs_id;
1291 };
1292 
1293 /**
1294  *   Make sure that it is not possible to assign float/int to subroutine
1295  *   uniform and that subroutine uniform values cannot be compared.
1296  *
1297  **/
1298 class NegativeTest9 : public deqp::TestCase
1299 {
1300 public:
1301     /* Public methods */
1302     NegativeTest9(deqp::Context &context);
1303 
1304     virtual void deinit();
1305     virtual tcu::TestNode::IterateResult iterate();
1306 
1307 private:
1308     /* Private type definitions */
1309     enum _test_case
1310     {
1311         TEST_CASE_FIRST,
1312 
1313         TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT = TEST_CASE_FIRST,
1314         TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT,
1315         TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON,
1316 
1317         /* Always last */
1318         TEST_CASE_COUNT
1319     };
1320 
1321     /* Private methods */
1322     std::string getTestCaseString(const _test_case &test_case);
1323     std::string getVertexShader(const _test_case &test_case);
1324 
1325     /* Private fields */
1326     bool m_has_test_passed;
1327     glw::GLuint m_po_id;
1328     glw::GLuint m_vs_id;
1329 };
1330 
1331 /**
1332  * Check that an overloaded function cannot be declared with subroutine and
1333  * a program will fail to compile or link if any shader or stage contains
1334  * two or more  functions with the same name if the name is associated with
1335  * a subroutine type.
1336  *
1337  **/
1338 class NegativeTest10 : public deqp::TestCase
1339 {
1340 public:
1341     /* Public methods */
1342     NegativeTest10(deqp::Context &context);
1343 
1344     virtual void deinit();
1345     virtual tcu::TestNode::IterateResult iterate();
1346 
1347 private:
1348     /* Private type definitions */
1349     struct _test_case
1350     {
1351         std::string name;
1352 
1353         std::string fs_body;
1354         std::string gs_body;
1355         std::string tc_body;
1356         std::string te_body;
1357         std::string vs_body;
1358     };
1359 
1360     typedef std::vector<_test_case> _test_cases;
1361     typedef _test_cases::const_iterator _test_cases_const_iterator;
1362 
1363     /* Private methods */
1364     std::string getFragmentShader(bool include_duplicate_function);
1365     std::string getGeometryShader(bool include_duplicate_function);
1366     std::string getTessellationControlShader(bool include_duplicate_function);
1367     std::string getTessellationEvaluationShader(bool include_duplicate_function);
1368     std::string getVertexShader(bool include_duplicate_function);
1369     void initTestCases();
1370 
1371     /* Private fields */
1372     bool m_has_test_passed;
1373     glw::GLuint m_fs_id;
1374     glw::GLuint m_gs_id;
1375     glw::GLuint m_po_id;
1376     glw::GLuint m_tc_id;
1377     glw::GLuint m_te_id;
1378     _test_cases m_test_cases;
1379     glw::GLuint m_vs_id;
1380 };
1381 
1382 /**
1383  *   Try to use subroutine uniform in invalid way in sampling, atomic and
1384  *   image functions. Verify that compile or link time error occurs.
1385  *
1386  **/
1387 class NegativeTest11 : public deqp::TestCase
1388 {
1389 public:
1390     /* Public methods */
1391     NegativeTest11(deqp::Context &context);
1392 
1393     virtual void deinit();
1394     virtual tcu::TestNode::IterateResult iterate();
1395 
1396 private:
1397     /* Private type definitions */
1398     enum _test_case
1399     {
1400         TEST_CASE_FIRST,
1401 
1402         TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT = TEST_CASE_FIRST,
1403         TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT,
1404         TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT,
1405 
1406         /* Always last */
1407         TEST_CASE_COUNT
1408     };
1409 
1410     /* Private methods */
1411     std::string getTestCaseString(const _test_case &test_case);
1412     std::string getVertexShader(const _test_case &test_case);
1413 
1414     /* Private fields */
1415     bool m_has_test_passed;
1416     glw::GLuint m_po_id;
1417     glw::GLuint m_vs_id;
1418 };
1419 
1420 /**
1421  *  Verify that it is not allowed to use subroutine type for local/global
1422  *  variables, constructors or argument/return type.
1423  *
1424  **/
1425 class NegativeTest12 : public deqp::TestCase
1426 {
1427 public:
1428     /* Public methods */
1429     NegativeTest12(deqp::Context &context);
1430 
1431     virtual void deinit();
1432     virtual tcu::TestNode::IterateResult iterate();
1433 
1434 private:
1435     /* Private type definitions */
1436     enum _test_case
1437     {
1438         TEST_CASE_FIRST,
1439 
1440         TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE = TEST_CASE_FIRST,
1441         TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE,
1442         TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR,
1443         TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT,
1444         TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE,
1445 
1446         /* Always last */
1447         TEST_CASE_COUNT
1448     };
1449 
1450     /* Private methods */
1451     std::string getTestCaseString(const _test_case &test_case);
1452     std::string getVertexShader(const _test_case &test_case);
1453 
1454     /* Private fields */
1455     bool m_has_test_passed;
1456     glw::GLuint m_po_id;
1457     glw::GLuint m_vs_id;
1458 };
1459 } // namespace ShaderSubroutine
1460 
1461 /** Group class for Shader Subroutine conformance tests */
1462 class ShaderSubroutineTests : public deqp::TestCaseGroup
1463 {
1464 public:
1465     /* Public methods */
1466     ShaderSubroutineTests(deqp::Context &context);
~ShaderSubroutineTests()1467     virtual ~ShaderSubroutineTests()
1468     {
1469     }
1470 
1471     virtual void init(void);
1472 
1473 private:
1474     /* Private methods */
1475     ShaderSubroutineTests(const ShaderSubroutineTests &);
1476     ShaderSubroutineTests &operator=(const ShaderSubroutineTests &);
1477 };
1478 
1479 } // namespace gl4cts
1480 
1481 #endif // _GL4CSHADERSUBROUTINETESTS_HPP
1482