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