1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Uniform API tests.
22 *
23 * \todo [2013-02-26 nuutti] Much duplication between this and ES2.
24 * Utilities to glshared?
25 *//*--------------------------------------------------------------------*/
26
27 #include "es3fUniformApiTests.hpp"
28 #include "gluCallLogWrapper.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "gluVarType.hpp"
31 #include "gluPixelTransfer.hpp"
32 #include "gluTextureUtil.hpp"
33 #include "gluTexture.hpp"
34 #include "tcuRenderTarget.hpp"
35 #include "tcuTestLog.hpp"
36 #include "tcuSurface.hpp"
37 #include "tcuCommandLine.hpp"
38 #include "deRandom.hpp"
39 #include "deStringUtil.hpp"
40 #include "deString.h"
41 #include "deSharedPtr.hpp"
42 #include "deMemory.h"
43
44 #include "glwEnums.hpp"
45 #include "glwFunctions.hpp"
46
47 #include <set>
48 #include <cstring>
49
50 using namespace glw;
51
52 namespace deqp
53 {
54 namespace gles3
55 {
56 namespace Functional
57 {
58
59 using std::vector;
60 using std::string;
61 using tcu::TestLog;
62 using tcu::ScopedLogSection;
63 using glu::ShaderProgram;
64 using glu::StructType;
65 using de::Random;
66 using de::SharedPtr;
67
68 typedef bool (* dataTypePredicate)(glu::DataType);
69
70 static const int MAX_RENDER_WIDTH = 32;
71 static const int MAX_RENDER_HEIGHT = 32;
72 static const int MAX_NUM_SAMPLER_UNIFORMS = 16;
73
74 static const glu::DataType s_testDataTypes[] =
75 {
76 glu::TYPE_FLOAT,
77 glu::TYPE_FLOAT_VEC2,
78 glu::TYPE_FLOAT_VEC3,
79 glu::TYPE_FLOAT_VEC4,
80 glu::TYPE_FLOAT_MAT2,
81 glu::TYPE_FLOAT_MAT2X3,
82 glu::TYPE_FLOAT_MAT2X4,
83 glu::TYPE_FLOAT_MAT3X2,
84 glu::TYPE_FLOAT_MAT3,
85 glu::TYPE_FLOAT_MAT3X4,
86 glu::TYPE_FLOAT_MAT4X2,
87 glu::TYPE_FLOAT_MAT4X3,
88 glu::TYPE_FLOAT_MAT4,
89
90 glu::TYPE_INT,
91 glu::TYPE_INT_VEC2,
92 glu::TYPE_INT_VEC3,
93 glu::TYPE_INT_VEC4,
94
95 glu::TYPE_UINT,
96 glu::TYPE_UINT_VEC2,
97 glu::TYPE_UINT_VEC3,
98 glu::TYPE_UINT_VEC4,
99
100 glu::TYPE_BOOL,
101 glu::TYPE_BOOL_VEC2,
102 glu::TYPE_BOOL_VEC3,
103 glu::TYPE_BOOL_VEC4,
104
105 glu::TYPE_SAMPLER_2D,
106 glu::TYPE_SAMPLER_CUBE
107 // \note We don't test all sampler types here.
108 };
109
getGLInt(const glw::Functions & funcs,const deUint32 name)110 static inline int getGLInt (const glw::Functions& funcs, const deUint32 name)
111 {
112 int val = -1;
113 funcs.getIntegerv(name, &val);
114 return val;
115 }
116
vec4FromPtr(const float * const ptr)117 static inline tcu::Vec4 vec4FromPtr (const float* const ptr)
118 {
119 tcu::Vec4 result;
120 for (int i = 0; i < 4; i++)
121 result[i] = ptr[i];
122 return result;
123 }
124
beforeLast(const string & str,const char c)125 static inline string beforeLast (const string& str, const char c)
126 {
127 return str.substr(0, str.find_last_of(c));
128 }
129
fillWithColor(const tcu::PixelBufferAccess & access,const tcu::Vec4 & color)130 static inline void fillWithColor (const tcu::PixelBufferAccess& access, const tcu::Vec4& color)
131 {
132 for (int z = 0; z < access.getDepth(); z++)
133 for (int y = 0; y < access.getHeight(); y++)
134 for (int x = 0; x < access.getWidth(); x++)
135 access.setPixel(color, x, y, z);
136 }
137
getSamplerNumLookupDimensions(const glu::DataType type)138 static inline int getSamplerNumLookupDimensions (const glu::DataType type)
139 {
140 switch (type)
141 {
142 case glu::TYPE_SAMPLER_2D:
143 case glu::TYPE_INT_SAMPLER_2D:
144 case glu::TYPE_UINT_SAMPLER_2D:
145 return 2;
146
147 case glu::TYPE_SAMPLER_3D:
148 case glu::TYPE_INT_SAMPLER_3D:
149 case glu::TYPE_UINT_SAMPLER_3D:
150 case glu::TYPE_SAMPLER_2D_SHADOW:
151 case glu::TYPE_SAMPLER_2D_ARRAY:
152 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
153 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
154 case glu::TYPE_SAMPLER_CUBE:
155 case glu::TYPE_INT_SAMPLER_CUBE:
156 case glu::TYPE_UINT_SAMPLER_CUBE:
157 return 3;
158
159 case glu::TYPE_SAMPLER_CUBE_SHADOW:
160 case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
161 return 4;
162
163 default:
164 DE_ASSERT(false);
165 return 0;
166 }
167 }
168
getSamplerLookupReturnType(const glu::DataType type)169 static inline glu::DataType getSamplerLookupReturnType (const glu::DataType type)
170 {
171 switch (type)
172 {
173 case glu::TYPE_SAMPLER_2D:
174 case glu::TYPE_SAMPLER_CUBE:
175 case glu::TYPE_SAMPLER_2D_ARRAY:
176 case glu::TYPE_SAMPLER_3D:
177 return glu::TYPE_FLOAT_VEC4;
178
179 case glu::TYPE_UINT_SAMPLER_2D:
180 case glu::TYPE_UINT_SAMPLER_CUBE:
181 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
182 case glu::TYPE_UINT_SAMPLER_3D:
183 return glu::TYPE_UINT_VEC4;
184
185 case glu::TYPE_INT_SAMPLER_2D:
186 case glu::TYPE_INT_SAMPLER_CUBE:
187 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
188 case glu::TYPE_INT_SAMPLER_3D:
189 return glu::TYPE_INT_VEC4;
190
191 case glu::TYPE_SAMPLER_2D_SHADOW:
192 case glu::TYPE_SAMPLER_CUBE_SHADOW:
193 case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
194 return glu::TYPE_FLOAT;
195
196 default:
197 DE_ASSERT(false);
198 return glu::TYPE_LAST;
199 }
200 }
201
202 template<glu::DataType T>
dataTypeEquals(const glu::DataType t)203 static bool dataTypeEquals (const glu::DataType t)
204 {
205 return t == T;
206 }
207
208 template<int N>
dataTypeIsMatrixWithNRows(const glu::DataType t)209 static bool dataTypeIsMatrixWithNRows (const glu::DataType t)
210 {
211 return glu::isDataTypeMatrix(t) && glu::getDataTypeMatrixNumRows(t) == N;
212 }
213
typeContainsMatchingBasicType(const glu::VarType & type,const dataTypePredicate predicate)214 static bool typeContainsMatchingBasicType (const glu::VarType& type, const dataTypePredicate predicate)
215 {
216 if (type.isBasicType())
217 return predicate(type.getBasicType());
218 else if (type.isArrayType())
219 return typeContainsMatchingBasicType(type.getElementType(), predicate);
220 else
221 {
222 DE_ASSERT(type.isStructType());
223 const StructType& structType = *type.getStructPtr();
224 for (int i = 0; i < structType.getNumMembers(); i++)
225 if (typeContainsMatchingBasicType(structType.getMember(i).getType(), predicate))
226 return true;
227 return false;
228 }
229 }
230
getDistinctSamplerTypes(vector<glu::DataType> & dst,const glu::VarType & type)231 static void getDistinctSamplerTypes (vector<glu::DataType>& dst, const glu::VarType& type)
232 {
233 if (type.isBasicType())
234 {
235 const glu::DataType basicType = type.getBasicType();
236 if (glu::isDataTypeSampler(basicType) && std::find(dst.begin(), dst.end(), basicType) == dst.end())
237 dst.push_back(basicType);
238 }
239 else if (type.isArrayType())
240 getDistinctSamplerTypes(dst, type.getElementType());
241 else
242 {
243 DE_ASSERT(type.isStructType());
244 const StructType& structType = *type.getStructPtr();
245 for (int i = 0; i < structType.getNumMembers(); i++)
246 getDistinctSamplerTypes(dst, structType.getMember(i).getType());
247 }
248 }
249
getNumSamplersInType(const glu::VarType & type)250 static int getNumSamplersInType (const glu::VarType& type)
251 {
252 if (type.isBasicType())
253 return glu::isDataTypeSampler(type.getBasicType()) ? 1 : 0;
254 else if (type.isArrayType())
255 return getNumSamplersInType(type.getElementType()) * type.getArraySize();
256 else
257 {
258 DE_ASSERT(type.isStructType());
259 const StructType& structType = *type.getStructPtr();
260 int sum = 0;
261 for (int i = 0; i < structType.getNumMembers(); i++)
262 sum += getNumSamplersInType(structType.getMember(i).getType());
263 return sum;
264 }
265 }
266
generateRandomType(const int maxDepth,int & curStructIdx,vector<const StructType * > & structTypesDst,Random & rnd)267 static glu::VarType generateRandomType (const int maxDepth, int& curStructIdx, vector<const StructType*>& structTypesDst, Random& rnd)
268 {
269 const bool isStruct = maxDepth > 0 && rnd.getFloat() < 0.2f;
270 const bool isArray = rnd.getFloat() < 0.3f;
271
272 if (isStruct)
273 {
274 const int numMembers = rnd.getInt(1, 5);
275 StructType* const structType = new StructType(("structType" + de::toString(curStructIdx++)).c_str());
276
277 for (int i = 0; i < numMembers; i++)
278 structType->addMember(("m" + de::toString(i)).c_str(), generateRandomType(maxDepth-1, curStructIdx, structTypesDst, rnd));
279
280 structTypesDst.push_back(structType);
281 return isArray ? glu::VarType(glu::VarType(structType), rnd.getInt(1, 5)) : glu::VarType(structType);
282 }
283 else
284 {
285 const glu::DataType basicType = (glu::DataType)s_testDataTypes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testDataTypes)-1)];
286 const glu::Precision precision = glu::isDataTypeBoolOrBVec(basicType) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
287 return isArray ? glu::VarType(glu::VarType(basicType, precision), rnd.getInt(1, 5)) : glu::VarType(basicType, precision);
288 }
289 }
290
291 namespace
292 {
293
294 struct VarValue
295 {
296 glu::DataType type;
297
298 union
299 {
300 float floatV[4*4]; // At most mat4. \note Matrices here are column-major.
301 deInt32 intV[4];
302 deUint32 uintV[4];
303 bool boolV[4];
304 struct
305 {
306 int unit;
307 union
308 {
309 float floatV[4];
310 deInt32 intV[4];
311 deUint32 uintV[4];
312 } fillColor;
313 } samplerV;
314 } val;
315 };
316
317 enum CaseShaderType
318 {
319 CASESHADERTYPE_VERTEX = 0,
320 CASESHADERTYPE_FRAGMENT,
321 CASESHADERTYPE_BOTH,
322
323 CASESHADERTYPE_LAST
324 };
325
326 struct Uniform
327 {
328 string name;
329 glu::VarType type;
330
Uniformdeqp::gles3::Functional::__anon861d11500111::Uniform331 Uniform (const char* const name_, const glu::VarType& type_) : name(name_), type(type_) {}
332 };
333
334 // A set of uniforms, along with related struct types.
335 class UniformCollection
336 {
337 public:
getNumUniforms(void) const338 int getNumUniforms (void) const { return (int)m_uniforms.size(); }
getNumStructTypes(void) const339 int getNumStructTypes (void) const { return (int)m_structTypes.size(); }
getUniform(const int ndx)340 Uniform& getUniform (const int ndx) { return m_uniforms[ndx]; }
getUniform(const int ndx) const341 const Uniform& getUniform (const int ndx) const { return m_uniforms[ndx]; }
getStructType(const int ndx) const342 const StructType* getStructType (const int ndx) const { return m_structTypes[ndx]; }
addUniform(const Uniform & uniform)343 void addUniform (const Uniform& uniform) { m_uniforms.push_back(uniform); }
addStructType(const StructType * const type)344 void addStructType (const StructType* const type) { m_structTypes.push_back(type); }
345
UniformCollection(void)346 UniformCollection (void) {}
~UniformCollection(void)347 ~UniformCollection (void)
348 {
349 for (int i = 0; i < (int)m_structTypes.size(); i++)
350 delete m_structTypes[i];
351 }
352
353 // Add the contents of m_uniforms and m_structTypes to receiver, and remove them from this one.
354 // \note receiver takes ownership of the struct types.
moveContents(UniformCollection & receiver)355 void moveContents (UniformCollection& receiver)
356 {
357 for (int i = 0; i < (int)m_uniforms.size(); i++)
358 receiver.addUniform(m_uniforms[i]);
359 m_uniforms.clear();
360
361 for (int i = 0; i < (int)m_structTypes.size(); i++)
362 receiver.addStructType(m_structTypes[i]);
363 m_structTypes.clear();
364 }
365
containsMatchingBasicType(const dataTypePredicate predicate) const366 bool containsMatchingBasicType (const dataTypePredicate predicate) const
367 {
368 for (int i = 0; i < (int)m_uniforms.size(); i++)
369 if (typeContainsMatchingBasicType(m_uniforms[i].type, predicate))
370 return true;
371 return false;
372 }
373
getSamplerTypes(void) const374 vector<glu::DataType> getSamplerTypes (void) const
375 {
376 vector<glu::DataType> samplerTypes;
377 for (int i = 0; i < (int)m_uniforms.size(); i++)
378 getDistinctSamplerTypes(samplerTypes, m_uniforms[i].type);
379 return samplerTypes;
380 }
381
containsSeveralSamplerTypes(void) const382 bool containsSeveralSamplerTypes (void) const
383 {
384 return getSamplerTypes().size() > 1;
385 }
386
getNumSamplers(void) const387 int getNumSamplers (void) const
388 {
389 int sum = 0;
390 for (int i = 0; i < (int)m_uniforms.size(); i++)
391 sum += getNumSamplersInType(m_uniforms[i].type);
392 return sum;
393 }
394
basic(const glu::DataType type,const char * const nameSuffix="")395 static UniformCollection* basic (const glu::DataType type, const char* const nameSuffix = "")
396 {
397 UniformCollection* const res = new UniformCollection;
398 const glu::Precision prec = glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
399 res->m_uniforms.push_back(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(type, prec)));
400 return res;
401 }
402
basicArray(const glu::DataType type,const char * const nameSuffix="")403 static UniformCollection* basicArray (const glu::DataType type, const char* const nameSuffix = "")
404 {
405 UniformCollection* const res = new UniformCollection;
406 const glu::Precision prec = glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
407 res->m_uniforms.push_back(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(glu::VarType(type, prec), 3)));
408 return res;
409 }
410
basicStruct(const glu::DataType type0,const glu::DataType type1,const bool containsArrays,const char * const nameSuffix="")411 static UniformCollection* basicStruct (const glu::DataType type0, const glu::DataType type1, const bool containsArrays, const char* const nameSuffix = "")
412 {
413 UniformCollection* const res = new UniformCollection;
414 const glu::Precision prec0 = glu::isDataTypeBoolOrBVec(type0) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
415 const glu::Precision prec1 = glu::isDataTypeBoolOrBVec(type1) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
416
417 StructType* const structType = new StructType((string("structType") + nameSuffix).c_str());
418 structType->addMember("m0", glu::VarType(type0, prec0));
419 structType->addMember("m1", glu::VarType(type1, prec1));
420 if (containsArrays)
421 {
422 structType->addMember("m2", glu::VarType(glu::VarType(type0, prec0), 3));
423 structType->addMember("m3", glu::VarType(glu::VarType(type1, prec1), 3));
424 }
425
426 res->addStructType(structType);
427 res->addUniform(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(structType)));
428
429 return res;
430 }
431
structInArray(const glu::DataType type0,const glu::DataType type1,const bool containsArrays,const char * const nameSuffix="")432 static UniformCollection* structInArray (const glu::DataType type0, const glu::DataType type1, const bool containsArrays, const char* const nameSuffix = "")
433 {
434 UniformCollection* const res = basicStruct(type0, type1, containsArrays, nameSuffix);
435 res->getUniform(0).type = glu::VarType(res->getUniform(0).type, 3);
436 return res;
437 }
438
nestedArraysStructs(const glu::DataType type0,const glu::DataType type1,const char * const nameSuffix="")439 static UniformCollection* nestedArraysStructs (const glu::DataType type0, const glu::DataType type1, const char* const nameSuffix = "")
440 {
441 UniformCollection* const res = new UniformCollection;
442 const glu::Precision prec0 = glu::isDataTypeBoolOrBVec(type0) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
443 const glu::Precision prec1 = glu::isDataTypeBoolOrBVec(type1) ? glu::PRECISION_LAST : glu::PRECISION_MEDIUMP;
444 StructType* const structType = new StructType((string("structType") + nameSuffix).c_str());
445 StructType* const subStructType = new StructType((string("subStructType") + nameSuffix).c_str());
446 StructType* const subSubStructType = new StructType((string("subSubStructType") + nameSuffix).c_str());
447
448 subSubStructType->addMember("mss0", glu::VarType(type0, prec0));
449 subSubStructType->addMember("mss1", glu::VarType(type1, prec1));
450
451 subStructType->addMember("ms0", glu::VarType(type1, prec1));
452 subStructType->addMember("ms1", glu::VarType(glu::VarType(type0, prec0), 2));
453 subStructType->addMember("ms2", glu::VarType(glu::VarType(subSubStructType), 2));
454
455 structType->addMember("m0", glu::VarType(type0, prec0));
456 structType->addMember("m1", glu::VarType(subStructType));
457 structType->addMember("m2", glu::VarType(type1, prec1));
458
459 res->addStructType(subSubStructType);
460 res->addStructType(subStructType);
461 res->addStructType(structType);
462
463 res->addUniform(Uniform((string("u_var") + nameSuffix).c_str(), glu::VarType(structType)));
464
465 return res;
466 }
467
multipleBasic(const char * const nameSuffix="")468 static UniformCollection* multipleBasic (const char* const nameSuffix = "")
469 {
470 static const glu::DataType types[] = { glu::TYPE_FLOAT, glu::TYPE_INT_VEC3, glu::TYPE_UINT_VEC4, glu::TYPE_FLOAT_MAT3, glu::TYPE_BOOL_VEC2 };
471 UniformCollection* const res = new UniformCollection;
472
473 for (int i = 0; i < DE_LENGTH_OF_ARRAY(types); i++)
474 {
475 UniformCollection* const sub = basic(types[i], ("_" + de::toString(i) + nameSuffix).c_str());
476 sub->moveContents(*res);
477 delete sub;
478 }
479
480 return res;
481 }
482
multipleBasicArray(const char * const nameSuffix="")483 static UniformCollection* multipleBasicArray (const char* const nameSuffix = "")
484 {
485 static const glu::DataType types[] = { glu::TYPE_FLOAT, glu::TYPE_INT_VEC3, glu::TYPE_BOOL_VEC2 };
486 UniformCollection* const res = new UniformCollection;
487
488 for (int i = 0; i < DE_LENGTH_OF_ARRAY(types); i++)
489 {
490 UniformCollection* const sub = basicArray(types[i], ("_" + de::toString(i) + nameSuffix).c_str());
491 sub->moveContents(*res);
492 delete sub;
493 }
494
495 return res;
496 }
497
multipleNestedArraysStructs(const char * const nameSuffix="")498 static UniformCollection* multipleNestedArraysStructs (const char* const nameSuffix = "")
499 {
500 static const glu::DataType types0[] = { glu::TYPE_FLOAT, glu::TYPE_INT, glu::TYPE_BOOL_VEC4 };
501 static const glu::DataType types1[] = { glu::TYPE_FLOAT_VEC4, glu::TYPE_INT_VEC4, glu::TYPE_BOOL };
502 UniformCollection* const res = new UniformCollection;
503
504 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types0) == DE_LENGTH_OF_ARRAY(types1));
505
506 for (int i = 0; i < DE_LENGTH_OF_ARRAY(types0); i++)
507 {
508 UniformCollection* const sub = nestedArraysStructs(types0[i], types1[i], ("_" + de::toString(i) + nameSuffix).c_str());
509 sub->moveContents(*res);
510 delete sub;
511 }
512
513 return res;
514 }
515
random(const deUint32 seed)516 static UniformCollection* random (const deUint32 seed)
517 {
518 Random rnd (seed);
519 const int numUniforms = rnd.getInt(1, 5);
520 int structIdx = 0;
521 UniformCollection* const res = new UniformCollection;
522
523 for (int i = 0; i < numUniforms; i++)
524 {
525 vector<const StructType*> structTypes;
526 Uniform uniform(("u_var" + de::toString(i)).c_str(), glu::VarType());
527
528 // \note Discard uniforms that would cause number of samplers to exceed MAX_NUM_SAMPLER_UNIFORMS.
529 do
530 {
531 for (int j = 0; j < (int)structTypes.size(); j++)
532 delete structTypes[j];
533 structTypes.clear();
534 uniform.type = (("u_var" + de::toString(i)).c_str(), generateRandomType(3, structIdx, structTypes, rnd));
535 } while (res->getNumSamplers() + getNumSamplersInType(uniform.type) > MAX_NUM_SAMPLER_UNIFORMS);
536
537 res->addUniform(uniform);
538 for (int j = 0; j < (int)structTypes.size(); j++)
539 res->addStructType(structTypes[j]);
540 }
541
542 return res;
543 }
544
545 private:
546 // \note Copying these would be cumbersome, since deep-copying both m_uniforms and m_structTypes
547 // would mean that we'd need to update pointers from uniforms to point to the new structTypes.
548 // When the same UniformCollection is needed in several places, a SharedPtr is used instead.
549 UniformCollection (const UniformCollection&); // Not allowed.
550 UniformCollection& operator= (const UniformCollection&); // Not allowed.
551
552 vector<Uniform> m_uniforms;
553 vector<const StructType*> m_structTypes;
554 };
555
556 }; // anonymous
557
getSamplerFillValue(const VarValue & sampler)558 static VarValue getSamplerFillValue (const VarValue& sampler)
559 {
560 DE_ASSERT(glu::isDataTypeSampler(sampler.type));
561
562 VarValue result;
563 result.type = getSamplerLookupReturnType(sampler.type);
564
565 switch (result.type)
566 {
567 case glu::TYPE_FLOAT_VEC4:
568 for (int i = 0; i < 4; i++)
569 result.val.floatV[i] = sampler.val.samplerV.fillColor.floatV[i];
570 break;
571 case glu::TYPE_UINT_VEC4:
572 for (int i = 0; i < 4; i++)
573 result.val.uintV[i] = sampler.val.samplerV.fillColor.uintV[i];
574 break;
575 case glu::TYPE_INT_VEC4:
576 for (int i = 0; i < 4; i++)
577 result.val.intV[i] = sampler.val.samplerV.fillColor.intV[i];
578 break;
579 case glu::TYPE_FLOAT:
580 result.val.floatV[0] = sampler.val.samplerV.fillColor.floatV[0];
581 break;
582 default:
583 DE_ASSERT(false);
584 }
585
586 return result;
587 }
588
getSamplerUnitValue(const VarValue & sampler)589 static VarValue getSamplerUnitValue (const VarValue& sampler)
590 {
591 DE_ASSERT(glu::isDataTypeSampler(sampler.type));
592
593 VarValue result;
594 result.type = glu::TYPE_INT;
595 result.val.intV[0] = sampler.val.samplerV.unit;
596
597 return result;
598 }
599
getDataTypeTransposedMatrix(const glu::DataType original)600 static glu::DataType getDataTypeTransposedMatrix (const glu::DataType original)
601 {
602 return glu::getDataTypeMatrix(glu::getDataTypeMatrixNumRows(original), glu::getDataTypeMatrixNumColumns(original));
603 }
604
getTransposeMatrix(const VarValue & original)605 static VarValue getTransposeMatrix (const VarValue& original)
606 {
607 DE_ASSERT(glu::isDataTypeMatrix(original.type));
608
609 const int rows = glu::getDataTypeMatrixNumRows(original.type);
610 const int cols = glu::getDataTypeMatrixNumColumns(original.type);
611 VarValue result;
612 result.type = getDataTypeTransposedMatrix(original.type);
613
614 for (int i = 0; i < rows; i++)
615 for (int j = 0; j < cols; j++)
616 result.val.floatV[i*cols + j] = original.val.floatV[j*rows + i];
617
618 return result;
619 }
620
shaderVarValueStr(const VarValue & value)621 static string shaderVarValueStr (const VarValue& value)
622 {
623 const int numElems = glu::getDataTypeScalarSize(value.type);
624 std::ostringstream result;
625
626 if (numElems > 1)
627 result << glu::getDataTypeName(value.type) << "(";
628
629 for (int i = 0; i < numElems; i++)
630 {
631 if (i > 0)
632 result << ", ";
633
634 if (glu::isDataTypeFloatOrVec(value.type) || glu::isDataTypeMatrix(value.type))
635 result << de::floatToString(value.val.floatV[i], 2);
636 else if (glu::isDataTypeIntOrIVec((value.type)))
637 result << de::toString(value.val.intV[i]);
638 else if (glu::isDataTypeUintOrUVec((value.type)))
639 result << de::toString(value.val.uintV[i]) << "u";
640 else if (glu::isDataTypeBoolOrBVec((value.type)))
641 result << (value.val.boolV[i] ? "true" : "false");
642 else if (glu::isDataTypeSampler((value.type)))
643 result << shaderVarValueStr(getSamplerFillValue(value));
644 else
645 DE_ASSERT(false);
646 }
647
648 if (numElems > 1)
649 result << ")";
650
651 return result.str();
652 }
653
apiVarValueStr(const VarValue & value)654 static string apiVarValueStr (const VarValue& value)
655 {
656 const int numElems = glu::getDataTypeScalarSize(value.type);
657 std::ostringstream result;
658
659 if (numElems > 1)
660 result << "(";
661
662 for (int i = 0; i < numElems; i++)
663 {
664 if (i > 0)
665 result << ", ";
666
667 if (glu::isDataTypeFloatOrVec(value.type) || glu::isDataTypeMatrix(value.type))
668 result << de::floatToString(value.val.floatV[i], 2);
669 else if (glu::isDataTypeIntOrIVec((value.type)))
670 result << de::toString(value.val.intV[i]);
671 else if (glu::isDataTypeUintOrUVec((value.type)))
672 result << de::toString(value.val.uintV[i]);
673 else if (glu::isDataTypeBoolOrBVec((value.type)))
674 result << (value.val.boolV[i] ? "true" : "false");
675 else if (glu::isDataTypeSampler((value.type)))
676 result << value.val.samplerV.unit;
677 else
678 DE_ASSERT(false);
679 }
680
681 if (numElems > 1)
682 result << ")";
683
684 return result.str();
685 }
686
generateRandomVarValue(const glu::DataType type,Random & rnd,int samplerUnit=-1)687 static 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. */)
688 {
689 const int numElems = glu::getDataTypeScalarSize(type);
690 VarValue result;
691 result.type = type;
692
693 DE_ASSERT((samplerUnit >= 0) == (glu::isDataTypeSampler(type)));
694
695 if (glu::isDataTypeFloatOrVec(type) || glu::isDataTypeMatrix(type))
696 {
697 for (int i = 0; i < numElems; i++)
698 result.val.floatV[i] = rnd.getFloat(-10.0f, 10.0f);
699 }
700 else if (glu::isDataTypeIntOrIVec(type))
701 {
702 for (int i = 0; i < numElems; i++)
703 result.val.intV[i] = rnd.getInt(-10, 10);
704 }
705 else if (glu::isDataTypeUintOrUVec(type))
706 {
707 for (int i = 0; i < numElems; i++)
708 result.val.uintV[i] = (deUint32)rnd.getInt(0, 10);
709 }
710 else if (glu::isDataTypeBoolOrBVec(type))
711 {
712 for (int i = 0; i < numElems; i++)
713 result.val.boolV[i] = rnd.getBool();
714 }
715 else if (glu::isDataTypeSampler(type))
716 {
717 const glu::DataType texResultType = getSamplerLookupReturnType(type);
718 const glu::DataType texResultScalarType = glu::getDataTypeScalarType(texResultType);
719 const int texResultNumDims = glu::getDataTypeScalarSize(texResultType);
720
721 result.val.samplerV.unit = samplerUnit;
722
723 for (int i = 0; i < texResultNumDims; i++)
724 {
725 switch (texResultScalarType)
726 {
727 case glu::TYPE_FLOAT: result.val.samplerV.fillColor.floatV[i] = rnd.getFloat(0.0f, 1.0f); break;
728 case glu::TYPE_INT: result.val.samplerV.fillColor.intV[i] = rnd.getInt(-10, 10); break;
729 case glu::TYPE_UINT: result.val.samplerV.fillColor.uintV[i] = (deUint32)rnd.getInt(0, 10); break;
730 default:
731 DE_ASSERT(false);
732 }
733 }
734 }
735 else
736 DE_ASSERT(false);
737
738 return result;
739 }
740
generateZeroVarValue(const glu::DataType type)741 static VarValue generateZeroVarValue (const glu::DataType type)
742 {
743 const int numElems = glu::getDataTypeScalarSize(type);
744 VarValue result;
745 result.type = type;
746
747 if (glu::isDataTypeFloatOrVec(type) || glu::isDataTypeMatrix(type))
748 {
749 for (int i = 0; i < numElems; i++)
750 result.val.floatV[i] = 0.0f;
751 }
752 else if (glu::isDataTypeIntOrIVec(type))
753 {
754 for (int i = 0; i < numElems; i++)
755 result.val.intV[i] = 0;
756 }
757 else if (glu::isDataTypeUintOrUVec(type))
758 {
759 for (int i = 0; i < numElems; i++)
760 result.val.uintV[i] = 0u;
761 }
762 else if (glu::isDataTypeBoolOrBVec(type))
763 {
764 for (int i = 0; i < numElems; i++)
765 result.val.boolV[i] = false;
766 }
767 else if (glu::isDataTypeSampler(type))
768 {
769 const glu::DataType texResultType = getSamplerLookupReturnType(type);
770 const glu::DataType texResultScalarType = glu::getDataTypeScalarType(texResultType);
771 const int texResultNumDims = glu::getDataTypeScalarSize(texResultType);
772
773 result.val.samplerV.unit = 0;
774
775 for (int i = 0; i < texResultNumDims; i++)
776 {
777 switch (texResultScalarType)
778 {
779 case glu::TYPE_FLOAT: result.val.samplerV.fillColor.floatV[i] = 0.12f * (float)i; break;
780 case glu::TYPE_INT: result.val.samplerV.fillColor.intV[i] = -2 + i; break;
781 case glu::TYPE_UINT: result.val.samplerV.fillColor.uintV[i] = 4 + i; break;
782 default:
783 DE_ASSERT(false);
784 }
785 }
786 }
787 else
788 DE_ASSERT(false);
789
790 return result;
791 }
792
apiVarValueEquals(const VarValue & a,const VarValue & b)793 static bool apiVarValueEquals (const VarValue& a, const VarValue& b)
794 {
795 const int size = glu::getDataTypeScalarSize(a.type);
796 const float floatThreshold = 0.05f;
797
798 DE_ASSERT(a.type == b.type);
799
800 if (glu::isDataTypeFloatOrVec(a.type) || glu::isDataTypeMatrix(a.type))
801 {
802 for (int i = 0; i < size; i++)
803 if (de::abs(a.val.floatV[i] - b.val.floatV[i]) >= floatThreshold)
804 return false;
805 }
806 else if (glu::isDataTypeIntOrIVec(a.type))
807 {
808 for (int i = 0; i < size; i++)
809 if (a.val.intV[i] != b.val.intV[i])
810 return false;
811 }
812 else if (glu::isDataTypeUintOrUVec(a.type))
813 {
814 for (int i = 0; i < size; i++)
815 if (a.val.uintV[i] != b.val.uintV[i])
816 return false;
817 }
818 else if (glu::isDataTypeBoolOrBVec(a.type))
819 {
820 for (int i = 0; i < size; i++)
821 if (a.val.boolV[i] != b.val.boolV[i])
822 return false;
823 }
824 else if (glu::isDataTypeSampler(a.type))
825 {
826 if (a.val.samplerV.unit != b.val.samplerV.unit)
827 return false;
828 }
829 else
830 DE_ASSERT(false);
831
832 return true;
833 }
834
getRandomBoolRepresentation(const VarValue & boolValue,const glu::DataType targetScalarType,Random & rnd)835 static VarValue getRandomBoolRepresentation (const VarValue& boolValue, const glu::DataType targetScalarType, Random& rnd)
836 {
837 DE_ASSERT(glu::isDataTypeBoolOrBVec(boolValue.type));
838
839 const int size = glu::getDataTypeScalarSize(boolValue.type);
840 const glu::DataType targetType = size == 1 ? targetScalarType : glu::getDataTypeVector(targetScalarType, size);
841 VarValue result;
842 result.type = targetType;
843
844 switch (targetScalarType)
845 {
846 case glu::TYPE_INT:
847 for (int i = 0; i < size; i++)
848 {
849 if (boolValue.val.boolV[i])
850 {
851 result.val.intV[i] = rnd.getInt(-10, 10);
852 if (result.val.intV[i] == 0)
853 result.val.intV[i] = 1;
854 }
855 else
856 result.val.intV[i] = 0;
857 }
858 break;
859
860 case glu::TYPE_UINT:
861 for (int i = 0; i < size; i++)
862 {
863 if (boolValue.val.boolV[i])
864 result.val.uintV[i] = rnd.getInt(1, 10);
865 else
866 result.val.uintV[i] = 0;
867 }
868 break;
869
870 case glu::TYPE_FLOAT:
871 for (int i = 0; i < size; i++)
872 {
873 if (boolValue.val.boolV[i])
874 {
875 result.val.floatV[i] = rnd.getFloat(-10.0f, 10.0f);
876 if (result.val.floatV[i] == 0.0f)
877 result.val.floatV[i] = 1.0f;
878 }
879 else
880 result.val.floatV[i] = 0;
881 }
882 break;
883
884 default:
885 DE_ASSERT(false);
886 }
887
888 return result;
889 }
890
getCaseShaderTypeName(const CaseShaderType type)891 static const char* getCaseShaderTypeName (const CaseShaderType type)
892 {
893 switch (type)
894 {
895 case CASESHADERTYPE_VERTEX: return "vertex";
896 case CASESHADERTYPE_FRAGMENT: return "fragment";
897 case CASESHADERTYPE_BOTH: return "both";
898 default:
899 DE_ASSERT(false);
900 return DE_NULL;
901 }
902 }
903
randomCaseShaderType(const deUint32 seed)904 static CaseShaderType randomCaseShaderType (const deUint32 seed)
905 {
906 return (CaseShaderType)Random(seed).getInt(0, CASESHADERTYPE_LAST-1);
907 }
908
909 class UniformCase : public TestCase, protected glu::CallLogWrapper
910 {
911 public:
912 enum Feature
913 {
914 // ARRAYUSAGE_ONLY_MIDDLE_INDEX: only middle index of each array is used in shader. If not given, use all indices.
915 FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX = 1<<0,
916
917 // UNIFORMFUNC_VALUE: use pass-by-value versions of uniform assignment funcs, e.g. glUniform1f(), where possible. If not given, use pass-by-pointer versions.
918 FEATURE_UNIFORMFUNC_VALUE = 1<<1,
919
920 // MATRIXMODE_ROWMAJOR: pass matrices to GL in row major form. If not given, use column major.
921 FEATURE_MATRIXMODE_ROWMAJOR = 1<<2,
922
923 // ARRAYASSIGN: how basic-type arrays are assigned with glUniform*(). If none given, assign each element of an array separately.
924 FEATURE_ARRAYASSIGN_FULL = 1<<3, //!< Assign all elements of an array with one glUniform*().
925 FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO = 1<<4, //!< Assign two elements per one glUniform*().
926
927 // 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).
928 FEATURE_UNIFORMUSAGE_EVERY_OTHER = 1<<5,
929
930 // BOOLEANAPITYPE: type used to pass booleans to and from GL api. If none given, use float.
931 FEATURE_BOOLEANAPITYPE_INT = 1<<6,
932 FEATURE_BOOLEANAPITYPE_UINT = 1<<7,
933
934 // UNIFORMVALUE_ZERO: use zero-valued uniforms. If not given, use random uniform values.
935 FEATURE_UNIFORMVALUE_ZERO = 1<<8,
936
937 // 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.
938 FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX = 1<<9
939 };
940
941 UniformCase (Context& context, const char* name, const char* description, CaseShaderType caseType, const SharedPtr<const UniformCollection>& uniformCollection);
942 UniformCase (Context& context, const char* name, const char* description, CaseShaderType caseType, const SharedPtr<const UniformCollection>& uniformCollection, deUint32 features);
943 UniformCase (Context& context, const char* name, const char* description, deUint32 seed); // \note Randomizes caseType, uniformCollection and features.
944 virtual ~UniformCase (void);
945
946 virtual void init (void);
947 virtual void deinit (void);
948
949 IterateResult iterate (void);
950
951 protected:
952 // A basic uniform is a uniform (possibly struct or array member) whose type is a basic type (e.g. float, ivec4, sampler2d).
953 struct BasicUniform
954 {
955 string name;
956 glu::DataType type;
957 bool isUsedInShader;
958 VarValue finalValue; //!< The value we ultimately want to set for this uniform.
959
960 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.
961 int elemNdx; //!< If this is a member of a basic-typed array, elemNdx is the index in that array. Otherwise -1.
962 int rootSize; //!< If this is a member of a basic-typed array, rootSize is the size of that array. Otherwise 1.
963
BasicUniformdeqp::gles3::Functional::UniformCase::BasicUniform964 BasicUniform (const char* const name_,
965 const glu::DataType type_,
966 const bool isUsedInShader_,
967 const VarValue& finalValue_,
968 const char* const rootName_ = DE_NULL,
969 const int elemNdx_ = -1,
970 const int rootSize_ = 1)
971 : name (name_)
972 , type (type_)
973 , isUsedInShader (isUsedInShader_)
974 , finalValue (finalValue_)
975 , rootName (rootName_ == DE_NULL ? name_ : rootName_)
976 , elemNdx (elemNdx_)
977 , rootSize (rootSize_)
978 {
979 }
980
findWithNamedeqp::gles3::Functional::UniformCase::BasicUniform981 static vector<BasicUniform>::const_iterator findWithName (const vector<BasicUniform>& vec, const char* const name)
982 {
983 for (vector<BasicUniform>::const_iterator it = vec.begin(); it != vec.end(); it++)
984 {
985 if (it->name == name)
986 return it;
987 }
988 return vec.end();
989 }
990 };
991
992 // Reference values for info that is expected to be reported by glGetActiveUniform() or glGetActiveUniformsiv().
993 struct BasicUniformReportRef
994 {
995 string name;
996 // \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.
997 int minSize;
998 int maxSize;
999 glu::DataType type;
1000 bool isUsedInShader;
1001
BasicUniformReportRefdeqp::gles3::Functional::UniformCase::BasicUniformReportRef1002 BasicUniformReportRef (const char* const name_, const int minS, const int maxS, const glu::DataType type_, const bool used)
1003 : name(name_), minSize(minS), maxSize(maxS), type(type_), isUsedInShader(used) { DE_ASSERT(minSize <= maxSize); }
BasicUniformReportRefdeqp::gles3::Functional::UniformCase::BasicUniformReportRef1004 BasicUniformReportRef (const char* const name_, const glu::DataType type_, const bool used)
1005 : name(name_), minSize(1), maxSize(1), type(type_), isUsedInShader(used) {}
1006 };
1007
1008 // Info that is actually reported by glGetActiveUniform() or glGetActiveUniformsiv().
1009 struct BasicUniformReportGL
1010 {
1011 string name;
1012 int nameLength; // \note Whether this includes the null byte depends on whether it was queried with glGetActiveUniform() or glGetActiveUniformsiv().
1013 int size;
1014 glu::DataType type;
1015
1016 int index;
1017
BasicUniformReportGLdeqp::gles3::Functional::UniformCase::BasicUniformReportGL1018 BasicUniformReportGL (const char* const name_, const int nameLength_, const int size_, const glu::DataType type_, const int index_)
1019 : name(name_), nameLength(nameLength_), size(size_), type(type_), index(index_) {}
1020
findWithNamedeqp::gles3::Functional::UniformCase::BasicUniformReportGL1021 static vector<BasicUniformReportGL>::const_iterator findWithName (const vector<BasicUniformReportGL>& vec, const char* const name)
1022 {
1023 for (vector<BasicUniformReportGL>::const_iterator it = vec.begin(); it != vec.end(); it++)
1024 {
1025 if (it->name == name)
1026 return it;
1027 }
1028 return vec.end();
1029 }
1030 };
1031
1032 // Query info with glGetActiveUniform() and check validity.
1033 bool getActiveUniforms (vector<BasicUniformReportGL>& dst, const vector<BasicUniformReportRef>& ref, deUint32 programGL);
1034 // Query info with glGetUniformIndices() + glGetActiveUniformsiv() and check validity.
1035 bool getActiveUniformsiv (vector<BasicUniformReportGL>& dst, const vector<BasicUniformReportRef>& ref, deUint32 programGL);
1036 // Compare infos returned by glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniformsiv().
1037 bool uniformVsUniformsivComparison (const vector<BasicUniformReportGL>& uniformsResult, const vector<BasicUniformReportGL>& uniformsivResult);
1038 // Get uniform values with glGetUniform*() and put to valuesDst. Uniforms that get -1 from glGetUniformLocation() get glu::TYPE_INVALID.
1039 bool getUniforms (vector<VarValue>& valuesDst, const vector<BasicUniform>& basicUniforms, deUint32 programGL);
1040 // Check that every uniform has the default (zero) value.
1041 bool checkUniformDefaultValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms);
1042 // Assign the basicUniforms[].finalValue values for uniforms. \note rnd parameter is for booleans (true can be any nonzero value).
1043 void assignUniforms (const vector<BasicUniform>& basicUniforms, deUint32 programGL, Random& rnd);
1044 // Compare the uniform values given in values (obtained with glGetUniform*()) with the basicUniform.finalValue values.
1045 bool compareUniformValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms);
1046 // Render and check that all pixels are white (i.e. all uniform comparisons passed).
1047 bool renderTest (const vector<BasicUniform>& basicUniforms, const ShaderProgram& program, Random& rnd);
1048
1049 virtual bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd) = 0;
1050
1051 const deUint32 m_features;
1052 const SharedPtr<const UniformCollection> m_uniformCollection;
1053
1054 private:
1055 static deUint32 randomFeatures (deUint32 seed);
1056
1057 // Generates the basic uniforms, based on the uniform with name varName and type varType, in the same manner as are expected
1058 // to be returned by glGetActiveUniform(), e.g. generates a name like var[0] for arrays, and recursively generates struct member names.
1059 void generateBasicUniforms (vector<BasicUniform>& basicUniformsDst,
1060 vector<BasicUniformReportRef>& basicUniformReportsDst,
1061 const glu::VarType& varType,
1062 const char* varName,
1063 bool isParentActive,
1064 int& samplerUnitCounter,
1065 Random& rnd) const;
1066
1067 void writeUniformDefinitions (std::ostringstream& dst) const;
1068 void writeUniformCompareExpr (std::ostringstream& dst, const BasicUniform& uniform) const;
1069 void writeUniformComparisons (std::ostringstream& dst, const vector<BasicUniform>& basicUniforms, const char* variableName) const;
1070
1071 string generateVertexSource (const vector<BasicUniform>& basicUniforms) const;
1072 string generateFragmentSource (const vector<BasicUniform>& basicUniforms) const;
1073
1074 void setupTexture (const VarValue& value);
1075
1076 const CaseShaderType m_caseShaderType;
1077
1078 vector<glu::Texture2D*> m_textures2d;
1079 vector<glu::TextureCube*> m_texturesCube;
1080 vector<deUint32> m_filledTextureUnits;
1081 };
1082
randomFeatures(const deUint32 seed)1083 deUint32 UniformCase::randomFeatures (const deUint32 seed)
1084 {
1085 static const deUint32 arrayUsageChoices[] = { 0, FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX };
1086 static const deUint32 uniformFuncChoices[] = { 0, FEATURE_UNIFORMFUNC_VALUE };
1087 static const deUint32 matrixModeChoices[] = { 0, FEATURE_MATRIXMODE_ROWMAJOR };
1088 static const deUint32 arrayAssignChoices[] = { 0, FEATURE_ARRAYASSIGN_FULL, FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO };
1089 static const deUint32 uniformUsageChoices[] = { 0, FEATURE_UNIFORMUSAGE_EVERY_OTHER };
1090 static const deUint32 booleanApiTypeChoices[] = { 0, FEATURE_BOOLEANAPITYPE_INT, FEATURE_BOOLEANAPITYPE_UINT };
1091 static const deUint32 uniformValueChoices[] = { 0, FEATURE_UNIFORMVALUE_ZERO };
1092
1093 Random rnd(seed);
1094
1095 deUint32 result = 0;
1096
1097 #define ARRAY_CHOICE(ARR) (ARR[rnd.getInt(0, DE_LENGTH_OF_ARRAY(ARR)-1)])
1098
1099 result |= ARRAY_CHOICE(arrayUsageChoices);
1100 result |= ARRAY_CHOICE(uniformFuncChoices);
1101 result |= ARRAY_CHOICE(matrixModeChoices);
1102 result |= ARRAY_CHOICE(arrayAssignChoices);
1103 result |= ARRAY_CHOICE(uniformUsageChoices);
1104 result |= ARRAY_CHOICE(booleanApiTypeChoices);
1105 result |= ARRAY_CHOICE(uniformValueChoices);
1106
1107 #undef ARRAY_CHOICE
1108
1109 return result;
1110 }
1111
UniformCase(Context & context,const char * const name,const char * const description,const CaseShaderType caseShaderType,const SharedPtr<const UniformCollection> & uniformCollection,const deUint32 features)1112 UniformCase::UniformCase (Context& context, const char* const name, const char* const description, const CaseShaderType caseShaderType, const SharedPtr<const UniformCollection>& uniformCollection, const deUint32 features)
1113 : TestCase (context, name, description)
1114 , CallLogWrapper (context.getRenderContext().getFunctions(), m_testCtx.getLog())
1115 , m_features (features)
1116 , m_uniformCollection (uniformCollection)
1117 , m_caseShaderType (caseShaderType)
1118 {
1119 }
1120
UniformCase(Context & context,const char * const name,const char * const description,const CaseShaderType caseShaderType,const SharedPtr<const UniformCollection> & uniformCollection)1121 UniformCase::UniformCase (Context& context, const char* const name, const char* const description, const CaseShaderType caseShaderType, const SharedPtr<const UniformCollection>& uniformCollection)
1122 : TestCase (context, name, description)
1123 , CallLogWrapper (context.getRenderContext().getFunctions(), m_testCtx.getLog())
1124 , m_features (0)
1125 , m_uniformCollection (uniformCollection)
1126 , m_caseShaderType (caseShaderType)
1127 {
1128 }
1129
UniformCase(Context & context,const char * name,const char * description,const deUint32 seed)1130 UniformCase::UniformCase (Context& context, const char* name, const char* description, const deUint32 seed)
1131 : TestCase (context, name, description)
1132 , CallLogWrapper (context.getRenderContext().getFunctions(), m_testCtx.getLog())
1133 , m_features (randomFeatures(seed))
1134 , m_uniformCollection (UniformCollection::random(seed))
1135 , m_caseShaderType (randomCaseShaderType(seed))
1136 {
1137 }
1138
init(void)1139 void UniformCase::init (void)
1140 {
1141 {
1142 const glw::Functions& funcs = m_context.getRenderContext().getFunctions();
1143 const int numSamplerUniforms = m_uniformCollection->getNumSamplers();
1144 const int vertexTexUnitsRequired = m_caseShaderType != CASESHADERTYPE_FRAGMENT ? numSamplerUniforms : 0;
1145 const int fragmentTexUnitsRequired = m_caseShaderType != CASESHADERTYPE_VERTEX ? numSamplerUniforms : 0;
1146 const int combinedTexUnitsRequired = vertexTexUnitsRequired + fragmentTexUnitsRequired;
1147 const int vertexTexUnitsSupported = getGLInt(funcs, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
1148 const int fragmentTexUnitsSupported = getGLInt(funcs, GL_MAX_TEXTURE_IMAGE_UNITS);
1149 const int combinedTexUnitsSupported = getGLInt(funcs, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
1150
1151 DE_ASSERT(numSamplerUniforms <= MAX_NUM_SAMPLER_UNIFORMS);
1152
1153 if (vertexTexUnitsRequired > vertexTexUnitsSupported)
1154 throw tcu::NotSupportedError(de::toString(vertexTexUnitsRequired) + " vertex texture units required, " + de::toString(vertexTexUnitsSupported) + " supported");
1155 if (fragmentTexUnitsRequired > fragmentTexUnitsSupported)
1156 throw tcu::NotSupportedError(de::toString(fragmentTexUnitsRequired) + " fragment texture units required, " + de::toString(fragmentTexUnitsSupported) + " supported");
1157 if (combinedTexUnitsRequired > combinedTexUnitsSupported)
1158 throw tcu::NotSupportedError(de::toString(combinedTexUnitsRequired) + " combined texture units required, " + de::toString(combinedTexUnitsSupported) + " supported");
1159 }
1160
1161 enableLogging(true);
1162 }
1163
deinit(void)1164 void UniformCase::deinit (void)
1165 {
1166 for (int i = 0; i < (int)m_textures2d.size(); i++)
1167 delete m_textures2d[i];
1168 m_textures2d.clear();
1169
1170 for (int i = 0; i < (int)m_texturesCube.size(); i++)
1171 delete m_texturesCube[i];
1172 m_texturesCube.clear();
1173
1174 m_filledTextureUnits.clear();
1175 }
1176
~UniformCase(void)1177 UniformCase::~UniformCase (void)
1178 {
1179 UniformCase::deinit();
1180 }
1181
generateBasicUniforms(vector<BasicUniform> & basicUniformsDst,vector<BasicUniformReportRef> & basicUniformReportsDst,const glu::VarType & varType,const char * const varName,const bool isParentActive,int & samplerUnitCounter,Random & rnd) const1182 void UniformCase::generateBasicUniforms (vector<BasicUniform>& basicUniformsDst, vector<BasicUniformReportRef>& basicUniformReportsDst, const glu::VarType& varType, const char* const varName, const bool isParentActive, int& samplerUnitCounter, Random& rnd) const
1183 {
1184 if (varType.isBasicType())
1185 {
1186 const bool isActive = isParentActive && (m_features & FEATURE_UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.size() % 2 == 0 : true);
1187 const glu::DataType type = varType.getBasicType();
1188 const VarValue value = m_features & FEATURE_UNIFORMVALUE_ZERO ? generateZeroVarValue(type)
1189 : glu::isDataTypeSampler(type) ? generateRandomVarValue(type, rnd, samplerUnitCounter++)
1190 : generateRandomVarValue(varType.getBasicType(), rnd);
1191
1192 basicUniformsDst.push_back(BasicUniform(varName, varType.getBasicType(), isActive, value));
1193 basicUniformReportsDst.push_back(BasicUniformReportRef(varName, varType.getBasicType(), isActive));
1194 }
1195 else if (varType.isArrayType())
1196 {
1197 const int size = varType.getArraySize();
1198 const string arrayRootName = string("") + varName + "[0]";
1199 vector<bool> isElemActive;
1200
1201 for (int elemNdx = 0; elemNdx < varType.getArraySize(); elemNdx++)
1202 {
1203 const string indexedName = string("") + varName + "[" + de::toString(elemNdx) + "]";
1204 const bool isCurElemActive = isParentActive &&
1205 (m_features & FEATURE_UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.size() % 2 == 0 : true) &&
1206 (m_features & FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX ? elemNdx == size/2 : true);
1207
1208 isElemActive.push_back(isCurElemActive);
1209
1210 if (varType.getElementType().isBasicType())
1211 {
1212 // \note We don't want separate entries in basicUniformReportsDst for elements of basic-type arrays.
1213 const glu::DataType elemBasicType = varType.getElementType().getBasicType();
1214 const VarValue value = m_features & FEATURE_UNIFORMVALUE_ZERO ? generateZeroVarValue(elemBasicType)
1215 : glu::isDataTypeSampler(elemBasicType) ? generateRandomVarValue(elemBasicType, rnd, samplerUnitCounter++)
1216 : generateRandomVarValue(elemBasicType, rnd);
1217
1218 basicUniformsDst.push_back(BasicUniform(indexedName.c_str(), elemBasicType, isCurElemActive, value, arrayRootName.c_str(), elemNdx, size));
1219 }
1220 else
1221 generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, varType.getElementType(), indexedName.c_str(), isCurElemActive, samplerUnitCounter, rnd);
1222 }
1223
1224 if (varType.getElementType().isBasicType())
1225 {
1226 int minSize;
1227 for (minSize = varType.getArraySize(); minSize > 0 && !isElemActive[minSize-1]; minSize--);
1228
1229 basicUniformReportsDst.push_back(BasicUniformReportRef(arrayRootName.c_str(), minSize, size, varType.getElementType().getBasicType(), isParentActive && minSize > 0));
1230 }
1231 }
1232 else
1233 {
1234 DE_ASSERT(varType.isStructType());
1235
1236 const StructType& structType = *varType.getStructPtr();
1237
1238 for (int i = 0; i < structType.getNumMembers(); i++)
1239 {
1240 const glu::StructMember& member = structType.getMember(i);
1241 const string memberFullName = string("") + varName + "." + member.getName();
1242
1243 generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, member.getType(), memberFullName.c_str(), isParentActive, samplerUnitCounter, rnd);
1244 }
1245 }
1246 }
1247
writeUniformDefinitions(std::ostringstream & dst) const1248 void UniformCase::writeUniformDefinitions (std::ostringstream& dst) const
1249 {
1250 for (int i = 0; i < (int)m_uniformCollection->getNumStructTypes(); i++)
1251 dst << glu::declare(m_uniformCollection->getStructType(i)) << ";\n";
1252
1253 for (int i = 0; i < (int)m_uniformCollection->getNumUniforms(); i++)
1254 dst << "uniform " << glu::declare(m_uniformCollection->getUniform(i).type, m_uniformCollection->getUniform(i).name.c_str()) << ";\n";
1255
1256 dst << "\n";
1257
1258 {
1259 static const struct
1260 {
1261 dataTypePredicate requiringTypes[2];
1262 const char* definition;
1263 } compareFuncs[] =
1264 {
1265 { { glu::isDataTypeFloatOrVec, glu::isDataTypeMatrix }, "mediump float compare_float (mediump float a, mediump float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }" },
1266 { { 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); }" },
1267 { { 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); }" },
1268 { { 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); }" },
1269 { { 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]); }" },
1270 { { 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]); }" },
1271 { { 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]); }" },
1272 { { 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]); }" },
1273 { { 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]); }" },
1274 { { 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]); }" },
1275 { { 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]); }" },
1276 { { 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]); }" },
1277 { { 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]); }" },
1278 { { 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; }" },
1279 { { 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; }" },
1280 { { 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; }" },
1281 { { 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; }" },
1282 { { 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; }" },
1283 { { 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; }" },
1284 { { 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; }" },
1285 { { 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; }" },
1286 { { dataTypeEquals<glu::TYPE_BOOL>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }" },
1287 { { dataTypeEquals<glu::TYPE_BOOL_VEC2>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }" },
1288 { { dataTypeEquals<glu::TYPE_BOOL_VEC3>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }" },
1289 { { dataTypeEquals<glu::TYPE_BOOL_VEC4>, dataTypeEquals<glu::TYPE_INVALID> }, "mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }" }
1290 };
1291
1292 const vector<glu::DataType> samplerTypes = m_uniformCollection->getSamplerTypes();
1293
1294 for (int compFuncNdx = 0; compFuncNdx < DE_LENGTH_OF_ARRAY(compareFuncs); compFuncNdx++)
1295 {
1296 const dataTypePredicate (&typeReq)[2] = compareFuncs[compFuncNdx].requiringTypes;
1297 bool containsTypeSampler = false;
1298
1299 for (int i = 0; i < (int)samplerTypes.size(); i++)
1300 {
1301 if (glu::isDataTypeSampler(samplerTypes[i]))
1302 {
1303 const glu::DataType retType = getSamplerLookupReturnType(samplerTypes[i]);
1304 if (typeReq[0](retType) || typeReq[1](retType))
1305 {
1306 containsTypeSampler = true;
1307 break;
1308 }
1309 }
1310 }
1311
1312 if (containsTypeSampler || m_uniformCollection->containsMatchingBasicType(typeReq[0]) || m_uniformCollection->containsMatchingBasicType(typeReq[1]))
1313 dst << compareFuncs[compFuncNdx].definition << "\n";
1314 }
1315 }
1316 }
1317
writeUniformCompareExpr(std::ostringstream & dst,const BasicUniform & uniform) const1318 void UniformCase::writeUniformCompareExpr (std::ostringstream& dst, const BasicUniform& uniform) const
1319 {
1320 if (glu::isDataTypeSampler(uniform.type))
1321 dst << "compare_" << glu::getDataTypeName(getSamplerLookupReturnType(uniform.type)) << "(texture(" << uniform.name << ", vec" << getSamplerNumLookupDimensions(uniform.type) << "(0.0))";
1322 else
1323 dst << "compare_" << glu::getDataTypeName(uniform.type) << "(" << uniform.name;
1324
1325 dst << ", " << shaderVarValueStr(uniform.finalValue) << ")";
1326 }
1327
writeUniformComparisons(std::ostringstream & dst,const vector<BasicUniform> & basicUniforms,const char * const variableName) const1328 void UniformCase::writeUniformComparisons (std::ostringstream& dst, const vector<BasicUniform>& basicUniforms, const char* const variableName) const
1329 {
1330 for (int i = 0; i < (int)basicUniforms.size(); i++)
1331 {
1332 const BasicUniform& unif = basicUniforms[i];
1333
1334 if (unif.isUsedInShader)
1335 {
1336 dst << "\t" << variableName << " *= ";
1337 writeUniformCompareExpr(dst, basicUniforms[i]);
1338 dst << ";\n";
1339 }
1340 else
1341 dst << "\t// UNUSED: " << basicUniforms[i].name << "\n";
1342 }
1343 }
1344
generateVertexSource(const vector<BasicUniform> & basicUniforms) const1345 string UniformCase::generateVertexSource (const vector<BasicUniform>& basicUniforms) const
1346 {
1347 const bool isVertexCase = m_caseShaderType == CASESHADERTYPE_VERTEX || m_caseShaderType == CASESHADERTYPE_BOTH;
1348 std::ostringstream result;
1349
1350 result << "#version 300 es\n"
1351 "in highp vec4 a_position;\n"
1352 "out mediump float v_vtxOut;\n"
1353 "\n";
1354
1355 if (isVertexCase)
1356 writeUniformDefinitions(result);
1357
1358 result << "\n"
1359 "void main (void)\n"
1360 "{\n"
1361 " gl_Position = a_position;\n"
1362 " v_vtxOut = 1.0;\n";
1363
1364 if (isVertexCase)
1365 writeUniformComparisons(result, basicUniforms, "v_vtxOut");
1366
1367 result << "}\n";
1368
1369 return result.str();
1370 }
1371
generateFragmentSource(const vector<BasicUniform> & basicUniforms) const1372 string UniformCase::generateFragmentSource (const vector<BasicUniform>& basicUniforms) const
1373 {
1374 const bool isFragmentCase = m_caseShaderType == CASESHADERTYPE_FRAGMENT || m_caseShaderType == CASESHADERTYPE_BOTH;
1375 std::ostringstream result;
1376
1377 result << "#version 300 es\n"
1378 "in mediump float v_vtxOut;\n"
1379 "\n";
1380
1381 if (isFragmentCase)
1382 writeUniformDefinitions(result);
1383
1384 result << "\n"
1385 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1386 "\n"
1387 "void main (void)\n"
1388 "{\n"
1389 " mediump float result = v_vtxOut;\n";
1390
1391 if (isFragmentCase)
1392 writeUniformComparisons(result, basicUniforms, "result");
1393
1394 result << " dEQP_FragColor = vec4(result, result, result, 1.0);\n"
1395 "}\n";
1396
1397 return result.str();
1398 }
1399
setupTexture(const VarValue & value)1400 void UniformCase::setupTexture (const VarValue& value)
1401 {
1402 // \note No handling for samplers other than 2D or cube.
1403
1404 enableLogging(false);
1405
1406 DE_ASSERT(getSamplerLookupReturnType(value.type) == glu::TYPE_FLOAT_VEC4);
1407
1408 const int width = 32;
1409 const int height = 32;
1410 const tcu::Vec4 color = vec4FromPtr(&value.val.samplerV.fillColor.floatV[0]);
1411
1412 if (value.type == glu::TYPE_SAMPLER_2D)
1413 {
1414 glu::Texture2D* texture = new glu::Texture2D(m_context.getRenderContext(), GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1415 tcu::Texture2D& refTexture = texture->getRefTexture();
1416 m_textures2d.push_back(texture);
1417
1418 refTexture.allocLevel(0);
1419 fillWithColor(refTexture.getLevel(0), color);
1420
1421 GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0 + value.val.samplerV.unit));
1422 m_filledTextureUnits.push_back(value.val.samplerV.unit);
1423 texture->upload();
1424 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1425 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1426 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
1427 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
1428 }
1429 else if (value.type == glu::TYPE_SAMPLER_CUBE)
1430 {
1431 DE_ASSERT(width == height);
1432
1433 glu::TextureCube* texture = new glu::TextureCube(m_context.getRenderContext(), GL_RGBA, GL_UNSIGNED_BYTE, width);
1434 tcu::TextureCube& refTexture = texture->getRefTexture();
1435 m_texturesCube.push_back(texture);
1436
1437 for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++)
1438 {
1439 refTexture.allocLevel((tcu::CubeFace)face, 0);
1440 fillWithColor(refTexture.getLevelFace(0, (tcu::CubeFace)face), color);
1441 }
1442
1443 GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0 + value.val.samplerV.unit));
1444 m_filledTextureUnits.push_back(value.val.samplerV.unit);
1445 texture->upload();
1446 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1447 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1448 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
1449 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
1450
1451 }
1452 else
1453 DE_ASSERT(false);
1454
1455 enableLogging(true);
1456 }
1457
getActiveUniforms(vector<BasicUniformReportGL> & basicUniformReportsDst,const vector<BasicUniformReportRef> & basicUniformReportsRef,const deUint32 programGL)1458 bool UniformCase::getActiveUniforms (vector<BasicUniformReportGL>& basicUniformReportsDst, const vector<BasicUniformReportRef>& basicUniformReportsRef, const deUint32 programGL)
1459 {
1460 TestLog& log = m_testCtx.getLog();
1461 GLint numActiveUniforms = 0;
1462 GLint uniformMaxNameLength = 0;
1463 vector<char> nameBuffer;
1464 bool success = true;
1465
1466 GLU_CHECK_CALL(glGetProgramiv(programGL, GL_ACTIVE_UNIFORMS, &numActiveUniforms));
1467 log << TestLog::Message << "// Number of active uniforms reported: " << numActiveUniforms << TestLog::EndMessage;
1468 GLU_CHECK_CALL(glGetProgramiv(programGL, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformMaxNameLength));
1469 log << TestLog::Message << "// Maximum uniform name length reported: " << uniformMaxNameLength << TestLog::EndMessage;
1470 nameBuffer.resize(uniformMaxNameLength);
1471
1472 for (int unifNdx = 0; unifNdx < numActiveUniforms; unifNdx++)
1473 {
1474 GLsizei reportedNameLength = 0;
1475 GLint reportedSize = -1;
1476 GLenum reportedTypeGL = GL_NONE;
1477
1478 GLU_CHECK_CALL(glGetActiveUniform(programGL, (GLuint)unifNdx, (GLsizei)uniformMaxNameLength, &reportedNameLength, &reportedSize, &reportedTypeGL, &nameBuffer[0]));
1479
1480 const glu::DataType reportedType = glu::getDataTypeFromGLType(reportedTypeGL);
1481 const string reportedNameStr (&nameBuffer[0]);
1482
1483 TCU_CHECK_MSG(reportedType != glu::TYPE_LAST, "Invalid uniform type");
1484
1485 log << TestLog::Message << "// Got name = " << reportedNameStr << ", name length = " << reportedNameLength << ", size = " << reportedSize << ", type = " << glu::getDataTypeName(reportedType) << TestLog::EndMessage;
1486
1487 if ((GLsizei)reportedNameStr.length() != reportedNameLength)
1488 {
1489 log << TestLog::Message << "// FAILURE: wrong name length reported, should be " << reportedNameStr.length() << TestLog::EndMessage;
1490 success = false;
1491 }
1492
1493 if (!deStringBeginsWith(reportedNameStr.c_str(), "gl_")) // Ignore built-in uniforms.
1494 {
1495 int referenceNdx;
1496 for (referenceNdx = 0; referenceNdx < (int)basicUniformReportsRef.size(); referenceNdx++)
1497 {
1498 if (basicUniformReportsRef[referenceNdx].name == reportedNameStr)
1499 break;
1500 }
1501
1502 if (referenceNdx >= (int)basicUniformReportsRef.size())
1503 {
1504 log << TestLog::Message << "// FAILURE: invalid non-built-in uniform name reported" << TestLog::EndMessage;
1505 success = false;
1506 }
1507 else
1508 {
1509 const BasicUniformReportRef& reference = basicUniformReportsRef[referenceNdx];
1510
1511 DE_ASSERT(reference.type != glu::TYPE_LAST);
1512 DE_ASSERT(reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader));
1513 DE_ASSERT(reference.minSize <= reference.maxSize);
1514
1515 if (BasicUniformReportGL::findWithName(basicUniformReportsDst, reportedNameStr.c_str()) != basicUniformReportsDst.end())
1516 {
1517 log << TestLog::Message << "// FAILURE: same uniform name reported twice" << TestLog::EndMessage;
1518 success = false;
1519 }
1520
1521 basicUniformReportsDst.push_back(BasicUniformReportGL(reportedNameStr.c_str(), reportedNameLength, reportedSize, reportedType, unifNdx));
1522
1523 if (reportedType != reference.type)
1524 {
1525 log << TestLog::Message << "// FAILURE: wrong type reported, should be " << glu::getDataTypeName(reference.type) << TestLog::EndMessage;
1526 success = false;
1527 }
1528 if (reportedSize < reference.minSize || reportedSize > reference.maxSize)
1529 {
1530 log << TestLog::Message
1531 << "// FAILURE: wrong size reported, should be "
1532 << (reference.minSize == reference.maxSize ? de::toString(reference.minSize) : "in the range [" + de::toString(reference.minSize) + ", " + de::toString(reference.maxSize) + "]")
1533 << TestLog::EndMessage;
1534
1535 success = false;
1536 }
1537 }
1538 }
1539 }
1540
1541 for (int i = 0; i < (int)basicUniformReportsRef.size(); i++)
1542 {
1543 const BasicUniformReportRef& expected = basicUniformReportsRef[i];
1544 if (expected.isUsedInShader && BasicUniformReportGL::findWithName(basicUniformReportsDst, expected.name.c_str()) == basicUniformReportsDst.end())
1545 {
1546 log << TestLog::Message << "// FAILURE: uniform with name " << expected.name << " was not reported by GL" << TestLog::EndMessage;
1547 success = false;
1548 }
1549 }
1550
1551 return success;
1552 }
1553
getActiveUniformsiv(vector<BasicUniformReportGL> & basicUniformReportsDst,const vector<BasicUniformReportRef> & basicUniformReportsRef,const deUint32 programGL)1554 bool UniformCase::getActiveUniformsiv (vector<BasicUniformReportGL>& basicUniformReportsDst, const vector<BasicUniformReportRef>& basicUniformReportsRef, const deUint32 programGL)
1555 {
1556 TestLog& log = m_testCtx.getLog();
1557 vector<string> queryNames (basicUniformReportsRef.size());
1558 vector<const char*> queryNamesC (basicUniformReportsRef.size());
1559 vector<GLuint> uniformIndices (basicUniformReportsRef.size());
1560 vector<deUint32> validUniformIndices; // This shall have the same contents, and in same order, as uniformIndices, but with GL_INVALID_INDEX entries removed.
1561 bool success = true;
1562
1563 for (int i = 0; i < (int)basicUniformReportsRef.size(); i++)
1564 {
1565 const string& name = basicUniformReportsRef[i].name;
1566 queryNames[i] = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && name[name.size()-1] == ']' ? beforeLast(name, '[') : name;
1567 queryNamesC[i] = queryNames[i].c_str();
1568 }
1569
1570 GLU_CHECK_CALL(glGetUniformIndices(programGL, (GLsizei)basicUniformReportsRef.size(), &queryNamesC[0], &uniformIndices[0]));
1571
1572 for (int i = 0; i < (int)uniformIndices.size(); i++)
1573 {
1574 if (uniformIndices[i] != GL_INVALID_INDEX)
1575 validUniformIndices.push_back(uniformIndices[i]);
1576 else
1577 {
1578 if (basicUniformReportsRef[i].isUsedInShader)
1579 {
1580 log << TestLog::Message << "// FAILURE: uniform with name " << basicUniformReportsRef[i].name << " received GL_INVALID_INDEX" << TestLog::EndMessage;
1581 success = false;
1582 }
1583 }
1584 }
1585
1586 if (!validUniformIndices.empty())
1587 {
1588 vector<GLint> uniformNameLengthBuf (validUniformIndices.size());
1589 vector<GLint> uniformSizeBuf (validUniformIndices.size());
1590 vector<GLint> uniformTypeBuf (validUniformIndices.size());
1591
1592 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_NAME_LENGTH, &uniformNameLengthBuf[0]));
1593 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_SIZE, &uniformSizeBuf[0]));
1594 GLU_CHECK_CALL(glGetActiveUniformsiv(programGL, (GLsizei)validUniformIndices.size(), &validUniformIndices[0], GL_UNIFORM_TYPE, &uniformTypeBuf[0]));
1595
1596 {
1597 int validNdx = -1; // Keeps the corresponding index to validUniformIndices while unifNdx is the index to uniformIndices.
1598 for (int unifNdx = 0; unifNdx < (int)uniformIndices.size(); unifNdx++)
1599 {
1600 if (uniformIndices[unifNdx] == GL_INVALID_INDEX)
1601 continue;
1602
1603 validNdx++;
1604
1605 const BasicUniformReportRef& reference = basicUniformReportsRef[unifNdx];
1606 const int reportedIndex = validUniformIndices[validNdx];
1607 const int reportedNameLength = (int)uniformNameLengthBuf[validNdx];
1608 const int reportedSize = (int)uniformSizeBuf[validNdx];
1609 const glu::DataType reportedType = glu::getDataTypeFromGLType((deUint32)uniformTypeBuf[validNdx]);
1610
1611 TCU_CHECK_MSG(reportedType != glu::TYPE_LAST, "Invalid uniform type");
1612
1613 log << TestLog::Message
1614 << "// Got name length = " << reportedNameLength
1615 << ", size = " << reportedSize
1616 << ", type = " << glu::getDataTypeName(reportedType)
1617 << " for the uniform at index " << reportedIndex << " (" << reference.name << ")"
1618 << TestLog::EndMessage;
1619
1620 DE_ASSERT(reference.type != glu::TYPE_LAST);
1621 DE_ASSERT(reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader));
1622 DE_ASSERT(reference.minSize <= reference.maxSize);
1623 basicUniformReportsDst.push_back(BasicUniformReportGL(reference.name.c_str(), reportedNameLength, reportedSize, reportedType, reportedIndex));
1624
1625 if (reportedNameLength != (int)reference.name.length() + 1)
1626 {
1627 log << TestLog::Message << "// FAILURE: wrong name length reported, should be " << reference.name.length() + 1 << TestLog::EndMessage;
1628 success = false;
1629 }
1630
1631 if (reportedType != reference.type)
1632 {
1633 log << TestLog::Message << "// FAILURE: wrong type reported, should be " << glu::getDataTypeName(reference.type) << TestLog::EndMessage;
1634 success = false;
1635 }
1636
1637 if (reportedSize < reference.minSize || reportedSize > reference.maxSize)
1638 {
1639 log << TestLog::Message
1640 << "// FAILURE: wrong size reported, should be "
1641 << (reference.minSize == reference.maxSize ? de::toString(reference.minSize) : "in the range [" + de::toString(reference.minSize) + ", " + de::toString(reference.maxSize) + "]")
1642 << TestLog::EndMessage;
1643
1644 success = false;
1645 }
1646 }
1647 }
1648 }
1649
1650 return success;
1651 }
1652
uniformVsUniformsivComparison(const vector<BasicUniformReportGL> & uniformResults,const vector<BasicUniformReportGL> & uniformsivResults)1653 bool UniformCase::uniformVsUniformsivComparison (const vector<BasicUniformReportGL>& uniformResults, const vector<BasicUniformReportGL>& uniformsivResults)
1654 {
1655 TestLog& log = m_testCtx.getLog();
1656 bool success = true;
1657
1658 for (int uniformResultNdx = 0; uniformResultNdx < (int)uniformResults.size(); uniformResultNdx++)
1659 {
1660 const BasicUniformReportGL& uniformResult = uniformResults[uniformResultNdx];
1661 const string& uniformName = uniformResult.name;
1662 const vector<BasicUniformReportGL>::const_iterator uniformsivResultIt = BasicUniformReportGL::findWithName(uniformsivResults, uniformName.c_str());
1663
1664 if (uniformsivResultIt != uniformsivResults.end())
1665 {
1666 const BasicUniformReportGL& uniformsivResult = *uniformsivResultIt;
1667
1668 log << TestLog::Message << "// Checking uniform " << uniformName << TestLog::EndMessage;
1669
1670 if (uniformResult.index != uniformsivResult.index)
1671 {
1672 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetUniformIndices() gave different indices for uniform " << uniformName << TestLog::EndMessage;
1673 success = false;
1674 }
1675 if (uniformResult.nameLength + 1 != uniformsivResult.nameLength)
1676 {
1677 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave incompatible name lengths for uniform " << uniformName << TestLog::EndMessage;
1678 success = false;
1679 }
1680 if (uniformResult.size != uniformsivResult.size)
1681 {
1682 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave different sizes for uniform " << uniformName << TestLog::EndMessage;
1683 success = false;
1684 }
1685 if (uniformResult.type != uniformsivResult.type)
1686 {
1687 log << TestLog::Message << "// FAILURE: glGetActiveUniform() and glGetActiveUniformsiv() gave different types for uniform " << uniformName << TestLog::EndMessage;
1688 success = false;
1689 }
1690 }
1691 else
1692 {
1693 log << TestLog::Message << "// FAILURE: uniform " << uniformName << " was reported active by glGetActiveUniform() but not by glGetUniformIndices()" << TestLog::EndMessage;
1694 success = false;
1695 }
1696 }
1697
1698 for (int uniformsivResultNdx = 0; uniformsivResultNdx < (int)uniformsivResults.size(); uniformsivResultNdx++)
1699 {
1700 const BasicUniformReportGL& uniformsivResult = uniformsivResults[uniformsivResultNdx];
1701 const string& uniformsivName = uniformsivResult.name;
1702 const vector<BasicUniformReportGL>::const_iterator uniformsResultIt = BasicUniformReportGL::findWithName(uniformsivResults, uniformsivName.c_str());
1703
1704 if (uniformsResultIt == uniformsivResults.end())
1705 {
1706 log << TestLog::Message << "// FAILURE: uniform " << uniformsivName << " was reported active by glGetUniformIndices() but not by glGetActiveUniform()" << TestLog::EndMessage;
1707 success = false;
1708 }
1709 }
1710
1711 return success;
1712 }
1713
getUniforms(vector<VarValue> & valuesDst,const vector<BasicUniform> & basicUniforms,const deUint32 programGL)1714 bool UniformCase::getUniforms (vector<VarValue>& valuesDst, const vector<BasicUniform>& basicUniforms, const deUint32 programGL)
1715 {
1716 TestLog& log = m_testCtx.getLog();
1717 bool success = true;
1718
1719 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++)
1720 {
1721 const BasicUniform& uniform = basicUniforms[unifNdx];
1722 const string queryName = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? beforeLast(uniform.name, '[') : uniform.name;
1723 const int location = glGetUniformLocation(programGL, queryName.c_str());
1724 const int size = glu::getDataTypeScalarSize(uniform.type);
1725 VarValue value;
1726
1727 deMemset(&value, 0xcd, sizeof(value)); // Initialize to known garbage.
1728
1729 if (location == -1)
1730 {
1731 value.type = glu::TYPE_INVALID;
1732 valuesDst.push_back(value);
1733 if (uniform.isUsedInShader)
1734 {
1735 log << TestLog::Message << "// FAILURE: " << uniform.name << " was used in shader, but has location -1" << TestLog::EndMessage;
1736 success = false;
1737 }
1738 continue;
1739 }
1740
1741 value.type = uniform.type;
1742
1743 DE_STATIC_ASSERT(sizeof(GLint) == sizeof(value.val.intV[0]));
1744 DE_STATIC_ASSERT(sizeof(GLuint) == sizeof(value.val.uintV[0]));
1745 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(value.val.floatV[0]));
1746
1747 if (glu::isDataTypeFloatOrVec(uniform.type) || glu::isDataTypeMatrix(uniform.type))
1748 GLU_CHECK_CALL(glGetUniformfv(programGL, location, &value.val.floatV[0]));
1749 else if (glu::isDataTypeIntOrIVec(uniform.type))
1750 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &value.val.intV[0]));
1751 else if (glu::isDataTypeUintOrUVec(uniform.type))
1752 GLU_CHECK_CALL(glGetUniformuiv(programGL, location, &value.val.uintV[0]));
1753 else if (glu::isDataTypeBoolOrBVec(uniform.type))
1754 {
1755 if (m_features & FEATURE_BOOLEANAPITYPE_INT)
1756 {
1757 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &value.val.intV[0]));
1758 for (int i = 0; i < size; i++)
1759 value.val.boolV[i] = value.val.intV[i] != 0;
1760 }
1761 else if (m_features & FEATURE_BOOLEANAPITYPE_UINT)
1762 {
1763 GLU_CHECK_CALL(glGetUniformuiv(programGL, location, &value.val.uintV[0]));
1764 for (int i = 0; i < size; i++)
1765 value.val.boolV[i] = value.val.uintV[i] != 0;
1766 }
1767 else // Default: use float.
1768 {
1769 GLU_CHECK_CALL(glGetUniformfv(programGL, location, &value.val.floatV[0]));
1770 for (int i = 0; i < size; i++)
1771 value.val.boolV[i] = value.val.floatV[i] != 0.0f;
1772 }
1773 }
1774 else if (glu::isDataTypeSampler(uniform.type))
1775 {
1776 GLint unit = -1;
1777 GLU_CHECK_CALL(glGetUniformiv(programGL, location, &unit));
1778 value.val.samplerV.unit = unit;
1779 }
1780 else
1781 DE_ASSERT(false);
1782
1783 valuesDst.push_back(value);
1784
1785 log << TestLog::Message << "// Got " << uniform.name << " value " << apiVarValueStr(value) << TestLog::EndMessage;
1786 }
1787
1788 return success;
1789 }
1790
checkUniformDefaultValues(const vector<VarValue> & values,const vector<BasicUniform> & basicUniforms)1791 bool UniformCase::checkUniformDefaultValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms)
1792 {
1793 TestLog& log = m_testCtx.getLog();
1794 bool success = true;
1795
1796 DE_ASSERT(values.size() == basicUniforms.size());
1797
1798 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++)
1799 {
1800 const BasicUniform& uniform = basicUniforms[unifNdx];
1801 const VarValue& unifValue = values[unifNdx];
1802 const int valSize = glu::getDataTypeScalarSize(uniform.type);
1803
1804 log << TestLog::Message << "// Checking uniform " << uniform.name << TestLog::EndMessage;
1805
1806 if (unifValue.type == glu::TYPE_INVALID) // This happens when glGetUniformLocation() returned -1.
1807 continue;
1808
1809 #define CHECK_UNIFORM(VAR_VALUE_MEMBER, ZERO) \
1810 do \
1811 { \
1812 for (int i = 0; i < valSize; i++) \
1813 { \
1814 if (unifValue.val.VAR_VALUE_MEMBER[i] != ZERO) \
1815 { \
1816 log << TestLog::Message << "// FAILURE: uniform " << uniform.name << " has non-zero initial value" << TestLog::EndMessage; \
1817 success = false; \
1818 } \
1819 } \
1820 } while (false)
1821
1822 if (glu::isDataTypeFloatOrVec(uniform.type) || glu::isDataTypeMatrix(uniform.type))
1823 CHECK_UNIFORM(floatV, 0.0f);
1824 else if (glu::isDataTypeIntOrIVec(uniform.type))
1825 CHECK_UNIFORM(intV, 0);
1826 else if (glu::isDataTypeUintOrUVec(uniform.type))
1827 CHECK_UNIFORM(uintV, 0);
1828 else if (glu::isDataTypeBoolOrBVec(uniform.type))
1829 CHECK_UNIFORM(boolV, false);
1830 else if (glu::isDataTypeSampler(uniform.type))
1831 {
1832 if (unifValue.val.samplerV.unit != 0)
1833 {
1834 log << TestLog::Message << "// FAILURE: uniform " << uniform.name << " has non-zero initial value" << TestLog::EndMessage;
1835 success = false;
1836 }
1837 }
1838 else
1839 DE_ASSERT(false);
1840
1841 #undef CHECK_UNIFORM
1842 }
1843
1844 return success;
1845 }
1846
assignUniforms(const vector<BasicUniform> & basicUniforms,deUint32 programGL,Random & rnd)1847 void UniformCase::assignUniforms (const vector<BasicUniform>& basicUniforms, deUint32 programGL, Random& rnd)
1848 {
1849 TestLog& log = m_testCtx.getLog();
1850 const bool transpose = (m_features & FEATURE_MATRIXMODE_ROWMAJOR) != 0;
1851 const GLboolean transposeGL = transpose ? GL_TRUE : GL_FALSE;
1852 const glu::DataType boolApiType = m_features & FEATURE_BOOLEANAPITYPE_INT ? glu::TYPE_INT
1853 : m_features & FEATURE_BOOLEANAPITYPE_UINT ? glu::TYPE_UINT
1854 : glu::TYPE_FLOAT;
1855
1856 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++)
1857 {
1858 const BasicUniform& uniform = basicUniforms[unifNdx];
1859 const bool isArrayMember = uniform.elemNdx >= 0;
1860 const string queryName = m_features & FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? beforeLast(uniform.name, '[') : uniform.name;
1861 const int numValuesToAssign = !isArrayMember ? 1
1862 : m_features & FEATURE_ARRAYASSIGN_FULL ? (uniform.elemNdx == 0 ? uniform.rootSize : 0)
1863 : m_features & FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO ? (uniform.elemNdx % 2 == 0 ? 2 : 0)
1864 : /* Default: assign array elements separately */ 1;
1865
1866 DE_ASSERT(numValuesToAssign >= 0);
1867 DE_ASSERT(numValuesToAssign == 1 || isArrayMember);
1868
1869 if (numValuesToAssign == 0)
1870 {
1871 log << TestLog::Message << "// Uniform " << uniform.name << " is covered by another glUniform*v() call to the same array" << TestLog::EndMessage;
1872 continue;
1873 }
1874
1875 const int location = glGetUniformLocation(programGL, queryName.c_str());
1876 const int typeSize = glu::getDataTypeScalarSize(uniform.type);
1877 const bool assignByValue = m_features & FEATURE_UNIFORMFUNC_VALUE && !glu::isDataTypeMatrix(uniform.type) && numValuesToAssign == 1;
1878 vector<VarValue> valuesToAssign;
1879
1880 for (int i = 0; i < numValuesToAssign; i++)
1881 {
1882 const string curName = isArrayMember ? beforeLast(uniform.rootName, '[') + "[" + de::toString(uniform.elemNdx+i) + "]" : uniform.name;
1883 VarValue unifValue;
1884
1885 if (isArrayMember)
1886 {
1887 const vector<BasicUniform>::const_iterator elemUnif = BasicUniform::findWithName(basicUniforms, curName.c_str());
1888 if (elemUnif == basicUniforms.end())
1889 continue;
1890 unifValue = elemUnif->finalValue;
1891 }
1892 else
1893 unifValue = uniform.finalValue;
1894
1895 const VarValue apiValue = glu::isDataTypeBoolOrBVec(unifValue.type) ? getRandomBoolRepresentation(unifValue, boolApiType, rnd)
1896 : glu::isDataTypeSampler(unifValue.type) ? getSamplerUnitValue(unifValue)
1897 : unifValue;
1898
1899 valuesToAssign.push_back(glu::isDataTypeMatrix(apiValue.type) && transpose ? getTransposeMatrix(apiValue) : apiValue);
1900
1901 if (glu::isDataTypeBoolOrBVec(uniform.type))
1902 log << TestLog::Message << "// Using type " << glu::getDataTypeName(boolApiType) << " to set boolean value " << apiVarValueStr(unifValue) << " for " << curName << TestLog::EndMessage;
1903 else if (glu::isDataTypeSampler(uniform.type))
1904 log << TestLog::Message << "// Texture for the sampler uniform " << curName << " will be filled with color " << apiVarValueStr(getSamplerFillValue(uniform.finalValue)) << TestLog::EndMessage;
1905 }
1906
1907 DE_ASSERT(!valuesToAssign.empty());
1908
1909 if (glu::isDataTypeFloatOrVec(valuesToAssign[0].type))
1910 {
1911 if (assignByValue)
1912 {
1913 const float* const ptr = &valuesToAssign[0].val.floatV[0];
1914
1915 switch (typeSize)
1916 {
1917 case 1: GLU_CHECK_CALL(glUniform1f(location, ptr[0])); break;
1918 case 2: GLU_CHECK_CALL(glUniform2f(location, ptr[0], ptr[1])); break;
1919 case 3: GLU_CHECK_CALL(glUniform3f(location, ptr[0], ptr[1], ptr[2])); break;
1920 case 4: GLU_CHECK_CALL(glUniform4f(location, ptr[0], ptr[1], ptr[2], ptr[3])); break;
1921 default:
1922 DE_ASSERT(false);
1923 }
1924 }
1925 else
1926 {
1927 vector<float> buffer(valuesToAssign.size() * typeSize);
1928 for (int i = 0; i < (int)buffer.size(); i++)
1929 buffer[i] = valuesToAssign[i / typeSize].val.floatV[i % typeSize];
1930
1931 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(buffer[0]));
1932 switch (typeSize)
1933 {
1934 case 1: GLU_CHECK_CALL(glUniform1fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1935 case 2: GLU_CHECK_CALL(glUniform2fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1936 case 3: GLU_CHECK_CALL(glUniform3fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1937 case 4: GLU_CHECK_CALL(glUniform4fv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1938 default:
1939 DE_ASSERT(false);
1940 }
1941 }
1942 }
1943 else if (glu::isDataTypeMatrix(valuesToAssign[0].type))
1944 {
1945 DE_ASSERT(!assignByValue);
1946
1947 vector<float> buffer(valuesToAssign.size() * typeSize);
1948 for (int i = 0; i < (int)buffer.size(); i++)
1949 buffer[i] = valuesToAssign[i / typeSize].val.floatV[i % typeSize];
1950
1951 DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(buffer[0]));
1952 switch (uniform.type)
1953 {
1954 case glu::TYPE_FLOAT_MAT2: GLU_CHECK_CALL(glUniformMatrix2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1955 case glu::TYPE_FLOAT_MAT3: GLU_CHECK_CALL(glUniformMatrix3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1956 case glu::TYPE_FLOAT_MAT4: GLU_CHECK_CALL(glUniformMatrix4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1957 case glu::TYPE_FLOAT_MAT2X3: GLU_CHECK_CALL(glUniformMatrix2x3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1958 case glu::TYPE_FLOAT_MAT2X4: GLU_CHECK_CALL(glUniformMatrix2x4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1959 case glu::TYPE_FLOAT_MAT3X2: GLU_CHECK_CALL(glUniformMatrix3x2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1960 case glu::TYPE_FLOAT_MAT3X4: GLU_CHECK_CALL(glUniformMatrix3x4fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1961 case glu::TYPE_FLOAT_MAT4X2: GLU_CHECK_CALL(glUniformMatrix4x2fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1962 case glu::TYPE_FLOAT_MAT4X3: GLU_CHECK_CALL(glUniformMatrix4x3fv (location, (GLsizei)valuesToAssign.size(), transposeGL, &buffer[0])); break;
1963 default:
1964 DE_ASSERT(false);
1965 }
1966 }
1967 else if (glu::isDataTypeIntOrIVec(valuesToAssign[0].type))
1968 {
1969 if (assignByValue)
1970 {
1971 const deInt32* const ptr = &valuesToAssign[0].val.intV[0];
1972
1973 switch (typeSize)
1974 {
1975 case 1: GLU_CHECK_CALL(glUniform1i(location, ptr[0])); break;
1976 case 2: GLU_CHECK_CALL(glUniform2i(location, ptr[0], ptr[1])); break;
1977 case 3: GLU_CHECK_CALL(glUniform3i(location, ptr[0], ptr[1], ptr[2])); break;
1978 case 4: GLU_CHECK_CALL(glUniform4i(location, ptr[0], ptr[1], ptr[2], ptr[3])); break;
1979 default:
1980 DE_ASSERT(false);
1981 }
1982 }
1983 else
1984 {
1985 vector<deInt32> buffer(valuesToAssign.size() * typeSize);
1986 for (int i = 0; i < (int)buffer.size(); i++)
1987 buffer[i] = valuesToAssign[i / typeSize].val.intV[i % typeSize];
1988
1989 DE_STATIC_ASSERT(sizeof(GLint) == sizeof(buffer[0]));
1990 switch (typeSize)
1991 {
1992 case 1: GLU_CHECK_CALL(glUniform1iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1993 case 2: GLU_CHECK_CALL(glUniform2iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1994 case 3: GLU_CHECK_CALL(glUniform3iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1995 case 4: GLU_CHECK_CALL(glUniform4iv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
1996 default:
1997 DE_ASSERT(false);
1998 }
1999 }
2000 }
2001 else if (glu::isDataTypeUintOrUVec(valuesToAssign[0].type))
2002 {
2003 if (assignByValue)
2004 {
2005 const deUint32* const ptr = &valuesToAssign[0].val.uintV[0];
2006
2007 switch (typeSize)
2008 {
2009 case 1: GLU_CHECK_CALL(glUniform1ui(location, ptr[0])); break;
2010 case 2: GLU_CHECK_CALL(glUniform2ui(location, ptr[0], ptr[1])); break;
2011 case 3: GLU_CHECK_CALL(glUniform3ui(location, ptr[0], ptr[1], ptr[2])); break;
2012 case 4: GLU_CHECK_CALL(glUniform4ui(location, ptr[0], ptr[1], ptr[2], ptr[3])); break;
2013 default:
2014 DE_ASSERT(false);
2015 }
2016 }
2017 else
2018 {
2019 vector<deUint32> buffer(valuesToAssign.size() * typeSize);
2020 for (int i = 0; i < (int)buffer.size(); i++)
2021 buffer[i] = valuesToAssign[i / typeSize].val.intV[i % typeSize];
2022
2023 DE_STATIC_ASSERT(sizeof(GLuint) == sizeof(buffer[0]));
2024 switch (typeSize)
2025 {
2026 case 1: GLU_CHECK_CALL(glUniform1uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
2027 case 2: GLU_CHECK_CALL(glUniform2uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
2028 case 3: GLU_CHECK_CALL(glUniform3uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
2029 case 4: GLU_CHECK_CALL(glUniform4uiv(location, (GLsizei)valuesToAssign.size(), &buffer[0])); break;
2030 default:
2031 DE_ASSERT(false);
2032 }
2033 }
2034 }
2035 else if (glu::isDataTypeSampler(valuesToAssign[0].type))
2036 {
2037 if (assignByValue)
2038 GLU_CHECK_CALL(glUniform1i(location, uniform.finalValue.val.samplerV.unit));
2039 else
2040 {
2041 const GLint unit = uniform.finalValue.val.samplerV.unit;
2042 GLU_CHECK_CALL(glUniform1iv(location, (GLsizei)valuesToAssign.size(), &unit));
2043 }
2044 }
2045 else
2046 DE_ASSERT(false);
2047 }
2048 }
2049
compareUniformValues(const vector<VarValue> & values,const vector<BasicUniform> & basicUniforms)2050 bool UniformCase::compareUniformValues (const vector<VarValue>& values, const vector<BasicUniform>& basicUniforms)
2051 {
2052 TestLog& log = m_testCtx.getLog();
2053 bool success = true;
2054
2055 for (int unifNdx = 0; unifNdx < (int)basicUniforms.size(); unifNdx++)
2056 {
2057 const BasicUniform& uniform = basicUniforms[unifNdx];
2058 const VarValue& unifValue = values[unifNdx];
2059
2060 log << TestLog::Message << "// Checking uniform " << uniform.name << TestLog::EndMessage;
2061
2062 if (unifValue.type == glu::TYPE_INVALID) // This happens when glGetUniformLocation() returned -1.
2063 continue;
2064
2065 if (!apiVarValueEquals(unifValue, uniform.finalValue))
2066 {
2067 log << TestLog::Message << "// FAILURE: value obtained with glGetUniform*() for uniform " << uniform.name << " differs from value set with glUniform*()" << TestLog::EndMessage;
2068 success = false;
2069 }
2070 }
2071
2072 return success;
2073 }
2074
renderTest(const vector<BasicUniform> & basicUniforms,const ShaderProgram & program,Random & rnd)2075 bool UniformCase::renderTest (const vector<BasicUniform>& basicUniforms, const ShaderProgram& program, Random& rnd)
2076 {
2077 TestLog& log = m_testCtx.getLog();
2078 const tcu::RenderTarget& renderTarget = m_context.getRenderTarget();
2079 const int viewportW = de::min(renderTarget.getWidth(), MAX_RENDER_WIDTH);
2080 const int viewportH = de::min(renderTarget.getHeight(), MAX_RENDER_HEIGHT);
2081 const int viewportX = rnd.getInt(0, renderTarget.getWidth() - viewportW);
2082 const int viewportY = rnd.getInt(0, renderTarget.getHeight() - viewportH);
2083 tcu::Surface renderedImg (viewportW, viewportH);
2084
2085 // Assert that no two samplers of different types have the same texture unit - this is an error in GL.
2086 for (int i = 0; i < (int)basicUniforms.size(); i++)
2087 {
2088 if (glu::isDataTypeSampler(basicUniforms[i].type))
2089 {
2090 for (int j = 0; j < i; j++)
2091 {
2092 if (glu::isDataTypeSampler(basicUniforms[j].type) && basicUniforms[i].type != basicUniforms[j].type)
2093 DE_ASSERT(basicUniforms[i].finalValue.val.samplerV.unit != basicUniforms[j].finalValue.val.samplerV.unit);
2094 }
2095 }
2096 }
2097
2098 for (int i = 0; i < (int)basicUniforms.size(); i++)
2099 {
2100 if (glu::isDataTypeSampler(basicUniforms[i].type) && std::find(m_filledTextureUnits.begin(), m_filledTextureUnits.end(), basicUniforms[i].finalValue.val.samplerV.unit) == m_filledTextureUnits.end())
2101 {
2102 log << TestLog::Message << "// Filling texture at unit " << apiVarValueStr(basicUniforms[i].finalValue) << " with color " << shaderVarValueStr(basicUniforms[i].finalValue) << TestLog::EndMessage;
2103 setupTexture(basicUniforms[i].finalValue);
2104 }
2105 }
2106
2107 GLU_CHECK_CALL(glViewport(viewportX, viewportY, viewportW, viewportH));
2108
2109 {
2110 static const float position[] =
2111 {
2112 -1.0f, -1.0f, 0.0f, 1.0f,
2113 -1.0f, +1.0f, 0.0f, 1.0f,
2114 +1.0f, -1.0f, 0.0f, 1.0f,
2115 +1.0f, +1.0f, 0.0f, 1.0f
2116 };
2117 static const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
2118
2119 const int posLoc = glGetAttribLocation(program.getProgram(), "a_position");
2120 glEnableVertexAttribArray(posLoc);
2121 glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
2122 GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]));
2123 }
2124
2125 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess());
2126
2127 int numFailedPixels = 0;
2128 for (int y = 0; y < renderedImg.getHeight(); y++)
2129 {
2130 for (int x = 0; x < renderedImg.getWidth(); x++)
2131 {
2132 if (renderedImg.getPixel(x, y) != tcu::RGBA::white)
2133 numFailedPixels += 1;
2134 }
2135 }
2136
2137 if (numFailedPixels > 0)
2138 {
2139 log << TestLog::Image("RenderedImage", "Rendered image", renderedImg);
2140 log << TestLog::Message << "FAILURE: image comparison failed, got " << numFailedPixels << " non-white pixels" << TestLog::EndMessage;
2141 return false;
2142 }
2143 else
2144 {
2145 log << TestLog::Message << "Success: got all-white pixels (all uniforms have correct values)" << TestLog::EndMessage;
2146 return true;
2147 }
2148 }
2149
iterate(void)2150 UniformCase::IterateResult UniformCase::iterate (void)
2151 {
2152 Random rnd (deStringHash(getName()) ^ (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
2153 TestLog& log = m_testCtx.getLog();
2154 vector<BasicUniform> basicUniforms;
2155 vector<BasicUniformReportRef> basicUniformReportsRef;
2156
2157 {
2158 int samplerUnitCounter = 0;
2159 for (int i = 0; i < (int)m_uniformCollection->getNumUniforms(); i++)
2160 generateBasicUniforms(basicUniforms, basicUniformReportsRef, m_uniformCollection->getUniform(i).type, m_uniformCollection->getUniform(i).name.c_str(), true, samplerUnitCounter, rnd);
2161 }
2162
2163 const string vertexSource = generateVertexSource(basicUniforms);
2164 const string fragmentSource = generateFragmentSource(basicUniforms);
2165 const ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(vertexSource, fragmentSource));
2166
2167 log << program;
2168
2169 if (!program.isOk())
2170 {
2171 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
2172 return STOP;
2173 }
2174
2175 GLU_CHECK_CALL(glUseProgram(program.getProgram()));
2176
2177 const bool success = test(basicUniforms, basicUniformReportsRef, program, rnd);
2178 m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
2179 success ? "Passed" : "Failed");
2180
2181 return STOP;
2182 }
2183
2184 class UniformInfoQueryCase : public UniformCase
2185 {
2186 public:
2187 enum CaseType
2188 {
2189 CASETYPE_UNIFORM = 0, //!< Check info returned by glGetActiveUniform().
2190 CASETYPE_INDICES_UNIFORMSIV, //!< Check info returned by glGetUniformIndices() + glGetActiveUniformsiv().
2191 CASETYPE_CONSISTENCY, //!< Query info with both above methods, and check consistency.
2192
2193 CASETYPE_LAST
2194 };
2195
2196 UniformInfoQueryCase (Context& context, const char* name, const char* description, CaseShaderType shaderType, const SharedPtr<const UniformCollection>& uniformCollection, CaseType caseType, deUint32 additionalFeatures = 0);
2197 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd);
2198
2199 static const char* getCaseTypeName (CaseType caseType);
2200 static const char* getCaseTypeDescription (CaseType caseType);
2201
2202 private:
2203 const CaseType m_caseType;
2204 };
2205
getCaseTypeName(const CaseType caseType)2206 const char* UniformInfoQueryCase::getCaseTypeName (const CaseType caseType)
2207 {
2208 switch (caseType)
2209 {
2210 case CASETYPE_UNIFORM: return "active_uniform";
2211 case CASETYPE_INDICES_UNIFORMSIV: return "indices_active_uniformsiv";
2212 case CASETYPE_CONSISTENCY: return "consistency";
2213 default:
2214 DE_ASSERT(false);
2215 return DE_NULL;
2216 }
2217 }
2218
getCaseTypeDescription(const CaseType caseType)2219 const char* UniformInfoQueryCase::getCaseTypeDescription (const CaseType caseType)
2220 {
2221 switch (caseType)
2222 {
2223 case CASETYPE_UNIFORM: return "Test glGetActiveUniform()";
2224 case CASETYPE_INDICES_UNIFORMSIV: return "Test glGetUniformIndices() along with glGetActiveUniformsiv()";
2225 case CASETYPE_CONSISTENCY: return "Check consistency between results from glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniformsiv()";
2226 default:
2227 DE_ASSERT(false);
2228 return DE_NULL;
2229 }
2230 }
2231
UniformInfoQueryCase(Context & context,const char * const name,const char * const description,const CaseShaderType shaderType,const SharedPtr<const UniformCollection> & uniformCollection,const CaseType caseType,const deUint32 additionalFeatures)2232 UniformInfoQueryCase::UniformInfoQueryCase (Context& context, const char* const name, const char* const description, const CaseShaderType shaderType, const SharedPtr<const UniformCollection>& uniformCollection, const CaseType caseType, const deUint32 additionalFeatures)
2233 : UniformCase (context, name, description, shaderType, uniformCollection, additionalFeatures)
2234 , m_caseType (caseType)
2235 {
2236 }
2237
test(const vector<BasicUniform> & basicUniforms,const vector<BasicUniformReportRef> & basicUniformReportsRef,const ShaderProgram & program,Random & rnd)2238 bool UniformInfoQueryCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd)
2239 {
2240 DE_UNREF(basicUniforms);
2241 DE_UNREF(rnd);
2242
2243 const deUint32 programGL = program.getProgram();
2244 TestLog& log = m_testCtx.getLog();
2245 vector<BasicUniformReportGL> basicUniformReportsUniform;
2246 vector<BasicUniformReportGL> basicUniformReportsUniformsiv;
2247
2248 if (m_caseType == CASETYPE_UNIFORM || m_caseType == CASETYPE_CONSISTENCY)
2249 {
2250 bool success = false;
2251
2252 {
2253 const ScopedLogSection section(log, "InfoGetActiveUniform", "Uniform information queries with glGetActiveUniform()");
2254 success = getActiveUniforms(basicUniformReportsUniform, basicUniformReportsRef, programGL);
2255 }
2256
2257 if (!success)
2258 {
2259 if (m_caseType == CASETYPE_UNIFORM)
2260 return false;
2261 else
2262 {
2263 DE_ASSERT(m_caseType == CASETYPE_CONSISTENCY);
2264 log << TestLog::Message << "// Note: this is a consistency case, so ignoring above failure(s)" << TestLog::EndMessage;
2265 }
2266 }
2267 }
2268
2269 if (m_caseType == CASETYPE_INDICES_UNIFORMSIV || m_caseType == CASETYPE_CONSISTENCY)
2270 {
2271 bool success = false;
2272
2273 {
2274 const ScopedLogSection section(log, "InfoGetActiveUniformsiv", "Uniform information queries with glGetUniformIndices() and glGetActiveUniformsiv()");
2275 success = getActiveUniformsiv(basicUniformReportsUniformsiv, basicUniformReportsRef, programGL);
2276 }
2277
2278 if (!success)
2279 {
2280 if (m_caseType == CASETYPE_INDICES_UNIFORMSIV)
2281 return false;
2282 else
2283 {
2284 DE_ASSERT(m_caseType == CASETYPE_CONSISTENCY);
2285 log << TestLog::Message << "// Note: this is a consistency case, so ignoring above failure(s)" << TestLog::EndMessage;
2286 }
2287 }
2288 }
2289
2290 if (m_caseType == CASETYPE_CONSISTENCY)
2291 {
2292 bool success = false;
2293
2294 {
2295 const ScopedLogSection section(log, "CompareUniformVsUniformsiv", "Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()");
2296 success = uniformVsUniformsivComparison(basicUniformReportsUniform, basicUniformReportsUniformsiv);
2297 }
2298
2299 if (!success)
2300 return false;
2301 }
2302
2303 return true;
2304 }
2305
2306 class UniformValueCase : public UniformCase
2307 {
2308 public:
2309 enum ValueToCheck
2310 {
2311 VALUETOCHECK_INITIAL = 0, //!< Verify the initial values of the uniforms (i.e. check that they're zero).
2312 VALUETOCHECK_ASSIGNED, //!< Assign values to uniforms with glUniform*(), and check those.
2313
2314 VALUETOCHECK_LAST
2315 };
2316 enum CheckMethod
2317 {
2318 CHECKMETHOD_GET_UNIFORM = 0, //!< Check values with glGetUniform*().
2319 CHECKMETHOD_RENDER, //!< Check values by rendering with the value-checking shader.
2320
2321 CHECKMETHOD_LAST
2322 };
2323 enum AssignMethod
2324 {
2325 ASSIGNMETHOD_POINTER = 0,
2326 ASSIGNMETHOD_VALUE,
2327
2328 ASSIGNMETHOD_LAST
2329 };
2330
2331 UniformValueCase (Context& context,
2332 const char* name,
2333 const char* description,
2334 CaseShaderType shaderType,
2335 const SharedPtr<const UniformCollection>& uniformCollection,
2336 ValueToCheck valueToCheck,
2337 CheckMethod checkMethod,
2338 AssignMethod assignMethod,
2339 deUint32 additionalFeatures = 0);
2340
2341 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd);
2342
2343 static const char* getValueToCheckName (ValueToCheck valueToCheck);
2344 static const char* getValueToCheckDescription (ValueToCheck valueToCheck);
2345 static const char* getCheckMethodName (CheckMethod checkMethod);
2346 static const char* getCheckMethodDescription (CheckMethod checkMethod);
2347 static const char* getAssignMethodName (AssignMethod checkMethod);
2348 static const char* getAssignMethodDescription (AssignMethod checkMethod);
2349
2350 private:
2351 const ValueToCheck m_valueToCheck;
2352 const CheckMethod m_checkMethod;
2353 };
2354
getValueToCheckName(const ValueToCheck valueToCheck)2355 const char* UniformValueCase::getValueToCheckName (const ValueToCheck valueToCheck)
2356 {
2357 switch (valueToCheck)
2358 {
2359 case VALUETOCHECK_INITIAL: return "initial";
2360 case VALUETOCHECK_ASSIGNED: return "assigned";
2361 default: DE_ASSERT(false); return DE_NULL;
2362 }
2363 }
2364
getValueToCheckDescription(const ValueToCheck valueToCheck)2365 const char* UniformValueCase::getValueToCheckDescription (const ValueToCheck valueToCheck)
2366 {
2367 switch (valueToCheck)
2368 {
2369 case VALUETOCHECK_INITIAL: return "Check initial uniform values (zeros)";
2370 case VALUETOCHECK_ASSIGNED: return "Check assigned uniform values";
2371 default: DE_ASSERT(false); return DE_NULL;
2372 }
2373 }
2374
getCheckMethodName(const CheckMethod checkMethod)2375 const char* UniformValueCase::getCheckMethodName (const CheckMethod checkMethod)
2376 {
2377 switch (checkMethod)
2378 {
2379 case CHECKMETHOD_GET_UNIFORM: return "get_uniform";
2380 case CHECKMETHOD_RENDER: return "render";
2381 default: DE_ASSERT(false); return DE_NULL;
2382 }
2383 }
2384
getCheckMethodDescription(const CheckMethod checkMethod)2385 const char* UniformValueCase::getCheckMethodDescription (const CheckMethod checkMethod)
2386 {
2387 switch (checkMethod)
2388 {
2389 case CHECKMETHOD_GET_UNIFORM: return "Verify values with glGetUniform*()";
2390 case CHECKMETHOD_RENDER: return "Verify values by rendering";
2391 default: DE_ASSERT(false); return DE_NULL;
2392 }
2393 }
2394
getAssignMethodName(const AssignMethod assignMethod)2395 const char* UniformValueCase::getAssignMethodName (const AssignMethod assignMethod)
2396 {
2397 switch (assignMethod)
2398 {
2399 case ASSIGNMETHOD_POINTER: return "by_pointer";
2400 case ASSIGNMETHOD_VALUE: return "by_value";
2401 default: DE_ASSERT(false); return DE_NULL;
2402 }
2403 }
2404
getAssignMethodDescription(const AssignMethod assignMethod)2405 const char* UniformValueCase::getAssignMethodDescription (const AssignMethod assignMethod)
2406 {
2407 switch (assignMethod)
2408 {
2409 case ASSIGNMETHOD_POINTER: return "Assign values by-pointer";
2410 case ASSIGNMETHOD_VALUE: return "Assign values by-value";
2411 default: DE_ASSERT(false); return DE_NULL;
2412 }
2413 }
2414
UniformValueCase(Context & context,const char * const name,const char * const description,const CaseShaderType shaderType,const SharedPtr<const UniformCollection> & uniformCollection,const ValueToCheck valueToCheck,const CheckMethod checkMethod,const AssignMethod assignMethod,const deUint32 additionalFeatures)2415 UniformValueCase::UniformValueCase (Context& context,
2416 const char* const name,
2417 const char* const description,
2418 const CaseShaderType shaderType,
2419 const SharedPtr<const UniformCollection>& uniformCollection,
2420 const ValueToCheck valueToCheck,
2421 const CheckMethod checkMethod,
2422 const AssignMethod assignMethod,
2423 const deUint32 additionalFeatures)
2424 : UniformCase (context, name, description, shaderType, uniformCollection,
2425 (valueToCheck == VALUETOCHECK_INITIAL ? FEATURE_UNIFORMVALUE_ZERO : 0) | (assignMethod == ASSIGNMETHOD_VALUE ? FEATURE_UNIFORMFUNC_VALUE : 0) | additionalFeatures)
2426 , m_valueToCheck (valueToCheck)
2427 , m_checkMethod (checkMethod)
2428 {
2429 DE_ASSERT(!(assignMethod == ASSIGNMETHOD_LAST && valueToCheck == VALUETOCHECK_ASSIGNED));
2430 }
2431
test(const vector<BasicUniform> & basicUniforms,const vector<BasicUniformReportRef> & basicUniformReportsRef,const ShaderProgram & program,Random & rnd)2432 bool UniformValueCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd)
2433 {
2434 DE_UNREF(basicUniformReportsRef);
2435
2436 const deUint32 programGL = program.getProgram();
2437 TestLog& log = m_testCtx.getLog();
2438
2439 if (m_valueToCheck == VALUETOCHECK_ASSIGNED)
2440 {
2441 const ScopedLogSection section(log, "UniformAssign", "Uniform value assignments");
2442 assignUniforms(basicUniforms, programGL, rnd);
2443 }
2444 else
2445 DE_ASSERT(m_valueToCheck == VALUETOCHECK_INITIAL);
2446
2447 if (m_checkMethod == CHECKMETHOD_GET_UNIFORM)
2448 {
2449 vector<VarValue> values;
2450
2451 {
2452 const ScopedLogSection section(log, "GetUniforms", "Uniform value query");
2453 const bool success = getUniforms(values, basicUniforms, program.getProgram());
2454
2455 if (!success)
2456 return false;
2457 }
2458
2459 if (m_valueToCheck == VALUETOCHECK_ASSIGNED)
2460 {
2461 const ScopedLogSection section(log, "ValueCheck", "Verify that the reported values match the assigned values");
2462 const bool success = compareUniformValues(values, basicUniforms);
2463
2464 if (!success)
2465 return false;
2466 }
2467 else
2468 {
2469 DE_ASSERT(m_valueToCheck == VALUETOCHECK_INITIAL);
2470
2471 const ScopedLogSection section(log, "ValueCheck", "Verify that the uniforms have correct initial values (zeros)");
2472 const bool success = checkUniformDefaultValues(values, basicUniforms);
2473
2474 if (!success)
2475 return false;
2476 }
2477 }
2478 else
2479 {
2480 DE_ASSERT(m_checkMethod == CHECKMETHOD_RENDER);
2481
2482 const ScopedLogSection section(log, "RenderTest", "Render test");
2483 const bool success = renderTest(basicUniforms, program, rnd);
2484
2485 if (!success)
2486 return false;
2487 }
2488
2489 return true;
2490 }
2491
2492 class RandomUniformCase : public UniformCase
2493 {
2494 public:
2495 RandomUniformCase (Context& m_context, const char* name, const char* description, deUint32 seed);
2496
2497 bool test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd);
2498 };
2499
RandomUniformCase(Context & context,const char * const name,const char * const description,const deUint32 seed)2500 RandomUniformCase::RandomUniformCase (Context& context, const char* const name, const char* const description, const deUint32 seed)
2501 : UniformCase (context, name, description, seed ^ (deUint32)context.getTestContext().getCommandLine().getBaseSeed())
2502 {
2503 }
2504
test(const vector<BasicUniform> & basicUniforms,const vector<BasicUniformReportRef> & basicUniformReportsRef,const ShaderProgram & program,Random & rnd)2505 bool RandomUniformCase::test (const vector<BasicUniform>& basicUniforms, const vector<BasicUniformReportRef>& basicUniformReportsRef, const ShaderProgram& program, Random& rnd)
2506 {
2507 // \note Different sampler types may not be bound to same unit when rendering.
2508 const bool renderingPossible = (m_features & FEATURE_UNIFORMVALUE_ZERO) == 0 || !m_uniformCollection->containsSeveralSamplerTypes();
2509
2510 bool performGetActiveUniforms = rnd.getBool();
2511 const bool performGetActiveUniformsiv = rnd.getBool();
2512 const bool performUniformVsUniformsivComparison = performGetActiveUniforms && performGetActiveUniformsiv && rnd.getBool();
2513 const bool performGetUniforms = rnd.getBool();
2514 const bool performCheckUniformDefaultValues = performGetUniforms && rnd.getBool();
2515 const bool performAssignUniforms = rnd.getBool();
2516 const bool performCompareUniformValues = performGetUniforms && performAssignUniforms && rnd.getBool();
2517 const bool performRenderTest = renderingPossible && performAssignUniforms && rnd.getBool();
2518 const deUint32 programGL = program.getProgram();
2519 TestLog& log = m_testCtx.getLog();
2520
2521 if (!(performGetActiveUniforms || performGetActiveUniformsiv || performUniformVsUniformsivComparison || performGetUniforms || performCheckUniformDefaultValues || performAssignUniforms || performCompareUniformValues || performRenderTest))
2522 performGetActiveUniforms = true; // Do something at least.
2523
2524 #define PERFORM_AND_CHECK(CALL, SECTION_NAME, SECTION_DESCRIPTION) \
2525 do \
2526 { \
2527 const ScopedLogSection section(log, (SECTION_NAME), (SECTION_DESCRIPTION)); \
2528 const bool success = (CALL); \
2529 if (!success) \
2530 return false; \
2531 } while (false)
2532
2533 {
2534 vector<BasicUniformReportGL> reportsUniform;
2535 vector<BasicUniformReportGL> reportsUniformsiv;
2536
2537 if (performGetActiveUniforms)
2538 PERFORM_AND_CHECK(getActiveUniforms(reportsUniform, basicUniformReportsRef, programGL), "InfoGetActiveUniform", "Uniform information queries with glGetActiveUniform()");
2539 if (performGetActiveUniformsiv)
2540 PERFORM_AND_CHECK(getActiveUniformsiv(reportsUniformsiv, basicUniformReportsRef, programGL), "InfoGetActiveUniformsiv", "Uniform information queries with glGetIndices() and glGetActiveUniformsiv()");
2541 if (performUniformVsUniformsivComparison)
2542 PERFORM_AND_CHECK(uniformVsUniformsivComparison(reportsUniform, reportsUniformsiv), "CompareUniformVsUniformsiv", "Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()");
2543 }
2544
2545 {
2546 vector<VarValue> uniformDefaultValues;
2547
2548 if (performGetUniforms)
2549 PERFORM_AND_CHECK(getUniforms(uniformDefaultValues, basicUniforms, programGL), "GetUniformDefaults", "Uniform default value query");
2550 if (performCheckUniformDefaultValues)
2551 PERFORM_AND_CHECK(checkUniformDefaultValues(uniformDefaultValues, basicUniforms), "DefaultValueCheck", "Verify that the uniforms have correct initial values (zeros)");
2552 }
2553
2554 {
2555 vector<VarValue> uniformValues;
2556
2557 if (performAssignUniforms)
2558 {
2559 const ScopedLogSection section(log, "UniformAssign", "Uniform value assignments");
2560 assignUniforms(basicUniforms, programGL, rnd);
2561 }
2562 if (performCompareUniformValues)
2563 {
2564 PERFORM_AND_CHECK(getUniforms(uniformValues, basicUniforms, programGL), "GetUniforms", "Uniform value query");
2565 PERFORM_AND_CHECK(compareUniformValues(uniformValues, basicUniforms), "ValueCheck", "Verify that the reported values match the assigned values");
2566 }
2567 }
2568
2569 if (performRenderTest)
2570 PERFORM_AND_CHECK(renderTest(basicUniforms, program, rnd), "RenderTest", "Render test");
2571
2572 #undef PERFORM_AND_CHECK
2573
2574 return true;
2575 }
2576
UniformApiTests(Context & context)2577 UniformApiTests::UniformApiTests (Context& context)
2578 : TestCaseGroup(context, "uniform_api", "Uniform API Tests")
2579 {
2580 }
2581
~UniformApiTests(void)2582 UniformApiTests::~UniformApiTests (void)
2583 {
2584 }
2585
2586 namespace
2587 {
2588
2589 // \note Although this is only used in UniformApiTest::init, it needs to be defined here as it's used as a template argument.
2590 struct UniformCollectionCase
2591 {
2592 string namePrefix;
2593 SharedPtr<const UniformCollection> uniformCollection;
2594
UniformCollectionCasedeqp::gles3::Functional::__anon861d11500611::UniformCollectionCase2595 UniformCollectionCase (const char* const name, const UniformCollection* uniformCollection_)
2596 : namePrefix (name ? name + string("_") : "")
2597 , uniformCollection (uniformCollection_)
2598 {
2599 }
2600 };
2601
2602 } // anonymous
2603
init(void)2604 void UniformApiTests::init (void)
2605 {
2606 // Generate sets of UniformCollections that are used by several cases.
2607
2608 enum
2609 {
2610 UNIFORMCOLLECTIONS_BASIC = 0,
2611 UNIFORMCOLLECTIONS_BASIC_ARRAY,
2612 UNIFORMCOLLECTIONS_BASIC_STRUCT,
2613 UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY,
2614 UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT,
2615 UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS,
2616 UNIFORMCOLLECTIONS_MULTIPLE_BASIC,
2617 UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY,
2618 UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS,
2619
2620 UNIFORMCOLLECTIONS_LAST
2621 };
2622
2623 struct UniformCollectionGroup
2624 {
2625 string name;
2626 vector<UniformCollectionCase> cases;
2627 } defaultUniformCollections[UNIFORMCOLLECTIONS_LAST];
2628
2629 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC].name = "basic";
2630 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_ARRAY].name = "basic_array";
2631 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_STRUCT].name = "basic_struct";
2632 defaultUniformCollections[UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY].name = "struct_in_array";
2633 defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT].name = "array_in_struct";
2634 defaultUniformCollections[UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS].name = "nested_structs_arrays";
2635 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC].name = "multiple_basic";
2636 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY].name = "multiple_basic_array";
2637 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS].name = "multiple_nested_structs_arrays";
2638
2639 for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_testDataTypes); dataTypeNdx++)
2640 {
2641 const glu::DataType dataType = s_testDataTypes[dataTypeNdx];
2642 const char* const typeName = glu::getDataTypeName(dataType);
2643
2644 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC].cases.push_back(UniformCollectionCase(typeName, UniformCollection::basic(dataType)));
2645
2646 if (glu::isDataTypeScalar(dataType) ||
2647 (glu::isDataTypeVector(dataType) && glu::getDataTypeScalarSize(dataType) == 4) ||
2648 dataType == glu::TYPE_FLOAT_MAT4 ||
2649 dataType == glu::TYPE_SAMPLER_2D)
2650 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_ARRAY].cases.push_back(UniformCollectionCase(typeName, UniformCollection::basicArray(dataType)));
2651
2652 if (glu::isDataTypeScalar(dataType) ||
2653 dataType == glu::TYPE_FLOAT_MAT4 ||
2654 dataType == glu::TYPE_SAMPLER_2D)
2655 {
2656 const glu::DataType secondDataType = glu::isDataTypeScalar(dataType) ? glu::getDataTypeVector(dataType, 4)
2657 : dataType == glu::TYPE_FLOAT_MAT4 ? glu::TYPE_FLOAT_MAT2
2658 : dataType == glu::TYPE_SAMPLER_2D ? glu::TYPE_SAMPLER_CUBE
2659 : glu::TYPE_LAST;
2660 DE_ASSERT(secondDataType != glu::TYPE_LAST);
2661 const char* const secondTypeName = glu::getDataTypeName(secondDataType);
2662 const string name = string("") + typeName + "_" + secondTypeName;
2663
2664 defaultUniformCollections[UNIFORMCOLLECTIONS_BASIC_STRUCT].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::basicStruct(dataType, secondDataType, false)));
2665 defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::basicStruct(dataType, secondDataType, true)));
2666 defaultUniformCollections[UNIFORMCOLLECTIONS_STRUCT_IN_ARRAY].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::structInArray(dataType, secondDataType, false)));
2667 defaultUniformCollections[UNIFORMCOLLECTIONS_NESTED_STRUCTS_ARRAYS].cases.push_back (UniformCollectionCase(name.c_str(), UniformCollection::nestedArraysStructs(dataType, secondDataType)));
2668 }
2669 }
2670 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleBasic()));
2671 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleBasicArray()));
2672 defaultUniformCollections[UNIFORMCOLLECTIONS_MULTIPLE_NESTED_STRUCTS_ARRAYS].cases.push_back (UniformCollectionCase(DE_NULL, UniformCollection::multipleNestedArraysStructs()));
2673
2674 // Info-query cases (check info returned by e.g. glGetActiveUniforms()).
2675
2676 {
2677 TestCaseGroup* const infoQueryGroup = new TestCaseGroup(m_context, "info_query", "Test uniform info querying functions");
2678 addChild(infoQueryGroup);
2679 for (int caseTypeI = 0; caseTypeI < (int)UniformInfoQueryCase::CASETYPE_LAST; caseTypeI++)
2680 {
2681 const UniformInfoQueryCase::CaseType caseType = (UniformInfoQueryCase::CaseType)caseTypeI;
2682 TestCaseGroup* const caseTypeGroup = new TestCaseGroup(m_context, UniformInfoQueryCase::getCaseTypeName(caseType), UniformInfoQueryCase::getCaseTypeDescription(caseType));
2683 infoQueryGroup->addChild(caseTypeGroup);
2684
2685 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++)
2686 {
2687 const int numArrayFirstElemNameCases = caseType == UniformInfoQueryCase::CASETYPE_INDICES_UNIFORMSIV && collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY ? 2 : 1;
2688
2689 for (int referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++)
2690 {
2691 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx];
2692 const string collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? "" : "_first_elem_without_brackets");
2693 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroupName.c_str(), "");
2694 caseTypeGroup->addChild(collectionTestGroup);
2695
2696 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
2697 {
2698 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx];
2699
2700 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
2701 {
2702 const string name = collectionCase.namePrefix + getCaseShaderTypeName((CaseShaderType)shaderType);
2703 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection;
2704
2705 collectionTestGroup->addChild(new UniformInfoQueryCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, (UniformInfoQueryCase::CaseType)caseType,
2706 referToFirstArrayElemWithoutIndexI == 0 ? 0 : UniformCase::FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX));
2707 }
2708 }
2709 }
2710 }
2711
2712 // Info-querying cases when unused uniforms are present.
2713
2714 {
2715 TestCaseGroup* const unusedUniformsGroup = new TestCaseGroup(m_context, "unused_uniforms", "Test with unused uniforms");
2716 caseTypeGroup->addChild(unusedUniformsGroup);
2717
2718 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT];
2719
2720 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
2721 {
2722 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx];
2723 const string collName = collectionCase.namePrefix;
2724 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection;
2725
2726 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
2727 {
2728 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType);
2729 unusedUniformsGroup->addChild(new UniformInfoQueryCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection, (UniformInfoQueryCase::CaseType)caseType,
2730 UniformCase::FEATURE_UNIFORMUSAGE_EVERY_OTHER | UniformCase::FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX));
2731 }
2732 }
2733 }
2734 }
2735 }
2736
2737 // Cases testing uniform values.
2738
2739 {
2740 TestCaseGroup* const valueGroup = new TestCaseGroup(m_context, "value", "Uniform value tests");
2741 addChild(valueGroup);
2742
2743 // Cases checking uniforms' initial values (all must be zeros), with glGetUniform*() or by rendering.
2744
2745 {
2746 TestCaseGroup* const initialValuesGroup = new TestCaseGroup(m_context,
2747 UniformValueCase::getValueToCheckName(UniformValueCase::VALUETOCHECK_INITIAL),
2748 UniformValueCase::getValueToCheckDescription(UniformValueCase::VALUETOCHECK_INITIAL));
2749 valueGroup->addChild(initialValuesGroup);
2750
2751 for (int checkMethodI = 0; checkMethodI < (int)UniformValueCase::CHECKMETHOD_LAST; checkMethodI++)
2752 {
2753 const UniformValueCase::CheckMethod checkMethod = (UniformValueCase::CheckMethod)checkMethodI;
2754 TestCaseGroup* const checkMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getCheckMethodName(checkMethod), UniformValueCase::getCheckMethodDescription(checkMethod));
2755 initialValuesGroup->addChild(checkMethodGroup);
2756
2757 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++)
2758 {
2759 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx];
2760 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroup.name.c_str(), "");
2761 checkMethodGroup->addChild(collectionTestGroup);
2762
2763 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
2764 {
2765 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx];
2766 const string collName = collectionCase.namePrefix;
2767 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection;
2768 const bool containsBooleans = uniformCollection->containsMatchingBasicType(glu::isDataTypeBoolOrBVec);
2769 const bool varyBoolApiType = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && containsBooleans &&
2770 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY);
2771 const int numBoolVariations = varyBoolApiType ? 3 : 1;
2772
2773 if (checkMethod == UniformValueCase::CHECKMETHOD_RENDER && uniformCollection->containsSeveralSamplerTypes())
2774 continue; // \note Samplers' initial API values (i.e. their texture units) are 0, and no two samplers of different types shall have same unit when rendering.
2775
2776 for (int booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++)
2777 {
2778 const deUint32 booleanTypeFeat = booleanTypeI == 1 ? UniformCase::FEATURE_BOOLEANAPITYPE_INT
2779 : booleanTypeI == 2 ? UniformCase::FEATURE_BOOLEANAPITYPE_UINT
2780 : 0;
2781 const char* const booleanTypeName = booleanTypeI == 1 ? "int"
2782 : booleanTypeI == 2 ? "uint"
2783 : "float";
2784 const string nameWithApiType = varyBoolApiType ? collName + "api_" + booleanTypeName + "_" : collName;
2785
2786 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
2787 {
2788 const string name = nameWithApiType + getCaseShaderTypeName((CaseShaderType)shaderType);
2789 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection,
2790 UniformValueCase::VALUETOCHECK_INITIAL, checkMethod, UniformValueCase::ASSIGNMETHOD_LAST, booleanTypeFeat));
2791 }
2792 }
2793 }
2794 }
2795 }
2796 }
2797
2798 // Cases that first assign values to each uniform, then check the values with glGetUniform*() or by rendering.
2799
2800 {
2801 TestCaseGroup* const assignedValuesGroup = new TestCaseGroup(m_context,
2802 UniformValueCase::getValueToCheckName(UniformValueCase::VALUETOCHECK_ASSIGNED),
2803 UniformValueCase::getValueToCheckDescription(UniformValueCase::VALUETOCHECK_ASSIGNED));
2804 valueGroup->addChild(assignedValuesGroup);
2805
2806 for (int assignMethodI = 0; assignMethodI < (int)UniformValueCase::ASSIGNMETHOD_LAST; assignMethodI++)
2807 {
2808 const UniformValueCase::AssignMethod assignMethod = (UniformValueCase::AssignMethod)assignMethodI;
2809 TestCaseGroup* const assignMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getAssignMethodName(assignMethod), UniformValueCase::getAssignMethodDescription(assignMethod));
2810 assignedValuesGroup->addChild(assignMethodGroup);
2811
2812 for (int checkMethodI = 0; checkMethodI < (int)UniformValueCase::CHECKMETHOD_LAST; checkMethodI++)
2813 {
2814 const UniformValueCase::CheckMethod checkMethod = (UniformValueCase::CheckMethod)checkMethodI;
2815 TestCaseGroup* const checkMethodGroup = new TestCaseGroup(m_context, UniformValueCase::getCheckMethodName(checkMethod), UniformValueCase::getCheckMethodDescription(checkMethod));
2816 assignMethodGroup->addChild(checkMethodGroup);
2817
2818 for (int collectionGroupNdx = 0; collectionGroupNdx < (int)UNIFORMCOLLECTIONS_LAST; collectionGroupNdx++)
2819 {
2820 const int numArrayFirstElemNameCases = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY ? 2 : 1;
2821
2822 for (int referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++)
2823 {
2824 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[collectionGroupNdx];
2825 const string collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? "" : "_first_elem_without_brackets");
2826 TestCaseGroup* collectionTestGroup = DE_NULL;
2827
2828 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
2829 {
2830 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx];
2831 const string collName = collectionCase.namePrefix;
2832 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection;
2833 const bool containsBooleans = uniformCollection->containsMatchingBasicType(glu::isDataTypeBoolOrBVec);
2834 const bool varyBoolApiType = checkMethod == UniformValueCase::CHECKMETHOD_GET_UNIFORM && containsBooleans &&
2835 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY);
2836 const int numBoolVariations = varyBoolApiType ? 3 : 1;
2837 const bool containsMatrices = uniformCollection->containsMatchingBasicType(glu::isDataTypeMatrix);
2838 const bool varyMatrixMode = containsMatrices &&
2839 (collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC || collectionGroupNdx == UNIFORMCOLLECTIONS_BASIC_ARRAY);
2840 const int numMatVariations = varyMatrixMode ? 2 : 1;
2841
2842 if (containsMatrices && assignMethod != UniformValueCase::ASSIGNMETHOD_POINTER)
2843 continue;
2844
2845 for (int booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++)
2846 {
2847 const deUint32 booleanTypeFeat = booleanTypeI == 1 ? UniformCase::FEATURE_BOOLEANAPITYPE_INT
2848 : booleanTypeI == 2 ? UniformCase::FEATURE_BOOLEANAPITYPE_UINT
2849 : 0;
2850 const char* const booleanTypeName = booleanTypeI == 1 ? "int"
2851 : booleanTypeI == 2 ? "uint"
2852 : "float";
2853 const string nameWithBoolType = varyBoolApiType ? collName + "api_" + booleanTypeName + "_" : collName;
2854
2855 for (int matrixTypeI = 0; matrixTypeI < numMatVariations; matrixTypeI++)
2856 {
2857 const string nameWithMatrixType = nameWithBoolType + (matrixTypeI == 1 ? "row_major_" : "");
2858
2859 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
2860 {
2861 const string name = nameWithMatrixType + getCaseShaderTypeName((CaseShaderType)shaderType);
2862 const deUint32 arrayFirstElemNameNoIndexFeat = referToFirstArrayElemWithoutIndexI == 0 ? 0 : UniformCase::FEATURE_ARRAY_FIRST_ELEM_NAME_NO_INDEX;
2863
2864 // skip empty groups by creating groups on demand
2865 if (!collectionTestGroup)
2866 {
2867 collectionTestGroup = new TestCaseGroup(m_context, collectionGroupName.c_str(), "");
2868 checkMethodGroup->addChild(collectionTestGroup);
2869 }
2870
2871 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection,
2872 UniformValueCase::VALUETOCHECK_ASSIGNED, checkMethod, assignMethod,
2873 booleanTypeFeat | arrayFirstElemNameNoIndexFeat | (matrixTypeI == 1 ? UniformCase::FEATURE_MATRIXMODE_ROWMAJOR : 0)));
2874 }
2875 }
2876 }
2877 }
2878 }
2879 }
2880 }
2881 }
2882
2883 // Cases assign multiple basic-array elements with one glUniform*v() (i.e. the count parameter is bigger than 1).
2884
2885 {
2886 static const struct
2887 {
2888 UniformCase::Feature arrayAssignMode;
2889 const char* name;
2890 const char* description;
2891 } arrayAssignGroups[] =
2892 {
2893 { UniformCase::FEATURE_ARRAYASSIGN_FULL, "basic_array_assign_full", "Assign entire basic-type arrays per glUniform*v() call" },
2894 { UniformCase::FEATURE_ARRAYASSIGN_BLOCKS_OF_TWO, "basic_array_assign_partial", "Assign two elements of a basic-type array per glUniform*v() call" }
2895 };
2896
2897 for (int arrayAssignGroupNdx = 0; arrayAssignGroupNdx < DE_LENGTH_OF_ARRAY(arrayAssignGroups); arrayAssignGroupNdx++)
2898 {
2899 UniformCase::Feature arrayAssignMode = arrayAssignGroups[arrayAssignGroupNdx].arrayAssignMode;
2900 const char* const groupName = arrayAssignGroups[arrayAssignGroupNdx].name;
2901 const char* const groupDesc = arrayAssignGroups[arrayAssignGroupNdx].description;
2902
2903 TestCaseGroup* const curArrayAssignGroup = new TestCaseGroup(m_context, groupName, groupDesc);
2904 assignedValuesGroup->addChild(curArrayAssignGroup);
2905
2906 static const int basicArrayCollectionGroups[] = { UNIFORMCOLLECTIONS_BASIC_ARRAY, UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT, UNIFORMCOLLECTIONS_MULTIPLE_BASIC_ARRAY };
2907
2908 for (int collectionGroupNdx = 0; collectionGroupNdx < DE_LENGTH_OF_ARRAY(basicArrayCollectionGroups); collectionGroupNdx++)
2909 {
2910 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[basicArrayCollectionGroups[collectionGroupNdx]];
2911 TestCaseGroup* const collectionTestGroup = new TestCaseGroup(m_context, collectionGroup.name.c_str(), "");
2912 curArrayAssignGroup->addChild(collectionTestGroup);
2913
2914 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
2915 {
2916 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx];
2917 const string collName = collectionCase.namePrefix;
2918 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection;
2919
2920 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
2921 {
2922 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType);
2923 collectionTestGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection,
2924 UniformValueCase::VALUETOCHECK_ASSIGNED, UniformValueCase::CHECKMETHOD_GET_UNIFORM, UniformValueCase::ASSIGNMETHOD_POINTER,
2925 arrayAssignMode));
2926 }
2927 }
2928 }
2929 }
2930 }
2931
2932 // Value checking cases when unused uniforms are present.
2933
2934 {
2935 TestCaseGroup* const unusedUniformsGroup = new TestCaseGroup(m_context, "unused_uniforms", "Test with unused uniforms");
2936 assignedValuesGroup->addChild(unusedUniformsGroup);
2937
2938 const UniformCollectionGroup& collectionGroup = defaultUniformCollections[UNIFORMCOLLECTIONS_ARRAY_IN_STRUCT];
2939
2940 for (int collectionNdx = 0; collectionNdx < (int)collectionGroup.cases.size(); collectionNdx++)
2941 {
2942 const UniformCollectionCase& collectionCase = collectionGroup.cases[collectionNdx];
2943 const string collName = collectionCase.namePrefix;
2944 const SharedPtr<const UniformCollection>& uniformCollection = collectionCase.uniformCollection;
2945
2946 for (int shaderType = 0; shaderType < (int)CASESHADERTYPE_LAST; shaderType++)
2947 {
2948 const string name = collName + getCaseShaderTypeName((CaseShaderType)shaderType);
2949 unusedUniformsGroup->addChild(new UniformValueCase(m_context, name.c_str(), "", (CaseShaderType)shaderType, uniformCollection,
2950 UniformValueCase::VALUETOCHECK_ASSIGNED, UniformValueCase::CHECKMETHOD_GET_UNIFORM, UniformValueCase::ASSIGNMETHOD_POINTER,
2951 UniformCase::FEATURE_ARRAYUSAGE_ONLY_MIDDLE_INDEX | UniformCase::FEATURE_UNIFORMUSAGE_EVERY_OTHER));
2952 }
2953 }
2954 }
2955 }
2956 }
2957
2958 // Random cases.
2959
2960 {
2961 const int numRandomCases = 100;
2962 TestCaseGroup* const randomGroup = new TestCaseGroup(m_context, "random", "Random cases");
2963 addChild(randomGroup);
2964
2965 for (int ndx = 0; ndx < numRandomCases; ndx++)
2966 randomGroup->addChild(new RandomUniformCase(m_context, de::toString(ndx).c_str(), "", (deUint32)ndx));
2967 }
2968 }
2969
2970 } // Functional
2971 } // gles3
2972 } // deqp
2973