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