1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Uniform block tests.
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktUniformBlockTests.hpp"
27
28 #include "vktUniformBlockCase.hpp"
29 #include "vktRandomUniformBlockCase.hpp"
30
31 #include "tcuCommandLine.hpp"
32 #include "deStringUtil.hpp"
33
34 namespace vkt
35 {
36 namespace ubo
37 {
38
39 namespace
40 {
41
42 class BlockBasicTypeCase : public UniformBlockCase
43 {
44 public:
BlockBasicTypeCase(tcu::TestContext & testCtx,const std::string & name,const VarType & type,uint32_t layoutFlags,int numInstances,MatrixLoadFlags matrixLoadFlag)45 BlockBasicTypeCase(tcu::TestContext &testCtx, const std::string &name, const VarType &type, uint32_t layoutFlags,
46 int numInstances, MatrixLoadFlags matrixLoadFlag)
47 : UniformBlockCase(testCtx, name, BUFFERMODE_PER_BLOCK, matrixLoadFlag)
48 {
49 VarType tempType = type;
50 while (tempType.isArrayType())
51 {
52 tempType = tempType.getElementType();
53 }
54 if (getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_UINT16 ||
55 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_INT16 ||
56 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_FLOAT16)
57 {
58 layoutFlags |= LAYOUT_16BIT_STORAGE;
59 }
60 if (getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_UINT8 ||
61 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_INT8)
62 {
63 layoutFlags |= LAYOUT_8BIT_STORAGE;
64 }
65
66 UniformBlock &block = m_interface.allocBlock("Block");
67 // For scalar layout tests with non-scalar types, add a scalar padding variable
68 // before "var", to make var only be scalar aligned.
69 if ((layoutFlags & LAYOUT_SCALAR) && !isDataTypeScalar(type.getBasicType()))
70 {
71 block.addUniform(Uniform("padding", VarType(getDataTypeScalarType(tempType.getBasicType()), 0), 0));
72 }
73 block.addUniform(Uniform("var", type, 0));
74
75 block.setFlags(layoutFlags);
76
77 if (numInstances > 0)
78 {
79 block.setArraySize(numInstances);
80 block.setInstanceName("block");
81 }
82 }
83 };
84
createBlockBasicTypeCases(tcu::TestCaseGroup & group,tcu::TestContext & testCtx,const std::string & name,const VarType & type,uint32_t layoutFlags,int numInstances=0)85 void createBlockBasicTypeCases(tcu::TestCaseGroup &group, tcu::TestContext &testCtx, const std::string &name,
86 const VarType &type, uint32_t layoutFlags, int numInstances = 0)
87 {
88 de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(group.getTestContext(), name.c_str()));
89
90 typeGroup->addChild(
91 new BlockBasicTypeCase(testCtx, "vertex", type, layoutFlags | DECLARE_VERTEX, numInstances, LOAD_FULL_MATRIX));
92 typeGroup->addChild(new BlockBasicTypeCase(testCtx, "fragment", type, layoutFlags | DECLARE_FRAGMENT, numInstances,
93 LOAD_FULL_MATRIX));
94 typeGroup->addChild(new BlockBasicTypeCase(testCtx, "both", type, layoutFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
95 numInstances, LOAD_FULL_MATRIX));
96 typeGroup->addChild(new BlockBasicTypeCase(testCtx, "vertex_comp_access", type, layoutFlags | DECLARE_VERTEX,
97 numInstances, LOAD_MATRIX_COMPONENTS));
98 typeGroup->addChild(new BlockBasicTypeCase(testCtx, "fragment_comp_access", type, layoutFlags | DECLARE_FRAGMENT,
99 numInstances, LOAD_MATRIX_COMPONENTS));
100 typeGroup->addChild(new BlockBasicTypeCase(testCtx, "both_comp_access", type,
101 layoutFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, numInstances,
102 LOAD_MATRIX_COMPONENTS));
103
104 group.addChild(typeGroup.release());
105 }
106
107 class BlockSingleStructCase : public UniformBlockCase
108 {
109 public:
BlockSingleStructCase(tcu::TestContext & testCtx,const std::string & name,uint32_t layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)110 BlockSingleStructCase(tcu::TestContext &testCtx, const std::string &name, uint32_t layoutFlags,
111 BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
112 : UniformBlockCase(testCtx, name, bufferMode, matrixLoadFlag)
113 {
114 StructType &typeS = m_interface.allocStruct("S");
115 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH); // First member is unused.
116 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
117 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
118
119 UniformBlock &block = m_interface.allocBlock("Block");
120 block.addUniform(Uniform("s", VarType(&typeS), 0));
121 block.setFlags(layoutFlags);
122
123 if (numInstances > 0)
124 {
125 block.setInstanceName("block");
126 block.setArraySize(numInstances);
127 }
128 }
129 };
130
131 class BlockSingleStructArrayCase : public UniformBlockCase
132 {
133 public:
BlockSingleStructArrayCase(tcu::TestContext & testCtx,const std::string & name,uint32_t layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)134 BlockSingleStructArrayCase(tcu::TestContext &testCtx, const std::string &name, uint32_t layoutFlags,
135 BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
136 : UniformBlockCase(testCtx, name, bufferMode, matrixLoadFlag)
137 {
138 StructType &typeS = m_interface.allocStruct("S");
139 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
140 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
141 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
142
143 UniformBlock &block = m_interface.allocBlock("Block");
144 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_LOW)));
145 block.addUniform(Uniform("s", VarType(VarType(&typeS), 3)));
146 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_MEDIUM)));
147 block.setFlags(layoutFlags);
148
149 if (numInstances > 0)
150 {
151 block.setInstanceName("block");
152 block.setArraySize(numInstances);
153 }
154 }
155 };
156
157 class BlockSingleNestedStructCase : public UniformBlockCase
158 {
159 public:
BlockSingleNestedStructCase(tcu::TestContext & testCtx,const std::string & name,uint32_t layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)160 BlockSingleNestedStructCase(tcu::TestContext &testCtx, const std::string &name, uint32_t layoutFlags,
161 BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
162 : UniformBlockCase(testCtx, name, bufferMode, matrixLoadFlag)
163 {
164 StructType &typeS = m_interface.allocStruct("S");
165 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
166 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
167 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
168
169 StructType &typeT = m_interface.allocStruct("T");
170 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
171 typeT.addMember("b", VarType(&typeS));
172
173 UniformBlock &block = m_interface.allocBlock("Block");
174 block.addUniform(Uniform("s", VarType(&typeS), 0));
175 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
176 block.addUniform(Uniform("t", VarType(&typeT), 0));
177 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
178 block.setFlags(layoutFlags);
179
180 if (numInstances > 0)
181 {
182 block.setInstanceName("block");
183 block.setArraySize(numInstances);
184 }
185 }
186 };
187
188 class BlockSingleNestedStructArrayCase : public UniformBlockCase
189 {
190 public:
BlockSingleNestedStructArrayCase(tcu::TestContext & testCtx,const std::string & name,uint32_t layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)191 BlockSingleNestedStructArrayCase(tcu::TestContext &testCtx, const std::string &name, uint32_t layoutFlags,
192 BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
193 : UniformBlockCase(testCtx, name, bufferMode, matrixLoadFlag)
194 {
195 StructType &typeS = m_interface.allocStruct("S");
196 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
197 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
198 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
199
200 StructType &typeT = m_interface.allocStruct("T");
201 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
202 typeT.addMember("b", VarType(VarType(&typeS), 3));
203
204 UniformBlock &block = m_interface.allocBlock("Block");
205 block.addUniform(Uniform("s", VarType(&typeS), 0));
206 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
207 block.addUniform(Uniform("t", VarType(VarType(&typeT), 2), 0));
208 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
209 block.setFlags(layoutFlags);
210
211 if (numInstances > 0)
212 {
213 block.setInstanceName("block");
214 block.setArraySize(numInstances);
215 }
216 }
217 };
218
219 class BlockMultiBasicTypesCase : public UniformBlockCase
220 {
221 public:
BlockMultiBasicTypesCase(tcu::TestContext & testCtx,const std::string & name,uint32_t flagsA,uint32_t flagsB,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)222 BlockMultiBasicTypesCase(tcu::TestContext &testCtx, const std::string &name, uint32_t flagsA, uint32_t flagsB,
223 BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
224 : UniformBlockCase(testCtx, name, bufferMode, matrixLoadFlag)
225 {
226 UniformBlock &blockA = m_interface.allocBlock("BlockA");
227 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
228 blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
229 blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
230 blockA.setInstanceName("blockA");
231 blockA.setFlags(flagsA);
232
233 UniformBlock &blockB = m_interface.allocBlock("BlockB");
234 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
235 blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
236 blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
237 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
238 blockB.setInstanceName("blockB");
239 blockB.setFlags(flagsB);
240
241 if (numInstances > 0)
242 {
243 blockA.setArraySize(numInstances);
244 blockB.setArraySize(numInstances);
245 }
246 }
247 };
248
249 class BlockMultiNestedStructCase : public UniformBlockCase
250 {
251 public:
BlockMultiNestedStructCase(tcu::TestContext & testCtx,const std::string & name,uint32_t flagsA,uint32_t flagsB,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)252 BlockMultiNestedStructCase(tcu::TestContext &testCtx, const std::string &name, uint32_t flagsA, uint32_t flagsB,
253 BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
254 : UniformBlockCase(testCtx, name, bufferMode, matrixLoadFlag)
255 {
256 StructType &typeS = m_interface.allocStruct("S");
257 typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_LOW));
258 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
259 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
260
261 StructType &typeT = m_interface.allocStruct("T");
262 typeT.addMember("a", VarType(glu::TYPE_UINT, PRECISION_MEDIUM), UNUSED_BOTH);
263 typeT.addMember("b", VarType(&typeS));
264 typeT.addMember("c", VarType(glu::TYPE_BOOL_VEC4, 0));
265
266 UniformBlock &blockA = m_interface.allocBlock("BlockA");
267 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
268 blockA.addUniform(Uniform("b", VarType(&typeS)));
269 blockA.addUniform(Uniform("c", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
270 blockA.setInstanceName("blockA");
271 blockA.setFlags(flagsA);
272
273 UniformBlock &blockB = m_interface.allocBlock("BlockB");
274 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
275 blockB.addUniform(Uniform("b", VarType(&typeT)));
276 blockB.addUniform(Uniform("c", VarType(glu::TYPE_BOOL_VEC4, 0), UNUSED_BOTH));
277 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
278 blockB.setInstanceName("blockB");
279 blockB.setFlags(flagsB);
280
281 if (numInstances > 0)
282 {
283 blockA.setArraySize(numInstances);
284 blockB.setArraySize(numInstances);
285 }
286 }
287 };
288
289 class Block2LevelStructArrayCase : public UniformBlockCase
290 {
291 public:
Block2LevelStructArrayCase(tcu::TestContext & testCtx,const std::string & name,uint32_t layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)292 Block2LevelStructArrayCase(tcu::TestContext &testCtx, const std::string &name, uint32_t layoutFlags,
293 BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
294 : UniformBlockCase(testCtx, name, bufferMode, matrixLoadFlag)
295 , m_layoutFlags(layoutFlags)
296 , m_numInstances(numInstances)
297 {
298 StructType &typeS = m_interface.allocStruct("S");
299 typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
300 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 4));
301 typeS.addMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW));
302
303 UniformBlock &block = m_interface.allocBlock("Block");
304 block.addUniform(Uniform("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM)));
305 block.addUniform(Uniform("s", VarType(VarType(VarType(&typeS), 3), 2)));
306 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM)));
307 block.setFlags(m_layoutFlags);
308
309 if (m_numInstances > 0)
310 {
311 block.setInstanceName("block");
312 block.setArraySize(m_numInstances);
313 }
314 }
315
316 private:
317 uint32_t m_layoutFlags;
318 int m_numInstances;
319 };
320
321 class LinkByBindingCase : public UniformBlockCase
322 {
323 public:
LinkByBindingCase(tcu::TestContext & testCtx,const std::string & name,BufferMode bufferMode,int numInstances)324 LinkByBindingCase(tcu::TestContext &testCtx, const std::string &name, BufferMode bufferMode, int numInstances)
325 : UniformBlockCase(testCtx, name, bufferMode, LOAD_FULL_MATRIX)
326 {
327 UniformBlock &blockA = m_interface.allocBlock("TestBlock");
328 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
329 blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
330 blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
331 blockA.setFlags(LAYOUT_STD140 | DECLARE_VERTEX);
332
333 UniformBlock &blockB = m_interface.allocBlock("TestBlock");
334 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
335 blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
336 blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
337 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
338 blockB.setFlags(LAYOUT_STD140 | DECLARE_FRAGMENT);
339
340 if (numInstances > 0)
341 {
342 blockA.setInstanceName("testBlock");
343 blockA.setArraySize(numInstances);
344 blockB.setInstanceName("testBlock");
345 blockB.setArraySize(numInstances);
346 }
347 }
348 };
349
createRandomCaseGroup(tcu::TestCaseGroup * parentGroup,tcu::TestContext & testCtx,const char * groupName,UniformBlockCase::BufferMode bufferMode,uint32_t features,int numCases,uint32_t baseSeed)350 void createRandomCaseGroup(tcu::TestCaseGroup *parentGroup, tcu::TestContext &testCtx, const char *groupName,
351 UniformBlockCase::BufferMode bufferMode, uint32_t features, int numCases, uint32_t baseSeed)
352 {
353 tcu::TestCaseGroup *group = new tcu::TestCaseGroup(testCtx, groupName);
354 parentGroup->addChild(group);
355
356 baseSeed += (uint32_t)testCtx.getCommandLine().getBaseSeed();
357
358 for (int ndx = 0; ndx < numCases; ndx++)
359 group->addChild(
360 new RandomUniformBlockCase(testCtx, de::toString(ndx), bufferMode, features, (uint32_t)ndx + baseSeed));
361 }
362
363 // UniformBlockTests
364
365 class UniformBlockTests : public tcu::TestCaseGroup
366 {
367 public:
368 UniformBlockTests(tcu::TestContext &testCtx, const std::string &name);
369 ~UniformBlockTests(void);
370
371 void init(void);
372
373 private:
374 UniformBlockTests(const UniformBlockTests &other);
375 UniformBlockTests &operator=(const UniformBlockTests &other);
376 };
377
UniformBlockTests(tcu::TestContext & testCtx,const std::string & name)378 UniformBlockTests::UniformBlockTests(tcu::TestContext &testCtx, const std::string &name)
379 : TestCaseGroup(testCtx, name.c_str())
380 {
381 }
382
~UniformBlockTests(void)383 UniformBlockTests::~UniformBlockTests(void)
384 {
385 }
386
init(void)387 void UniformBlockTests::init(void)
388 {
389 static const glu::DataType basicTypes[] = {
390 glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC4,
391 glu::TYPE_INT, glu::TYPE_INT_VEC2, glu::TYPE_INT_VEC3, glu::TYPE_INT_VEC4,
392 glu::TYPE_UINT, glu::TYPE_UINT_VEC2, glu::TYPE_UINT_VEC3, glu::TYPE_UINT_VEC4,
393 glu::TYPE_BOOL, glu::TYPE_BOOL_VEC2, glu::TYPE_BOOL_VEC3, glu::TYPE_BOOL_VEC4,
394 glu::TYPE_FLOAT_MAT2, glu::TYPE_FLOAT_MAT3, glu::TYPE_FLOAT_MAT4, glu::TYPE_FLOAT_MAT2X3,
395 glu::TYPE_FLOAT_MAT2X4, glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2,
396 glu::TYPE_FLOAT_MAT4X3, glu::TYPE_UINT8, glu::TYPE_UINT8_VEC2, glu::TYPE_UINT8_VEC3,
397 glu::TYPE_UINT8_VEC4, glu::TYPE_INT8, glu::TYPE_INT8_VEC2, glu::TYPE_INT8_VEC3,
398 glu::TYPE_INT8_VEC4, glu::TYPE_UINT16, glu::TYPE_UINT16_VEC2, glu::TYPE_UINT16_VEC3,
399 glu::TYPE_UINT16_VEC4, glu::TYPE_INT16, glu::TYPE_INT16_VEC2, glu::TYPE_INT16_VEC3,
400 glu::TYPE_INT16_VEC4, glu::TYPE_FLOAT16, glu::TYPE_FLOAT16_VEC2, glu::TYPE_FLOAT16_VEC3,
401 glu::TYPE_FLOAT16_VEC4,
402 };
403
404 static const struct
405 {
406 const std::string name;
407 uint32_t flags;
408 } precisionFlags[] = {
409 // TODO remove PRECISION_LOW because both PRECISION_LOW and PRECISION_MEDIUM means relaxed precision?
410 {"lowp", PRECISION_LOW},
411 {"mediump", PRECISION_MEDIUM},
412 {"highp", PRECISION_HIGH}};
413
414 static const struct
415 {
416 const char *name;
417 uint32_t flags;
418 } layoutFlags[] = {{"std140", LAYOUT_STD140}, {"std430", LAYOUT_STD430}, {"scalar", LAYOUT_SCALAR}};
419
420 static const struct
421 {
422 const std::string name;
423 uint32_t flags;
424 } matrixFlags[] = {{"row_major", LAYOUT_ROW_MAJOR}, {"column_major", LAYOUT_COLUMN_MAJOR}};
425
426 static const struct
427 {
428 const char *name;
429 UniformBlockCase::BufferMode mode;
430 } bufferModes[] = {{"per_block_buffer", UniformBlockCase::BUFFERMODE_PER_BLOCK},
431 {"single_buffer", UniformBlockCase::BUFFERMODE_SINGLE}};
432
433 // ubo.2_level_array
434 {
435 tcu::TestCaseGroup *nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_array");
436 addChild(nestedArrayGroup);
437
438 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
439 {
440 de::MovePtr<tcu::TestCaseGroup> layoutGroup(
441 new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name));
442
443 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
444 {
445 const glu::DataType type = basicTypes[basicTypeNdx];
446 const char *const typeName = glu::getDataTypeName(type);
447 const int childSize = 4;
448 const int parentSize = 3;
449 const VarType childType(VarType(type, !dataTypeSupportsPrecisionModifier(type) ? 0 : PRECISION_HIGH),
450 childSize);
451 const VarType parentType(childType, parentSize);
452
453 createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName, parentType,
454 layoutFlags[layoutFlagNdx].flags);
455
456 if (glu::isDataTypeMatrix(type))
457 {
458 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
459 createBlockBasicTypeCases(
460 *layoutGroup, m_testCtx, (std::string(matrixFlags[matFlagNdx].name) + "_" + typeName),
461 parentType, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
462 }
463 }
464 nestedArrayGroup->addChild(layoutGroup.release());
465 }
466 }
467
468 // ubo.3_level_array
469 {
470 tcu::TestCaseGroup *nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "3_level_array");
471 addChild(nestedArrayGroup);
472
473 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
474 {
475 de::MovePtr<tcu::TestCaseGroup> layoutGroup(
476 new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name));
477
478 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
479 {
480 const glu::DataType type = basicTypes[basicTypeNdx];
481 const char *const typeName = glu::getDataTypeName(type);
482 const int childSize0 = 2;
483 const int childSize1 = 4;
484 const int parentSize = 3;
485 const VarType childType0(VarType(type, !dataTypeSupportsPrecisionModifier(type) ? 0 : PRECISION_HIGH),
486 childSize0);
487 const VarType childType1(childType0, childSize1);
488 const VarType parentType(childType1, parentSize);
489
490 createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName, parentType,
491 layoutFlags[layoutFlagNdx].flags);
492
493 if (glu::isDataTypeMatrix(type))
494 {
495 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
496 createBlockBasicTypeCases(
497 *layoutGroup, m_testCtx, (std::string(matrixFlags[matFlagNdx].name) + "_" + typeName),
498 parentType, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
499 }
500 }
501 nestedArrayGroup->addChild(layoutGroup.release());
502 }
503 }
504
505 // ubo.2_level_struct_array
506 {
507 tcu::TestCaseGroup *structArrayArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array");
508 addChild(structArrayArrayGroup);
509
510 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
511 {
512 tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name);
513 structArrayArrayGroup->addChild(modeGroup);
514
515 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
516 {
517 for (int isArray = 0; isArray < 2; isArray++)
518 {
519 std::string baseName = layoutFlags[layoutFlagNdx].name;
520 uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags;
521
522 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
523 continue; // Doesn't make sense to add this variant.
524
525 if (isArray)
526 baseName += "_instance_array";
527
528 modeGroup->addChild(
529 new Block2LevelStructArrayCase(m_testCtx, (baseName + "_vertex"), baseFlags | DECLARE_VERTEX,
530 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
531 modeGroup->addChild(new Block2LevelStructArrayCase(
532 m_testCtx, (baseName + "_fragment"), baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode,
533 isArray ? 3 : 0, LOAD_FULL_MATRIX));
534 modeGroup->addChild(new Block2LevelStructArrayCase(
535 m_testCtx, (baseName + "_both"), baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
536 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
537 modeGroup->addChild(new Block2LevelStructArrayCase(
538 m_testCtx, (baseName + "_vertex_comp_access"), baseFlags | DECLARE_VERTEX,
539 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
540 modeGroup->addChild(new Block2LevelStructArrayCase(
541 m_testCtx, (baseName + "_fragment_comp_access"), baseFlags | DECLARE_FRAGMENT,
542 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
543 modeGroup->addChild(new Block2LevelStructArrayCase(
544 m_testCtx, (baseName + "_both_comp_access"), baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
545 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
546 }
547 }
548 }
549 }
550
551 // ubo.single_basic_type
552 {
553 tcu::TestCaseGroup *singleBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_type");
554 addChild(singleBasicTypeGroup);
555
556 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
557 {
558 de::MovePtr<tcu::TestCaseGroup> layoutGroup(
559 new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name));
560
561 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
562 {
563 glu::DataType type = basicTypes[basicTypeNdx];
564 const char *const typeName = glu::getDataTypeName(type);
565
566 if (!dataTypeSupportsPrecisionModifier(type))
567 createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName, VarType(type, 0),
568 layoutFlags[layoutFlagNdx].flags);
569 }
570
571 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
572 {
573 de::MovePtr<tcu::TestCaseGroup> precGroup(
574 new tcu::TestCaseGroup(m_testCtx, precisionFlags[precNdx].name.c_str()));
575
576 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
577 {
578 glu::DataType type = basicTypes[basicTypeNdx];
579 const char *const typeName = glu::getDataTypeName(type);
580
581 if (dataTypeSupportsPrecisionModifier(type))
582 createBlockBasicTypeCases(*precGroup, m_testCtx, typeName,
583 VarType(type, precisionFlags[precNdx].flags),
584 layoutFlags[layoutFlagNdx].flags);
585
586 if (glu::isDataTypeMatrix(type))
587 {
588 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
589 {
590 createBlockBasicTypeCases(*precGroup, m_testCtx,
591 matrixFlags[matFlagNdx].name + "_" + typeName,
592 VarType(type, precisionFlags[precNdx].flags),
593 layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
594 }
595 }
596 }
597 layoutGroup->addChild(precGroup.release());
598 }
599 singleBasicTypeGroup->addChild(layoutGroup.release());
600 }
601 }
602
603 // ubo.single_basic_array
604 {
605 tcu::TestCaseGroup *singleBasicArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_array");
606 addChild(singleBasicArrayGroup);
607
608 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
609 {
610 de::MovePtr<tcu::TestCaseGroup> layoutGroup(
611 new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name));
612
613 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
614 {
615 glu::DataType type = basicTypes[basicTypeNdx];
616 const char *const typeName = glu::getDataTypeName(type);
617 const int arraySize = 3;
618
619 createBlockBasicTypeCases(
620 *layoutGroup, m_testCtx, typeName,
621 VarType(VarType(type, !dataTypeSupportsPrecisionModifier(type) ? 0 : PRECISION_HIGH), arraySize),
622 layoutFlags[layoutFlagNdx].flags);
623
624 if (glu::isDataTypeMatrix(type))
625 {
626 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
627 createBlockBasicTypeCases(*layoutGroup, m_testCtx,
628 matrixFlags[matFlagNdx].name + "_" + typeName,
629 VarType(VarType(type, PRECISION_HIGH), arraySize),
630 layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
631 }
632 }
633 singleBasicArrayGroup->addChild(layoutGroup.release());
634 }
635 }
636
637 // ubo.single_struct
638 {
639 tcu::TestCaseGroup *singleStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct");
640 addChild(singleStructGroup);
641
642 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
643 {
644 tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name);
645 singleStructGroup->addChild(modeGroup);
646
647 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
648 {
649 for (int isArray = 0; isArray < 2; isArray++)
650 {
651 std::string baseName = layoutFlags[layoutFlagNdx].name;
652 uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags;
653
654 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
655 continue; // Doesn't make sense to add this variant.
656
657 if (isArray)
658 baseName += "_instance_array";
659
660 modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_vertex",
661 baseFlags | DECLARE_VERTEX, bufferModes[modeNdx].mode,
662 isArray ? 3 : 0, LOAD_FULL_MATRIX));
663 modeGroup->addChild(
664 new BlockSingleStructCase(m_testCtx, baseName + "_fragment", baseFlags | DECLARE_FRAGMENT,
665 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
666 modeGroup->addChild(new BlockSingleStructCase(
667 m_testCtx, baseName + "_both", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
668 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
669 modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_vertex_comp_access",
670 baseFlags | DECLARE_VERTEX, bufferModes[modeNdx].mode,
671 isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
672 modeGroup->addChild(new BlockSingleStructCase(
673 m_testCtx, baseName + "_fragment_comp_access", baseFlags | DECLARE_FRAGMENT,
674 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
675 modeGroup->addChild(new BlockSingleStructCase(
676 m_testCtx, baseName + "_both_comp_access", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
677 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
678 }
679 }
680 }
681 }
682
683 // ubo.single_struct_array
684 {
685 tcu::TestCaseGroup *singleStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct_array");
686 addChild(singleStructArrayGroup);
687
688 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
689 {
690 tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name);
691 singleStructArrayGroup->addChild(modeGroup);
692
693 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
694 {
695 for (int isArray = 0; isArray < 2; isArray++)
696 {
697 std::string baseName = layoutFlags[layoutFlagNdx].name;
698 uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags;
699
700 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
701 continue; // Doesn't make sense to add this variant.
702
703 if (isArray)
704 baseName += "_instance_array";
705
706 modeGroup->addChild(
707 new BlockSingleStructArrayCase(m_testCtx, baseName + "_vertex", baseFlags | DECLARE_VERTEX,
708 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
709 modeGroup->addChild(
710 new BlockSingleStructArrayCase(m_testCtx, baseName + "_fragment", baseFlags | DECLARE_FRAGMENT,
711 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
712 modeGroup->addChild(new BlockSingleStructArrayCase(
713 m_testCtx, baseName + "_both", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
714 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
715 modeGroup->addChild(new BlockSingleStructArrayCase(
716 m_testCtx, baseName + "_vertex_comp_access", baseFlags | DECLARE_VERTEX,
717 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
718 modeGroup->addChild(new BlockSingleStructArrayCase(
719 m_testCtx, baseName + "_fragment_comp_access", baseFlags | DECLARE_FRAGMENT,
720 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
721 modeGroup->addChild(new BlockSingleStructArrayCase(
722 m_testCtx, baseName + "_both_comp_access", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
723 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
724 }
725 }
726 }
727 }
728
729 // ubo.single_nested_struct
730 {
731 tcu::TestCaseGroup *singleNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct");
732 addChild(singleNestedStructGroup);
733
734 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
735 {
736 tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name);
737 singleNestedStructGroup->addChild(modeGroup);
738
739 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
740 {
741 for (int isArray = 0; isArray < 2; isArray++)
742 {
743 std::string baseName = layoutFlags[layoutFlagNdx].name;
744 uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags;
745
746 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
747 continue; // Doesn't make sense to add this variant.
748
749 if (isArray)
750 baseName += "_instance_array";
751
752 modeGroup->addChild(
753 new BlockSingleNestedStructCase(m_testCtx, baseName + "_vertex", baseFlags | DECLARE_VERTEX,
754 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
755 modeGroup->addChild(
756 new BlockSingleNestedStructCase(m_testCtx, baseName + "_fragment", baseFlags | DECLARE_FRAGMENT,
757 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
758 modeGroup->addChild(new BlockSingleNestedStructCase(
759 m_testCtx, baseName + "_both", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
760 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
761 modeGroup->addChild(new BlockSingleNestedStructCase(
762 m_testCtx, baseName + "_vertex_comp_access", baseFlags | DECLARE_VERTEX,
763 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
764 modeGroup->addChild(new BlockSingleNestedStructCase(
765 m_testCtx, baseName + "_fragment_comp_access", baseFlags | DECLARE_FRAGMENT,
766 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
767 modeGroup->addChild(new BlockSingleNestedStructCase(
768 m_testCtx, baseName + "_both_comp_access", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
769 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
770 }
771 }
772 }
773 }
774
775 // ubo.single_nested_struct_array
776 {
777 tcu::TestCaseGroup *singleNestedStructArrayGroup =
778 new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array");
779 addChild(singleNestedStructArrayGroup);
780
781 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
782 {
783 tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name);
784 singleNestedStructArrayGroup->addChild(modeGroup);
785
786 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
787 {
788 for (int isArray = 0; isArray < 2; isArray++)
789 {
790 std::string baseName = layoutFlags[layoutFlagNdx].name;
791 uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags;
792
793 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
794 continue; // Doesn't make sense to add this variant.
795
796 if (isArray)
797 baseName += "_instance_array";
798
799 modeGroup->addChild(new BlockSingleNestedStructArrayCase(
800 m_testCtx, baseName + "_vertex", baseFlags | DECLARE_VERTEX, bufferModes[modeNdx].mode,
801 isArray ? 3 : 0, LOAD_FULL_MATRIX));
802 modeGroup->addChild(new BlockSingleNestedStructArrayCase(
803 m_testCtx, baseName + "_fragment", baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode,
804 isArray ? 3 : 0, LOAD_FULL_MATRIX));
805 modeGroup->addChild(new BlockSingleNestedStructArrayCase(
806 m_testCtx, baseName + "_both", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
807 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
808 modeGroup->addChild(new BlockSingleNestedStructArrayCase(
809 m_testCtx, baseName + "_vertex_comp_access", baseFlags | DECLARE_VERTEX,
810 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
811 modeGroup->addChild(new BlockSingleNestedStructArrayCase(
812 m_testCtx, baseName + "_fragment_comp_access", baseFlags | DECLARE_FRAGMENT,
813 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
814 modeGroup->addChild(new BlockSingleNestedStructArrayCase(
815 m_testCtx, baseName + "_both_comp_access", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
816 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
817 }
818 }
819 }
820 }
821
822 // ubo.instance_array_basic_type
823 {
824 tcu::TestCaseGroup *instanceArrayBasicTypeGroup =
825 new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type");
826 addChild(instanceArrayBasicTypeGroup);
827
828 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
829 {
830 de::MovePtr<tcu::TestCaseGroup> layoutGroup(
831 new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name));
832
833 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
834 {
835 glu::DataType type = basicTypes[basicTypeNdx];
836 const char *const typeName = glu::getDataTypeName(type);
837 const int numInstances = 3;
838
839 createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName,
840 VarType(type, !dataTypeSupportsPrecisionModifier(type) ? 0 : PRECISION_HIGH),
841 layoutFlags[layoutFlagNdx].flags, numInstances);
842
843 if (glu::isDataTypeMatrix(type))
844 {
845 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
846 createBlockBasicTypeCases(
847 *layoutGroup, m_testCtx, matrixFlags[matFlagNdx].name + "_" + typeName,
848 VarType(type, PRECISION_HIGH),
849 layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags, numInstances);
850 }
851 }
852 instanceArrayBasicTypeGroup->addChild(layoutGroup.release());
853 }
854 }
855
856 // ubo.multi_basic_types
857 {
858 tcu::TestCaseGroup *multiBasicTypesGroup = new tcu::TestCaseGroup(m_testCtx, "multi_basic_types");
859 addChild(multiBasicTypesGroup);
860
861 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
862 {
863 tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name);
864 multiBasicTypesGroup->addChild(modeGroup);
865
866 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
867 {
868 for (int isArray = 0; isArray < 2; isArray++)
869 {
870 std::string baseName = layoutFlags[layoutFlagNdx].name;
871 uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags;
872
873 if (isArray)
874 baseName += "_instance_array";
875
876 modeGroup->addChild(new BlockMultiBasicTypesCase(
877 m_testCtx, baseName + "_vertex", baseFlags | DECLARE_VERTEX, baseFlags | DECLARE_VERTEX,
878 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
879 modeGroup->addChild(new BlockMultiBasicTypesCase(
880 m_testCtx, baseName + "_fragment", baseFlags | DECLARE_FRAGMENT, baseFlags | DECLARE_FRAGMENT,
881 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
882 modeGroup->addChild(new BlockMultiBasicTypesCase(
883 m_testCtx, baseName + "_both", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
884 baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0,
885 LOAD_FULL_MATRIX));
886 modeGroup->addChild(new BlockMultiBasicTypesCase(
887 m_testCtx, baseName + "_mixed", baseFlags | DECLARE_VERTEX, baseFlags | DECLARE_FRAGMENT,
888 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
889 modeGroup->addChild(new BlockMultiBasicTypesCase(
890 m_testCtx, baseName + "_vertex_comp_access", baseFlags | DECLARE_VERTEX,
891 baseFlags | DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0,
892 LOAD_MATRIX_COMPONENTS));
893 modeGroup->addChild(new BlockMultiBasicTypesCase(
894 m_testCtx, baseName + "_fragment_comp_access", baseFlags | DECLARE_FRAGMENT,
895 baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0,
896 LOAD_MATRIX_COMPONENTS));
897 modeGroup->addChild(new BlockMultiBasicTypesCase(
898 m_testCtx, baseName + "_both_comp_access", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
899 baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0,
900 LOAD_MATRIX_COMPONENTS));
901 modeGroup->addChild(new BlockMultiBasicTypesCase(
902 m_testCtx, baseName + "_mixed_comp_access", baseFlags | DECLARE_VERTEX,
903 baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0,
904 LOAD_MATRIX_COMPONENTS));
905 }
906 }
907 }
908 }
909
910 // ubo.multi_nested_struct
911 {
912 tcu::TestCaseGroup *multiNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct");
913 addChild(multiNestedStructGroup);
914
915 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
916 {
917 tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name);
918 multiNestedStructGroup->addChild(modeGroup);
919
920 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
921 {
922 for (int isArray = 0; isArray < 2; isArray++)
923 {
924 std::string baseName = layoutFlags[layoutFlagNdx].name;
925 uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags;
926
927 if (isArray)
928 baseName += "_instance_array";
929
930 modeGroup->addChild(new BlockMultiNestedStructCase(
931 m_testCtx, baseName + "_vertex", baseFlags | DECLARE_VERTEX, baseFlags | DECLARE_VERTEX,
932 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
933 modeGroup->addChild(new BlockMultiNestedStructCase(
934 m_testCtx, baseName + "_fragment", baseFlags | DECLARE_FRAGMENT, baseFlags | DECLARE_FRAGMENT,
935 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
936 modeGroup->addChild(new BlockMultiNestedStructCase(
937 m_testCtx, baseName + "_both", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
938 baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0,
939 LOAD_FULL_MATRIX));
940 modeGroup->addChild(new BlockMultiNestedStructCase(
941 m_testCtx, baseName + "_mixed", baseFlags | DECLARE_VERTEX, baseFlags | DECLARE_FRAGMENT,
942 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
943 modeGroup->addChild(new BlockMultiNestedStructCase(
944 m_testCtx, baseName + "_vertex_comp_access", baseFlags | DECLARE_VERTEX,
945 baseFlags | DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0,
946 LOAD_MATRIX_COMPONENTS));
947 modeGroup->addChild(new BlockMultiNestedStructCase(
948 m_testCtx, baseName + "_fragment_comp_access", baseFlags | DECLARE_FRAGMENT,
949 baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0,
950 LOAD_MATRIX_COMPONENTS));
951 modeGroup->addChild(new BlockMultiNestedStructCase(
952 m_testCtx, baseName + "_both_comp_access", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
953 baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0,
954 LOAD_MATRIX_COMPONENTS));
955 modeGroup->addChild(new BlockMultiNestedStructCase(
956 m_testCtx, baseName + "_mixed_comp_access", baseFlags | DECLARE_VERTEX,
957 baseFlags | DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0,
958 LOAD_MATRIX_COMPONENTS));
959 }
960 }
961 }
962 }
963
964 // .link_by_binding
965 {
966 tcu::TestCaseGroup *linkByBindingGroup = new tcu::TestCaseGroup(m_testCtx, "link_by_binding");
967 addChild(linkByBindingGroup);
968
969 linkByBindingGroup->addChild(
970 new LinkByBindingCase(m_testCtx, "single_buf_single_instance", UniformBlockCase::BUFFERMODE_SINGLE, 0));
971 linkByBindingGroup->addChild(
972 new LinkByBindingCase(m_testCtx, "single_buf_instance_array", UniformBlockCase::BUFFERMODE_SINGLE, 2));
973 linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "per_block_buf_single_instance",
974 UniformBlockCase::BUFFERMODE_PER_BLOCK, 0));
975 linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "per_block_buf_instance_array",
976 UniformBlockCase::BUFFERMODE_PER_BLOCK, 2));
977 }
978
979 // ubo.random
980 {
981 const uint32_t allShaders = FEATURE_VERTEX_BLOCKS | FEATURE_FRAGMENT_BLOCKS | FEATURE_SHARED_BLOCKS;
982 const uint32_t allLayouts = FEATURE_STD140_LAYOUT;
983 const uint32_t allBasicTypes = FEATURE_VECTORS | FEATURE_MATRICES;
984 const uint32_t unused = FEATURE_UNUSED_MEMBERS | FEATURE_UNUSED_UNIFORMS;
985 const uint32_t matFlags = FEATURE_MATRIX_LAYOUT;
986 const uint32_t allFeatures = ~FEATURE_OUT_OF_ORDER_OFFSETS & ~FEATURE_16BIT_STORAGE & ~FEATURE_8BIT_STORAGE &
987 ~FEATURE_STD430_LAYOUT & ~FEATURE_SCALAR_LAYOUT &
988 ~FEATURE_DESCRIPTOR_INDEXING; // OOO offsets handled in a dedicated case group
989 const uint32_t allScalar =
990 ~allLayouts & ~FEATURE_16BIT_STORAGE & ~FEATURE_8BIT_STORAGE & ~FEATURE_DESCRIPTOR_INDEXING;
991 const uint32_t descriptorIndexing = FEATURE_STD140_LAYOUT | FEATURE_STD430_LAYOUT | FEATURE_SCALAR_LAYOUT |
992 FEATURE_DESCRIPTOR_INDEXING | allShaders | allBasicTypes | unused |
993 matFlags;
994
995 tcu::TestCaseGroup *randomGroup = new tcu::TestCaseGroup(m_testCtx, "random");
996 addChild(randomGroup);
997
998 for (int i = 0; i < 3; ++i)
999 {
1000
1001 tcu::TestCaseGroup *group = randomGroup;
1002 if (i == 1)
1003 {
1004 group = new tcu::TestCaseGroup(m_testCtx, "16bit");
1005 randomGroup->addChild(group);
1006 }
1007 if (i == 2)
1008 {
1009 group = new tcu::TestCaseGroup(m_testCtx, "8bit");
1010 randomGroup->addChild(group);
1011 }
1012 const uint32_t use16BitStorage = i == 1 ? FEATURE_16BIT_STORAGE : 0;
1013 const uint32_t use8BitStorage = i == 2 ? FEATURE_8BIT_STORAGE : 0;
1014
1015 // Basic types.
1016 // Scalar types only, per-block buffers
1017 createRandomCaseGroup(group, m_testCtx, "scalar_types", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1018 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused, 25, 0);
1019 // Scalar and vector types only, per-block buffers
1020 createRandomCaseGroup(group, m_testCtx, "vector_types", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1021 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused | FEATURE_VECTORS,
1022 25, 25);
1023 // All basic types, per-block buffers
1024 createRandomCaseGroup(
1025 group, m_testCtx, "basic_types", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1026 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused | allBasicTypes | matFlags, 25, 50);
1027 // Arrays, per-block buffers
1028 createRandomCaseGroup(group, m_testCtx, "basic_arrays", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1029 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused | allBasicTypes |
1030 matFlags | FEATURE_ARRAYS,
1031 25, 50);
1032
1033 // Basic instance arrays, per-block buffers
1034 createRandomCaseGroup(group, m_testCtx, "basic_instance_arrays", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1035 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused | allBasicTypes |
1036 matFlags | FEATURE_INSTANCE_ARRAYS,
1037 25, 75);
1038 // Nested structs, per-block buffers
1039 createRandomCaseGroup(group, m_testCtx, "nested_structs", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1040 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused | allBasicTypes |
1041 matFlags | FEATURE_STRUCTS,
1042 25, 100);
1043 // Nested structs, arrays, per-block buffers
1044 createRandomCaseGroup(group, m_testCtx, "nested_structs_arrays", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1045 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused | allBasicTypes |
1046 matFlags | FEATURE_STRUCTS | FEATURE_ARRAYS,
1047 25, 150);
1048 // Nested structs, instance arrays, per-block buffers
1049 createRandomCaseGroup(group, m_testCtx, "nested_structs_instance_arrays",
1050 UniformBlockCase::BUFFERMODE_PER_BLOCK,
1051 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused | allBasicTypes |
1052 matFlags | FEATURE_STRUCTS | FEATURE_INSTANCE_ARRAYS,
1053 25, 125);
1054 // Nested structs, instance arrays, per-block buffers
1055 createRandomCaseGroup(group, m_testCtx, "nested_structs_arrays_instance_arrays",
1056 UniformBlockCase::BUFFERMODE_PER_BLOCK,
1057 use8BitStorage | use16BitStorage | allShaders | allLayouts | unused | allBasicTypes |
1058 matFlags | FEATURE_STRUCTS | FEATURE_ARRAYS | FEATURE_INSTANCE_ARRAYS,
1059 25, 175);
1060
1061 // All random features, per-block buffers
1062 createRandomCaseGroup(group, m_testCtx, "all_per_block_buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1063 use8BitStorage | use16BitStorage | allFeatures, 50, 200);
1064 // All random features, shared buffer
1065 createRandomCaseGroup(group, m_testCtx, "all_shared_buffer", UniformBlockCase::BUFFERMODE_SINGLE,
1066 use8BitStorage | use16BitStorage | allFeatures, 50, 250);
1067
1068 // All random features, out of order member offsets
1069 createRandomCaseGroup(group, m_testCtx, "all_out_of_order_offsets", UniformBlockCase::BUFFERMODE_PER_BLOCK,
1070 use8BitStorage | use16BitStorage | allFeatures | FEATURE_OUT_OF_ORDER_OFFSETS, 50,
1071 300);
1072 // VK_EXT_scalar_block_layout
1073 createRandomCaseGroup(group, m_testCtx, "scalar", UniformBlockCase::BUFFERMODE_SINGLE,
1074 use8BitStorage | use16BitStorage | allScalar, 100, deInt32Hash(313));
1075 // VK_EXT_descriptor_indexing
1076 createRandomCaseGroup(group, m_testCtx, "descriptor_indexing", UniformBlockCase::BUFFERMODE_SINGLE,
1077 use8BitStorage | use16BitStorage | descriptorIndexing, 50, 123);
1078 }
1079 }
1080 }
1081
1082 } // namespace
1083
createTests(tcu::TestContext & testCtx,const std::string & name)1084 tcu::TestCaseGroup *createTests(tcu::TestContext &testCtx, const std::string &name)
1085 {
1086 return new UniformBlockTests(testCtx, name);
1087 }
1088
1089 } // namespace ubo
1090 } // namespace vkt
1091