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