• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #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 tcu::TestLog;
341 using std::string;
342 using std::vector;
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), m_glslVersion(glslVersion)
528 	{
529 	}
530 
~CreateShadProgCase(void)531 	~CreateShadProgCase(void)
532 	{
533 	}
534 
535 	// Check program validity created with CreateShaderProgram
checkCSProg(const glw::Functions & gl,GLuint program,int expectedSep=GL_TRUE,int expectedLink=GL_TRUE)536 	bool checkCSProg(const glw::Functions& gl, GLuint program, int expectedSep = GL_TRUE, int expectedLink = GL_TRUE)
537 	{
538 		int separable = GL_FALSE;
539 		int linked	= GL_FALSE;
540 		if (program != 0)
541 		{
542 			gl.getProgramiv(program, GL_PROGRAM_SEPARABLE, &separable);
543 			gl.getProgramiv(program, GL_LINK_STATUS, &linked);
544 		}
545 
546 		return (program != 0) && (separable == expectedSep) && (linked == expectedLink);
547 	}
548 
iterate(void)549 	IterateResult iterate(void)
550 	{
551 		TestLog&			  log = m_testCtx.getLog();
552 		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
553 		int					  i;
554 		const char*			  srcStrings[10];
555 		glw::GLuint			  program;
556 		glw::GLenum			  err;
557 
558 		// CreateShaderProgramv verification
559 		log << TestLog::Message << "Begin:CreateShadProgCase iterate" << TestLog::EndMessage;
560 
561 		// vertex shader
562 		i				= 0;
563 		srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion);
564 		srcStrings[i++] = "\n";
565 		if (m_glslVersion >= glu::GLSL_VERSION_410)
566 		{
567 			srcStrings[i++] = "out gl_PerVertex {\n"
568 							  "  vec4 gl_Position;\n"
569 							  "};\n";
570 		}
571 		srcStrings[i++] = "in vec4 a_position;\n";
572 		srcStrings[i++] = "void main ()\n";
573 		srcStrings[i++] = "{\n";
574 		srcStrings[i++] = "    gl_Position = a_position;\n";
575 		srcStrings[i++] = "}\n";
576 
577 		program = gl.createShaderProgramv(GL_VERTEX_SHADER, i, srcStrings);
578 		if (!checkCSProg(gl, program))
579 		{
580 			TCU_FAIL("CreateShaderProgramv failed for vertex shader");
581 		}
582 
583 		gl.deleteProgram(program);
584 
585 		// Half as many strings
586 		i				= 0;
587 		srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion);
588 		srcStrings[i++] = "\n";
589 		if (m_glslVersion >= glu::GLSL_VERSION_410)
590 		{
591 			srcStrings[i++] = "out gl_PerVertex {\n"
592 							  "  vec4 gl_Position;\n"
593 							  "};\n";
594 		}
595 		srcStrings[i++] = "in vec4 a_position;\n"
596 						  "void main ()\n";
597 		srcStrings[i++] = "{\n"
598 						  "    gl_Position = a_position;\n";
599 		srcStrings[i++] = "}\n";
600 
601 		program = gl.createShaderProgramv(GL_VERTEX_SHADER, i, srcStrings);
602 		if (!checkCSProg(gl, program))
603 		{
604 			TCU_FAIL("CreateShaderProgramv failed for vertex shader");
605 		}
606 
607 		gl.deleteProgram(program);
608 
609 		// Fragment shader
610 		i				= 0;
611 		srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion);
612 		srcStrings[i++] = "\nin highp vec4 u_color;\n";
613 		srcStrings[i++] = "layout(location = 0) out mediump vec4 o_color;\n";
614 		srcStrings[i++] = "void main ()\n";
615 		srcStrings[i++] = "{\n";
616 		srcStrings[i++] = "    o_color = u_color;\n";
617 		srcStrings[i++] = "}\n";
618 
619 		program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, i, srcStrings);
620 		if (!checkCSProg(gl, program))
621 		{
622 			TCU_FAIL("CreateShaderProgramv failed for fragment shader");
623 		}
624 
625 		gl.deleteProgram(program);
626 
627 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShaderProgramv failed");
628 
629 		// Negative Cases
630 
631 		// invalid type
632 		program = gl.createShaderProgramv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, i, srcStrings);
633 		err		= gl.getError();
634 		if ((program != 0) || (err != GL_INVALID_ENUM))
635 		{
636 			TCU_FAIL("CreateShaderProgramv failed");
637 		}
638 
639 		// Negative count
640 		program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, -1, srcStrings);
641 		err		= gl.getError();
642 		if ((program != 0) || (err != GL_INVALID_VALUE))
643 		{
644 			TCU_FAIL("CreateShaderProgramv failed");
645 		}
646 
647 		// source compile error
648 		i				= 0;
649 		srcStrings[i++] = glu::getGLSLVersionDeclaration(m_glslVersion);
650 		srcStrings[i++] = "\nin highp vec4 u_color;\n";
651 		srcStrings[i++] = "layout(location = 0) out mediump vec4 o_color;\n";
652 		srcStrings[i++] = "void main ()\n";
653 		srcStrings[i++] = "{\n";
654 		srcStrings[i++] = "    o_color = u_color;\n";
655 
656 		program = gl.createShaderProgramv(GL_FRAGMENT_SHADER, i, srcStrings);
657 		// expect valid program and false for link status
658 		if (!checkCSProg(gl, program, GL_FALSE, GL_FALSE))
659 		{
660 			TCU_FAIL("CreateShaderProgramv failed for fragment shader");
661 		}
662 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShaderProgramv failed");
663 		gl.deleteProgram(program);
664 
665 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
666 		return STOP;
667 	}
668 
669 private:
670 	glu::GLSLVersion m_glslVersion;
671 };
672 
673 // Testcase for glUseProgamStages
674 class UseProgStagesCase : public TestCase
675 {
676 public:
UseProgStagesCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)677 	UseProgStagesCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion)
678 		: TestCase(context, name, description), m_glslVersion(glslVersion)
679 	{
680 	}
681 
~UseProgStagesCase(void)682 	~UseProgStagesCase(void)
683 	{
684 	}
685 
iterate(void)686 	IterateResult iterate(void)
687 	{
688 		TestLog&			  log = m_testCtx.getLog();
689 		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
690 		glw::GLenum			  err;
691 		glw::GLuint			  pipeline;
692 		glw::GLuint			  progIdV, progIdF;
693 		glw::GLuint			  programVtx, programFrag;
694 		const char*			  shaderSrc[1];
695 		std::string			  vtx;
696 		std::string			  frag;
697 		glw::GLint			  linkStatus;
698 
699 		vtx  = generateBasicVertexSrc(m_glslVersion);
700 		frag = generateBasicFragmentSrc(m_glslVersion);
701 
702 		// UseProgramStages verification
703 		log << TestLog::Message << "Begin:UseProgStagesCase iterate" << TestLog::EndMessage;
704 
705 		gl.genProgramPipelines(1, &pipeline);
706 		gl.bindProgramPipeline(pipeline);
707 
708 		// Use Vertex Shader
709 		shaderSrc[0] = vtx.c_str();
710 		programVtx   = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, shaderSrc);
711 
712 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx);
713 		gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint*)&progIdV);
714 		gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF);
715 		if ((programVtx == 0) || (progIdV != programVtx) || (progIdF != 0))
716 		{
717 			TCU_FAIL("UseProgramStages failed");
718 		}
719 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
720 
721 		// Use Fragment Shader
722 		shaderSrc[0] = frag.c_str();
723 		programFrag  = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc);
724 
725 		gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programFrag);
726 		gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF);
727 		if ((programFrag == 0) || (progIdF != programFrag) || (progIdF == progIdV))
728 		{
729 			TCU_FAIL("UseProgramStages failed");
730 		}
731 
732 		// Reset stages
733 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0);
734 		gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint*)&progIdV);
735 		gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF);
736 		if ((progIdV != 0) || (progIdF != 0))
737 		{
738 			TCU_FAIL("UseProgramStages failed");
739 		}
740 
741 		// One program for both.
742 		glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str()));
743 
744 		// Make separable and relink
745 		gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
746 		gl.linkProgram(progVF.getProgram());
747 		gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus);
748 		if (linkStatus != 1)
749 		{
750 			TCU_FAIL("UseProgramStages failed");
751 		}
752 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
753 
754 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram());
755 		gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint*)&progIdV);
756 		gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF);
757 		if ((progIdV != progVF.getProgram()) || (progIdV != progIdF))
758 		{
759 			TCU_FAIL("UseProgramStages failed");
760 		}
761 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
762 
763 		// Use a fragment program with vertex bit
764 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0);
765 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programFrag);
766 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
767 
768 		// Unbound pipeline
769 		gl.bindProgramPipeline(0);
770 		gl.deleteProgramPipelines(1, &pipeline);
771 		pipeline = 0;
772 		gl.genProgramPipelines(1, &pipeline);
773 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx);
774 		gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programFrag);
775 		gl.getProgramPipelineiv(pipeline, GL_VERTEX_SHADER, (glw::GLint*)&progIdV);
776 		gl.getProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, (glw::GLint*)&progIdF);
777 		if ((progIdV != programVtx) || (progIdF != programFrag))
778 		{
779 			TCU_FAIL("UseProgramStages failed");
780 		}
781 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
782 
783 		// Negative Cases
784 
785 		// Invalid stages
786 		gl.useProgramStages(pipeline, GL_ALL_SHADER_BITS ^ (GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT), programVtx);
787 		err = gl.getError();
788 		if (err != GL_INVALID_VALUE)
789 		{
790 			TCU_FAIL("UseProgramStages failed");
791 		}
792 
793 		// Program that is not separable
794 		gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
795 		gl.linkProgram(progVF.getProgram());
796 		gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus);
797 		if (linkStatus != 1)
798 		{
799 			TCU_FAIL("UseProgramStages failed");
800 		}
801 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failed");
802 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram());
803 		err = gl.getError();
804 		if (err != GL_INVALID_OPERATION)
805 		{
806 			TCU_FAIL("UseProgramStages failed");
807 		}
808 
809 		// Program that is not successfully linked
810 		// remove the main keyword
811 		std::string  fragNoMain = frag;
812 		unsigned int pos		= (unsigned int)fragNoMain.find("main");
813 		fragNoMain.replace(pos, 4, "niaM");
814 		glu::ShaderProgram progNoLink(m_context.getRenderContext(),
815 									  glu::makeVtxFragSources(vtx.c_str(), fragNoMain.c_str()));
816 
817 		gl.programParameteri(progNoLink.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
818 		gl.linkProgram(progNoLink.getProgram());
819 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progNoLink.getProgram());
820 		err = gl.getError();
821 		if (err != GL_INVALID_OPERATION)
822 		{
823 			TCU_FAIL("UseProgramStages failed");
824 		}
825 
826 		// Invalid pipeline
827 		gl.useProgramStages(pipeline + 1000, GL_VERTEX_SHADER_BIT, programVtx);
828 		err = gl.getError();
829 		if (err != GL_INVALID_OPERATION)
830 		{
831 			TCU_FAIL("UseProgramStages failed");
832 		}
833 
834 		// Invalid pipeline
835 		gl.deleteProgramPipelines(1, &pipeline);
836 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programVtx);
837 		err = gl.getError();
838 		if (err != GL_INVALID_OPERATION)
839 		{
840 			TCU_FAIL("UseProgramStages failed");
841 		}
842 
843 		gl.deleteProgram(programVtx);
844 		gl.deleteProgram(programFrag);
845 
846 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
847 		return STOP;
848 	}
849 
850 private:
851 	glu::GLSLVersion m_glslVersion;
852 };
853 
854 // Testcase for pipeline api
855 class PipelineApiCase : public TestCase
856 {
857 public:
PipelineApiCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)858 	PipelineApiCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion)
859 		: TestCase(context, name, description), m_glslVersion(glslVersion)
860 	{
861 	}
862 
~PipelineApiCase(void)863 	~PipelineApiCase(void)
864 	{
865 	}
866 
867 	// Validate glGetProgramPipelineInfoLog
checkProgInfoLog(const glw::Functions & gl,GLuint pipeline)868 	void checkProgInfoLog(const glw::Functions& gl, GLuint pipeline)
869 	{
870 		glw::GLint   value;
871 		glw::GLsizei bufSize;
872 		glw::GLsizei length;
873 		glw::GLenum  err;
874 
875 		gl.getProgramPipelineiv(pipeline, GL_INFO_LOG_LENGTH, &value);
876 		std::vector<char> infoLogBuf(value + 1);
877 
878 		bufSize = 0;
879 		gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]);
880 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramPipelineInfoLog failed");
881 
882 		bufSize = value / 2; // read half the log
883 		gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]);
884 		if ((bufSize != 0) && (bufSize != length + 1))
885 		{
886 			TCU_FAIL("GetProgramPipelineInfoLog failed");
887 		}
888 		bufSize = value;
889 		gl.getProgramPipelineInfoLog(pipeline, bufSize, &length, &infoLogBuf[0]);
890 		if ((bufSize != 0) && (bufSize != length + 1))
891 		{
892 			TCU_FAIL("GetProgramPipelineInfoLog failed");
893 		}
894 
895 		// Negative case for GetProgramPipelineInfoLog
896 
897 		gl.getProgramPipelineInfoLog(pipeline + 101, bufSize, &length, &infoLogBuf[0]);
898 		err = gl.getError();
899 		if (err != GL_INVALID_VALUE)
900 		{
901 			TCU_FAIL("GetProgramPipelineInfoLog failed");
902 		}
903 	}
904 
iterate(void)905 	IterateResult iterate(void)
906 	{
907 		TestLog&			  log = m_testCtx.getLog();
908 		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
909 		glw::GLenum			  err;
910 		const int			  maxpipelines = 10;
911 		glw::GLuint			  pipelines[maxpipelines];
912 		std::string			  vtx;
913 		std::string			  frag;
914 		glw::GLint			  linkStatus;
915 		glw::GLuint			  value;
916 
917 		vtx  = generateBasicVertexSrc(m_glslVersion);
918 		frag = generateBasicFragmentSrc(m_glslVersion);
919 
920 		// Pipeline API verification
921 		log << TestLog::Message << "Begin:PipelineApiCase iterate" << TestLog::EndMessage;
922 
923 		glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str()));
924 
925 		// Make separable and relink
926 		gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
927 		gl.linkProgram(progVF.getProgram());
928 		gl.getProgramiv(progVF.getProgram(), GL_LINK_STATUS, &linkStatus);
929 		if (linkStatus != 1)
930 		{
931 			TCU_FAIL("LinkProgram failed");
932 		}
933 
934 		gl.genProgramPipelines(1, pipelines);
935 
936 		// ActiveShaderProgram
937 		gl.activeShaderProgram(pipelines[0], progVF.getProgram());
938 		GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveShaderProgram failed");
939 
940 		// Negative cases for ActiveShaderProgram
941 
942 		// Nonexistent program
943 		gl.activeShaderProgram(pipelines[0], progVF.getProgram() + 100);
944 		err = gl.getError();
945 		if (err != GL_INVALID_VALUE)
946 		{
947 			TCU_FAIL("ActiveShaderProgram failed");
948 		}
949 		gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint*)&value);
950 		if (value != progVF.getProgram())
951 		{
952 			TCU_FAIL("ActiveShaderProgram failed");
953 		}
954 
955 		// Deleted pipeline
956 		gl.deleteProgramPipelines(1, pipelines);
957 		gl.activeShaderProgram(pipelines[0], progVF.getProgram());
958 		err = gl.getError();
959 		if (err != GL_INVALID_OPERATION)
960 		{
961 			TCU_FAIL("ActiveShaderProgram failed");
962 		}
963 
964 		// GenProgramPipeline
965 
966 		gl.genProgramPipelines(2, &pipelines[0]);
967 		gl.genProgramPipelines(3, &pipelines[2]);
968 		gl.genProgramPipelines(5, &pipelines[5]);
969 
970 		for (int i = 0; i < maxpipelines; i++)
971 		{
972 			gl.bindProgramPipeline(pipelines[i]); // has to be bound to be recognized
973 			if (!gl.isProgramPipeline(pipelines[i]))
974 			{
975 				TCU_FAIL("GenProgramPipelines failed");
976 			}
977 		}
978 		gl.deleteProgramPipelines(maxpipelines, pipelines);
979 
980 		// BindProgramPipeline
981 
982 		gl.genProgramPipelines(2, pipelines);
983 		gl.bindProgramPipeline(pipelines[0]);
984 		gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint*)&value);
985 		if (value != pipelines[0])
986 		{
987 			TCU_FAIL("BindProgramPipeline failed");
988 		}
989 		gl.bindProgramPipeline(pipelines[1]);
990 		gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint*)&value);
991 		if (value != pipelines[1])
992 		{
993 			TCU_FAIL("BindProgramPipeline failed");
994 		}
995 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline failed");
996 
997 		// Negative Case for BindProgramPipeline
998 
999 		gl.bindProgramPipeline(pipelines[2]); // deleted pipeline
1000 		gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint*)&value);
1001 		err = gl.getError();
1002 		if ((err != GL_INVALID_OPERATION) || (value != pipelines[1]))
1003 		{
1004 			TCU_FAIL("BindProgramPipeline failed");
1005 		}
1006 
1007 		// DeleteProgramPipelines
1008 
1009 		gl.genProgramPipelines(8, &pipelines[2]); // back to 10 total
1010 		gl.deleteProgramPipelines(2, &pipelines[8]);
1011 		gl.deleteProgramPipelines(3, &pipelines[5]);
1012 		pipelines[9] = 0;
1013 		gl.deleteProgramPipelines(maxpipelines, pipelines); // 5 good, 4 deleted, 1 zero
1014 		gl.deleteProgramPipelines(0, pipelines);
1015 		GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteProgramPipelines failed");
1016 		for (int i = 0; i < maxpipelines; i++)
1017 		{
1018 			if (gl.isProgramPipeline(pipelines[i]))
1019 			{
1020 				TCU_FAIL("DeleteProgramPipelines failed");
1021 			}
1022 		}
1023 		gl.getIntegerv(GL_PROGRAM_PIPELINE_BINDING, (glw::GLint*)&value);
1024 		if (value != 0)
1025 		{
1026 			TCU_FAIL("DeleteProgramPipelines failed");
1027 		}
1028 
1029 		// IsProgramPipeline
1030 
1031 		pipelines[1] = 0x1000;
1032 		pipelines[2] += 100;
1033 		for (int i = 0; i < 3; i++)
1034 		{
1035 			// 1 deleted and 2 bogus values
1036 			if (gl.isProgramPipeline(pipelines[i]))
1037 			{
1038 				TCU_FAIL("IsProgramPipeline failed");
1039 			}
1040 		}
1041 		gl.genProgramPipelines(1, pipelines);
1042 		if (gl.isProgramPipeline(pipelines[0]))
1043 		{
1044 			TCU_FAIL("IsProgramPipeline failed");
1045 		}
1046 		gl.deleteProgramPipelines(1, pipelines);
1047 		GLU_EXPECT_NO_ERROR(gl.getError(), "IsProgramPipeline failed");
1048 
1049 		// ProgramParameteri PROGRAM_SEPARABLE
1050 		// NOTE: The query for PROGRAM_SEPARABLE must query latched
1051 		//       state. In other words, the state of the binary after
1052 		//       it was linked. So in the tests below, the queries
1053 		//       should return the default state GL_FALSE since the
1054 		//       program has no linked binary.
1055 
1056 		glw::GLuint programSep = gl.createProgram();
1057 		int			separable;
1058 		gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_TRUE);
1059 		gl.getProgramiv(programSep, GL_PROGRAM_SEPARABLE, &separable);
1060 		if (separable != GL_FALSE)
1061 		{
1062 			TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed");
1063 		}
1064 		gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_FALSE);
1065 		gl.getProgramiv(programSep, GL_PROGRAM_SEPARABLE, &separable);
1066 		if (separable != 0)
1067 		{
1068 			TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed");
1069 		}
1070 
1071 		// Negative Case for ProgramParameteri PROGRAM_SEPARABLE
1072 
1073 		gl.deleteProgram(programSep);
1074 		gl.programParameteri(programSep, GL_PROGRAM_SEPARABLE, GL_TRUE);
1075 		err = gl.getError();
1076 		if (err != GL_INVALID_VALUE)
1077 		{
1078 			TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed");
1079 		}
1080 		gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, 501);
1081 		err = gl.getError();
1082 		if (err != GL_INVALID_VALUE)
1083 		{
1084 			TCU_FAIL("programParameteri PROGRAM_SEPARABLE failed");
1085 		}
1086 
1087 		// GetProgramPipelineiv
1088 
1089 		gl.genProgramPipelines(1, pipelines);
1090 		gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint*)&value);
1091 		if (value != 0)
1092 		{
1093 			TCU_FAIL("GetProgramPipelineiv failed for ACTIVE_PROGRAM");
1094 		}
1095 		gl.getProgramPipelineiv(pipelines[0], GL_VERTEX_SHADER, (glw::GLint*)&value);
1096 		if (value != 0)
1097 		{
1098 			TCU_FAIL("GetProgramPipelineiv failed for VERTEX_SHADER");
1099 		}
1100 		gl.getProgramPipelineiv(pipelines[0], GL_FRAGMENT_SHADER, (glw::GLint*)&value);
1101 		if (value != 0)
1102 		{
1103 			TCU_FAIL("GetProgramPipelineiv failed for FRAGMENT_SHADER");
1104 		}
1105 		gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value);
1106 		if (value != 0)
1107 		{
1108 			TCU_FAIL("GetProgramPipelineiv failed for VALIDATE_STATUS");
1109 		}
1110 		gl.getProgramPipelineiv(pipelines[0], GL_INFO_LOG_LENGTH, (glw::GLint*)&value);
1111 		if (value != 0)
1112 		{
1113 			TCU_FAIL("GetProgramPipelineiv failed for INFO_LOG_LENGTH");
1114 		}
1115 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramPipelineiv failed");
1116 
1117 		// Negative Case for GetProgramPipelineiv
1118 
1119 		gl.deleteProgramPipelines(1, pipelines);
1120 		gl.getProgramPipelineiv(pipelines[0], GL_ACTIVE_PROGRAM, (glw::GLint*)&value);
1121 		err = gl.getError();
1122 		if (err != GL_INVALID_OPERATION)
1123 		{
1124 			TCU_FAIL("GetProgramPipelineiv failed for ACTIVE_PROGRAM");
1125 		}
1126 
1127 		// ValidateProgramPipeline
1128 
1129 		gl.genProgramPipelines(1, pipelines); // Unvalidated
1130 		gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value);
1131 		if (value != 0)
1132 		{
1133 			TCU_FAIL("ValidateProgramPipeline failed");
1134 		}
1135 
1136 		gl.validateProgramPipeline(pipelines[0]); // Not bound yet
1137 		gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value);
1138 		if (value != 0)
1139 		{
1140 			TCU_FAIL("ValidateProgramPipeline failed");
1141 		}
1142 
1143 		gl.bindProgramPipeline(pipelines[0]);
1144 
1145 		gl.validateProgramPipeline(pipelines[0]); // Still empty program pipeline.
1146 		gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value);
1147 		if (value != 0)
1148 		{
1149 			TCU_FAIL("ValidateProgramPipeline failed with empty program pipeline");
1150 		}
1151 
1152 		gl.useProgramStages(pipelines[0], GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, progVF.getProgram());
1153 		gl.validateProgramPipeline(pipelines[0]);
1154 		gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value);
1155 		if (value != 1)
1156 		{
1157 			TCU_FAIL("ValidateProgramPipeline failed");
1158 		}
1159 
1160 		// GetProgramPipelineInfoLog
1161 		checkProgInfoLog(gl, pipelines[0]);
1162 
1163 		// ValidateProgramPipeline additional
1164 		// Relink the bound separable program as not separable
1165 		gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
1166 		gl.linkProgram(progVF.getProgram());
1167 		err = gl.getError();
1168 		gl.validateProgramPipeline(pipelines[0]);
1169 		gl.getProgramPipelineiv(pipelines[0], GL_VALIDATE_STATUS, (glw::GLint*)&value);
1170 		if (value != 0)
1171 		{
1172 			TCU_FAIL("ValidateProgramPipeline failed");
1173 		}
1174 		GLU_EXPECT_NO_ERROR(gl.getError(), "ValidateProgramPipeline failed");
1175 
1176 		// GetProgramPipelineInfoLog
1177 		checkProgInfoLog(gl, pipelines[0]);
1178 
1179 		// Negative Case for ValidateProgramPipeline
1180 
1181 		gl.deleteProgramPipelines(1, pipelines);
1182 		gl.validateProgramPipeline(pipelines[0]);
1183 		err = gl.getError();
1184 		if (err != GL_INVALID_OPERATION)
1185 		{
1186 			TCU_FAIL("ValidateProgramPipeline failed");
1187 		}
1188 
1189 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1190 		return STOP;
1191 	}
1192 
1193 private:
1194 	glu::GLSLVersion m_glslVersion;
1195 };
1196 
1197 // Testcase for glProgramUniform
1198 class ProgramUniformCase : public TestCase
1199 {
1200 public:
ProgramUniformCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)1201 	ProgramUniformCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion)
1202 		: TestCase(context, name, description), m_glslVersion(glslVersion)
1203 	{
1204 	}
1205 
~ProgramUniformCase(void)1206 	~ProgramUniformCase(void)
1207 	{
1208 	}
1209 
isDataTypeSquareMatrix(glu::DataType dtyp)1210 	bool isDataTypeSquareMatrix(glu::DataType dtyp)
1211 	{
1212 		return (dtyp == glu::TYPE_FLOAT_MAT2) || (dtyp == glu::TYPE_FLOAT_MAT3) || (dtyp == glu::TYPE_FLOAT_MAT4);
1213 	}
1214 
1215 	// outFragSrc will hold a fragment program that is DataType specific
generateUniformFragSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,glu::DataType dType)1216 	void generateUniformFragSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion, glu::DataType dType)
1217 	{
1218 		std::ostringstream fragSrc;
1219 
1220 		fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
1221 		if (isDataTypeMatrix(dType) && isDataTypeSquareMatrix(dType))
1222 		{
1223 			fragSrc << s_unifFragSquareMatShaderSrc;
1224 		}
1225 		else if (isDataTypeMatrix(dType) && !isDataTypeSquareMatrix(dType))
1226 		{
1227 			fragSrc << s_unifFragNonSquareMatShaderSrc;
1228 		}
1229 		else
1230 		{
1231 			fragSrc << s_unifFragShaderSrc;
1232 		}
1233 
1234 		std::map<std::string, std::string> params;
1235 
1236 		if (dType == glu::TYPE_INT)
1237 		{
1238 			params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "int"));
1239 			params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "ivec"));
1240 			params.insert(std::pair<std::string, std::string>("SFX", ""));
1241 		}
1242 		else if (dType == glu::TYPE_UINT)
1243 		{
1244 			params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "uint"));
1245 			params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "uvec"));
1246 			params.insert(std::pair<std::string, std::string>("SFX", "u"));
1247 		}
1248 		else if (dType == glu::TYPE_FLOAT)
1249 		{
1250 			params.insert(std::pair<std::string, std::string>("SCALAR_TYPE", "float"));
1251 			params.insert(std::pair<std::string, std::string>("VECTOR_TYPE", "vec"));
1252 			params.insert(std::pair<std::string, std::string>("SFX", ".0"));
1253 		}
1254 
1255 		tcu::StringTemplate fragTmpl(fragSrc.str().c_str());
1256 		outFragSrc = fragTmpl.specialize(params);
1257 	}
1258 
1259 	// Set the integer programUniforms
progUniformi(const glw::Functions & gl,glw::GLuint prog,int arraySize,int * location,int * value)1260 	void progUniformi(const glw::Functions& gl, glw::GLuint prog, int arraySize, int* location, int* value)
1261 	{
1262 		gl.programUniform1i(prog, location[0], value[0]);
1263 		value += 1;
1264 		gl.programUniform2i(prog, location[1], value[0], value[1]);
1265 		value += 2;
1266 		gl.programUniform3i(prog, location[2], value[0], value[1], value[2]);
1267 		value += 3;
1268 		gl.programUniform4i(prog, location[3], value[0], value[1], value[2], value[3]);
1269 		value += 4;
1270 
1271 		gl.programUniform1iv(prog, location[4], arraySize, value);
1272 		value += 1 * arraySize;
1273 		gl.programUniform2iv(prog, location[6], arraySize, value);
1274 		value += 2 * arraySize;
1275 		gl.programUniform3iv(prog, location[8], arraySize, value);
1276 		value += 3 * arraySize;
1277 		gl.programUniform4iv(prog, location[10], arraySize, value);
1278 	}
1279 
1280 	// Set the unsigned integer programUniforms
progUniformui(const glw::Functions & gl,glw::GLuint prog,int arraySize,int * location,unsigned int * value)1281 	void progUniformui(const glw::Functions& gl, glw::GLuint prog, int arraySize, int* location, unsigned int* value)
1282 	{
1283 		gl.programUniform1ui(prog, location[0], value[0]);
1284 		value += 1;
1285 		gl.programUniform2ui(prog, location[1], value[0], value[1]);
1286 		value += 2;
1287 		gl.programUniform3ui(prog, location[2], value[0], value[1], value[2]);
1288 		value += 3;
1289 		gl.programUniform4ui(prog, location[3], value[0], value[1], value[2], value[3]);
1290 		value += 4;
1291 
1292 		gl.programUniform1uiv(prog, location[4], arraySize, value);
1293 		value += 1 * arraySize;
1294 		gl.programUniform2uiv(prog, location[6], arraySize, value);
1295 		value += 2 * arraySize;
1296 		gl.programUniform3uiv(prog, location[8], arraySize, value);
1297 		value += 3 * arraySize;
1298 		gl.programUniform4uiv(prog, location[10], arraySize, value);
1299 	}
1300 
1301 	// Set the float programUniforms
progUniformf(const glw::Functions & gl,glw::GLuint prog,int arraySize,int * location,float * value)1302 	void progUniformf(const glw::Functions& gl, glw::GLuint prog, int arraySize, int* location, float* value)
1303 	{
1304 		gl.programUniform1f(prog, location[0], value[0]);
1305 		value += 1;
1306 		gl.programUniform2f(prog, location[1], value[0], value[1]);
1307 		value += 2;
1308 		gl.programUniform3f(prog, location[2], value[0], value[1], value[2]);
1309 		value += 3;
1310 		gl.programUniform4f(prog, location[3], value[0], value[1], value[2], value[3]);
1311 		value += 4;
1312 
1313 		gl.programUniform1fv(prog, location[4], arraySize, value);
1314 		value += 1 * arraySize;
1315 		gl.programUniform2fv(prog, location[6], arraySize, value);
1316 		value += 2 * arraySize;
1317 		gl.programUniform3fv(prog, location[8], arraySize, value);
1318 		value += 3 * arraySize;
1319 		gl.programUniform4fv(prog, location[10], arraySize, value);
1320 	}
1321 
1322 	// Set the integer uniforms with conventional glUniformi
activeUniformi(const glw::Functions & gl,int arraySize,int * location,int * value)1323 	void activeUniformi(const glw::Functions& gl, int arraySize, int* location, int* value)
1324 	{
1325 		gl.uniform1i(location[0], value[0]);
1326 		value += 1;
1327 		gl.uniform2i(location[1], value[0], value[1]);
1328 		value += 2;
1329 		gl.uniform3i(location[2], value[0], value[1], value[2]);
1330 		value += 3;
1331 		gl.uniform4i(location[3], value[0], value[1], value[2], value[3]);
1332 		value += 4;
1333 
1334 		gl.uniform1iv(location[4], arraySize, value);
1335 		value += 1 * arraySize;
1336 		gl.uniform2iv(location[6], arraySize, value);
1337 		value += 2 * arraySize;
1338 		gl.uniform3iv(location[8], arraySize, value);
1339 		value += 3 * arraySize;
1340 		gl.uniform4iv(location[10], arraySize, value);
1341 	}
1342 
1343 	// Set the unsigned integer uniforms with conventional glUniformui
activeUniformui(const glw::Functions & gl,int arraySize,int * location,unsigned int * value)1344 	void activeUniformui(const glw::Functions& gl, int arraySize, int* location, unsigned int* value)
1345 	{
1346 		gl.uniform1ui(location[0], value[0]);
1347 		value += 1;
1348 		gl.uniform2ui(location[1], value[0], value[1]);
1349 		value += 2;
1350 		gl.uniform3ui(location[2], value[0], value[1], value[2]);
1351 		value += 3;
1352 		gl.uniform4ui(location[3], value[0], value[1], value[2], value[3]);
1353 		value += 4;
1354 
1355 		gl.uniform1uiv(location[4], arraySize, value);
1356 		value += 1 * arraySize;
1357 		gl.uniform2uiv(location[6], arraySize, value);
1358 		value += 2 * arraySize;
1359 		gl.uniform3uiv(location[8], arraySize, value);
1360 		value += 3 * arraySize;
1361 		gl.uniform4uiv(location[10], arraySize, value);
1362 	}
1363 
1364 	// Set the float uniforms with conventional glUniformui
activeUniformf(const glw::Functions & gl,int arraySize,int * location,float * value)1365 	void activeUniformf(const glw::Functions& gl, int arraySize, int* location, float* value)
1366 	{
1367 		gl.uniform1f(location[0], value[0]);
1368 		value += 1;
1369 		gl.uniform2f(location[1], value[0], value[1]);
1370 		value += 2;
1371 		gl.uniform3f(location[2], value[0], value[1], value[2]);
1372 		value += 3;
1373 		gl.uniform4f(location[3], value[0], value[1], value[2], value[3]);
1374 		value += 4;
1375 
1376 		gl.uniform1fv(location[4], arraySize, value);
1377 		value += 1 * arraySize;
1378 		gl.uniform2fv(location[6], arraySize, value);
1379 		value += 2 * arraySize;
1380 		gl.uniform3fv(location[8], arraySize, value);
1381 		value += 3 * arraySize;
1382 		gl.uniform4fv(location[10], arraySize, value);
1383 	}
1384 
1385 	// Call programUniform and verify for non-Matrix uniforms
1386 	// Two programs are verified independently and against each other
setAndCompareUniforms(glw::GLuint pipeline,glw::GLuint programA,glw::GLuint programB,glu::DataType dType,int seed)1387 	bool setAndCompareUniforms(glw::GLuint pipeline, glw::GLuint programA, glw::GLuint programB, glu::DataType dType,
1388 							   int seed)
1389 	{
1390 		TestLog&			  log = m_testCtx.getLog();
1391 		const glw::Functions& gl  = m_context.getRenderContext().getFunctions();
1392 		// The fragment shader has defined uniforms of type:
1393 		// scalar, vec2, vec3, vec4, and then length 2 arrays of
1394 		// scalar, vec2, vec3, and vec4.
1395 		// 4 uniforms in array form and 4 not in arrays.
1396 		// We query a total of 12 uniform locations
1397 		const int nonarrayUnifCount = 4;
1398 		const int arrayUnifCount	= 4;
1399 		const int arraySize			= 2;
1400 		const int locationCount		= nonarrayUnifCount + arraySize * arrayUnifCount;
1401 		// dwordCount represents the number of dwords to compare for each uniform location
1402 		// scalar, vec2, vec3, vec4, scalar[0], scalar[1], vec2[0], vec2[1], etc.
1403 		const int  dwordCount[locationCount] = { 1, 2, 3, 4, 1, 1, 2, 2, 3, 3, 4, 4 };
1404 		glw::GLint locationA[locationCount];
1405 		glw::GLint locationB[locationCount];
1406 		// The total amount of data the uniforms take up: 1+2+3+4 + 2*(1+2+3+4)
1407 		const int	udataCount = 30;
1408 		unsigned int udata[udataCount]; //
1409 		int*		 data  = (int*)&udata[0];
1410 		float*		 fdata = (float*)&udata[0];
1411 		int			 i, j, k;
1412 		std::string  uniformBaseName("uVal");
1413 
1414 		// ProgramUniform API verification
1415 		log << TestLog::Message << "Begin:ProgramUniformCase iterate" << TestLog::EndMessage;
1416 
1417 		// get uniform locations
1418 		// scalar and vec uniforms
1419 		for (i = 0; i < nonarrayUnifCount; i++)
1420 		{
1421 			string name  = uniformBaseName + de::toString(i);
1422 			locationA[i] = gl.getUniformLocation(programA, name.c_str());
1423 			locationB[i] = gl.getUniformLocation(programB, name.c_str());
1424 		}
1425 		// uniform arrays
1426 		for (j = 0; j < arrayUnifCount; j++)
1427 		{
1428 			for (k = 0; k < arraySize; k++)
1429 			{
1430 				string name  = uniformBaseName + de::toString(nonarrayUnifCount + j) + "[" + de::toString(k) + "]";
1431 				locationA[i] = gl.getUniformLocation(programA, name.c_str());
1432 				locationB[i] = gl.getUniformLocation(programB, name.c_str());
1433 				i++;
1434 			}
1435 		}
1436 
1437 		// seed data buffer with unique values
1438 		if (dType == glu::TYPE_FLOAT)
1439 		{
1440 			for (i = 0; i < udataCount; i++)
1441 			{
1442 				fdata[i] = (float)(seed + i);
1443 			}
1444 		}
1445 		else
1446 		{
1447 			for (i = 0; i < udataCount; i++)
1448 			{
1449 				data[i] = seed + i;
1450 			}
1451 		}
1452 
1453 		// set uniforms in program A
1454 		if (dType == glu::TYPE_INT)
1455 		{
1456 			progUniformi(gl, programA, arraySize, locationA, data);
1457 		}
1458 		else if (dType == glu::TYPE_UINT)
1459 		{
1460 			progUniformui(gl, programA, arraySize, locationA, udata);
1461 		}
1462 		else if (dType == glu::TYPE_FLOAT)
1463 		{
1464 			progUniformf(gl, programA, arraySize, locationA, fdata);
1465 		}
1466 
1467 		// get and compare uniforms
1468 		unsigned int* uValue = &udata[0];
1469 		for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++)
1470 		{
1471 			unsigned int retValA[4], retValB[4];
1472 
1473 			if (dType == glu::TYPE_INT)
1474 			{
1475 				gl.getUniformiv(programA, locationA[i], (int*)&retValA[0]);
1476 				gl.getUniformiv(programB, locationB[i], (int*)&retValB[0]);
1477 			}
1478 			else if (dType == glu::TYPE_UINT)
1479 			{
1480 				gl.getUniformuiv(programA, locationA[i], &retValA[0]);
1481 				gl.getUniformuiv(programB, locationB[i], &retValB[0]);
1482 			}
1483 			else if (dType == glu::TYPE_FLOAT)
1484 			{
1485 				gl.getUniformfv(programA, locationA[i], (float*)&retValA[0]);
1486 				gl.getUniformfv(programB, locationB[i], (float*)&retValB[0]);
1487 			}
1488 
1489 			for (j = 0; j < dwordCount[i]; j++)
1490 			{
1491 				// Compare programA uniform to expected value and
1492 				// test to see if programB picked up the value.
1493 				if ((retValA[j] != *uValue++) || (retValA[j] == retValB[j]))
1494 				{
1495 					TCU_FAIL("ProgramUniformi failed");
1496 				}
1497 			}
1498 		}
1499 
1500 		// reseed data buffer, continuing to increment
1501 		if (dType == glu::TYPE_FLOAT)
1502 		{
1503 			fdata[0] = fdata[udataCount - 1] + 1.0f;
1504 			for (i = 1; i < udataCount; i++)
1505 			{
1506 				fdata[i] = fdata[i - 1] + 1.0f;
1507 			}
1508 		}
1509 		else
1510 		{
1511 			data[0] = data[udataCount - 1] + 1;
1512 			for (i = 1; i < udataCount; i++)
1513 			{
1514 				data[i] = data[i - 1] + 1;
1515 			}
1516 		}
1517 
1518 		// set uniforms in program B
1519 
1520 		if (dType == glu::TYPE_INT)
1521 		{
1522 			progUniformi(gl, programB, arraySize, locationB, data);
1523 		}
1524 		else if (dType == glu::TYPE_UINT)
1525 		{
1526 			progUniformui(gl, programB, arraySize, locationB, udata);
1527 		}
1528 		else if (dType == glu::TYPE_FLOAT)
1529 		{
1530 			progUniformf(gl, programB, arraySize, locationB, fdata);
1531 		}
1532 
1533 		// get and compare uniforms
1534 		uValue = &udata[0];
1535 		for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++)
1536 		{
1537 			unsigned int retValA[4], retValB[4];
1538 
1539 			if (dType == glu::TYPE_INT)
1540 			{
1541 				gl.getUniformiv(programA, locationA[i], (int*)&retValA[0]);
1542 				gl.getUniformiv(programB, locationB[i], (int*)&retValB[0]);
1543 			}
1544 			else if (dType == glu::TYPE_UINT)
1545 			{
1546 				gl.getUniformuiv(programA, locationA[i], &retValA[0]);
1547 				gl.getUniformuiv(programB, locationB[i], &retValB[0]);
1548 			}
1549 			else if (dType == glu::TYPE_FLOAT)
1550 			{
1551 				gl.getUniformfv(programA, locationA[i], (float*)&retValA[0]);
1552 				gl.getUniformfv(programB, locationB[i], (float*)&retValB[0]);
1553 			}
1554 
1555 			for (j = 0; j < dwordCount[i]; j++)
1556 			{
1557 				// Compare programB uniform to expected value and
1558 				// test to see if programA picked up the value.
1559 				if ((retValB[j] != *uValue++) || (retValA[j] == retValB[j]))
1560 				{
1561 					TCU_FAIL("ProgramUniformi failed");
1562 				}
1563 			}
1564 		}
1565 
1566 		// Test the conventional uniform interfaces on an ACTIVE_PROGRAM
1567 		glw::GLuint activeProgram = 0;
1568 		if (pipeline != 0)
1569 		{
1570 			gl.getProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, (int*)&activeProgram);
1571 		}
1572 		if ((activeProgram != 0) && ((activeProgram == programA) || (activeProgram == programB)))
1573 		{
1574 			glw::GLint* location;
1575 
1576 			location = (activeProgram == programA) ? locationA : locationB;
1577 
1578 			// reseed data buffer, continuing to increment
1579 			if (dType == glu::TYPE_FLOAT)
1580 			{
1581 				fdata[0] = fdata[udataCount - 1] + 1.0f;
1582 				for (i = 1; i < udataCount; i++)
1583 				{
1584 					fdata[i] = fdata[i - 1] + 1.0f;
1585 				}
1586 			}
1587 			else
1588 			{
1589 				data[0] = data[udataCount - 1] + 1;
1590 				for (i = 1; i < udataCount; i++)
1591 				{
1592 					data[i] = data[i - 1] + 1;
1593 				}
1594 			}
1595 
1596 			// set uniforms using original glUniform*
1597 
1598 			if (dType == glu::TYPE_INT)
1599 			{
1600 				activeUniformi(gl, arraySize, location, data);
1601 			}
1602 			else if (dType == glu::TYPE_UINT)
1603 			{
1604 				activeUniformui(gl, arraySize, location, udata);
1605 			}
1606 			else if (dType == glu::TYPE_FLOAT)
1607 			{
1608 				activeUniformf(gl, arraySize, location, fdata);
1609 			}
1610 
1611 			// get and compare uniforms
1612 			uValue = &udata[0];
1613 			for (i = 0; i < nonarrayUnifCount + arraySize * arrayUnifCount; i++)
1614 			{
1615 				unsigned int retVal[4];
1616 
1617 				if (dType == glu::TYPE_INT)
1618 				{
1619 					gl.getUniformiv(activeProgram, location[i], (int*)&retVal[0]);
1620 				}
1621 				else if (dType == glu::TYPE_UINT)
1622 				{
1623 					gl.getUniformuiv(activeProgram, location[i], &retVal[0]);
1624 				}
1625 				else if (dType == glu::TYPE_FLOAT)
1626 				{
1627 					gl.getUniformfv(activeProgram, location[i], (float*)&retVal[0]);
1628 				}
1629 
1630 				for (j = 0; j < dwordCount[i]; j++)
1631 				{
1632 					// Compare activeProgram uniform to expected value
1633 					if ((retVal[j] != *uValue++))
1634 					{
1635 						TCU_FAIL("ActiveShaderProgram failed");
1636 					}
1637 				}
1638 			}
1639 		}
1640 
1641 		return true;
1642 	}
1643 
1644 	// Call programUniform for Matrix uniforms
1645 	// Two programs are verified independently and against each other
setAndCompareMatrixUniforms(glw::GLuint pipeline,glw::GLuint programA,glw::GLuint programB,glu::DataType dType,int seed)1646 	bool setAndCompareMatrixUniforms(glw::GLuint pipeline, glw::GLuint programA, glw::GLuint programB,
1647 									 glu::DataType dType, int seed)
1648 	{
1649 		TestLog&			  log		  = m_testCtx.getLog();
1650 		const glw::Functions& gl		  = m_context.getRenderContext().getFunctions();
1651 		bool				  isSquareMat = isDataTypeSquareMatrix(dType);
1652 		// The matrix versions of the fragment shader have two element arrays
1653 		// of each uniform.
1654 		// There are 3 * 2 uniforms for the square matrix shader and
1655 		// 6 * 2 uniforms in the non-square matrix shader.
1656 		const int  maxUniforms = 12;
1657 		int		   numUniforms;
1658 		const int  arraySize = 2;
1659 		glw::GLint locationA[maxUniforms];
1660 		glw::GLint locationB[maxUniforms];
1661 		// These arrays represent the number of floats for each uniform location
1662 		// 2x2[0], 2x2[1], 3x3[0], 3x3[1], 4x4[0], 4x4[1]
1663 		const int floatCountSqu[maxUniforms] = { 4, 4, 9, 9, 16, 16, 0, 0, 0, 0, 0, 0 };
1664 		// 2x3[0], 2x3[1], 2x4[0], 2x4[1], 3x2[0], 3x2[1], 3x4[0], 3x4[1], 4x2[0]...
1665 		const int  floatCountNonSqu[maxUniforms] = { 6, 6, 8, 8, 6, 6, 12, 12, 8, 8, 12, 12 };
1666 		const int* floatCount;
1667 		// Max data for the uniforms = 2*(2*3 + 3*2 + 2*4 + 4*2 + 3*4 + 4*3)
1668 		const int   maxDataCount = 104;
1669 		float		data[maxDataCount];
1670 		int			i, j, k;
1671 		std::string uniformBaseName("uValM");
1672 
1673 		// ProgramUniform API verification
1674 		log << TestLog::Message << "Begin:ProgramUniformCase for Matrix iterate" << TestLog::EndMessage;
1675 
1676 		numUniforms = 0;
1677 		// get uniform locations
1678 		for (i = 2; i <= 4; i++) // matrix dimension m
1679 		{
1680 			for (j = 2; j <= 4; j++) // matrix dimension n
1681 			{
1682 				for (k = 0; k < arraySize; k++)
1683 				{
1684 					if ((i == j) && isSquareMat)
1685 					{
1686 						string name			   = uniformBaseName + de::toString(i) + "[" + de::toString(k) + "]";
1687 						locationA[numUniforms] = gl.getUniformLocation(programA, name.c_str());
1688 						locationB[numUniforms] = gl.getUniformLocation(programB, name.c_str());
1689 						numUniforms++;
1690 					}
1691 					else if ((i != j) && !isSquareMat)
1692 					{
1693 						string name =
1694 							uniformBaseName + de::toString(i) + "x" + de::toString(j) + "[" + de::toString(k) + "]";
1695 						locationA[numUniforms] = gl.getUniformLocation(programA, name.c_str());
1696 						locationB[numUniforms] = gl.getUniformLocation(programB, name.c_str());
1697 						numUniforms++;
1698 					}
1699 				}
1700 			}
1701 		}
1702 		DE_ASSERT((numUniforms == 6) || (numUniforms == 12));
1703 
1704 		// init the float data array
1705 		for (i = 0; i < maxDataCount; i++)
1706 		{
1707 			data[i] = (float)(seed + i);
1708 		}
1709 
1710 		// Set the uniforms in programA
1711 		float* value = &data[0];
1712 		if (isSquareMat)
1713 		{
1714 			floatCount = floatCountSqu;
1715 			gl.programUniformMatrix2fv(programA, locationA[0], arraySize, GL_FALSE, value);
1716 			value += 2 * 2 * arraySize;
1717 			gl.programUniformMatrix3fv(programA, locationA[2], arraySize, GL_FALSE, value);
1718 			value += 3 * 3 * arraySize;
1719 			gl.programUniformMatrix4fv(programA, locationA[4], arraySize, GL_FALSE, value);
1720 		}
1721 		else
1722 		{
1723 			floatCount = floatCountNonSqu;
1724 			gl.programUniformMatrix2x3fv(programA, locationA[0], arraySize, GL_FALSE, value);
1725 			value += 2 * 3 * arraySize;
1726 			gl.programUniformMatrix2x4fv(programA, locationA[2], arraySize, GL_FALSE, value);
1727 			value += 2 * 4 * arraySize;
1728 			gl.programUniformMatrix3x2fv(programA, locationA[4], arraySize, GL_FALSE, value);
1729 			value += 3 * 2 * arraySize;
1730 			gl.programUniformMatrix3x4fv(programA, locationA[6], arraySize, GL_FALSE, value);
1731 			value += 3 * 4 * arraySize;
1732 			gl.programUniformMatrix4x2fv(programA, locationA[8], arraySize, GL_FALSE, value);
1733 			value += 4 * 2 * arraySize;
1734 			gl.programUniformMatrix4x3fv(programA, locationA[10], arraySize, GL_FALSE, value);
1735 		}
1736 
1737 		// get and compare the uniform data
1738 		value = &data[0];
1739 		for (i = 0; i < numUniforms; i++)
1740 		{
1741 			float retValA[16], retValB[16];
1742 
1743 			gl.getUniformfv(programA, locationA[i], retValA);
1744 			gl.getUniformfv(programB, locationB[i], retValB);
1745 
1746 			for (j = 0; j < floatCount[i]; j++)
1747 			{
1748 				// Compare programA uniform to expected value and
1749 				// test to see if programB picked up the value.
1750 				if ((retValA[j] != *value++) || (retValA[j] == retValB[j]))
1751 				{
1752 					TCU_FAIL("ProgramUniformi failed");
1753 				}
1754 			}
1755 		}
1756 
1757 		// reseed the float buffer
1758 		data[0] = data[maxDataCount - 1];
1759 		for (i = 1; i < maxDataCount; i++)
1760 		{
1761 			data[i] = data[i - 1] + 1.0f;
1762 		}
1763 
1764 		// set uniforms in program B
1765 		value = &data[0];
1766 		if (isSquareMat)
1767 		{
1768 			floatCount = floatCountSqu;
1769 			gl.programUniformMatrix2fv(programB, locationB[0], arraySize, GL_FALSE, value);
1770 			value += 2 * 2 * arraySize;
1771 			gl.programUniformMatrix3fv(programB, locationB[2], arraySize, GL_FALSE, value);
1772 			value += 3 * 3 * arraySize;
1773 			gl.programUniformMatrix4fv(programB, locationB[4], arraySize, GL_FALSE, value);
1774 		}
1775 		else
1776 		{
1777 			floatCount = floatCountNonSqu;
1778 			gl.programUniformMatrix2x3fv(programB, locationB[0], arraySize, GL_FALSE, value);
1779 			value += 2 * 3 * arraySize;
1780 			gl.programUniformMatrix2x4fv(programB, locationB[2], arraySize, GL_FALSE, value);
1781 			value += 2 * 4 * arraySize;
1782 			gl.programUniformMatrix3x2fv(programB, locationB[4], arraySize, GL_FALSE, value);
1783 			value += 3 * 2 * arraySize;
1784 			gl.programUniformMatrix3x4fv(programB, locationB[6], arraySize, GL_FALSE, value);
1785 			value += 3 * 4 * arraySize;
1786 			gl.programUniformMatrix4x2fv(programB, locationB[8], arraySize, GL_FALSE, value);
1787 			value += 4 * 2 * arraySize;
1788 			gl.programUniformMatrix4x3fv(programB, locationB[10], arraySize, GL_FALSE, value);
1789 		}
1790 
1791 		// get and compare the uniform data
1792 		value = &data[0];
1793 		for (i = 0; i < numUniforms; i++)
1794 		{
1795 			float retValA[16], retValB[16];
1796 
1797 			gl.getUniformfv(programA, locationA[i], retValA);
1798 			gl.getUniformfv(programB, locationB[i], retValB);
1799 
1800 			for (j = 0; j < floatCount[i]; j++)
1801 			{
1802 				// Compare programB uniform to expected value and
1803 				// test to see if programA picked up the value.
1804 				if ((retValB[j] != *value++) || (retValA[j] == retValB[j]))
1805 				{
1806 					TCU_FAIL("ProgramUniformi failed");
1807 				}
1808 			}
1809 		}
1810 
1811 		// Use the conventional uniform interfaces on an ACTIVE_PROGRAM
1812 		glw::GLuint activeProgram = 0;
1813 		if (pipeline != 0)
1814 		{
1815 			gl.getProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, (int*)&activeProgram);
1816 		}
1817 		if ((activeProgram != 0) && ((activeProgram == programA) || (activeProgram == programB)))
1818 		{
1819 			glw::GLint* location;
1820 
1821 			location = (activeProgram == programA) ? locationA : locationB;
1822 
1823 			// reseed the float buffer
1824 			data[0] = data[maxDataCount - 1];
1825 			for (i = 1; i < maxDataCount; i++)
1826 			{
1827 				data[i] = data[i - 1] + 1.0f;
1828 			}
1829 
1830 			// set uniforms with conventional uniform calls
1831 			value = &data[0];
1832 			if (isSquareMat)
1833 			{
1834 				floatCount = floatCountSqu;
1835 				gl.uniformMatrix2fv(location[0], arraySize, GL_FALSE, value);
1836 				value += 2 * 2 * arraySize;
1837 				gl.uniformMatrix3fv(location[2], arraySize, GL_FALSE, value);
1838 				value += 3 * 3 * arraySize;
1839 				gl.uniformMatrix4fv(location[4], arraySize, GL_FALSE, value);
1840 			}
1841 			else
1842 			{
1843 				floatCount = floatCountNonSqu;
1844 				gl.uniformMatrix2x3fv(location[0], arraySize, GL_FALSE, value);
1845 				value += 2 * 3 * arraySize;
1846 				gl.uniformMatrix2x4fv(location[2], arraySize, GL_FALSE, value);
1847 				value += 2 * 4 * arraySize;
1848 				gl.uniformMatrix3x2fv(location[4], arraySize, GL_FALSE, value);
1849 				value += 3 * 2 * arraySize;
1850 				gl.uniformMatrix3x4fv(location[6], arraySize, GL_FALSE, value);
1851 				value += 3 * 4 * arraySize;
1852 				gl.uniformMatrix4x2fv(location[8], arraySize, GL_FALSE, value);
1853 				value += 4 * 2 * arraySize;
1854 				gl.uniformMatrix4x3fv(location[10], arraySize, GL_FALSE, value);
1855 			}
1856 
1857 			// get and compare the uniform data
1858 			value = &data[0];
1859 			for (i = 0; i < numUniforms; i++)
1860 			{
1861 				float retVal[16];
1862 
1863 				gl.getUniformfv(activeProgram, location[i], retVal);
1864 
1865 				for (j = 0; j < floatCount[i]; j++)
1866 				{
1867 					// Compare activeshaderprogram uniform to expected value
1868 					if (retVal[j] != *value++)
1869 					{
1870 						TCU_FAIL("ActiveShaderProgram with glUniform failed");
1871 					}
1872 				}
1873 			}
1874 		}
1875 
1876 		return true;
1877 	}
1878 
iterate(void)1879 	IterateResult iterate(void)
1880 	{
1881 		const glw::Functions& gl	   = m_context.getRenderContext().getFunctions();
1882 		glu::DataType		  dType[5] = { glu::TYPE_INT, glu::TYPE_UINT, glu::TYPE_FLOAT, glu::TYPE_FLOAT_MAT2,
1883 								   glu::TYPE_FLOAT_MAT2X3 };
1884 
1885 		// Loop over the various data types, generate fragment programs, and test uniforms
1886 		// (MAT2 means stands for all square matrices, MAT2x3 stands for all non-square matrices)
1887 		for (int i = 0; i < 5; i++)
1888 		{
1889 			glw::GLuint programA, programB;
1890 			glw::GLuint pipeline = 0;
1891 			const char* shaderSrc[1];
1892 			std::string fragSrc;
1893 			int			seed = 1000 + (1000 * i);
1894 
1895 			generateUniformFragSrc(fragSrc, m_glslVersion, dType[i]);
1896 
1897 			size_t			  length = fragSrc.size();
1898 			std::vector<char> shaderbuf(length + 1);
1899 			fragSrc.copy(&shaderbuf[0], length);
1900 			shaderbuf[length] = '\0';
1901 			shaderSrc[0]	  = &shaderbuf[0];
1902 			programA		  = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc);
1903 			programB		  = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, shaderSrc);
1904 
1905 			if (isDataTypeMatrix(dType[i]))
1906 			{
1907 				// programs are unbound
1908 				setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed);
1909 
1910 				// bind one program with useProgramStages
1911 				gl.genProgramPipelines(1, &pipeline);
1912 				gl.bindProgramPipeline(pipeline);
1913 				gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programA);
1914 				seed += 100;
1915 				setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed);
1916 
1917 				// make an active program with activeShaderProgram
1918 				gl.activeShaderProgram(pipeline, programB);
1919 				seed += 100;
1920 				setAndCompareMatrixUniforms(pipeline, programA, programB, dType[i], seed);
1921 			}
1922 			else
1923 			{
1924 				// programs are unbound
1925 				setAndCompareUniforms(pipeline, programA, programB, dType[i], seed);
1926 
1927 				// bind one program with useProgramStages
1928 				gl.genProgramPipelines(1, &pipeline);
1929 				gl.bindProgramPipeline(pipeline);
1930 				gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programA);
1931 				seed += 100;
1932 				setAndCompareUniforms(pipeline, programA, programB, dType[i], seed);
1933 
1934 				// make an active program with activeShaderProgram
1935 				gl.activeShaderProgram(pipeline, programB);
1936 				seed += 100;
1937 				setAndCompareUniforms(pipeline, programA, programB, dType[i], seed);
1938 			}
1939 
1940 			gl.deleteProgram(programA);
1941 			gl.deleteProgram(programB);
1942 			gl.deleteProgramPipelines(1, &pipeline);
1943 		}
1944 
1945 		// Negative Cases
1946 
1947 		// Program that is not successfully linked
1948 		glw::GLenum err;
1949 		std::string vtx;
1950 		std::string frag;
1951 
1952 		vtx  = generateBasicVertexSrc(m_glslVersion);
1953 		frag = generateBasicFragmentSrc(m_glslVersion);
1954 
1955 		// remove the main keyword so it doesn't link
1956 		std::string  fragNoMain = frag;
1957 		unsigned int pos		= (unsigned int)fragNoMain.find("main");
1958 		fragNoMain.replace(pos, 4, "niaM");
1959 		glu::ShaderProgram progNoLink(m_context.getRenderContext(),
1960 									  glu::makeVtxFragSources(vtx.c_str(), fragNoMain.c_str()));
1961 		gl.programParameteri(progNoLink.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
1962 		gl.linkProgram(progNoLink.getProgram());
1963 		int unifLocation = gl.getUniformLocation(progNoLink.getProgram(), "u_color");
1964 		gl.programUniform4f(progNoLink.getProgram(), unifLocation, 1.0, 1.0, 1.0, 1.0);
1965 		err = gl.getError();
1966 		if (err != GL_INVALID_OPERATION)
1967 		{
1968 			TCU_FAIL("ProgramUniformi failed");
1969 		}
1970 
1971 		// deleted program
1972 		gl.deleteProgram(progNoLink.getProgram());
1973 		gl.programUniform4f(progNoLink.getProgram(), unifLocation, 1.0, 1.0, 1.0, 1.0);
1974 		err = gl.getError();
1975 		if (err != GL_INVALID_VALUE)
1976 		{
1977 			TCU_FAIL("ProgramUniformi failed");
1978 		}
1979 
1980 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1981 		return STOP;
1982 	}
1983 
1984 private:
1985 	glu::GLSLVersion m_glslVersion;
1986 };
1987 
1988 // Testcase for state interactions
1989 class StateInteractionCase : public TestCase
1990 {
1991 public:
StateInteractionCase(Context & context,const char * name,const char * description,glu::GLSLVersion glslVersion)1992 	StateInteractionCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion)
1993 		: TestCase(context, name, description), m_glslVersion(glslVersion)
1994 	{
1995 	}
1996 
~StateInteractionCase(void)1997 	~StateInteractionCase(void)
1998 	{
1999 	}
2000 
2001 	// Log the program info log
logProgramInfoLog(const glw::Functions & gl,glw::GLuint program)2002 	void logProgramInfoLog(const glw::Functions& gl, glw::GLuint program)
2003 	{
2004 		TestLog&	 log	 = m_testCtx.getLog();
2005 		glw::GLint   value   = 0;
2006 		glw::GLsizei bufSize = 0;
2007 		glw::GLsizei length  = 0;
2008 
2009 		gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &value);
2010 		std::vector<char> infoLogBuf(value + 1);
2011 
2012 		gl.getProgramInfoLog(program, bufSize, &length, &infoLogBuf[0]);
2013 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog failed");
2014 
2015 		log << TestLog::Message << "Program Log:\n" << &infoLogBuf[0] << TestLog::EndMessage;
2016 	}
2017 
2018 	// Check program validity created with CreateShaderProgram
checkCSProg(const glw::Functions & gl,GLuint program,int expectedLink=GL_TRUE)2019 	bool checkCSProg(const glw::Functions& gl, GLuint program, int expectedLink = GL_TRUE)
2020 	{
2021 		int linked = GL_FALSE;
2022 		if (program != 0)
2023 		{
2024 			gl.getProgramiv(program, GL_LINK_STATUS, &linked);
2025 
2026 			if (expectedLink && !linked)
2027 			{
2028 				logProgramInfoLog(gl, program);
2029 			}
2030 		}
2031 
2032 		return (program != 0) && (linked == expectedLink);
2033 	}
2034 
2035 	// Generate a vertex shader for variable input/output testing
generateVarLinkVertexShaderSrc(std::string & outVtxSrc,glu::GLSLVersion glslVersion,int numOutputs)2036 	void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, int numOutputs)
2037 	{
2038 		std::ostringstream vtxSrc;
2039 
2040 		vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2041 		if (glslVersion >= glu::GLSL_VERSION_410)
2042 		{
2043 			vtxSrc << "out gl_PerVertex {\n"
2044 					  "  vec4 gl_Position;\n"
2045 					  "};\n";
2046 		}
2047 		vtxSrc << "in highp vec4 a_position;\n";
2048 		vtxSrc << "uniform highp vec4 u_color;\n";
2049 
2050 		switch (numOutputs)
2051 		{
2052 		// Note all these cases fall through
2053 		case 5:
2054 			vtxSrc << "layout(location = 3) out vec4 o_val5;\n";
2055 		// Fallthrough
2056 		case 4:
2057 			vtxSrc << "flat out uvec4 val4;\n";
2058 		// Fallthrough
2059 		case 3:
2060 			vtxSrc << "flat out ivec2 val3;\n";
2061 		// Fallthrough
2062 		case 2:
2063 			vtxSrc << "out vec3 val2[2];\n";
2064 		// Fallthrough
2065 		case 1:
2066 			vtxSrc << "out vec4 val1;\n";
2067 		// Fallthrough
2068 		default:
2069 			vtxSrc << "out float val0;\n";
2070 		}
2071 
2072 		vtxSrc << "void main (void)\n";
2073 		vtxSrc << "{\n";
2074 		vtxSrc << "   gl_Position = a_position;\n";
2075 
2076 		// The color uniform is passed in the last declared output variable
2077 		switch (numOutputs)
2078 		{
2079 		case 5:
2080 			vtxSrc << "    o_val5 = u_color;\n";
2081 			break;
2082 		case 4:
2083 			vtxSrc << "    val4 = uvec4(u_color);\n";
2084 			break;
2085 		case 3:
2086 			vtxSrc << "    val3 = ivec2(u_color);\n";
2087 			break;
2088 		case 2:
2089 			vtxSrc << "    val2[0] = vec3(u_color);\n";
2090 			break;
2091 		case 1:
2092 			vtxSrc << "    val1 = u_color;\n";
2093 			break;
2094 		default:
2095 			vtxSrc << "    val0 = u_color.x;\n";
2096 			break;
2097 		}
2098 		vtxSrc << "}\n";
2099 
2100 		outVtxSrc = vtxSrc.str();
2101 	}
2102 
2103 	// Generate a fragment shader for variable input/output testing
generateVarLinkFragmentShaderSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,int numInputs)2104 	void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion, int numInputs)
2105 	{
2106 		std::ostringstream fragSrc;
2107 
2108 		fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2109 		fragSrc << "precision highp float;\n";
2110 		fragSrc << "precision highp int;\n";
2111 
2112 		switch (numInputs)
2113 		{
2114 		// Note all these cases fall through
2115 		case 5:
2116 			fragSrc << "layout(location = 3) in vec4 i_val5;\n";
2117 		// Fallthrough
2118 		case 4:
2119 			fragSrc << "flat in uvec4 val4;\n";
2120 		// Fallthrough
2121 		case 3:
2122 			fragSrc << "flat in ivec2 val3;\n";
2123 		// Fallthrough
2124 		case 2:
2125 			fragSrc << "in vec3 val2[2];\n";
2126 		// Fallthrough
2127 		case 1:
2128 			fragSrc << "in vec4 val1;\n";
2129 		// Fallthrough
2130 		default:
2131 			fragSrc << "in float val0;\n";
2132 		}
2133 
2134 		fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
2135 		fragSrc << "void main (void)\n";
2136 		fragSrc << "{\n";
2137 
2138 		switch (numInputs)
2139 		{
2140 		case 5:
2141 			fragSrc << "    o_color = i_val5;\n";
2142 			break;
2143 		case 4:
2144 			fragSrc << "    o_color = vec4(val4);\n";
2145 			break;
2146 		case 3:
2147 			fragSrc << "    o_color = vec4(val3, 1.0, 1.0);\n";
2148 			break;
2149 		case 2:
2150 			fragSrc << "    o_color = vec4(val2[0], 1.0);\n";
2151 			break;
2152 		case 1:
2153 			fragSrc << "    o_color = vec4(val1);\n";
2154 			break;
2155 		default:
2156 			fragSrc << "    o_color = vec4(val0, val0, val0, 1.0);\n";
2157 			break;
2158 		}
2159 
2160 		fragSrc << "}\n";
2161 
2162 		outFragSrc = fragSrc.str();
2163 	}
2164 
2165 	// Verify the surface is filled with the expected color
checkSurface(tcu::Surface surface,tcu::RGBA expectedColor)2166 	bool checkSurface(tcu::Surface surface, tcu::RGBA expectedColor)
2167 	{
2168 		int numFailedPixels = 0;
2169 		for (int y = 0; y < surface.getHeight(); y++)
2170 		{
2171 			for (int x = 0; x < surface.getWidth(); x++)
2172 			{
2173 				if (surface.getPixel(x, y) != expectedColor)
2174 					numFailedPixels += 1;
2175 			}
2176 		}
2177 
2178 		return (numFailedPixels == 0);
2179 	}
2180 
iterate(void)2181 	IterateResult iterate(void)
2182 	{
2183 		TestLog&				 log		  = m_testCtx.getLog();
2184 		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();
2185 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2186 		int						 viewportW	= de::min(16, renderTarget.getWidth());
2187 		int						 viewportH	= de::min(16, renderTarget.getHeight());
2188 		tcu::Surface			 renderedFrame(viewportW, viewportH);
2189 
2190 		glw::GLuint programA, programB;
2191 		glw::GLuint vao, vertexBuf, indexBuf;
2192 		std::string vtx;
2193 		std::string frag, frag2;
2194 		glw::GLuint pipeline;
2195 		const char* srcStrings[1];
2196 		glw::GLenum err;
2197 
2198 		log << TestLog::Message << "Begin:StateInteractionCase iterate" << TestLog::EndMessage;
2199 
2200 		gl.viewport(0, 0, viewportW, viewportH);
2201 		gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2202 		gl.clear(GL_COLOR_BUFFER_BIT);
2203 
2204 		// Check the precedence of glUseProgram over glBindProgramPipeline
2205 		// The program bound with glUseProgram will draw green, the programs
2206 		// bound with glBindProgramPipeline will render blue.
2207 		vtx  = generateBasicVertexSrc(m_glslVersion);
2208 		frag = generateBasicFragmentSrc(m_glslVersion);
2209 
2210 		glu::ShaderProgram progVF(m_context.getRenderContext(), glu::makeVtxFragSources(vtx.c_str(), frag.c_str()));
2211 
2212 		gl.useProgram(progVF.getProgram());
2213 		// Ouput green in the fragment shader
2214 		gl.uniform4f(gl.getUniformLocation(progVF.getProgram(), "u_color"), 0.0f, 1.0f, 0.0f, 1.0f);
2215 
2216 		// Create and bind a pipeline with a different fragment shader
2217 		gl.genProgramPipelines(1, &pipeline);
2218 		// Use a different uniform name in another fragment shader
2219 		frag2	  = frag;
2220 		size_t pos = 0;
2221 		while ((pos = frag2.find("u_color", pos)) != std::string::npos)
2222 		{
2223 			frag2.replace(pos, 7, "u_clrPB");
2224 			pos += 7;
2225 		}
2226 
2227 		srcStrings[0] = vtx.c_str();
2228 		programA	  = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings);
2229 		if (!checkCSProg(gl, programA))
2230 		{
2231 			TCU_FAIL("CreateShaderProgramv failed for vertex shader");
2232 		}
2233 		srcStrings[0] = frag2.c_str();
2234 		programB	  = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings);
2235 		if (!checkCSProg(gl, programB))
2236 		{
2237 			TCU_FAIL("CreateShaderProgramv failed for fragment shader");
2238 		}
2239 		// Program B outputs blue.
2240 		gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 0.0f, 0.0f, 1.0f, 1.0f);
2241 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2242 		gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2243 		gl.bindProgramPipeline(pipeline);
2244 
2245 		static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
2246 		const float			  position[]	= { -1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f,  1.0f,
2247 								   +1.0f, -1.0f, 0.0f,  1.0f, +1.0f, +1.0f, -1.0f, 1.0f };
2248 
2249 		// Draw a quad with glu::draw
2250 		glu::VertexArrayBinding posArray = glu::va::Float("a_position", 4, 4, 0, &position[0]);
2251 		glu::draw(m_context.getRenderContext(), progVF.getProgram(), 1, &posArray,
2252 				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
2253 		GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction glu::draw failure");
2254 
2255 		glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2256 
2257 		// useProgram takes precedence and the buffer should be green
2258 		if (!checkSurface(renderedFrame, tcu::RGBA::green()))
2259 		{
2260 			TCU_FAIL("StateInteraction failed; surface should be green");
2261 		}
2262 
2263 		// The position attribute locations may be different.
2264 		int posLoc = gl.getAttribLocation(progVF.getProgram(), "a_position");
2265 
2266 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
2267 			gl.disableVertexAttribArray(posLoc);
2268 
2269 		/* Set up a vertex array object */
2270 		gl.genVertexArrays(1, &vao);
2271 		gl.bindVertexArray(vao);
2272 
2273 		gl.genBuffers(1, &indexBuf);
2274 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
2275 		gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW);
2276 
2277 		gl.genBuffers(1, &vertexBuf);
2278 		gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuf);
2279 		gl.bufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW);
2280 
2281 		posLoc = gl.getAttribLocation(programA, "a_position");
2282 		gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
2283 		gl.enableVertexAttribArray(posLoc);
2284 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
2285 
2286 		GLU_EXPECT_NO_ERROR(gl.getError(), "VAO setup failure");
2287 
2288 		// bindProgramPipeline without a program installed by useProgram
2289 		// Rerender the quad.  Don't use glu::draw because it takes the
2290 		// program as a parameter and sets state.
2291 		gl.useProgram(0);
2292 		gl.bindProgramPipeline(pipeline);
2293 
2294 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2295 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2296 
2297 		glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2298 
2299 		// bindProgramPipeline will render blue
2300 		if (!checkSurface(renderedFrame, tcu::RGBA::blue()))
2301 		{
2302 			TCU_FAIL("StateInteraction failed; surface should be blue");
2303 		}
2304 
2305 		// Test rendering with no program bound.  Rendering is undefined
2306 		// but shouldn't produce an error.
2307 		gl.useProgram(0);
2308 		gl.bindProgramPipeline(0);
2309 
2310 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2311 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2312 
2313 		// Render call with missing pipeline stages should not generate an error
2314 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, 0);
2315 		gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2316 		gl.bindProgramPipeline(pipeline);
2317 
2318 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2319 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2320 
2321 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2322 		gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, 0);
2323 
2324 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2325 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2326 
2327 		// Missing program for fragment shader
2328 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, programA);
2329 
2330 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2331 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2332 
2333 		// Separable program with both vertex and fragment shaders attached to only one stage
2334 
2335 		gl.programParameteri(progVF.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
2336 		gl.linkProgram(progVF.getProgram());
2337 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, progVF.getProgram());
2338 
2339 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2340 		err = gl.getError();
2341 		if (err != GL_INVALID_OPERATION)
2342 		{
2343 			TCU_FAIL("DrawElements failed");
2344 		}
2345 
2346 		gl.validateProgramPipeline(pipeline);
2347 		glw::GLint value;
2348 		gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint*)&value);
2349 		if (value != 0)
2350 		{
2351 			TCU_FAIL("Program pipeline validation failed");
2352 		}
2353 
2354 		// attached to just the fragment shader
2355 		// Call validateProgramPipeline before rendering this time
2356 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, 0);
2357 		gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, progVF.getProgram());
2358 
2359 		gl.validateProgramPipeline(pipeline);
2360 		gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint*)&value);
2361 		if (value != 0)
2362 		{
2363 			TCU_FAIL("Program pipeline validation failed");
2364 		}
2365 
2366 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2367 		err = gl.getError();
2368 		if (err != GL_INVALID_OPERATION)
2369 		{
2370 			TCU_FAIL("DrawElements failed");
2371 		}
2372 
2373 		// Program deletion
2374 		gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2375 		gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2376 
2377 		// Program B renders red this time
2378 		gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 1.0f, 0.0f, 0.0f, 1.0f);
2379 
2380 		gl.deleteProgram(programB);
2381 
2382 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2383 		glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2384 
2385 		// expect red
2386 		if (!checkSurface(renderedFrame, tcu::RGBA::red()))
2387 		{
2388 			TCU_FAIL("StateInteraction failed; surface should be red");
2389 		}
2390 
2391 		// Attach new shader
2392 		srcStrings[0] = frag2.c_str();
2393 		programB	  = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings);
2394 		if (!checkCSProg(gl, programB))
2395 		{
2396 			TCU_FAIL("CreateShaderProgramv failed for fragment shader");
2397 		}
2398 		// Render green
2399 		gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 0.0f, 1.0f, 0.0f, 1.0f);
2400 		gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2401 
2402 		// new shader
2403 		glw::GLuint vshader = gl.createShader(GL_FRAGMENT_SHADER);
2404 		srcStrings[0]		= frag.c_str(); // First frag shader with u_color uniform
2405 		gl.shaderSource(vshader, 1, srcStrings, NULL);
2406 		gl.compileShader(vshader);
2407 		gl.getShaderiv(vshader, GL_COMPILE_STATUS, &value);
2408 		DE_ASSERT(value == GL_TRUE);
2409 		gl.attachShader(programB, vshader);
2410 
2411 		// changing shader shouldn't affect link_status
2412 		gl.getProgramiv(programB, GL_LINK_STATUS, &value);
2413 		if (value != 1)
2414 		{
2415 			TCU_FAIL("Shader attachment shouldn't affect link status");
2416 		}
2417 
2418 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2419 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2420 
2421 		glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2422 
2423 		// expect green
2424 		if (!checkSurface(renderedFrame, tcu::RGBA::green()))
2425 		{
2426 			TCU_FAIL("StateInteraction failed; surface should be green");
2427 		}
2428 
2429 		// Negative Case: Unsuccessfully linked program should not affect current program
2430 
2431 		// Render white
2432 		gl.programUniform4f(programB, gl.getUniformLocation(programB, "u_clrPB"), 1.0f, 1.0f, 1.0f, 1.0f);
2433 		std::string noMain = frag;
2434 		pos				   = noMain.find("main", 0);
2435 		noMain.replace(pos, 4, "niaM");
2436 
2437 		srcStrings[0] = noMain.c_str();
2438 		gl.shaderSource(vshader, 1, srcStrings, NULL);
2439 		gl.compileShader(vshader);
2440 		gl.getShaderiv(vshader, GL_COMPILE_STATUS, &value);
2441 		gl.attachShader(programB, vshader);
2442 		gl.linkProgram(programB);
2443 		err = gl.getError();
2444 
2445 		// link_status should be false
2446 		gl.getProgramiv(programB, GL_LINK_STATUS, &value);
2447 		if (value != 0)
2448 		{
2449 			TCU_FAIL("StateInteraction failed; link failure");
2450 		}
2451 
2452 		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2453 
2454 		glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2455 
2456 		// expect white
2457 		if (!checkSurface(renderedFrame, tcu::RGBA::white()))
2458 		{
2459 			TCU_FAIL("StateInteraction failed; surface should be white");
2460 		}
2461 
2462 		gl.deleteProgram(programA);
2463 		gl.deleteProgram(programB);
2464 
2465 		// Shader interface matching inputs/outputs
2466 
2467 		int maxVars = 6; // generate code supports 6 variables
2468 		for (int numInputs = 0; numInputs < maxVars; numInputs++)
2469 		{
2470 			for (int numOutputs = 0; numOutputs < maxVars; numOutputs++)
2471 			{
2472 
2473 				generateVarLinkVertexShaderSrc(vtx, m_glslVersion, numOutputs);
2474 				generateVarLinkFragmentShaderSrc(frag, m_glslVersion, numInputs);
2475 
2476 				srcStrings[0] = vtx.c_str();
2477 				programA	  = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings);
2478 				if (!checkCSProg(gl, programA))
2479 				{
2480 					TCU_FAIL("CreateShaderProgramv failed for vertex shader");
2481 				}
2482 
2483 				srcStrings[0] = frag.c_str();
2484 				programB	  = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings);
2485 				if (!checkCSProg(gl, programB))
2486 				{
2487 					TCU_FAIL("CreateShaderProgramv failed for fragment shader");
2488 				}
2489 
2490 				gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2491 				gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2492 				GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages failure");
2493 
2494 				gl.validateProgramPipeline(pipeline);
2495 				gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint*)&value);
2496 
2497 				// Matched input and output variables should render
2498 				if (numInputs == numOutputs)
2499 				{
2500 					if (value != 1)
2501 					{
2502 						log << TestLog::Message << "Matched input and output variables should validate successfully.\n"
2503 							<< "Vertex Shader:\n"
2504 							<< vtx << "Fragment Shader:\n"
2505 							<< frag << TestLog::EndMessage;
2506 						TCU_FAIL("StateInteraction failed");
2507 					}
2508 					gl.clear(GL_COLOR_BUFFER_BIT);
2509 					// white
2510 					gl.programUniform4f(programA, gl.getUniformLocation(programA, "u_color"), 1.0f, 1.0f, 1.0f, 1.0f);
2511 					gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2512 					GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2513 
2514 					glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2515 
2516 					// expect white
2517 					if (!checkSurface(renderedFrame, tcu::RGBA::white()))
2518 					{
2519 						TCU_FAIL("StateInteraction failed; surface should be white");
2520 					}
2521 				}
2522 				else
2523 				{
2524 					// Mismatched input and output variables
2525 					// For OpenGL ES contexts, this should cause a validation failure
2526 					// For OpenGL contexts, validation should succeed.
2527 					if (glu::isContextTypeES(m_context.getRenderContext().getType()) != (value == 0))
2528 					{
2529 						log << TestLog::Message << "Mismatched input and output variables; validation should "
2530 							<< (glu::isContextTypeES(m_context.getRenderContext().getType()) ? "fail.\n" : "succeed.\n")
2531 							<< "Vertex Shader:\n"
2532 							<< vtx << "Fragment Shader:\n"
2533 							<< frag << TestLog::EndMessage;
2534 						TCU_FAIL("StateInteraction failed");
2535 					}
2536 				}
2537 
2538 				gl.deleteProgram(programA);
2539 				gl.deleteProgram(programB);
2540 			}
2541 		}
2542 
2543 		gl.bindProgramPipeline(0);
2544 		gl.bindVertexArray(0);
2545 		gl.deleteProgramPipelines(1, &pipeline);
2546 		gl.deleteShader(vshader);
2547 		gl.deleteVertexArrays(1, &vao);
2548 		gl.deleteBuffers(1, &indexBuf);
2549 		gl.deleteBuffers(1, &vertexBuf);
2550 
2551 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2552 		return STOP;
2553 	}
2554 
2555 private:
2556 	glu::GLSLVersion m_glslVersion;
2557 };
2558 
2559 // Testcase for interface qualifiers matching
2560 class InterfaceMatchingCase : public TestCase
2561 {
2562 public:
2563 	enum TestType
2564 	{
2565 		DEFAULT_PRECISION,
2566 		SET_DEFAULT_PRECISION,
2567 		SET_PRECISION
2568 	};
2569 
getTestTypeName(TestType testType)2570 	std::string getTestTypeName(TestType testType)
2571 	{
2572 		switch (testType)
2573 		{
2574 		case DEFAULT_PRECISION:
2575 			return "use predeclared precision";
2576 		case SET_DEFAULT_PRECISION:
2577 			return "set default precision";
2578 		case SET_PRECISION:
2579 			return "explicit precision";
2580 		}
2581 		return "";
2582 	}
2583 
InterfaceMatchingCase(Context & context,const char * name,glu::GLSLVersion glslVersion)2584 	InterfaceMatchingCase(Context& context, const char* name, glu::GLSLVersion glslVersion)
2585 		: TestCase(context, name, "matching precision qualifiers between stages"), m_glslVersion(glslVersion)
2586 	{
2587 	}
2588 
~InterfaceMatchingCase(void)2589 	~InterfaceMatchingCase(void)
2590 	{
2591 	}
2592 
getDefaultFragmentPrecision()2593 	string getDefaultFragmentPrecision()
2594 	{
2595 		return "";
2596 	}
2597 
2598 	// Generate a vertex shader for variable input/output precision testing
2599 	virtual void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion,
2600 												const string& precision, TestType testMode) = 0;
2601 
2602 	// Generate a fragment shader for variable input/output precision testing
2603 	virtual void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion,
2604 												  const string& precision, TestType testMode) = 0;
2605 
2606 	// Verify the surface is filled with the expected color
checkSurface(tcu::Surface surface,tcu::RGBA expectedColor)2607 	bool checkSurface(tcu::Surface surface, tcu::RGBA expectedColor)
2608 	{
2609 		int numFailedPixels = 0;
2610 		for (int y = 0; y < surface.getHeight(); y++)
2611 		{
2612 			for (int x = 0; x < surface.getWidth(); x++)
2613 			{
2614 				if (surface.getPixel(x, y) != expectedColor)
2615 					numFailedPixels += 1;
2616 			}
2617 		}
2618 		return (numFailedPixels == 0);
2619 	}
2620 
2621 	// Log the program info log
logProgramInfoLog(const glw::Functions & gl,glw::GLuint program)2622 	void logProgramInfoLog(const glw::Functions& gl, glw::GLuint program)
2623 	{
2624 		TestLog&	 log	 = m_testCtx.getLog();
2625 		glw::GLint   value   = 0;
2626 		glw::GLsizei bufSize = 0;
2627 		glw::GLsizei length  = 0;
2628 
2629 		gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &value);
2630 		std::vector<char> infoLogBuf(value + 1);
2631 
2632 		gl.getProgramInfoLog(program, bufSize, &length, &infoLogBuf[0]);
2633 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog failed");
2634 
2635 		log << TestLog::Message << "Program Log:\n" << &infoLogBuf[0] << TestLog::EndMessage;
2636 	}
2637 
2638 	// Check program validity created with CreateShaderProgram
checkCSProg(const glw::Functions & gl,GLuint program,int expectedLink=GL_TRUE)2639 	bool checkCSProg(const glw::Functions& gl, GLuint program, int expectedLink = GL_TRUE)
2640 	{
2641 		int linked = GL_FALSE;
2642 		if (program != 0)
2643 		{
2644 			gl.getProgramiv(program, GL_LINK_STATUS, &linked);
2645 
2646 			if (expectedLink && !linked)
2647 			{
2648 				logProgramInfoLog(gl, program);
2649 			}
2650 		}
2651 
2652 		return (program != 0) && (linked == expectedLink);
2653 	}
2654 
iterate(void)2655 	IterateResult iterate(void)
2656 	{
2657 		TestLog&				 log		  = m_testCtx.getLog();
2658 		const glw::Functions&	gl			  = m_context.getRenderContext().getFunctions();
2659 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2660 		int						 viewportW	= de::min(16, renderTarget.getWidth());
2661 		int						 viewportH	= de::min(16, renderTarget.getHeight());
2662 		tcu::Surface			 renderedFrame(viewportW, viewportH);
2663 
2664 		glw::GLuint programA, programB;
2665 		glw::GLuint vao, vertexBuf, indexBuf;
2666 		std::string vtx;
2667 		std::string frag, frag2;
2668 		glw::GLuint pipeline;
2669 		const char* srcStrings[1];
2670 		glw::GLuint value;
2671 
2672 		gl.viewport(0, 0, viewportW, viewportH);
2673 		gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2674 		gl.clear(GL_COLOR_BUFFER_BIT);
2675 
2676 		static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
2677 		const float			  position[]	= { -1.0f, -1.0f, +1.0f, 1.0f, -1.0f, +1.0f, 0.0f,  1.0f,
2678 								   +1.0f, -1.0f, 0.0f,  1.0f, +1.0f, +1.0f, -1.0f, 1.0f };
2679 
2680 		/* Set up a vertex array object */
2681 		gl.genVertexArrays(1, &vao);
2682 		gl.bindVertexArray(vao);
2683 
2684 		gl.genBuffers(1, &indexBuf);
2685 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
2686 		gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW);
2687 
2688 		gl.genBuffers(1, &vertexBuf);
2689 		gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuf);
2690 		gl.bufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW);
2691 
2692 		/* Set up shader pipeline */
2693 		gl.genProgramPipelines(1, &pipeline);
2694 		gl.bindProgramPipeline(pipeline);
2695 
2696 		struct PrecisionTests
2697 		{
2698 			TestType	testType;
2699 			std::string precision;
2700 		};
2701 
2702 		PrecisionTests vertexPrecisionTests[] = {
2703 			{ DEFAULT_PRECISION, "highp" },	{ SET_DEFAULT_PRECISION, "highp" }, { SET_DEFAULT_PRECISION, "mediump" },
2704 			{ SET_DEFAULT_PRECISION, "lowp" }, { SET_PRECISION, "highp" },		   { SET_PRECISION, "mediump" },
2705 			{ SET_PRECISION, "lowp" }
2706 		};
2707 
2708 		PrecisionTests fragmentPrecisionTests[] = { { DEFAULT_PRECISION, getDefaultFragmentPrecision() },
2709 													{ SET_DEFAULT_PRECISION, "highp" },
2710 													{ SET_DEFAULT_PRECISION, "mediump" },
2711 													{ SET_DEFAULT_PRECISION, "lowp" },
2712 													{ SET_PRECISION, "highp" },
2713 													{ SET_PRECISION, "mediump" },
2714 													{ SET_PRECISION, "lowp" } };
2715 
2716 		// Shader interface matching inputs/outputs precision
2717 		int maxTests = 7;
2718 		for (int vertexTestIteration = 0; vertexTestIteration < maxTests; vertexTestIteration++)
2719 		{
2720 			std::string vertexPrecision = vertexPrecisionTests[vertexTestIteration].precision;
2721 			TestType	vertexTestType  = vertexPrecisionTests[vertexTestIteration].testType;
2722 			for (int fragmentTestIteration = 0; fragmentTestIteration < maxTests; fragmentTestIteration++)
2723 			{
2724 				std::string fragmentPrecision = fragmentPrecisionTests[fragmentTestIteration].precision;
2725 				TestType	fragmentTestType  = fragmentPrecisionTests[fragmentTestIteration].testType;
2726 				if (fragmentPrecision.empty())
2727 					continue;
2728 
2729 				log << TestLog::Message << "vertex shader precision: " << vertexPrecision
2730 					<< ", shader test mode: " << getTestTypeName(vertexTestType) << TestLog::EndMessage;
2731 
2732 				log << TestLog::Message << "fragment shader precision: " << fragmentPrecision
2733 					<< ", shader test mode: " << getTestTypeName(fragmentTestType) << TestLog::EndMessage;
2734 
2735 				generateVarLinkVertexShaderSrc(vtx, m_glslVersion, vertexPrecision, vertexTestType);
2736 				generateVarLinkFragmentShaderSrc(frag, m_glslVersion, fragmentPrecision, fragmentTestType);
2737 
2738 				srcStrings[0] = vtx.c_str();
2739 				programA	  = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, srcStrings);
2740 				if (!checkCSProg(gl, programA))
2741 				{
2742 					TCU_FAIL("CreateShaderProgramv failed for vertex shader");
2743 				}
2744 				srcStrings[0] = frag.c_str();
2745 				programB	  = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, srcStrings);
2746 				if (!checkCSProg(gl, programB))
2747 				{
2748 					TCU_FAIL("CreateShaderProgramv failed for fragment shader");
2749 				}
2750 
2751 				gl.useProgramStages(pipeline, GL_VERTEX_SHADER_BIT, programA);
2752 				gl.useProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, programB);
2753 				GLU_EXPECT_NO_ERROR(gl.getError(), "InterfaceMatching failure");
2754 
2755 				// Mismatched input and output qualifiers
2756 				// For OpenGL ES contexts, this should result in a validation failure.
2757 				// For OpenGL contexts, validation should succeed.
2758 				gl.validateProgramPipeline(pipeline);
2759 				gl.getProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, (glw::GLint*)&value);
2760 				int precisionCompareResult = fragmentPrecision.compare(vertexPrecision);
2761 				if (glu::isContextTypeES(m_context.getRenderContext().getType()) && (precisionCompareResult != 0))
2762 				{
2763 					// precision mismatch
2764 					if (value != GL_FALSE)
2765 					{
2766 						log.startShaderProgram(
2767 							false, "Precision mismatch, pipeline validation status GL_TRUE expected GL_FALSE");
2768 						log.writeShader(QP_SHADER_TYPE_VERTEX, vtx.c_str(), true, "");
2769 						log.writeShader(QP_SHADER_TYPE_FRAGMENT, frag.c_str(), true, "");
2770 						log.endShaderProgram();
2771 						TCU_FAIL("InterfaceMatchingCase failed");
2772 					}
2773 					else
2774 					{
2775 						log << TestLog::Message << "Precision mismatch, Pipeline validation status GL_FALSE -> OK"
2776 							<< TestLog::EndMessage;
2777 					}
2778 				}
2779 				else
2780 				{
2781 					if (value != GL_TRUE)
2782 					{
2783 						std::stringstream str;
2784 						str << "Precision " << (precisionCompareResult ? "mismatch" : "matches")
2785 							<< ", pipeline validation status GL_FALSE expected GL_TRUE";
2786 
2787 						log.startShaderProgram(false, str.str().c_str());
2788 						log.writeShader(QP_SHADER_TYPE_VERTEX, vtx.c_str(), true, "");
2789 						log.writeShader(QP_SHADER_TYPE_FRAGMENT, frag.c_str(), true, "");
2790 						log.endShaderProgram();
2791 						TCU_FAIL("InterfaceMatchingCase failed");
2792 					}
2793 					else
2794 					{
2795 						log << TestLog::Message << "Precision " << (precisionCompareResult ? "mismatch" : "matches")
2796 							<< ", pipeline validation status GL_TRUE -> OK" << TestLog::EndMessage;
2797 						// precision matches
2798 						gl.clear(GL_COLOR_BUFFER_BIT);
2799 						// white
2800 						int posLoc = gl.getAttribLocation(programA, "a_position");
2801 						gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
2802 						gl.enableVertexAttribArray(posLoc);
2803 						gl.programUniform4f(programA, gl.getUniformLocation(programA, "u_color"), 1.0f, 1.0f, 1.0f,
2804 											1.0f);
2805 						GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction failure, set uniform value");
2806 						gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2807 						GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements failure");
2808 						gl.disableVertexAttribArray(posLoc);
2809 
2810 						glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2811 
2812 						// expect white
2813 						if (!checkSurface(renderedFrame, tcu::RGBA::white()))
2814 						{
2815 							TCU_FAIL("InterfaceMatchingCase failed; surface should be white");
2816 						}
2817 					}
2818 				}
2819 
2820 				// validate non separable program
2821 
2822 				glu::ShaderProgram progVF(m_context.getRenderContext(),
2823 										  glu::makeVtxFragSources(vtx.c_str(), frag.c_str()));
2824 
2825 				gl.useProgram(progVF.getProgram());
2826 				gl.uniform4f(gl.getUniformLocation(progVF.getProgram(), "u_color"), 1.0f, 1.0f, 1.0f, 1.0f);
2827 				if (!progVF.getProgramInfo().linkOk)
2828 				{
2829 					log << progVF;
2830 					log << TestLog::Message << "Non separable program link status GL_FALSE expected GL_TRUE"
2831 						<< TestLog::EndMessage;
2832 					TCU_FAIL("InterfaceMatchingCase failed, non separable program should link");
2833 				}
2834 
2835 				int posLoc = gl.getAttribLocation(progVF.getProgram(), "a_position");
2836 				gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
2837 				gl.enableVertexAttribArray(posLoc);
2838 				gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(quadIndices), GL_UNSIGNED_SHORT, NULL);
2839 				gl.disableVertexAttribArray(posLoc);
2840 
2841 				GLU_EXPECT_NO_ERROR(gl.getError(), "StateInteraction failure, non separable program draw call");
2842 				glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
2843 				// expect white
2844 				if (!checkSurface(renderedFrame, tcu::RGBA::white()))
2845 				{
2846 					TCU_FAIL("InterfaceMatchingCase failed, non separable program, unexpected color found");
2847 				}
2848 
2849 				gl.deleteProgram(programA);
2850 				gl.deleteProgram(programB);
2851 				gl.useProgram(0);
2852 			}
2853 		}
2854 		gl.bindVertexArray(0);
2855 		gl.deleteVertexArrays(1, &vao);
2856 		gl.deleteBuffers(1, &indexBuf);
2857 		gl.deleteBuffers(1, &vertexBuf);
2858 		gl.bindProgramPipeline(0);
2859 		gl.deleteProgramPipelines(1, &pipeline);
2860 
2861 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2862 		return STOP;
2863 	}
2864 
2865 protected:
2866 	glu::GLSLVersion m_glslVersion;
2867 };
2868 
2869 class InterfaceMatchingCaseFloat : public InterfaceMatchingCase
2870 {
2871 public:
InterfaceMatchingCaseFloat(Context & context,const char * name,glu::GLSLVersion glslVersion)2872 	InterfaceMatchingCaseFloat(Context& context, const char* name, glu::GLSLVersion glslVersion)
2873 		: InterfaceMatchingCase(context, name, glslVersion)
2874 	{
2875 	}
2876 
generateVarLinkVertexShaderSrc(std::string & outVtxSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)2877 	void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, const string& precision,
2878 										TestType testMode)
2879 	{
2880 		std::ostringstream vtxSrc;
2881 		vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2882 		if (glslVersion >= glu::GLSL_VERSION_410)
2883 		{
2884 			vtxSrc << "out gl_PerVertex {\n"
2885 					  "  vec4 gl_Position;\n"
2886 					  "};\n";
2887 		}
2888 		vtxSrc << "in highp vec4 a_position;\n";
2889 		vtxSrc << "uniform highp vec4 u_color;\n";
2890 		switch (testMode)
2891 		{
2892 		case SET_DEFAULT_PRECISION:
2893 			vtxSrc << "precision " << precision << " float;\n";
2894 		// Fallthrough
2895 		case DEFAULT_PRECISION:
2896 			vtxSrc << "out float var;\n";
2897 			break;
2898 		case SET_PRECISION:
2899 			vtxSrc << "out " << precision << " float var;\n";
2900 			break;
2901 		}
2902 		vtxSrc << "void main (void)\n";
2903 		vtxSrc << "{\n";
2904 		vtxSrc << "   gl_Position = a_position;\n";
2905 		vtxSrc << "   var = u_color.r;\n";
2906 		vtxSrc << "}\n";
2907 		outVtxSrc = vtxSrc.str();
2908 	}
2909 
generateVarLinkFragmentShaderSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)2910 	void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion,
2911 										  const string& precision, TestType testMode)
2912 	{
2913 		std::ostringstream fragSrc;
2914 		fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2915 		switch (testMode)
2916 		{
2917 		case SET_DEFAULT_PRECISION:
2918 			fragSrc << "precision " << precision << " float;\n";
2919 		// Fallthrough
2920 		case DEFAULT_PRECISION:
2921 			fragSrc << "in float var;\n";
2922 			break;
2923 		case SET_PRECISION:
2924 			fragSrc << "in " << precision << " float var;\n";
2925 			break;
2926 		}
2927 		fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
2928 		fragSrc << "void main (void)\n";
2929 		fragSrc << "{\n";
2930 		fragSrc << "    o_color = vec4(var);\n";
2931 		fragSrc << "}\n";
2932 		outFragSrc = fragSrc.str();
2933 	}
2934 };
2935 
2936 class InterfaceMatchingCaseInt : public InterfaceMatchingCase
2937 {
2938 public:
InterfaceMatchingCaseInt(Context & context,const char * name,glu::GLSLVersion glslVersion)2939 	InterfaceMatchingCaseInt(Context& context, const char* name, glu::GLSLVersion glslVersion)
2940 		: InterfaceMatchingCase(context, name, glslVersion)
2941 	{
2942 	}
2943 
getDefaultFragmentPrecision()2944 	std::string getDefaultFragmentPrecision()
2945 	{
2946 		return "mediump";
2947 	}
2948 
generateVarLinkVertexShaderSrc(std::string & outVtxSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)2949 	void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, const string& precision,
2950 										TestType testMode)
2951 	{
2952 		std::ostringstream vtxSrc;
2953 		vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2954 		if (glslVersion >= glu::GLSL_VERSION_410)
2955 		{
2956 			vtxSrc << "out gl_PerVertex {\n"
2957 					  "  vec4 gl_Position;\n"
2958 					  "};\n";
2959 		}
2960 		vtxSrc << "in highp vec4 a_position;\n";
2961 		vtxSrc << "uniform highp vec4 u_color;\n";
2962 		switch (testMode)
2963 		{
2964 		case SET_DEFAULT_PRECISION:
2965 			vtxSrc << "precision " << precision << " int;\n";
2966 		// Fallthrough
2967 		case DEFAULT_PRECISION:
2968 			vtxSrc << "flat out int var;\n";
2969 			break;
2970 		case SET_PRECISION:
2971 			vtxSrc << "flat out " << precision << " int var;\n";
2972 			break;
2973 		}
2974 		vtxSrc << "void main (void)\n";
2975 		vtxSrc << "{\n";
2976 		vtxSrc << "   gl_Position = a_position;\n";
2977 		vtxSrc << "   var = int(u_color.r);\n";
2978 		vtxSrc << "}\n";
2979 		outVtxSrc = vtxSrc.str();
2980 	}
2981 
generateVarLinkFragmentShaderSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)2982 	void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion,
2983 										  const string& precision, TestType testMode)
2984 	{
2985 		std::ostringstream fragSrc;
2986 		fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
2987 		switch (testMode)
2988 		{
2989 		case SET_DEFAULT_PRECISION:
2990 			fragSrc << "precision " << precision << " int;\n";
2991 		// Fallthrough
2992 		case DEFAULT_PRECISION:
2993 			fragSrc << "flat in int var;\n";
2994 			break;
2995 		case SET_PRECISION:
2996 			fragSrc << "flat in " << precision << " int var;\n";
2997 			break;
2998 		}
2999 		fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
3000 		fragSrc << "void main (void)\n";
3001 		fragSrc << "{\n";
3002 		fragSrc << "    o_color = vec4(var);\n";
3003 		fragSrc << "}\n";
3004 		outFragSrc = fragSrc.str();
3005 	}
3006 };
3007 
3008 class InterfaceMatchingCaseUInt : public InterfaceMatchingCase
3009 {
3010 public:
InterfaceMatchingCaseUInt(Context & context,const char * name,glu::GLSLVersion glslVersion)3011 	InterfaceMatchingCaseUInt(Context& context, const char* name, glu::GLSLVersion glslVersion)
3012 		: InterfaceMatchingCase(context, name, glslVersion)
3013 	{
3014 	}
3015 
getDefaultFragmentPrecision()3016 	std::string getDefaultFragmentPrecision()
3017 	{
3018 		return "mediump";
3019 	}
3020 
generateVarLinkVertexShaderSrc(std::string & outVtxSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)3021 	void generateVarLinkVertexShaderSrc(std::string& outVtxSrc, glu::GLSLVersion glslVersion, const string& precision,
3022 										TestType testMode)
3023 	{
3024 		std::ostringstream vtxSrc;
3025 		vtxSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
3026 		if (glslVersion >= glu::GLSL_VERSION_410)
3027 		{
3028 			vtxSrc << "out gl_PerVertex {\n"
3029 					  "  vec4 gl_Position;\n"
3030 					  "};\n";
3031 		}
3032 		vtxSrc << "in highp vec4 a_position;\n";
3033 		vtxSrc << "uniform highp vec4 u_color;\n";
3034 		switch (testMode)
3035 		{
3036 		case SET_DEFAULT_PRECISION:
3037 			vtxSrc << "precision " << precision << " int;\n";
3038 		// Fallthrough
3039 		case DEFAULT_PRECISION:
3040 			vtxSrc << "flat out uint var;\n";
3041 			break;
3042 		case SET_PRECISION:
3043 			vtxSrc << "flat out " << precision << " uint var;\n";
3044 			break;
3045 		}
3046 		vtxSrc << "void main (void)\n";
3047 		vtxSrc << "{\n";
3048 		vtxSrc << "   gl_Position = a_position;\n";
3049 		vtxSrc << "   var = uint(u_color.r);\n";
3050 		vtxSrc << "}\n";
3051 		outVtxSrc = vtxSrc.str();
3052 	}
3053 
generateVarLinkFragmentShaderSrc(std::string & outFragSrc,glu::GLSLVersion glslVersion,const string & precision,TestType testMode)3054 	void generateVarLinkFragmentShaderSrc(std::string& outFragSrc, glu::GLSLVersion glslVersion,
3055 										  const string& precision, TestType testMode)
3056 	{
3057 		std::ostringstream fragSrc;
3058 		fragSrc << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
3059 		switch (testMode)
3060 		{
3061 		case SET_DEFAULT_PRECISION:
3062 			fragSrc << "precision " << precision << " int;\n";
3063 		// Fallthrough
3064 		case DEFAULT_PRECISION:
3065 			fragSrc << "flat in uint var;\n";
3066 			break;
3067 		case SET_PRECISION:
3068 			fragSrc << "flat in " << precision << " uint var;\n";
3069 			break;
3070 		}
3071 		fragSrc << "layout(location = 0) out mediump vec4 o_color;\n";
3072 		fragSrc << "void main (void)\n";
3073 		fragSrc << "{\n";
3074 		fragSrc << "    o_color = vec4(var);\n";
3075 		fragSrc << "}\n";
3076 		outFragSrc = fragSrc.str();
3077 	}
3078 };
3079 
SeparateShaderObjsTests(Context & context,glu::GLSLVersion glslVersion)3080 SeparateShaderObjsTests::SeparateShaderObjsTests(Context& context, glu::GLSLVersion glslVersion)
3081 	: TestCaseGroup(context, "sepshaderobjs", "separate_shader_object tests"), m_glslVersion(glslVersion)
3082 {
3083 	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440);
3084 }
3085 
~SeparateShaderObjsTests(void)3086 SeparateShaderObjsTests::~SeparateShaderObjsTests(void)
3087 {
3088 }
3089 
init(void)3090 void SeparateShaderObjsTests::init(void)
3091 {
3092 
3093 	// API validation for CreateShaderProgram
3094 	addChild(new CreateShadProgCase(m_context, "CreateShadProgApi", "createShaderProgram API", m_glslVersion));
3095 	// API validation for UseProgramStages
3096 	addChild(new UseProgStagesCase(m_context, "UseProgStagesApi", "useProgramStages API", m_glslVersion));
3097 	// API validation for pipeline related functions
3098 	addChild(new PipelineApiCase(m_context, "PipelineApi", "Pipeline API", m_glslVersion));
3099 	// API validation for variations of ProgramUniform
3100 	addChild(new ProgramUniformCase(m_context, "ProgUniformAPI", "ProgramUniform API", m_glslVersion));
3101 	// State interactions
3102 	addChild(new StateInteractionCase(m_context, "StateInteraction", "SSO State Interactions", m_glslVersion));
3103 	// input / output precision matching
3104 	addChild(new InterfaceMatchingCaseFloat(m_context, "InterfacePrecisionMatchingFloat", m_glslVersion));
3105 	addChild(new InterfaceMatchingCaseInt(m_context, "InterfacePrecisionMatchingInt", m_glslVersion));
3106 	addChild(new InterfaceMatchingCaseUInt(m_context, "InterfacePrecisionMatchingUInt", m_glslVersion));
3107 }
3108 
3109 } // glcts
3110