1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.1 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
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 glProgramUniform*() tests.
22e5c31af7Sopenharmony_ci *
23e5c31af7Sopenharmony_ci * \todo [2013-02-26 nuutti] Much duplication between ES2&3 uniform api
24e5c31af7Sopenharmony_ci *							 tests and this. Utilities to glshared?
25e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_ci#include "es31fProgramUniformTests.hpp"
28e5c31af7Sopenharmony_ci#include "gluCallLogWrapper.hpp"
29e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
30e5c31af7Sopenharmony_ci#include "gluVarType.hpp"
31e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
32e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp"
33e5c31af7Sopenharmony_ci#include "gluTexture.hpp"
34e5c31af7Sopenharmony_ci#include "gluDrawUtil.hpp"
35e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
36e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
37e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
38e5c31af7Sopenharmony_ci#include "tcuCommandLine.hpp"
39e5c31af7Sopenharmony_ci#include "deRandom.hpp"
40e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
41e5c31af7Sopenharmony_ci#include "deString.h"
42e5c31af7Sopenharmony_ci#include "deSharedPtr.hpp"
43e5c31af7Sopenharmony_ci#include "deMemory.h"
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
46e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ci#include <set>
49e5c31af7Sopenharmony_ci#include <cstring>
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_ciusing namespace glw;
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_cinamespace deqp
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_cinamespace gles31
56e5c31af7Sopenharmony_ci{
57e5c31af7Sopenharmony_cinamespace Functional
58e5c31af7Sopenharmony_ci{
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ciusing std::vector;
61e5c31af7Sopenharmony_ciusing std::string;
62e5c31af7Sopenharmony_ciusing tcu::TestLog;
63e5c31af7Sopenharmony_ciusing tcu::ScopedLogSection;
64e5c31af7Sopenharmony_ciusing glu::ShaderProgram;
65e5c31af7Sopenharmony_ciusing glu::StructType;
66e5c31af7Sopenharmony_ciusing de::Random;
67e5c31af7Sopenharmony_ciusing de::SharedPtr;
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_citypedef bool (* dataTypePredicate)(glu::DataType);
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_cienum
72e5c31af7Sopenharmony_ci{
73e5c31af7Sopenharmony_ci	MAX_RENDER_WIDTH			= 32,
74e5c31af7Sopenharmony_ci	MAX_RENDER_HEIGHT			= 32,
75e5c31af7Sopenharmony_ci	MAX_NUM_SAMPLER_UNIFORMS	= 16
76e5c31af7Sopenharmony_ci};
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_cistatic const glu::DataType s_testDataTypes[] =
79e5c31af7Sopenharmony_ci{
80e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT,
81e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_VEC2,
82e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_VEC3,
83e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_VEC4,
84e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT2,
85e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT2X3,
86e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT2X4,
87e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT3X2,
88e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT3,
89e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT3X4,
90e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT4X2,
91e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT4X3,
92e5c31af7Sopenharmony_ci	glu::TYPE_FLOAT_MAT4,
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci	glu::TYPE_INT,
95e5c31af7Sopenharmony_ci	glu::TYPE_INT_VEC2,
96e5c31af7Sopenharmony_ci	glu::TYPE_INT_VEC3,
97e5c31af7Sopenharmony_ci	glu::TYPE_INT_VEC4,
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci	glu::TYPE_UINT,
100e5c31af7Sopenharmony_ci	glu::TYPE_UINT_VEC2,
101e5c31af7Sopenharmony_ci	glu::TYPE_UINT_VEC3,
102e5c31af7Sopenharmony_ci	glu::TYPE_UINT_VEC4,
103e5c31af7Sopenharmony_ci
104e5c31af7Sopenharmony_ci	glu::TYPE_BOOL,
105e5c31af7Sopenharmony_ci	glu::TYPE_BOOL_VEC2,
106e5c31af7Sopenharmony_ci	glu::TYPE_BOOL_VEC3,
107e5c31af7Sopenharmony_ci	glu::TYPE_BOOL_VEC4,
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci	glu::TYPE_SAMPLER_2D,
110e5c31af7Sopenharmony_ci	glu::TYPE_SAMPLER_CUBE
111e5c31af7Sopenharmony_ci	// \note We don't test all sampler types here.
112e5c31af7Sopenharmony_ci};
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_cistatic inline int getGLInt (const glw::Functions& funcs, const deUint32 name)
115e5c31af7Sopenharmony_ci{
116e5c31af7Sopenharmony_ci	int val = -1;
117e5c31af7Sopenharmony_ci	funcs.getIntegerv(name, &val);
118e5c31af7Sopenharmony_ci	return val;
119e5c31af7Sopenharmony_ci}
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_cistatic inline tcu::Vec4 vec4FromPtr (const float* const ptr)
122e5c31af7Sopenharmony_ci{
123e5c31af7Sopenharmony_ci	tcu::Vec4 result;
124e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; i++)
125e5c31af7Sopenharmony_ci		result[i] = ptr[i];
126e5c31af7Sopenharmony_ci	return result;
127e5c31af7Sopenharmony_ci}
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_cistatic inline string beforeLast (const string& str, const char c)
130e5c31af7Sopenharmony_ci{
131e5c31af7Sopenharmony_ci	return str.substr(0, str.find_last_of(c));
132e5c31af7Sopenharmony_ci}
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_cistatic inline void fillWithColor (const tcu::PixelBufferAccess& access, const tcu::Vec4& color)
135e5c31af7Sopenharmony_ci{
136e5c31af7Sopenharmony_ci	for (int z = 0; z < access.getDepth(); z++)
137e5c31af7Sopenharmony_ci	for (int y = 0; y < access.getHeight(); y++)
138e5c31af7Sopenharmony_ci	for (int x = 0; x < access.getWidth(); x++)
139e5c31af7Sopenharmony_ci		access.setPixel(color, x, y, z);
140e5c31af7Sopenharmony_ci}
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_cistatic inline int getSamplerNumLookupDimensions (const glu::DataType type)
143e5c31af7Sopenharmony_ci{
144e5c31af7Sopenharmony_ci	switch (type)
145e5c31af7Sopenharmony_ci	{
146e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_2D:
147e5c31af7Sopenharmony_ci		case glu::TYPE_INT_SAMPLER_2D:
148e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_SAMPLER_2D:
149e5c31af7Sopenharmony_ci			return 2;
150e5c31af7Sopenharmony_ci
151e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_3D:
152e5c31af7Sopenharmony_ci		case glu::TYPE_INT_SAMPLER_3D:
153e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_SAMPLER_3D:
154e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_2D_SHADOW:
155e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_2D_ARRAY:
156e5c31af7Sopenharmony_ci		case glu::TYPE_INT_SAMPLER_2D_ARRAY:
157e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
158e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_CUBE:
159e5c31af7Sopenharmony_ci		case glu::TYPE_INT_SAMPLER_CUBE:
160e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_SAMPLER_CUBE:
161e5c31af7Sopenharmony_ci			return 3;
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_CUBE_SHADOW:
164e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
165e5c31af7Sopenharmony_ci			return 4;
166e5c31af7Sopenharmony_ci
167e5c31af7Sopenharmony_ci		default:
168e5c31af7Sopenharmony_ci			DE_ASSERT(false);
169e5c31af7Sopenharmony_ci			return 0;
170e5c31af7Sopenharmony_ci	}
171e5c31af7Sopenharmony_ci}
172e5c31af7Sopenharmony_ci
173e5c31af7Sopenharmony_cistatic inline glu::DataType getSamplerLookupReturnType (const glu::DataType type)
174e5c31af7Sopenharmony_ci{
175e5c31af7Sopenharmony_ci	switch (type)
176e5c31af7Sopenharmony_ci	{
177e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_2D:
178e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_CUBE:
179e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_2D_ARRAY:
180e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_3D:
181e5c31af7Sopenharmony_ci			return glu::TYPE_FLOAT_VEC4;
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_SAMPLER_2D:
184e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_SAMPLER_CUBE:
185e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
186e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_SAMPLER_3D:
187e5c31af7Sopenharmony_ci			return glu::TYPE_UINT_VEC4;
188e5c31af7Sopenharmony_ci
189e5c31af7Sopenharmony_ci		case glu::TYPE_INT_SAMPLER_2D:
190e5c31af7Sopenharmony_ci		case glu::TYPE_INT_SAMPLER_CUBE:
191e5c31af7Sopenharmony_ci		case glu::TYPE_INT_SAMPLER_2D_ARRAY:
192e5c31af7Sopenharmony_ci		case glu::TYPE_INT_SAMPLER_3D:
193e5c31af7Sopenharmony_ci			return glu::TYPE_INT_VEC4;
194e5c31af7Sopenharmony_ci
195e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_2D_SHADOW:
196e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_CUBE_SHADOW:
197e5c31af7Sopenharmony_ci		case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
198e5c31af7Sopenharmony_ci			return glu::TYPE_FLOAT;
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci		default:
201e5c31af7Sopenharmony_ci			DE_ASSERT(false);
202e5c31af7Sopenharmony_ci			return glu::TYPE_LAST;
203e5c31af7Sopenharmony_ci	}
204e5c31af7Sopenharmony_ci}
205e5c31af7Sopenharmony_ci
206e5c31af7Sopenharmony_citemplate<glu::DataType T>
207e5c31af7Sopenharmony_cistatic bool dataTypeEquals (const glu::DataType t)
208e5c31af7Sopenharmony_ci{
209e5c31af7Sopenharmony_ci	return t == T;
210e5c31af7Sopenharmony_ci}
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_citemplate<int N>
213e5c31af7Sopenharmony_cistatic bool dataTypeIsMatrixWithNRows (const glu::DataType t)
214e5c31af7Sopenharmony_ci{
215e5c31af7Sopenharmony_ci	return glu::isDataTypeMatrix(t) && glu::getDataTypeMatrixNumRows(t) == N;
216e5c31af7Sopenharmony_ci}
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_cistatic bool typeContainsMatchingBasicType (const glu::VarType& type, const dataTypePredicate predicate)
219e5c31af7Sopenharmony_ci{
220e5c31af7Sopenharmony_ci	if (type.isBasicType())
221e5c31af7Sopenharmony_ci		return predicate(type.getBasicType());
222e5c31af7Sopenharmony_ci	else if (type.isArrayType())
223e5c31af7Sopenharmony_ci		return typeContainsMatchingBasicType(type.getElementType(), predicate);
224e5c31af7Sopenharmony_ci	else
225e5c31af7Sopenharmony_ci	{
226e5c31af7Sopenharmony_ci		DE_ASSERT(type.isStructType());
227e5c31af7Sopenharmony_ci		const StructType& structType = *type.getStructPtr();
228e5c31af7Sopenharmony_ci		for (int i = 0; i < structType.getNumMembers(); i++)
229e5c31af7Sopenharmony_ci			if (typeContainsMatchingBasicType(structType.getMember(i).getType(), predicate))
230e5c31af7Sopenharmony_ci				return true;
231e5c31af7Sopenharmony_ci		return false;
232e5c31af7Sopenharmony_ci	}
233e5c31af7Sopenharmony_ci}
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_cistatic void getDistinctSamplerTypes (vector<glu::DataType>& dst, const glu::VarType& type)
236e5c31af7Sopenharmony_ci{
237e5c31af7Sopenharmony_ci	if (type.isBasicType())
238e5c31af7Sopenharmony_ci	{
239e5c31af7Sopenharmony_ci		const glu::DataType basicType = type.getBasicType();
240e5c31af7Sopenharmony_ci		if (glu::isDataTypeSampler(basicType) && std::find(dst.begin(), dst.end(), basicType) == dst.end())
241e5c31af7Sopenharmony_ci			dst.push_back(basicType);
242e5c31af7Sopenharmony_ci	}
243e5c31af7Sopenharmony_ci	else if (type.isArrayType())
244e5c31af7Sopenharmony_ci		getDistinctSamplerTypes(dst, type.getElementType());
245e5c31af7Sopenharmony_ci	else
246e5c31af7Sopenharmony_ci	{
247e5c31af7Sopenharmony_ci		DE_ASSERT(type.isStructType());
248e5c31af7Sopenharmony_ci		const StructType& structType = *type.getStructPtr();
249e5c31af7Sopenharmony_ci		for (int i = 0; i < structType.getNumMembers(); i++)
250e5c31af7Sopenharmony_ci			getDistinctSamplerTypes(dst, structType.getMember(i).getType());
251e5c31af7Sopenharmony_ci	}
252e5c31af7Sopenharmony_ci}
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_cistatic int getNumSamplersInType (const glu::VarType& type)
255e5c31af7Sopenharmony_ci{
256e5c31af7Sopenharmony_ci	if (type.isBasicType())
257e5c31af7Sopenharmony_ci		return glu::isDataTypeSampler(type.getBasicType()) ? 1 : 0;
258e5c31af7Sopenharmony_ci	else if (type.isArrayType())
259e5c31af7Sopenharmony_ci		return getNumSamplersInType(type.getElementType()) * type.getArraySize();
260e5c31af7Sopenharmony_ci	else
261e5c31af7Sopenharmony_ci	{
262e5c31af7Sopenharmony_ci		DE_ASSERT(type.isStructType());
263e5c31af7Sopenharmony_ci		const StructType& structType = *type.getStructPtr();
264e5c31af7Sopenharmony_ci		int sum = 0;
265e5c31af7Sopenharmony_ci		for (int i = 0; i < structType.getNumMembers(); i++)
266e5c31af7Sopenharmony_ci			sum += getNumSamplersInType(structType.getMember(i).getType());
267e5c31af7Sopenharmony_ci		return sum;
268e5c31af7Sopenharmony_ci	}
269e5c31af7Sopenharmony_ci}
270e5c31af7Sopenharmony_ci
271e5c31af7Sopenharmony_cinamespace
272e5c31af7Sopenharmony_ci{
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_cistruct VarValue
275e5c31af7Sopenharmony_ci{
276e5c31af7Sopenharmony_ci	glu::DataType type;
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ci	union
279e5c31af7Sopenharmony_ci	{
280e5c31af7Sopenharmony_ci		float		floatV[4*4]; // At most mat4. \note Matrices here are column-major.
281e5c31af7Sopenharmony_ci		deInt32		intV[4];
282e5c31af7Sopenharmony_ci		deUint32	uintV[4];
283e5c31af7Sopenharmony_ci		bool		boolV[4];
284e5c31af7Sopenharmony_ci		struct
285e5c31af7Sopenharmony_ci		{
286e5c31af7Sopenharmony_ci			int		unit;
287e5c31af7Sopenharmony_ci			union
288e5c31af7Sopenharmony_ci			{
289e5c31af7Sopenharmony_ci				float		floatV[4];
290e5c31af7Sopenharmony_ci				deInt32		intV[4];
291e5c31af7Sopenharmony_ci				deUint32	uintV[4];
292e5c31af7Sopenharmony_ci			} fillColor;
293e5c31af7Sopenharmony_ci		} samplerV;
294e5c31af7Sopenharmony_ci	} val;
295e5c31af7Sopenharmony_ci};
296e5c31af7Sopenharmony_ci
297e5c31af7Sopenharmony_cienum CaseShaderType
298e5c31af7Sopenharmony_ci{
299e5c31af7Sopenharmony_ci	CASESHADERTYPE_VERTEX = 0,
300e5c31af7Sopenharmony_ci	CASESHADERTYPE_FRAGMENT,
301e5c31af7Sopenharmony_ci	CASESHADERTYPE_BOTH,
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci	CASESHADERTYPE_LAST
304e5c31af7Sopenharmony_ci};
305e5c31af7Sopenharmony_ci
306e5c31af7Sopenharmony_cistruct Uniform
307e5c31af7Sopenharmony_ci{
308e5c31af7Sopenharmony_ci	string			name;
309e5c31af7Sopenharmony_ci	glu::VarType	type;
310e5c31af7Sopenharmony_ci
311e5c31af7Sopenharmony_ci	Uniform (const char* const name_, const glu::VarType& type_) : name(name_), type(type_) {}
312e5c31af7Sopenharmony_ci};
313e5c31af7Sopenharmony_ci
314e5c31af7Sopenharmony_ci// A set of uniforms, along with related struct types.
315e5c31af7Sopenharmony_ciclass UniformCollection
316e5c31af7Sopenharmony_ci{
317e5c31af7Sopenharmony_cipublic:
318e5c31af7Sopenharmony_ci	int					getNumUniforms		(void) const					{ return (int)m_uniforms.size();	}
319e5c31af7Sopenharmony_ci	int					getNumStructTypes	(void) const					{ return (int)m_structTypes.size();	}
320e5c31af7Sopenharmony_ci	Uniform&			getUniform			(const int ndx)					{ return m_uniforms[ndx];			}
321e5c31af7Sopenharmony_ci	const Uniform&		getUniform			(const int ndx) const			{ return m_uniforms[ndx];			}
322e5c31af7Sopenharmony_ci	const StructType*	getStructType		(const int ndx) const			{ return m_structTypes[ndx];		}
323e5c31af7Sopenharmony_ci	void				addUniform			(const Uniform& uniform)		{ m_uniforms.push_back(uniform);	}
324e5c31af7Sopenharmony_ci	void				addStructType		(const StructType* const type)	{ m_structTypes.push_back(type);	}
325e5c31af7Sopenharmony_ci
326e5c31af7Sopenharmony_ci	UniformCollection	(void) {}
327e5c31af7Sopenharmony_ci	~UniformCollection	(void)
328e5c31af7Sopenharmony_ci	{
329e5c31af7Sopenharmony_ci		for (int i = 0; i < (int)m_structTypes.size(); i++)
330e5c31af7Sopenharmony_ci			delete m_structTypes[i];
331e5c31af7Sopenharmony_ci	}
332e5c31af7Sopenharmony_ci
333e5c31af7Sopenharmony_ci	// Add the contents of m_uniforms and m_structTypes to receiver, and remove them from this one.
334e5c31af7Sopenharmony_ci	// \note receiver takes ownership of the struct types.
335e5c31af7Sopenharmony_ci	void moveContents (UniformCollection& receiver)
336e5c31af7Sopenharmony_ci	{
337e5c31af7Sopenharmony_ci		for (int i = 0; i < (int)m_uniforms.size(); i++)
338e5c31af7Sopenharmony_ci			receiver.addUniform(m_uniforms[i]);
339e5c31af7Sopenharmony_ci		m_uniforms.clear();
340e5c31af7Sopenharmony_ci
341e5c31af7Sopenharmony_ci		for (int i = 0; i < (int)m_structTypes.size(); i++)
342e5c31af7Sopenharmony_ci			receiver.addStructType(m_structTypes[i]);
343e5c31af7Sopenharmony_ci		m_structTypes.clear();
344e5c31af7Sopenharmony_ci	}
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ci	bool containsMatchingBasicType (const dataTypePredicate predicate) const
347e5c31af7Sopenharmony_ci	{
348e5c31af7Sopenharmony_ci		for (int i = 0; i < (int)m_uniforms.size(); i++)
349e5c31af7Sopenharmony_ci			if (typeContainsMatchingBasicType(m_uniforms[i].type, predicate))
350e5c31af7Sopenharmony_ci				return true;
351e5c31af7Sopenharmony_ci		return false;
352e5c31af7Sopenharmony_ci	}
353e5c31af7Sopenharmony_ci
354e5c31af7Sopenharmony_ci	vector<glu::DataType> getSamplerTypes (void) const
355e5c31af7Sopenharmony_ci	{
356e5c31af7Sopenharmony_ci		vector<glu::DataType> samplerTypes;
357e5c31af7Sopenharmony_ci		for (int i = 0; i < (int)m_uniforms.size(); i++)
358e5c31af7Sopenharmony_ci			getDistinctSamplerTypes(samplerTypes, m_uniforms[i].type);
359e5c31af7Sopenharmony_ci		return samplerTypes;
360e5c31af7Sopenharmony_ci	}
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci	bool containsSeveralSamplerTypes (void) const
363e5c31af7Sopenharmony_ci	{
364e5c31af7Sopenharmony_ci		return getSamplerTypes().size() > 1;
365e5c31af7Sopenharmony_ci	}
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ci	int getNumSamplers (void) const
368e5c31af7Sopenharmony_ci	{
369e5c31af7Sopenharmony_ci		int sum = 0;
370e5c31af7Sopenharmony_ci		for (int i = 0; i < (int)m_uniforms.size(); i++)
371e5c31af7Sopenharmony_ci			sum += getNumSamplersInType(m_uniforms[i].type);
372e5c31af7Sopenharmony_ci		return sum;
373e5c31af7Sopenharmony_ci	}
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci	static UniformCollection* basic (const glu::DataType type, const char* const nameSuffix = "")
376e5c31af7Sopenharmony_ci	{
377e5c31af7Sopenharmony_ci		UniformCollection* const	res		= new UniformCollection;
378e5c31af7Sopenharmony_ci		const glu::Precision		prec	= glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
379e5c31af7Sopenharmony_ci		res->m_uniforms.push_back(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(type, prec)));
380e5c31af7Sopenharmony_ci		return res;
381e5c31af7Sopenharmony_ci	}
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ci	static UniformCollection* basicArray (const glu::DataType type, const char* const nameSuffix = "")
384e5c31af7Sopenharmony_ci	{
385e5c31af7Sopenharmony_ci		UniformCollection* const	res		= new UniformCollection;
386e5c31af7Sopenharmony_ci		const glu::Precision		prec	= glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
387e5c31af7Sopenharmony_ci		res->m_uniforms.push_back(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(glu::VarType(type, prec), 3)));
388e5c31af7Sopenharmony_ci		return res;
389e5c31af7Sopenharmony_ci	}
390e5c31af7Sopenharmony_ci
391e5c31af7Sopenharmony_ci	static UniformCollection* basicStruct (const glu::DataType type0, const glu::DataType type1, const bool containsArrays, const char* const nameSuffix = "")
392e5c31af7Sopenharmony_ci	{
393e5c31af7Sopenharmony_ci		UniformCollection* const	res		= new UniformCollection;
394e5c31af7Sopenharmony_ci		const glu::Precision		prec0	= glu::isDataTypeBoolOrBVec(type0) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
395e5c31af7Sopenharmony_ci		const glu::Precision		prec1	= glu::isDataTypeBoolOrBVec(type1) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci		StructType* const structType = new StructType((string("structType") + nameSuffix).c_str());
398e5c31af7Sopenharmony_ci		structType->addMember("m0", glu::VarType(type0, prec0));
399e5c31af7Sopenharmony_ci		structType->addMember("m1", glu::VarType(type1, prec1));
400e5c31af7Sopenharmony_ci		if (containsArrays)
401e5c31af7Sopenharmony_ci		{
402e5c31af7Sopenharmony_ci			structType->addMember("m2", glu::VarType(glu::VarType(type0, prec0), 3));
403e5c31af7Sopenharmony_ci			structType->addMember("m3", glu::VarType(glu::VarType(type1, prec1), 3));
404e5c31af7Sopenharmony_ci		}
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci		res->addStructType(structType);
407e5c31af7Sopenharmony_ci		res->addUniform(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(structType)));
408e5c31af7Sopenharmony_ci
409e5c31af7Sopenharmony_ci		return res;
410e5c31af7Sopenharmony_ci	}
411e5c31af7Sopenharmony_ci
412e5c31af7Sopenharmony_ci	static UniformCollection* structInArray (const glu::DataType type0, const glu::DataType type1, const bool containsArrays, const char* const nameSuffix = "")
413e5c31af7Sopenharmony_ci	{
414e5c31af7Sopenharmony_ci		UniformCollection* const res = basicStruct(type0, type1, containsArrays, nameSuffix);
415e5c31af7Sopenharmony_ci		res->getUniform(0).type = glu::VarType(res->getUniform(0).type, 3);
416e5c31af7Sopenharmony_ci		return res;
417e5c31af7Sopenharmony_ci	}
418e5c31af7Sopenharmony_ci
419e5c31af7Sopenharmony_ci	static UniformCollection* nestedArraysStructs (const glu::DataType type0, const glu::DataType type1, const char* const nameSuffix = "")
420e5c31af7Sopenharmony_ci	{
421e5c31af7Sopenharmony_ci		UniformCollection* const res		= new UniformCollection;
422e5c31af7Sopenharmony_ci		const glu::Precision prec0			= glu::isDataTypeBoolOrBVec(type0) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
423e5c31af7Sopenharmony_ci		const glu::Precision prec1			= glu::isDataTypeBoolOrBVec(type1) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
424e5c31af7Sopenharmony_ci		StructType* const structType		= new StructType((string("structType") + nameSuffix).c_str());
425e5c31af7Sopenharmony_ci		StructType* const subStructType		= new StructType((string("subStructType") + nameSuffix).c_str());
426e5c31af7Sopenharmony_ci		StructType* const subSubStructType	= new StructType((string("subSubStructType") + nameSuffix).c_str());
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci		subSubStructType->addMember("mss0", glu::VarType(type0, prec0));
429e5c31af7Sopenharmony_ci		subSubStructType->addMember("mss1", glu::VarType(type1, prec1));
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_ci		subStructType->addMember("ms0", glu::VarType(type1, prec1));
432e5c31af7Sopenharmony_ci		subStructType->addMember("ms1", glu::VarType(glu::VarType(type0, prec0), 2));
433e5c31af7Sopenharmony_ci		subStructType->addMember("ms2", glu::VarType(glu::VarType(subSubStructType), 2));
434e5c31af7Sopenharmony_ci
435e5c31af7Sopenharmony_ci		structType->addMember("m0", glu::VarType(type0, prec0));
436e5c31af7Sopenharmony_ci		structType->addMember("m1", glu::VarType(subStructType));
437e5c31af7Sopenharmony_ci		structType->addMember("m2", glu::VarType(type1, prec1));
438e5c31af7Sopenharmony_ci
439e5c31af7Sopenharmony_ci		res->addStructType(subSubStructType);
440e5c31af7Sopenharmony_ci		res->addStructType(subStructType);
441e5c31af7Sopenharmony_ci		res->addStructType(structType);
442e5c31af7Sopenharmony_ci
443e5c31af7Sopenharmony_ci		res->addUniform(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(structType)));
444e5c31af7Sopenharmony_ci
445e5c31af7Sopenharmony_ci		return res;
446e5c31af7Sopenharmony_ci	}
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_ci	static UniformCollection* multipleBasic (const char* const nameSuffix = "")
449e5c31af7Sopenharmony_ci	{
450e5c31af7Sopenharmony_ci		static const glu::DataType	types[]	= { glu::TYPE_FLOAT, glu::TYPE_INT_VEC3, glu::TYPE_UINT_VEC4, glu::TYPE_FLOAT_MAT3, glu::TYPE_BOOL_VEC2 };
451e5c31af7Sopenharmony_ci		UniformCollection* const	res		= new UniformCollection;
452e5c31af7Sopenharmony_ci
453e5c31af7Sopenharmony_ci		for (int i = 0; i < DE_LENGTH_OF_ARRAY(types); i++)
454e5c31af7Sopenharmony_ci		{
455e5c31af7Sopenharmony_ci			UniformCollection* const sub = basic(types[i], ("_" + de::toString(i) + nameSuffix).c_str());
456e5c31af7Sopenharmony_ci			sub->moveContents(*res);
457e5c31af7Sopenharmony_ci			delete sub;
458e5c31af7Sopenharmony_ci		}
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_ci		return res;
461e5c31af7Sopenharmony_ci	}
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci	static UniformCollection* multipleBasicArray (const char* const nameSuffix = "")
464e5c31af7Sopenharmony_ci	{
465e5c31af7Sopenharmony_ci		static const glu::DataType	types[]	= { glu::TYPE_FLOAT, glu::TYPE_INT_VEC3, glu::TYPE_BOOL_VEC2 };
466e5c31af7Sopenharmony_ci		UniformCollection* const	res		= new UniformCollection;
467e5c31af7Sopenharmony_ci
468e5c31af7Sopenharmony_ci		for (int i = 0; i < DE_LENGTH_OF_ARRAY(types); i++)
469e5c31af7Sopenharmony_ci		{
470e5c31af7Sopenharmony_ci			UniformCollection* const sub = basicArray(types[i], ("_" + de::toString(i) + nameSuffix).c_str());
471e5c31af7Sopenharmony_ci			sub->moveContents(*res);
472e5c31af7Sopenharmony_ci			delete sub;
473e5c31af7Sopenharmony_ci		}
474e5c31af7Sopenharmony_ci
475e5c31af7Sopenharmony_ci		return res;
476e5c31af7Sopenharmony_ci	}
477e5c31af7Sopenharmony_ci
478e5c31af7Sopenharmony_ci	static UniformCollection* multipleNestedArraysStructs (const char* const nameSuffix = "")
479e5c31af7Sopenharmony_ci	{
480e5c31af7Sopenharmony_ci		static const glu::DataType	types0[]	= { glu::TYPE_FLOAT,		glu::TYPE_INT,		glu::TYPE_BOOL_VEC4 };
481e5c31af7Sopenharmony_ci		static const glu::DataType	types1[]	= { glu::TYPE_FLOAT_VEC4,	glu::TYPE_INT_VEC4,	glu::TYPE_BOOL };
482e5c31af7Sopenharmony_ci		UniformCollection* const	res			= new UniformCollection;
483e5c31af7Sopenharmony_ci
484e5c31af7Sopenharmony_ci		DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types0) == DE_LENGTH_OF_ARRAY(types1));
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_ci		for (int i = 0; i < DE_LENGTH_OF_ARRAY(types0); i++)
487e5c31af7Sopenharmony_ci		{
488e5c31af7Sopenharmony_ci			UniformCollection* const sub = nestedArraysStructs(types0[i], types1[i], ("_" + de::toString(i) + nameSuffix).c_str());
489e5c31af7Sopenharmony_ci			sub->moveContents(*res);
490e5c31af7Sopenharmony_ci			delete sub;
491e5c31af7Sopenharmony_ci		}
492e5c31af7Sopenharmony_ci
493e5c31af7Sopenharmony_ci		return res;
494e5c31af7Sopenharmony_ci	}
495e5c31af7Sopenharmony_ci
496e5c31af7Sopenharmony_ciprivate:
497e5c31af7Sopenharmony_ci	// \note Copying these would be cumbersome, since deep-copying both m_uniforms and m_structTypes
498e5c31af7Sopenharmony_ci	// would mean that we'd need to update pointers from uniforms to point to the new structTypes.
499e5c31af7Sopenharmony_ci	// When the same UniformCollection is needed in several places, a SharedPtr is used instead.
500e5c31af7Sopenharmony_ci								UniformCollection	(const UniformCollection&); // Not allowed.
501e5c31af7Sopenharmony_ci	UniformCollection&			operator=			(const UniformCollection&); // Not allowed.
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci	vector<Uniform>				m_uniforms;
504e5c31af7Sopenharmony_ci	vector<const StructType*>	m_structTypes;
505e5c31af7Sopenharmony_ci};
506e5c31af7Sopenharmony_ci
507e5c31af7Sopenharmony_ci} // anonymous
508e5c31af7Sopenharmony_ci
509e5c31af7Sopenharmony_cistatic VarValue getSamplerFillValue (const VarValue& sampler)
510e5c31af7Sopenharmony_ci{
511e5c31af7Sopenharmony_ci	DE_ASSERT(glu::isDataTypeSampler(sampler.type));
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ci	VarValue result;
514e5c31af7Sopenharmony_ci	result.type = getSamplerLookupReturnType(sampler.type);
515e5c31af7Sopenharmony_ci
516e5c31af7Sopenharmony_ci	switch (result.type)
517e5c31af7Sopenharmony_ci	{
518e5c31af7Sopenharmony_ci		case glu::TYPE_FLOAT_VEC4:
519e5c31af7Sopenharmony_ci			for (int i = 0; i < 4; i++)
520e5c31af7Sopenharmony_ci				result.val.floatV[i] = sampler.val.samplerV.fillColor.floatV[i];
521e5c31af7Sopenharmony_ci			break;
522e5c31af7Sopenharmony_ci		case glu::TYPE_UINT_VEC4:
523e5c31af7Sopenharmony_ci			for (int i = 0; i < 4; i++)
524e5c31af7Sopenharmony_ci				result.val.uintV[i] = sampler.val.samplerV.fillColor.uintV[i];
525e5c31af7Sopenharmony_ci			break;
526e5c31af7Sopenharmony_ci		case glu::TYPE_INT_VEC4:
527e5c31af7Sopenharmony_ci			for (int i = 0; i < 4; i++)
528e5c31af7Sopenharmony_ci				result.val.intV[i] = sampler.val.samplerV.fillColor.intV[i];
529e5c31af7Sopenharmony_ci			break;
530e5c31af7Sopenharmony_ci		case glu::TYPE_FLOAT:
531e5c31af7Sopenharmony_ci			result.val.floatV[0] = sampler.val.samplerV.fillColor.floatV[0];
532e5c31af7Sopenharmony_ci			break;
533e5c31af7Sopenharmony_ci		default:
534e5c31af7Sopenharmony_ci			DE_ASSERT(false);
535e5c31af7Sopenharmony_ci	}
536e5c31af7Sopenharmony_ci
537e5c31af7Sopenharmony_ci	return result;
538e5c31af7Sopenharmony_ci}
539e5c31af7Sopenharmony_ci
540e5c31af7Sopenharmony_cistatic VarValue getSamplerUnitValue (const VarValue& sampler)
541e5c31af7Sopenharmony_ci{
542e5c31af7Sopenharmony_ci	DE_ASSERT(glu::isDataTypeSampler(sampler.type));
543e5c31af7Sopenharmony_ci
544e5c31af7Sopenharmony_ci	VarValue result;
545e5c31af7Sopenharmony_ci	result.type = glu::TYPE_INT;
546e5c31af7Sopenharmony_ci	result.val.intV[0] = sampler.val.samplerV.unit;
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci	return result;
549e5c31af7Sopenharmony_ci}
550e5c31af7Sopenharmony_ci
551e5c31af7Sopenharmony_cistatic glu::DataType getDataTypeTransposedMatrix (const glu::DataType original)
552e5c31af7Sopenharmony_ci{
553e5c31af7Sopenharmony_ci	return glu::getDataTypeMatrix(glu::getDataTypeMatrixNumRows(original), glu::getDataTypeMatrixNumColumns(original));
554e5c31af7Sopenharmony_ci}
555e5c31af7Sopenharmony_ci
556e5c31af7Sopenharmony_cistatic VarValue getTransposeMatrix (const VarValue& original)
557e5c31af7Sopenharmony_ci{
558e5c31af7Sopenharmony_ci	DE_ASSERT(glu::isDataTypeMatrix(original.type));
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci	const int	rows = glu::getDataTypeMatrixNumRows(original.type);
561e5c31af7Sopenharmony_ci	const int	cols = glu::getDataTypeMatrixNumColumns(original.type);
562e5c31af7Sopenharmony_ci	VarValue	result;
563e5c31af7Sopenharmony_ci	result.type = getDataTypeTransposedMatrix(original.type);
564e5c31af7Sopenharmony_ci
565e5c31af7Sopenharmony_ci	for (int i = 0; i < rows; i++)
566e5c31af7Sopenharmony_ci	for (int j = 0; j < cols; j++)
567e5c31af7Sopenharmony_ci		result.val.floatV[i*cols + j] = original.val.floatV[j*rows + i];
568e5c31af7Sopenharmony_ci
569e5c31af7Sopenharmony_ci	return result;
570e5c31af7Sopenharmony_ci}
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_cistatic string shaderVarValueStr (const VarValue& value)
573e5c31af7Sopenharmony_ci{
574e5c31af7Sopenharmony_ci	const int			numElems = glu::getDataTypeScalarSize(value.type);
575e5c31af7Sopenharmony_ci	std::ostringstream	result;
576e5c31af7Sopenharmony_ci
577e5c31af7Sopenharmony_ci	if (numElems > 1)
578e5c31af7Sopenharmony_ci		result << glu::getDataTypeName(value.type) << "(";
579e5c31af7Sopenharmony_ci
580e5c31af7Sopenharmony_ci	for (int i = 0; i < numElems; i++)
581e5c31af7Sopenharmony_ci	{
582e5c31af7Sopenharmony_ci		if (i > 0)
583e5c31af7Sopenharmony_ci			result << ", ";
584e5c31af7Sopenharmony_ci
585e5c31af7Sopenharmony_ci		if (glu::isDataTypeFloatOrVec(value.type) || glu::isDataTypeMatrix(value.type))
586e5c31af7Sopenharmony_ci			result << de::floatToString(value.val.floatV[i], 2);
587e5c31af7Sopenharmony_ci		else if (glu::isDataTypeIntOrIVec((value.type)))
588e5c31af7Sopenharmony_ci			result << de::toString(value.val.intV[i]);
589e5c31af7Sopenharmony_ci		else if (glu::isDataTypeUintOrUVec((value.type)))
590e5c31af7Sopenharmony_ci			result << de::toString(value.val.uintV[i]) << "u";
591e5c31af7Sopenharmony_ci		else if (glu::isDataTypeBoolOrBVec((value.type)))
592e5c31af7Sopenharmony_ci			result << (value.val.boolV[i] ? "true" : "false");
593e5c31af7Sopenharmony_ci		else if (glu::isDataTypeSampler((value.type)))
594e5c31af7Sopenharmony_ci			result << shaderVarValueStr(getSamplerFillValue(value));
595e5c31af7Sopenharmony_ci		else
596e5c31af7Sopenharmony_ci			DE_ASSERT(false);
597e5c31af7Sopenharmony_ci	}
598e5c31af7Sopenharmony_ci
599e5c31af7Sopenharmony_ci	if (numElems > 1)
600e5c31af7Sopenharmony_ci		result << ")";
601e5c31af7Sopenharmony_ci
602e5c31af7Sopenharmony_ci	return result.str();
603e5c31af7Sopenharmony_ci}
604e5c31af7Sopenharmony_ci
605e5c31af7Sopenharmony_cistatic string apiVarValueStr (const VarValue& value)
606e5c31af7Sopenharmony_ci{
607e5c31af7Sopenharmony_ci	const int			numElems = glu::getDataTypeScalarSize(value.type);
608e5c31af7Sopenharmony_ci	std::ostringstream	result;
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_ci	if (numElems > 1)
611e5c31af7Sopenharmony_ci		result << "(";
612e5c31af7Sopenharmony_ci
613e5c31af7Sopenharmony_ci	for (int i = 0; i < numElems; i++)
614e5c31af7Sopenharmony_ci	{
615e5c31af7Sopenharmony_ci		if (i > 0)
616e5c31af7Sopenharmony_ci			result << ", ";
617e5c31af7Sopenharmony_ci
618e5c31af7Sopenharmony_ci		if (glu::isDataTypeFloatOrVec(value.type) || glu::isDataTypeMatrix(value.type))
619e5c31af7Sopenharmony_ci			result << de::floatToString(value.val.floatV[i], 2);
620e5c31af7Sopenharmony_ci		else if (glu::isDataTypeIntOrIVec((value.type)))
621e5c31af7Sopenharmony_ci			result << de::toString(value.val.intV[i]);
622e5c31af7Sopenharmony_ci		else if (glu::isDataTypeUintOrUVec((value.type)))
623e5c31af7Sopenharmony_ci			result << de::toString(value.val.uintV[i]);
624e5c31af7Sopenharmony_ci		else if (glu::isDataTypeBoolOrBVec((value.type)))
625e5c31af7Sopenharmony_ci			result << (value.val.boolV[i] ? "true" : "false");
626e5c31af7Sopenharmony_ci		else if (glu::isDataTypeSampler((value.type)))
627e5c31af7Sopenharmony_ci			result << value.val.samplerV.unit;
628e5c31af7Sopenharmony_ci		else
629e5c31af7Sopenharmony_ci			DE_ASSERT(false);
630e5c31af7Sopenharmony_ci	}
631e5c31af7Sopenharmony_ci
632e5c31af7Sopenharmony_ci	if (numElems > 1)
633e5c31af7Sopenharmony_ci		result << ")";
634e5c31af7Sopenharmony_ci
635e5c31af7Sopenharmony_ci	return result.str();
636e5c31af7Sopenharmony_ci}
637e5c31af7Sopenharmony_ci
638e5c31af7Sopenharmony_cistatic VarValue generateRandomVarValue (const glu::DataType type, Random& rnd, int samplerUnit = -1 /* Used if type is a sampler type. \note Samplers' unit numbers are not randomized. */)
639e5c31af7Sopenharmony_ci{
640e5c31af7Sopenharmony_ci	const int	numElems = glu::getDataTypeScalarSize(type);
641e5c31af7Sopenharmony_ci	VarValue	result;
642e5c31af7Sopenharmony_ci	result.type = type;
643e5c31af7Sopenharmony_ci
644e5c31af7Sopenharmony_ci	DE_ASSERT((samplerUnit >= 0) == (glu::isDataTypeSampler(type)));
645e5c31af7Sopenharmony_ci
646e5c31af7Sopenharmony_ci	if (glu::isDataTypeFloatOrVec(type) || glu::isDataTypeMatrix(type))
647e5c31af7Sopenharmony_ci	{
648e5c31af7Sopenharmony_ci		for (int i = 0; i < numElems; i++)
649e5c31af7Sopenharmony_ci			result.val.floatV[i] = rnd.getFloat(-10.0f, 10.0f);
650e5c31af7Sopenharmony_ci	}
651e5c31af7Sopenharmony_ci	else if (glu::isDataTypeIntOrIVec(type))
652e5c31af7Sopenharmony_ci	{
653e5c31af7Sopenharmony_ci		for (int i = 0; i < numElems; i++)
654e5c31af7Sopenharmony_ci			result.val.intV[i] = rnd.getInt(-10, 10);
655e5c31af7Sopenharmony_ci	}
656e5c31af7Sopenharmony_ci	else if (glu::isDataTypeUintOrUVec(type))
657e5c31af7Sopenharmony_ci	{
658e5c31af7Sopenharmony_ci		for (int i = 0; i < numElems; i++)
659e5c31af7Sopenharmony_ci			result.val.uintV[i] = (deUint32)rnd.getInt(0, 10);
660e5c31af7Sopenharmony_ci	}
661e5c31af7Sopenharmony_ci	else if (glu::isDataTypeBoolOrBVec(type))
662e5c31af7Sopenharmony_ci	{
663e5c31af7Sopenharmony_ci		for (int i = 0; i < numElems; i++)
664e5c31af7Sopenharmony_ci			result.val.boolV[i] = rnd.getBool();
665e5c31af7Sopenharmony_ci	}
666e5c31af7Sopenharmony_ci	else if (glu::isDataTypeSampler(type))
667e5c31af7Sopenharmony_ci	{
668e5c31af7Sopenharmony_ci		const glu::DataType		texResultType		= getSamplerLookupReturnType(type);
669e5c31af7Sopenharmony_ci		const glu::DataType		texResultScalarType	= glu::getDataTypeScalarType(texResultType);
670e5c31af7Sopenharmony_ci		const int				texResultNumDims	= glu::getDataTypeScalarSize(texResultType);
671e5c31af7Sopenharmony_ci
672e5c31af7Sopenharmony_ci		result.val.samplerV.unit = samplerUnit;
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_ci		for (int i = 0; i < texResultNumDims; i++)
675e5c31af7Sopenharmony_ci		{
676e5c31af7Sopenharmony_ci			switch (texResultScalarType)
677e5c31af7Sopenharmony_ci			{
678e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT:	result.val.samplerV.fillColor.floatV[i]		= rnd.getFloat(0.0f, 1.0f);		break;
679e5c31af7Sopenharmony_ci				case glu::TYPE_INT:		result.val.samplerV.fillColor.intV[i]		= rnd.getInt(-10, 10);			break;
680e5c31af7Sopenharmony_ci				case glu::TYPE_UINT:	result.val.samplerV.fillColor.uintV[i]		= (deUint32)rnd.getInt(0, 10);	break;
681e5c31af7Sopenharmony_ci				default:
682e5c31af7Sopenharmony_ci					DE_ASSERT(false);
683e5c31af7Sopenharmony_ci			}
684e5c31af7Sopenharmony_ci		}
685e5c31af7Sopenharmony_ci	}
686e5c31af7Sopenharmony_ci	else
687e5c31af7Sopenharmony_ci		DE_ASSERT(false);
688e5c31af7Sopenharmony_ci
689e5c31af7Sopenharmony_ci	return result;
690e5c31af7Sopenharmony_ci}
691e5c31af7Sopenharmony_ci
692e5c31af7Sopenharmony_cistatic bool apiVarValueEquals (const VarValue& a, const VarValue& b)
693e5c31af7Sopenharmony_ci{
694e5c31af7Sopenharmony_ci	const int		size			= glu::getDataTypeScalarSize(a.type);
695e5c31af7Sopenharmony_ci	const float		floatThreshold	= 0.05f;
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci	DE_ASSERT(a.type == b.type);
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_ci	if (glu::isDataTypeFloatOrVec(a.type) || glu::isDataTypeMatrix(a.type))
700e5c31af7Sopenharmony_ci	{
701e5c31af7Sopenharmony_ci		for (int i = 0; i < size; i++)
702e5c31af7Sopenharmony_ci			if (de::abs(a.val.floatV[i] - b.val.floatV[i]) >= floatThreshold)
703e5c31af7Sopenharmony_ci				return false;
704e5c31af7Sopenharmony_ci	}
705e5c31af7Sopenharmony_ci	else if (glu::isDataTypeIntOrIVec(a.type))
706e5c31af7Sopenharmony_ci	{
707e5c31af7Sopenharmony_ci		for (int i = 0; i < size; i++)
708e5c31af7Sopenharmony_ci			if (a.val.intV[i] != b.val.intV[i])
709e5c31af7Sopenharmony_ci				return false;
710e5c31af7Sopenharmony_ci	}
711e5c31af7Sopenharmony_ci	else if (glu::isDataTypeUintOrUVec(a.type))
712e5c31af7Sopenharmony_ci	{
713e5c31af7Sopenharmony_ci		for (int i = 0; i < size; i++)
714e5c31af7Sopenharmony_ci			if (a.val.uintV[i] != b.val.uintV[i])
715e5c31af7Sopenharmony_ci				return false;
716e5c31af7Sopenharmony_ci	}
717e5c31af7Sopenharmony_ci	else if (glu::isDataTypeBoolOrBVec(a.type))
718e5c31af7Sopenharmony_ci	{
719e5c31af7Sopenharmony_ci		for (int i = 0; i < size; i++)
720e5c31af7Sopenharmony_ci			if (a.val.boolV[i] != b.val.boolV[i])
721e5c31af7Sopenharmony_ci				return false;
722e5c31af7Sopenharmony_ci	}
723e5c31af7Sopenharmony_ci	else if (glu::isDataTypeSampler(a.type))
724e5c31af7Sopenharmony_ci	{
725e5c31af7Sopenharmony_ci		if (a.val.samplerV.unit != b.val.samplerV.unit)
726e5c31af7Sopenharmony_ci			return false;
727e5c31af7Sopenharmony_ci	}
728e5c31af7Sopenharmony_ci	else
729e5c31af7Sopenharmony_ci		DE_ASSERT(false);
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ci	return true;
732e5c31af7Sopenharmony_ci}
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_cistatic VarValue getRandomBoolRepresentation (const VarValue& boolValue, const glu::DataType targetScalarType, Random& rnd)
735e5c31af7Sopenharmony_ci{
736e5c31af7Sopenharmony_ci	DE_ASSERT(glu::isDataTypeBoolOrBVec(boolValue.type));
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ci	const int				size		= glu::getDataTypeScalarSize(boolValue.type);
739e5c31af7Sopenharmony_ci	const glu::DataType		targetType	= size == 1 ? targetScalarType : glu::getDataTypeVector(targetScalarType, size);
740e5c31af7Sopenharmony_ci	VarValue				result;
741e5c31af7Sopenharmony_ci	result.type = targetType;
742e5c31af7Sopenharmony_ci
743e5c31af7Sopenharmony_ci	switch (targetScalarType)
744e5c31af7Sopenharmony_ci	{
745e5c31af7Sopenharmony_ci		case glu::TYPE_INT:
746e5c31af7Sopenharmony_ci			for (int i = 0; i < size; i++)
747e5c31af7Sopenharmony_ci			{
748e5c31af7Sopenharmony_ci				if (boolValue.val.boolV[i])
749e5c31af7Sopenharmony_ci				{
750e5c31af7Sopenharmony_ci					result.val.intV[i] = rnd.getInt(-10, 10);
751e5c31af7Sopenharmony_ci					if (result.val.intV[i] == 0)
752e5c31af7Sopenharmony_ci						result.val.intV[i] = 1;
753e5c31af7Sopenharmony_ci				}
754e5c31af7Sopenharmony_ci				else
755e5c31af7Sopenharmony_ci					result.val.intV[i] = 0;
756e5c31af7Sopenharmony_ci			}
757e5c31af7Sopenharmony_ci			break;
758e5c31af7Sopenharmony_ci
759e5c31af7Sopenharmony_ci		case glu::TYPE_UINT:
760e5c31af7Sopenharmony_ci			for (int i = 0; i < size; i++)
761e5c31af7Sopenharmony_ci			{
762e5c31af7Sopenharmony_ci				if (boolValue.val.boolV[i])
763e5c31af7Sopenharmony_ci					result.val.uintV[i] = rnd.getInt(1, 10);
764e5c31af7Sopenharmony_ci				else
765e5c31af7Sopenharmony_ci					result.val.uintV[i] = 0;
766e5c31af7Sopenharmony_ci			}
767e5c31af7Sopenharmony_ci			break;
768e5c31af7Sopenharmony_ci
769e5c31af7Sopenharmony_ci		case glu::TYPE_FLOAT:
770e5c31af7Sopenharmony_ci			for (int i = 0; i < size; i++)
771e5c31af7Sopenharmony_ci			{
772e5c31af7Sopenharmony_ci				if (boolValue.val.boolV[i])
773e5c31af7Sopenharmony_ci				{
774e5c31af7Sopenharmony_ci					result.val.floatV[i] = rnd.getFloat(-10.0f, 10.0f);
775e5c31af7Sopenharmony_ci					if (result.val.floatV[i] == 0.0f)
776e5c31af7Sopenharmony_ci						result.val.floatV[i] = 1.0f;
777e5c31af7Sopenharmony_ci				}
778e5c31af7Sopenharmony_ci				else
779e5c31af7Sopenharmony_ci					result.val.floatV[i] = 0;
780e5c31af7Sopenharmony_ci			}
781e5c31af7Sopenharmony_ci			break;
782e5c31af7Sopenharmony_ci
783e5c31af7Sopenharmony_ci		default:
784e5c31af7Sopenharmony_ci			DE_ASSERT(false);
785e5c31af7Sopenharmony_ci	}
786e5c31af7Sopenharmony_ci
787e5c31af7Sopenharmony_ci	return result;
788e5c31af7Sopenharmony_ci}
789e5c31af7Sopenharmony_ci
790e5c31af7Sopenharmony_cistatic const char* getCaseShaderTypeName (const CaseShaderType type)
791e5c31af7Sopenharmony_ci{
792e5c31af7Sopenharmony_ci	switch (type)
793e5c31af7Sopenharmony_ci	{
794e5c31af7Sopenharmony_ci		case CASESHADERTYPE_VERTEX:		return "vertex";
795e5c31af7Sopenharmony_ci		case CASESHADERTYPE_FRAGMENT:	return "fragment";
796e5c31af7Sopenharmony_ci		case CASESHADERTYPE_BOTH:		return "both";
797e5c31af7Sopenharmony_ci		default:
798e5c31af7Sopenharmony_ci			DE_ASSERT(false);
799e5c31af7Sopenharmony_ci			return DE_NULL;
800e5c31af7Sopenharmony_ci	}
801e5c31af7Sopenharmony_ci}
802e5c31af7Sopenharmony_ci
803e5c31af7Sopenharmony_ciclass UniformCase : public TestCase, protected glu::CallLogWrapper
804e5c31af7Sopenharmony_ci{
805e5c31af7Sopenharmony_cipublic:
806e5c31af7Sopenharmony_ci	enum Feature
807e5c31af7Sopenharmony_ci	{
808e5c31af7Sopenharmony_ci		// ARRAYUSAGE_ONLY_MIDDLE_INDEX: only middle index of each array is used in shader. If not given, use all indices.
809e5c31af7Sopenharmony_ci		FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX	= 1<<0,
810e5c31af7Sopenharmony_ci
811e5c31af7Sopenharmony_ci		// UNIFORMFUNC_VALUE: use pass-by-value versions of uniform assignment funcs, e.g. glProgramUniform1f(), where possible. If not given, use pass-by-pointer versions.
812e5c31af7Sopenharmony_ci		FEATURE_UNIFORMFUNC_VALUE				= 1<<1,
813e5c31af7Sopenharmony_ci
814e5c31af7Sopenharmony_ci		// MATRIXMODE_ROWMAJOR: pass matrices to GL in row major form. If not given, use column major.
815e5c31af7Sopenharmony_ci		FEATURE_MATRIXMODE_ROWMAJOR				= 1<<2,
816e5c31af7Sopenharmony_ci
817e5c31af7Sopenharmony_ci		// ARRAYASSIGN: how basic-type arrays are assigned with glProgramUniform*(). If none given, assign each element of an array separately.
818e5c31af7Sopenharmony_ci		FEATURE_ARRAYASSIGN_FULL				= 1<<3, //!< Assign all elements of an array with one glProgramUniform*().
819e5c31af7Sopenharmony_ci		FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO		= 1<<4, //!< Assign two elements per one glProgramUniform*().
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_ci		// UNIFORMUSAGE_EVERY_OTHER: use about half of the uniforms. If not given, use all uniforms (except that some array indices may be omitted according to ARRAYUSAGE).
822e5c31af7Sopenharmony_ci		FEATURE_UNIFORMUSAGE_EVERY_OTHER		= 1<<5,
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ci		// BOOLEANAPITYPE: type used to pass booleans to and from GL api. If none given, use float.
825e5c31af7Sopenharmony_ci		FEATURE_BOOLEANAPITYPE_INT				= 1<<6,
826e5c31af7Sopenharmony_ci		FEATURE_BOOLEANAPITYPE_UINT				= 1<<7,
827e5c31af7Sopenharmony_ci
828e5c31af7Sopenharmony_ci		// ARRAY_FIRST_ELEM_NAME_NO_INDEX: in certain API functions, when referring to the first element of an array, use just the array name without [0] at the end.
829e5c31af7Sopenharmony_ci		FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX	= 1<<8
830e5c31af7Sopenharmony_ci	};
831e5c31af7Sopenharmony_ci
832e5c31af7Sopenharmony_ci								UniformCase		(Context& context, const char* name, const char* description, CaseShaderType caseType, const SharedPtr<const UniformCollection>& uniformCollection, deUint32 features);
833e5c31af7Sopenharmony_ci	virtual						~UniformCase	(void);
834e5c31af7Sopenharmony_ci
835e5c31af7Sopenharmony_ci	virtual void				init			(void);
836e5c31af7Sopenharmony_ci	virtual void				deinit			(void);
837e5c31af7Sopenharmony_ci
838e5c31af7Sopenharmony_ci	IterateResult				iterate			(void);
839e5c31af7Sopenharmony_ci
840e5c31af7Sopenharmony_ciprotected:
841e5c31af7Sopenharmony_ci	// A basic uniform is a uniform (possibly struct or array member) whose type is a basic type (e.g. float, ivec4, sampler2d).
842e5c31af7Sopenharmony_ci	struct BasicUniform
843e5c31af7Sopenharmony_ci	{
844e5c31af7Sopenharmony_ci		string			name;
845e5c31af7Sopenharmony_ci		glu::DataType	type;
846e5c31af7Sopenharmony_ci		bool			isUsedInShader;
847e5c31af7Sopenharmony_ci		VarValue		finalValue;	//!< The value we ultimately want to set for this uniform.
848e5c31af7Sopenharmony_ci
849e5c31af7Sopenharmony_ci		string			rootName;	//!< If this is a member of a basic-typed array, rootName is the name of that array with "[0]" appended. Otherwise it equals name.
850e5c31af7Sopenharmony_ci		int				elemNdx;	//!< If this is a member of a basic-typed array, elemNdx is the index in that array. Otherwise -1.
851e5c31af7Sopenharmony_ci		int				rootSize;	//!< If this is a member of a basic-typed array, rootSize is the size of that array. Otherwise 1.
852e5c31af7Sopenharmony_ci
853e5c31af7Sopenharmony_ci		BasicUniform (const char* const		name_,
854e5c31af7Sopenharmony_ci					  const glu::DataType	type_,
855e5c31af7Sopenharmony_ci					  const bool			isUsedInShader_,
856e5c31af7Sopenharmony_ci					  const VarValue&		finalValue_,
857e5c31af7Sopenharmony_ci					  const char* const		rootName_	= DE_NULL,
858e5c31af7Sopenharmony_ci					  const int				elemNdx_	= -1,
859e5c31af7Sopenharmony_ci					  const int				rootSize_	= 1)
860e5c31af7Sopenharmony_ci					  : name			(name_)
861e5c31af7Sopenharmony_ci					  , type			(type_)
862e5c31af7Sopenharmony_ci					  , isUsedInShader	(isUsedInShader_)
863e5c31af7Sopenharmony_ci					  , finalValue		(finalValue_)
864e5c31af7Sopenharmony_ci					  , rootName		(rootName_ == DE_NULL ? name_ : rootName_)
865e5c31af7Sopenharmony_ci					  , elemNdx			(elemNdx_)
866e5c31af7Sopenharmony_ci					  , rootSize		(rootSize_)
867e5c31af7Sopenharmony_ci					 {
868e5c31af7Sopenharmony_ci					 }
869e5c31af7Sopenharmony_ci
870e5c31af7Sopenharmony_ci		static vector<BasicUniform>::const_iterator findWithName (const vector<BasicUniform>& vec, const char* const name)
871e5c31af7Sopenharmony_ci		{
872e5c31af7Sopenharmony_ci			for (vector<BasicUniform>::const_iterator it = vec.begin(); it != vec.end(); it++)
873e5c31af7Sopenharmony_ci			{
874e5c31af7Sopenharmony_ci				if (it->name == name)
875e5c31af7Sopenharmony_ci					return it;
876e5c31af7Sopenharmony_ci			}
877e5c31af7Sopenharmony_ci			return vec.end();
878e5c31af7Sopenharmony_ci		}
879e5c31af7Sopenharmony_ci	};
880e5c31af7Sopenharmony_ci
881e5c31af7Sopenharmony_ci	// Reference values for info that is expected to be reported by glGetActiveUniform() or glGetActiveUniformsiv().
882e5c31af7Sopenharmony_ci	struct BasicUniformReportRef
883e5c31af7Sopenharmony_ci	{
884e5c31af7Sopenharmony_ci		string			name;
885e5c31af7Sopenharmony_ci		// \note minSize and maxSize are for arrays and can be distinct since implementations are allowed, but not required, to trim the inactive end indices of arrays.
886e5c31af7Sopenharmony_ci		int				minSize;
887e5c31af7Sopenharmony_ci		int				maxSize;
888e5c31af7Sopenharmony_ci		glu::DataType	type;
889e5c31af7Sopenharmony_ci		bool			isUsedInShader;
890e5c31af7Sopenharmony_ci
891e5c31af7Sopenharmony_ci		BasicUniformReportRef (const char* const name_, const int minS, const int maxS, const glu::DataType type_, const bool used)
892e5c31af7Sopenharmony_ci			: name(name_), minSize(minS), maxSize(maxS), type(type_), isUsedInShader(used) { DE_ASSERT(minSize <= maxSize); }
893e5c31af7Sopenharmony_ci		BasicUniformReportRef (const char* const name_, const glu::DataType type_, const bool used)
894e5c31af7Sopenharmony_ci			: name(name_), minSize(1), maxSize(1), type(type_), isUsedInShader(used) {}
895e5c31af7Sopenharmony_ci	};
896e5c31af7Sopenharmony_ci
897e5c31af7Sopenharmony_ci	// Get uniform values with glGetUniform*() and put to valuesDst. Uniforms that get -1 from glGetUniformLocation() get glu::TYPE_INVALID.
898e5c31af7Sopenharmony_ci	bool						getUniforms								(vector<VarValue>& valuesDst, const vector<BasicUniform>& basicUniforms, deUint32 programGL);
899e5c31af7Sopenharmony_ci	// Assign the basicUniforms[].finalValue values for uniforms. \note rnd parameter is for booleans (true can be any nonzero value).
900e5c31af7Sopenharmony_ci	void						assignUniforms							(const vector<BasicUniform>& basicUniforms, deUint32 programGL, Random& rnd);
901e5c31af7Sopenharmony_ci	// Compare the uniform values given in values (obtained with glGetUniform*()) with the basicUniform.finalValue values.
902e5c31af7Sopenharmony_ci	bool						compareUniformValues					(const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms);
903e5c31af7Sopenharmony_ci	// Render and check that all pixels are green (i.e. all uniform comparisons passed).
904e5c31af7Sopenharmony_ci	bool						renderTest								(const vector<BasicUniform>& basicUniforms, const ShaderProgram& program, Random& rnd);
905e5c31af7Sopenharmony_ci
906e5c31af7Sopenharmony_ci	virtual bool				test									(const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) = 0;
907e5c31af7Sopenharmony_ci
908e5c31af7Sopenharmony_ci	const deUint32								m_features;
909e5c31af7Sopenharmony_ci	const SharedPtr<const UniformCollection>	m_uniformCollection;
910e5c31af7Sopenharmony_ci
911e5c31af7Sopenharmony_ciprivate:
912e5c31af7Sopenharmony_ci	// Generates the basic uniforms, based on the uniform with name varName and type varType, in the same manner as are expected
913e5c31af7Sopenharmony_ci	// to be returned by glGetActiveUniform(), e.g. generates a name like var[0] for arrays, and recursively generates struct member names.
914e5c31af7Sopenharmony_ci	void						generateBasicUniforms					(vector<BasicUniform>&				basicUniformsDst,
915e5c31af7Sopenharmony_ci																		 vector<BasicUniformReportRef>&		basicUniformReportsDst,
916e5c31af7Sopenharmony_ci																		 const glu::VarType&				varType,
917e5c31af7Sopenharmony_ci																		 const char*						varName,
918e5c31af7Sopenharmony_ci																		 bool								isParentActive,
919e5c31af7Sopenharmony_ci																		 int&								samplerUnitCounter,
920e5c31af7Sopenharmony_ci																		 Random&							rnd) const;
921e5c31af7Sopenharmony_ci
922e5c31af7Sopenharmony_ci	void						writeUniformDefinitions					(std::ostringstream& dst) const;
923e5c31af7Sopenharmony_ci	void						writeUniformCompareExpr					(std::ostringstream& dst, const BasicUniform& uniform) const;
924e5c31af7Sopenharmony_ci	void						writeUniformComparisons					(std::ostringstream& dst, const vector<BasicUniform>& basicUniforms, const char* variableName) const;
925e5c31af7Sopenharmony_ci
926e5c31af7Sopenharmony_ci	string						generateVertexSource					(const vector<BasicUniform>& basicUniforms) const;
927e5c31af7Sopenharmony_ci	string						generateFragmentSource					(const vector<BasicUniform>& basicUniforms) const;
928e5c31af7Sopenharmony_ci
929e5c31af7Sopenharmony_ci	void						setupTexture							(const VarValue& value);
930e5c31af7Sopenharmony_ci
931e5c31af7Sopenharmony_ci	const CaseShaderType						m_caseShaderType;
932e5c31af7Sopenharmony_ci
933e5c31af7Sopenharmony_ci	vector<glu::Texture2D*>						m_textures2d;
934e5c31af7Sopenharmony_ci	vector<glu::TextureCube*>					m_texturesCube;
935e5c31af7Sopenharmony_ci	vector<deUint32>							m_filledTextureUnits;
936e5c31af7Sopenharmony_ci};
937e5c31af7Sopenharmony_ci
938e5c31af7Sopenharmony_ciUniformCase::UniformCase (Context& context, const char* const name, const char* const description, const CaseShaderType caseShaderType, const SharedPtr<const UniformCollection>& uniformCollection, const deUint32 features)
939e5c31af7Sopenharmony_ci	: TestCase				(context, name, description)
940e5c31af7Sopenharmony_ci	, CallLogWrapper		(context.getRenderContext().getFunctions(), m_testCtx.getLog())
941e5c31af7Sopenharmony_ci	, m_features			(features)
942e5c31af7Sopenharmony_ci	, m_uniformCollection	(uniformCollection)
943e5c31af7Sopenharmony_ci	, m_caseShaderType		(caseShaderType)
944e5c31af7Sopenharmony_ci{
945e5c31af7Sopenharmony_ci}
946e5c31af7Sopenharmony_ci
947e5c31af7Sopenharmony_civoid UniformCase::init (void)
948e5c31af7Sopenharmony_ci{
949e5c31af7Sopenharmony_ci	{
950e5c31af7Sopenharmony_ci		const glw::Functions&	funcs						= m_context.getRenderContext().getFunctions();
951e5c31af7Sopenharmony_ci		const int				numSamplerUniforms			= m_uniformCollection->getNumSamplers();
952e5c31af7Sopenharmony_ci		const int				vertexTexUnitsRequired		= m_caseShaderType != CASESHADERTYPE_FRAGMENT ? numSamplerUniforms : 0;
953e5c31af7Sopenharmony_ci		const int				fragmentTexUnitsRequired	= m_caseShaderType != CASESHADERTYPE_VERTEX ? numSamplerUniforms : 0;
954e5c31af7Sopenharmony_ci		const int				combinedTexUnitsRequired	= vertexTexUnitsRequired + fragmentTexUnitsRequired;
955e5c31af7Sopenharmony_ci		const int				vertexTexUnitsSupported		= getGLInt(funcs, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
956e5c31af7Sopenharmony_ci		const int				fragmentTexUnitsSupported	= getGLInt(funcs, GL_MAX_TEXTURE_IMAGE_UNITS);
957e5c31af7Sopenharmony_ci		const int				combinedTexUnitsSupported	= getGLInt(funcs, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
958e5c31af7Sopenharmony_ci
959e5c31af7Sopenharmony_ci		DE_ASSERT(numSamplerUniforms <= MAX_NUM_SAMPLER_UNIFORMS);
960e5c31af7Sopenharmony_ci
961e5c31af7Sopenharmony_ci		if (vertexTexUnitsRequired > vertexTexUnitsSupported)
962e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError(de::toString(vertexTexUnitsRequired) + " vertex texture units required, " + de::toString(vertexTexUnitsSupported) + " supported");
963e5c31af7Sopenharmony_ci		if (fragmentTexUnitsRequired > fragmentTexUnitsSupported)
964e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError(de::toString(fragmentTexUnitsRequired) + " fragment texture units required, " + de::toString(fragmentTexUnitsSupported) + " supported");
965e5c31af7Sopenharmony_ci		if (combinedTexUnitsRequired > combinedTexUnitsSupported)
966e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError(de::toString(combinedTexUnitsRequired) + " combined texture units required, " + de::toString(combinedTexUnitsSupported) + " supported");
967e5c31af7Sopenharmony_ci	}
968e5c31af7Sopenharmony_ci
969e5c31af7Sopenharmony_ci	enableLogging(true);
970e5c31af7Sopenharmony_ci}
971e5c31af7Sopenharmony_ci
972e5c31af7Sopenharmony_civoid UniformCase::deinit (void)
973e5c31af7Sopenharmony_ci{
974e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)m_textures2d.size(); i++)
975e5c31af7Sopenharmony_ci		delete m_textures2d[i];
976e5c31af7Sopenharmony_ci	m_textures2d.clear();
977e5c31af7Sopenharmony_ci
978e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)m_texturesCube.size(); i++)
979e5c31af7Sopenharmony_ci		delete m_texturesCube[i];
980e5c31af7Sopenharmony_ci	m_texturesCube.clear();
981e5c31af7Sopenharmony_ci
982e5c31af7Sopenharmony_ci	m_filledTextureUnits.clear();
983e5c31af7Sopenharmony_ci}
984e5c31af7Sopenharmony_ci
985e5c31af7Sopenharmony_ciUniformCase::~UniformCase (void)
986e5c31af7Sopenharmony_ci{
987e5c31af7Sopenharmony_ci	UniformCase::deinit();
988e5c31af7Sopenharmony_ci}
989e5c31af7Sopenharmony_ci
990e5c31af7Sopenharmony_civoid UniformCase::generateBasicUniforms (vector<BasicUniform>& basicUniformsDst, vector<BasicUniformReportRef>& basicUniformReportsDst, const glu::VarType& varType, const char* const varName, const bool isParentActive, int& samplerUnitCounter, Random& rnd) const
991e5c31af7Sopenharmony_ci{
992e5c31af7Sopenharmony_ci	if (varType.isBasicType())
993e5c31af7Sopenharmony_ci	{
994e5c31af7Sopenharmony_ci		const bool				isActive	= isParentActive && (m_features & FEATURE_UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.size() % 2 == 0 : true);
995e5c31af7Sopenharmony_ci		const glu::DataType		type		= varType.getBasicType();
996e5c31af7Sopenharmony_ci		const VarValue			value		= glu::isDataTypeSampler(type) ? generateRandomVarValue(type, rnd, samplerUnitCounter++)
997e5c31af7Sopenharmony_ci																		   : generateRandomVarValue(varType.getBasicType(), rnd);
998e5c31af7Sopenharmony_ci
999e5c31af7Sopenharmony_ci		basicUniformsDst.push_back(BasicUniform(varName, varType.getBasicType(), isActive, value));
1000e5c31af7Sopenharmony_ci		basicUniformReportsDst.push_back(BasicUniformReportRef(varName, varType.getBasicType(), isActive));
1001e5c31af7Sopenharmony_ci	}
1002e5c31af7Sopenharmony_ci	else if (varType.isArrayType())
1003e5c31af7Sopenharmony_ci	{
1004e5c31af7Sopenharmony_ci		const int		size			= varType.getArraySize();
1005e5c31af7Sopenharmony_ci		const string	arrayRootName	= string("") + varName + "[0]";
1006e5c31af7Sopenharmony_ci		vector<bool>	isElemActive;
1007e5c31af7Sopenharmony_ci
1008e5c31af7Sopenharmony_ci		for (int elemNdx = 0; elemNdx < varType.getArraySize(); elemNdx++)
1009e5c31af7Sopenharmony_ci		{
1010e5c31af7Sopenharmony_ci			const string	indexedName		= string("") + varName + "[" + de::toString(elemNdx) + "]";
1011e5c31af7Sopenharmony_ci			const bool		isCurElemActive	= isParentActive																						&&
1012e5c31af7Sopenharmony_ci											  (m_features & FEATURE_UNIFORMUSAGE_EVERY_OTHER			? basicUniformsDst.size() % 2 == 0	: true)	&&
1013e5c31af7Sopenharmony_ci											  (m_features & FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX		? elemNdx == size/2					: true);
1014e5c31af7Sopenharmony_ci
1015e5c31af7Sopenharmony_ci			isElemActive.push_back(isCurElemActive);
1016e5c31af7Sopenharmony_ci
1017e5c31af7Sopenharmony_ci			if (varType.getElementType().isBasicType())
1018e5c31af7Sopenharmony_ci			{
1019e5c31af7Sopenharmony_ci				// \note We don't want separate entries in basicUniformReportsDst for elements of basic-type arrays.
1020e5c31af7Sopenharmony_ci				const glu::DataType	elemBasicType	= varType.getElementType().getBasicType();
1021e5c31af7Sopenharmony_ci				const VarValue		value			= glu::isDataTypeSampler(elemBasicType) ? generateRandomVarValue(elemBasicType, rnd, samplerUnitCounter++)
1022e5c31af7Sopenharmony_ci																							: generateRandomVarValue(elemBasicType, rnd);
1023e5c31af7Sopenharmony_ci
1024e5c31af7Sopenharmony_ci				basicUniformsDst.push_back(BasicUniform(indexedName.c_str(), elemBasicType, isCurElemActive, value, arrayRootName.c_str(), elemNdx, size));
1025e5c31af7Sopenharmony_ci			}
1026e5c31af7Sopenharmony_ci			else
1027e5c31af7Sopenharmony_ci				generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, varType.getElementType(), indexedName.c_str(), isCurElemActive, samplerUnitCounter, rnd);
1028e5c31af7Sopenharmony_ci		}
1029e5c31af7Sopenharmony_ci
1030e5c31af7Sopenharmony_ci		if (varType.getElementType().isBasicType())
1031e5c31af7Sopenharmony_ci		{
1032e5c31af7Sopenharmony_ci			int minSize;
1033e5c31af7Sopenharmony_ci			for (minSize = varType.getArraySize(); minSize > 0 && !isElemActive[minSize-1]; minSize--);
1034e5c31af7Sopenharmony_ci
1035e5c31af7Sopenharmony_ci			basicUniformReportsDst.push_back(BasicUniformReportRef(arrayRootName.c_str(), minSize, size, varType.getElementType().getBasicType(), isParentActive && minSize > 0));
1036e5c31af7Sopenharmony_ci		}
1037e5c31af7Sopenharmony_ci	}
1038e5c31af7Sopenharmony_ci	else
1039e5c31af7Sopenharmony_ci	{
1040e5c31af7Sopenharmony_ci		DE_ASSERT(varType.isStructType());
1041e5c31af7Sopenharmony_ci
1042e5c31af7Sopenharmony_ci		const StructType& structType = *varType.getStructPtr();
1043e5c31af7Sopenharmony_ci
1044e5c31af7Sopenharmony_ci		for (int i = 0; i < structType.getNumMembers(); i++)
1045e5c31af7Sopenharmony_ci		{
1046e5c31af7Sopenharmony_ci			const glu::StructMember&	member			= structType.getMember(i);
1047e5c31af7Sopenharmony_ci			const string				memberFullName	= string("") + varName + "." + member.getName();
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_ci			generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, member.getType(), memberFullName.c_str(), isParentActive, samplerUnitCounter, rnd);
1050e5c31af7Sopenharmony_ci		}
1051e5c31af7Sopenharmony_ci	}
1052e5c31af7Sopenharmony_ci}
1053e5c31af7Sopenharmony_ci
1054e5c31af7Sopenharmony_civoid UniformCase::writeUniformDefinitions (std::ostringstream& dst) const
1055e5c31af7Sopenharmony_ci{
1056e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)m_uniformCollection->getNumStructTypes(); i++)
1057e5c31af7Sopenharmony_ci		dst << glu::declare(m_uniformCollection->getStructType(i)) << ";\n";
1058e5c31af7Sopenharmony_ci
1059e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)m_uniformCollection->getNumUniforms(); i++)
1060e5c31af7Sopenharmony_ci		dst << "uniform " << glu::declare(m_uniformCollection->getUniform(i).type, m_uniformCollection->getUniform(i).name.c_str()) << ";\n";
1061e5c31af7Sopenharmony_ci
1062e5c31af7Sopenharmony_ci	dst << "\n";
1063e5c31af7Sopenharmony_ci
1064e5c31af7Sopenharmony_ci	{
1065e5c31af7Sopenharmony_ci		static const struct
1066e5c31af7Sopenharmony_ci		{
1067e5c31af7Sopenharmony_ci			dataTypePredicate	requiringTypes[2];
1068e5c31af7Sopenharmony_ci			const char*			definition;
1069e5c31af7Sopenharmony_ci		} compareFuncs[] =
1070e5c31af7Sopenharmony_ci		{
1071e5c31af7Sopenharmony_ci			{ { glu::isDataTypeFloatOrVec,				glu::isDataTypeMatrix				}, "mediump float compare_float    (mediump float a, mediump float b)  { return abs(a - b) < 0.05 ? 1.0 : 0.0; }"																		},
1072e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_VEC2>,	dataTypeIsMatrixWithNRows<2>		}, "mediump float compare_vec2     (mediump vec2 a, mediump vec2 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }"														},
1073e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_VEC3>,	dataTypeIsMatrixWithNRows<3>		}, "mediump float compare_vec3     (mediump vec3 a, mediump vec3 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }"								},
1074e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_VEC4>,	dataTypeIsMatrixWithNRows<4>		}, "mediump float compare_vec4     (mediump vec4 a, mediump vec4 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }"		},
1075e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT2>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat2     (mediump mat2 a, mediump mat2 b)    { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }"													},
1076e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT2X3>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat2x3   (mediump mat2x3 a, mediump mat2x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }"													},
1077e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT2X4>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat2x4   (mediump mat2x4 a, mediump mat2x4 b){ return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }"													},
1078e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT3X2>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat3x2   (mediump mat3x2 a, mediump mat3x2 b){ return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }"							},
1079e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT3>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat3     (mediump mat3 a, mediump mat3 b)    { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }"							},
1080e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT3X4>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat3x4   (mediump mat3x4 a, mediump mat3x4 b){ return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }"							},
1081e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT4X2>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat4x2   (mediump mat4x2 a, mediump mat4x2 b){ return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }"	},
1082e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT4X3>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat4x3   (mediump mat4x3 a, mediump mat4x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }"	},
1083e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_FLOAT_MAT4>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_mat4     (mediump mat4 a, mediump mat4 b)    { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }"	},
1084e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_INT>,			dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_int      (mediump int a, mediump int b)      { return a == b ? 1.0 : 0.0; }"																					},
1085e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_INT_VEC2>,		dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_ivec2    (mediump ivec2 a, mediump ivec2 b)  { return a == b ? 1.0 : 0.0; }"																					},
1086e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_INT_VEC3>,		dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_ivec3    (mediump ivec3 a, mediump ivec3 b)  { return a == b ? 1.0 : 0.0; }"																					},
1087e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_INT_VEC4>,		dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_ivec4    (mediump ivec4 a, mediump ivec4 b)  { return a == b ? 1.0 : 0.0; }"																					},
1088e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_UINT>,			dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_uint     (mediump uint a, mediump uint b)    { return a == b ? 1.0 : 0.0; }"																					},
1089e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_UINT_VEC2>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_uvec2    (mediump uvec2 a, mediump uvec2 b)  { return a == b ? 1.0 : 0.0; }"																					},
1090e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_UINT_VEC3>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_uvec3    (mediump uvec3 a, mediump uvec3 b)  { return a == b ? 1.0 : 0.0; }"																					},
1091e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_UINT_VEC4>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_uvec4    (mediump uvec4 a, mediump uvec4 b)  { return a == b ? 1.0 : 0.0; }"																					},
1092e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_BOOL>,			dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_bool     (bool a, bool b)                    { return a == b ? 1.0 : 0.0; }"																					},
1093e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_BOOL_VEC2>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_bvec2    (bvec2 a, bvec2 b)                  { return a == b ? 1.0 : 0.0; }"																					},
1094e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_BOOL_VEC3>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_bvec3    (bvec3 a, bvec3 b)                  { return a == b ? 1.0 : 0.0; }"																					},
1095e5c31af7Sopenharmony_ci			{ { dataTypeEquals<glu::TYPE_BOOL_VEC4>,	dataTypeEquals<glu::TYPE_INVALID>	}, "mediump float compare_bvec4    (bvec4 a, bvec4 b)                  { return a == b ? 1.0 : 0.0; }"																					}
1096e5c31af7Sopenharmony_ci		};
1097e5c31af7Sopenharmony_ci
1098e5c31af7Sopenharmony_ci		const vector<glu::DataType> samplerTypes = m_uniformCollection->getSamplerTypes();
1099e5c31af7Sopenharmony_ci
1100e5c31af7Sopenharmony_ci		for (int compFuncNdx = 0; compFuncNdx < DE_LENGTH_OF_ARRAY(compareFuncs); compFuncNdx++)
1101e5c31af7Sopenharmony_ci		{
1102e5c31af7Sopenharmony_ci			const dataTypePredicate		(&typeReq)[2]			= compareFuncs[compFuncNdx].requiringTypes;
1103e5c31af7Sopenharmony_ci			bool						containsTypeSampler		= false;
1104e5c31af7Sopenharmony_ci
1105e5c31af7Sopenharmony_ci			for (int i = 0; i < (int)samplerTypes.size(); i++)
1106e5c31af7Sopenharmony_ci			{
1107e5c31af7Sopenharmony_ci				if (glu::isDataTypeSampler(samplerTypes[i]))
1108e5c31af7Sopenharmony_ci				{
1109e5c31af7Sopenharmony_ci					const glu::DataType retType = getSamplerLookupReturnType(samplerTypes[i]);
1110e5c31af7Sopenharmony_ci					if (typeReq[0](retType) || typeReq[1](retType))
1111e5c31af7Sopenharmony_ci					{
1112e5c31af7Sopenharmony_ci						containsTypeSampler = true;
1113e5c31af7Sopenharmony_ci						break;
1114e5c31af7Sopenharmony_ci					}
1115e5c31af7Sopenharmony_ci				}
1116e5c31af7Sopenharmony_ci			}
1117e5c31af7Sopenharmony_ci
1118e5c31af7Sopenharmony_ci			if (containsTypeSampler || m_uniformCollection->containsMatchingBasicType(typeReq[0]) || m_uniformCollection->containsMatchingBasicType(typeReq[1]))
1119e5c31af7Sopenharmony_ci				dst << compareFuncs[compFuncNdx].definition << "\n";
1120e5c31af7Sopenharmony_ci		}
1121e5c31af7Sopenharmony_ci	}
1122e5c31af7Sopenharmony_ci}
1123e5c31af7Sopenharmony_ci
1124e5c31af7Sopenharmony_civoid UniformCase::writeUniformCompareExpr (std::ostringstream& dst, const BasicUniform& uniform) const
1125e5c31af7Sopenharmony_ci{
1126e5c31af7Sopenharmony_ci	if (glu::isDataTypeSampler(uniform.type))
1127e5c31af7Sopenharmony_ci		dst << "compare_" << glu::getDataTypeName(getSamplerLookupReturnType(uniform.type)) << "(texture(" << uniform.name << ", vec" << getSamplerNumLookupDimensions(uniform.type) << "(0.0))";
1128e5c31af7Sopenharmony_ci	else
1129e5c31af7Sopenharmony_ci		dst << "compare_" << glu::getDataTypeName(uniform.type) << "(" << uniform.name;
1130e5c31af7Sopenharmony_ci
1131e5c31af7Sopenharmony_ci	dst << ", " << shaderVarValueStr(uniform.finalValue) << ")";
1132e5c31af7Sopenharmony_ci}
1133e5c31af7Sopenharmony_ci
1134e5c31af7Sopenharmony_civoid UniformCase::writeUniformComparisons (std::ostringstream& dst, const vector<BasicUniform>& basicUniforms, const char* const variableName) const
1135e5c31af7Sopenharmony_ci{
1136e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)basicUniforms.size(); i++)
1137e5c31af7Sopenharmony_ci	{
1138e5c31af7Sopenharmony_ci		const BasicUniform& unif = basicUniforms[i];
1139e5c31af7Sopenharmony_ci
1140e5c31af7Sopenharmony_ci		if (unif.isUsedInShader)
1141e5c31af7Sopenharmony_ci		{
1142e5c31af7Sopenharmony_ci			dst << "\t" << variableName << " *= ";
1143e5c31af7Sopenharmony_ci			writeUniformCompareExpr(dst, basicUniforms[i]);
1144e5c31af7Sopenharmony_ci			dst << ";\n";
1145e5c31af7Sopenharmony_ci		}
1146e5c31af7Sopenharmony_ci		else
1147e5c31af7Sopenharmony_ci			dst << "\t// UNUSED: " << basicUniforms[i].name << "\n";
1148e5c31af7Sopenharmony_ci	}
1149e5c31af7Sopenharmony_ci}
1150e5c31af7Sopenharmony_ci
1151e5c31af7Sopenharmony_cistring UniformCase::generateVertexSource (const vector<BasicUniform>& basicUniforms) const
1152e5c31af7Sopenharmony_ci{
1153e5c31af7Sopenharmony_ci	const bool			isVertexCase = m_caseShaderType == CASESHADERTYPE_VERTEX || m_caseShaderType == CASESHADERTYPE_BOTH;
1154e5c31af7Sopenharmony_ci	std::ostringstream	result;
1155e5c31af7Sopenharmony_ci
1156e5c31af7Sopenharmony_ci	result << "#version 310 es\n"
1157e5c31af7Sopenharmony_ci			  "in highp vec4 a_position;\n"
1158e5c31af7Sopenharmony_ci			  "out mediump float v_vtxOut;\n"
1159e5c31af7Sopenharmony_ci			  "\n";
1160e5c31af7Sopenharmony_ci
1161e5c31af7Sopenharmony_ci	if (isVertexCase)
1162e5c31af7Sopenharmony_ci		writeUniformDefinitions(result);
1163e5c31af7Sopenharmony_ci
1164e5c31af7Sopenharmony_ci	result << "\n"
1165e5c31af7Sopenharmony_ci			  "void main (void)\n"
1166e5c31af7Sopenharmony_ci			  "{\n"
1167e5c31af7Sopenharmony_ci			  "	gl_Position = a_position;\n"
1168e5c31af7Sopenharmony_ci			  "	v_vtxOut = 1.0;\n";
1169e5c31af7Sopenharmony_ci
1170e5c31af7Sopenharmony_ci	if (isVertexCase)
1171e5c31af7Sopenharmony_ci		writeUniformComparisons(result, basicUniforms, "v_vtxOut");
1172e5c31af7Sopenharmony_ci
1173e5c31af7Sopenharmony_ci	result << "}\n";
1174e5c31af7Sopenharmony_ci
1175e5c31af7Sopenharmony_ci	return result.str();
1176e5c31af7Sopenharmony_ci}
1177e5c31af7Sopenharmony_ci
1178e5c31af7Sopenharmony_cistring UniformCase::generateFragmentSource (const vector<BasicUniform>& basicUniforms) const
1179e5c31af7Sopenharmony_ci{
1180e5c31af7Sopenharmony_ci	const bool			isFragmentCase = m_caseShaderType == CASESHADERTYPE_FRAGMENT || m_caseShaderType == CASESHADERTYPE_BOTH;
1181e5c31af7Sopenharmony_ci	std::ostringstream	result;
1182e5c31af7Sopenharmony_ci
1183e5c31af7Sopenharmony_ci	result << "#version 310 es\n"
1184e5c31af7Sopenharmony_ci			  "in mediump float v_vtxOut;\n"
1185e5c31af7Sopenharmony_ci			  "\n";
1186e5c31af7Sopenharmony_ci
1187e5c31af7Sopenharmony_ci	if (isFragmentCase)
1188e5c31af7Sopenharmony_ci		writeUniformDefinitions(result);
1189e5c31af7Sopenharmony_ci
1190e5c31af7Sopenharmony_ci	result << "\n"
1191e5c31af7Sopenharmony_ci			  "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1192e5c31af7Sopenharmony_ci			  "\n"
1193e5c31af7Sopenharmony_ci			  "void main (void)\n"
1194e5c31af7Sopenharmony_ci			  "{\n"
1195e5c31af7Sopenharmony_ci			  "	mediump float result = v_vtxOut;\n";
1196e5c31af7Sopenharmony_ci
1197e5c31af7Sopenharmony_ci	if (isFragmentCase)
1198e5c31af7Sopenharmony_ci		writeUniformComparisons(result, basicUniforms, "result");
1199e5c31af7Sopenharmony_ci
1200e5c31af7Sopenharmony_ci	result << "	dEQP_FragColor = vec4(1.0-result, result, 0.0, 1.0);\n"
1201e5c31af7Sopenharmony_ci			  "}\n";
1202e5c31af7Sopenharmony_ci
1203e5c31af7Sopenharmony_ci	return result.str();
1204e5c31af7Sopenharmony_ci}
1205e5c31af7Sopenharmony_ci
1206e5c31af7Sopenharmony_civoid UniformCase::setupTexture (const VarValue& value)
1207e5c31af7Sopenharmony_ci{
1208e5c31af7Sopenharmony_ci	// \note No handling for samplers other than 2D or cube.
1209e5c31af7Sopenharmony_ci
1210e5c31af7Sopenharmony_ci	enableLogging(false);
1211e5c31af7Sopenharmony_ci
1212e5c31af7Sopenharmony_ci	DE_ASSERT(getSamplerLookupReturnType(value.type) == glu::TYPE_FLOAT_VEC4);
1213e5c31af7Sopenharmony_ci
1214e5c31af7Sopenharmony_ci	const int						width			= 32;
1215e5c31af7Sopenharmony_ci	const int						height			= 32;
1216e5c31af7Sopenharmony_ci	const tcu::Vec4					color			= vec4FromPtr(&value.val.samplerV.fillColor.floatV[0]);
1217e5c31af7Sopenharmony_ci
1218e5c31af7Sopenharmony_ci	if (value.type == glu::TYPE_SAMPLER_2D)
1219e5c31af7Sopenharmony_ci	{
1220e5c31af7Sopenharmony_ci		glu::Texture2D* texture		= new glu::Texture2D(m_context.getRenderContext(), GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1221e5c31af7Sopenharmony_ci		tcu::Texture2D& refTexture	= texture->getRefTexture();
1222e5c31af7Sopenharmony_ci		m_textures2d.push_back(texture);
1223e5c31af7Sopenharmony_ci
1224e5c31af7Sopenharmony_ci		refTexture.allocLevel(0);
1225e5c31af7Sopenharmony_ci		fillWithColor(refTexture.getLevel(0), color);
1226e5c31af7Sopenharmony_ci
1227e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0 + value.val.samplerV.unit));
1228e5c31af7Sopenharmony_ci		m_filledTextureUnits.push_back(value.val.samplerV.unit);
1229e5c31af7Sopenharmony_ci		texture->upload();
1230e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1231e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1232e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
1233e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
1234e5c31af7Sopenharmony_ci	}
1235e5c31af7Sopenharmony_ci	else if (value.type == glu::TYPE_SAMPLER_CUBE)
1236e5c31af7Sopenharmony_ci	{
1237e5c31af7Sopenharmony_ci		DE_STATIC_ASSERT(width == height);
1238e5c31af7Sopenharmony_ci		glu::TextureCube* texture		= new glu::TextureCube(m_context.getRenderContext(), GL_RGBA, GL_UNSIGNED_BYTE, width);
1239e5c31af7Sopenharmony_ci		tcu::TextureCube& refTexture	= texture->getRefTexture();
1240e5c31af7Sopenharmony_ci		m_texturesCube.push_back(texture);
1241e5c31af7Sopenharmony_ci
1242e5c31af7Sopenharmony_ci		for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++)
1243e5c31af7Sopenharmony_ci		{
1244e5c31af7Sopenharmony_ci			refTexture.allocLevel((tcu::CubeFace)face, 0);
1245e5c31af7Sopenharmony_ci			fillWithColor(refTexture.getLevelFace(0, (tcu::CubeFace)face), color);
1246e5c31af7Sopenharmony_ci		}
1247e5c31af7Sopenharmony_ci
1248e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0 + value.val.samplerV.unit));
1249e5c31af7Sopenharmony_ci		m_filledTextureUnits.push_back(value.val.samplerV.unit);
1250e5c31af7Sopenharmony_ci		texture->upload();
1251e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1252e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1253e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
1254e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
1255e5c31af7Sopenharmony_ci
1256e5c31af7Sopenharmony_ci	}
1257e5c31af7Sopenharmony_ci	else
1258e5c31af7Sopenharmony_ci		DE_ASSERT(false);
1259e5c31af7Sopenharmony_ci
1260e5c31af7Sopenharmony_ci	enableLogging(true);
1261e5c31af7Sopenharmony_ci}
1262e5c31af7Sopenharmony_ci
1263e5c31af7Sopenharmony_cibool UniformCase::getUniforms (vector<VarValue>& valuesDst, const vector<BasicUniform>& basicUniforms, const deUint32 programGL)
1264e5c31af7Sopenharmony_ci{
1265e5c31af7Sopenharmony_ci	TestLog&	log			= m_testCtx.getLog();
1266e5c31af7Sopenharmony_ci	bool		success		= true;
1267e5c31af7Sopenharmony_ci
1268e5c31af7Sopenharmony_ci	for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++)
1269e5c31af7Sopenharmony_ci	{
1270e5c31af7Sopenharmony_ci		const BasicUniform&		uniform		= basicUniforms[unifNdx];
1271e5c31af7Sopenharmony_ci		const string			queryName	= m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? beforeLast(uniform.name, '[') : uniform.name;
1272e5c31af7Sopenharmony_ci		const int				location	= glGetUniformLocation(programGL, queryName.c_str());
1273e5c31af7Sopenharmony_ci		const int				size		= glu::getDataTypeScalarSize(uniform.type);
1274e5c31af7Sopenharmony_ci		VarValue				value;
1275e5c31af7Sopenharmony_ci
1276e5c31af7Sopenharmony_ci		deMemset(&value, 0xcd, sizeof(value)); // Initialize to known garbage.
1277e5c31af7Sopenharmony_ci
1278e5c31af7Sopenharmony_ci		if (location == -1)
1279e5c31af7Sopenharmony_ci		{
1280e5c31af7Sopenharmony_ci			value.type = glu::TYPE_INVALID;
1281e5c31af7Sopenharmony_ci			valuesDst.push_back(value);
1282e5c31af7Sopenharmony_ci			if (uniform.isUsedInShader)
1283e5c31af7Sopenharmony_ci			{
1284e5c31af7Sopenharmony_ci				log << TestLog::Message << "// FAILURE: " << uniform.name << " was used in shader, but has location -1" << TestLog::EndMessage;
1285e5c31af7Sopenharmony_ci				success = false;
1286e5c31af7Sopenharmony_ci			}
1287e5c31af7Sopenharmony_ci			continue;
1288e5c31af7Sopenharmony_ci		}
1289e5c31af7Sopenharmony_ci
1290e5c31af7Sopenharmony_ci		value.type = uniform.type;
1291e5c31af7Sopenharmony_ci
1292e5c31af7Sopenharmony_ci		DE_STATIC_ASSERT(sizeof(GLint) == sizeof(value.val.intV[0]));
1293e5c31af7Sopenharmony_ci		DE_STATIC_ASSERT(sizeof(GLuint) == sizeof(value.val.uintV[0]));
1294e5c31af7Sopenharmony_ci		DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(value.val.floatV[0]));
1295e5c31af7Sopenharmony_ci
1296e5c31af7Sopenharmony_ci		if (glu::isDataTypeFloatOrVec(uniform.type) || glu::isDataTypeMatrix(uniform.type))
1297e5c31af7Sopenharmony_ci			GLU_CHECK_CALL(glGetUniformfv(programGL, location, &value.val.floatV[0]));
1298e5c31af7Sopenharmony_ci		else if (glu::isDataTypeIntOrIVec(uniform.type))
1299e5c31af7Sopenharmony_ci			GLU_CHECK_CALL(glGetUniformiv(programGL, location, &value.val.intV[0]));
1300e5c31af7Sopenharmony_ci		else if (glu::isDataTypeUintOrUVec(uniform.type))
1301e5c31af7Sopenharmony_ci			GLU_CHECK_CALL(glGetUniformuiv(programGL, location, &value.val.uintV[0]));
1302e5c31af7Sopenharmony_ci		else if (glu::isDataTypeBoolOrBVec(uniform.type))
1303e5c31af7Sopenharmony_ci		{
1304e5c31af7Sopenharmony_ci			if (m_features & FEATURE_BOOLEANAPITYPE_INT)
1305e5c31af7Sopenharmony_ci			{
1306e5c31af7Sopenharmony_ci				GLU_CHECK_CALL(glGetUniformiv(programGL, location, &value.val.intV[0]));
1307e5c31af7Sopenharmony_ci				for (int i = 0; i < size; i++)
1308e5c31af7Sopenharmony_ci					value.val.boolV[i] = value.val.intV[i] != 0;
1309e5c31af7Sopenharmony_ci			}
1310e5c31af7Sopenharmony_ci			else if (m_features & FEATURE_BOOLEANAPITYPE_UINT)
1311e5c31af7Sopenharmony_ci			{
1312e5c31af7Sopenharmony_ci				GLU_CHECK_CALL(glGetUniformuiv(programGL, location, &value.val.uintV[0]));
1313e5c31af7Sopenharmony_ci				for (int i = 0; i < size; i++)
1314e5c31af7Sopenharmony_ci					value.val.boolV[i] = value.val.uintV[i] != 0;
1315e5c31af7Sopenharmony_ci			}
1316e5c31af7Sopenharmony_ci			else // Default: use float.
1317e5c31af7Sopenharmony_ci			{
1318e5c31af7Sopenharmony_ci				GLU_CHECK_CALL(glGetUniformfv(programGL, location, &value.val.floatV[0]));
1319e5c31af7Sopenharmony_ci				for (int i = 0; i < size; i++)
1320e5c31af7Sopenharmony_ci					value.val.boolV[i] = value.val.floatV[i] != 0.0f;
1321e5c31af7Sopenharmony_ci			}
1322e5c31af7Sopenharmony_ci		}
1323e5c31af7Sopenharmony_ci		else if (glu::isDataTypeSampler(uniform.type))
1324e5c31af7Sopenharmony_ci		{
1325e5c31af7Sopenharmony_ci			GLint unit = -1;
1326e5c31af7Sopenharmony_ci			GLU_CHECK_CALL(glGetUniformiv(programGL, location, &unit));
1327e5c31af7Sopenharmony_ci			value.val.samplerV.unit = unit;
1328e5c31af7Sopenharmony_ci		}
1329e5c31af7Sopenharmony_ci		else
1330e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1331e5c31af7Sopenharmony_ci
1332e5c31af7Sopenharmony_ci		valuesDst.push_back(value);
1333e5c31af7Sopenharmony_ci
1334e5c31af7Sopenharmony_ci		log << TestLog::Message << "// Got " << uniform.name << " value " << apiVarValueStr(value) << TestLog::EndMessage;
1335e5c31af7Sopenharmony_ci	}
1336e5c31af7Sopenharmony_ci
1337e5c31af7Sopenharmony_ci	return success;
1338e5c31af7Sopenharmony_ci}
1339e5c31af7Sopenharmony_ci
1340e5c31af7Sopenharmony_civoid UniformCase::assignUniforms (const vector<BasicUniform>& basicUniforms, deUint32 programGL, Random& rnd)
1341e5c31af7Sopenharmony_ci{
1342e5c31af7Sopenharmony_ci	TestLog&				log				= m_testCtx.getLog();
1343e5c31af7Sopenharmony_ci	const bool				transpose		= (m_features & FEATURE_MATRIXMODE_ROWMAJOR) != 0;
1344e5c31af7Sopenharmony_ci	const GLboolean			transposeGL		= transpose ? GL_TRUE : GL_FALSE;
1345e5c31af7Sopenharmony_ci	const glu::DataType		boolApiType		= m_features & FEATURE_BOOLEANAPITYPE_INT	? glu::TYPE_INT
1346e5c31af7Sopenharmony_ci											: m_features & FEATURE_BOOLEANAPITYPE_UINT	? glu::TYPE_UINT
1347e5c31af7Sopenharmony_ci											:											  glu::TYPE_FLOAT;
1348e5c31af7Sopenharmony_ci
1349e5c31af7Sopenharmony_ci	for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++)
1350e5c31af7Sopenharmony_ci	{
1351e5c31af7Sopenharmony_ci		const BasicUniform&		uniform				= basicUniforms[unifNdx];
1352e5c31af7Sopenharmony_ci		const bool				isArrayMember		= uniform.elemNdx >= 0;
1353e5c31af7Sopenharmony_ci		const string			queryName			= m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? beforeLast(uniform.name, '[') : uniform.name;
1354e5c31af7Sopenharmony_ci		const int				numValuesToAssign	= !isArrayMember									? 1
1355e5c31af7Sopenharmony_ci													: m_features & FEATURE_ARRAYASSIGN_FULL				? (uniform.elemNdx == 0			? uniform.rootSize	: 0)
1356e5c31af7Sopenharmony_ci													: m_features & FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO	? (uniform.elemNdx % 2 == 0		? 2					: 0)
1357e5c31af7Sopenharmony_ci													: /* Default: assign array elements separately */	  1;
1358e5c31af7Sopenharmony_ci
1359e5c31af7Sopenharmony_ci		DE_ASSERT(numValuesToAssign >= 0);
1360e5c31af7Sopenharmony_ci		DE_ASSERT(numValuesToAssign == 1 || isArrayMember);
1361e5c31af7Sopenharmony_ci
1362e5c31af7Sopenharmony_ci		if (numValuesToAssign == 0)
1363e5c31af7Sopenharmony_ci		{
1364e5c31af7Sopenharmony_ci			log << TestLog::Message << "// Uniform " << uniform.name << " is covered by another glProgramUniform*v() call to the same array" << TestLog::EndMessage;
1365e5c31af7Sopenharmony_ci			continue;
1366e5c31af7Sopenharmony_ci		}
1367e5c31af7Sopenharmony_ci
1368e5c31af7Sopenharmony_ci		const int			location			= glGetUniformLocation(programGL, queryName.c_str());
1369e5c31af7Sopenharmony_ci		const int			typeSize			= glu::getDataTypeScalarSize(uniform.type);
1370e5c31af7Sopenharmony_ci		const bool			assignByValue		= m_features & FEATURE_UNIFORMFUNC_VALUE && !glu::isDataTypeMatrix(uniform.type) && numValuesToAssign == 1;
1371e5c31af7Sopenharmony_ci		vector<VarValue>	valuesToAssign;
1372e5c31af7Sopenharmony_ci
1373e5c31af7Sopenharmony_ci		for (int i = 0; i < numValuesToAssign; i++)
1374e5c31af7Sopenharmony_ci		{
1375e5c31af7Sopenharmony_ci			const string	curName = isArrayMember ? beforeLast(uniform.rootName, '[') + "[" + de::toString(uniform.elemNdx+i) + "]" : uniform.name;
1376e5c31af7Sopenharmony_ci			VarValue		unifValue;
1377e5c31af7Sopenharmony_ci
1378e5c31af7Sopenharmony_ci			if (isArrayMember)
1379e5c31af7Sopenharmony_ci			{
1380e5c31af7Sopenharmony_ci				const vector<BasicUniform>::const_iterator elemUnif = BasicUniform::findWithName(basicUniforms, curName.c_str());
1381e5c31af7Sopenharmony_ci				if (elemUnif == basicUniforms.end())
1382e5c31af7Sopenharmony_ci					continue;
1383e5c31af7Sopenharmony_ci				unifValue = elemUnif->finalValue;
1384e5c31af7Sopenharmony_ci			}
1385e5c31af7Sopenharmony_ci			else
1386e5c31af7Sopenharmony_ci				unifValue = uniform.finalValue;
1387e5c31af7Sopenharmony_ci
1388e5c31af7Sopenharmony_ci			const VarValue apiValue = glu::isDataTypeBoolOrBVec(unifValue.type)	? getRandomBoolRepresentation(unifValue, boolApiType, rnd)
1389e5c31af7Sopenharmony_ci									: glu::isDataTypeSampler(unifValue.type)	? getSamplerUnitValue(unifValue)
1390e5c31af7Sopenharmony_ci									: unifValue;
1391e5c31af7Sopenharmony_ci
1392e5c31af7Sopenharmony_ci			valuesToAssign.push_back(glu::isDataTypeMatrix(apiValue.type) && transpose ? getTransposeMatrix(apiValue) : apiValue);
1393e5c31af7Sopenharmony_ci
1394e5c31af7Sopenharmony_ci			if (glu::isDataTypeBoolOrBVec(uniform.type))
1395e5c31af7Sopenharmony_ci				log << TestLog::Message << "// Using type " << glu::getDataTypeName(boolApiType) << " to set boolean value " << apiVarValueStr(unifValue) << " for " << curName << TestLog::EndMessage;
1396e5c31af7Sopenharmony_ci			else if (glu::isDataTypeSampler(uniform.type))
1397e5c31af7Sopenharmony_ci				log << TestLog::Message << "// Texture for the sampler uniform " << curName << " will be filled with color " << apiVarValueStr(getSamplerFillValue(uniform.finalValue)) << TestLog::EndMessage;
1398e5c31af7Sopenharmony_ci		}
1399e5c31af7Sopenharmony_ci
1400e5c31af7Sopenharmony_ci		DE_ASSERT(!valuesToAssign.empty());
1401e5c31af7Sopenharmony_ci
1402e5c31af7Sopenharmony_ci		if (glu::isDataTypeFloatOrVec(valuesToAssign[0].type))
1403e5c31af7Sopenharmony_ci		{
1404e5c31af7Sopenharmony_ci			if (assignByValue)
1405e5c31af7Sopenharmony_ci			{
1406e5c31af7Sopenharmony_ci				const float* const ptr = &valuesToAssign[0].val.floatV[0];
1407e5c31af7Sopenharmony_ci
1408e5c31af7Sopenharmony_ci				switch (typeSize)
1409e5c31af7Sopenharmony_ci				{
1410e5c31af7Sopenharmony_ci					case 1: GLU_CHECK_CALL(glProgramUniform1f(programGL, location, ptr[0]));							break;
1411e5c31af7Sopenharmony_ci					case 2: GLU_CHECK_CALL(glProgramUniform2f(programGL, location, ptr[0], ptr[1]));					break;
1412e5c31af7Sopenharmony_ci					case 3: GLU_CHECK_CALL(glProgramUniform3f(programGL, location, ptr[0], ptr[1], ptr[2]));			break;
1413e5c31af7Sopenharmony_ci					case 4: GLU_CHECK_CALL(glProgramUniform4f(programGL, location, ptr[0], ptr[1], ptr[2], ptr[3]));	break;
1414e5c31af7Sopenharmony_ci					default:
1415e5c31af7Sopenharmony_ci						DE_ASSERT(false);
1416e5c31af7Sopenharmony_ci				}
1417e5c31af7Sopenharmony_ci			}
1418e5c31af7Sopenharmony_ci			else
1419e5c31af7Sopenharmony_ci			{
1420e5c31af7Sopenharmony_ci				vector<float> buffer(valuesToAssign.size() * typeSize);
1421e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)buffer.size(); i++)
1422e5c31af7Sopenharmony_ci					buffer[i] = valuesToAssign[i / typeSize].val.floatV[i % typeSize];
1423e5c31af7Sopenharmony_ci
1424e5c31af7Sopenharmony_ci				DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(buffer[0]));
1425e5c31af7Sopenharmony_ci				switch (typeSize)
1426e5c31af7Sopenharmony_ci				{
1427e5c31af7Sopenharmony_ci					case 1: GLU_CHECK_CALL(glProgramUniform1fv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1428e5c31af7Sopenharmony_ci					case 2: GLU_CHECK_CALL(glProgramUniform2fv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1429e5c31af7Sopenharmony_ci					case 3: GLU_CHECK_CALL(glProgramUniform3fv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1430e5c31af7Sopenharmony_ci					case 4: GLU_CHECK_CALL(glProgramUniform4fv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1431e5c31af7Sopenharmony_ci					default:
1432e5c31af7Sopenharmony_ci						DE_ASSERT(false);
1433e5c31af7Sopenharmony_ci				}
1434e5c31af7Sopenharmony_ci			}
1435e5c31af7Sopenharmony_ci		}
1436e5c31af7Sopenharmony_ci		else if (glu::isDataTypeMatrix(valuesToAssign[0].type))
1437e5c31af7Sopenharmony_ci		{
1438e5c31af7Sopenharmony_ci			DE_ASSERT(!assignByValue);
1439e5c31af7Sopenharmony_ci
1440e5c31af7Sopenharmony_ci			vector<float> buffer(valuesToAssign.size() * typeSize);
1441e5c31af7Sopenharmony_ci			for (int i = 0; i < (int)buffer.size(); i++)
1442e5c31af7Sopenharmony_ci				buffer[i] = valuesToAssign[i / typeSize].val.floatV[i % typeSize];
1443e5c31af7Sopenharmony_ci
1444e5c31af7Sopenharmony_ci			DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(buffer[0]));
1445e5c31af7Sopenharmony_ci			switch (uniform.type)
1446e5c31af7Sopenharmony_ci			{
1447e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT2:		GLU_CHECK_CALL(glProgramUniformMatrix2fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1448e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT3:		GLU_CHECK_CALL(glProgramUniformMatrix3fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1449e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT4:		GLU_CHECK_CALL(glProgramUniformMatrix4fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1450e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT2X3:	GLU_CHECK_CALL(glProgramUniformMatrix2x3fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1451e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT2X4:	GLU_CHECK_CALL(glProgramUniformMatrix2x4fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1452e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT3X2:	GLU_CHECK_CALL(glProgramUniformMatrix3x2fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1453e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT3X4:	GLU_CHECK_CALL(glProgramUniformMatrix3x4fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1454e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT4X2:	GLU_CHECK_CALL(glProgramUniformMatrix4x2fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1455e5c31af7Sopenharmony_ci				case glu::TYPE_FLOAT_MAT4X3:	GLU_CHECK_CALL(glProgramUniformMatrix4x3fv	(programGL, location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1456e5c31af7Sopenharmony_ci				default:
1457e5c31af7Sopenharmony_ci					DE_ASSERT(false);
1458e5c31af7Sopenharmony_ci			}
1459e5c31af7Sopenharmony_ci		}
1460e5c31af7Sopenharmony_ci		else if (glu::isDataTypeIntOrIVec(valuesToAssign[0].type))
1461e5c31af7Sopenharmony_ci		{
1462e5c31af7Sopenharmony_ci			if (assignByValue)
1463e5c31af7Sopenharmony_ci			{
1464e5c31af7Sopenharmony_ci				const deInt32* const ptr = &valuesToAssign[0].val.intV[0];
1465e5c31af7Sopenharmony_ci
1466e5c31af7Sopenharmony_ci				switch (typeSize)
1467e5c31af7Sopenharmony_ci				{
1468e5c31af7Sopenharmony_ci					case 1: GLU_CHECK_CALL(glProgramUniform1i(programGL, location, ptr[0]));							break;
1469e5c31af7Sopenharmony_ci					case 2: GLU_CHECK_CALL(glProgramUniform2i(programGL, location, ptr[0], ptr[1]));					break;
1470e5c31af7Sopenharmony_ci					case 3: GLU_CHECK_CALL(glProgramUniform3i(programGL, location, ptr[0], ptr[1], ptr[2]));			break;
1471e5c31af7Sopenharmony_ci					case 4: GLU_CHECK_CALL(glProgramUniform4i(programGL, location, ptr[0], ptr[1], ptr[2], ptr[3]));	break;
1472e5c31af7Sopenharmony_ci					default:
1473e5c31af7Sopenharmony_ci						DE_ASSERT(false);
1474e5c31af7Sopenharmony_ci				}
1475e5c31af7Sopenharmony_ci			}
1476e5c31af7Sopenharmony_ci			else
1477e5c31af7Sopenharmony_ci			{
1478e5c31af7Sopenharmony_ci				vector<deInt32> buffer(valuesToAssign.size() * typeSize);
1479e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)buffer.size(); i++)
1480e5c31af7Sopenharmony_ci					buffer[i] = valuesToAssign[i / typeSize].val.intV[i % typeSize];
1481e5c31af7Sopenharmony_ci
1482e5c31af7Sopenharmony_ci				DE_STATIC_ASSERT(sizeof(GLint) == sizeof(buffer[0]));
1483e5c31af7Sopenharmony_ci				switch (typeSize)
1484e5c31af7Sopenharmony_ci				{
1485e5c31af7Sopenharmony_ci					case 1: GLU_CHECK_CALL(glProgramUniform1iv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1486e5c31af7Sopenharmony_ci					case 2: GLU_CHECK_CALL(glProgramUniform2iv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1487e5c31af7Sopenharmony_ci					case 3: GLU_CHECK_CALL(glProgramUniform3iv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1488e5c31af7Sopenharmony_ci					case 4: GLU_CHECK_CALL(glProgramUniform4iv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1489e5c31af7Sopenharmony_ci					default:
1490e5c31af7Sopenharmony_ci						DE_ASSERT(false);
1491e5c31af7Sopenharmony_ci				}
1492e5c31af7Sopenharmony_ci			}
1493e5c31af7Sopenharmony_ci		}
1494e5c31af7Sopenharmony_ci		else if (glu::isDataTypeUintOrUVec(valuesToAssign[0].type))
1495e5c31af7Sopenharmony_ci		{
1496e5c31af7Sopenharmony_ci			if (assignByValue)
1497e5c31af7Sopenharmony_ci			{
1498e5c31af7Sopenharmony_ci				const deUint32* const ptr = &valuesToAssign[0].val.uintV[0];
1499e5c31af7Sopenharmony_ci
1500e5c31af7Sopenharmony_ci				switch (typeSize)
1501e5c31af7Sopenharmony_ci				{
1502e5c31af7Sopenharmony_ci					case 1: GLU_CHECK_CALL(glProgramUniform1ui(programGL, location, ptr[0]));							break;
1503e5c31af7Sopenharmony_ci					case 2: GLU_CHECK_CALL(glProgramUniform2ui(programGL, location, ptr[0], ptr[1]));					break;
1504e5c31af7Sopenharmony_ci					case 3: GLU_CHECK_CALL(glProgramUniform3ui(programGL, location, ptr[0], ptr[1], ptr[2]));			break;
1505e5c31af7Sopenharmony_ci					case 4: GLU_CHECK_CALL(glProgramUniform4ui(programGL, location, ptr[0], ptr[1], ptr[2], ptr[3]));	break;
1506e5c31af7Sopenharmony_ci					default:
1507e5c31af7Sopenharmony_ci						DE_ASSERT(false);
1508e5c31af7Sopenharmony_ci				}
1509e5c31af7Sopenharmony_ci			}
1510e5c31af7Sopenharmony_ci			else
1511e5c31af7Sopenharmony_ci			{
1512e5c31af7Sopenharmony_ci				vector<deUint32> buffer(valuesToAssign.size() * typeSize);
1513e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)buffer.size(); i++)
1514e5c31af7Sopenharmony_ci					buffer[i] = valuesToAssign[i / typeSize].val.intV[i % typeSize];
1515e5c31af7Sopenharmony_ci
1516e5c31af7Sopenharmony_ci				DE_STATIC_ASSERT(sizeof(GLuint) == sizeof(buffer[0]));
1517e5c31af7Sopenharmony_ci				switch (typeSize)
1518e5c31af7Sopenharmony_ci				{
1519e5c31af7Sopenharmony_ci					case 1: GLU_CHECK_CALL(glProgramUniform1uiv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1520e5c31af7Sopenharmony_ci					case 2: GLU_CHECK_CALL(glProgramUniform2uiv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1521e5c31af7Sopenharmony_ci					case 3: GLU_CHECK_CALL(glProgramUniform3uiv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1522e5c31af7Sopenharmony_ci					case 4: GLU_CHECK_CALL(glProgramUniform4uiv(programGL, location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1523e5c31af7Sopenharmony_ci					default:
1524e5c31af7Sopenharmony_ci						DE_ASSERT(false);
1525e5c31af7Sopenharmony_ci				}
1526e5c31af7Sopenharmony_ci			}
1527e5c31af7Sopenharmony_ci		}
1528e5c31af7Sopenharmony_ci		else if (glu::isDataTypeSampler(valuesToAssign[0].type))
1529e5c31af7Sopenharmony_ci		{
1530e5c31af7Sopenharmony_ci			if (assignByValue)
1531e5c31af7Sopenharmony_ci				GLU_CHECK_CALL(glProgramUniform1i(programGL, location, uniform.finalValue.val.samplerV.unit));
1532e5c31af7Sopenharmony_ci			else
1533e5c31af7Sopenharmony_ci			{
1534e5c31af7Sopenharmony_ci				const GLint unit = uniform.finalValue.val.samplerV.unit;
1535e5c31af7Sopenharmony_ci				GLU_CHECK_CALL(glProgramUniform1iv(programGL, location, (GLsizei)valuesToAssign.size(), &unit));
1536e5c31af7Sopenharmony_ci			}
1537e5c31af7Sopenharmony_ci		}
1538e5c31af7Sopenharmony_ci		else
1539e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1540e5c31af7Sopenharmony_ci	}
1541e5c31af7Sopenharmony_ci}
1542e5c31af7Sopenharmony_ci
1543e5c31af7Sopenharmony_cibool UniformCase::compareUniformValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms)
1544e5c31af7Sopenharmony_ci{
1545e5c31af7Sopenharmony_ci	TestLog&	log			= m_testCtx.getLog();
1546e5c31af7Sopenharmony_ci	bool		success		= true;
1547e5c31af7Sopenharmony_ci
1548e5c31af7Sopenharmony_ci	for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++)
1549e5c31af7Sopenharmony_ci	{
1550e5c31af7Sopenharmony_ci		const BasicUniform&		uniform		= basicUniforms[unifNdx];
1551e5c31af7Sopenharmony_ci		const VarValue&			unifValue	= values[unifNdx];
1552e5c31af7Sopenharmony_ci
1553e5c31af7Sopenharmony_ci		log << TestLog::Message << "// Checking uniform " << uniform.name << TestLog::EndMessage;
1554e5c31af7Sopenharmony_ci
1555e5c31af7Sopenharmony_ci		if (unifValue.type == glu::TYPE_INVALID) // This happens when glGetUniformLocation() returned -1.
1556e5c31af7Sopenharmony_ci			continue;
1557e5c31af7Sopenharmony_ci
1558e5c31af7Sopenharmony_ci		if (!apiVarValueEquals(unifValue, uniform.finalValue))
1559e5c31af7Sopenharmony_ci		{
1560e5c31af7Sopenharmony_ci			log << TestLog::Message << "// FAILURE: value obtained with glGetUniform*() for uniform " << uniform.name << " differs from value set with glProgramUniform*()" << TestLog::EndMessage;
1561e5c31af7Sopenharmony_ci			success = false;
1562e5c31af7Sopenharmony_ci		}
1563e5c31af7Sopenharmony_ci	}
1564e5c31af7Sopenharmony_ci
1565e5c31af7Sopenharmony_ci	return success;
1566e5c31af7Sopenharmony_ci}
1567e5c31af7Sopenharmony_ci
1568e5c31af7Sopenharmony_cibool UniformCase::renderTest (const vector<BasicUniform>& basicUniforms, const ShaderProgram& program, Random& rnd)
1569e5c31af7Sopenharmony_ci{
1570e5c31af7Sopenharmony_ci	TestLog&					log				= m_testCtx.getLog();
1571e5c31af7Sopenharmony_ci	const tcu::RenderTarget&	renderTarget	= m_context.getRenderTarget();
1572e5c31af7Sopenharmony_ci	const int					viewportW		= de::min<int>(renderTarget.getWidth(),		MAX_RENDER_WIDTH);
1573e5c31af7Sopenharmony_ci	const int					viewportH		= de::min<int>(renderTarget.getHeight(),	MAX_RENDER_HEIGHT);
1574e5c31af7Sopenharmony_ci	const int					viewportX		= rnd.getInt(0, renderTarget.getWidth()		- viewportW);
1575e5c31af7Sopenharmony_ci	const int					viewportY		= rnd.getInt(0, renderTarget.getHeight()	- viewportH);
1576e5c31af7Sopenharmony_ci	tcu::Surface				renderedImg		(viewportW, viewportH);
1577e5c31af7Sopenharmony_ci
1578e5c31af7Sopenharmony_ci	// Assert that no two samplers of different types have the same texture unit - this is an error in GL.
1579e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)basicUniforms.size(); i++)
1580e5c31af7Sopenharmony_ci	{
1581e5c31af7Sopenharmony_ci		if (glu::isDataTypeSampler(basicUniforms[i].type))
1582e5c31af7Sopenharmony_ci		{
1583e5c31af7Sopenharmony_ci			for (int j = 0; j < i; j++)
1584e5c31af7Sopenharmony_ci			{
1585e5c31af7Sopenharmony_ci				if (glu::isDataTypeSampler(basicUniforms[j].type) && basicUniforms[i].type != basicUniforms[j].type)
1586e5c31af7Sopenharmony_ci					DE_ASSERT(basicUniforms[i].finalValue.val.samplerV.unit != basicUniforms[j].finalValue.val.samplerV.unit);
1587e5c31af7Sopenharmony_ci			}
1588e5c31af7Sopenharmony_ci		}
1589e5c31af7Sopenharmony_ci	}
1590e5c31af7Sopenharmony_ci
1591e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)basicUniforms.size(); i++)
1592e5c31af7Sopenharmony_ci	{
1593e5c31af7Sopenharmony_ci		if (glu::isDataTypeSampler(basicUniforms[i].type) && std::find(m_filledTextureUnits.begin(), m_filledTextureUnits.end(), basicUniforms[i].finalValue.val.samplerV.unit) == m_filledTextureUnits.end())
1594e5c31af7Sopenharmony_ci		{
1595e5c31af7Sopenharmony_ci			log << TestLog::Message << "// Filling texture at unit " << apiVarValueStr(basicUniforms[i].finalValue) << " with color " << shaderVarValueStr(basicUniforms[i].finalValue) << TestLog::EndMessage;
1596e5c31af7Sopenharmony_ci			setupTexture(basicUniforms[i].finalValue);
1597e5c31af7Sopenharmony_ci		}
1598e5c31af7Sopenharmony_ci	}
1599e5c31af7Sopenharmony_ci
1600e5c31af7Sopenharmony_ci	GLU_CHECK_CALL(glViewport(viewportX, viewportY, viewportW, viewportH));
1601e5c31af7Sopenharmony_ci	GLU_CHECK_CALL(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
1602e5c31af7Sopenharmony_ci	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
1603e5c31af7Sopenharmony_ci	GLU_CHECK_CALL(glUseProgram(program.getProgram()));
1604e5c31af7Sopenharmony_ci
1605e5c31af7Sopenharmony_ci	{
1606e5c31af7Sopenharmony_ci		static const float position[] =
1607e5c31af7Sopenharmony_ci		{
1608e5c31af7Sopenharmony_ci			-1.0f, -1.0f, 0.0f, 1.0f,
1609e5c31af7Sopenharmony_ci			-1.0f, +1.0f, 0.0f, 1.0f,
1610e5c31af7Sopenharmony_ci			+1.0f, -1.0f, 0.0f, 1.0f,
1611e5c31af7Sopenharmony_ci			+1.0f, +1.0f, 0.0f, 1.0f
1612e5c31af7Sopenharmony_ci		};
1613e5c31af7Sopenharmony_ci		static const deUint16			indices[]	= { 0, 1, 2, 2, 1, 3 };
1614e5c31af7Sopenharmony_ci		const glu::VertexArrayBinding	binding		= glu::va::Float("a_position", 4, 4, 0, &position[0]);
1615e5c31af7Sopenharmony_ci
1616e5c31af7Sopenharmony_ci		glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &binding, glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
1617e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess());
1618e5c31af7Sopenharmony_ci	}
1619e5c31af7Sopenharmony_ci
1620e5c31af7Sopenharmony_ci	int numFailedPixels = 0;
1621e5c31af7Sopenharmony_ci	for (int y = 0; y < renderedImg.getHeight(); y++)
1622e5c31af7Sopenharmony_ci	{
1623e5c31af7Sopenharmony_ci		for (int x = 0; x < renderedImg.getWidth(); x++)
1624e5c31af7Sopenharmony_ci		{
1625e5c31af7Sopenharmony_ci			if (renderedImg.getPixel(x, y) != tcu::RGBA::green())
1626e5c31af7Sopenharmony_ci				numFailedPixels += 1;
1627e5c31af7Sopenharmony_ci		}
1628e5c31af7Sopenharmony_ci	}
1629e5c31af7Sopenharmony_ci
1630e5c31af7Sopenharmony_ci	if (numFailedPixels > 0)
1631e5c31af7Sopenharmony_ci	{
1632e5c31af7Sopenharmony_ci		log << TestLog::Image("RenderedImage", "Rendered image", renderedImg);
1633e5c31af7Sopenharmony_ci		log << TestLog::Message << "FAILURE: image comparison failed, got " << numFailedPixels << " non-green pixels" << TestLog::EndMessage;
1634e5c31af7Sopenharmony_ci		return false;
1635e5c31af7Sopenharmony_ci	}
1636e5c31af7Sopenharmony_ci	else
1637e5c31af7Sopenharmony_ci	{
1638e5c31af7Sopenharmony_ci		log << TestLog::Message << "Success: got all-green pixels (all uniforms have correct values)" << TestLog::EndMessage;
1639e5c31af7Sopenharmony_ci		return true;
1640e5c31af7Sopenharmony_ci	}
1641e5c31af7Sopenharmony_ci}
1642e5c31af7Sopenharmony_ci
1643e5c31af7Sopenharmony_ciUniformCase::IterateResult UniformCase::iterate (void)
1644e5c31af7Sopenharmony_ci{
1645e5c31af7Sopenharmony_ci	Random							rnd				(deStringHash(getName()) ^ (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
1646e5c31af7Sopenharmony_ci	TestLog&						log				= m_testCtx.getLog();
1647e5c31af7Sopenharmony_ci	vector<BasicUniform>			basicUniforms;
1648e5c31af7Sopenharmony_ci	vector<BasicUniformReportRef>	basicUniformReportsRef;
1649e5c31af7Sopenharmony_ci
1650e5c31af7Sopenharmony_ci	{
1651e5c31af7Sopenharmony_ci		int samplerUnitCounter = 0;
1652e5c31af7Sopenharmony_ci		for (int i = 0; i < (int)m_uniformCollection->getNumUniforms(); i++)
1653e5c31af7Sopenharmony_ci			generateBasicUniforms(basicUniforms, basicUniformReportsRef, m_uniformCollection->getUniform(i).type, m_uniformCollection->getUniform(i).name.c_str(), true, samplerUnitCounter, rnd);
1654e5c31af7Sopenharmony_ci	}
1655e5c31af7Sopenharmony_ci
1656e5c31af7Sopenharmony_ci	const string					vertexSource	= generateVertexSource(basicUniforms);
1657e5c31af7Sopenharmony_ci	const string					fragmentSource	= generateFragmentSource(basicUniforms);
1658e5c31af7Sopenharmony_ci	const ShaderProgram				program			(m_context.getRenderContext(), glu::makeVtxFragSources(vertexSource, fragmentSource));
1659e5c31af7Sopenharmony_ci
1660e5c31af7Sopenharmony_ci	// An unused program that we'll give to glUseProgram before we actually need
1661e5c31af7Sopenharmony_ci	// the real program above, to see if an implementation tries to use the
1662e5c31af7Sopenharmony_ci	// currently active program for something inappropriate (instead of the
1663e5c31af7Sopenharmony_ci	// program given as argument to, say, glProgramUniform*).
1664e5c31af7Sopenharmony_ci	const ShaderProgram				unusedProgram	(m_context.getRenderContext(), glu::makeVtxFragSources("#version 310 es\n"
1665e5c31af7Sopenharmony_ci																										   "void main (void) { gl_Position = vec4(1.0); }\n",
1666e5c31af7Sopenharmony_ci
1667e5c31af7Sopenharmony_ci																										   "#version 310 es\n"
1668e5c31af7Sopenharmony_ci																										   "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1669e5c31af7Sopenharmony_ci																										   "void main (void) { dEQP_FragColor = vec4(0.0, 0.0, 1.0, 1.0); }\n"));
1670e5c31af7Sopenharmony_ci
1671e5c31af7Sopenharmony_ci	log << program;
1672e5c31af7Sopenharmony_ci
1673e5c31af7Sopenharmony_ci	if (!program.isOk())
1674e5c31af7Sopenharmony_ci	{
1675e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
1676e5c31af7Sopenharmony_ci		return STOP;
1677e5c31af7Sopenharmony_ci	}
1678e5c31af7Sopenharmony_ci
1679e5c31af7Sopenharmony_ci	if (!unusedProgram.isOk())
1680e5c31af7Sopenharmony_ci	{
1681e5c31af7Sopenharmony_ci		log << unusedProgram;
1682e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compilation of unused program failed");
1683e5c31af7Sopenharmony_ci		return STOP;
1684e5c31af7Sopenharmony_ci	}
1685e5c31af7Sopenharmony_ci
1686e5c31af7Sopenharmony_ci	log << TestLog::Message << "// Note: calling glUseProgram with a unused program (will only use the real program once it's needed for rendering)" << TestLog::EndMessage;
1687e5c31af7Sopenharmony_ci	glUseProgram(unusedProgram.getProgram());
1688e5c31af7Sopenharmony_ci
1689e5c31af7Sopenharmony_ci	const bool success = test(basicUniforms, basicUniformReportsRef, program, rnd);
1690e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
1691e5c31af7Sopenharmony_ci							success ? "Passed"				: "Failed");
1692e5c31af7Sopenharmony_ci
1693e5c31af7Sopenharmony_ci	return STOP;
1694e5c31af7Sopenharmony_ci}
1695e5c31af7Sopenharmony_ci
1696e5c31af7Sopenharmony_ciclass UniformAssignCase : public UniformCase
1697e5c31af7Sopenharmony_ci{
1698e5c31af7Sopenharmony_cipublic:
1699e5c31af7Sopenharmony_ci	enum CheckMethod
1700e5c31af7Sopenharmony_ci	{
1701e5c31af7Sopenharmony_ci		CHECKMETHOD_GET_UNIFORM = 0,	//!< Check values with glGetUniform*().
1702e5c31af7Sopenharmony_ci		CHECKMETHOD_RENDER,				//!< Check values by rendering with the value-checking shader.
1703e5c31af7Sopenharmony_ci
1704e5c31af7Sopenharmony_ci		CHECKMETHOD_LAST
1705e5c31af7Sopenharmony_ci	};
1706e5c31af7Sopenharmony_ci	enum AssignMethod
1707e5c31af7Sopenharmony_ci	{
1708e5c31af7Sopenharmony_ci		ASSIGNMETHOD_POINTER = 0,
1709e5c31af7Sopenharmony_ci		ASSIGNMETHOD_VALUE,
1710e5c31af7Sopenharmony_ci
1711e5c31af7Sopenharmony_ci		ASSIGNMETHOD_LAST
1712e5c31af7Sopenharmony_ci	};
1713e5c31af7Sopenharmony_ci
1714e5c31af7Sopenharmony_ci						UniformAssignCase			(Context&									context,
1715e5c31af7Sopenharmony_ci													 const char*								name,
1716e5c31af7Sopenharmony_ci													 const char*								description,
1717e5c31af7Sopenharmony_ci													 CaseShaderType								shaderType,
1718e5c31af7Sopenharmony_ci													 const SharedPtr<const UniformCollection>&	uniformCollection,
1719e5c31af7Sopenharmony_ci													 CheckMethod								checkMethod,
1720e5c31af7Sopenharmony_ci													 AssignMethod								assignMethod,
1721e5c31af7Sopenharmony_ci													 deUint32									additionalFeatures = 0);
1722e5c31af7Sopenharmony_ci
1723e5c31af7Sopenharmony_ci	bool				test						(const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd);
1724e5c31af7Sopenharmony_ci
1725e5c31af7Sopenharmony_ci	static const char*	getCheckMethodName			(CheckMethod checkMethod);
1726e5c31af7Sopenharmony_ci	static const char*	getCheckMethodDescription	(CheckMethod checkMethod);
1727e5c31af7Sopenharmony_ci	static const char*	getAssignMethodName			(AssignMethod checkMethod);
1728e5c31af7Sopenharmony_ci	static const char*	getAssignMethodDescription	(AssignMethod checkMethod);
1729e5c31af7Sopenharmony_ci
1730e5c31af7Sopenharmony_ciprivate:
1731e5c31af7Sopenharmony_ci	const CheckMethod m_checkMethod;
1732e5c31af7Sopenharmony_ci};
1733e5c31af7Sopenharmony_ci
1734e5c31af7Sopenharmony_ciconst char* UniformAssignCase::getCheckMethodName (const CheckMethod checkMethod)
1735e5c31af7Sopenharmony_ci{
1736e5c31af7Sopenharmony_ci	switch (checkMethod)
1737e5c31af7Sopenharmony_ci	{
1738e5c31af7Sopenharmony_ci		case CHECKMETHOD_GET_UNIFORM:	return "get_uniform";
1739e5c31af7Sopenharmony_ci		case CHECKMETHOD_RENDER:		return "render";
1740e5c31af7Sopenharmony_ci		default: DE_ASSERT(false);		return DE_NULL;
1741e5c31af7Sopenharmony_ci	}
1742e5c31af7Sopenharmony_ci}
1743e5c31af7Sopenharmony_ci
1744e5c31af7Sopenharmony_ciconst char* UniformAssignCase::getCheckMethodDescription (const CheckMethod checkMethod)
1745e5c31af7Sopenharmony_ci{
1746e5c31af7Sopenharmony_ci	switch (checkMethod)
1747e5c31af7Sopenharmony_ci	{
1748e5c31af7Sopenharmony_ci		case CHECKMETHOD_GET_UNIFORM:	return "Verify values with glGetUniform*()";
1749e5c31af7Sopenharmony_ci		case CHECKMETHOD_RENDER:		return "Verify values by rendering";
1750e5c31af7Sopenharmony_ci		default: DE_ASSERT(false);		return DE_NULL;
1751e5c31af7Sopenharmony_ci	}
1752e5c31af7Sopenharmony_ci}
1753e5c31af7Sopenharmony_ci
1754e5c31af7Sopenharmony_ciconst char* UniformAssignCase::getAssignMethodName (const AssignMethod assignMethod)
1755e5c31af7Sopenharmony_ci{
1756e5c31af7Sopenharmony_ci	switch (assignMethod)
1757e5c31af7Sopenharmony_ci	{
1758e5c31af7Sopenharmony_ci		case ASSIGNMETHOD_POINTER:		return "by_pointer";
1759e5c31af7Sopenharmony_ci		case ASSIGNMETHOD_VALUE:		return "by_value";
1760e5c31af7Sopenharmony_ci		default: DE_ASSERT(false);		return DE_NULL;
1761e5c31af7Sopenharmony_ci	}
1762e5c31af7Sopenharmony_ci}
1763e5c31af7Sopenharmony_ci
1764e5c31af7Sopenharmony_ciconst char* UniformAssignCase::getAssignMethodDescription (const AssignMethod assignMethod)
1765e5c31af7Sopenharmony_ci{
1766e5c31af7Sopenharmony_ci	switch (assignMethod)
1767e5c31af7Sopenharmony_ci	{
1768e5c31af7Sopenharmony_ci		case ASSIGNMETHOD_POINTER:		return "Assign values by-pointer";
1769e5c31af7Sopenharmony_ci		case ASSIGNMETHOD_VALUE:		return "Assign values by-value";
1770e5c31af7Sopenharmony_ci		default: DE_ASSERT(false);		return DE_NULL;
1771e5c31af7Sopenharmony_ci	}
1772e5c31af7Sopenharmony_ci}
1773e5c31af7Sopenharmony_ci
1774e5c31af7Sopenharmony_ciUniformAssignCase::UniformAssignCase (Context&									context,
1775e5c31af7Sopenharmony_ci									  const char* const							name,
1776e5c31af7Sopenharmony_ci									  const char* const							description,
1777e5c31af7Sopenharmony_ci									  const CaseShaderType						shaderType,
1778e5c31af7Sopenharmony_ci									  const SharedPtr<const UniformCollection>&	uniformCollection,
1779e5c31af7Sopenharmony_ci									  const CheckMethod							checkMethod,
1780e5c31af7Sopenharmony_ci									  const AssignMethod						assignMethod,
1781e5c31af7Sopenharmony_ci									  const deUint32							additionalFeatures)
1782e5c31af7Sopenharmony_ci	: UniformCase		(context, name, description, shaderType, uniformCollection,
1783e5c31af7Sopenharmony_ci						 (assignMethod == ASSIGNMETHOD_VALUE ? FEATURE_UNIFORMFUNC_VALUE : 0) | additionalFeatures)
1784e5c31af7Sopenharmony_ci	, m_checkMethod		(checkMethod)
1785e5c31af7Sopenharmony_ci{
1786e5c31af7Sopenharmony_ci	DE_ASSERT(assignMethod != ASSIGNMETHOD_LAST);
1787e5c31af7Sopenharmony_ci}
1788e5c31af7Sopenharmony_ci
1789e5c31af7Sopenharmony_cibool UniformAssignCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd)
1790e5c31af7Sopenharmony_ci{
1791e5c31af7Sopenharmony_ci	DE_UNREF(basicUniformReportsRef);
1792e5c31af7Sopenharmony_ci
1793e5c31af7Sopenharmony_ci	const deUint32	programGL	= program.getProgram();
1794e5c31af7Sopenharmony_ci	TestLog&		log			= m_testCtx.getLog();
1795e5c31af7Sopenharmony_ci
1796e5c31af7Sopenharmony_ci	{
1797e5c31af7Sopenharmony_ci		const ScopedLogSection section(log, "UniformAssign", "Uniform value assignments");
1798e5c31af7Sopenharmony_ci		assignUniforms(basicUniforms, programGL, rnd);
1799e5c31af7Sopenharmony_ci	}
1800e5c31af7Sopenharmony_ci
1801e5c31af7Sopenharmony_ci	if (m_checkMethod == CHECKMETHOD_GET_UNIFORM)
1802e5c31af7Sopenharmony_ci	{
1803e5c31af7Sopenharmony_ci		vector<VarValue> values;
1804e5c31af7Sopenharmony_ci
1805e5c31af7Sopenharmony_ci		{
1806e5c31af7Sopenharmony_ci			const ScopedLogSection section(log, "GetUniforms", "Uniform value query");
1807e5c31af7Sopenharmony_ci			const bool success = getUniforms(values, basicUniforms, program.getProgram());
1808e5c31af7Sopenharmony_ci
1809e5c31af7Sopenharmony_ci			if (!success)
1810e5c31af7Sopenharmony_ci				return false;
1811e5c31af7Sopenharmony_ci		}
1812e5c31af7Sopenharmony_ci
1813e5c31af7Sopenharmony_ci		{
1814e5c31af7Sopenharmony_ci			const ScopedLogSection section(log, "ValueCheck", "Verify that the reported values match the assigned values");
1815e5c31af7Sopenharmony_ci			const bool success = compareUniformValues(values, basicUniforms);
1816e5c31af7Sopenharmony_ci
1817e5c31af7Sopenharmony_ci			if (!success)
1818e5c31af7Sopenharmony_ci				return false;
1819e5c31af7Sopenharmony_ci		}
1820e5c31af7Sopenharmony_ci	}
1821e5c31af7Sopenharmony_ci	else
1822e5c31af7Sopenharmony_ci	{
1823e5c31af7Sopenharmony_ci		DE_ASSERT(m_checkMethod == CHECKMETHOD_RENDER);
1824e5c31af7Sopenharmony_ci
1825e5c31af7Sopenharmony_ci		const ScopedLogSection section(log, "RenderTest", "Render test");
1826e5c31af7Sopenharmony_ci		const bool success = renderTest(basicUniforms, program, rnd);
1827e5c31af7Sopenharmony_ci
1828e5c31af7Sopenharmony_ci		if (!success)
1829e5c31af7Sopenharmony_ci			return false;
1830e5c31af7Sopenharmony_ci	}
1831e5c31af7Sopenharmony_ci
1832e5c31af7Sopenharmony_ci	return true;
1833e5c31af7Sopenharmony_ci}
1834e5c31af7Sopenharmony_ci
1835e5c31af7Sopenharmony_ciProgramUniformTests::ProgramUniformTests (Context& context)
1836e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "program_uniform", "glProgramUniform*() tests")
1837e5c31af7Sopenharmony_ci{
1838e5c31af7Sopenharmony_ci}
1839e5c31af7Sopenharmony_ci
1840e5c31af7Sopenharmony_ciProgramUniformTests::~ProgramUniformTests (void)
1841e5c31af7Sopenharmony_ci{
1842e5c31af7Sopenharmony_ci}
1843e5c31af7Sopenharmony_ci
1844e5c31af7Sopenharmony_cinamespace
1845e5c31af7Sopenharmony_ci{
1846e5c31af7Sopenharmony_ci
1847e5c31af7Sopenharmony_ci// \note Although this is only used in ProgramUniformTests::init, it needs to be defined here as it's used as a template argument.
1848e5c31af7Sopenharmony_cistruct UniformCollectionCase
1849e5c31af7Sopenharmony_ci{
1850e5c31af7Sopenharmony_ci	string								namePrefix;
1851e5c31af7Sopenharmony_ci	SharedPtr<const UniformCollection>	uniformCollection;
1852e5c31af7Sopenharmony_ci
1853e5c31af7Sopenharmony_ci	UniformCollectionCase (const char* const name, const UniformCollection* uniformCollection_)
1854e5c31af7Sopenharmony_ci		: namePrefix			(name ? name + string("_") : "")
1855e5c31af7Sopenharmony_ci		, uniformCollection		(uniformCollection_)
1856e5c31af7Sopenharmony_ci	{
1857e5c31af7Sopenharmony_ci	}
1858e5c31af7Sopenharmony_ci};
1859e5c31af7Sopenharmony_ci
1860e5c31af7Sopenharmony_ci} // anonymous
1861e5c31af7Sopenharmony_ci
1862e5c31af7Sopenharmony_civoid ProgramUniformTests::init (void)
1863e5c31af7Sopenharmony_ci{
1864e5c31af7Sopenharmony_ci	// Generate sets of UniformCollections that are used by several cases.
1865e5c31af7Sopenharmony_ci
1866e5c31af7Sopenharmony_ci	enum
1867e5c31af7Sopenharmony_ci	{
1868e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_BASIC = 0,
1869e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_BASIC_ARRAY,
1870e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_BASIC_STRUCT,
1871e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY,
1872e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT,
1873e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS,
1874e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_MULTIPLE_BASIC,
1875e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY,
1876e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS,
1877e5c31af7Sopenharmony_ci
1878e5c31af7Sopenharmony_ci		UNIFORMCOLLECTIONS_LAST
1879e5c31af7Sopenharmony_ci	};
1880e5c31af7Sopenharmony_ci
1881e5c31af7Sopenharmony_ci	struct UniformCollectionGroup
1882e5c31af7Sopenharmony_ci	{
1883e5c31af7Sopenharmony_ci		string							name;
1884e5c31af7Sopenharmony_ci		vector<UniformCollectionCase>	cases;
1885e5c31af7Sopenharmony_ci	} defaultUniformCollections[UNIFORMCOLLECTIONS_LAST];
1886e5c31af7Sopenharmony_ci
1887e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC].name							= "basic";
1888e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_ARRAY].name						= "basic_array";
1889e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_STRUCT].name						= "basic_struct";
1890e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY].name					= "struct_in_array";
1891e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT].name					= "array_in_struct";
1892e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS].name			= "nested_structs_arrays";
1893e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC].name					= "multiple_basic";
1894e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY].name				= "multiple_basic_array";
1895e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS].name	= "multiple_nested_structs_arrays";
1896e5c31af7Sopenharmony_ci
1897e5c31af7Sopenharmony_ci	for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_testDataTypes); dataTypeNdx++)
1898e5c31af7Sopenharmony_ci	{
1899e5c31af7Sopenharmony_ci		const glu::DataType		dataType	= s_testDataTypes[dataTypeNdx];
1900e5c31af7Sopenharmony_ci		const char* const		typeName	= glu::getDataTypeName(dataType);
1901e5c31af7Sopenharmony_ci
1902e5c31af7Sopenharmony_ci		defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC].cases.push_back(UniformCollectionCase(typeName, UniformCollection::basic(dataType)));
1903e5c31af7Sopenharmony_ci
1904e5c31af7Sopenharmony_ci		if (glu::isDataTypeScalar(dataType)													||
1905e5c31af7Sopenharmony_ci			(glu::isDataTypeVector(dataType) && glu::getDataTypeScalarSize(dataType) == 4)	||
1906e5c31af7Sopenharmony_ci			dataType == glu::TYPE_FLOAT_MAT4												||
1907e5c31af7Sopenharmony_ci			dataType == glu::TYPE_SAMPLER_2D)
1908e5c31af7Sopenharmony_ci			defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_ARRAY].cases.push_back(UniformCollectionCase(typeName, UniformCollection::basicArray(dataType)));
1909e5c31af7Sopenharmony_ci
1910e5c31af7Sopenharmony_ci		if (glu::isDataTypeScalar(dataType)		||
1911e5c31af7Sopenharmony_ci			dataType == glu::TYPE_FLOAT_MAT4	||
1912e5c31af7Sopenharmony_ci			dataType == glu::TYPE_SAMPLER_2D)
1913e5c31af7Sopenharmony_ci		{
1914e5c31af7Sopenharmony_ci			const glu::DataType		secondDataType	= glu::isDataTypeScalar(dataType)	? glu::getDataTypeVector(dataType, 4)
1915e5c31af7Sopenharmony_ci													: dataType == glu::TYPE_FLOAT_MAT4	? glu::TYPE_FLOAT_MAT2
1916e5c31af7Sopenharmony_ci													: dataType == glu::TYPE_SAMPLER_2D	? glu::TYPE_SAMPLER_CUBE
1917e5c31af7Sopenharmony_ci													: glu::TYPE_LAST;
1918e5c31af7Sopenharmony_ci			DE_ASSERT(secondDataType != glu::TYPE_LAST);
1919e5c31af7Sopenharmony_ci			const char* const		secondTypeName	= glu::getDataTypeName(secondDataType);
1920e5c31af7Sopenharmony_ci			const string			name			= string("") + typeName + "_" + secondTypeName;
1921e5c31af7Sopenharmony_ci
1922e5c31af7Sopenharmony_ci			defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_STRUCT].cases.push_back			(UniformCollectionCase(name.c_str(), UniformCollection::basicStruct(dataType, secondDataType, false)));
1923e5c31af7Sopenharmony_ci			defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT].cases.push_back		(UniformCollectionCase(name.c_str(), UniformCollection::basicStruct(dataType, secondDataType, true)));
1924e5c31af7Sopenharmony_ci			defaultUniformCollections[UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY].cases.push_back		(UniformCollectionCase(name.c_str(), UniformCollection::structInArray(dataType, secondDataType, false)));
1925e5c31af7Sopenharmony_ci			defaultUniformCollections[UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS].cases.push_back	(UniformCollectionCase(name.c_str(), UniformCollection::nestedArraysStructs(dataType, secondDataType)));
1926e5c31af7Sopenharmony_ci		}
1927e5c31af7Sopenharmony_ci	}
1928e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC].cases.push_back					(UniformCollectionCase(DE_NULL, UniformCollection::multipleBasic()));
1929e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY].cases.push_back				(UniformCollectionCase(DE_NULL, UniformCollection::multipleBasicArray()));
1930e5c31af7Sopenharmony_ci	defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS].cases.push_back	(UniformCollectionCase(DE_NULL, UniformCollection::multipleNestedArraysStructs()));
1931e5c31af7Sopenharmony_ci
1932e5c31af7Sopenharmony_ci	// Basic by-pointer or by-value uniform assignment cases.
1933e5c31af7Sopenharmony_ci
1934e5c31af7Sopenharmony_ci	for (int assignMethodI = 0; assignMethodI < (int)UniformAssignCase::ASSIGNMETHOD_LAST; assignMethodI++)
1935e5c31af7Sopenharmony_ci	{
1936e5c31af7Sopenharmony_ci		const UniformAssignCase::AssignMethod	assignMethod		= (UniformAssignCase::AssignMethod)assignMethodI;
1937e5c31af7Sopenharmony_ci		TestCaseGroup* const					assignMethodGroup	= new TestCaseGroup(m_context, UniformAssignCase::getAssignMethodName(assignMethod), UniformAssignCase::getAssignMethodDescription(assignMethod));
1938e5c31af7Sopenharmony_ci		addChild(assignMethodGroup);
1939e5c31af7Sopenharmony_ci
1940e5c31af7Sopenharmony_ci		for (int checkMethodI = 0; checkMethodI < (int)UniformAssignCase::CHECKMETHOD_LAST; checkMethodI++)
1941e5c31af7Sopenharmony_ci		{
1942e5c31af7Sopenharmony_ci			const UniformAssignCase::CheckMethod	checkMethod			= (UniformAssignCase::CheckMethod)checkMethodI;
1943e5c31af7Sopenharmony_ci			TestCaseGroup* const					checkMethodGroup	= new TestCaseGroup(m_context, UniformAssignCase::getCheckMethodName(checkMethod), UniformAssignCase::getCheckMethodDescription(checkMethod));
1944e5c31af7Sopenharmony_ci			assignMethodGroup->addChild(checkMethodGroup);
1945e5c31af7Sopenharmony_ci
1946e5c31af7Sopenharmony_ci			for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++)
1947e5c31af7Sopenharmony_ci			{
1948e5c31af7Sopenharmony_ci				const int numArrayFirstElemNameCases = checkMethod == UniformAssignCase::CHECKMETHOD_GET_UNIFORM && collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY ? 2 : 1;
1949e5c31af7Sopenharmony_ci
1950e5c31af7Sopenharmony_ci				for (int referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++)
1951e5c31af7Sopenharmony_ci				{
1952e5c31af7Sopenharmony_ci					const UniformCollectionGroup&	collectionGroup			= defaultUniformCollections[collectionGroupNdx];
1953e5c31af7Sopenharmony_ci					const string					collectionGroupName		= collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? "" : "_first_elem_without_brackets");
1954e5c31af7Sopenharmony_ci					TestCaseGroup*					collectionTestGroup		= DE_NULL;
1955e5c31af7Sopenharmony_ci
1956e5c31af7Sopenharmony_ci					for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
1957e5c31af7Sopenharmony_ci					{
1958e5c31af7Sopenharmony_ci						const UniformCollectionCase&				collectionCase		= collectionGroup.cases[collectionNdx];
1959e5c31af7Sopenharmony_ci						const string								collName			= collectionCase.namePrefix;
1960e5c31af7Sopenharmony_ci						const SharedPtr<const UniformCollection>&	uniformCollection	= collectionCase.uniformCollection;
1961e5c31af7Sopenharmony_ci						const bool									containsBooleans	= uniformCollection->containsMatchingBasicType(glu::isDataTypeBoolOrBVec);
1962e5c31af7Sopenharmony_ci						const bool									varyBoolApiType		= checkMethod == UniformAssignCase::CHECKMETHOD_GET_UNIFORM && containsBooleans &&
1963e5c31af7Sopenharmony_ci																							(collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY);
1964e5c31af7Sopenharmony_ci						const int									numBoolVariations	= varyBoolApiType ? 3 : 1;
1965e5c31af7Sopenharmony_ci						const bool									containsMatrices	= uniformCollection->containsMatchingBasicType(glu::isDataTypeMatrix);
1966e5c31af7Sopenharmony_ci						const bool									varyMatrixMode		= containsMatrices &&
1967e5c31af7Sopenharmony_ci																							(collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY);
1968e5c31af7Sopenharmony_ci						const int									numMatVariations	= varyMatrixMode ? 2 : 1;
1969e5c31af7Sopenharmony_ci
1970e5c31af7Sopenharmony_ci						if (containsMatrices && assignMethod != UniformAssignCase::ASSIGNMETHOD_POINTER)
1971e5c31af7Sopenharmony_ci							continue;
1972e5c31af7Sopenharmony_ci
1973e5c31af7Sopenharmony_ci						for (int booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++)
1974e5c31af7Sopenharmony_ci						{
1975e5c31af7Sopenharmony_ci							const deUint32		booleanTypeFeat		= booleanTypeI == 1 ? UniformCase::FEATURE_BOOLEANAPITYPE_INT
1976e5c31af7Sopenharmony_ci																	: booleanTypeI == 2 ? UniformCase::FEATURE_BOOLEANAPITYPE_UINT
1977e5c31af7Sopenharmony_ci																	: 0;
1978e5c31af7Sopenharmony_ci							const char* const	booleanTypeName		= booleanTypeI == 1 ? "int"
1979e5c31af7Sopenharmony_ci																	: booleanTypeI == 2 ? "uint"
1980e5c31af7Sopenharmony_ci																	: "float";
1981e5c31af7Sopenharmony_ci							const string		nameWithBoolType	= varyBoolApiType ? collName + "api_" + booleanTypeName + "_" : collName;
1982e5c31af7Sopenharmony_ci
1983e5c31af7Sopenharmony_ci							for (int matrixTypeI = 0; matrixTypeI < numMatVariations; matrixTypeI++)
1984e5c31af7Sopenharmony_ci							{
1985e5c31af7Sopenharmony_ci								const string nameWithMatrixType = nameWithBoolType + (matrixTypeI == 1 ? "row_major_" : "");
1986e5c31af7Sopenharmony_ci
1987e5c31af7Sopenharmony_ci								for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
1988e5c31af7Sopenharmony_ci								{
1989e5c31af7Sopenharmony_ci									const string	name							= nameWithMatrixType + getCaseShaderTypeName((CaseShaderType)shaderType);
1990e5c31af7Sopenharmony_ci									const deUint32	arrayFirstElemNameNoIndexFeat	= referToFirstArrayElemWithoutIndexI == 0 ? 0 : UniformCase::FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX;
1991e5c31af7Sopenharmony_ci
1992e5c31af7Sopenharmony_ci									// skip empty groups by creating groups on demand
1993e5c31af7Sopenharmony_ci									if (!collectionTestGroup)
1994e5c31af7Sopenharmony_ci									{
1995e5c31af7Sopenharmony_ci										collectionTestGroup = new TestCaseGroup(m_context, collectionGroupName.c_str(), "");
1996e5c31af7Sopenharmony_ci										checkMethodGroup->addChild(collectionTestGroup);
1997e5c31af7Sopenharmony_ci									}
1998e5c31af7Sopenharmony_ci
1999e5c31af7Sopenharmony_ci									collectionTestGroup->addChild(new UniformAssignCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection,
2000e5c31af7Sopenharmony_ci																						checkMethod, assignMethod,
2001e5c31af7Sopenharmony_ci																						booleanTypeFeat | arrayFirstElemNameNoIndexFeat | (matrixTypeI == 1 ? UniformCase::FEATURE_MATRIXMODE_ROWMAJOR : 0)));
2002e5c31af7Sopenharmony_ci								}
2003e5c31af7Sopenharmony_ci							}
2004e5c31af7Sopenharmony_ci						}
2005e5c31af7Sopenharmony_ci					}
2006e5c31af7Sopenharmony_ci				}
2007e5c31af7Sopenharmony_ci			}
2008e5c31af7Sopenharmony_ci		}
2009e5c31af7Sopenharmony_ci	}
2010e5c31af7Sopenharmony_ci
2011e5c31af7Sopenharmony_ci	// Cases that assign multiple basic-array elements with one glProgramUniform*v() (i.e. the count parameter is bigger than 1).
2012e5c31af7Sopenharmony_ci
2013e5c31af7Sopenharmony_ci	{
2014e5c31af7Sopenharmony_ci		static const struct
2015e5c31af7Sopenharmony_ci		{
2016e5c31af7Sopenharmony_ci			UniformCase::Feature	arrayAssignMode;
2017e5c31af7Sopenharmony_ci			const char*				name;
2018e5c31af7Sopenharmony_ci			const char*				description;
2019e5c31af7Sopenharmony_ci		} arrayAssignGroups[] =
2020e5c31af7Sopenharmony_ci		{
2021e5c31af7Sopenharmony_ci			{ UniformCase::FEATURE_ARRAYASSIGN_FULL,			"basic_array_assign_full",		"Assign entire basic-type arrays per glProgramUniform*v() call"				},
2022e5c31af7Sopenharmony_ci			{ UniformCase::FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO,	"basic_array_assign_partial",	"Assign two elements of a basic-type array per glProgramUniform*v() call"	}
2023e5c31af7Sopenharmony_ci		};
2024e5c31af7Sopenharmony_ci
2025e5c31af7Sopenharmony_ci		for (int arrayAssignGroupNdx = 0; arrayAssignGroupNdx < DE_LENGTH_OF_ARRAY(arrayAssignGroups); arrayAssignGroupNdx++)
2026e5c31af7Sopenharmony_ci		{
2027e5c31af7Sopenharmony_ci			UniformCase::Feature	arrayAssignMode		= arrayAssignGroups[arrayAssignGroupNdx].arrayAssignMode;
2028e5c31af7Sopenharmony_ci			const char* const		groupName			= arrayAssignGroups[arrayAssignGroupNdx].name;
2029e5c31af7Sopenharmony_ci			const char* const		groupDesc			= arrayAssignGroups[arrayAssignGroupNdx].description;
2030e5c31af7Sopenharmony_ci
2031e5c31af7Sopenharmony_ci			TestCaseGroup* const curArrayAssignGroup = new TestCaseGroup(m_context, groupName, groupDesc);
2032e5c31af7Sopenharmony_ci			addChild(curArrayAssignGroup);
2033e5c31af7Sopenharmony_ci
2034e5c31af7Sopenharmony_ci			static const int basicArrayCollectionGroups[] = { UNIFORMCOLLECTIONS_BASIC_ARRAY, UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT, UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY };
2035e5c31af7Sopenharmony_ci
2036e5c31af7Sopenharmony_ci			for (int collectionGroupNdx = 0; collectionGroupNdx < DE_LENGTH_OF_ARRAY(basicArrayCollectionGroups); collectionGroupNdx++)
2037e5c31af7Sopenharmony_ci			{
2038e5c31af7Sopenharmony_ci				const UniformCollectionGroup&	collectionGroup		= defaultUniformCollections[basicArrayCollectionGroups[collectionGroupNdx]];
2039e5c31af7Sopenharmony_ci				TestCaseGroup* const			collectionTestGroup	= new TestCaseGroup(m_context, collectionGroup.name.c_str(), "");
2040e5c31af7Sopenharmony_ci				curArrayAssignGroup->addChild(collectionTestGroup);
2041e5c31af7Sopenharmony_ci
2042e5c31af7Sopenharmony_ci				for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
2043e5c31af7Sopenharmony_ci				{
2044e5c31af7Sopenharmony_ci					const UniformCollectionCase&				collectionCase		= collectionGroup.cases[collectionNdx];
2045e5c31af7Sopenharmony_ci					const string								collName			= collectionCase.namePrefix;
2046e5c31af7Sopenharmony_ci					const SharedPtr<const UniformCollection>&	uniformCollection	= collectionCase.uniformCollection;
2047e5c31af7Sopenharmony_ci
2048e5c31af7Sopenharmony_ci					for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
2049e5c31af7Sopenharmony_ci					{
2050e5c31af7Sopenharmony_ci						const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType);
2051e5c31af7Sopenharmony_ci						collectionTestGroup->addChild(new UniformAssignCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection,
2052e5c31af7Sopenharmony_ci																			UniformAssignCase::CHECKMETHOD_GET_UNIFORM, UniformAssignCase::ASSIGNMETHOD_POINTER,
2053e5c31af7Sopenharmony_ci																			arrayAssignMode));
2054e5c31af7Sopenharmony_ci					}
2055e5c31af7Sopenharmony_ci				}
2056e5c31af7Sopenharmony_ci			}
2057e5c31af7Sopenharmony_ci		}
2058e5c31af7Sopenharmony_ci	}
2059e5c31af7Sopenharmony_ci
2060e5c31af7Sopenharmony_ci	// Cases with unused uniforms.
2061e5c31af7Sopenharmony_ci
2062e5c31af7Sopenharmony_ci	{
2063e5c31af7Sopenharmony_ci		TestCaseGroup* const unusedUniformsGroup = new TestCaseGroup(m_context, "unused_uniforms", "Test with unused uniforms");
2064e5c31af7Sopenharmony_ci		addChild(unusedUniformsGroup);
2065e5c31af7Sopenharmony_ci
2066e5c31af7Sopenharmony_ci		const UniformCollectionGroup& collectionGroup = defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT];
2067e5c31af7Sopenharmony_ci
2068e5c31af7Sopenharmony_ci		for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
2069e5c31af7Sopenharmony_ci		{
2070e5c31af7Sopenharmony_ci			const UniformCollectionCase&				collectionCase		= collectionGroup.cases[collectionNdx];
2071e5c31af7Sopenharmony_ci			const string								collName			= collectionCase.namePrefix;
2072e5c31af7Sopenharmony_ci			const SharedPtr<const UniformCollection>&	uniformCollection	= collectionCase.uniformCollection;
2073e5c31af7Sopenharmony_ci
2074e5c31af7Sopenharmony_ci			for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
2075e5c31af7Sopenharmony_ci			{
2076e5c31af7Sopenharmony_ci				const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType);
2077e5c31af7Sopenharmony_ci				unusedUniformsGroup->addChild(new UniformAssignCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection,
2078e5c31af7Sopenharmony_ci																	UniformAssignCase::CHECKMETHOD_GET_UNIFORM, UniformAssignCase::ASSIGNMETHOD_POINTER,
2079e5c31af7Sopenharmony_ci																	UniformCase::FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX | UniformCase::FEATURE_UNIFORMUSAGE_EVERY_OTHER));
2080e5c31af7Sopenharmony_ci			}
2081e5c31af7Sopenharmony_ci		}
2082e5c31af7Sopenharmony_ci	}
2083e5c31af7Sopenharmony_ci}
2084e5c31af7Sopenharmony_ci
2085e5c31af7Sopenharmony_ci} // Functional
2086e5c31af7Sopenharmony_ci} // gles31
2087e5c31af7Sopenharmony_ci} // deqp
2088