xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fSSBOLayoutTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief SSBO layout tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fSSBOLayoutTests.hpp"
25 #include "es31fSSBOLayoutCase.hpp"
26 #include "tcuCommandLine.hpp"
27 #include "deRandom.hpp"
28 #include "deStringUtil.hpp"
29 #include "deString.h"
30 
31 using std::string;
32 using std::vector;
33 
34 namespace deqp
35 {
36 namespace gles31
37 {
38 namespace Functional
39 {
40 
41 using namespace bb;
42 using glu::StructType;
43 using glu::VarType;
44 
45 namespace
46 {
47 
48 enum FeatureBits
49 {
50     FEATURE_VECTORS          = (1 << 0),
51     FEATURE_MATRICES         = (1 << 1),
52     FEATURE_ARRAYS           = (1 << 2),
53     FEATURE_STRUCTS          = (1 << 3),
54     FEATURE_NESTED_STRUCTS   = (1 << 4),
55     FEATURE_INSTANCE_ARRAYS  = (1 << 5),
56     FEATURE_UNUSED_VARS      = (1 << 6),
57     FEATURE_UNUSED_MEMBERS   = (1 << 7),
58     FEATURE_PACKED_LAYOUT    = (1 << 8),
59     FEATURE_SHARED_LAYOUT    = (1 << 9),
60     FEATURE_STD140_LAYOUT    = (1 << 10),
61     FEATURE_STD430_LAYOUT    = (1 << 11),
62     FEATURE_MATRIX_LAYOUT    = (1 << 12), //!< Matrix layout flags.
63     FEATURE_UNSIZED_ARRAYS   = (1 << 13),
64     FEATURE_ARRAYS_OF_ARRAYS = (1 << 14)
65 };
66 
67 class RandomSSBOLayoutCase : public SSBOLayoutCase
68 {
69 public:
70     RandomSSBOLayoutCase(Context &context, const char *name, const char *description, BufferMode bufferMode,
71                          uint32_t features, uint32_t seed);
72 
73     void init(void);
74 
75 private:
76     void generateBlock(de::Random &rnd, uint32_t layoutFlags);
77     void generateBufferVar(de::Random &rnd, BufferBlock &block, bool isLastMember);
78     glu::VarType generateType(de::Random &rnd, int structDepth, int arrayDepth, bool arrayOk, bool unusedArrayOk);
79 
80     uint32_t m_features;
81     int m_maxBlocks;
82     int m_maxInstances;
83     int m_maxArrayLength;
84     int m_maxArrayDepth;
85     int m_maxStructDepth;
86     int m_maxBlockMembers;
87     int m_maxStructMembers;
88     uint32_t m_seed;
89 
90     int m_blockNdx;
91     int m_bufferVarNdx;
92     int m_structNdx;
93 };
94 
RandomSSBOLayoutCase(Context & context,const char * name,const char * description,BufferMode bufferMode,uint32_t features,uint32_t seed)95 RandomSSBOLayoutCase::RandomSSBOLayoutCase(Context &context, const char *name, const char *description,
96                                            BufferMode bufferMode, uint32_t features, uint32_t seed)
97     : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_310_ES,
98                      bufferMode)
99     , m_features(features)
100     , m_maxBlocks(3)
101     , m_maxInstances((features & FEATURE_INSTANCE_ARRAYS) ? 3 : 0)
102     , m_maxArrayLength((features & FEATURE_ARRAYS) ? 8 : 0)
103     , m_maxArrayDepth((features & FEATURE_ARRAYS_OF_ARRAYS) ? 2 : 0)
104     , m_maxStructDepth((features & FEATURE_STRUCTS) ? 2 : 0)
105     , m_maxBlockMembers(4)
106     , m_maxStructMembers(4)
107     , m_seed(seed)
108     , m_blockNdx(1)
109     , m_bufferVarNdx(1)
110     , m_structNdx(1)
111 {
112 }
113 
init(void)114 void RandomSSBOLayoutCase::init(void)
115 {
116     de::Random rnd(m_seed);
117 
118     const int numBlocks = rnd.getInt(1, m_maxBlocks);
119 
120     for (int ndx = 0; ndx < numBlocks; ndx++)
121         generateBlock(rnd, 0);
122 }
123 
generateBlock(de::Random & rnd,uint32_t layoutFlags)124 void RandomSSBOLayoutCase::generateBlock(de::Random &rnd, uint32_t layoutFlags)
125 {
126     DE_ASSERT(m_blockNdx <= 'z' - 'a');
127 
128     const float instanceArrayWeight = 0.3f;
129     BufferBlock &block              = m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
130     int numInstances = (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
131     int numVars      = rnd.getInt(1, m_maxBlockMembers);
132 
133     if (numInstances > 0)
134         block.setArraySize(numInstances);
135 
136     if (numInstances > 0 || rnd.getBool())
137         block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
138 
139     // Layout flag candidates.
140     vector<uint32_t> layoutFlagCandidates;
141     layoutFlagCandidates.push_back(0);
142     if (m_features & FEATURE_PACKED_LAYOUT)
143         layoutFlagCandidates.push_back(LAYOUT_PACKED);
144     if ((m_features & FEATURE_SHARED_LAYOUT))
145         layoutFlagCandidates.push_back(LAYOUT_SHARED);
146     if (m_features & FEATURE_STD140_LAYOUT)
147         layoutFlagCandidates.push_back(LAYOUT_STD140);
148 
149     layoutFlags |= rnd.choose<uint32_t>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
150 
151     if (m_features & FEATURE_MATRIX_LAYOUT)
152     {
153         static const uint32_t matrixCandidates[] = {0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR};
154         layoutFlags |=
155             rnd.choose<uint32_t>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
156     }
157 
158     block.setFlags(layoutFlags);
159 
160     for (int ndx = 0; ndx < numVars; ndx++)
161         generateBufferVar(rnd, block, (ndx + 1 == numVars));
162 
163     if (numVars > 0)
164     {
165         const BufferVar &lastVar     = *(block.end() - 1);
166         const glu::VarType &lastType = lastVar.getType();
167         const bool isUnsizedArr = lastType.isArrayType() && (lastType.getArraySize() == glu::VarType::UNSIZED_ARRAY);
168 
169         if (isUnsizedArr)
170         {
171             for (int instanceNdx = 0; instanceNdx < (numInstances ? numInstances : 1); instanceNdx++)
172             {
173                 const int arrSize = rnd.getInt(0, m_maxArrayLength);
174                 block.setLastUnsizedArraySize(instanceNdx, arrSize);
175             }
176         }
177     }
178 
179     m_blockNdx += 1;
180 }
181 
genName(char first,char last,int ndx)182 static std::string genName(char first, char last, int ndx)
183 {
184     std::string str = "";
185     int alphabetLen = last - first + 1;
186 
187     while (ndx > alphabetLen)
188     {
189         str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen)));
190         ndx = ((ndx - 1) / alphabetLen);
191     }
192 
193     str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1));
194 
195     return str;
196 }
197 
generateBufferVar(de::Random & rnd,BufferBlock & block,bool isLastMember)198 void RandomSSBOLayoutCase::generateBufferVar(de::Random &rnd, BufferBlock &block, bool isLastMember)
199 {
200     const float readWeight   = 0.7f;
201     const float writeWeight  = 0.7f;
202     const float accessWeight = 0.85f;
203     const bool unusedOk      = (m_features & FEATURE_UNUSED_VARS) != 0;
204     const std::string name   = genName('a', 'z', m_bufferVarNdx);
205     const glu::VarType type  = generateType(rnd, 0, 0, true, isLastMember && (m_features & FEATURE_UNSIZED_ARRAYS));
206     const bool access        = !unusedOk || (rnd.getFloat() < accessWeight);
207     const bool read          = access ? (rnd.getFloat() < readWeight) : false;
208     const bool write         = access ? (!read || (rnd.getFloat() < writeWeight)) : false;
209     const uint32_t flags     = (read ? ACCESS_READ : 0) | (write ? ACCESS_WRITE : 0);
210 
211     block.addMember(BufferVar(name.c_str(), type, flags));
212 
213     m_bufferVarNdx += 1;
214 }
215 
generateType(de::Random & rnd,int structDepth,int arrayDepth,bool arrayOk,bool unsizedArrayOk)216 glu::VarType RandomSSBOLayoutCase::generateType(de::Random &rnd, int structDepth, int arrayDepth, bool arrayOk,
217                                                 bool unsizedArrayOk)
218 {
219     const float structWeight       = 0.1f;
220     const float arrayWeight        = 0.1f;
221     const float unsizedArrayWeight = 0.8f;
222 
223     DE_ASSERT(arrayOk || !unsizedArrayOk);
224 
225     if (unsizedArrayOk && (rnd.getFloat() < unsizedArrayWeight))
226     {
227         const bool childArrayOk = ((m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0) && (arrayDepth < m_maxArrayDepth);
228         const glu::VarType elementType = generateType(rnd, structDepth, arrayDepth + 1, childArrayOk, false);
229         return glu::VarType(elementType, glu::VarType::UNSIZED_ARRAY);
230     }
231     else if (structDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
232     {
233         // \todo [2013-10-14 pyry] Implement unused flags for members!
234         // bool unusedOk = (m_features & FEATURE_UNUSED_MEMBERS) != 0;
235         vector<glu::VarType> memberTypes;
236         int numMembers = rnd.getInt(1, m_maxStructMembers);
237 
238         // Generate members first so nested struct declarations are in correct order.
239         for (int ndx = 0; ndx < numMembers; ndx++)
240             memberTypes.push_back(
241                 generateType(rnd, structDepth + 1, arrayDepth, (arrayDepth < m_maxArrayDepth), false));
242 
243         glu::StructType &structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
244         m_structNdx += 1;
245 
246         DE_ASSERT(numMembers <= 'Z' - 'A');
247         for (int ndx = 0; ndx < numMembers; ndx++)
248         {
249             structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx]);
250         }
251 
252         return glu::VarType(&structType);
253     }
254     else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
255     {
256         const int arrayLength   = rnd.getInt(1, m_maxArrayLength);
257         const bool childArrayOk = ((m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0) && (arrayDepth < m_maxArrayDepth);
258         const glu::VarType elementType = generateType(rnd, structDepth, arrayDepth + 1, childArrayOk, false);
259 
260         return glu::VarType(elementType, arrayLength);
261     }
262     else
263     {
264         vector<glu::DataType> typeCandidates;
265 
266         typeCandidates.push_back(glu::TYPE_FLOAT);
267         typeCandidates.push_back(glu::TYPE_INT);
268         typeCandidates.push_back(glu::TYPE_UINT);
269         typeCandidates.push_back(glu::TYPE_BOOL);
270 
271         if (m_features & FEATURE_VECTORS)
272         {
273             typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
274             typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
275             typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
276             typeCandidates.push_back(glu::TYPE_INT_VEC2);
277             typeCandidates.push_back(glu::TYPE_INT_VEC3);
278             typeCandidates.push_back(glu::TYPE_INT_VEC4);
279             typeCandidates.push_back(glu::TYPE_UINT_VEC2);
280             typeCandidates.push_back(glu::TYPE_UINT_VEC3);
281             typeCandidates.push_back(glu::TYPE_UINT_VEC4);
282             typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
283             typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
284             typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
285         }
286 
287         if (m_features & FEATURE_MATRICES)
288         {
289             typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
290             typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
291             typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
292             typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
293             typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
294             typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
295             typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
296             typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
297         }
298 
299         glu::DataType type = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
300         glu::Precision precision;
301 
302         if (!glu::isDataTypeBoolOrBVec(type))
303         {
304             // Precision.
305             static const glu::Precision precisionCandidates[] = {glu::PRECISION_LOWP, glu::PRECISION_MEDIUMP,
306                                                                  glu::PRECISION_HIGHP};
307             precision                                         = rnd.choose<glu::Precision>(&precisionCandidates[0],
308                                                    &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
309         }
310         else
311             precision = glu::PRECISION_LAST;
312 
313         return glu::VarType(type, precision);
314     }
315 }
316 
317 class BlockBasicTypeCase : public SSBOLayoutCase
318 {
319 public:
BlockBasicTypeCase(Context & context,const char * name,const char * description,const VarType & type,uint32_t layoutFlags,int numInstances)320     BlockBasicTypeCase(Context &context, const char *name, const char *description, const VarType &type,
321                        uint32_t layoutFlags, int numInstances)
322         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
323                          glu::GLSL_VERSION_310_ES, BUFFERMODE_PER_BLOCK)
324     {
325         BufferBlock &block = m_interface.allocBlock("Block");
326         block.addMember(BufferVar("var", type, ACCESS_READ | ACCESS_WRITE));
327         block.setFlags(layoutFlags);
328 
329         if (numInstances > 0)
330         {
331             block.setArraySize(numInstances);
332             block.setInstanceName("block");
333         }
334     }
335 };
336 
337 class BlockBasicUnsizedArrayCase : public SSBOLayoutCase
338 {
339 public:
BlockBasicUnsizedArrayCase(Context & context,const char * name,const char * description,const VarType & elementType,int arraySize,uint32_t layoutFlags)340     BlockBasicUnsizedArrayCase(Context &context, const char *name, const char *description, const VarType &elementType,
341                                int arraySize, uint32_t layoutFlags)
342         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
343                          glu::GLSL_VERSION_310_ES, BUFFERMODE_PER_BLOCK)
344     {
345         BufferBlock &block = m_interface.allocBlock("Block");
346         block.addMember(BufferVar("var", VarType(elementType, VarType::UNSIZED_ARRAY), ACCESS_READ | ACCESS_WRITE));
347         block.setFlags(layoutFlags);
348 
349         block.setLastUnsizedArraySize(0, arraySize);
350     }
351 };
352 
createRandomCaseGroup(tcu::TestCaseGroup * parentGroup,Context & context,const char * groupName,const char * description,SSBOLayoutCase::BufferMode bufferMode,uint32_t features,int numCases,uint32_t baseSeed)353 static void createRandomCaseGroup(tcu::TestCaseGroup *parentGroup, Context &context, const char *groupName,
354                                   const char *description, SSBOLayoutCase::BufferMode bufferMode, uint32_t features,
355                                   int numCases, uint32_t baseSeed)
356 {
357     tcu::TestCaseGroup *group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description);
358     parentGroup->addChild(group);
359 
360     baseSeed += (uint32_t)context.getTestContext().getCommandLine().getBaseSeed();
361 
362     for (int ndx = 0; ndx < numCases; ndx++)
363         group->addChild(new RandomSSBOLayoutCase(context, de::toString(ndx).c_str(), "", bufferMode, features,
364                                                  (uint32_t)ndx + baseSeed));
365 }
366 
367 class BlockSingleStructCase : public SSBOLayoutCase
368 {
369 public:
BlockSingleStructCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)370     BlockSingleStructCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
371                           BufferMode bufferMode, int numInstances)
372         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
373                          glu::GLSL_VERSION_310_ES, bufferMode)
374         , m_layoutFlags(layoutFlags)
375         , m_numInstances(numInstances)
376     {
377     }
378 
init(void)379     void init(void)
380     {
381         StructType &typeS = m_interface.allocStruct("S");
382         typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP)); // \todo [pyry] First member is unused.
383         typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP), 4));
384         typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
385 
386         BufferBlock &block = m_interface.allocBlock("Block");
387         block.addMember(BufferVar("s", VarType(&typeS), ACCESS_READ | ACCESS_WRITE));
388         block.setFlags(m_layoutFlags);
389 
390         if (m_numInstances > 0)
391         {
392             block.setInstanceName("block");
393             block.setArraySize(m_numInstances);
394         }
395     }
396 
397 private:
398     uint32_t m_layoutFlags;
399     int m_numInstances;
400 };
401 
402 class BlockSingleStructArrayCase : public SSBOLayoutCase
403 {
404 public:
BlockSingleStructArrayCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)405     BlockSingleStructArrayCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
406                                BufferMode bufferMode, int numInstances)
407         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
408                          glu::GLSL_VERSION_310_ES, bufferMode)
409         , m_layoutFlags(layoutFlags)
410         , m_numInstances(numInstances)
411     {
412     }
413 
init(void)414     void init(void)
415     {
416         StructType &typeS = m_interface.allocStruct("S");
417         typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
418         typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP), 4));
419         typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
420 
421         BufferBlock &block = m_interface.allocBlock("Block");
422         block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_LOWP), 0 /* no access */));
423         block.addMember(BufferVar("s", VarType(VarType(&typeS), 3), ACCESS_READ | ACCESS_WRITE));
424         block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
425         block.setFlags(m_layoutFlags);
426 
427         if (m_numInstances > 0)
428         {
429             block.setInstanceName("block");
430             block.setArraySize(m_numInstances);
431         }
432     }
433 
434 private:
435     uint32_t m_layoutFlags;
436     int m_numInstances;
437 };
438 
439 class BlockSingleNestedStructCase : public SSBOLayoutCase
440 {
441 public:
BlockSingleNestedStructCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)442     BlockSingleNestedStructCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
443                                 BufferMode bufferMode, int numInstances)
444         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
445                          glu::GLSL_VERSION_310_ES, bufferMode)
446         , m_layoutFlags(layoutFlags)
447         , m_numInstances(numInstances)
448     {
449     }
450 
init(void)451     void init(void)
452     {
453         StructType &typeS = m_interface.allocStruct("S");
454         typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP));
455         typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP), 4));
456         typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
457 
458         StructType &typeT = m_interface.allocStruct("T");
459         typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP));
460         typeT.addMember("b", VarType(&typeS));
461 
462         BufferBlock &block = m_interface.allocBlock("Block");
463         block.addMember(BufferVar("s", VarType(&typeS), ACCESS_READ));
464         block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_LOWP), 0 /* no access */));
465         block.addMember(BufferVar("t", VarType(&typeT), ACCESS_READ | ACCESS_WRITE));
466         block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP), ACCESS_WRITE));
467         block.setFlags(m_layoutFlags);
468 
469         if (m_numInstances > 0)
470         {
471             block.setInstanceName("block");
472             block.setArraySize(m_numInstances);
473         }
474     }
475 
476 private:
477     uint32_t m_layoutFlags;
478     int m_numInstances;
479 };
480 
481 class BlockSingleNestedStructArrayCase : public SSBOLayoutCase
482 {
483 public:
BlockSingleNestedStructArrayCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)484     BlockSingleNestedStructArrayCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
485                                      BufferMode bufferMode, int numInstances)
486         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
487                          glu::GLSL_VERSION_310_ES, bufferMode)
488         , m_layoutFlags(layoutFlags)
489         , m_numInstances(numInstances)
490     {
491     }
492 
init(void)493     void init(void)
494     {
495         StructType &typeS = m_interface.allocStruct("S");
496         typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP));
497         typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, glu::PRECISION_MEDIUMP), 4));
498         typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
499 
500         StructType &typeT = m_interface.allocStruct("T");
501         typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP));
502         typeT.addMember("b", VarType(VarType(&typeS), 3));
503 
504         BufferBlock &block = m_interface.allocBlock("Block");
505         block.addMember(BufferVar("s", VarType(&typeS), ACCESS_WRITE));
506         block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_LOWP), 0 /* no access */));
507         block.addMember(BufferVar("t", VarType(VarType(&typeT), 2), ACCESS_READ));
508         block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP), ACCESS_READ | ACCESS_WRITE));
509         block.setFlags(m_layoutFlags);
510 
511         if (m_numInstances > 0)
512         {
513             block.setInstanceName("block");
514             block.setArraySize(m_numInstances);
515         }
516     }
517 
518 private:
519     uint32_t m_layoutFlags;
520     int m_numInstances;
521 };
522 
523 class BlockUnsizedStructArrayCase : public SSBOLayoutCase
524 {
525 public:
BlockUnsizedStructArrayCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)526     BlockUnsizedStructArrayCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
527                                 BufferMode bufferMode, int numInstances)
528         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
529                          glu::GLSL_VERSION_310_ES, bufferMode)
530         , m_layoutFlags(layoutFlags)
531         , m_numInstances(numInstances)
532     {
533     }
534 
init(void)535     void init(void)
536     {
537         StructType &typeS = m_interface.allocStruct("S");
538         typeS.addMember("a", VarType(glu::TYPE_UINT_VEC2, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
539         typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2X4, glu::PRECISION_MEDIUMP), 4));
540         typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC3, glu::PRECISION_HIGHP));
541 
542         BufferBlock &block = m_interface.allocBlock("Block");
543         block.addMember(BufferVar("u", VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_LOWP), 0 /* no access */));
544         block.addMember(BufferVar("v", VarType(glu::TYPE_UINT, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
545         block.addMember(BufferVar("s", VarType(VarType(&typeS), VarType::UNSIZED_ARRAY), ACCESS_READ | ACCESS_WRITE));
546         block.setFlags(m_layoutFlags);
547 
548         if (m_numInstances > 0)
549         {
550             block.setInstanceName("block");
551             block.setArraySize(m_numInstances);
552         }
553 
554         {
555             de::Random rnd(246);
556             for (int ndx = 0; ndx < (m_numInstances ? m_numInstances : 1); ndx++)
557             {
558                 const int lastArrayLen = rnd.getInt(1, 5);
559                 block.setLastUnsizedArraySize(ndx, lastArrayLen);
560             }
561         }
562     }
563 
564 private:
565     uint32_t m_layoutFlags;
566     int m_numInstances;
567 };
568 
569 class Block2LevelUnsizedStructArrayCase : public SSBOLayoutCase
570 {
571 public:
Block2LevelUnsizedStructArrayCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)572     Block2LevelUnsizedStructArrayCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
573                                       BufferMode bufferMode, int numInstances)
574         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
575                          glu::GLSL_VERSION_310_ES, bufferMode)
576         , m_layoutFlags(layoutFlags)
577         , m_numInstances(numInstances)
578     {
579     }
580 
init(void)581     void init(void)
582     {
583         StructType &typeS = m_interface.allocStruct("S");
584         typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP));
585         typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
586 
587         BufferBlock &block = m_interface.allocBlock("Block");
588         block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_LOWP), 0 /* no access */));
589         block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
590         block.addMember(
591             BufferVar("s", VarType(VarType(VarType(&typeS), 2), VarType::UNSIZED_ARRAY), ACCESS_READ | ACCESS_WRITE));
592         block.setFlags(m_layoutFlags);
593 
594         if (m_numInstances > 0)
595         {
596             block.setInstanceName("block");
597             block.setArraySize(m_numInstances);
598         }
599 
600         {
601             de::Random rnd(2344);
602             for (int ndx = 0; ndx < (m_numInstances ? m_numInstances : 1); ndx++)
603             {
604                 const int lastArrayLen = rnd.getInt(1, 5);
605                 block.setLastUnsizedArraySize(ndx, lastArrayLen);
606             }
607         }
608     }
609 
610 private:
611     uint32_t m_layoutFlags;
612     int m_numInstances;
613 };
614 
615 class BlockUnsizedNestedStructArrayCase : public SSBOLayoutCase
616 {
617 public:
BlockUnsizedNestedStructArrayCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)618     BlockUnsizedNestedStructArrayCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
619                                       BufferMode bufferMode, int numInstances)
620         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
621                          glu::GLSL_VERSION_310_ES, bufferMode)
622         , m_layoutFlags(layoutFlags)
623         , m_numInstances(numInstances)
624     {
625     }
626 
init(void)627     void init(void)
628     {
629         StructType &typeS = m_interface.allocStruct("S");
630         typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, glu::PRECISION_HIGHP));
631         typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_MEDIUMP), 4));
632         typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
633 
634         StructType &typeT = m_interface.allocStruct("T");
635         typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT4X3, glu::PRECISION_MEDIUMP));
636         typeT.addMember("b", VarType(VarType(&typeS), 3));
637         typeT.addMember("c", VarType(glu::TYPE_INT, glu::PRECISION_HIGHP));
638 
639         BufferBlock &block = m_interface.allocBlock("Block");
640         block.addMember(BufferVar("s", VarType(&typeS), ACCESS_WRITE));
641         block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_LOWP), 0 /* no access */));
642         block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP), ACCESS_READ | ACCESS_WRITE));
643         block.addMember(BufferVar("t", VarType(VarType(&typeT), VarType::UNSIZED_ARRAY), ACCESS_READ));
644         block.setFlags(m_layoutFlags);
645 
646         if (m_numInstances > 0)
647         {
648             block.setInstanceName("block");
649             block.setArraySize(m_numInstances);
650         }
651 
652         {
653             de::Random rnd(7921);
654             for (int ndx = 0; ndx < (m_numInstances ? m_numInstances : 1); ndx++)
655             {
656                 const int lastArrayLen = rnd.getInt(1, 5);
657                 block.setLastUnsizedArraySize(ndx, lastArrayLen);
658             }
659         }
660     }
661 
662 private:
663     uint32_t m_layoutFlags;
664     int m_numInstances;
665 };
666 
667 class BlockMultiBasicTypesCase : public SSBOLayoutCase
668 {
669 public:
BlockMultiBasicTypesCase(Context & context,const char * name,const char * description,uint32_t flagsA,uint32_t flagsB,BufferMode bufferMode,int numInstances)670     BlockMultiBasicTypesCase(Context &context, const char *name, const char *description, uint32_t flagsA,
671                              uint32_t flagsB, BufferMode bufferMode, int numInstances)
672         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
673                          glu::GLSL_VERSION_310_ES, bufferMode)
674         , m_flagsA(flagsA)
675         , m_flagsB(flagsB)
676         , m_numInstances(numInstances)
677     {
678     }
679 
init(void)680     void init(void)
681     {
682         BufferBlock &blockA = m_interface.allocBlock("BlockA");
683         blockA.addMember(BufferVar("a", VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), ACCESS_READ | ACCESS_WRITE));
684         blockA.addMember(BufferVar("b", VarType(glu::TYPE_UINT_VEC3, glu::PRECISION_LOWP), 0 /* no access */));
685         blockA.addMember(BufferVar("c", VarType(glu::TYPE_FLOAT_MAT2, glu::PRECISION_MEDIUMP), ACCESS_READ));
686         blockA.setInstanceName("blockA");
687         blockA.setFlags(m_flagsA);
688 
689         BufferBlock &blockB = m_interface.allocBlock("BlockB");
690         blockB.addMember(BufferVar("a", VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
691         blockB.addMember(BufferVar("b", VarType(glu::TYPE_INT_VEC2, glu::PRECISION_LOWP), ACCESS_READ));
692         blockB.addMember(BufferVar("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), 0 /* no access */));
693         blockB.addMember(BufferVar("d", VarType(glu::TYPE_BOOL, glu::PRECISION_LAST), ACCESS_READ | ACCESS_WRITE));
694         blockB.setInstanceName("blockB");
695         blockB.setFlags(m_flagsB);
696 
697         if (m_numInstances > 0)
698         {
699             blockA.setArraySize(m_numInstances);
700             blockB.setArraySize(m_numInstances);
701         }
702     }
703 
704 private:
705     uint32_t m_flagsA;
706     uint32_t m_flagsB;
707     int m_numInstances;
708 };
709 
710 class BlockMultiNestedStructCase : public SSBOLayoutCase
711 {
712 public:
BlockMultiNestedStructCase(Context & context,const char * name,const char * description,uint32_t flagsA,uint32_t flagsB,BufferMode bufferMode,int numInstances)713     BlockMultiNestedStructCase(Context &context, const char *name, const char *description, uint32_t flagsA,
714                                uint32_t flagsB, BufferMode bufferMode, int numInstances)
715         : SSBOLayoutCase(context.getTestContext(), context.getRenderContext(), name, description,
716                          glu::GLSL_VERSION_310_ES, bufferMode)
717         , m_flagsA(flagsA)
718         , m_flagsB(flagsB)
719         , m_numInstances(numInstances)
720     {
721     }
722 
init(void)723     void init(void)
724     {
725         StructType &typeS = m_interface.allocStruct("S");
726         typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_LOWP));
727         typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, glu::PRECISION_MEDIUMP), 4));
728         typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
729 
730         StructType &typeT = m_interface.allocStruct("T");
731         typeT.addMember("a", VarType(glu::TYPE_UINT, glu::PRECISION_MEDIUMP)); // \todo [pyry] UNUSED
732         typeT.addMember("b", VarType(&typeS));
733         typeT.addMember("c", VarType(glu::TYPE_BOOL_VEC4, glu::PRECISION_LAST));
734 
735         BufferBlock &blockA = m_interface.allocBlock("BlockA");
736         blockA.addMember(BufferVar("a", VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), ACCESS_READ | ACCESS_WRITE));
737         blockA.addMember(BufferVar("b", VarType(&typeS), ACCESS_WRITE));
738         blockA.addMember(BufferVar("c", VarType(glu::TYPE_UINT_VEC3, glu::PRECISION_LOWP), 0 /* no access */));
739         blockA.setInstanceName("blockA");
740         blockA.setFlags(m_flagsA);
741 
742         BufferBlock &blockB = m_interface.allocBlock("BlockB");
743         blockB.addMember(BufferVar("a", VarType(glu::TYPE_FLOAT_MAT2, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
744         blockB.addMember(BufferVar("b", VarType(&typeT), ACCESS_READ | ACCESS_WRITE));
745         blockB.addMember(BufferVar("c", VarType(glu::TYPE_BOOL_VEC4, glu::PRECISION_LAST), 0 /* no access */));
746         blockB.addMember(BufferVar("d", VarType(glu::TYPE_BOOL, glu::PRECISION_LAST), ACCESS_READ | ACCESS_WRITE));
747         blockB.setInstanceName("blockB");
748         blockB.setFlags(m_flagsB);
749 
750         if (m_numInstances > 0)
751         {
752             blockA.setArraySize(m_numInstances);
753             blockB.setArraySize(m_numInstances);
754         }
755     }
756 
757 private:
758     uint32_t m_flagsA;
759     uint32_t m_flagsB;
760     int m_numInstances;
761 };
762 
763 } // namespace
764 
SSBOLayoutTests(Context & context)765 SSBOLayoutTests::SSBOLayoutTests(Context &context) : TestCaseGroup(context, "layout", "SSBO Layout Tests")
766 {
767 }
768 
~SSBOLayoutTests(void)769 SSBOLayoutTests::~SSBOLayoutTests(void)
770 {
771 }
772 
init(void)773 void SSBOLayoutTests::init(void)
774 {
775     static const glu::DataType basicTypes[] = {
776         glu::TYPE_FLOAT,        glu::TYPE_FLOAT_VEC2,   glu::TYPE_FLOAT_VEC3,   glu::TYPE_FLOAT_VEC4,
777         glu::TYPE_INT,          glu::TYPE_INT_VEC2,     glu::TYPE_INT_VEC3,     glu::TYPE_INT_VEC4,
778         glu::TYPE_UINT,         glu::TYPE_UINT_VEC2,    glu::TYPE_UINT_VEC3,    glu::TYPE_UINT_VEC4,
779         glu::TYPE_BOOL,         glu::TYPE_BOOL_VEC2,    glu::TYPE_BOOL_VEC3,    glu::TYPE_BOOL_VEC4,
780         glu::TYPE_FLOAT_MAT2,   glu::TYPE_FLOAT_MAT3,   glu::TYPE_FLOAT_MAT4,   glu::TYPE_FLOAT_MAT2X3,
781         glu::TYPE_FLOAT_MAT2X4, glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2,
782         glu::TYPE_FLOAT_MAT4X3};
783 
784     static const struct
785     {
786         const char *name;
787         uint32_t flags;
788     } layoutFlags[] = {
789         {"shared", LAYOUT_SHARED}, {"packed", LAYOUT_PACKED}, {"std140", LAYOUT_STD140}, {"std430", LAYOUT_STD430}};
790 
791     static const struct
792     {
793         const char *name;
794         uint32_t flags;
795     } matrixFlags[] = {{"row_major", LAYOUT_ROW_MAJOR}, {"column_major", LAYOUT_COLUMN_MAJOR}};
796 
797     static const struct
798     {
799         const char *name;
800         SSBOLayoutCase::BufferMode mode;
801     } bufferModes[] = {{"per_block_buffer", SSBOLayoutCase::BUFFERMODE_PER_BLOCK},
802                        {"single_buffer", SSBOLayoutCase::BUFFERMODE_SINGLE}};
803 
804     // ubo.single_basic_type
805     {
806         tcu::TestCaseGroup *singleBasicTypeGroup =
807             new tcu::TestCaseGroup(m_testCtx, "single_basic_type", "Single basic variable in single buffer");
808         addChild(singleBasicTypeGroup);
809 
810         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
811         {
812             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
813             singleBasicTypeGroup->addChild(layoutGroup);
814 
815             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
816             {
817                 glu::DataType type   = basicTypes[basicTypeNdx];
818                 const char *typeName = glu::getDataTypeName(type);
819 
820                 if (glu::isDataTypeBoolOrBVec(type))
821                     layoutGroup->addChild(new BlockBasicTypeCase(m_context, typeName, "",
822                                                                  VarType(type, glu::PRECISION_LAST),
823                                                                  layoutFlags[layoutFlagNdx].flags, 0));
824                 else
825                 {
826                     for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
827                     {
828                         const glu::Precision precision = glu::Precision(precNdx);
829                         const string caseName          = string(glu::getPrecisionName(precision)) + "_" + typeName;
830 
831                         layoutGroup->addChild(new BlockBasicTypeCase(m_context, caseName.c_str(), "",
832                                                                      VarType(type, precision),
833                                                                      layoutFlags[layoutFlagNdx].flags, 0));
834                     }
835                 }
836 
837                 if (glu::isDataTypeMatrix(type))
838                 {
839                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
840                     {
841                         for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
842                         {
843                             const glu::Precision precision = glu::Precision(precNdx);
844                             const string caseName          = string(matrixFlags[matFlagNdx].name) + "_" +
845                                                     string(glu::getPrecisionName(precision)) + "_" + typeName;
846 
847                             layoutGroup->addChild(new BlockBasicTypeCase(
848                                 m_context, caseName.c_str(), "", glu::VarType(type, precision),
849                                 layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags, 0));
850                         }
851                     }
852                 }
853             }
854         }
855     }
856 
857     // ubo.single_basic_array
858     {
859         tcu::TestCaseGroup *singleBasicArrayGroup =
860             new tcu::TestCaseGroup(m_testCtx, "single_basic_array", "Single basic array variable in single buffer");
861         addChild(singleBasicArrayGroup);
862 
863         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
864         {
865             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
866             singleBasicArrayGroup->addChild(layoutGroup);
867 
868             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
869             {
870                 glu::DataType type   = basicTypes[basicTypeNdx];
871                 const char *typeName = glu::getDataTypeName(type);
872                 const int arraySize  = 3;
873 
874                 layoutGroup->addChild(new BlockBasicTypeCase(
875                     m_context, typeName, "",
876                     VarType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP),
877                             arraySize),
878                     layoutFlags[layoutFlagNdx].flags, 0));
879 
880                 if (glu::isDataTypeMatrix(type))
881                 {
882                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
883                         layoutGroup->addChild(new BlockBasicTypeCase(
884                             m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
885                             VarType(VarType(type, glu::PRECISION_HIGHP), arraySize),
886                             layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags, 0));
887                 }
888             }
889         }
890     }
891 
892     // ubo.basic_unsized_array
893     {
894         tcu::TestCaseGroup *basicUnsizedArray =
895             new tcu::TestCaseGroup(m_testCtx, "basic_unsized_array", "Basic unsized array tests");
896         addChild(basicUnsizedArray);
897 
898         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
899         {
900             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
901             basicUnsizedArray->addChild(layoutGroup);
902 
903             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
904             {
905                 glu::DataType type   = basicTypes[basicTypeNdx];
906                 const char *typeName = glu::getDataTypeName(type);
907                 const int arraySize  = 19;
908 
909                 layoutGroup->addChild(new BlockBasicUnsizedArrayCase(
910                     m_context, typeName, "",
911                     VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP),
912                     arraySize, layoutFlags[layoutFlagNdx].flags));
913 
914                 if (glu::isDataTypeMatrix(type))
915                 {
916                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
917                         layoutGroup->addChild(new BlockBasicUnsizedArrayCase(
918                             m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
919                             VarType(type, glu::PRECISION_HIGHP), arraySize,
920                             layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags));
921                 }
922             }
923         }
924     }
925 
926     // ubo.2_level_array
927     {
928         tcu::TestCaseGroup *nestedArrayGroup =
929             new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level nested array");
930         addChild(nestedArrayGroup);
931 
932         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
933         {
934             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
935             nestedArrayGroup->addChild(layoutGroup);
936 
937             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
938             {
939                 glu::DataType type   = basicTypes[basicTypeNdx];
940                 const char *typeName = glu::getDataTypeName(type);
941                 const int childSize  = 3;
942                 const int parentSize = 4;
943                 const VarType childType(
944                     VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP),
945                     childSize);
946                 const VarType fullType(childType, parentSize);
947 
948                 layoutGroup->addChild(
949                     new BlockBasicTypeCase(m_context, typeName, "", fullType, layoutFlags[layoutFlagNdx].flags, 0));
950 
951                 if (glu::isDataTypeMatrix(type))
952                 {
953                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
954                         layoutGroup->addChild(new BlockBasicTypeCase(
955                             m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "", fullType,
956                             layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags, 0));
957                 }
958             }
959         }
960     }
961 
962     // ubo.3_level_array
963     {
964         tcu::TestCaseGroup *nestedArrayGroup =
965             new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level nested array");
966         addChild(nestedArrayGroup);
967 
968         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
969         {
970             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
971             nestedArrayGroup->addChild(layoutGroup);
972 
973             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
974             {
975                 glu::DataType type   = basicTypes[basicTypeNdx];
976                 const char *typeName = glu::getDataTypeName(type);
977                 const int childSize0 = 3;
978                 const int childSize1 = 2;
979                 const int parentSize = 4;
980                 const VarType childType0(
981                     VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP),
982                     childSize0);
983                 const VarType childType1(childType0, childSize1);
984                 const VarType fullType(childType1, parentSize);
985 
986                 layoutGroup->addChild(
987                     new BlockBasicTypeCase(m_context, typeName, "", fullType, layoutFlags[layoutFlagNdx].flags, 0));
988 
989                 if (glu::isDataTypeMatrix(type))
990                 {
991                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
992                         layoutGroup->addChild(new BlockBasicTypeCase(
993                             m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "", fullType,
994                             layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags, 0));
995                 }
996             }
997         }
998     }
999 
1000     // ubo.3_level_unsized_array
1001     {
1002         tcu::TestCaseGroup *nestedArrayGroup =
1003             new tcu::TestCaseGroup(m_testCtx, "3_level_unsized_array", "3-level nested array, top-level array unsized");
1004         addChild(nestedArrayGroup);
1005 
1006         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1007         {
1008             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1009             nestedArrayGroup->addChild(layoutGroup);
1010 
1011             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1012             {
1013                 glu::DataType type   = basicTypes[basicTypeNdx];
1014                 const char *typeName = glu::getDataTypeName(type);
1015                 const int childSize0 = 2;
1016                 const int childSize1 = 4;
1017                 const int parentSize = 3;
1018                 const VarType childType0(
1019                     VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP),
1020                     childSize0);
1021                 const VarType childType1(childType0, childSize1);
1022 
1023                 layoutGroup->addChild(new BlockBasicUnsizedArrayCase(m_context, typeName, "", childType1, parentSize,
1024                                                                      layoutFlags[layoutFlagNdx].flags));
1025 
1026                 if (glu::isDataTypeMatrix(type))
1027                 {
1028                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1029                         layoutGroup->addChild(new BlockBasicUnsizedArrayCase(
1030                             m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "", childType1,
1031                             parentSize, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags));
1032                 }
1033             }
1034         }
1035     }
1036 
1037     // ubo.single_struct
1038     {
1039         tcu::TestCaseGroup *singleStructGroup =
1040             new tcu::TestCaseGroup(m_testCtx, "single_struct", "Single struct in uniform block");
1041         addChild(singleStructGroup);
1042 
1043         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1044         {
1045             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1046             singleStructGroup->addChild(modeGroup);
1047 
1048             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1049             {
1050                 for (int isArray = 0; isArray < 2; isArray++)
1051                 {
1052                     const uint32_t caseFlags = layoutFlags[layoutFlagNdx].flags;
1053                     string caseName          = layoutFlags[layoutFlagNdx].name;
1054 
1055                     if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1056                         continue; // Doesn't make sense to add this variant.
1057 
1058                     if (isArray)
1059                         caseName += "_instance_array";
1060 
1061                     modeGroup->addChild(new BlockSingleStructCase(m_context, caseName.c_str(), "", caseFlags,
1062                                                                   bufferModes[modeNdx].mode, isArray ? 3 : 0));
1063                 }
1064             }
1065         }
1066     }
1067 
1068     // ubo.single_struct_array
1069     {
1070         tcu::TestCaseGroup *singleStructArrayGroup =
1071             new tcu::TestCaseGroup(m_testCtx, "single_struct_array", "Struct array in one uniform block");
1072         addChild(singleStructArrayGroup);
1073 
1074         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1075         {
1076             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1077             singleStructArrayGroup->addChild(modeGroup);
1078 
1079             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1080             {
1081                 for (int isArray = 0; isArray < 2; isArray++)
1082                 {
1083                     std::string baseName = layoutFlags[layoutFlagNdx].name;
1084                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
1085 
1086                     if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1087                         continue; // Doesn't make sense to add this variant.
1088 
1089                     if (isArray)
1090                         baseName += "_instance_array";
1091 
1092                     modeGroup->addChild(new BlockSingleStructArrayCase(m_context, baseName.c_str(), "", baseFlags,
1093                                                                        bufferModes[modeNdx].mode, isArray ? 3 : 0));
1094                 }
1095             }
1096         }
1097     }
1098 
1099     // ubo.single_nested_struct
1100     {
1101         tcu::TestCaseGroup *singleNestedStructGroup =
1102             new tcu::TestCaseGroup(m_testCtx, "single_nested_struct", "Nested struct in one uniform block");
1103         addChild(singleNestedStructGroup);
1104 
1105         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1106         {
1107             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1108             singleNestedStructGroup->addChild(modeGroup);
1109 
1110             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1111             {
1112                 for (int isArray = 0; isArray < 2; isArray++)
1113                 {
1114                     std::string baseName = layoutFlags[layoutFlagNdx].name;
1115                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
1116 
1117                     if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1118                         continue; // Doesn't make sense to add this variant.
1119 
1120                     if (isArray)
1121                         baseName += "_instance_array";
1122 
1123                     modeGroup->addChild(new BlockSingleNestedStructCase(m_context, baseName.c_str(), "", baseFlags,
1124                                                                         bufferModes[modeNdx].mode, isArray ? 3 : 0));
1125                 }
1126             }
1127         }
1128     }
1129 
1130     // ubo.single_nested_struct_array
1131     {
1132         tcu::TestCaseGroup *singleNestedStructArrayGroup =
1133             new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array", "Nested struct array in one uniform block");
1134         addChild(singleNestedStructArrayGroup);
1135 
1136         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1137         {
1138             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1139             singleNestedStructArrayGroup->addChild(modeGroup);
1140 
1141             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1142             {
1143                 for (int isArray = 0; isArray < 2; isArray++)
1144                 {
1145                     std::string baseName = layoutFlags[layoutFlagNdx].name;
1146                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
1147 
1148                     if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1149                         continue; // Doesn't make sense to add this variant.
1150 
1151                     if (isArray)
1152                         baseName += "_instance_array";
1153 
1154                     modeGroup->addChild(new BlockSingleNestedStructArrayCase(
1155                         m_context, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1156                 }
1157             }
1158         }
1159     }
1160 
1161     // ubo.unsized_struct_array
1162     {
1163         tcu::TestCaseGroup *singleStructArrayGroup =
1164             new tcu::TestCaseGroup(m_testCtx, "unsized_struct_array", "Unsized struct array in one uniform block");
1165         addChild(singleStructArrayGroup);
1166 
1167         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1168         {
1169             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1170             singleStructArrayGroup->addChild(modeGroup);
1171 
1172             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1173             {
1174                 for (int isArray = 0; isArray < 2; isArray++)
1175                 {
1176                     std::string baseName = layoutFlags[layoutFlagNdx].name;
1177                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
1178 
1179                     if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1180                         continue; // Doesn't make sense to add this variant.
1181 
1182                     if (isArray)
1183                         baseName += "_instance_array";
1184 
1185                     modeGroup->addChild(new BlockUnsizedStructArrayCase(m_context, baseName.c_str(), "", baseFlags,
1186                                                                         bufferModes[modeNdx].mode, isArray ? 3 : 0));
1187                 }
1188             }
1189         }
1190     }
1191 
1192     // ubo.2_level_unsized_struct_array
1193     {
1194         tcu::TestCaseGroup *structArrayGroup = new tcu::TestCaseGroup(
1195             m_testCtx, "2_level_unsized_struct_array", "Unsized 2-level struct array in one uniform block");
1196         addChild(structArrayGroup);
1197 
1198         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1199         {
1200             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1201             structArrayGroup->addChild(modeGroup);
1202 
1203             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1204             {
1205                 for (int isArray = 0; isArray < 2; isArray++)
1206                 {
1207                     std::string baseName = layoutFlags[layoutFlagNdx].name;
1208                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
1209 
1210                     if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1211                         continue; // Doesn't make sense to add this variant.
1212 
1213                     if (isArray)
1214                         baseName += "_instance_array";
1215 
1216                     modeGroup->addChild(new Block2LevelUnsizedStructArrayCase(
1217                         m_context, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1218                 }
1219             }
1220         }
1221     }
1222 
1223     // ubo.unsized_nested_struct_array
1224     {
1225         tcu::TestCaseGroup *singleNestedStructArrayGroup = new tcu::TestCaseGroup(
1226             m_testCtx, "unsized_nested_struct_array", "Unsized, nested struct array in one uniform block");
1227         addChild(singleNestedStructArrayGroup);
1228 
1229         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1230         {
1231             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1232             singleNestedStructArrayGroup->addChild(modeGroup);
1233 
1234             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1235             {
1236                 for (int isArray = 0; isArray < 2; isArray++)
1237                 {
1238                     std::string baseName = layoutFlags[layoutFlagNdx].name;
1239                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
1240 
1241                     if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1242                         continue; // Doesn't make sense to add this variant.
1243 
1244                     if (isArray)
1245                         baseName += "_instance_array";
1246 
1247                     modeGroup->addChild(new BlockUnsizedNestedStructArrayCase(
1248                         m_context, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0));
1249                 }
1250             }
1251         }
1252     }
1253 
1254     // ubo.instance_array_basic_type
1255     {
1256         tcu::TestCaseGroup *instanceArrayBasicTypeGroup =
1257             new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type", "Single basic variable in instance array");
1258         addChild(instanceArrayBasicTypeGroup);
1259 
1260         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1261         {
1262             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1263             instanceArrayBasicTypeGroup->addChild(layoutGroup);
1264 
1265             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1266             {
1267                 glu::DataType type     = basicTypes[basicTypeNdx];
1268                 const char *typeName   = glu::getDataTypeName(type);
1269                 const int numInstances = 3;
1270 
1271                 layoutGroup->addChild(new BlockBasicTypeCase(
1272                     m_context, typeName, "",
1273                     VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP),
1274                     layoutFlags[layoutFlagNdx].flags, numInstances));
1275 
1276                 if (glu::isDataTypeMatrix(type))
1277                 {
1278                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1279                         layoutGroup->addChild(new BlockBasicTypeCase(
1280                             m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
1281                             VarType(type, glu::PRECISION_HIGHP),
1282                             layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags, numInstances));
1283                 }
1284             }
1285         }
1286     }
1287 
1288     // ubo.multi_basic_types
1289     {
1290         tcu::TestCaseGroup *multiBasicTypesGroup =
1291             new tcu::TestCaseGroup(m_testCtx, "multi_basic_types", "Multiple buffers with basic types");
1292         addChild(multiBasicTypesGroup);
1293 
1294         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1295         {
1296             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1297             multiBasicTypesGroup->addChild(modeGroup);
1298 
1299             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1300             {
1301                 for (int isArray = 0; isArray < 2; isArray++)
1302                 {
1303                     std::string baseName = layoutFlags[layoutFlagNdx].name;
1304                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
1305 
1306                     if (isArray)
1307                         baseName += "_instance_array";
1308 
1309                     modeGroup->addChild(new BlockMultiBasicTypesCase(m_context, baseName.c_str(), "", baseFlags,
1310                                                                      baseFlags, bufferModes[modeNdx].mode,
1311                                                                      isArray ? 3 : 0));
1312                 }
1313             }
1314         }
1315     }
1316 
1317     // ubo.multi_nested_struct
1318     {
1319         tcu::TestCaseGroup *multiNestedStructGroup =
1320             new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct", "Multiple buffers with nested structs");
1321         addChild(multiNestedStructGroup);
1322 
1323         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1324         {
1325             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1326             multiNestedStructGroup->addChild(modeGroup);
1327 
1328             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1329             {
1330                 for (int isArray = 0; isArray < 2; isArray++)
1331                 {
1332                     std::string baseName = layoutFlags[layoutFlagNdx].name;
1333                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
1334 
1335                     if (isArray)
1336                         baseName += "_instance_array";
1337 
1338                     modeGroup->addChild(new BlockMultiNestedStructCase(m_context, baseName.c_str(), "", baseFlags,
1339                                                                        baseFlags, bufferModes[modeNdx].mode,
1340                                                                        isArray ? 3 : 0));
1341                 }
1342             }
1343         }
1344     }
1345 
1346     // ubo.random
1347     {
1348         const uint32_t allLayouts    = FEATURE_PACKED_LAYOUT | FEATURE_SHARED_LAYOUT | FEATURE_STD140_LAYOUT;
1349         const uint32_t allBasicTypes = FEATURE_VECTORS | FEATURE_MATRICES;
1350         const uint32_t unused        = FEATURE_UNUSED_MEMBERS | FEATURE_UNUSED_VARS;
1351         const uint32_t unsized       = FEATURE_UNSIZED_ARRAYS;
1352         const uint32_t matFlags      = FEATURE_MATRIX_LAYOUT;
1353 
1354         tcu::TestCaseGroup *randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
1355         addChild(randomGroup);
1356 
1357         // Basic types.
1358         createRandomCaseGroup(randomGroup, m_context, "scalar_types", "Scalar types only, per-block buffers",
1359                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK, allLayouts | unused, 25, 0);
1360         createRandomCaseGroup(randomGroup, m_context, "vector_types", "Scalar and vector types only, per-block buffers",
1361                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK, allLayouts | unused | FEATURE_VECTORS, 25, 25);
1362         createRandomCaseGroup(randomGroup, m_context, "basic_types", "All basic types, per-block buffers",
1363                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK, allLayouts | unused | allBasicTypes | matFlags, 25,
1364                               50);
1365         createRandomCaseGroup(randomGroup, m_context, "basic_arrays", "Arrays, per-block buffers",
1366                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK,
1367                               allLayouts | unused | allBasicTypes | matFlags | FEATURE_ARRAYS, 25, 50);
1368         createRandomCaseGroup(randomGroup, m_context, "unsized_arrays", "Unsized arrays, per-block buffers",
1369                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK,
1370                               allLayouts | unused | allBasicTypes | matFlags | unsized | FEATURE_ARRAYS, 25, 50);
1371         createRandomCaseGroup(randomGroup, m_context, "arrays_of_arrays", "Arrays of arrays, per-block buffers",
1372                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK,
1373                               allLayouts | unused | allBasicTypes | matFlags | unsized | FEATURE_ARRAYS |
1374                                   FEATURE_ARRAYS_OF_ARRAYS,
1375                               25, 950);
1376 
1377         createRandomCaseGroup(randomGroup, m_context, "basic_instance_arrays",
1378                               "Basic instance arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK,
1379                               allLayouts | unused | allBasicTypes | matFlags | unsized | FEATURE_INSTANCE_ARRAYS, 25,
1380                               75);
1381         createRandomCaseGroup(randomGroup, m_context, "nested_structs", "Nested structs, per-block buffers",
1382                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK,
1383                               allLayouts | unused | allBasicTypes | matFlags | unsized | FEATURE_STRUCTS, 25, 100);
1384         createRandomCaseGroup(randomGroup, m_context, "nested_structs_arrays",
1385                               "Nested structs, arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK,
1386                               allLayouts | unused | allBasicTypes | matFlags | unsized | FEATURE_STRUCTS |
1387                                   FEATURE_ARRAYS | FEATURE_ARRAYS_OF_ARRAYS,
1388                               25, 150);
1389         createRandomCaseGroup(
1390             randomGroup, m_context, "nested_structs_instance_arrays",
1391             "Nested structs, instance arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK,
1392             allLayouts | unused | allBasicTypes | matFlags | unsized | FEATURE_STRUCTS | FEATURE_INSTANCE_ARRAYS, 25,
1393             125);
1394         createRandomCaseGroup(randomGroup, m_context, "nested_structs_arrays_instance_arrays",
1395                               "Nested structs, instance arrays, per-block buffers",
1396                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK,
1397                               allLayouts | unused | allBasicTypes | matFlags | unsized | FEATURE_STRUCTS |
1398                                   FEATURE_ARRAYS | FEATURE_ARRAYS_OF_ARRAYS | FEATURE_INSTANCE_ARRAYS,
1399                               25, 175);
1400 
1401         createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers", "All random features, per-block buffers",
1402                               SSBOLayoutCase::BUFFERMODE_PER_BLOCK, ~0u, 50, 200);
1403         createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer", "All random features, shared buffer",
1404                               SSBOLayoutCase::BUFFERMODE_SINGLE, ~0u, 50, 250);
1405     }
1406 }
1407 
1408 } // namespace Functional
1409 } // namespace gles31
1410 } // namespace deqp
1411