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