1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2016 Google Inc.
6 * Copyright (c) 2016 The Khronos Group Inc.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 * \brief Uniform block tests.
23 */ /*-------------------------------------------------------------------*/
25 #include "glcUniformBlockTests.hpp"
26 #include "deRandom.hpp"
27 #include "deStringUtil.hpp"
28 #include "glcUniformBlockCase.hpp"
29 #include "tcuCommandLine.hpp"
42 FEATURE_VECTORS = (1 << 0),
43 FEATURE_MATRICES = (1 << 1),
44 FEATURE_ARRAYS = (1 << 2),
45 FEATURE_STRUCTS = (1 << 3),
46 FEATURE_NESTED_STRUCTS = (1 << 4),
47 FEATURE_INSTANCE_ARRAYS = (1 << 5),
48 FEATURE_VERTEX_BLOCKS = (1 << 6),
49 FEATURE_FRAGMENT_BLOCKS = (1 << 7),
50 FEATURE_SHARED_BLOCKS = (1 << 8),
51 FEATURE_UNUSED_UNIFORMS = (1 << 9),
52 FEATURE_UNUSED_MEMBERS = (1 << 10),
53 FEATURE_PACKED_LAYOUT = (1 << 11),
54 FEATURE_SHARED_LAYOUT = (1 << 12),
55 FEATURE_STD140_LAYOUT = (1 << 13),
56 FEATURE_MATRIX_LAYOUT = (1 << 14) //!< Matrix layout flags.
59 class RandomUniformBlockCase : public UniformBlockCase
62 RandomUniformBlockCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
63 BufferMode bufferMode, deUint32 features, deUint32 seed);
68 void generateBlock(de::Random& rnd, deUint32 layoutFlags);
69 void generateUniform(de::Random& rnd, UniformBlock& block);
70 VarType generateType(de::Random& rnd, int typeDepth, bool arrayOk);
73 int m_maxVertexBlocks;
74 int m_maxFragmentBlocks;
75 int m_maxSharedBlocks;
79 int m_maxBlockMembers;
80 int m_maxStructMembers;
88 RandomUniformBlockCase::RandomUniformBlockCase(Context& context, const char* name, const char* description,
89 glu::GLSLVersion glslVersion, BufferMode bufferMode, deUint32 features,
91 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
92 , m_features(features)
93 , m_maxVertexBlocks((features & FEATURE_VERTEX_BLOCKS) ? 4 : 0)
94 , m_maxFragmentBlocks((features & FEATURE_FRAGMENT_BLOCKS) ? 4 : 0)
95 , m_maxSharedBlocks((features & FEATURE_SHARED_BLOCKS) ? 4 : 0)
96 , m_maxInstances((features & FEATURE_INSTANCE_ARRAYS) ? 3 : 0)
97 , m_maxArrayLength((features & FEATURE_ARRAYS) ? 8 : 0)
98 , m_maxStructDepth((features & FEATURE_STRUCTS) ? 2 : 0)
99 , m_maxBlockMembers(5)
100 , m_maxStructMembers(4)
108 void RandomUniformBlockCase::init(void)
110 de::Random rnd(m_seed);
112 int numShared = m_maxSharedBlocks > 0 ? rnd.getInt(1, m_maxSharedBlocks) : 0;
113 int numVtxBlocks = m_maxVertexBlocks - numShared > 0 ? rnd.getInt(1, m_maxVertexBlocks - numShared) : 0;
114 int numFragBlocks = m_maxFragmentBlocks - numShared > 0 ? rnd.getInt(1, m_maxFragmentBlocks - numShared) : 0;
116 for (int ndx = 0; ndx < numShared; ndx++)
117 generateBlock(rnd, DECLARE_VERTEX | DECLARE_FRAGMENT);
119 for (int ndx = 0; ndx < numVtxBlocks; ndx++)
120 generateBlock(rnd, DECLARE_VERTEX);
122 for (int ndx = 0; ndx < numFragBlocks; ndx++)
123 generateBlock(rnd, DECLARE_FRAGMENT);
126 void RandomUniformBlockCase::generateBlock(de::Random& rnd, deUint32 layoutFlags)
128 DE_ASSERT(m_blockNdx <= 'z' - 'a');
130 const float instanceArrayWeight = 0.3f;
131 UniformBlock& block = m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
132 int numInstances = (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
133 int numUniforms = rnd.getInt(1, m_maxBlockMembers);
135 if (numInstances > 0)
136 block.setArraySize(numInstances);
138 if (numInstances > 0 || rnd.getBool())
139 block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
141 // Layout flag candidates.
142 vector<deUint32> layoutFlagCandidates;
143 layoutFlagCandidates.push_back(0);
144 if (m_features & FEATURE_PACKED_LAYOUT)
145 layoutFlagCandidates.push_back(LAYOUT_SHARED);
146 if ((m_features & FEATURE_SHARED_LAYOUT) && ((layoutFlags & DECLARE_BOTH) != DECLARE_BOTH))
147 layoutFlagCandidates.push_back(LAYOUT_PACKED); // \note packed layout can only be used in a single shader stage.
148 if (m_features & FEATURE_STD140_LAYOUT)
149 layoutFlagCandidates.push_back(LAYOUT_STD140);
151 layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
153 if (m_features & FEATURE_MATRIX_LAYOUT)
155 static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
157 rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
160 block.setFlags(layoutFlags);
162 for (int ndx = 0; ndx < numUniforms; ndx++)
163 generateUniform(rnd, block);
168 static std::string genName(char first, char last, int ndx)
170 std::string str = "";
171 int alphabetLen = last - first + 1;
173 while (ndx > alphabetLen)
175 str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen)));
176 ndx = ((ndx - 1) / alphabetLen);
179 str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1));
184 void RandomUniformBlockCase::generateUniform(de::Random& rnd, UniformBlock& block)
186 const float unusedVtxWeight = 0.15f;
187 const float unusedFragWeight = 0.15f;
188 bool unusedOk = (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
190 std::string name = genName('a', 'z', m_uniformNdx);
191 VarType type = generateType(rnd, 0, true);
193 flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
194 flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
196 block.addUniform(Uniform(name.c_str(), type, flags));
201 VarType RandomUniformBlockCase::generateType(de::Random& rnd, int typeDepth, bool arrayOk)
203 const float structWeight = 0.1f;
204 const float arrayWeight = 0.1f;
206 if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
208 const float unusedVtxWeight = 0.15f;
209 const float unusedFragWeight = 0.15f;
210 bool unusedOk = (m_features & FEATURE_UNUSED_MEMBERS) != 0;
211 vector<VarType> memberTypes;
212 int numMembers = rnd.getInt(1, m_maxStructMembers);
214 // Generate members first so nested struct declarations are in correct order.
215 for (int ndx = 0; ndx < numMembers; ndx++)
216 memberTypes.push_back(generateType(rnd, typeDepth + 1, true));
218 StructType& structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
221 DE_ASSERT(numMembers <= 'Z' - 'A');
222 for (int ndx = 0; ndx < numMembers; ndx++)
226 flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
227 flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
229 structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx], flags);
232 return VarType(&structType);
234 else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
236 int arrayLength = rnd.getInt(1, m_maxArrayLength);
237 VarType elementType = generateType(rnd, typeDepth, false /* nested arrays are not allowed */);
238 return VarType(elementType, arrayLength);
242 vector<glu::DataType> typeCandidates;
244 typeCandidates.push_back(glu::TYPE_FLOAT);
245 typeCandidates.push_back(glu::TYPE_INT);
246 typeCandidates.push_back(glu::TYPE_UINT);
247 typeCandidates.push_back(glu::TYPE_BOOL);
249 if (m_features & FEATURE_VECTORS)
251 typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
252 typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
253 typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
254 typeCandidates.push_back(glu::TYPE_INT_VEC2);
255 typeCandidates.push_back(glu::TYPE_INT_VEC3);
256 typeCandidates.push_back(glu::TYPE_INT_VEC4);
257 typeCandidates.push_back(glu::TYPE_UINT_VEC2);
258 typeCandidates.push_back(glu::TYPE_UINT_VEC3);
259 typeCandidates.push_back(glu::TYPE_UINT_VEC4);
260 typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
261 typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
262 typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
265 if (m_features & FEATURE_MATRICES)
267 typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
268 typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
269 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
270 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
271 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
272 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
273 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
274 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
277 glu::DataType type = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
280 if (!glu::isDataTypeBoolOrBVec(type))
283 static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
284 flags |= rnd.choose<deUint32>(&precisionCandidates[0],
285 &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
288 return VarType(type, flags);
292 class BlockBasicTypeCase : public UniformBlockCase
295 BlockBasicTypeCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
296 const VarType& type, deUint32 layoutFlags, int numInstances)
297 : UniformBlockCase(context, name, description, glslVersion, BUFFERMODE_PER_BLOCK)
299 UniformBlock& block = m_interface.allocBlock("Block");
300 block.addUniform(Uniform("var", type, 0));
301 block.setFlags(layoutFlags);
303 if (numInstances > 0)
305 block.setArraySize(numInstances);
306 block.setInstanceName("block");
311 static void createRandomCaseGroup(tcu::TestCaseGroup* parentGroup, Context& context, const char* groupName,
312 const char* description, glu::GLSLVersion glslVersion,
313 UniformBlockCase::BufferMode bufferMode, deUint32 features, int numCases,
316 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description);
317 parentGroup->addChild(group);
319 baseSeed += (deUint32)context.getTestContext().getCommandLine().getBaseSeed();
321 for (int ndx = 0; ndx < numCases; ndx++)
322 group->addChild(new RandomUniformBlockCase(context, de::toString(ndx).c_str(), "", glslVersion, bufferMode,
323 features, (deUint32)deInt32Hash(ndx + baseSeed)));
326 class BlockSingleStructCase : public UniformBlockCase
329 BlockSingleStructCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
330 deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
331 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
332 , m_layoutFlags(layoutFlags)
333 , m_numInstances(numInstances)
339 StructType& typeS = m_interface.allocStruct("S");
340 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH); // First member is unused.
341 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
342 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
344 UniformBlock& block = m_interface.allocBlock("Block");
345 block.addUniform(Uniform("s", VarType(&typeS), 0));
346 block.setFlags(m_layoutFlags);
348 if (m_numInstances > 0)
350 block.setInstanceName("block");
351 block.setArraySize(m_numInstances);
356 deUint32 m_layoutFlags;
360 class BlockSingleStructArrayCase : public UniformBlockCase
363 BlockSingleStructArrayCase(Context& context, const char* name, const char* description,
364 glu::GLSLVersion glslVersion, deUint32 layoutFlags, BufferMode bufferMode,
366 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
367 , m_layoutFlags(layoutFlags)
368 , m_numInstances(numInstances)
374 StructType& typeS = m_interface.allocStruct("S");
375 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
376 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
377 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
379 UniformBlock& block = m_interface.allocBlock("Block");
380 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_LOW)));
381 block.addUniform(Uniform("s", VarType(VarType(&typeS), 3)));
382 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_MEDIUM)));
383 block.setFlags(m_layoutFlags);
385 if (m_numInstances > 0)
387 block.setInstanceName("block");
388 block.setArraySize(m_numInstances);
393 deUint32 m_layoutFlags;
397 class BlockSingleNestedStructCase : public UniformBlockCase
400 BlockSingleNestedStructCase(Context& context, const char* name, const char* description,
401 glu::GLSLVersion glslVersion, deUint32 layoutFlags, BufferMode bufferMode,
403 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
404 , m_layoutFlags(layoutFlags)
405 , m_numInstances(numInstances)
411 StructType& typeS = m_interface.allocStruct("S");
412 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
413 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
414 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
416 StructType& typeT = m_interface.allocStruct("T");
417 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
418 typeT.addMember("b", VarType(&typeS));
420 UniformBlock& block = m_interface.allocBlock("Block");
421 block.addUniform(Uniform("s", VarType(&typeS), 0));
422 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
423 block.addUniform(Uniform("t", VarType(&typeT), 0));
424 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
425 block.setFlags(m_layoutFlags);
427 if (m_numInstances > 0)
429 block.setInstanceName("block");
430 block.setArraySize(m_numInstances);
435 deUint32 m_layoutFlags;
439 class BlockSingleNestedStructArrayCase : public UniformBlockCase
442 BlockSingleNestedStructArrayCase(Context& context, const char* name, const char* description,
443 glu::GLSLVersion glslVersion, deUint32 layoutFlags, BufferMode bufferMode,
445 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
446 , m_layoutFlags(layoutFlags)
447 , m_numInstances(numInstances)
453 StructType& typeS = m_interface.allocStruct("S");
454 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
455 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
456 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
458 StructType& typeT = m_interface.allocStruct("T");
459 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
460 typeT.addMember("b", VarType(VarType(&typeS), 3));
462 UniformBlock& block = m_interface.allocBlock("Block");
463 block.addUniform(Uniform("s", VarType(&typeS), 0));
464 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
465 block.addUniform(Uniform("t", VarType(VarType(&typeT), 2), 0));
466 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
467 block.setFlags(m_layoutFlags);
469 if (m_numInstances > 0)
471 block.setInstanceName("block");
472 block.setArraySize(m_numInstances);
477 deUint32 m_layoutFlags;
481 class BlockMultiBasicTypesCase : public UniformBlockCase
484 BlockMultiBasicTypesCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
485 deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances)
486 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
489 , m_numInstances(numInstances)
495 UniformBlock& blockA = m_interface.allocBlock("BlockA");
496 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
497 blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
498 blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
499 blockA.setInstanceName("blockA");
500 blockA.setFlags(m_flagsA);
502 UniformBlock& blockB = m_interface.allocBlock("BlockB");
503 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
504 blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
505 blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
506 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
507 blockB.setInstanceName("blockB");
508 blockB.setFlags(m_flagsB);
510 if (m_numInstances > 0)
512 blockA.setArraySize(m_numInstances);
513 blockB.setArraySize(m_numInstances);
523 class BlockMultiNestedStructCase : public UniformBlockCase
526 BlockMultiNestedStructCase(Context& context, const char* name, const char* description,
527 glu::GLSLVersion glslVersion, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode,
529 : UniformBlockCase(context, name, description, glslVersion, bufferMode)
532 , m_numInstances(numInstances)
538 StructType& typeS = m_interface.allocStruct("S");
539 typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_LOW));
540 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
541 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
543 StructType& typeT = m_interface.allocStruct("T");
544 typeT.addMember("a", VarType(glu::TYPE_UINT, PRECISION_MEDIUM), UNUSED_BOTH);
545 typeT.addMember("b", VarType(&typeS));
546 typeT.addMember("c", VarType(glu::TYPE_BOOL_VEC4, 0));
548 UniformBlock& blockA = m_interface.allocBlock("BlockA");
549 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
550 blockA.addUniform(Uniform("b", VarType(&typeS)));
551 blockA.addUniform(Uniform("c", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
552 blockA.setInstanceName("blockA");
553 blockA.setFlags(m_flagsA);
555 UniformBlock& blockB = m_interface.allocBlock("BlockB");
556 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
557 blockB.addUniform(Uniform("b", VarType(&typeT)));
558 blockB.addUniform(Uniform("c", VarType(glu::TYPE_BOOL_VEC4, 0), UNUSED_BOTH));
559 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
560 blockB.setInstanceName("blockB");
561 blockB.setFlags(m_flagsB);
563 if (m_numInstances > 0)
565 blockA.setArraySize(m_numInstances);
566 blockB.setArraySize(m_numInstances);
576 UniformBlockTests::UniformBlockTests(Context& context, glu::GLSLVersion glslVersion)
577 : TestCaseGroup(context, "uniform_block", "Uniform Block tests"), m_glslVersion(glslVersion)
581 UniformBlockTests::~UniformBlockTests(void)
585 void UniformBlockTests::init(void)
587 static const glu::DataType basicTypes[] = { glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3,
588 glu::TYPE_FLOAT_VEC4, glu::TYPE_INT, glu::TYPE_INT_VEC2,
589 glu::TYPE_INT_VEC3, glu::TYPE_INT_VEC4, glu::TYPE_UINT,
590 glu::TYPE_UINT_VEC2, glu::TYPE_UINT_VEC3, glu::TYPE_UINT_VEC4,
591 glu::TYPE_BOOL, glu::TYPE_BOOL_VEC2, glu::TYPE_BOOL_VEC3,
592 glu::TYPE_BOOL_VEC4, glu::TYPE_FLOAT_MAT2, glu::TYPE_FLOAT_MAT3,
593 glu::TYPE_FLOAT_MAT4, glu::TYPE_FLOAT_MAT2X3, glu::TYPE_FLOAT_MAT2X4,
594 glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2,
595 glu::TYPE_FLOAT_MAT4X3 };
601 } precisionFlags[] = { { "lowp", PRECISION_LOW }, { "mediump", PRECISION_MEDIUM }, { "highp", PRECISION_HIGH } };
607 } layoutFlags[] = { { "shared", LAYOUT_SHARED }, { "packed", LAYOUT_PACKED }, { "std140", LAYOUT_STD140 } };
613 } matrixFlags[] = { { "row_major", LAYOUT_ROW_MAJOR }, { "column_major", LAYOUT_COLUMN_MAJOR } };
618 UniformBlockCase::BufferMode mode;
619 } bufferModes[] = { { "per_block_buffer", UniformBlockCase::BUFFERMODE_PER_BLOCK },
620 { "single_buffer", UniformBlockCase::BUFFERMODE_SINGLE } };
622 // ubo.single_basic_type
624 tcu::TestCaseGroup* singleBasicTypeGroup =
625 new tcu::TestCaseGroup(m_testCtx, "single_basic_type", "Single basic variable in single buffer");
626 addChild(singleBasicTypeGroup);
628 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
630 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
631 singleBasicTypeGroup->addChild(layoutGroup);
633 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
635 glu::DataType type = basicTypes[basicTypeNdx];
636 const char* typeName = glu::getDataTypeName(type);
637 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
638 deUint32 flags = baseFlags | ((baseFlags & LAYOUT_PACKED) ?
639 (basicTypeNdx % 2 == 0 ? DECLARE_VERTEX : DECLARE_FRAGMENT) :
642 if (glu::isDataTypeBoolOrBVec(type))
643 layoutGroup->addChild(new BlockBasicTypeCase(m_context, typeName, "", m_glslVersion,
644 VarType(type, 0), flags, 0 /* no instance array */));
647 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
648 layoutGroup->addChild(new BlockBasicTypeCase(
649 m_context, (string(precisionFlags[precNdx].name) + "_" + typeName).c_str(), "",
650 m_glslVersion, VarType(type, precisionFlags[precNdx].flags), flags,
651 0 /* no instance array */));
654 if (glu::isDataTypeMatrix(type))
656 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
658 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
659 layoutGroup->addChild(new BlockBasicTypeCase(
661 (string(matrixFlags[matFlagNdx].name) + "_" + precisionFlags[precNdx].name + "_" +
664 "", m_glslVersion, VarType(type, precisionFlags[precNdx].flags),
665 flags | matrixFlags[matFlagNdx].flags, 0 /* no instance array */));
672 // ubo.single_basic_array
674 tcu::TestCaseGroup* singleBasicArrayGroup =
675 new tcu::TestCaseGroup(m_testCtx, "single_basic_array", "Single basic array variable in single buffer");
676 addChild(singleBasicArrayGroup);
678 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
680 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
681 singleBasicArrayGroup->addChild(layoutGroup);
683 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
685 glu::DataType type = basicTypes[basicTypeNdx];
686 const char* typeName = glu::getDataTypeName(type);
687 const int arraySize = 3;
688 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
689 deUint32 flags = baseFlags | ((baseFlags & LAYOUT_PACKED) ?
690 (basicTypeNdx % 2 == 0 ? DECLARE_VERTEX : DECLARE_FRAGMENT) :
693 layoutGroup->addChild(new BlockBasicTypeCase(
694 m_context, typeName, "", m_glslVersion,
695 VarType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), arraySize), flags,
696 0 /* no instance array */));
698 if (glu::isDataTypeMatrix(type))
700 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
701 layoutGroup->addChild(new BlockBasicTypeCase(
702 m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
703 m_glslVersion, VarType(VarType(type, PRECISION_HIGH), arraySize),
704 flags | matrixFlags[matFlagNdx].flags, 0 /* no instance array */));
712 tcu::TestCaseGroup* singleStructGroup =
713 new tcu::TestCaseGroup(m_testCtx, "single_struct", "Single struct in uniform block");
714 addChild(singleStructGroup);
716 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
718 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
720 for (int isArray = 0; isArray < 2; isArray++)
722 std::string name = std::string(bufferModes[modeNdx].name) + "_" + layoutFlags[layoutFlagNdx].name;
723 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
724 deUint32 flags = baseFlags | ((baseFlags & LAYOUT_PACKED) ? DECLARE_VERTEX : DECLARE_BOTH);
726 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
727 continue; // Doesn't make sense to add this variant.
730 name += "_instance_array";
732 singleStructGroup->addChild(new BlockSingleStructCase(
733 m_context, name.c_str(), "", m_glslVersion, flags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
739 // ubo.single_struct_array
741 tcu::TestCaseGroup* singleStructArrayGroup =
742 new tcu::TestCaseGroup(m_testCtx, "single_struct_array", "Struct array in one uniform block");
743 addChild(singleStructArrayGroup);
745 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
747 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
749 for (int isArray = 0; isArray < 2; isArray++)
751 std::string name = std::string(bufferModes[modeNdx].name) + "_" + layoutFlags[layoutFlagNdx].name;
752 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
753 deUint32 flags = baseFlags | ((baseFlags & LAYOUT_PACKED) ? DECLARE_FRAGMENT : DECLARE_BOTH);
755 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
756 continue; // Doesn't make sense to add this variant.
759 name += "_instance_array";
761 singleStructArrayGroup->addChild(new BlockSingleStructArrayCase(
762 m_context, name.c_str(), "", m_glslVersion, flags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
768 // ubo.single_nested_struct
770 tcu::TestCaseGroup* singleNestedStructGroup =
771 new tcu::TestCaseGroup(m_testCtx, "single_nested_struct", "Nested struct in one uniform block");
772 addChild(singleNestedStructGroup);
774 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
776 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
778 for (int isArray = 0; isArray < 2; isArray++)
780 std::string name = std::string(bufferModes[modeNdx].name) + "_" + layoutFlags[layoutFlagNdx].name;
781 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
782 deUint32 flags = baseFlags | ((baseFlags & LAYOUT_PACKED) ? DECLARE_VERTEX : DECLARE_BOTH);
784 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
785 continue; // Doesn't make sense to add this variant.
788 name += "_instance_array";
790 singleNestedStructGroup->addChild(new BlockSingleNestedStructCase(
791 m_context, name.c_str(), "", m_glslVersion, flags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
797 // ubo.single_nested_struct_array
799 tcu::TestCaseGroup* singleNestedStructArrayGroup =
800 new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array", "Nested struct array in one uniform block");
801 addChild(singleNestedStructArrayGroup);
803 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
805 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
807 for (int isArray = 0; isArray < 2; isArray++)
809 std::string name = std::string(bufferModes[modeNdx].name) + "_" + layoutFlags[layoutFlagNdx].name;
810 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
811 deUint32 flags = baseFlags | ((baseFlags & LAYOUT_PACKED) ? DECLARE_FRAGMENT : DECLARE_BOTH);
813 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
814 continue; // Doesn't make sense to add this variant.
817 name += "_instance_array";
819 singleNestedStructArrayGroup->addChild(new BlockSingleNestedStructArrayCase(
820 m_context, name.c_str(), "", m_glslVersion, flags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
826 // ubo.instance_array_basic_type
828 tcu::TestCaseGroup* instanceArrayBasicTypeGroup =
829 new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type", "Single basic variable in instance array");
830 addChild(instanceArrayBasicTypeGroup);
832 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
834 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
835 instanceArrayBasicTypeGroup->addChild(layoutGroup);
837 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
839 glu::DataType type = basicTypes[basicTypeNdx];
840 const char* typeName = glu::getDataTypeName(type);
841 const int numInstances = 3;
842 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
843 deUint32 flags = baseFlags | ((baseFlags & LAYOUT_PACKED) ?
844 (basicTypeNdx % 2 == 0 ? DECLARE_VERTEX : DECLARE_FRAGMENT) :
847 layoutGroup->addChild(new BlockBasicTypeCase(
848 m_context, typeName, "", m_glslVersion,
849 VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), flags, numInstances));
851 if (glu::isDataTypeMatrix(type))
853 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
854 layoutGroup->addChild(new BlockBasicTypeCase(
855 m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
856 m_glslVersion, VarType(type, PRECISION_HIGH), flags | matrixFlags[matFlagNdx].flags,
863 // ubo.multi_basic_types
865 tcu::TestCaseGroup* multiBasicTypesGroup =
866 new tcu::TestCaseGroup(m_testCtx, "multi_basic_types", "Multiple buffers with basic types");
867 addChild(multiBasicTypesGroup);
869 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
871 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
872 multiBasicTypesGroup->addChild(modeGroup);
874 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
876 for (int isArray = 0; isArray < 2; isArray++)
878 std::string baseName = layoutFlags[layoutFlagNdx].name;
879 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
882 baseName += "_instance_array";
884 modeGroup->addChild(new BlockMultiBasicTypesCase(
885 m_context, (baseName + "_mixed").c_str(), "", m_glslVersion, baseFlags | DECLARE_VERTEX,
886 baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
888 if (!(baseFlags & LAYOUT_PACKED))
889 modeGroup->addChild(new BlockMultiBasicTypesCase(
890 m_context, (baseName + "_both").c_str(), "", m_glslVersion,
891 baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
892 baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
898 // ubo.multi_nested_struct
900 tcu::TestCaseGroup* multiNestedStructGroup =
901 new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct", "Multiple buffers with nested structs");
902 addChild(multiNestedStructGroup);
904 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
906 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
907 multiNestedStructGroup->addChild(modeGroup);
909 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
911 for (int isArray = 0; isArray < 2; isArray++)
913 std::string baseName = layoutFlags[layoutFlagNdx].name;
914 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
917 baseName += "_instance_array";
919 modeGroup->addChild(new BlockMultiNestedStructCase(
920 m_context, (baseName + "_mixed").c_str(), "", m_glslVersion, baseFlags | DECLARE_VERTEX,
921 baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
923 if (!(baseFlags & LAYOUT_PACKED))
924 modeGroup->addChild(new BlockMultiNestedStructCase(
925 m_context, (baseName + "_both").c_str(), "", m_glslVersion,
926 baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
927 baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
935 const deUint32 allShaders = FEATURE_VERTEX_BLOCKS | FEATURE_FRAGMENT_BLOCKS | FEATURE_SHARED_BLOCKS;
936 const deUint32 allLayouts = FEATURE_PACKED_LAYOUT | FEATURE_SHARED_LAYOUT | FEATURE_STD140_LAYOUT;
937 const deUint32 allBasicTypes = FEATURE_VECTORS | FEATURE_MATRICES;
938 const deUint32 unused = FEATURE_UNUSED_MEMBERS | FEATURE_UNUSED_UNIFORMS;
939 const deUint32 matFlags = FEATURE_MATRIX_LAYOUT;
941 tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
942 addChild(randomGroup);
945 createRandomCaseGroup(randomGroup, m_context, "scalar_types", "Scalar types only, per-block buffers",
946 m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders | allLayouts | unused,
948 createRandomCaseGroup(randomGroup, m_context, "vector_types", "Scalar and vector types only, per-block buffers",
949 m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK,
950 allShaders | allLayouts | unused | FEATURE_VECTORS, 10, 25);
951 createRandomCaseGroup(randomGroup, m_context, "basic_types", "All basic types, per-block buffers",
952 m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK,
953 allShaders | allLayouts | unused | allBasicTypes | matFlags, 10, 50);
954 createRandomCaseGroup(randomGroup, m_context, "basic_arrays", "Arrays, per-block buffers", m_glslVersion,
955 UniformBlockCase::BUFFERMODE_PER_BLOCK,
956 allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_ARRAYS, 10, 50);
958 createRandomCaseGroup(
959 randomGroup, m_context, "basic_instance_arrays", "Basic instance arrays, per-block buffers", m_glslVersion,
960 UniformBlockCase::BUFFERMODE_PER_BLOCK,
961 allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_INSTANCE_ARRAYS, 10, 75);
962 createRandomCaseGroup(randomGroup, m_context, "nested_structs", "Nested structs, per-block buffers",
963 m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK,
964 allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_STRUCTS, 10, 100);
965 createRandomCaseGroup(
966 randomGroup, m_context, "nested_structs_arrays", "Nested structs, arrays, per-block buffers", m_glslVersion,
967 UniformBlockCase::BUFFERMODE_PER_BLOCK,
968 allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_STRUCTS | FEATURE_ARRAYS, 10, 150);
969 createRandomCaseGroup(
970 randomGroup, m_context, "nested_structs_instance_arrays",
971 "Nested structs, instance arrays, per-block buffers", m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK,
972 allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_STRUCTS | FEATURE_INSTANCE_ARRAYS, 10,
974 createRandomCaseGroup(randomGroup, m_context, "nested_structs_arrays_instance_arrays",
975 "Nested structs, instance arrays, per-block buffers", m_glslVersion,
976 UniformBlockCase::BUFFERMODE_PER_BLOCK,
977 allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_STRUCTS |
978 FEATURE_ARRAYS | FEATURE_INSTANCE_ARRAYS,
981 createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers", "All random features, per-block buffers",
982 m_glslVersion, UniformBlockCase::BUFFERMODE_PER_BLOCK, ~0u, 20, 200);
983 createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer", "All random features, shared buffer",
984 m_glslVersion, UniformBlockCase::BUFFERMODE_SINGLE, ~0u, 20, 250);