xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gles31/es31cSeparateShaderObjsTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 #include "es31cSeparateShaderObjsTests.hpp"
25 #include "deMath.h"
26 #include "deRandom.hpp"
27 #include "deString.h"
28 #include "deStringUtil.hpp"
29 #include "gluDrawUtil.hpp"
30 #include "gluPixelTransfer.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "glw.h"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuStringTemplate.hpp"
38 #include "tcuSurface.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuVector.hpp"
41 
42 #include <map>
43 
44 /*************************************************************************/
45 /* Test Plan for shared_shader_objects:
46  * Overview
47  *
48  *    This is a conformance test for XXX_separate_shader_objects extension. The
49  *    results of the tests are verified by checking the expected GL error,
50  *    by checking the expected state with state query functions and by rendering
51  *    test images and comparing specified pixels with expected values. Not all of
52  *    the methods are applicable for all tests. Additional details such as
53  *    expected error codes are included in test descriptions.
54  *
55  *New Tests
56  *
57  *--  Tests for invidual API functions
58  *
59  *
60  *    CreateShaderProgramv tests
61  *
62  *    Positive tests:
63  *
64  *    * Test with valid parameters and verify that program and GL state are set
65  *      accordingly to the code sequence defined in the extension spec.
66  *    * Test with vertex and fragment shader types.
67  *    * Test with few different count/strings parameters (count >= 1)
68  *
69  *    Negative tests:
70  *
71  *    * Test with invalid type. Expect INVALID_ENUM and zero return value.
72  *    * Test with uncompilable / unlinkable source. Expect no errors. Program
73  *      should be returned Program info log may contain information about link /
74  *      compile failure.
75  *    * Test with count < 0. Expect INVALID_VALUE and zero return value.
76  *
77  *
78  *    UseProgramStages tests
79  *
80  *    Positive tests:
81  *
82  *    * Test with a program containing
83  *      - vertex stage only
84  *      - fragment stage only
85  *      - both stages
86  *    * Test with null program to reset a stage or stages. Expect no errors.
87  *    * Test with a program that doesn't contain code for a stage defined in the
88  *      stages bitfield. Expect no errors.
89  *    * Test with a new program pipeline object that has not yet been used/bound.
90  *
91  *    Negative tests:
92  *
93  *    * Test with invalid stages bitfield (with unused bits). Expect INVALID_VALUE GL error.
94  *    * Test with deleted/nonexistent pipeline. Expect INVALID_OPERATION GL error.
95  *    * Test with program that isn't separable. Expect INVALID_OPERATION GL error.
96  *    * Test with program that isn't linked succesfully. Expect INVALID_OPERATION
97  *      GL error.
98  *    * Test with deleted/nonexistent program. Expect INVALID_OPERATION error.
99  *
100  *
101  *    ActiveShaderProgram tests
102  *
103  *    Positive tests:
104  *
105  *    * Test with a new program pipeline object that has not yet been used/bound.
106  *
107  *    Negative tests:
108  *
109  *    * Test with deleted/nonexistent program pipeline object. Expect INVALID_OPERATION and no
110  *      changes to active program.
111  *    * Test with nonexistent/deleted/unsuccesfully linked program. Expect
112  *      INVALID_OPERATION GL error and no changes to active program.
113  *
114  *
115  *    GenProgramPipelines tests
116  *
117  *    Positive tests:
118  *
119  *    * Test creating different amounts of program pipeline object names.
120  *      Verify with IsProgramPipeline.
121  *
122  *
123  *    BindProgramPipeline tests
124  *
125  *    Positive tests:
126  *
127  *    * Test binding existing program pipeline object. Verify with
128  *      PROGRAM_PIPELINE_BINDING
129  *    * Test binding zero program pipeline object. Verify
130  *      PROGRAM_PIPELINE_BINDING is reset to 0
131  *
132  *    Negative tests:
133  *
134  *    * Test binding deleted/nonexistent program pipeline object. Expect
135  *      INVALID_OPERATION GL error and no changes to bound pipeline.
136  *
137  *
138  *    DeleteProgramPipelines tests
139  *
140  *    Positive tests:
141  *
142  *    * Test deleting zero and unused names. Expect no errors (should be no-op)
143  *    * Test deleting different amounts of existing pipeline names. Verify
144  *      deletion with IsProgramPipeline.
145  *    * Test deleting bound names. Expect pipeline binding revert to zero, verify
146  *      with PROGRAM_PIPELINE_BINDING.
147  *
148  *
149  *    IsProgramPipeline
150  *
151  *    Positive tests:
152  *
153  *    * Test with deleted/nonexistent program pipeline names.
154  *    * Test with existing program pipeline names.
155  *
156  *
157  *    ProgramParameteri / PROGRAM_SEPARABLE tests
158  *
159  *    Positive tests:
160  *
161  *    * Test setting TRUE and FALSE values for existing, unlinked programs.
162  *      Verify with GetProgramParameteri
163  *
164  *    Negative tests:
165  *
166  *    * Test with nonexistent/deleted program. Expect INVALID_OPERATION GL error
167  *    * Test with invalid value. Expect INVALID_VALUE GL error
168  *
169  *
170  *    GetProgramPipelineiv tests
171  *
172  *    Positive tests:
173  *
174  *    * Test with new program pipeline object that has not yet been used/bound
175  *    * Test ACTIVE_PROGRAM
176  *    * Test VERTEX_SHADER
177  *    * Test FRAGMENT_SHADER
178  *    * Test VALIDATE_STATUS
179  *    * Test INFO_LOG_LENGTH
180  *
181  *    Negative tests:
182  *
183  *    * Test with deleted/nonexistent pipeline. Expect INVALID_OPERATION GL error
184  *
185  *
186  *    ValidateProgramPipeline tests:
187  *
188  *    Positive tests:
189  *
190  *    * Test with valid program pipeline. Expect VALIDATE_STATUS = TRUE
191  *    * Test with invalid program pipeline Expect VALIDATE_STATUS = FALSE
192  *    * Test with empty program pipeline (uninitialized, but bound). Expect VALIDATE_STATUS = FALSE.
193  *    * Test that initial (unvalidated) VALIDATE_STATUS is FALSE
194  *    * Test with a new program pipeline object that has not been used/bound yet
195  *
196  *    Negative tests:
197  *
198  *    * Test with deleted/nonexistent program pipeline object. Expect
199  *      INVALID_OPERATION
200  *
201  *
202  *    ProgramUniform* tests
203  *
204  *    Positive tests:
205  *
206  *    * Test all ProgramUniform* methods with few different parameters combinations
207  *    * Setup pipeline with programs A and B. Update uniforms for A and verify
208  *      that only A is affected.
209  *    * Test with a program with all combinations of
210  *      - program is/isn't part of a bound pipeline
211  *      - program is/isn't made current with UseProgram
212  *      - program is/isn't made active with ActiveShaderProgram
213  *      in all cases, only the uniforms of the specified program should be
214  *      updated.
215  *
216  *    Negative tests:
217  *
218  *    * Test with deleted/nonexistent program. Expect INVALID_VALUE GL error.
219  *    * Test with unsuccesfully linked program. Expect INVALID_OPERATION GL error.
220  *
221  *
222  *    GetProgramPipelineInfoLog tests
223  *
224  *    Run ValidateProgramPipeline for valid / invalid program pipeline object
225  *    before running the tests. NOTE: The spec doesn't require that the driver
226  *    updates the pipeline info log. It may or may not contain information about
227  *    validation.
228  *
229  *    Positive tests
230  *
231  *    * Test with NULL length.
232  *    * Test with zero bufSize. Expect no errors
233  *    * Test with varying bufSizes (where 0 < bufSize <= INFO_LOG_LENGTH). Except
234  *    * length = (bufSize - 1) and zero-terminated string with matching length in
235  *      infoLog.
236  *
237  *    Negative tests
238  *
239  *    * Test with deleted/nonexistent program pipeline object. Expect
240  *      GL_INVALID_VALUE error (the error is still missing from the spec)
241  *
242  *
243  *--  Other tests
244  *
245  *
246  *    UseProgram vs. BindProgramPipeline tests
247  *
248  *    Positive tests:
249  *
250  *    * Test that a program made active with UseProgram has precedence over
251  *      program pipeline object bound with BindProgramPipeline.
252  *    * Test that program(s) in bound program pipeline object will be used if
253  *      there is no active program set with UseProgram
254  *    * Test that a state without active program or without bound pipeline object
255  *      generates no errors.
256  *
257  *
258  *    Pipeline setup tests
259  *
260  *    Positive tests:
261  *
262  *    * Test that missing pipeline stages produces no errors:
263  *      - no program set with UseProgramStages for vertex or frargment stages
264  *      - no vertex or fragment code in a program set for the stage
265  *
266  *    Negative tests:
267  *
268  *    * Test that program with both vertex and fragment shaders cannot be attached
269  *      just to vertex or fragment stage. Expect DrawArrays/Elements to generate
270  *      INVALID_OPERATION and pipeline VALIDATE_STATUS set to FALSE.
271  *      - Run with and without validating the pipeline with ValidateProgramPipeline
272  *
273  *
274  *    Shader/program management tests
275  *
276  *    Positive tests:
277  *
278  *    * Test creating separable shader objects both by
279  *      - Using the core functions combined with PROGRAM_SEPARABLE flag
280  *      - CreateShaderProgram
281  *    * Test that separable program can contain and links properly if there are
282  *      - vertex stage
283  *      - fragment stage
284  *      - both stages
285  *    * Test that active program isn't deleted immediately (deletion doesn't
286  *      affect rendering state)
287  *    * Test that program in current pipeline isn't deleted immediately
288  *    * Test that attaching/detaching/recompiling a shader in active program or
289  *      program in current pipeline doesn't affect the program link status or
290  *      rendering state.
291  *    * Test that succesfully re-linking active program or program in current
292  *      pipeline affects the rendering state.
293  *
294  *    Negative tests:
295  *
296  *      aren't present.
297  *    * Test that unsuccesfully re-linking active program or program in current
298  *      pipeline sets LINK_STATUS=FALSE but doesn't affect the rendering state.
299  *    * Test that unsuccesfully linked program cannot be made part of a program
300  *      pipeline object.
301  *
302  *
303  *    Uniform update tests
304  *
305  *    Positive cases:
306  *
307  *      with UseProgram.
308  *    * Test that Uniform* functions update the uniforms of a program made active with
309  *      ActiveShader program if no program has been made active with UseProgram.
310  *    * Test that ProgramUniform* functions update the uniforms of a specified
311  *      program regardless of active program (probably already covered with
312  *      "ProgramUniform* tests")
313  *
314  *    Negative cases:
315  *
316  *    * Test that Uniform* functions set INVALID_OPERATION if there is no active
317  *      program set with UseProgram nor ActiveShaderProgram
318  *
319  *
320  *    Shader interface matching tests
321  *
322  *    Positive tests:
323  *
324  *    * Test that partially or completely mismatching shaders do not generate
325  *      validation nor other GL errors (just undefined inputs)
326  *    * Test that exactly matching shaders work.
327  *    * Test that variables with matching layout qualifiers match and are defined
328  *      even if the shaders don't match exactly.
329  *      - Test with int, uint and float component types
330  *      - Test with different vector sizes, where output vector size >= input
331  *        vector size
332  *
333  *
334  * End Test Plan */
335 /*************************************************************************/
336 
337 namespace glcts
338 {
339 
340 using std::string;
341 using std::vector;
342 using tcu::TestLog;
343 
344 // A fragment shader to allow testing various scalar and vector
345 // uniforms as well as array [2] varieties.  To keep the uniforms
346 // active they are compared against constants.
347 static const char *s_unifFragShaderSrc =
348     "precision highp float;\n"
349     "uniform ${SCALAR_TYPE}  uVal0;\n"
350     "uniform ${VECTOR_TYPE}2 uVal1;\n"
351     "uniform ${VECTOR_TYPE}3 uVal2;\n"
352     "uniform ${VECTOR_TYPE}4 uVal3;\n"
353     "\n"
354     "uniform ${SCALAR_TYPE}  uVal4[2];\n"
355     "uniform ${VECTOR_TYPE}2 uVal5[2];\n"
356     "uniform ${VECTOR_TYPE}3 uVal6[2];\n"
357     "uniform ${VECTOR_TYPE}4 uVal7[2];\n"
358     "\n"
359     "const ${SCALAR_TYPE}  kVal0= 1${SFX};\n"
360     "const ${VECTOR_TYPE}2 kVal1 = ${VECTOR_TYPE}2(2${SFX}, 3${SFX});\n"
361     "const ${VECTOR_TYPE}3 kVal2 = ${VECTOR_TYPE}3(4${SFX}, 5${SFX}, 6${SFX});\n"
362     "const ${VECTOR_TYPE}4 kVal3 = ${VECTOR_TYPE}4(7${SFX}, 8${SFX}, 9${SFX}, 10${SFX});\n"
363     "\n"
364     "const ${SCALAR_TYPE}  kArr4_0 = 11${SFX};\n"
365     "const ${SCALAR_TYPE}  kArr4_1 = 12${SFX};\n"
366     "const ${VECTOR_TYPE}2 kArr5_0 = ${VECTOR_TYPE}2(13${SFX}, 14${SFX});\n"
367     "const ${VECTOR_TYPE}2 kArr5_1 = ${VECTOR_TYPE}2(15${SFX}, 16${SFX});\n"
368     "const ${VECTOR_TYPE}3 kArr6_0 = ${VECTOR_TYPE}3(17${SFX}, 18${SFX}, 19${SFX});\n"
369     "const ${VECTOR_TYPE}3 kArr6_1 = ${VECTOR_TYPE}3(20${SFX}, 21${SFX}, 22${SFX});\n"
370     "const ${VECTOR_TYPE}4 kArr7_0 = ${VECTOR_TYPE}4(23${SFX}, 24${SFX}, 25${SFX}, 26${SFX});\n"
371     "const ${VECTOR_TYPE}4 kArr7_1 = ${VECTOR_TYPE}4(27${SFX}, 28${SFX}, 29${SFX}, 30${SFX});\n"
372     "\n"
373     "layout(location = 0) out mediump vec4 o_color;\n"
374     "\n"
375     "void main() {\n"
376     "    if ((uVal0 != kVal0) ||\n"
377     "        (uVal1 != kVal1) ||\n"
378     "        (uVal2 != kVal2) ||\n"
379     "        (uVal3 != kVal3) ||\n"
380     "        (uVal4[0] != kArr4_0) || (uVal4[1] != kArr4_1) ||\n"
381     "        (uVal5[0] != kArr5_0) || (uVal5[1] != kArr5_1) ||\n"
382     "        (uVal6[0] != kArr6_0) || (uVal6[1] != kArr6_1) ||\n"
383     "        (uVal7[0] != kArr7_0) || (uVal7[1] != kArr7_1)) {\n"
384     "        o_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
385     "    } else {\n"
386     "        o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
387     "    }\n"
388     "}\n";
389 
390 // A fragment shader to test uniforms of square matrices
391 static const char *s_unifFragSquareMatShaderSrc = "precision highp float;\n"
392                                                   "uniform mat2 uValM2[2];\n"
393                                                   "uniform mat3 uValM3[2];\n"
394                                                   "uniform mat4 uValM4[2];\n"
395                                                   "\n"
396                                                   "const mat2 kMat2_0 = mat2(91.0, 92.0, 93.0, 94.0);\n"
397                                                   "const mat2 kMat2_1 = mat2(95.0, 96.0, 97.0, 98.0);\n"
398                                                   "const mat3 kMat3_0 = mat3(vec3( 99.0, 100.0, 101.0),\n"
399                                                   "                          vec3(102.0, 103.0, 104.0),\n"
400                                                   "                          vec3(105.0, 106.0, 107.0));\n"
401                                                   "const mat3 kMat3_1 = mat3(vec3(108.0, 109.0, 110.0),\n"
402                                                   "                          vec3(111.0, 112.0, 113.0),\n"
403                                                   "                          vec3(114.0, 115.0, 116.0));\n"
404                                                   "const mat4 kMat4_0 = mat4(vec4(117.0, 118.0, 119.0, 120.0),\n"
405                                                   "                          vec4(121.0, 122.0, 123.0, 124.0),\n"
406                                                   "                          vec4(125.0, 126.0, 127.0, 128.0),\n"
407                                                   "                          vec4(129.0, 130.0, 131.0, 132.0));\n"
408                                                   "const mat4 kMat4_1 = mat4(vec4(133.0, 134.0, 135.0, 136.0),\n"
409                                                   "                          vec4(137.0, 138.0, 139.0, 140.0),\n"
410                                                   "                          vec4(141.0, 142.0, 143.0, 144.0),\n"
411                                                   "                          vec4(145.0, 146.0, 147.0, 148.0));\n"
412                                                   "\n"
413                                                   "layout(location = 0) out mediump vec4 o_color;\n"
414                                                   "\n"
415                                                   "void main() {\n"
416                                                   "    if ((uValM2[0] != kMat2_0) || (uValM2[1] != kMat2_1) ||\n"
417                                                   "        (uValM3[0] != kMat3_0) || (uValM3[1] != kMat3_1) ||\n"
418                                                   "        (uValM4[0] != kMat4_0) || (uValM4[1] != kMat4_1)) {\n"
419                                                   "        o_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
420                                                   "    } else {\n"
421                                                   "        o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
422                                                   "    }\n"
423                                                   "}\n";
424 
425 // A fragment shader to test uniforms of square matrices
426 static const char *s_unifFragNonSquareMatShaderSrc =
427     "precision highp float;\n"
428     "uniform mat2x3 uValM2x3[2];\n"
429     "uniform mat3x2 uValM3x2[2];\n"
430     "uniform mat2x4 uValM2x4[2];\n"
431     "uniform mat4x2 uValM4x2[2];\n"
432     "uniform mat3x4 uValM3x4[2];\n"
433     "uniform mat4x3 uValM4x3[2];\n"
434     "\n"
435     "const mat2x3 kMat2x3_0 = mat2x3(vec2(149.0, 150.0),\n"
436     "                                vec2(151.0, 152.0),\n"
437     "                                vec2(153.0, 154.0));\n"
438     "const mat2x3 kMat2x3_1 = mat2x3(vec2(155.0, 156.0),\n"
439     "                                vec2(157.0, 158.0),\n"
440     "                                vec2(159.0, 160.0));\n"
441     "const mat3x2 kMat3x2_0 = mat3x2(vec3(161.0, 162.0, 163.0),\n"
442     "                                vec3(164.0, 165.0, 166.0));\n"
443     "const mat3x2 kMat3x2_1 = mat3x2(vec3(167.0, 168.0, 169.0),\n"
444     "                                vec3(170.0, 171.0, 172.0));\n"
445     "const mat2x4 kMat2x4_0 = mat2x4(vec2(173.0, 174.0),\n"
446     "                                vec2(175.0, 176.0),\n"
447     "                                vec2(177.0, 178.0),\n"
448     "                                vec2(179.0, 180.0));\n"
449     "const mat2x4 kMat2x4_1 = mat2x4(vec2(181.0, 182.0),\n"
450     "                                vec2(183.0, 184.0),\n"
451     "                                vec2(185.0, 186.0),\n"
452     "                                vec2(187.0, 188.0));\n"
453     "const mat4x2 kMat4x2_0 = mat4x2(vec4(189.0, 190.0, 191.0, 192.0),\n"
454     "                                vec4(193.0, 194.0, 195.0, 196.0));\n"
455     "const mat4x2 kMat4x2_1 = mat4x2(vec4(197.0, 198.0, 199.0, 200.0),\n"
456     "                                vec4(201.0, 202.0, 203.0, 204.0));\n"
457     "const mat3x4 kMat3x4_0 = mat3x4(vec3(205.0, 206.0, 207.0),\n"
458     "                                vec3(208.0, 209.0, 210.0),\n"
459     "                                vec3(211.0, 212.0, 213.0),\n"
460     "                                vec3(214.0, 215.0, 216.0));\n"
461     "const mat3x4 kMat3x4_1 = mat3x4(vec3(217.0, 218.0, 219.0),\n"
462     "                                vec3(220.0, 221.0, 222.0),\n"
463     "                                vec3(223.0, 224.0, 225.0),\n"
464     "                                vec3(226.0, 227.0, 228.0));\n"
465     "const mat4x3 kMat4x3_0 = mat4x3(vec4(229.0, 230.0, 231.0, 232.0),\n"
466     "                                vec4(233.0, 234.0, 235.0, 236.0),\n"
467     "                                vec4(237.0, 238.0, 239.0, 240.0));\n"
468     "const mat4x3 kMat4x3_1 = mat4x3(vec4(241.0, 242.0, 243.0, 244.0),\n"
469     "                                vec4(245.0, 246.0, 247.0, 248.0),\n"
470     "                                vec4(249.0, 250.0, 251.0, 252.0));\n"
471     "\n"
472     "layout(location = 0) out mediump vec4 o_color;\n"
473     "\n"
474     "void main() {\n"
475     "    if ((uValM2x3[0] != kMat2x3_0) || (uValM2x3[1] != kMat2x3_1) ||\n"
476     "        (uValM3x2[0] != kMat3x2_0) || (uValM3x2[1] != kMat3x2_1) ||\n"
477     "        (uValM2x4[0] != kMat2x4_0) || (uValM2x4[1] != kMat2x4_1) ||\n"
478     "        (uValM4x2[0] != kMat4x2_0) || (uValM4x2[1] != kMat4x2_1) ||\n"
479     "        (uValM3x4[0] != kMat3x4_0) || (uValM3x4[1] != kMat3x4_1) ||\n"
480     "        (uValM4x3[0] != kMat4x3_0) || (uValM4x3[1] != kMat4x3_1)) {\n"
481     "        o_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
482     "    } else {\n"
483     "        o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
484     "    }\n"
485     "}\n";
486 
generateBasicVertexSrc(glu::GLSLVersion glslVersion)487 static std::string generateBasicVertexSrc(glu::GLSLVersion glslVersion)
488 {
489     std::stringstream str;
490 
491     str << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
492     str << "in highp vec4 a_position;\n";
493     if (glslVersion >= glu::GLSL_VERSION_410)
494     {
495         str << "out gl_PerVertex {\n"
496                "  vec4 gl_Position;\n"
497                "};\n";
498     }
499     str << "void main (void)\n"
500            "{\n"
501            "   gl_Position = a_position;\n"
502            "}\n";
503 
504     return str.str();
505 }
506 
generateBasicFragmentSrc(glu::GLSLVersion glslVersion)507 static std::string generateBasicFragmentSrc(glu::GLSLVersion glslVersion)
508 {
509     std::stringstream str;
510 
511     str << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
512     str << "uniform highp vec4 u_color;\n"
513            "layout(location = 0) out mediump vec4 o_color;\n"
514            "void main (void)\n"
515            "{\n"
516            "   o_color = u_color;\n"
517            "}\n";
518 
519     return str.str();
520 }
521 
522 // Testcase for glCreateShaderProgramv
523 class CreateShadProgCase : public TestCase
524 {
525 public:
CreateShadProgCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)526     CreateShadProgCase(Context &context, const char *name, const char *description, glu::GLSLVersion glslVersion)
527         : TestCase(context, name, description)
528         , m_glslVersion(glslVersion)
529     {
530     }
531 
~CreateShadProgCase(void)532     ~CreateShadProgCase(void)
533     {
534     }
535 
536     // Check program validity created with CreateShaderProgram
checkCSProg(const glw::Functions & gl,GLuint program,int expectedSep=GL_TRUE,int expectedLink=GL_TRUE)537     bool checkCSProg(const glw::Functions &gl, GLuint program, int expectedSep = GL_TRUE, int expectedLink = GL_TRUE)
538     {
539         int separable = GL_FALSE;
540         int linked    = GL_FALSE;
541         if (program != 0)
542         {
543             gl.getProgramiv(program, GL_PROGRAM_SEPARABLE, &separable);
544             gl.getProgramiv(program, GL_LINK_STATUS, &linked);
545         }
546 
547         return (program != 0) && (separable == expectedSep) && (linked == expectedLink);
548     }
549 
iterate(void)550     IterateResult iterate(void)
551     {
552         TestLog &log             = m_testCtx.getLog();
553         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
554         int i;
555         const char *srcStrings[10];
556         glw::GLuint program;
557         glw::GLenum err;
558 
559         // CreateShaderProgramv verification
560         log << TestLog::Message << "Begin:CreateShadProgCase iterate" << TestLog::EndMessage;
561 
562         // vertex shader
563         i               = 0;
564         srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion);
565         srcStrings[i++] = "\n";
566         if (m_glslVersion >= glu::GLSL_VERSION_410)
567         {
568             srcStrings[i++] = "out gl_PerVertex {\n"
569                               "  vec4 gl_Position;\n"
570                               "};\n";
571         }
572         srcStrings[i++] = "in vec4 a_position;\n";
573         srcStrings[i++] = "void main ()\n";
574         srcStrings[i++] = "{\n";
575         srcStrings[i++] = "    gl_Position = a_position;\n";
576         srcStrings[i++] = "}\n";
577 
578         program = gl.createShaderProgramv(GL_VERTEX_SHADER, i, srcStrings);
579         if (!checkCSProg(gl, program))
580         {
581             TCU_FAIL("CreateShaderProgramv failed for vertex shader");
582         }
583 
584         gl.deleteProgram(program);
585 
586         // Half as many strings
587         i               = 0;
588         srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion);
589         srcStrings[i++] = "\n";
590         if (m_glslVersion >= glu::GLSL_VERSION_410)
591         {
592             srcStrings[i++] = "out gl_PerVertex {\n"
593                               "  vec4 gl_Position;\n"
594                               "};\n";
595         }
596         srcStrings[i++] = "in vec4 a_position;\n"
597                           "void main ()\n";
598         srcStrings[i++] = "{\n"
599                           "    gl_Position = a_position;\n";
600         srcStrings[i++] = "}\n";
601 
602         program = gl.createShaderProgramv(GL_VERTEX_SHADER, i, srcStrings);
603         if (!checkCSProg(gl, program))
604         {
605             TCU_FAIL("CreateShaderProgramv failed for vertex shader");
606         }
607 
608         gl.deleteProgram(program);
609 
610         // Fragment shader
611         i               = 0;
612         srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion);
613         srcStrings[i++] = "\nin highp vec4 u_color;\n";
614         srcStrings[i++] = "layout(location = 0) out mediump vec4 o_color;\n";
615         srcStrings[i++] = "void main ()\n";
616         srcStrings[i++] = "{\n";
617         srcStrings[i++] = "    o_color = u_color;\n";
618         srcStrings[i++] = "}\n";
619 
620         program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, i, srcStrings);
621         if (!checkCSProg(gl, program))
622         {
623             TCU_FAIL("CreateShaderProgramv failed for fragment shader");
624         }
625 
626         gl.deleteProgram(program);
627 
628         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShaderProgramv failed");
629 
630         // Negative Cases
631 
632         // invalid type
633         program = gl.createShaderProgramv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, i, srcStrings);
634         err     = gl.getError();
635         if ((program != 0) || (err != GL_INVALID_ENUM))
636         {
637             TCU_FAIL("CreateShaderProgramv failed");
638         }
639 
640         // Negative count
641         program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, -1, srcStrings);
642         err     = gl.getError();
643         if ((program != 0) || (err != GL_INVALID_VALUE))
644         {
645             TCU_FAIL("CreateShaderProgramv failed");
646         }
647 
648         // source compile error
649         i               = 0;
650         srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion);
651         srcStrings[i++] = "\nin highp vec4 u_color;\n";
652         srcStrings[i++] = "layout(location = 0) out mediump vec4 o_color;\n";
653         srcStrings[i++] = "void main ()\n";
654         srcStrings[i++] = "{\n";
655         srcStrings[i++] = "    o_color = u_color;\n";
656 
657         program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, i, srcStrings);
658         // expect valid program and false for link status
659         if (!checkCSProg(gl, program, GL_FALSE, GL_FALSE))
660         {
661             TCU_FAIL("CreateShaderProgramv failed for fragment shader");
662         }
663         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShaderProgramv failed");
664         gl.deleteProgram(program);
665 
666         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
667         return STOP;
668     }
669 
670 private:
671     glu::GLSLVersion m_glslVersion;
672 };
673 
674 // Testcase for glUseProgamStages
675 class UseProgStagesCase : public TestCase
676 {
677 public:
UseProgStagesCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)678     UseProgStagesCase(Context &context, const char *name, const char *description, glu::GLSLVersion glslVersion)
679         : TestCase(context, name, description)
680         , m_glslVersion(glslVersion)
681     {
682     }
683 
~UseProgStagesCase(void)684     ~UseProgStagesCase(void)
685     {
686     }
687 
iterate(void)688     IterateResult iterate(void)
689     {
690         TestLog &log             = m_testCtx.getLog();
691         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
692         glw::GLenum err;
693         glw::GLuint pipeline;
694         glw::GLuint progIdV, progIdF;
695         glw::GLuint programVtx, programFrag;
696         const char *shaderSrc[1];
697         std::string vtx;
698         std::string frag;
699         glw::GLint linkStatus;
700 
701         vtx  = generateBasicVertexSrc(m_glslVersion);
702         frag = generateBasicFragmentSrc(m_glslVersion);
703 
704         // UseProgramStages verification
705         log << TestLog::Message << "Begin:UseProgStagesCase iterate" << TestLog::EndMessage;
706 
707         gl.genProgramPipelines(1, &pipeline);
708         gl.bindProgramPipeline(pipeline);
709 
710         // Use Vertex Shader
711         shaderSrc[0] = vtx.c_str();
712         programVtx   = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, shaderSrc);
713 
714         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx);
715         gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint *)&progIdV);
716         gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint *)&progIdF);
717         if ((programVtx == 0) || (progIdV != programVtx) || (progIdF != 0))
718         {
719             TCU_FAIL("UseProgramStages failed");
720         }
721         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
722 
723         // Use Fragment Shader
724         shaderSrc[0] = frag.c_str();
725         programFrag  = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc);
726 
727         gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programFrag);
728         gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint *)&progIdF);
729         if ((programFrag == 0) || (progIdF != programFrag) || (progIdF == progIdV))
730         {
731             TCU_FAIL("UseProgramStages failed");
732         }
733 
734         // Reset stages
735         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0);
736         gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint *)&progIdV);
737         gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint *)&progIdF);
738         if ((progIdV != 0) || (progIdF != 0))
739         {
740             TCU_FAIL("UseProgramStages failed");
741         }
742 
743         // One program for both.
744         glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str()));
745 
746         // Make separable and relink
747         gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
748         gl.linkProgram(progVF.getProgram());
749         gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus);
750         if (linkStatus != 1)
751         {
752             TCU_FAIL("UseProgramStages failed");
753         }
754         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
755 
756         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram());
757         gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint *)&progIdV);
758         gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint *)&progIdF);
759         if ((progIdV != progVF.getProgram()) || (progIdV != progIdF))
760         {
761             TCU_FAIL("UseProgramStages failed");
762         }
763         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
764 
765         // Use a fragment program with vertex bit
766         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0);
767         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programFrag);
768         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
769 
770         // Unbound pipeline
771         gl.bindProgramPipeline(0);
772         gl.deleteProgramPipelines(1, &pipeline);
773         pipeline = 0;
774         gl.genProgramPipelines(1, &pipeline);
775         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx);
776         gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programFrag);
777         gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint *)&progIdV);
778         gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint *)&progIdF);
779         if ((progIdV != programVtx) || (progIdF != programFrag))
780         {
781             TCU_FAIL("UseProgramStages failed");
782         }
783         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
784 
785         // Negative Cases
786 
787         // Invalid stages
788         gl.useProgramStages(pipeline, GL_ALL_SHADER_BITS ^ (GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT), programVtx);
789         err = gl.getError();
790         if (err != GL_INVALID_VALUE)
791         {
792             TCU_FAIL("UseProgramStages failed");
793         }
794 
795         // Program that is not separable
796         gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
797         gl.linkProgram(progVF.getProgram());
798         gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus);
799         if (linkStatus != 1)
800         {
801             TCU_FAIL("UseProgramStages failed");
802         }
803         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
804         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram());
805         err = gl.getError();
806         if (err != GL_INVALID_OPERATION)
807         {
808             TCU_FAIL("UseProgramStages failed");
809         }
810 
811         // Program that is not successfully linked
812         // remove the main keyword
813         std::string fragNoMain = frag;
814         unsigned int pos       = (unsigned int)fragNoMain.find("main");
815         fragNoMain.replace(pos, 4, "niaM");
816         glu::ShaderProgram progNoLink(m_context.getRenderContext(),
817                                       glu::makeVtxFragSources(vtx.c_str(), fragNoMain.c_str()));
818 
819         gl.programParameteri(progNoLink.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
820         gl.linkProgram(progNoLink.getProgram());
821         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progNoLink.getProgram());
822         err = gl.getError();
823         if (err != GL_INVALID_OPERATION)
824         {
825             TCU_FAIL("UseProgramStages failed");
826         }
827 
828         // Invalid pipeline
829         gl.useProgramStages(pipeline + 1000, GL_VERTEX_SHADER_BIT, programVtx);
830         err = gl.getError();
831         if (err != GL_INVALID_OPERATION)
832         {
833             TCU_FAIL("UseProgramStages failed");
834         }
835 
836         // Invalid pipeline
837         gl.deleteProgramPipelines(1, &pipeline);
838         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx);
839         err = gl.getError();
840         if (err != GL_INVALID_OPERATION)
841         {
842             TCU_FAIL("UseProgramStages failed");
843         }
844 
845         gl.deleteProgram(programVtx);
846         gl.deleteProgram(programFrag);
847 
848         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
849         return STOP;
850     }
851 
852 private:
853     glu::GLSLVersion m_glslVersion;
854 };
855 
856 // Testcase for pipeline api
857 class PipelineApiCase : public TestCase
858 {
859 public:
PipelineApiCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)860     PipelineApiCase(Context &context, const char *name, const char *description, glu::GLSLVersion glslVersion)
861         : TestCase(context, name, description)
862         , m_glslVersion(glslVersion)
863     {
864     }
865 
~PipelineApiCase(void)866     ~PipelineApiCase(void)
867     {
868     }
869 
870     // Validate glGetProgramPipelineInfoLog
checkProgInfoLog(const glw::Functions & gl,GLuint pipeline)871     void checkProgInfoLog(const glw::Functions &gl, GLuint pipeline)
872     {
873         glw::GLint value;
874         glw::GLsizei bufSize;
875         glw::GLsizei length;
876         glw::GLenum err;
877 
878         gl.getProgramPipelineiv(pipeline, GL_INFO_LOG_LENGTH, &value);
879         std::vector<char> infoLogBuf(value + 1);
880 
881         bufSize = 0;
882         gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]);
883         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramPipelineInfoLog failed");
884 
885         bufSize = value / 2; // read half the log
886         gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]);
887         if ((bufSize != 0) && (bufSize != length + 1))
888         {
889             TCU_FAIL("GetProgramPipelineInfoLog failed");
890         }
891         bufSize = value;
892         gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]);
893         if ((bufSize != 0) && (bufSize != length + 1))
894         {
895             TCU_FAIL("GetProgramPipelineInfoLog failed");
896         }
897 
898         // Negative case for GetProgramPipelineInfoLog
899 
900         gl.getProgramPipelineInfoLog(pipeline + 101, bufSize, &length, &infoLogBuf[0]);
901         err = gl.getError();
902         if (err != GL_INVALID_VALUE)
903         {
904             TCU_FAIL("GetProgramPipelineInfoLog failed");
905         }
906     }
907 
iterate(void)908     IterateResult iterate(void)
909     {
910         TestLog &log             = m_testCtx.getLog();
911         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
912         glw::GLenum err;
913         const int maxpipelines = 10;
914         glw::GLuint pipelines[maxpipelines];
915         std::string vtx;
916         std::string frag;
917         glw::GLint linkStatus;
918         glw::GLuint value;
919 
920         vtx  = generateBasicVertexSrc(m_glslVersion);
921         frag = generateBasicFragmentSrc(m_glslVersion);
922 
923         // Pipeline API verification
924         log << TestLog::Message << "Begin:PipelineApiCase iterate" << TestLog::EndMessage;
925 
926         glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str()));
927 
928         // Make separable and relink
929         gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
930         gl.linkProgram(progVF.getProgram());
931         gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus);
932         if (linkStatus != 1)
933         {
934             TCU_FAIL("LinkProgram failed");
935         }
936 
937         gl.genProgramPipelines(1, pipelines);
938 
939         // ActiveShaderProgram
940         gl.activeShaderProgram(pipelines[0], progVF.getProgram());
941         GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveShaderProgram failed");
942 
943         // Negative cases for ActiveShaderProgram
944 
945         // Nonexistent program
946         gl.activeShaderProgram(pipelines[0], progVF.getProgram() + 100);
947         err = gl.getError();
948         if (err != GL_INVALID_VALUE)
949         {
950             TCU_FAIL("ActiveShaderProgram failed");
951         }
952         gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint *)&value);
953         if (value != progVF.getProgram())
954         {
955             TCU_FAIL("ActiveShaderProgram failed");
956         }
957 
958         // Deleted pipeline
959         gl.deleteProgramPipelines(1, pipelines);
960         gl.activeShaderProgram(pipelines[0], progVF.getProgram());
961         err = gl.getError();
962         if (err != GL_INVALID_OPERATION)
963         {
964             TCU_FAIL("ActiveShaderProgram failed");
965         }
966 
967         // GenProgramPipeline
968 
969         gl.genProgramPipelines(2, &pipelines[0]);
970         gl.genProgramPipelines(3, &pipelines[2]);
971         gl.genProgramPipelines(5, &pipelines[5]);
972 
973         for (int i = 0; i < maxpipelines; i++)
974         {
975             gl.bindProgramPipeline(pipelines[i]); // has to be bound to be recognized
976             if (!gl.isProgramPipeline(pipelines[i]))
977             {
978                 TCU_FAIL("GenProgramPipelines failed");
979             }
980         }
981         gl.deleteProgramPipelines(maxpipelines, pipelines);
982 
983         // BindProgramPipeline
984 
985         gl.genProgramPipelines(2, pipelines);
986         gl.bindProgramPipeline(pipelines[0]);
987         gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint *)&value);
988         if (value != pipelines[0])
989         {
990             TCU_FAIL("BindProgramPipeline failed");
991         }
992         gl.bindProgramPipeline(pipelines[1]);
993         gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint *)&value);
994         if (value != pipelines[1])
995         {
996             TCU_FAIL("BindProgramPipeline failed");
997         }
998         GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline failed");
999 
1000         // Negative Case for BindProgramPipeline
1001 
1002         gl.bindProgramPipeline(pipelines[2]); // deleted pipeline
1003         gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint *)&value);
1004         err = gl.getError();
1005         if ((err != GL_INVALID_OPERATION) || (value != pipelines[1]))
1006         {
1007             TCU_FAIL("BindProgramPipeline failed");
1008         }
1009 
1010         // DeleteProgramPipelines
1011 
1012         gl.genProgramPipelines(8, &pipelines[2]); // back to 10 total
1013         gl.deleteProgramPipelines(2, &pipelines[8]);
1014         gl.deleteProgramPipelines(3, &pipelines[5]);
1015         pipelines[9] = 0;
1016         gl.deleteProgramPipelines(maxpipelines, pipelines); // 5 good, 4 deleted, 1 zero
1017         gl.deleteProgramPipelines(0, pipelines);
1018         GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteProgramPipelines failed");
1019         for (int i = 0; i < maxpipelines; i++)
1020         {
1021             if (gl.isProgramPipeline(pipelines[i]))
1022             {
1023                 TCU_FAIL("DeleteProgramPipelines failed");
1024             }
1025         }
1026         gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint *)&value);
1027         if (value != 0)
1028         {
1029             TCU_FAIL("DeleteProgramPipelines failed");
1030         }
1031 
1032         // IsProgramPipeline
1033 
1034         pipelines[1] = 0x1000;
1035         pipelines[2] += 100;
1036         for (int i = 0; i < 3; i++)
1037         {
1038             // 1 deleted and 2 bogus values
1039             if (gl.isProgramPipeline(pipelines[i]))
1040             {
1041                 TCU_FAIL("IsProgramPipeline failed");
1042             }
1043         }
1044         gl.genProgramPipelines(1, pipelines);
1045         if (gl.isProgramPipeline(pipelines[0]))
1046         {
1047             TCU_FAIL("IsProgramPipeline failed");
1048         }
1049         gl.deleteProgramPipelines(1, pipelines);
1050         GLU_EXPECT_NO_ERROR(gl.getError(), "IsProgramPipeline failed");
1051 
1052         // ProgramParameteri PROGRAM_SEPARABLE
1053         // NOTE: The query for PROGRAM_SEPARABLE must query latched
1054         //       state. In other words, the state of the binary after
1055         //       it was linked. So in the tests below, the queries
1056         //       should return the default state GL_FALSE since the
1057         //       program has no linked binary.
1058 
1059         glw::GLuint programSep = gl.createProgram();
1060         int separable;
1061         gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_TRUE);
1062         gl.getProgramiv(programSep, GL_PROGRAM_SEPARABLE, &separable);
1063         if (separable != GL_FALSE)
1064         {
1065             TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed");
1066         }
1067         gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_FALSE);
1068         gl.getProgramiv(programSep, GL_PROGRAM_SEPARABLE, &separable);
1069         if (separable != 0)
1070         {
1071             TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed");
1072         }
1073 
1074         // Negative Case for ProgramParameteri PROGRAM_SEPARABLE
1075 
1076         gl.deleteProgram(programSep);
1077         gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_TRUE);
1078         err = gl.getError();
1079         if (err != GL_INVALID_VALUE)
1080         {
1081             TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed");
1082         }
1083         gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, 501);
1084         err = gl.getError();
1085         if (err != GL_INVALID_VALUE)
1086         {
1087             TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed");
1088         }
1089 
1090         // GetProgramPipelineiv
1091 
1092         gl.genProgramPipelines(1, pipelines);
1093         gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint *)&value);
1094         if (value != 0)
1095         {
1096             TCU_FAIL("GetProgramPipelineiv failed for ACTIVE_PROGRAM");
1097         }
1098         gl.getProgramPipelineiv(pipelines[0], GL_VERTEX_SHADER, (glw::GLint *)&value);
1099         if (value != 0)
1100         {
1101             TCU_FAIL("GetProgramPipelineiv failed for VERTEX_SHADER");
1102         }
1103         gl.getProgramPipelineiv(pipelines[0], GL_FRAGMENT_SHADER, (glw::GLint *)&value);
1104         if (value != 0)
1105         {
1106             TCU_FAIL("GetProgramPipelineiv failed for FRAGMENT_SHADER");
1107         }
1108         gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint *)&value);
1109         if (value != 0)
1110         {
1111             TCU_FAIL("GetProgramPipelineiv failed for VALIDATE_STATUS");
1112         }
1113         gl.getProgramPipelineiv(pipelines[0], GL_INFO_LOG_LENGTH, (glw::GLint *)&value);
1114         if (value != 0)
1115         {
1116             TCU_FAIL("GetProgramPipelineiv failed for INFO_LOG_LENGTH");
1117         }
1118         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramPipelineiv failed");
1119 
1120         // Negative Case for GetProgramPipelineiv
1121 
1122         gl.deleteProgramPipelines(1, pipelines);
1123         gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint *)&value);
1124         err = gl.getError();
1125         if (err != GL_INVALID_OPERATION)
1126         {
1127             TCU_FAIL("GetProgramPipelineiv failed for ACTIVE_PROGRAM");
1128         }
1129 
1130         // ValidateProgramPipeline
1131 
1132         gl.genProgramPipelines(1, pipelines); // Unvalidated
1133         gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint *)&value);
1134         if (value != 0)
1135         {
1136             TCU_FAIL("ValidateProgramPipeline failed");
1137         }
1138 
1139         gl.validateProgramPipeline(pipelines[0]); // Not bound yet
1140         gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint *)&value);
1141         if (value != 0)
1142         {
1143             TCU_FAIL("ValidateProgramPipeline failed");
1144         }
1145 
1146         gl.bindProgramPipeline(pipelines[0]);
1147 
1148         gl.validateProgramPipeline(pipelines[0]); // Still empty program pipeline.
1149         gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint *)&value);
1150         if (value != 0)
1151         {
1152             TCU_FAIL("ValidateProgramPipeline failed with empty program pipeline");
1153         }
1154 
1155         gl.useProgramStages(pipelines[0], GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram());
1156         gl.validateProgramPipeline(pipelines[0]);
1157         gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint *)&value);
1158         if (value != 1)
1159         {
1160             TCU_FAIL("ValidateProgramPipeline failed");
1161         }
1162 
1163         // GetProgramPipelineInfoLog
1164         checkProgInfoLog(gl, pipelines[0]);
1165 
1166         // ValidateProgramPipeline additional
1167         // Relink the bound separable program as not separable
1168         gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
1169         gl.linkProgram(progVF.getProgram());
1170         err = gl.getError();
1171         gl.validateProgramPipeline(pipelines[0]);
1172         gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint *)&value);
1173         if (value != 0)
1174         {
1175             TCU_FAIL("ValidateProgramPipeline failed");
1176         }
1177         GLU_EXPECT_NO_ERROR(gl.getError(), "ValidateProgramPipeline failed");
1178 
1179         // GetProgramPipelineInfoLog
1180         checkProgInfoLog(gl, pipelines[0]);
1181 
1182         // Negative Case for ValidateProgramPipeline
1183 
1184         gl.deleteProgramPipelines(1, pipelines);
1185         gl.validateProgramPipeline(pipelines[0]);
1186         err = gl.getError();
1187         if (err != GL_INVALID_OPERATION)
1188         {
1189             TCU_FAIL("ValidateProgramPipeline failed");
1190         }
1191 
1192         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1193         return STOP;
1194     }
1195 
1196 private:
1197     glu::GLSLVersion m_glslVersion;
1198 };
1199 
1200 // Testcase for glProgramUniform
1201 class ProgramUniformCase : public TestCase
1202 {
1203 public:
ProgramUniformCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)1204     ProgramUniformCase(Context &context, const char *name, const char *description, glu::GLSLVersion glslVersion)
1205         : TestCase(context, name, description)
1206         , m_glslVersion(glslVersion)
1207     {
1208     }
1209 
~ProgramUniformCase(void)1210     ~ProgramUniformCase(void)
1211     {
1212     }
1213 
isDataTypeSquareMatrix(glu::DataType dtyp)1214     bool isDataTypeSquareMatrix(glu::DataType dtyp)
1215     {
1216         return (dtyp == glu::TYPE_FLOAT_MAT2) || (dtyp == glu::TYPE_FLOAT_MAT3) || (dtyp == glu::TYPE_FLOAT_MAT4);
1217     }
1218 
1219     // outFragSrc will hold a fragment program that is DataType specific
generateUniformFragSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,glu::DataType dType)1220     void generateUniformFragSrc(std::string &outFragSrc, glu::GLSLVersion glslVersion, glu::DataType dType)
1221     {
1222         std::ostringstream fragSrc;
1223 
1224         fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
1225         if (isDataTypeMatrix(dType) && isDataTypeSquareMatrix(dType))
1226         {
1227             fragSrc << s_unifFragSquareMatShaderSrc;
1228         }
1229         else if (isDataTypeMatrix(dType) && !isDataTypeSquareMatrix(dType))
1230         {
1231             fragSrc << s_unifFragNonSquareMatShaderSrc;
1232         }
1233         else
1234         {
1235             fragSrc << s_unifFragShaderSrc;
1236         }
1237 
1238         std::map<std::string, std::string> params;
1239 
1240         if (dType == glu::TYPE_INT)
1241         {
1242             params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "int"));
1243             params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "ivec"));
1244             params.insert(std::pair<std::string, std::string>("SFX", ""));
1245         }
1246         else if (dType == glu::TYPE_UINT)
1247         {
1248             params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "uint"));
1249             params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "uvec"));
1250             params.insert(std::pair<std::string, std::string>("SFX", "u"));
1251         }
1252         else if (dType == glu::TYPE_FLOAT)
1253         {
1254             params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "float"));
1255             params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "vec"));
1256             params.insert(std::pair<std::string, std::string>("SFX", ".0"));
1257         }
1258 
1259         tcu::StringTemplate fragTmpl(fragSrc.str().c_str());
1260         outFragSrc = fragTmpl.specialize(params);
1261     }
1262 
1263     // Set the integer programUniforms
progUniformi(const glw::Functions & gl,glw::GLuint prog,int arraySize,int * location,int * value)1264     void progUniformi(const glw::Functions &gl, glw::GLuint prog, int arraySize, int *location, int *value)
1265     {
1266         gl.programUniform1i(prog, location[0], value[0]);
1267         value += 1;
1268         gl.programUniform2i(prog, location[1], value[0], value[1]);
1269         value += 2;
1270         gl.programUniform3i(prog, location[2], value[0], value[1], value[2]);
1271         value += 3;
1272         gl.programUniform4i(prog, location[3], value[0], value[1], value[2], value[3]);
1273         value += 4;
1274 
1275         gl.programUniform1iv(prog, location[4], arraySize, value);
1276         value += 1 * arraySize;
1277         gl.programUniform2iv(prog, location[6], arraySize, value);
1278         value += 2 * arraySize;
1279         gl.programUniform3iv(prog, location[8], arraySize, value);
1280         value += 3 * arraySize;
1281         gl.programUniform4iv(prog, location[10], arraySize, value);
1282     }
1283 
1284     // Set the unsigned integer programUniforms
progUniformui(const glw::Functions & gl,glw::GLuint prog,int arraySize,int * location,unsigned int * value)1285     void progUniformui(const glw::Functions &gl, glw::GLuint prog, int arraySize, int *location, unsigned int *value)
1286     {
1287         gl.programUniform1ui(prog, location[0], value[0]);
1288         value += 1;
1289         gl.programUniform2ui(prog, location[1], value[0], value[1]);
1290         value += 2;
1291         gl.programUniform3ui(prog, location[2], value[0], value[1], value[2]);
1292         value += 3;
1293         gl.programUniform4ui(prog, location[3], value[0], value[1], value[2], value[3]);
1294         value += 4;
1295 
1296         gl.programUniform1uiv(prog, location[4], arraySize, value);
1297         value += 1 * arraySize;
1298         gl.programUniform2uiv(prog, location[6], arraySize, value);
1299         value += 2 * arraySize;
1300         gl.programUniform3uiv(prog, location[8], arraySize, value);
1301         value += 3 * arraySize;
1302         gl.programUniform4uiv(prog, location[10], arraySize, value);
1303     }
1304 
1305     // Set the float programUniforms
progUniformf(const glw::Functions & gl,glw::GLuint prog,int arraySize,int * location,float * value)1306     void progUniformf(const glw::Functions &gl, glw::GLuint prog, int arraySize, int *location, float *value)
1307     {
1308         gl.programUniform1f(prog, location[0], value[0]);
1309         value += 1;
1310         gl.programUniform2f(prog, location[1], value[0], value[1]);
1311         value += 2;
1312         gl.programUniform3f(prog, location[2], value[0], value[1], value[2]);
1313         value += 3;
1314         gl.programUniform4f(prog, location[3], value[0], value[1], value[2], value[3]);
1315         value += 4;
1316 
1317         gl.programUniform1fv(prog, location[4], arraySize, value);
1318         value += 1 * arraySize;
1319         gl.programUniform2fv(prog, location[6], arraySize, value);
1320         value += 2 * arraySize;
1321         gl.programUniform3fv(prog, location[8], arraySize, value);
1322         value += 3 * arraySize;
1323         gl.programUniform4fv(prog, location[10], arraySize, value);
1324     }
1325 
1326     // Set the integer uniforms with conventional glUniformi
activeUniformi(const glw::Functions & gl,int arraySize,int * location,int * value)1327     void activeUniformi(const glw::Functions &gl, int arraySize, int *location, int *value)
1328     {
1329         gl.uniform1i(location[0], value[0]);
1330         value += 1;
1331         gl.uniform2i(location[1], value[0], value[1]);
1332         value += 2;
1333         gl.uniform3i(location[2], value[0], value[1], value[2]);
1334         value += 3;
1335         gl.uniform4i(location[3], value[0], value[1], value[2], value[3]);
1336         value += 4;
1337 
1338         gl.uniform1iv(location[4], arraySize, value);
1339         value += 1 * arraySize;
1340         gl.uniform2iv(location[6], arraySize, value);
1341         value += 2 * arraySize;
1342         gl.uniform3iv(location[8], arraySize, value);
1343         value += 3 * arraySize;
1344         gl.uniform4iv(location[10], arraySize, value);
1345     }
1346 
1347     // Set the unsigned integer uniforms with conventional glUniformui
activeUniformui(const glw::Functions & gl,int arraySize,int * location,unsigned int * value)1348     void activeUniformui(const glw::Functions &gl, int arraySize, int *location, unsigned int *value)
1349     {
1350         gl.uniform1ui(location[0], value[0]);
1351         value += 1;
1352         gl.uniform2ui(location[1], value[0], value[1]);
1353         value += 2;
1354         gl.uniform3ui(location[2], value[0], value[1], value[2]);
1355         value += 3;
1356         gl.uniform4ui(location[3], value[0], value[1], value[2], value[3]);
1357         value += 4;
1358 
1359         gl.uniform1uiv(location[4], arraySize, value);
1360         value += 1 * arraySize;
1361         gl.uniform2uiv(location[6], arraySize, value);
1362         value += 2 * arraySize;
1363         gl.uniform3uiv(location[8], arraySize, value);
1364         value += 3 * arraySize;
1365         gl.uniform4uiv(location[10], arraySize, value);
1366     }
1367 
1368     // Set the float uniforms with conventional glUniformui
activeUniformf(const glw::Functions & gl,int arraySize,int * location,float * value)1369     void activeUniformf(const glw::Functions &gl, int arraySize, int *location, float *value)
1370     {
1371         gl.uniform1f(location[0], value[0]);
1372         value += 1;
1373         gl.uniform2f(location[1], value[0], value[1]);
1374         value += 2;
1375         gl.uniform3f(location[2], value[0], value[1], value[2]);
1376         value += 3;
1377         gl.uniform4f(location[3], value[0], value[1], value[2], value[3]);
1378         value += 4;
1379 
1380         gl.uniform1fv(location[4], arraySize, value);
1381         value += 1 * arraySize;
1382         gl.uniform2fv(location[6], arraySize, value);
1383         value += 2 * arraySize;
1384         gl.uniform3fv(location[8], arraySize, value);
1385         value += 3 * arraySize;
1386         gl.uniform4fv(location[10], arraySize, value);
1387     }
1388 
1389     // Call programUniform and verify for non-Matrix uniforms
1390     // Two programs are verified independently and against each other
setAndCompareUniforms(glw::GLuint pipeline,glw::GLuint programA,glw::GLuint programB,glu::DataType dType,int seed)1391     bool setAndCompareUniforms(glw::GLuint pipeline, glw::GLuint programA, glw::GLuint programB, glu::DataType dType,
1392                                int seed)
1393     {
1394         TestLog &log             = m_testCtx.getLog();
1395         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1396         // The fragment shader has defined uniforms of type:
1397         // scalar, vec2, vec3, vec4, and then length 2 arrays of
1398         // scalar, vec2, vec3, and vec4.
1399         // 4 uniforms in array form and 4 not in arrays.
1400         // We query a total of 12 uniform locations
1401         const int nonarrayUnifCount = 4;
1402         const int arrayUnifCount    = 4;
1403         const int arraySize         = 2;
1404         const int locationCount     = nonarrayUnifCount + arraySize * arrayUnifCount;
1405         // dwordCount represents the number of dwords to compare for each uniform location
1406         // scalar, vec2, vec3, vec4, scalar[0], scalar[1], vec2[0], vec2[1], etc.
1407         const int dwordCount[locationCount] = {1, 2, 3, 4, 1, 1, 2, 2, 3, 3, 4, 4};
1408         glw::GLint locationA[locationCount];
1409         glw::GLint locationB[locationCount];
1410         // The total amount of data the uniforms take up: 1+2+3+4 + 2*(1+2+3+4)
1411         const int udataCount = 30;
1412         unsigned int udata[udataCount]; //
1413         int *data    = (int *)&udata[0];
1414         float *fdata = (float *)&udata[0];
1415         int i, j, k;
1416         std::string uniformBaseName("uVal");
1417 
1418         // ProgramUniform API verification
1419         log << TestLog::Message << "Begin:ProgramUniformCase iterate" << TestLog::EndMessage;
1420 
1421         // get uniform locations
1422         // scalar and vec uniforms
1423         for (i = 0; i < nonarrayUnifCount; i++)
1424         {
1425             string name  = uniformBaseName + de::toString(i);
1426             locationA[i] = gl.getUniformLocation(programA, name.c_str());
1427             locationB[i] = gl.getUniformLocation(programB, name.c_str());
1428         }
1429         // uniform arrays
1430         for (j = 0; j < arrayUnifCount; j++)
1431         {
1432             for (k = 0; k < arraySize; k++)
1433             {
1434                 string name  = uniformBaseName + de::toString(nonarrayUnifCount + j) + "[" + de::toString(k) + "]";
1435                 locationA[i] = gl.getUniformLocation(programA, name.c_str());
1436                 locationB[i] = gl.getUniformLocation(programB, name.c_str());
1437                 i++;
1438             }
1439         }
1440 
1441         // seed data buffer with unique values
1442         if (dType == glu::TYPE_FLOAT)
1443         {
1444             for (i = 0; i < udataCount; i++)
1445             {
1446                 fdata[i] = (float)(seed + i);
1447             }
1448         }
1449         else
1450         {
1451             for (i = 0; i < udataCount; i++)
1452             {
1453                 data[i] = seed + i;
1454             }
1455         }
1456 
1457         // set uniforms in program A
1458         if (dType == glu::TYPE_INT)
1459         {
1460             progUniformi(gl, programA, arraySize, locationA, data);
1461         }
1462         else if (dType == glu::TYPE_UINT)
1463         {
1464             progUniformui(gl, programA, arraySize, locationA, udata);
1465         }
1466         else if (dType == glu::TYPE_FLOAT)
1467         {
1468             progUniformf(gl, programA, arraySize, locationA, fdata);
1469         }
1470 
1471         // get and compare uniforms
1472         unsigned int *uValue = &udata[0];
1473         for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++)
1474         {
1475             unsigned int retValA[4], retValB[4];
1476 
1477             if (dType == glu::TYPE_INT)
1478             {
1479                 gl.getUniformiv(programA, locationA[i], (int *)&retValA[0]);
1480                 gl.getUniformiv(programB, locationB[i], (int *)&retValB[0]);
1481             }
1482             else if (dType == glu::TYPE_UINT)
1483             {
1484                 gl.getUniformuiv(programA, locationA[i], &retValA[0]);
1485                 gl.getUniformuiv(programB, locationB[i], &retValB[0]);
1486             }
1487             else if (dType == glu::TYPE_FLOAT)
1488             {
1489                 gl.getUniformfv(programA, locationA[i], (float *)&retValA[0]);
1490                 gl.getUniformfv(programB, locationB[i], (float *)&retValB[0]);
1491             }
1492 
1493             for (j = 0; j < dwordCount[i]; j++)
1494             {
1495                 // Compare programA uniform to expected value and
1496                 // test to see if programB picked up the value.
1497                 if ((retValA[j] != *uValue++) || (retValA[j] == retValB[j]))
1498                 {
1499                     TCU_FAIL("ProgramUniformi failed");
1500                 }
1501             }
1502         }
1503 
1504         // reseed data buffer, continuing to increment
1505         if (dType == glu::TYPE_FLOAT)
1506         {
1507             fdata[0] = fdata[udataCount - 1] + 1.0f;
1508             for (i = 1; i < udataCount; i++)
1509             {
1510                 fdata[i] = fdata[i - 1] + 1.0f;
1511             }
1512         }
1513         else
1514         {
1515             data[0] = data[udataCount - 1] + 1;
1516             for (i = 1; i < udataCount; i++)
1517             {
1518                 data[i] = data[i - 1] + 1;
1519             }
1520         }
1521 
1522         // set uniforms in program B
1523 
1524         if (dType == glu::TYPE_INT)
1525         {
1526             progUniformi(gl, programB, arraySize, locationB, data);
1527         }
1528         else if (dType == glu::TYPE_UINT)
1529         {
1530             progUniformui(gl, programB, arraySize, locationB, udata);
1531         }
1532         else if (dType == glu::TYPE_FLOAT)
1533         {
1534             progUniformf(gl, programB, arraySize, locationB, fdata);
1535         }
1536 
1537         // get and compare uniforms
1538         uValue = &udata[0];
1539         for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++)
1540         {
1541             unsigned int retValA[4], retValB[4];
1542 
1543             if (dType == glu::TYPE_INT)
1544             {
1545                 gl.getUniformiv(programA, locationA[i], (int *)&retValA[0]);
1546                 gl.getUniformiv(programB, locationB[i], (int *)&retValB[0]);
1547             }
1548             else if (dType == glu::TYPE_UINT)
1549             {
1550                 gl.getUniformuiv(programA, locationA[i], &retValA[0]);
1551                 gl.getUniformuiv(programB, locationB[i], &retValB[0]);
1552             }
1553             else if (dType == glu::TYPE_FLOAT)
1554             {
1555                 gl.getUniformfv(programA, locationA[i], (float *)&retValA[0]);
1556                 gl.getUniformfv(programB, locationB[i], (float *)&retValB[0]);
1557             }
1558 
1559             for (j = 0; j < dwordCount[i]; j++)
1560             {
1561                 // Compare programB uniform to expected value and
1562                 // test to see if programA picked up the value.
1563                 if ((retValB[j] != *uValue++) || (retValA[j] == retValB[j]))
1564                 {
1565                     TCU_FAIL("ProgramUniformi failed");
1566                 }
1567             }
1568         }
1569 
1570         // Test the conventional uniform interfaces on an ACTIVE_PROGRAM
1571         glw::GLuint activeProgram = 0;
1572         if (pipeline != 0)
1573         {
1574             gl.getProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, (int *)&activeProgram);
1575         }
1576         if ((activeProgram != 0) && ((activeProgram == programA) || (activeProgram == programB)))
1577         {
1578             glw::GLint *location;
1579 
1580             location = (activeProgram == programA) ? locationA : locationB;
1581 
1582             // reseed data buffer, continuing to increment
1583             if (dType == glu::TYPE_FLOAT)
1584             {
1585                 fdata[0] = fdata[udataCount - 1] + 1.0f;
1586                 for (i = 1; i < udataCount; i++)
1587                 {
1588                     fdata[i] = fdata[i - 1] + 1.0f;
1589                 }
1590             }
1591             else
1592             {
1593                 data[0] = data[udataCount - 1] + 1;
1594                 for (i = 1; i < udataCount; i++)
1595                 {
1596                     data[i] = data[i - 1] + 1;
1597                 }
1598             }
1599 
1600             // set uniforms using original glUniform*
1601 
1602             if (dType == glu::TYPE_INT)
1603             {
1604                 activeUniformi(gl, arraySize, location, data);
1605             }
1606             else if (dType == glu::TYPE_UINT)
1607             {
1608                 activeUniformui(gl, arraySize, location, udata);
1609             }
1610             else if (dType == glu::TYPE_FLOAT)
1611             {
1612                 activeUniformf(gl, arraySize, location, fdata);
1613             }
1614 
1615             // get and compare uniforms
1616             uValue = &udata[0];
1617             for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++)
1618             {
1619                 unsigned int retVal[4];
1620 
1621                 if (dType == glu::TYPE_INT)
1622                 {
1623                     gl.getUniformiv(activeProgram, location[i], (int *)&retVal[0]);
1624                 }
1625                 else if (dType == glu::TYPE_UINT)
1626                 {
1627                     gl.getUniformuiv(activeProgram, location[i], &retVal[0]);
1628                 }
1629                 else if (dType == glu::TYPE_FLOAT)
1630                 {
1631                     gl.getUniformfv(activeProgram, location[i], (float *)&retVal[0]);
1632                 }
1633 
1634                 for (j = 0; j < dwordCount[i]; j++)
1635                 {
1636                     // Compare activeProgram uniform to expected value
1637                     if ((retVal[j] != *uValue++))
1638                     {
1639                         TCU_FAIL("ActiveShaderProgram failed");
1640                     }
1641                 }
1642             }
1643         }
1644 
1645         return true;
1646     }
1647 
1648     // Call programUniform for Matrix uniforms
1649     // Two programs are verified independently and against each other
setAndCompareMatrixUniforms(glw::GLuint pipeline,glw::GLuint programA,glw::GLuint programB,glu::DataType dType,int seed)1650     bool setAndCompareMatrixUniforms(glw::GLuint pipeline, glw::GLuint programA, glw::GLuint programB,
1651                                      glu::DataType dType, int seed)
1652     {
1653         TestLog &log             = m_testCtx.getLog();
1654         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1655         bool isSquareMat         = isDataTypeSquareMatrix(dType);
1656         // The matrix versions of the fragment shader have two element arrays
1657         // of each uniform.
1658         // There are 3 * 2 uniforms for the square matrix shader and
1659         // 6 * 2 uniforms in the non-square matrix shader.
1660         const int maxUniforms = 12;
1661         int numUniforms;
1662         const int arraySize = 2;
1663         glw::GLint locationA[maxUniforms];
1664         glw::GLint locationB[maxUniforms];
1665         // These arrays represent the number of floats for each uniform location
1666         // 2x2[0], 2x2[1], 3x3[0], 3x3[1], 4x4[0], 4x4[1]
1667         const int floatCountSqu[maxUniforms] = {4, 4, 9, 9, 16, 16, 0, 0, 0, 0, 0, 0};
1668         // 2x3[0], 2x3[1], 2x4[0], 2x4[1], 3x2[0], 3x2[1], 3x4[0], 3x4[1], 4x2[0]...
1669         const int floatCountNonSqu[maxUniforms] = {6, 6, 8, 8, 6, 6, 12, 12, 8, 8, 12, 12};
1670         const int *floatCount;
1671         // Max data for the uniforms = 2*(2*3 + 3*2 + 2*4 + 4*2 + 3*4 + 4*3)
1672         const int maxDataCount = 104;
1673         float data[maxDataCount];
1674         int i, j, k;
1675         std::string uniformBaseName("uValM");
1676 
1677         // ProgramUniform API verification
1678         log << TestLog::Message << "Begin:ProgramUniformCase for Matrix iterate" << TestLog::EndMessage;
1679 
1680         numUniforms = 0;
1681         // get uniform locations
1682         for (i = 2; i <= 4; i++) // matrix dimension m
1683         {
1684             for (j = 2; j <= 4; j++) // matrix dimension n
1685             {
1686                 for (k = 0; k < arraySize; k++)
1687                 {
1688                     if ((i == j) && isSquareMat)
1689                     {
1690                         string name            = uniformBaseName + de::toString(i) + "[" + de::toString(k) + "]";
1691                         locationA[numUniforms] = gl.getUniformLocation(programA, name.c_str());
1692                         locationB[numUniforms] = gl.getUniformLocation(programB, name.c_str());
1693                         numUniforms++;
1694                     }
1695                     else if ((i != j) && !isSquareMat)
1696                     {
1697                         string name =
1698                             uniformBaseName + de::toString(i) + "x" + de::toString(j) + "[" + de::toString(k) + "]";
1699                         locationA[numUniforms] = gl.getUniformLocation(programA, name.c_str());
1700                         locationB[numUniforms] = gl.getUniformLocation(programB, name.c_str());
1701                         numUniforms++;
1702                     }
1703                 }
1704             }
1705         }
1706         DE_ASSERT((numUniforms == 6) || (numUniforms == 12));
1707 
1708         // init the float data array
1709         for (i = 0; i < maxDataCount; i++)
1710         {
1711             data[i] = (float)(seed + i);
1712         }
1713 
1714         // Set the uniforms in programA
1715         float *value = &data[0];
1716         if (isSquareMat)
1717         {
1718             floatCount = floatCountSqu;
1719             gl.programUniformMatrix2fv(programA, locationA[0], arraySize, GL_FALSE, value);
1720             value += 2 * 2 * arraySize;
1721             gl.programUniformMatrix3fv(programA, locationA[2], arraySize, GL_FALSE, value);
1722             value += 3 * 3 * arraySize;
1723             gl.programUniformMatrix4fv(programA, locationA[4], arraySize, GL_FALSE, value);
1724         }
1725         else
1726         {
1727             floatCount = floatCountNonSqu;
1728             gl.programUniformMatrix2x3fv(programA, locationA[0], arraySize, GL_FALSE, value);
1729             value += 2 * 3 * arraySize;
1730             gl.programUniformMatrix2x4fv(programA, locationA[2], arraySize, GL_FALSE, value);
1731             value += 2 * 4 * arraySize;
1732             gl.programUniformMatrix3x2fv(programA, locationA[4], arraySize, GL_FALSE, value);
1733             value += 3 * 2 * arraySize;
1734             gl.programUniformMatrix3x4fv(programA, locationA[6], arraySize, GL_FALSE, value);
1735             value += 3 * 4 * arraySize;
1736             gl.programUniformMatrix4x2fv(programA, locationA[8], arraySize, GL_FALSE, value);
1737             value += 4 * 2 * arraySize;
1738             gl.programUniformMatrix4x3fv(programA, locationA[10], arraySize, GL_FALSE, value);
1739         }
1740 
1741         // get and compare the uniform data
1742         value = &data[0];
1743         for (i = 0; i < numUniforms; i++)
1744         {
1745             float retValA[16], retValB[16];
1746 
1747             gl.getUniformfv(programA, locationA[i], retValA);
1748             gl.getUniformfv(programB, locationB[i], retValB);
1749 
1750             for (j = 0; j < floatCount[i]; j++)
1751             {
1752                 // Compare programA uniform to expected value and
1753                 // test to see if programB picked up the value.
1754                 if ((retValA[j] != *value++) || (retValA[j] == retValB[j]))
1755                 {
1756                     TCU_FAIL("ProgramUniformi failed");
1757                 }
1758             }
1759         }
1760 
1761         // reseed the float buffer
1762         data[0] = data[maxDataCount - 1];
1763         for (i = 1; i < maxDataCount; i++)
1764         {
1765             data[i] = data[i - 1] + 1.0f;
1766         }
1767 
1768         // set uniforms in program B
1769         value = &data[0];
1770         if (isSquareMat)
1771         {
1772             floatCount = floatCountSqu;
1773             gl.programUniformMatrix2fv(programB, locationB[0], arraySize, GL_FALSE, value);
1774             value += 2 * 2 * arraySize;
1775             gl.programUniformMatrix3fv(programB, locationB[2], arraySize, GL_FALSE, value);
1776             value += 3 * 3 * arraySize;
1777             gl.programUniformMatrix4fv(programB, locationB[4], arraySize, GL_FALSE, value);
1778         }
1779         else
1780         {
1781             floatCount = floatCountNonSqu;
1782             gl.programUniformMatrix2x3fv(programB, locationB[0], arraySize, GL_FALSE, value);
1783             value += 2 * 3 * arraySize;
1784             gl.programUniformMatrix2x4fv(programB, locationB[2], arraySize, GL_FALSE, value);
1785             value += 2 * 4 * arraySize;
1786             gl.programUniformMatrix3x2fv(programB, locationB[4], arraySize, GL_FALSE, value);
1787             value += 3 * 2 * arraySize;
1788             gl.programUniformMatrix3x4fv(programB, locationB[6], arraySize, GL_FALSE, value);
1789             value += 3 * 4 * arraySize;
1790             gl.programUniformMatrix4x2fv(programB, locationB[8], arraySize, GL_FALSE, value);
1791             value += 4 * 2 * arraySize;
1792             gl.programUniformMatrix4x3fv(programB, locationB[10], arraySize, GL_FALSE, value);
1793         }
1794 
1795         // get and compare the uniform data
1796         value = &data[0];
1797         for (i = 0; i < numUniforms; i++)
1798         {
1799             float retValA[16], retValB[16];
1800 
1801             gl.getUniformfv(programA, locationA[i], retValA);
1802             gl.getUniformfv(programB, locationB[i], retValB);
1803 
1804             for (j = 0; j < floatCount[i]; j++)
1805             {
1806                 // Compare programB uniform to expected value and
1807                 // test to see if programA picked up the value.
1808                 if ((retValB[j] != *value++) || (retValA[j] == retValB[j]))
1809                 {
1810                     TCU_FAIL("ProgramUniformi failed");
1811                 }
1812             }
1813         }
1814 
1815         // Use the conventional uniform interfaces on an ACTIVE_PROGRAM
1816         glw::GLuint activeProgram = 0;
1817         if (pipeline != 0)
1818         {
1819             gl.getProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, (int *)&activeProgram);
1820         }
1821         if ((activeProgram != 0) && ((activeProgram == programA) || (activeProgram == programB)))
1822         {
1823             glw::GLint *location;
1824 
1825             location = (activeProgram == programA) ? locationA : locationB;
1826 
1827             // reseed the float buffer
1828             data[0] = data[maxDataCount - 1];
1829             for (i = 1; i < maxDataCount; i++)
1830             {
1831                 data[i] = data[i - 1] + 1.0f;
1832             }
1833 
1834             // set uniforms with conventional uniform calls
1835             value = &data[0];
1836             if (isSquareMat)
1837             {
1838                 floatCount = floatCountSqu;
1839                 gl.uniformMatrix2fv(location[0], arraySize, GL_FALSE, value);
1840                 value += 2 * 2 * arraySize;
1841                 gl.uniformMatrix3fv(location[2], arraySize, GL_FALSE, value);
1842                 value += 3 * 3 * arraySize;
1843                 gl.uniformMatrix4fv(location[4], arraySize, GL_FALSE, value);
1844             }
1845             else
1846             {
1847                 floatCount = floatCountNonSqu;
1848                 gl.uniformMatrix2x3fv(location[0], arraySize, GL_FALSE, value);
1849                 value += 2 * 3 * arraySize;
1850                 gl.uniformMatrix2x4fv(location[2], arraySize, GL_FALSE, value);
1851                 value += 2 * 4 * arraySize;
1852                 gl.uniformMatrix3x2fv(location[4], arraySize, GL_FALSE, value);
1853                 value += 3 * 2 * arraySize;
1854                 gl.uniformMatrix3x4fv(location[6], arraySize, GL_FALSE, value);
1855                 value += 3 * 4 * arraySize;
1856                 gl.uniformMatrix4x2fv(location[8], arraySize, GL_FALSE, value);
1857                 value += 4 * 2 * arraySize;
1858                 gl.uniformMatrix4x3fv(location[10], arraySize, GL_FALSE, value);
1859             }
1860 
1861             // get and compare the uniform data
1862             value = &data[0];
1863             for (i = 0; i < numUniforms; i++)
1864             {
1865                 float retVal[16];
1866 
1867                 gl.getUniformfv(activeProgram, location[i], retVal);
1868 
1869                 for (j = 0; j < floatCount[i]; j++)
1870                 {
1871                     // Compare activeshaderprogram uniform to expected value
1872                     if (retVal[j] != *value++)
1873                     {
1874                         TCU_FAIL("ActiveShaderProgram with glUniform failed");
1875                     }
1876                 }
1877             }
1878         }
1879 
1880         return true;
1881     }
1882 
iterate(void)1883     IterateResult iterate(void)
1884     {
1885         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1886         glu::DataType dType[5]   = {glu::TYPE_INT, glu::TYPE_UINT, glu::TYPE_FLOAT, glu::TYPE_FLOAT_MAT2,
1887                                     glu::TYPE_FLOAT_MAT2X3};
1888 
1889         // Loop over the various data types, generate fragment programs, and test uniforms
1890         // (MAT2 means stands for all square matrices, MAT2x3 stands for all non-square matrices)
1891         for (int i = 0; i < 5; i++)
1892         {
1893             glw::GLuint programA, programB;
1894             glw::GLuint pipeline = 0;
1895             const char *shaderSrc[1];
1896             std::string fragSrc;
1897             int seed = 1000 + (1000 * i);
1898 
1899             generateUniformFragSrc(fragSrc, m_glslVersion, dType[i]);
1900 
1901             size_t length = fragSrc.size();
1902             std::vector<char> shaderbuf(length + 1);
1903             fragSrc.copy(&shaderbuf[0], length);
1904             shaderbuf[length] = '\0';
1905             shaderSrc[0]      = &shaderbuf[0];
1906             programA          = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc);
1907             programB          = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc);
1908 
1909             if (isDataTypeMatrix(dType[i]))
1910             {
1911                 // programs are unbound
1912                 setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed);
1913 
1914                 // bind one program with useProgramStages
1915                 gl.genProgramPipelines(1, &pipeline);
1916                 gl.bindProgramPipeline(pipeline);
1917                 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programA);
1918                 seed += 100;
1919                 setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed);
1920 
1921                 // make an active program with activeShaderProgram
1922                 gl.activeShaderProgram(pipeline, programB);
1923                 seed += 100;
1924                 setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed);
1925             }
1926             else
1927             {
1928                 // programs are unbound
1929                 setAndCompareUniforms(pipeline, programA, programB, dType[i], seed);
1930 
1931                 // bind one program with useProgramStages
1932                 gl.genProgramPipelines(1, &pipeline);
1933                 gl.bindProgramPipeline(pipeline);
1934                 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programA);
1935                 seed += 100;
1936                 setAndCompareUniforms(pipeline, programA, programB, dType[i], seed);
1937 
1938                 // make an active program with activeShaderProgram
1939                 gl.activeShaderProgram(pipeline, programB);
1940                 seed += 100;
1941                 setAndCompareUniforms(pipeline, programA, programB, dType[i], seed);
1942             }
1943 
1944             gl.deleteProgram(programA);
1945             gl.deleteProgram(programB);
1946             gl.deleteProgramPipelines(1, &pipeline);
1947         }
1948 
1949         // Negative Cases
1950 
1951         // Program that is not successfully linked
1952         glw::GLenum err;
1953         std::string vtx;
1954         std::string frag;
1955 
1956         vtx  = generateBasicVertexSrc(m_glslVersion);
1957         frag = generateBasicFragmentSrc(m_glslVersion);
1958 
1959         // remove the main keyword so it doesn't link
1960         std::string fragNoMain = frag;
1961         unsigned int pos       = (unsigned int)fragNoMain.find("main");
1962         fragNoMain.replace(pos, 4, "niaM");
1963         glu::ShaderProgram progNoLink(m_context.getRenderContext(),
1964                                       glu::makeVtxFragSources(vtx.c_str(), fragNoMain.c_str()));
1965         gl.programParameteri(progNoLink.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
1966         gl.linkProgram(progNoLink.getProgram());
1967         int unifLocation = gl.getUniformLocation(progNoLink.getProgram(), "u_color");
1968         gl.programUniform4f(progNoLink.getProgram(), unifLocation, 1.0, 1.0, 1.0, 1.0);
1969         err = gl.getError();
1970         if (err != GL_INVALID_OPERATION)
1971         {
1972             TCU_FAIL("ProgramUniformi failed");
1973         }
1974 
1975         // deleted program
1976         gl.deleteProgram(progNoLink.getProgram());
1977         gl.programUniform4f(progNoLink.getProgram(), unifLocation, 1.0, 1.0, 1.0, 1.0);
1978         err = gl.getError();
1979         if (err != GL_INVALID_VALUE)
1980         {
1981             TCU_FAIL("ProgramUniformi failed");
1982         }
1983 
1984         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1985         return STOP;
1986     }
1987 
1988 private:
1989     glu::GLSLVersion m_glslVersion;
1990 };
1991 
1992 // Testcase for state interactions
1993 class StateInteractionCase : public TestCase
1994 {
1995 public:
StateInteractionCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)1996     StateInteractionCase(Context &context, const char *name, const char *description, glu::GLSLVersion glslVersion)
1997         : TestCase(context, name, description)
1998         , m_glslVersion(glslVersion)
1999     {
2000     }
2001 
~StateInteractionCase(void)2002     ~StateInteractionCase(void)
2003     {
2004     }
2005 
2006     // Log the program info log
logProgramInfoLog(const glw::Functions & gl,glw::GLuint program)2007     void logProgramInfoLog(const glw::Functions &gl, glw::GLuint program)
2008     {
2009         TestLog &log         = m_testCtx.getLog();
2010         glw::GLint value     = 0;
2011         glw::GLsizei bufSize = 0;
2012         glw::GLsizei length  = 0;
2013 
2014         gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &value);
2015         std::vector<char> infoLogBuf(value + 1);
2016 
2017         gl.getProgramInfoLog(program, bufSize, &length, &infoLogBuf[0]);
2018         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog failed");
2019 
2020         log << TestLog::Message << "Program Log:\n" << &infoLogBuf[0] << TestLog::EndMessage;
2021     }
2022 
2023     // Check program validity created with CreateShaderProgram
checkCSProg(const glw::Functions & gl,GLuint program,int expectedLink=GL_TRUE)2024     bool checkCSProg(const glw::Functions &gl, GLuint program, int expectedLink = GL_TRUE)
2025     {
2026         int linked = GL_FALSE;
2027         if (program != 0)
2028         {
2029             gl.getProgramiv(program, GL_LINK_STATUS, &linked);
2030 
2031             if (expectedLink && !linked)
2032             {
2033                 logProgramInfoLog(gl, program);
2034             }
2035         }
2036 
2037         return (program != 0) && (linked == expectedLink);
2038     }
2039 
2040     // Generate a vertex shader for variable input/output testing
generateVarLinkVertexShaderSrc(std::string & outVtxSrc,glu::GLSLVersion glslVersion,int numOutputs)2041     void generateVarLinkVertexShaderSrc(std::string &outVtxSrc, glu::GLSLVersion glslVersion, int numOutputs)
2042     {
2043         std::ostringstream vtxSrc;
2044 
2045         vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2046         if (glslVersion >= glu::GLSL_VERSION_410)
2047         {
2048             vtxSrc << "out gl_PerVertex {\n"
2049                       "  vec4 gl_Position;\n"
2050                       "};\n";
2051         }
2052         vtxSrc << "in highp vec4 a_position;\n";
2053         vtxSrc << "uniform highp vec4 u_color;\n";
2054 
2055         switch (numOutputs)
2056         {
2057         // Note all these cases fall through
2058         case 5:
2059             vtxSrc << "layout(location = 3) out vec4 o_val5;\n";
2060         // Fallthrough
2061         case 4:
2062             vtxSrc << "flat out uvec4 val4;\n";
2063         // Fallthrough
2064         case 3:
2065             vtxSrc << "flat out ivec2 val3;\n";
2066         // Fallthrough
2067         case 2:
2068             vtxSrc << "out vec3 val2[2];\n";
2069         // Fallthrough
2070         case 1:
2071             vtxSrc << "out vec4 val1;\n";
2072         // Fallthrough
2073         default:
2074             vtxSrc << "out float val0;\n";
2075         }
2076 
2077         vtxSrc << "void main (void)\n";
2078         vtxSrc << "{\n";
2079         vtxSrc << "   gl_Position = a_position;\n";
2080 
2081         // The color uniform is passed in the last declared output variable
2082         switch (numOutputs)
2083         {
2084         case 5:
2085             vtxSrc << "    o_val5 = u_color;\n";
2086             break;
2087         case 4:
2088             vtxSrc << "    val4 = uvec4(u_color);\n";
2089             break;
2090         case 3:
2091             vtxSrc << "    val3 = ivec2(u_color);\n";
2092             break;
2093         case 2:
2094             vtxSrc << "    val2[0] = vec3(u_color);\n";
2095             break;
2096         case 1:
2097             vtxSrc << "    val1 = u_color;\n";
2098             break;
2099         default:
2100             vtxSrc << "    val0 = u_color.x;\n";
2101             break;
2102         }
2103         vtxSrc << "}\n";
2104 
2105         outVtxSrc = vtxSrc.str();
2106     }
2107 
2108     // Generate a fragment shader for variable input/output testing
generateVarLinkFragmentShaderSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,int numInputs)2109     void generateVarLinkFragmentShaderSrc(std::string &outFragSrc, glu::GLSLVersion glslVersion, int numInputs)
2110     {
2111         std::ostringstream fragSrc;
2112 
2113         fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2114         fragSrc << "precision highp float;\n";
2115         fragSrc << "precision highp int;\n";
2116 
2117         switch (numInputs)
2118         {
2119         // Note all these cases fall through
2120         case 5:
2121             fragSrc << "layout(location = 3) in vec4 i_val5;\n";
2122         // Fallthrough
2123         case 4:
2124             fragSrc << "flat in uvec4 val4;\n";
2125         // Fallthrough
2126         case 3:
2127             fragSrc << "flat in ivec2 val3;\n";
2128         // Fallthrough
2129         case 2:
2130             fragSrc << "in vec3 val2[2];\n";
2131         // Fallthrough
2132         case 1:
2133             fragSrc << "in vec4 val1;\n";
2134         // Fallthrough
2135         default:
2136             fragSrc << "in float val0;\n";
2137         }
2138 
2139         fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
2140         fragSrc << "void main (void)\n";
2141         fragSrc << "{\n";
2142 
2143         switch (numInputs)
2144         {
2145         case 5:
2146             fragSrc << "    o_color = i_val5;\n";
2147             break;
2148         case 4:
2149             fragSrc << "    o_color = vec4(val4);\n";
2150             break;
2151         case 3:
2152             fragSrc << "    o_color = vec4(val3, 1.0, 1.0);\n";
2153             break;
2154         case 2:
2155             fragSrc << "    o_color = vec4(val2[0], 1.0);\n";
2156             break;
2157         case 1:
2158             fragSrc << "    o_color = vec4(val1);\n";
2159             break;
2160         default:
2161             fragSrc << "    o_color = vec4(val0, val0, val0, 1.0);\n";
2162             break;
2163         }
2164 
2165         fragSrc << "}\n";
2166 
2167         outFragSrc = fragSrc.str();
2168     }
2169 
2170     // Verify the surface is filled with the expected color
checkSurface(tcu::Surface surface,tcu::RGBA expectedColor)2171     bool checkSurface(tcu::Surface surface, tcu::RGBA expectedColor)
2172     {
2173         int numFailedPixels = 0;
2174         for (int y = 0; y < surface.getHeight(); y++)
2175         {
2176             for (int x = 0; x < surface.getWidth(); x++)
2177             {
2178                 if (surface.getPixel(x, y) != expectedColor)
2179                     numFailedPixels += 1;
2180             }
2181         }
2182 
2183         return (numFailedPixels == 0);
2184     }
2185 
iterate(void)2186     IterateResult iterate(void)
2187     {
2188         TestLog &log                          = m_testCtx.getLog();
2189         const glw::Functions &gl              = m_context.getRenderContext().getFunctions();
2190         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
2191         int viewportW                         = de::min(16, renderTarget.getWidth());
2192         int viewportH                         = de::min(16, renderTarget.getHeight());
2193         tcu::Surface renderedFrame(viewportW, viewportH);
2194 
2195         glw::GLuint programA, programB;
2196         glw::GLuint vao, vertexBuf, indexBuf;
2197         std::string vtx;
2198         std::string frag, frag2;
2199         glw::GLuint pipeline;
2200         const char *srcStrings[1];
2201         glw::GLenum err;
2202 
2203         log << TestLog::Message << "Begin:StateInteractionCase iterate" << TestLog::EndMessage;
2204 
2205         gl.viewport(0, 0, viewportW, viewportH);
2206         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2207         gl.clear(GL_COLOR_BUFFER_BIT);
2208 
2209         // Check the precedence of glUseProgram over glBindProgramPipeline
2210         // The program bound with glUseProgram will draw green, the programs
2211         // bound with glBindProgramPipeline will render blue.
2212         vtx  = generateBasicVertexSrc(m_glslVersion);
2213         frag = generateBasicFragmentSrc(m_glslVersion);
2214 
2215         glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str()));
2216 
2217         gl.useProgram(progVF.getProgram());
2218         // Ouput green in the fragment shader
2219         gl.uniform4f(gl.getUniformLocation(progVF.getProgram(), "u_color"), 0.0f, 1.0f, 0.0f, 1.0f);
2220 
2221         // Create and bind a pipeline with a different fragment shader
2222         gl.genProgramPipelines(1, &pipeline);
2223         // Use a different uniform name in another fragment shader
2224         frag2      = frag;
2225         size_t pos = 0;
2226         while ((pos = frag2.find("u_color", pos)) != std::string::npos)
2227         {
2228             frag2.replace(pos, 7, "u_clrPB");
2229             pos += 7;
2230         }
2231 
2232         srcStrings[0] = vtx.c_str();
2233         programA      = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings);
2234         if (!checkCSProg(gl, programA))
2235         {
2236             TCU_FAIL("CreateShaderProgramv failed for vertex shader");
2237         }
2238         srcStrings[0] = frag2.c_str();
2239         programB      = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings);
2240         if (!checkCSProg(gl, programB))
2241         {
2242             TCU_FAIL("CreateShaderProgramv failed for fragment shader");
2243         }
2244         // Program B outputs blue.
2245         gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 0.0f, 0.0f, 1.0f, 1.0f);
2246         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2247         gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2248         gl.bindProgramPipeline(pipeline);
2249 
2250         static const uint16_t quadIndices[] = {0, 1, 2, 2, 1, 3};
2251         const float position[]              = {-1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f,  1.0f,
2252                                                +1.0f, -1.0f, 0.0f,  1.0f, +1.0f, +1.0f, -1.0f, 1.0f};
2253 
2254         // Draw a quad with glu::draw
2255         glu::VertexArrayBinding posArray = glu::va::Float("a_position", 4, 4, 0, &position[0]);
2256         glu::draw(m_context.getRenderContext(), progVF.getProgram(), 1, &posArray,
2257                   glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
2258         GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction glu::draw failure");
2259 
2260         glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2261 
2262         // useProgram takes precedence and the buffer should be green
2263         if (!checkSurface(renderedFrame, tcu::RGBA::green()))
2264         {
2265             TCU_FAIL("StateInteraction failed; surface should be green");
2266         }
2267 
2268         // The position attribute locations may be different.
2269         int posLoc = gl.getAttribLocation(progVF.getProgram(), "a_position");
2270 
2271         if (glu::isContextTypeES(m_context.getRenderContext().getType()))
2272             gl.disableVertexAttribArray(posLoc);
2273 
2274         /* Set up a vertex array object */
2275         gl.genVertexArrays(1, &vao);
2276         gl.bindVertexArray(vao);
2277 
2278         gl.genBuffers(1, &indexBuf);
2279         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
2280         gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW);
2281 
2282         gl.genBuffers(1, &vertexBuf);
2283         gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuf);
2284         gl.bufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW);
2285 
2286         posLoc = gl.getAttribLocation(programA, "a_position");
2287         gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
2288         gl.enableVertexAttribArray(posLoc);
2289         gl.bindBuffer(GL_ARRAY_BUFFER, 0);
2290 
2291         GLU_EXPECT_NO_ERROR(gl.getError(), "VAO setup failure");
2292 
2293         // bindProgramPipeline without a program installed by useProgram
2294         // Rerender the quad.  Don't use glu::draw because it takes the
2295         // program as a parameter and sets state.
2296         gl.useProgram(0);
2297         gl.bindProgramPipeline(pipeline);
2298 
2299         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2300         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2301 
2302         glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2303 
2304         // bindProgramPipeline will render blue
2305         if (!checkSurface(renderedFrame, tcu::RGBA::blue()))
2306         {
2307             TCU_FAIL("StateInteraction failed; surface should be blue");
2308         }
2309 
2310         // Test rendering with no program bound.  Rendering is undefined
2311         // but shouldn't produce an error.
2312         gl.useProgram(0);
2313         gl.bindProgramPipeline(0);
2314 
2315         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2316         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2317 
2318         // Render call with missing pipeline stages should not generate an error
2319         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, 0);
2320         gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2321         gl.bindProgramPipeline(pipeline);
2322 
2323         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2324         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2325 
2326         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2327         gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, 0);
2328 
2329         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2330         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2331 
2332         // Missing program for fragment shader
2333         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, programA);
2334 
2335         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2336         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2337 
2338         // Separable program with both vertex and fragment shaders attached to only one stage
2339 
2340         gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
2341         gl.linkProgram(progVF.getProgram());
2342         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, progVF.getProgram());
2343 
2344         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2345         err = gl.getError();
2346         if (err != GL_INVALID_OPERATION)
2347         {
2348             TCU_FAIL("DrawElements failed");
2349         }
2350 
2351         gl.validateProgramPipeline(pipeline);
2352         glw::GLint value;
2353         gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint *)&value);
2354         if (value != 0)
2355         {
2356             TCU_FAIL("Program pipeline validation failed");
2357         }
2358 
2359         // attached to just the fragment shader
2360         // Call validateProgramPipeline before rendering this time
2361         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, 0);
2362         gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, progVF.getProgram());
2363 
2364         gl.validateProgramPipeline(pipeline);
2365         gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint *)&value);
2366         if (value != 0)
2367         {
2368             TCU_FAIL("Program pipeline validation failed");
2369         }
2370 
2371         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2372         err = gl.getError();
2373         if (err != GL_INVALID_OPERATION)
2374         {
2375             TCU_FAIL("DrawElements failed");
2376         }
2377 
2378         // Program deletion
2379         gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2380         gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2381 
2382         // Program B renders red this time
2383         gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 1.0f, 0.0f, 0.0f, 1.0f);
2384 
2385         gl.deleteProgram(programB);
2386 
2387         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2388         glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2389 
2390         // expect red
2391         if (!checkSurface(renderedFrame, tcu::RGBA::red()))
2392         {
2393             TCU_FAIL("StateInteraction failed; surface should be red");
2394         }
2395 
2396         // Attach new shader
2397         srcStrings[0] = frag2.c_str();
2398         programB      = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings);
2399         if (!checkCSProg(gl, programB))
2400         {
2401             TCU_FAIL("CreateShaderProgramv failed for fragment shader");
2402         }
2403         // Render green
2404         gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 0.0f, 1.0f, 0.0f, 1.0f);
2405         gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2406 
2407         // new shader
2408         glw::GLuint vshader = gl.createShader(GL_FRAGMENT_SHADER);
2409         srcStrings[0]       = frag.c_str(); // First frag shader with u_color uniform
2410         gl.shaderSource(vshader, 1, srcStrings, NULL);
2411         gl.compileShader(vshader);
2412         gl.getShaderiv(vshader, GL_COMPILE_STATUS, &value);
2413         DE_ASSERT(value == GL_TRUE);
2414         gl.attachShader(programB, vshader);
2415 
2416         // changing shader shouldn't affect link_status
2417         gl.getProgramiv(programB, GL_LINK_STATUS, &value);
2418         if (value != 1)
2419         {
2420             TCU_FAIL("Shader attachment shouldn't affect link status");
2421         }
2422 
2423         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2424         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2425 
2426         glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2427 
2428         // expect green
2429         if (!checkSurface(renderedFrame, tcu::RGBA::green()))
2430         {
2431             TCU_FAIL("StateInteraction failed; surface should be green");
2432         }
2433 
2434         // Negative Case: Unsuccessfully linked program should not affect current program
2435 
2436         // Render white
2437         gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 1.0f, 1.0f, 1.0f, 1.0f);
2438         std::string noMain = frag;
2439         pos                = noMain.find("main", 0);
2440         noMain.replace(pos, 4, "niaM");
2441 
2442         srcStrings[0] = noMain.c_str();
2443         gl.shaderSource(vshader, 1, srcStrings, NULL);
2444         gl.compileShader(vshader);
2445         gl.getShaderiv(vshader, GL_COMPILE_STATUS, &value);
2446         gl.attachShader(programB, vshader);
2447         gl.linkProgram(programB);
2448         err = gl.getError();
2449 
2450         // link_status should be false
2451         gl.getProgramiv(programB, GL_LINK_STATUS, &value);
2452         if (value != 0)
2453         {
2454             TCU_FAIL("StateInteraction failed; link failure");
2455         }
2456 
2457         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2458 
2459         glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2460 
2461         // expect white
2462         if (!checkSurface(renderedFrame, tcu::RGBA::white()))
2463         {
2464             TCU_FAIL("StateInteraction failed; surface should be white");
2465         }
2466 
2467         gl.deleteProgram(programA);
2468         gl.deleteProgram(programB);
2469 
2470         // Shader interface matching inputs/outputs
2471 
2472         int maxVars = 6; // generate code supports 6 variables
2473         for (int numInputs = 0; numInputs < maxVars; numInputs++)
2474         {
2475             for (int numOutputs = 0; numOutputs < maxVars; numOutputs++)
2476             {
2477 
2478                 generateVarLinkVertexShaderSrc(vtx, m_glslVersion, numOutputs);
2479                 generateVarLinkFragmentShaderSrc(frag, m_glslVersion, numInputs);
2480 
2481                 srcStrings[0] = vtx.c_str();
2482                 programA      = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings);
2483                 if (!checkCSProg(gl, programA))
2484                 {
2485                     TCU_FAIL("CreateShaderProgramv failed for vertex shader");
2486                 }
2487 
2488                 srcStrings[0] = frag.c_str();
2489                 programB      = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings);
2490                 if (!checkCSProg(gl, programB))
2491                 {
2492                     TCU_FAIL("CreateShaderProgramv failed for fragment shader");
2493                 }
2494 
2495                 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2496                 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2497                 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failure");
2498 
2499                 gl.validateProgramPipeline(pipeline);
2500                 gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint *)&value);
2501 
2502                 // Matched input and output variables should render
2503                 if (numInputs == numOutputs)
2504                 {
2505                     if (value != 1)
2506                     {
2507                         log << TestLog::Message << "Matched input and output variables should validate successfully.\n"
2508                             << "Vertex Shader:\n"
2509                             << vtx << "Fragment Shader:\n"
2510                             << frag << TestLog::EndMessage;
2511                         TCU_FAIL("StateInteraction failed");
2512                     }
2513                     gl.clear(GL_COLOR_BUFFER_BIT);
2514                     // white
2515                     gl.programUniform4f(programA, gl.getUniformLocation(programA, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f);
2516                     gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2517                     GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2518 
2519                     glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2520 
2521                     // expect white
2522                     if (!checkSurface(renderedFrame, tcu::RGBA::white()))
2523                     {
2524                         TCU_FAIL("StateInteraction failed; surface should be white");
2525                     }
2526                 }
2527                 else
2528                 {
2529                     // Mismatched input and output variables
2530                     // For OpenGL ES contexts, this should cause a validation failure
2531                     // For OpenGL contexts, validation should succeed.
2532                     if (glu::isContextTypeES(m_context.getRenderContext().getType()) != (value == 0))
2533                     {
2534                         log << TestLog::Message << "Mismatched input and output variables; validation should "
2535                             << (glu::isContextTypeES(m_context.getRenderContext().getType()) ? "fail.\n" : "succeed.\n")
2536                             << "Vertex Shader:\n"
2537                             << vtx << "Fragment Shader:\n"
2538                             << frag << TestLog::EndMessage;
2539                         TCU_FAIL("StateInteraction failed");
2540                     }
2541                 }
2542 
2543                 gl.deleteProgram(programA);
2544                 gl.deleteProgram(programB);
2545             }
2546         }
2547 
2548         gl.bindProgramPipeline(0);
2549         gl.bindVertexArray(0);
2550         gl.deleteProgramPipelines(1, &pipeline);
2551         gl.deleteShader(vshader);
2552         gl.deleteVertexArrays(1, &vao);
2553         gl.deleteBuffers(1, &indexBuf);
2554         gl.deleteBuffers(1, &vertexBuf);
2555 
2556         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2557         return STOP;
2558     }
2559 
2560 private:
2561     glu::GLSLVersion m_glslVersion;
2562 };
2563 
2564 // Testcase for interface qualifiers matching
2565 class InterfaceMatchingCase : public TestCase
2566 {
2567 public:
2568     enum TestType
2569     {
2570         DEFAULT_PRECISION,
2571         SET_DEFAULT_PRECISION,
2572         SET_PRECISION
2573     };
2574 
getTestTypeName(TestType testType)2575     std::string getTestTypeName(TestType testType)
2576     {
2577         switch (testType)
2578         {
2579         case DEFAULT_PRECISION:
2580             return "use predeclared precision";
2581         case SET_DEFAULT_PRECISION:
2582             return "set default precision";
2583         case SET_PRECISION:
2584             return "explicit precision";
2585         }
2586         return "";
2587     }
2588 
InterfaceMatchingCase(Context & context,const char * name,glu::GLSLVersion glslVersion)2589     InterfaceMatchingCase(Context &context, const char *name, glu::GLSLVersion glslVersion)
2590         : TestCase(context, name, "matching precision qualifiers between stages")
2591         , m_glslVersion(glslVersion)
2592     {
2593     }
2594 
~InterfaceMatchingCase(void)2595     ~InterfaceMatchingCase(void)
2596     {
2597     }
2598 
getDefaultFragmentPrecision()2599     string getDefaultFragmentPrecision()
2600     {
2601         return "";
2602     }
2603 
2604     // Generate a vertex shader for variable input/output precision testing
2605     virtual void generateVarLinkVertexShaderSrc(std::string &outVtxSrc, glu::GLSLVersion glslVersion,
2606                                                 const string &precision, TestType testMode) = 0;
2607 
2608     // Generate a fragment shader for variable input/output precision testing
2609     virtual void generateVarLinkFragmentShaderSrc(std::string &outFragSrc, glu::GLSLVersion glslVersion,
2610                                                   const string &precision, TestType testMode) = 0;
2611 
2612     // Verify the surface is filled with the expected color
checkSurface(tcu::Surface surface,tcu::RGBA expectedColor)2613     bool checkSurface(tcu::Surface surface, tcu::RGBA expectedColor)
2614     {
2615         int numFailedPixels = 0;
2616         for (int y = 0; y < surface.getHeight(); y++)
2617         {
2618             for (int x = 0; x < surface.getWidth(); x++)
2619             {
2620                 if (surface.getPixel(x, y) != expectedColor)
2621                     numFailedPixels += 1;
2622             }
2623         }
2624         return (numFailedPixels == 0);
2625     }
2626 
2627     // Log the program info log
logProgramInfoLog(const glw::Functions & gl,glw::GLuint program)2628     void logProgramInfoLog(const glw::Functions &gl, glw::GLuint program)
2629     {
2630         TestLog &log         = m_testCtx.getLog();
2631         glw::GLint value     = 0;
2632         glw::GLsizei bufSize = 0;
2633         glw::GLsizei length  = 0;
2634 
2635         gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &value);
2636         std::vector<char> infoLogBuf(value + 1);
2637 
2638         gl.getProgramInfoLog(program, bufSize, &length, &infoLogBuf[0]);
2639         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog failed");
2640 
2641         log << TestLog::Message << "Program Log:\n" << &infoLogBuf[0] << TestLog::EndMessage;
2642     }
2643 
2644     // Check program validity created with CreateShaderProgram
checkCSProg(const glw::Functions & gl,GLuint program,int expectedLink=GL_TRUE)2645     bool checkCSProg(const glw::Functions &gl, GLuint program, int expectedLink = GL_TRUE)
2646     {
2647         int linked = GL_FALSE;
2648         if (program != 0)
2649         {
2650             gl.getProgramiv(program, GL_LINK_STATUS, &linked);
2651 
2652             if (expectedLink && !linked)
2653             {
2654                 logProgramInfoLog(gl, program);
2655             }
2656         }
2657 
2658         return (program != 0) && (linked == expectedLink);
2659     }
2660 
iterate(void)2661     IterateResult iterate(void)
2662     {
2663         TestLog &log                          = m_testCtx.getLog();
2664         const glw::Functions &gl              = m_context.getRenderContext().getFunctions();
2665         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
2666         int viewportW                         = de::min(16, renderTarget.getWidth());
2667         int viewportH                         = de::min(16, renderTarget.getHeight());
2668         tcu::Surface renderedFrame(viewportW, viewportH);
2669 
2670         glw::GLuint programA, programB;
2671         glw::GLuint vao, vertexBuf, indexBuf;
2672         std::string vtx;
2673         std::string frag, frag2;
2674         glw::GLuint pipeline;
2675         const char *srcStrings[1];
2676         glw::GLuint value;
2677 
2678         gl.viewport(0, 0, viewportW, viewportH);
2679         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2680         gl.clear(GL_COLOR_BUFFER_BIT);
2681 
2682         static const uint16_t quadIndices[] = {0, 1, 2, 2, 1, 3};
2683         const float position[]              = {-1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f,  1.0f,
2684                                                +1.0f, -1.0f, 0.0f,  1.0f, +1.0f, +1.0f, -1.0f, 1.0f};
2685 
2686         /* Set up a vertex array object */
2687         gl.genVertexArrays(1, &vao);
2688         gl.bindVertexArray(vao);
2689 
2690         gl.genBuffers(1, &indexBuf);
2691         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
2692         gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW);
2693 
2694         gl.genBuffers(1, &vertexBuf);
2695         gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuf);
2696         gl.bufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW);
2697 
2698         /* Set up shader pipeline */
2699         gl.genProgramPipelines(1, &pipeline);
2700         gl.bindProgramPipeline(pipeline);
2701 
2702         struct PrecisionTests
2703         {
2704             TestType testType;
2705             std::string precision;
2706         };
2707 
2708         PrecisionTests vertexPrecisionTests[] = {
2709             {DEFAULT_PRECISION, "highp"},    {SET_DEFAULT_PRECISION, "highp"}, {SET_DEFAULT_PRECISION, "mediump"},
2710             {SET_DEFAULT_PRECISION, "lowp"}, {SET_PRECISION, "highp"},         {SET_PRECISION, "mediump"},
2711             {SET_PRECISION, "lowp"}};
2712 
2713         PrecisionTests fragmentPrecisionTests[] = {{DEFAULT_PRECISION, getDefaultFragmentPrecision()},
2714                                                    {SET_DEFAULT_PRECISION, "highp"},
2715                                                    {SET_DEFAULT_PRECISION, "mediump"},
2716                                                    {SET_DEFAULT_PRECISION, "lowp"},
2717                                                    {SET_PRECISION, "highp"},
2718                                                    {SET_PRECISION, "mediump"},
2719                                                    {SET_PRECISION, "lowp"}};
2720 
2721         // Shader interface matching inputs/outputs precision
2722         int maxTests = 7;
2723         for (int vertexTestIteration = 0; vertexTestIteration < maxTests; vertexTestIteration++)
2724         {
2725             std::string vertexPrecision = vertexPrecisionTests[vertexTestIteration].precision;
2726             TestType vertexTestType     = vertexPrecisionTests[vertexTestIteration].testType;
2727             for (int fragmentTestIteration = 0; fragmentTestIteration < maxTests; fragmentTestIteration++)
2728             {
2729                 std::string fragmentPrecision = fragmentPrecisionTests[fragmentTestIteration].precision;
2730                 TestType fragmentTestType     = fragmentPrecisionTests[fragmentTestIteration].testType;
2731                 if (fragmentPrecision.empty())
2732                     continue;
2733 
2734                 log << TestLog::Message << "vertex shader precision: " << vertexPrecision
2735                     << ", shader test mode: " << getTestTypeName(vertexTestType) << TestLog::EndMessage;
2736 
2737                 log << TestLog::Message << "fragment shader precision: " << fragmentPrecision
2738                     << ", shader test mode: " << getTestTypeName(fragmentTestType) << TestLog::EndMessage;
2739 
2740                 generateVarLinkVertexShaderSrc(vtx, m_glslVersion, vertexPrecision, vertexTestType);
2741                 generateVarLinkFragmentShaderSrc(frag, m_glslVersion, fragmentPrecision, fragmentTestType);
2742 
2743                 srcStrings[0] = vtx.c_str();
2744                 programA      = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings);
2745                 if (!checkCSProg(gl, programA))
2746                 {
2747                     TCU_FAIL("CreateShaderProgramv failed for vertex shader");
2748                 }
2749                 srcStrings[0] = frag.c_str();
2750                 programB      = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings);
2751                 if (!checkCSProg(gl, programB))
2752                 {
2753                     TCU_FAIL("CreateShaderProgramv failed for fragment shader");
2754                 }
2755 
2756                 gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2757                 gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2758                 GLU_EXPECT_NO_ERROR(gl.getError(), "InterfaceMatching failure");
2759 
2760                 // Mismatched input and output qualifiers
2761                 // For OpenGL ES contexts, this should result in a validation failure.
2762                 // For OpenGL contexts, validation should succeed.
2763                 gl.validateProgramPipeline(pipeline);
2764                 gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint *)&value);
2765                 int precisionCompareResult = fragmentPrecision.compare(vertexPrecision);
2766                 if (glu::isContextTypeES(m_context.getRenderContext().getType()) && (precisionCompareResult != 0))
2767                 {
2768                     // precision mismatch
2769                     if (value != GL_FALSE)
2770                     {
2771                         log.startShaderProgram(
2772                             false, "Precision mismatch, pipeline validation status GL_TRUE expected GL_FALSE");
2773                         log.writeShader(QP_SHADER_TYPE_VERTEX, vtx.c_str(), true, "");
2774                         log.writeShader(QP_SHADER_TYPE_FRAGMENT, frag.c_str(), true, "");
2775                         log.endShaderProgram();
2776                         TCU_FAIL("InterfaceMatchingCase failed");
2777                     }
2778                     else
2779                     {
2780                         log << TestLog::Message << "Precision mismatch, Pipeline validation status GL_FALSE -> OK"
2781                             << TestLog::EndMessage;
2782                     }
2783                 }
2784                 else
2785                 {
2786                     if (value != GL_TRUE)
2787                     {
2788                         std::stringstream str;
2789                         str << "Precision " << (precisionCompareResult ? "mismatch" : "matches")
2790                             << ", pipeline validation status GL_FALSE expected GL_TRUE";
2791 
2792                         log.startShaderProgram(false, str.str().c_str());
2793                         log.writeShader(QP_SHADER_TYPE_VERTEX, vtx.c_str(), true, "");
2794                         log.writeShader(QP_SHADER_TYPE_FRAGMENT, frag.c_str(), true, "");
2795                         log.endShaderProgram();
2796                         TCU_FAIL("InterfaceMatchingCase failed");
2797                     }
2798                     else
2799                     {
2800                         log << TestLog::Message << "Precision " << (precisionCompareResult ? "mismatch" : "matches")
2801                             << ", pipeline validation status GL_TRUE -> OK" << TestLog::EndMessage;
2802                         // precision matches
2803                         gl.clear(GL_COLOR_BUFFER_BIT);
2804                         // white
2805                         int posLoc = gl.getAttribLocation(programA, "a_position");
2806                         gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
2807                         gl.enableVertexAttribArray(posLoc);
2808                         gl.programUniform4f(programA, gl.getUniformLocation(programA, "u_color"), 1.0f, 1.0f, 1.0f,
2809                                             1.0f);
2810                         GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction failure, set uniform value");
2811                         gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2812                         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2813                         gl.disableVertexAttribArray(posLoc);
2814 
2815                         glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2816 
2817                         // expect white
2818                         if (!checkSurface(renderedFrame, tcu::RGBA::white()))
2819                         {
2820                             TCU_FAIL("InterfaceMatchingCase failed; surface should be white");
2821                         }
2822                     }
2823                 }
2824 
2825                 // validate non separable program
2826 
2827                 glu::ShaderProgram progVF(m_context.getRenderContext(),
2828                                           glu::makeVtxFragSources(vtx.c_str(), frag.c_str()));
2829 
2830                 gl.useProgram(progVF.getProgram());
2831                 gl.uniform4f(gl.getUniformLocation(progVF.getProgram(), "u_color"), 1.0f, 1.0f, 1.0f, 1.0f);
2832                 if (!progVF.getProgramInfo().linkOk)
2833                 {
2834                     log << progVF;
2835                     log << TestLog::Message << "Non separable program link status GL_FALSE expected GL_TRUE"
2836                         << TestLog::EndMessage;
2837                     TCU_FAIL("InterfaceMatchingCase failed, non separable program should link");
2838                 }
2839 
2840                 int posLoc = gl.getAttribLocation(progVF.getProgram(), "a_position");
2841                 gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
2842                 gl.enableVertexAttribArray(posLoc);
2843                 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2844                 gl.disableVertexAttribArray(posLoc);
2845 
2846                 GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction failure, non separable program draw call");
2847                 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2848                 // expect white
2849                 if (!checkSurface(renderedFrame, tcu::RGBA::white()))
2850                 {
2851                     TCU_FAIL("InterfaceMatchingCase failed, non separable program, unexpected color found");
2852                 }
2853 
2854                 gl.deleteProgram(programA);
2855                 gl.deleteProgram(programB);
2856                 gl.useProgram(0);
2857             }
2858         }
2859         gl.bindVertexArray(0);
2860         gl.deleteVertexArrays(1, &vao);
2861         gl.deleteBuffers(1, &indexBuf);
2862         gl.deleteBuffers(1, &vertexBuf);
2863         gl.bindProgramPipeline(0);
2864         gl.deleteProgramPipelines(1, &pipeline);
2865 
2866         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2867         return STOP;
2868     }
2869 
2870 protected:
2871     glu::GLSLVersion m_glslVersion;
2872 };
2873 
2874 class InterfaceMatchingCaseFloat : public InterfaceMatchingCase
2875 {
2876 public:
InterfaceMatchingCaseFloat(Context & context,const char * name,glu::GLSLVersion glslVersion)2877     InterfaceMatchingCaseFloat(Context &context, const char *name, glu::GLSLVersion glslVersion)
2878         : InterfaceMatchingCase(context, name, glslVersion)
2879     {
2880     }
2881 
generateVarLinkVertexShaderSrc(std::string & outVtxSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)2882     void generateVarLinkVertexShaderSrc(std::string &outVtxSrc, glu::GLSLVersion glslVersion, const string &precision,
2883                                         TestType testMode)
2884     {
2885         std::ostringstream vtxSrc;
2886         vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2887         if (glslVersion >= glu::GLSL_VERSION_410)
2888         {
2889             vtxSrc << "out gl_PerVertex {\n"
2890                       "  vec4 gl_Position;\n"
2891                       "};\n";
2892         }
2893         vtxSrc << "in highp vec4 a_position;\n";
2894         vtxSrc << "uniform highp vec4 u_color;\n";
2895         switch (testMode)
2896         {
2897         case SET_DEFAULT_PRECISION:
2898             vtxSrc << "precision " << precision << " float;\n";
2899         // Fallthrough
2900         case DEFAULT_PRECISION:
2901             vtxSrc << "out float var;\n";
2902             break;
2903         case SET_PRECISION:
2904             vtxSrc << "out " << precision << " float var;\n";
2905             break;
2906         }
2907         vtxSrc << "void main (void)\n";
2908         vtxSrc << "{\n";
2909         vtxSrc << "   gl_Position = a_position;\n";
2910         vtxSrc << "   var = u_color.r;\n";
2911         vtxSrc << "}\n";
2912         outVtxSrc = vtxSrc.str();
2913     }
2914 
generateVarLinkFragmentShaderSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)2915     void generateVarLinkFragmentShaderSrc(std::string &outFragSrc, glu::GLSLVersion glslVersion,
2916                                           const string &precision, TestType testMode)
2917     {
2918         std::ostringstream fragSrc;
2919         fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2920         switch (testMode)
2921         {
2922         case SET_DEFAULT_PRECISION:
2923             fragSrc << "precision " << precision << " float;\n";
2924         // Fallthrough
2925         case DEFAULT_PRECISION:
2926             fragSrc << "in float var;\n";
2927             break;
2928         case SET_PRECISION:
2929             fragSrc << "in " << precision << " float var;\n";
2930             break;
2931         }
2932         fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
2933         fragSrc << "void main (void)\n";
2934         fragSrc << "{\n";
2935         fragSrc << "    o_color = vec4(var);\n";
2936         fragSrc << "}\n";
2937         outFragSrc = fragSrc.str();
2938     }
2939 };
2940 
2941 class InterfaceMatchingCaseInt : public InterfaceMatchingCase
2942 {
2943 public:
InterfaceMatchingCaseInt(Context & context,const char * name,glu::GLSLVersion glslVersion)2944     InterfaceMatchingCaseInt(Context &context, const char *name, glu::GLSLVersion glslVersion)
2945         : InterfaceMatchingCase(context, name, glslVersion)
2946     {
2947     }
2948 
getDefaultFragmentPrecision()2949     std::string getDefaultFragmentPrecision()
2950     {
2951         return "mediump";
2952     }
2953 
generateVarLinkVertexShaderSrc(std::string & outVtxSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)2954     void generateVarLinkVertexShaderSrc(std::string &outVtxSrc, glu::GLSLVersion glslVersion, const string &precision,
2955                                         TestType testMode)
2956     {
2957         std::ostringstream vtxSrc;
2958         vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2959         if (glslVersion >= glu::GLSL_VERSION_410)
2960         {
2961             vtxSrc << "out gl_PerVertex {\n"
2962                       "  vec4 gl_Position;\n"
2963                       "};\n";
2964         }
2965         vtxSrc << "in highp vec4 a_position;\n";
2966         vtxSrc << "uniform highp vec4 u_color;\n";
2967         switch (testMode)
2968         {
2969         case SET_DEFAULT_PRECISION:
2970             vtxSrc << "precision " << precision << " int;\n";
2971         // Fallthrough
2972         case DEFAULT_PRECISION:
2973             vtxSrc << "flat out int var;\n";
2974             break;
2975         case SET_PRECISION:
2976             vtxSrc << "flat out " << precision << " int var;\n";
2977             break;
2978         }
2979         vtxSrc << "void main (void)\n";
2980         vtxSrc << "{\n";
2981         vtxSrc << "   gl_Position = a_position;\n";
2982         vtxSrc << "   var = int(u_color.r);\n";
2983         vtxSrc << "}\n";
2984         outVtxSrc = vtxSrc.str();
2985     }
2986 
generateVarLinkFragmentShaderSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)2987     void generateVarLinkFragmentShaderSrc(std::string &outFragSrc, glu::GLSLVersion glslVersion,
2988                                           const string &precision, TestType testMode)
2989     {
2990         std::ostringstream fragSrc;
2991         fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2992         switch (testMode)
2993         {
2994         case SET_DEFAULT_PRECISION:
2995             fragSrc << "precision " << precision << " int;\n";
2996         // Fallthrough
2997         case DEFAULT_PRECISION:
2998             fragSrc << "flat in int var;\n";
2999             break;
3000         case SET_PRECISION:
3001             fragSrc << "flat in " << precision << " int var;\n";
3002             break;
3003         }
3004         fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
3005         fragSrc << "void main (void)\n";
3006         fragSrc << "{\n";
3007         fragSrc << "    o_color = vec4(var);\n";
3008         fragSrc << "}\n";
3009         outFragSrc = fragSrc.str();
3010     }
3011 };
3012 
3013 class InterfaceMatchingCaseUInt : public InterfaceMatchingCase
3014 {
3015 public:
InterfaceMatchingCaseUInt(Context & context,const char * name,glu::GLSLVersion glslVersion)3016     InterfaceMatchingCaseUInt(Context &context, const char *name, glu::GLSLVersion glslVersion)
3017         : InterfaceMatchingCase(context, name, glslVersion)
3018     {
3019     }
3020 
getDefaultFragmentPrecision()3021     std::string getDefaultFragmentPrecision()
3022     {
3023         return "mediump";
3024     }
3025 
generateVarLinkVertexShaderSrc(std::string & outVtxSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)3026     void generateVarLinkVertexShaderSrc(std::string &outVtxSrc, glu::GLSLVersion glslVersion, const string &precision,
3027                                         TestType testMode)
3028     {
3029         std::ostringstream vtxSrc;
3030         vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
3031         if (glslVersion >= glu::GLSL_VERSION_410)
3032         {
3033             vtxSrc << "out gl_PerVertex {\n"
3034                       "  vec4 gl_Position;\n"
3035                       "};\n";
3036         }
3037         vtxSrc << "in highp vec4 a_position;\n";
3038         vtxSrc << "uniform highp vec4 u_color;\n";
3039         switch (testMode)
3040         {
3041         case SET_DEFAULT_PRECISION:
3042             vtxSrc << "precision " << precision << " int;\n";
3043         // Fallthrough
3044         case DEFAULT_PRECISION:
3045             vtxSrc << "flat out uint var;\n";
3046             break;
3047         case SET_PRECISION:
3048             vtxSrc << "flat out " << precision << " uint var;\n";
3049             break;
3050         }
3051         vtxSrc << "void main (void)\n";
3052         vtxSrc << "{\n";
3053         vtxSrc << "   gl_Position = a_position;\n";
3054         vtxSrc << "   var = uint(u_color.r);\n";
3055         vtxSrc << "}\n";
3056         outVtxSrc = vtxSrc.str();
3057     }
3058 
generateVarLinkFragmentShaderSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)3059     void generateVarLinkFragmentShaderSrc(std::string &outFragSrc, glu::GLSLVersion glslVersion,
3060                                           const string &precision, TestType testMode)
3061     {
3062         std::ostringstream fragSrc;
3063         fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
3064         switch (testMode)
3065         {
3066         case SET_DEFAULT_PRECISION:
3067             fragSrc << "precision " << precision << " int;\n";
3068         // Fallthrough
3069         case DEFAULT_PRECISION:
3070             fragSrc << "flat in uint var;\n";
3071             break;
3072         case SET_PRECISION:
3073             fragSrc << "flat in " << precision << " uint var;\n";
3074             break;
3075         }
3076         fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
3077         fragSrc << "void main (void)\n";
3078         fragSrc << "{\n";
3079         fragSrc << "    o_color = vec4(var);\n";
3080         fragSrc << "}\n";
3081         outFragSrc = fragSrc.str();
3082     }
3083 };
3084 
SeparateShaderObjsTests(Context & context,glu::GLSLVersion glslVersion)3085 SeparateShaderObjsTests::SeparateShaderObjsTests(Context &context, glu::GLSLVersion glslVersion)
3086     : TestCaseGroup(context, "sepshaderobjs", "separate_shader_object tests")
3087     , m_glslVersion(glslVersion)
3088 {
3089     DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440);
3090 }
3091 
~SeparateShaderObjsTests(void)3092 SeparateShaderObjsTests::~SeparateShaderObjsTests(void)
3093 {
3094 }
3095 
init(void)3096 void SeparateShaderObjsTests::init(void)
3097 {
3098 
3099     // API validation for CreateShaderProgram
3100     addChild(new CreateShadProgCase(m_context, "CreateShadProgApi", "createShaderProgram API", m_glslVersion));
3101     // API validation for UseProgramStages
3102     addChild(new UseProgStagesCase(m_context, "UseProgStagesApi", "useProgramStages API", m_glslVersion));
3103     // API validation for pipeline related functions
3104     addChild(new PipelineApiCase(m_context, "PipelineApi", "Pipeline API", m_glslVersion));
3105     // API validation for variations of ProgramUniform
3106     addChild(new ProgramUniformCase(m_context, "ProgUniformAPI", "ProgramUniform API", m_glslVersion));
3107     // State interactions
3108     addChild(new StateInteractionCase(m_context, "StateInteraction", "SSO State Interactions", m_glslVersion));
3109     // input / output precision matching
3110     addChild(new InterfaceMatchingCaseFloat(m_context, "InterfacePrecisionMatchingFloat", m_glslVersion));
3111     addChild(new InterfaceMatchingCaseInt(m_context, "InterfacePrecisionMatchingInt", m_glslVersion));
3112     addChild(new InterfaceMatchingCaseUInt(m_context, "InterfacePrecisionMatchingUInt", m_glslVersion));
3113 }
3114 
3115 } // namespace glcts
3116