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