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