Merge "DO NOT MERGE: Temporarily disable failing deqp tests" into oc-dev am: 4695739815
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / ubo / vktUniformBlockTests.cpp
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:
45         BlockBasicTypeCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const VarType& type, deUint32 layoutFlags, int numInstances, MatrixLoadFlags matrixLoadFlag)
46                 : UniformBlockCase(testCtx, name, description, BUFFERMODE_PER_BLOCK, matrixLoadFlag)
47         {
48                 UniformBlock& block = m_interface.allocBlock("Block");
49                 block.addUniform(Uniform("var", type, 0));
50                 block.setFlags(layoutFlags);
51
52                 if (numInstances > 0)
53                 {
54                         block.setArraySize(numInstances);
55                         block.setInstanceName("block");
56                 }
57
58                 init();
59         }
60 };
61
62 void createBlockBasicTypeCases (tcu::TestCaseGroup& group, tcu::TestContext& testCtx, const std::string& name, const VarType& type, deUint32 layoutFlags, int numInstances = 0)
63 {
64         de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(group.getTestContext(), name.c_str(), ""));
65
66         typeGroup->addChild(new BlockBasicTypeCase(testCtx, "vertex",                           "", type, layoutFlags|DECLARE_VERTEX,                                   numInstances, LOAD_FULL_MATRIX));
67         typeGroup->addChild(new BlockBasicTypeCase(testCtx, "fragment",                         "", type, layoutFlags|DECLARE_FRAGMENT,                                 numInstances, LOAD_FULL_MATRIX));
68         typeGroup->addChild(new BlockBasicTypeCase(testCtx, "both",                                     "",     type, layoutFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      numInstances, LOAD_FULL_MATRIX));
69         typeGroup->addChild(new BlockBasicTypeCase(testCtx, "vertex_comp_access",       "", type, layoutFlags|DECLARE_VERTEX,                                   numInstances, LOAD_MATRIX_COMPONENTS));
70         typeGroup->addChild(new BlockBasicTypeCase(testCtx, "fragment_comp_access",     "", type, layoutFlags|DECLARE_FRAGMENT,                                 numInstances, LOAD_MATRIX_COMPONENTS));
71         typeGroup->addChild(new BlockBasicTypeCase(testCtx, "both_comp_access",         "",     type, layoutFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      numInstances, LOAD_MATRIX_COMPONENTS));
72
73         group.addChild(typeGroup.release());
74 }
75
76 class BlockSingleStructCase : public UniformBlockCase
77 {
78 public:
79         BlockSingleStructCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
80                 : UniformBlockCase      (testCtx, name, description, bufferMode, matrixLoadFlag)
81         {
82                 StructType& typeS = m_interface.allocStruct("S");
83                 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH); // First member is unused.
84                 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
85                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
86
87                 UniformBlock& block = m_interface.allocBlock("Block");
88                 block.addUniform(Uniform("s", VarType(&typeS), 0));
89                 block.setFlags(layoutFlags);
90
91                 if (numInstances > 0)
92                 {
93                         block.setInstanceName("block");
94                         block.setArraySize(numInstances);
95                 }
96
97                 init();
98         }
99 };
100
101 class BlockSingleStructArrayCase : public UniformBlockCase
102 {
103 public:
104         BlockSingleStructArrayCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
105                 : UniformBlockCase      (testCtx, name, description, bufferMode, matrixLoadFlag)
106         {
107                 StructType& typeS = m_interface.allocStruct("S");
108                 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
109                 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
110                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
111
112                 UniformBlock& block = m_interface.allocBlock("Block");
113                 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_LOW)));
114                 block.addUniform(Uniform("s", VarType(VarType(&typeS), 3)));
115                 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_MEDIUM)));
116                 block.setFlags(layoutFlags);
117
118                 if (numInstances > 0)
119                 {
120                         block.setInstanceName("block");
121                         block.setArraySize(numInstances);
122                 }
123
124                 init();
125         }
126 };
127
128 class BlockSingleNestedStructCase : public UniformBlockCase
129 {
130 public:
131         BlockSingleNestedStructCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
132                 : UniformBlockCase      (testCtx, name, description, bufferMode, matrixLoadFlag)
133         {
134                 StructType& typeS = m_interface.allocStruct("S");
135                 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
136                 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
137                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
138
139                 StructType& typeT = m_interface.allocStruct("T");
140                 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
141                 typeT.addMember("b", VarType(&typeS));
142
143                 UniformBlock& block = m_interface.allocBlock("Block");
144                 block.addUniform(Uniform("s", VarType(&typeS), 0));
145                 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
146                 block.addUniform(Uniform("t", VarType(&typeT), 0));
147                 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
148                 block.setFlags(layoutFlags);
149
150                 if (numInstances > 0)
151                 {
152                         block.setInstanceName("block");
153                         block.setArraySize(numInstances);
154                 }
155
156                 init();
157         }
158 };
159
160 class BlockSingleNestedStructArrayCase : public UniformBlockCase
161 {
162 public:
163         BlockSingleNestedStructArrayCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
164                 : UniformBlockCase      (testCtx, name, description, bufferMode, matrixLoadFlag)
165         {
166                 StructType& typeS = m_interface.allocStruct("S");
167                 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
168                 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
169                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
170
171                 StructType& typeT = m_interface.allocStruct("T");
172                 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
173                 typeT.addMember("b", VarType(VarType(&typeS), 3));
174
175                 UniformBlock& block = m_interface.allocBlock("Block");
176                 block.addUniform(Uniform("s", VarType(&typeS), 0));
177                 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
178                 block.addUniform(Uniform("t", VarType(VarType(&typeT), 2), 0));
179                 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
180                 block.setFlags(layoutFlags);
181
182                 if (numInstances > 0)
183                 {
184                         block.setInstanceName("block");
185                         block.setArraySize(numInstances);
186                 }
187
188                 init();
189         }
190 };
191
192 class BlockMultiBasicTypesCase : public UniformBlockCase
193 {
194 public:
195         BlockMultiBasicTypesCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
196                 : UniformBlockCase      (testCtx, name, description, bufferMode, matrixLoadFlag)
197         {
198                 UniformBlock& blockA = m_interface.allocBlock("BlockA");
199                 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
200                 blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
201                 blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
202                 blockA.setInstanceName("blockA");
203                 blockA.setFlags(flagsA);
204
205                 UniformBlock& blockB = m_interface.allocBlock("BlockB");
206                 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
207                 blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
208                 blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
209                 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
210                 blockB.setInstanceName("blockB");
211                 blockB.setFlags(flagsB);
212
213                 if (numInstances > 0)
214                 {
215                         blockA.setArraySize(numInstances);
216                         blockB.setArraySize(numInstances);
217                 }
218
219                 init();
220         }
221 };
222
223 class BlockMultiNestedStructCase : public UniformBlockCase
224 {
225 public:
226         BlockMultiNestedStructCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
227                 : UniformBlockCase      (testCtx, name, description, bufferMode, matrixLoadFlag)
228         {
229                 StructType& typeS = m_interface.allocStruct("S");
230                 typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_LOW));
231                 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
232                 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
233
234                 StructType& typeT = m_interface.allocStruct("T");
235                 typeT.addMember("a", VarType(glu::TYPE_UINT, PRECISION_MEDIUM), UNUSED_BOTH);
236                 typeT.addMember("b", VarType(&typeS));
237                 typeT.addMember("c", VarType(glu::TYPE_BOOL_VEC4, 0));
238
239                 UniformBlock& blockA = m_interface.allocBlock("BlockA");
240                 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
241                 blockA.addUniform(Uniform("b", VarType(&typeS)));
242                 blockA.addUniform(Uniform("c", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
243                 blockA.setInstanceName("blockA");
244                 blockA.setFlags(flagsA);
245
246                 UniformBlock& blockB = m_interface.allocBlock("BlockB");
247                 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
248                 blockB.addUniform(Uniform("b", VarType(&typeT)));
249                 blockB.addUniform(Uniform("c", VarType(glu::TYPE_BOOL_VEC4, 0), UNUSED_BOTH));
250                 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
251                 blockB.setInstanceName("blockB");
252                 blockB.setFlags(flagsB);
253
254                 if (numInstances > 0)
255                 {
256                         blockA.setArraySize(numInstances);
257                         blockB.setArraySize(numInstances);
258                 }
259
260                 init();
261         }
262 };
263
264 class Block2LevelStructArrayCase : public UniformBlockCase
265 {
266 public:
267         Block2LevelStructArrayCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
268                 : UniformBlockCase      (testCtx, name, description, bufferMode, matrixLoadFlag)
269                 , m_layoutFlags         (layoutFlags)
270                 , m_numInstances        (numInstances)
271         {
272                 StructType& typeS = m_interface.allocStruct("S");
273                 typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
274                 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 4));
275                 typeS.addMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW));
276
277                 UniformBlock& block = m_interface.allocBlock("Block");
278                 block.addUniform(Uniform("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM)));
279                 block.addUniform(Uniform("s", VarType(VarType(VarType(&typeS), 3), 2)));
280                 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM)));
281                 block.setFlags(m_layoutFlags);
282
283                 if (m_numInstances > 0)
284                 {
285                         block.setInstanceName("block");
286                         block.setArraySize(m_numInstances);
287                 }
288
289                 init();
290         }
291
292 private:
293         deUint32        m_layoutFlags;
294         int                     m_numInstances;
295 };
296
297 class LinkByBindingCase : public UniformBlockCase
298 {
299 public:
300         LinkByBindingCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, BufferMode bufferMode, int numInstances)
301                 : UniformBlockCase      (testCtx, name, description, bufferMode, LOAD_FULL_MATRIX)
302         {
303                 UniformBlock& blockA = m_interface.allocBlock("TestBlock");
304                 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
305                 blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
306                 blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
307                 blockA.setFlags(LAYOUT_STD140|DECLARE_VERTEX);
308
309                 UniformBlock& blockB = m_interface.allocBlock("TestBlock");
310                 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
311                 blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
312                 blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
313                 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
314                 blockB.setFlags(LAYOUT_STD140|DECLARE_FRAGMENT);
315
316                 if (numInstances > 0)
317                 {
318                         blockA.setInstanceName("testBlock");
319                         blockA.setArraySize(numInstances);
320                         blockB.setInstanceName("testBlock");
321                         blockB.setArraySize(numInstances);
322                 }
323
324                 init();
325         }
326 };
327
328 void createRandomCaseGroup (tcu::TestCaseGroup* parentGroup, tcu::TestContext& testCtx, const char* groupName, const char* description, UniformBlockCase::BufferMode bufferMode, deUint32 features, int numCases, deUint32 baseSeed)
329 {
330         tcu::TestCaseGroup* group = new tcu::TestCaseGroup(testCtx, groupName, description);
331         parentGroup->addChild(group);
332
333         baseSeed += (deUint32)testCtx.getCommandLine().getBaseSeed();
334
335         for (int ndx = 0; ndx < numCases; ndx++)
336                 group->addChild(new RandomUniformBlockCase(testCtx, de::toString(ndx), "", bufferMode, features, (deUint32)ndx + baseSeed));
337 }
338
339 // UniformBlockTests
340
341 class UniformBlockTests : public tcu::TestCaseGroup
342 {
343 public:
344                                                         UniformBlockTests               (tcu::TestContext& testCtx);
345                                                         ~UniformBlockTests              (void);
346
347         void                                    init                                    (void);
348
349 private:
350                                                         UniformBlockTests               (const UniformBlockTests& other);
351         UniformBlockTests&              operator=                               (const UniformBlockTests& other);
352 };
353
354 UniformBlockTests::UniformBlockTests (tcu::TestContext& testCtx)
355         : TestCaseGroup(testCtx, "ubo", "Uniform Block tests")
356 {
357 }
358
359 UniformBlockTests::~UniformBlockTests (void)
360 {
361 }
362
363 void UniformBlockTests::init (void)
364 {
365         static const glu::DataType basicTypes[] =
366         {
367                 glu::TYPE_FLOAT,
368                 glu::TYPE_FLOAT_VEC2,
369                 glu::TYPE_FLOAT_VEC3,
370                 glu::TYPE_FLOAT_VEC4,
371                 glu::TYPE_INT,
372                 glu::TYPE_INT_VEC2,
373                 glu::TYPE_INT_VEC3,
374                 glu::TYPE_INT_VEC4,
375                 glu::TYPE_UINT,
376                 glu::TYPE_UINT_VEC2,
377                 glu::TYPE_UINT_VEC3,
378                 glu::TYPE_UINT_VEC4,
379                 glu::TYPE_BOOL,
380                 glu::TYPE_BOOL_VEC2,
381                 glu::TYPE_BOOL_VEC3,
382                 glu::TYPE_BOOL_VEC4,
383                 glu::TYPE_FLOAT_MAT2,
384                 glu::TYPE_FLOAT_MAT3,
385                 glu::TYPE_FLOAT_MAT4,
386                 glu::TYPE_FLOAT_MAT2X3,
387                 glu::TYPE_FLOAT_MAT2X4,
388                 glu::TYPE_FLOAT_MAT3X2,
389                 glu::TYPE_FLOAT_MAT3X4,
390                 glu::TYPE_FLOAT_MAT4X2,
391                 glu::TYPE_FLOAT_MAT4X3
392         };
393
394         static const struct
395         {
396                 const std::string       name;
397                 deUint32                        flags;
398         } precisionFlags[] =
399         {
400                 // TODO remove PRECISION_LOW because both PRECISION_LOW and PRECISION_MEDIUM means relaxed precision?
401                 { "lowp",               PRECISION_LOW           },
402                 { "mediump",    PRECISION_MEDIUM        },
403                 { "highp",              PRECISION_HIGH          }
404         };
405
406         static const struct
407         {
408                 const char*                     name;
409                 deUint32                        flags;
410         } layoutFlags[] =
411         {
412                 { "std140",             LAYOUT_STD140   }
413         };
414
415         static const struct
416         {
417                 const std::string       name;
418                 deUint32                        flags;
419         } matrixFlags[] =
420         {
421                 { "row_major",          LAYOUT_ROW_MAJOR        },
422                 { "column_major",       LAYOUT_COLUMN_MAJOR }
423         };
424
425         static const struct
426         {
427                 const char*                                                     name;
428                 UniformBlockCase::BufferMode            mode;
429         } bufferModes[] =
430         {
431                 { "per_block_buffer",   UniformBlockCase::BUFFERMODE_PER_BLOCK },
432                 { "single_buffer",              UniformBlockCase::BUFFERMODE_SINGLE     }
433         };
434
435         // ubo.2_level_array
436         {
437                 tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level basic array variable in single buffer");
438                 addChild(nestedArrayGroup);
439
440                 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
441                 {
442                         de::MovePtr<tcu::TestCaseGroup> layoutGroup(new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""));
443
444                         for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
445                         {
446                                 const glu::DataType     type            = basicTypes[basicTypeNdx];
447                                 const char* const       typeName        = glu::getDataTypeName(type);
448                                 const int                       childSize       = 4;
449                                 const int                       parentSize      = 3;
450                                 const VarType           childType       (VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize);
451                                 const VarType           parentType      (childType, parentSize);
452
453                                 createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName, parentType, layoutFlags[layoutFlagNdx].flags);
454
455                                 if (glu::isDataTypeMatrix(type))
456                                 {
457                                         for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
458                                                 createBlockBasicTypeCases(*layoutGroup, m_testCtx, (std::string(matrixFlags[matFlagNdx].name) + "_" + typeName),
459                                                                                                   parentType, layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
460                                 }
461                         }
462                         nestedArrayGroup->addChild(layoutGroup.release());
463                 }
464         }
465
466         // ubo.3_level_array
467         {
468                 tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level basic array variable in single buffer");
469                 addChild(nestedArrayGroup);
470
471                 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
472                 {
473                         de::MovePtr<tcu::TestCaseGroup> layoutGroup(new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""));
474
475                         for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
476                         {
477                                 const glu::DataType     type            = basicTypes[basicTypeNdx];
478                                 const char* const       typeName        = glu::getDataTypeName(type);
479                                 const int                       childSize0      = 2;
480                                 const int                       childSize1      = 4;
481                                 const int                       parentSize      = 3;
482                                 const VarType           childType0      (VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize0);
483                                 const VarType           childType1      (childType0, childSize1);
484                                 const VarType           parentType      (childType1, parentSize);
485
486                                 createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName, parentType, layoutFlags[layoutFlagNdx].flags);
487
488                                 if (glu::isDataTypeMatrix(type))
489                                 {
490                                         for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
491                                                 createBlockBasicTypeCases(*layoutGroup, m_testCtx, (std::string(matrixFlags[matFlagNdx].name) + "_" + typeName),
492                                                                                                   parentType, layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
493                                 }
494                         }
495                         nestedArrayGroup->addChild(layoutGroup.release());
496                 }
497         }
498
499         // ubo.2_level_struct_array
500         {
501                 tcu::TestCaseGroup* structArrayArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array", "Struct array in one uniform block");
502                 addChild(structArrayArrayGroup);
503
504                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
505                 {
506                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
507                         structArrayArrayGroup->addChild(modeGroup);
508
509                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
510                         {
511                                 for (int isArray = 0; isArray < 2; isArray++)
512                                 {
513                                         std::string     baseName        = layoutFlags[layoutFlagNdx].name;
514                                         deUint32        baseFlags       = layoutFlags[layoutFlagNdx].flags;
515
516                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
517                                                 continue; // Doesn't make sense to add this variant.
518
519                                         if (isArray)
520                                                 baseName += "_instance_array";
521
522                                         modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_vertex"),                           "", baseFlags|DECLARE_VERTEX,                                   bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
523                                         modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_fragment"),                         "", baseFlags|DECLARE_FRAGMENT,                                 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
524                                         modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_both"),                                     "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,  bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
525                                         modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_vertex_comp_access"),       "", baseFlags|DECLARE_VERTEX,                                   bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
526                                         modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_fragment_comp_access"),     "", baseFlags|DECLARE_FRAGMENT,                                 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
527                                         modeGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_both_comp_access"),         "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,  bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
528                                 }
529                         }
530                 }
531         }
532
533         // ubo.single_basic_type
534         {
535                 tcu::TestCaseGroup* singleBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_type", "Single basic variable in single buffer");
536                 addChild(singleBasicTypeGroup);
537
538                 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
539                 {
540                         de::MovePtr<tcu::TestCaseGroup> layoutGroup(new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""));
541
542                         for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
543                         {
544                                 glu::DataType           type = basicTypes[basicTypeNdx];
545                                 const char* const       typeName = glu::getDataTypeName(type);
546
547                                 if (glu::isDataTypeBoolOrBVec(type))
548                                         createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName, VarType(type, 0), layoutFlags[layoutFlagNdx].flags);
549                         }
550
551                         for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
552                         {
553                                 de::MovePtr<tcu::TestCaseGroup> precGroup(new tcu::TestCaseGroup(m_testCtx, precisionFlags[precNdx].name.c_str(), ""));
554
555                                 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
556                                 {
557                                         glu::DataType           type            = basicTypes[basicTypeNdx];
558                                         const char* const       typeName        = glu::getDataTypeName(type);
559
560                                         if (!glu::isDataTypeBoolOrBVec(type))
561                                                 createBlockBasicTypeCases(*precGroup, m_testCtx, typeName,
562                                                                                                   VarType(type, precisionFlags[precNdx].flags), layoutFlags[layoutFlagNdx].flags);
563
564                                         if (glu::isDataTypeMatrix(type))
565                                         {
566                                                 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
567                                                 {
568                                                         createBlockBasicTypeCases(*precGroup, m_testCtx, matrixFlags[matFlagNdx].name + "_" + typeName,
569                                                                                                           VarType(type, precisionFlags[precNdx].flags), layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
570
571                                                 }
572                                         }
573                                 }
574                                 layoutGroup->addChild(precGroup.release());
575                         }
576                         singleBasicTypeGroup->addChild(layoutGroup.release());
577                 }
578         }
579
580         // ubo.single_basic_array
581         {
582                 tcu::TestCaseGroup* singleBasicArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_array", "Single basic array variable in single buffer");
583                 addChild(singleBasicArrayGroup);
584
585                 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
586                 {
587                         de::MovePtr<tcu::TestCaseGroup> layoutGroup(new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""));
588
589                         for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
590                         {
591                                 glu::DataType           type            = basicTypes[basicTypeNdx];
592                                 const char* const       typeName        = glu::getDataTypeName(type);
593                                 const int                       arraySize       = 3;
594
595                                 createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName,
596                                                                                   VarType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), arraySize),
597                                                                                   layoutFlags[layoutFlagNdx].flags);
598
599                                 if (glu::isDataTypeMatrix(type))
600                                 {
601                                         for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
602                                                 createBlockBasicTypeCases(*layoutGroup, m_testCtx, matrixFlags[matFlagNdx].name + "_" + typeName,
603                                                                                                   VarType(VarType(type, PRECISION_HIGH), arraySize),
604                                                                                                   layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
605                                 }
606                         }
607                         singleBasicArrayGroup->addChild(layoutGroup.release());
608                 }
609         }
610
611         // ubo.single_struct
612         {
613                 tcu::TestCaseGroup* singleStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct", "Single struct in uniform block");
614                 addChild(singleStructGroup);
615
616                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
617                 {
618                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
619                         singleStructGroup->addChild(modeGroup);
620
621                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
622                         {
623                                 for (int isArray = 0; isArray < 2; isArray++)
624                                 {
625                                         std::string     baseName        = layoutFlags[layoutFlagNdx].name;
626                                         deUint32        baseFlags       = layoutFlags[layoutFlagNdx].flags;
627
628                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
629                                                 continue; // Doesn't make sense to add this variant.
630
631                                         if (isArray)
632                                                 baseName += "_instance_array";
633
634                                         modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_vertex",                           "", baseFlags|DECLARE_VERTEX,                                  bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
635                                         modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_fragment",                         "", baseFlags|DECLARE_FRAGMENT,                                bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
636                                         modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_both",                             "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
637                                         modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_vertex_comp_access",       "", baseFlags|DECLARE_VERTEX,                                  bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
638                                         modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_fragment_comp_access", "", baseFlags|DECLARE_FRAGMENT,                            bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
639                                         modeGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_both_comp_access",         "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
640                                 }
641                         }
642                 }
643         }
644
645         // ubo.single_struct_array
646         {
647                 tcu::TestCaseGroup* singleStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct_array", "Struct array in one uniform block");
648                 addChild(singleStructArrayGroup);
649
650                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
651                 {
652                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
653                         singleStructArrayGroup->addChild(modeGroup);
654
655                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
656                         {
657                                 for (int isArray = 0; isArray < 2; isArray++)
658                                 {
659                                         std::string     baseName        = layoutFlags[layoutFlagNdx].name;
660                                         deUint32        baseFlags       = layoutFlags[layoutFlagNdx].flags;
661
662                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
663                                                 continue; // Doesn't make sense to add this variant.
664
665                                         if (isArray)
666                                                 baseName += "_instance_array";
667
668                                         modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_vertex",                               "", baseFlags|DECLARE_VERTEX,                                         bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
669                                         modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_fragment",                     "", baseFlags|DECLARE_FRAGMENT,                                       bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
670                                         modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_both",                                 "",   baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
671                                         modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_vertex_comp_access",   "", baseFlags|DECLARE_VERTEX,                                         bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
672                                         modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_fragment_comp_access", "", baseFlags|DECLARE_FRAGMENT,                                       bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
673                                         modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_both_comp_access",     "",   baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
674                                 }
675                         }
676                 }
677         }
678
679         // ubo.single_nested_struct
680         {
681                 tcu::TestCaseGroup* singleNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct", "Nested struct in one uniform block");
682                 addChild(singleNestedStructGroup);
683
684                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
685                 {
686                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
687                         singleNestedStructGroup->addChild(modeGroup);
688
689                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
690                         {
691                                 for (int isArray = 0; isArray < 2; isArray++)
692                                 {
693                                         std::string     baseName        = layoutFlags[layoutFlagNdx].name;
694                                         deUint32        baseFlags       = layoutFlags[layoutFlagNdx].flags;
695
696                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
697                                                 continue; // Doesn't make sense to add this variant.
698
699                                         if (isArray)
700                                                 baseName += "_instance_array";
701
702                                         modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_vertex",                            "", baseFlags|DECLARE_VERTEX,                                   bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
703                                         modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_fragment",                          "", baseFlags|DECLARE_FRAGMENT,                                 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
704                                         modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_both",                                      "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,  bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
705                                         modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_vertex_comp_access",        "", baseFlags|DECLARE_VERTEX,                                   bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
706                                         modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_fragment_comp_access",      "", baseFlags|DECLARE_FRAGMENT,                                 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
707                                         modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_both_comp_access",          "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,  bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
708                                 }
709                         }
710                 }
711         }
712
713         // ubo.single_nested_struct_array
714         {
715                 tcu::TestCaseGroup* singleNestedStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array", "Nested struct array in one uniform block");
716                 addChild(singleNestedStructArrayGroup);
717
718                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
719                 {
720                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
721                         singleNestedStructArrayGroup->addChild(modeGroup);
722
723                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
724                         {
725                                 for (int isArray = 0; isArray < 2; isArray++)
726                                 {
727                                         std::string     baseName        = layoutFlags[layoutFlagNdx].name;
728                                         deUint32        baseFlags       = layoutFlags[layoutFlagNdx].flags;
729
730                                         if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
731                                                 continue; // Doesn't make sense to add this variant.
732
733                                         if (isArray)
734                                                 baseName += "_instance_array";
735
736                                         modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_vertex",                               "", baseFlags|DECLARE_VERTEX,                                   bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
737                                         modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_fragment",                             "", baseFlags|DECLARE_FRAGMENT,                                 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
738                                         modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_both",                                 "",     baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
739                                         modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_vertex_comp_access",   "", baseFlags|DECLARE_VERTEX,                                   bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
740                                         modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_fragment_comp_access", "", baseFlags|DECLARE_FRAGMENT,                                 bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
741                                         modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_both_comp_access",             "",     baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
742                                 }
743                         }
744                 }
745         }
746
747         // ubo.instance_array_basic_type
748         {
749                 tcu::TestCaseGroup* instanceArrayBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type", "Single basic variable in instance array");
750                 addChild(instanceArrayBasicTypeGroup);
751
752                 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
753                 {
754                         de::MovePtr<tcu::TestCaseGroup> layoutGroup(new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""));
755
756                         for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
757                         {
758                                 glu::DataType           type                    = basicTypes[basicTypeNdx];
759                                 const char* const       typeName                = glu::getDataTypeName(type);
760                                 const int                       numInstances    = 3;
761
762                                 createBlockBasicTypeCases(*layoutGroup, m_testCtx, typeName,
763                                                                                   VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH),
764                                                                                   layoutFlags[layoutFlagNdx].flags, numInstances);
765
766                                 if (glu::isDataTypeMatrix(type))
767                                 {
768                                         for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
769                                                 createBlockBasicTypeCases(*layoutGroup, m_testCtx, matrixFlags[matFlagNdx].name + "_" + typeName,
770                                                                                                   VarType(type, PRECISION_HIGH), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags,
771                                                                                                   numInstances);
772                                 }
773                         }
774                         instanceArrayBasicTypeGroup->addChild(layoutGroup.release());
775                 }
776         }
777
778         // ubo.multi_basic_types
779         {
780                 tcu::TestCaseGroup* multiBasicTypesGroup = new tcu::TestCaseGroup(m_testCtx, "multi_basic_types", "Multiple buffers with basic types");
781                 addChild(multiBasicTypesGroup);
782
783                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
784                 {
785                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
786                         multiBasicTypesGroup->addChild(modeGroup);
787
788                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
789                         {
790                                 for (int isArray = 0; isArray < 2; isArray++)
791                                 {
792                                         std::string     baseName        = layoutFlags[layoutFlagNdx].name;
793                                         deUint32        baseFlags       = layoutFlags[layoutFlagNdx].flags;
794
795                                         if (isArray)
796                                                 baseName += "_instance_array";
797
798                                         modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_vertex",                               "", baseFlags|DECLARE_VERTEX,                                   baseFlags|DECLARE_VERTEX,                                       bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
799                                         modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_fragment",                             "", baseFlags|DECLARE_FRAGMENT,                                 baseFlags|DECLARE_FRAGMENT,                                     bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
800                                         modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_both",                                 "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,  baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
801                                         modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_mixed",                                "", baseFlags|DECLARE_VERTEX,                                   baseFlags|DECLARE_FRAGMENT,                                     bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
802                                         modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_vertex_comp_access",   "", baseFlags|DECLARE_VERTEX,                                   baseFlags|DECLARE_VERTEX,                                       bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
803                                         modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_fragment_comp_access", "", baseFlags|DECLARE_FRAGMENT,                                 baseFlags|DECLARE_FRAGMENT,                                     bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
804                                         modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_both_comp_access",             "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,  baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
805                                         modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_mixed_comp_access",    "", baseFlags|DECLARE_VERTEX,                                   baseFlags|DECLARE_FRAGMENT,                                     bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
806                                 }
807                         }
808                 }
809         }
810
811         // ubo.multi_nested_struct
812         {
813                 tcu::TestCaseGroup* multiNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct", "Multiple buffers with nested structs");
814                 addChild(multiNestedStructGroup);
815
816                 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
817                 {
818                         tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
819                         multiNestedStructGroup->addChild(modeGroup);
820
821                         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
822                         {
823                                 for (int isArray = 0; isArray < 2; isArray++)
824                                 {
825                                         std::string     baseName        = layoutFlags[layoutFlagNdx].name;
826                                         deUint32        baseFlags       = layoutFlags[layoutFlagNdx].flags;
827
828                                         if (isArray)
829                                                 baseName += "_instance_array";
830
831                                         modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_vertex",                               "", baseFlags|DECLARE_VERTEX,                                         baseFlags|DECLARE_VERTEX,                                       bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
832                                         modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_fragment",                     "", baseFlags|DECLARE_FRAGMENT,                                       baseFlags|DECLARE_FRAGMENT,                                     bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
833                                         modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_both",                                 "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,        baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
834                                         modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_mixed",                                "", baseFlags|DECLARE_VERTEX,                                         baseFlags|DECLARE_FRAGMENT,                                     bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
835                                         modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_vertex_comp_access",   "", baseFlags|DECLARE_VERTEX,                                         baseFlags|DECLARE_VERTEX,                                       bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
836                                         modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_fragment_comp_access", "", baseFlags|DECLARE_FRAGMENT,                                       baseFlags|DECLARE_FRAGMENT,                                     bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
837                                         modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_both_comp_access",     "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,        baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT,      bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
838                                         modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_mixed_comp_access",    "", baseFlags|DECLARE_VERTEX,                                         baseFlags|DECLARE_FRAGMENT,                                     bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
839                                 }
840                         }
841                 }
842         }
843
844         // .link_by_binding
845         {
846                 tcu::TestCaseGroup* linkByBindingGroup = new tcu::TestCaseGroup(m_testCtx, "link_by_binding", "Blocks with same name but different binding");
847                 addChild(linkByBindingGroup);
848
849                 linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "single_buf_single_instance",             "", UniformBlockCase::BUFFERMODE_SINGLE, 0));
850                 linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "single_buf_instance_array",              "", UniformBlockCase::BUFFERMODE_SINGLE, 2));
851                 linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "per_block_buf_single_instance",  "", UniformBlockCase::BUFFERMODE_PER_BLOCK, 0));
852                 linkByBindingGroup->addChild(new LinkByBindingCase(m_testCtx, "per_block_buf_instance_array",   "", UniformBlockCase::BUFFERMODE_PER_BLOCK, 2));
853         }
854
855         // ubo.random
856         {
857                 const deUint32  allShaders              = FEATURE_VERTEX_BLOCKS|FEATURE_FRAGMENT_BLOCKS|FEATURE_SHARED_BLOCKS;
858                 const deUint32  allLayouts              = FEATURE_STD140_LAYOUT;
859                 const deUint32  allBasicTypes   = FEATURE_VECTORS|FEATURE_MATRICES;
860                 const deUint32  unused                  = FEATURE_UNUSED_MEMBERS|FEATURE_UNUSED_UNIFORMS;
861                 const deUint32  matFlags                = FEATURE_MATRIX_LAYOUT;
862                 const deUint32  allFeatures             = ~FEATURE_OUT_OF_ORDER_OFFSETS;  // OOO offsets handled in a dedicated case group
863
864                 tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
865                 addChild(randomGroup);
866
867                 // Basic types.
868                 createRandomCaseGroup(randomGroup, m_testCtx, "scalar_types",   "Scalar types only, per-block buffers",                         UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused,                                                                           25, 0);
869                 createRandomCaseGroup(randomGroup, m_testCtx, "vector_types",   "Scalar and vector types only, per-block buffers",      UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|FEATURE_VECTORS,                                           25, 25);
870                 createRandomCaseGroup(randomGroup, m_testCtx, "basic_types",    "All basic types, per-block buffers",                           UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags,                            25, 50);
871                 createRandomCaseGroup(randomGroup, m_testCtx, "basic_arrays",   "Arrays, per-block buffers",                                            UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_ARRAYS,     25, 50);
872
873                 createRandomCaseGroup(randomGroup, m_testCtx, "basic_instance_arrays",                                  "Basic instance arrays, per-block buffers",                             UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_INSTANCE_ARRAYS,                                                            25, 75);
874                 createRandomCaseGroup(randomGroup, m_testCtx, "nested_structs",                                                 "Nested structs, per-block buffers",                                    UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS,                                                                            25, 100);
875                 createRandomCaseGroup(randomGroup, m_testCtx, "nested_structs_arrays",                                  "Nested structs, arrays, per-block buffers",                    UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_ARRAYS,                                                     25, 150);
876                 createRandomCaseGroup(randomGroup, m_testCtx, "nested_structs_instance_arrays",                 "Nested structs, instance arrays, per-block buffers",   UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_INSTANCE_ARRAYS,                            25, 125);
877                 createRandomCaseGroup(randomGroup, m_testCtx, "nested_structs_arrays_instance_arrays",  "Nested structs, instance arrays, per-block buffers",   UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_ARRAYS|FEATURE_INSTANCE_ARRAYS,     25, 175);
878
879                 createRandomCaseGroup(randomGroup, m_testCtx, "all_per_block_buffers",  "All random features, per-block buffers",       UniformBlockCase::BUFFERMODE_PER_BLOCK, allFeatures,    50, 200);
880                 createRandomCaseGroup(randomGroup, m_testCtx, "all_shared_buffer",              "All random features, shared buffer",           UniformBlockCase::BUFFERMODE_SINGLE,    allFeatures,    50, 250);
881
882                 createRandomCaseGroup(randomGroup, m_testCtx, "all_out_of_order_offsets",       "All random features, out of order member offsets",             UniformBlockCase::BUFFERMODE_PER_BLOCK, allFeatures | FEATURE_OUT_OF_ORDER_OFFSETS,     50, 300);
883         }
884 }
885
886 } // anonymous
887
888 tcu::TestCaseGroup*     createTests     (tcu::TestContext& testCtx)
889 {
890         return new UniformBlockTests(testCtx);
891 }
892
893 } // ubo
894 } // vkt