1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief SSBO layout tests.
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktSSBOLayoutTests.hpp"
27 #include "vktSSBOLayoutCase.hpp"
28
29 #include "deUniquePtr.hpp"
30 #include "tcuCommandLine.hpp"
31 #include "tcuTestLog.hpp"
32 #include "deRandom.hpp"
33 #include "deStringUtil.hpp"
34 #include "deString.h"
35 #include "vktTestCaseUtil.hpp"
36 #include "vktTestGroupUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkQueryUtil.hpp"
42 #include "vkMemUtil.hpp"
43 #include "vkTypeUtil.hpp"
44 #include "vkCmdUtil.hpp"
45
46 namespace vkt
47 {
48 namespace ssbo
49 {
50 namespace
51 {
52
53 using std::string;
54 using std::vector;
55 using glu::VarType;
56 using glu::StructType;
57 using namespace vk;
58
59 enum FeatureBits
60 {
61 FEATURE_VECTORS = (1<<0),
62 FEATURE_MATRICES = (1<<1),
63 FEATURE_ARRAYS = (1<<2),
64 FEATURE_STRUCTS = (1<<3),
65 FEATURE_NESTED_STRUCTS = (1<<4),
66 FEATURE_INSTANCE_ARRAYS = (1<<5),
67 FEATURE_UNUSED_VARS = (1<<6),
68 FEATURE_UNUSED_MEMBERS = (1<<7),
69 FEATURE_STD140_LAYOUT = (1<<8),
70 FEATURE_STD430_LAYOUT = (1<<9),
71 FEATURE_MATRIX_LAYOUT = (1<<10), //!< Matrix layout flags.
72 FEATURE_UNSIZED_ARRAYS = (1<<11),
73 FEATURE_ARRAYS_OF_ARRAYS = (1<<12),
74 FEATURE_RELAXED_LAYOUT = (1<<13),
75 FEATURE_16BIT_STORAGE = (1<<14),
76 FEATURE_8BIT_STORAGE = (1<<15),
77 FEATURE_SCALAR_LAYOUT = (1<<16),
78 };
79
80 class RandomSSBOLayoutCase : public SSBOLayoutCase
81 {
82 public:
83
84 RandomSSBOLayoutCase (tcu::TestContext& testCtx, const char* name, const char* description, BufferMode bufferMode, deUint32 features, deUint32 seed);
85
86 private:
87 void generateBlock (de::Random& rnd, deUint32 layoutFlags);
88 void generateBufferVar (de::Random& rnd, BufferBlock& block, bool isLastMember);
89 glu::VarType generateType (de::Random& rnd, int typeDepth, bool arrayOk, bool unusedArrayOk);
90
91 deUint32 m_features;
92 int m_maxBlocks;
93 int m_maxInstances;
94 int m_maxArrayLength;
95 int m_maxStructDepth;
96 int m_maxBlockMembers;
97 int m_maxStructMembers;
98 deUint32 m_seed;
99
100 int m_blockNdx;
101 int m_bufferVarNdx;
102 int m_structNdx;
103 };
104
RandomSSBOLayoutCase(tcu::TestContext & testCtx,const char * name,const char * description,BufferMode bufferMode,deUint32 features,deUint32 seed)105 RandomSSBOLayoutCase::RandomSSBOLayoutCase (tcu::TestContext& testCtx, const char* name, const char* description, BufferMode bufferMode, deUint32 features, deUint32 seed)
106 : SSBOLayoutCase (testCtx, name, description, bufferMode, LOAD_FULL_MATRIX)
107 , m_features (features)
108 , m_maxBlocks (4)
109 , m_maxInstances ((features & FEATURE_INSTANCE_ARRAYS) ? 3 : 0)
110 , m_maxArrayLength ((features & FEATURE_ARRAYS) ? 8 : 1)
111 , m_maxStructDepth ((features & FEATURE_STRUCTS) ? 2 : 0)
112 , m_maxBlockMembers (5)
113 , m_maxStructMembers (4)
114 , m_seed (seed)
115 , m_blockNdx (1)
116 , m_bufferVarNdx (1)
117 , m_structNdx (1)
118 {
119 de::Random rnd(m_seed);
120
121 const int numBlocks = rnd.getInt(1, m_maxBlocks);
122
123 for (int ndx = 0; ndx < numBlocks; ndx++)
124 generateBlock(rnd, 0);
125
126 init();
127 }
128
generateBlock(de::Random & rnd,deUint32 layoutFlags)129 void RandomSSBOLayoutCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
130 {
131 DE_ASSERT(m_blockNdx <= 'z' - 'a');
132
133 const float instanceArrayWeight = 0.3f;
134 BufferBlock& block = m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
135 int numInstances = (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
136 int numVars = rnd.getInt(1, m_maxBlockMembers);
137
138 if (numInstances > 0)
139 block.setArraySize(numInstances);
140
141 if (numInstances > 0 || rnd.getBool())
142 block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
143
144 // Layout flag candidates.
145 vector<deUint32> layoutFlagCandidates;
146
147 if (m_features & FEATURE_STD430_LAYOUT)
148 layoutFlagCandidates.push_back(LAYOUT_STD430);
149
150 if (m_features & FEATURE_STD140_LAYOUT)
151 layoutFlagCandidates.push_back(LAYOUT_STD140);
152
153 if (m_features & FEATURE_RELAXED_LAYOUT)
154 layoutFlagCandidates.push_back(LAYOUT_RELAXED);
155
156 if (m_features & FEATURE_16BIT_STORAGE)
157 layoutFlags |= LAYOUT_16BIT_STORAGE;
158
159 if (m_features & FEATURE_8BIT_STORAGE)
160 layoutFlags |= LAYOUT_8BIT_STORAGE;
161
162 if (m_features & FEATURE_SCALAR_LAYOUT)
163 layoutFlagCandidates.push_back(LAYOUT_SCALAR);
164
165 DE_ASSERT(!layoutFlagCandidates.empty());
166
167 layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
168
169 if (m_features & FEATURE_MATRIX_LAYOUT)
170 {
171 static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
172 layoutFlags |= rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
173 }
174
175 block.setFlags(layoutFlags);
176
177 for (int ndx = 0; ndx < numVars; ndx++)
178 generateBufferVar(rnd, block, (ndx+1 == numVars));
179
180 if (numVars > 0)
181 {
182 const BufferVar& lastVar = *(block.end()-1);
183 const glu::VarType& lastType = lastVar.getType();
184 const bool isUnsizedArr = lastType.isArrayType() && (lastType.getArraySize() == glu::VarType::UNSIZED_ARRAY);
185
186 if (isUnsizedArr)
187 {
188 for (int instanceNdx = 0; instanceNdx < (numInstances ? numInstances : 1); instanceNdx++)
189 {
190 const int arrSize = rnd.getInt(1, m_maxArrayLength);
191 block.setLastUnsizedArraySize(instanceNdx, arrSize);
192 }
193 }
194 }
195
196 m_blockNdx += 1;
197 }
198
genName(char first,char last,int ndx)199 static std::string genName (char first, char last, int ndx)
200 {
201 std::string str = "";
202 int alphabetLen = last - first + 1;
203
204 while (ndx > alphabetLen)
205 {
206 str.insert(str.begin(), (char)(first + ((ndx-1)%alphabetLen)));
207 ndx = ((ndx-1) / alphabetLen);
208 }
209
210 str.insert(str.begin(), (char)(first + (ndx%(alphabetLen+1)) - 1));
211
212 return str;
213 }
214
generateBufferVar(de::Random & rnd,BufferBlock & block,bool isLastMember)215 void RandomSSBOLayoutCase::generateBufferVar (de::Random& rnd, BufferBlock& block, bool isLastMember)
216 {
217 const float readWeight = 0.7f;
218 const float writeWeight = 0.7f;
219 const float accessWeight = 0.85f;
220 const bool unusedOk = (m_features & FEATURE_UNUSED_VARS) != 0;
221 const std::string name = genName('a', 'z', m_bufferVarNdx);
222 const glu::VarType type = generateType(rnd, 0, true, isLastMember && (m_features & FEATURE_UNSIZED_ARRAYS));
223 const bool access = !unusedOk || (rnd.getFloat() < accessWeight);
224 const bool read = access ? (rnd.getFloat() < readWeight) : false;
225 const bool write = access ? (!read || (rnd.getFloat() < writeWeight)) : false;
226 const deUint32 flags = (read ? ACCESS_READ : 0) | (write ? ACCESS_WRITE : 0);
227
228 block.addMember(BufferVar(name.c_str(), type, flags));
229
230 m_bufferVarNdx += 1;
231 }
232
generateType(de::Random & rnd,int typeDepth,bool arrayOk,bool unsizedArrayOk)233 glu::VarType RandomSSBOLayoutCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk, bool unsizedArrayOk)
234 {
235 const float structWeight = 0.1f;
236 const float arrayWeight = 0.1f;
237 const float unsizedArrayWeight = 0.8f;
238
239 DE_ASSERT(arrayOk || !unsizedArrayOk);
240
241 if (unsizedArrayOk && (rnd.getFloat() < unsizedArrayWeight))
242 {
243 const bool childArrayOk = (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
244 const glu::VarType elementType = generateType(rnd, typeDepth, childArrayOk, false);
245 return glu::VarType(elementType, glu::VarType::UNSIZED_ARRAY);
246 }
247 else if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
248 {
249 vector<glu::VarType> memberTypes;
250 int numMembers = rnd.getInt(1, m_maxStructMembers);
251
252 // Generate members first so nested struct declarations are in correct order.
253 for (int ndx = 0; ndx < numMembers; ndx++)
254 memberTypes.push_back(generateType(rnd, typeDepth+1, true, false));
255
256 glu::StructType& structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
257 m_structNdx += 1;
258
259 DE_ASSERT(numMembers <= 'Z' - 'A');
260 for (int ndx = 0; ndx < numMembers; ndx++)
261 {
262 structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx]);
263 }
264
265 return glu::VarType(&structType);
266 }
267 else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
268 {
269 const int arrayLength = rnd.getInt(1, m_maxArrayLength);
270 const bool childArrayOk = (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
271 const glu::VarType elementType = generateType(rnd, typeDepth, childArrayOk, false);
272
273 return glu::VarType(elementType, arrayLength);
274 }
275 else
276 {
277 vector<glu::DataType> typeCandidates;
278
279 typeCandidates.push_back(glu::TYPE_FLOAT);
280 typeCandidates.push_back(glu::TYPE_INT);
281 typeCandidates.push_back(glu::TYPE_UINT);
282 typeCandidates.push_back(glu::TYPE_BOOL);
283
284 if (m_features & FEATURE_16BIT_STORAGE)
285 {
286 typeCandidates.push_back(glu::TYPE_UINT16);
287 typeCandidates.push_back(glu::TYPE_INT16);
288 typeCandidates.push_back(glu::TYPE_FLOAT16);
289 }
290
291 if (m_features & FEATURE_8BIT_STORAGE)
292 {
293 typeCandidates.push_back(glu::TYPE_UINT8);
294 typeCandidates.push_back(glu::TYPE_INT8);
295 }
296
297 if (m_features & FEATURE_VECTORS)
298 {
299 typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
300 typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
301 typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
302 typeCandidates.push_back(glu::TYPE_INT_VEC2);
303 typeCandidates.push_back(glu::TYPE_INT_VEC3);
304 typeCandidates.push_back(glu::TYPE_INT_VEC4);
305 typeCandidates.push_back(glu::TYPE_UINT_VEC2);
306 typeCandidates.push_back(glu::TYPE_UINT_VEC3);
307 typeCandidates.push_back(glu::TYPE_UINT_VEC4);
308 typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
309 typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
310 typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
311 if (m_features & FEATURE_16BIT_STORAGE)
312 {
313 typeCandidates.push_back(glu::TYPE_FLOAT16_VEC2);
314 typeCandidates.push_back(glu::TYPE_FLOAT16_VEC3);
315 typeCandidates.push_back(glu::TYPE_FLOAT16_VEC4);
316 typeCandidates.push_back(glu::TYPE_INT16_VEC2);
317 typeCandidates.push_back(glu::TYPE_INT16_VEC3);
318 typeCandidates.push_back(glu::TYPE_INT16_VEC4);
319 typeCandidates.push_back(glu::TYPE_UINT16_VEC2);
320 typeCandidates.push_back(glu::TYPE_UINT16_VEC3);
321 typeCandidates.push_back(glu::TYPE_UINT16_VEC4);
322 }
323 if (m_features & FEATURE_8BIT_STORAGE)
324 {
325 typeCandidates.push_back(glu::TYPE_INT8_VEC2);
326 typeCandidates.push_back(glu::TYPE_INT8_VEC3);
327 typeCandidates.push_back(glu::TYPE_INT8_VEC4);
328 typeCandidates.push_back(glu::TYPE_UINT8_VEC2);
329 typeCandidates.push_back(glu::TYPE_UINT8_VEC3);
330 typeCandidates.push_back(glu::TYPE_UINT8_VEC4);
331 }
332 }
333
334 if (m_features & FEATURE_MATRICES)
335 {
336 typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
337 typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
338 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
339 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
340 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
341 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
342 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
343 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
344 }
345
346 glu::DataType type = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
347 glu::Precision precision;
348
349 if (glu::dataTypeSupportsPrecisionModifier(type))
350 {
351 // Precision.
352 static const glu::Precision precisionCandidates[] = { glu::PRECISION_LOWP, glu::PRECISION_MEDIUMP, glu::PRECISION_HIGHP };
353 precision = rnd.choose<glu::Precision>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
354 }
355 else
356 precision = glu::PRECISION_LAST;
357
358 return glu::VarType(type, precision);
359 }
360 }
361
362 class BlockBasicTypeCase : public SSBOLayoutCase
363 {
364 public:
BlockBasicTypeCase(tcu::TestContext & testCtx,const char * name,const char * description,const VarType & type,deUint32 layoutFlags,int numInstances,MatrixLoadFlags matrixLoadFlag)365 BlockBasicTypeCase (tcu::TestContext& testCtx, const char* name, const char* description, const VarType& type, deUint32 layoutFlags, int numInstances, MatrixLoadFlags matrixLoadFlag)
366 : SSBOLayoutCase(testCtx, name, description, BUFFERMODE_PER_BLOCK, matrixLoadFlag)
367 {
368 VarType tempType = type;
369 while (tempType.isArrayType())
370 {
371 tempType = tempType.getElementType();
372 }
373 if (getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_UINT16 ||
374 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_INT16 ||
375 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_FLOAT16)
376 {
377 layoutFlags |= LAYOUT_16BIT_STORAGE;
378 }
379 if (getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_UINT8 ||
380 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_INT8)
381 {
382 layoutFlags |= LAYOUT_8BIT_STORAGE;
383 }
384
385 BufferBlock& block = m_interface.allocBlock("Block");
386 // For scalar layout tests with non-scalar types, add a scalar padding variable
387 // before "var", to make var only be scalar aligned.
388 if ((layoutFlags & LAYOUT_SCALAR) && !(type.isBasicType() && isDataTypeScalar(type.getBasicType()))) {
389 block.addMember(BufferVar("padding", VarType(getDataTypeScalarType(tempType.getBasicType()), glu::PRECISION_LAST), ACCESS_READ|ACCESS_WRITE));
390 }
391 block.addMember(BufferVar("var", type, ACCESS_READ|ACCESS_WRITE));
392
393 block.setFlags(layoutFlags);
394
395 if (numInstances > 0)
396 {
397 block.setArraySize(numInstances);
398 block.setInstanceName("block");
399 }
400
401 init();
402 }
403 };
404
405 class BlockBasicUnsizedArrayCase : public SSBOLayoutCase
406 {
407 public:
BlockBasicUnsizedArrayCase(tcu::TestContext & testCtx,const char * name,const char * description,const VarType & elementType,int arraySize,deUint32 layoutFlags,MatrixLoadFlags matrixLoadFlag)408 BlockBasicUnsizedArrayCase (tcu::TestContext& testCtx, const char* name, const char* description, const VarType& elementType, int arraySize, deUint32 layoutFlags, MatrixLoadFlags matrixLoadFlag)
409 : SSBOLayoutCase(testCtx, name, description, BUFFERMODE_PER_BLOCK, matrixLoadFlag)
410 {
411 BufferBlock& block = m_interface.allocBlock("Block");
412 block.addMember(BufferVar("var", VarType(elementType, VarType::UNSIZED_ARRAY), ACCESS_READ|ACCESS_WRITE));
413
414 VarType tempType = elementType;
415 while (tempType.isArrayType())
416 {
417 tempType = tempType.getElementType();
418 }
419 if (getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_UINT16 ||
420 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_INT16 ||
421 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_FLOAT16)
422 {
423 layoutFlags |= LAYOUT_16BIT_STORAGE;
424 }
425 if (getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_UINT8 ||
426 getDataTypeScalarType(tempType.getBasicType()) == glu::TYPE_INT8)
427 {
428 layoutFlags |= LAYOUT_8BIT_STORAGE;
429 }
430
431 block.setFlags(layoutFlags);
432
433 block.setLastUnsizedArraySize(0, arraySize);
434
435 init();
436 }
437 };
438
createRandomCaseGroup(tcu::TestCaseGroup * parentGroup,tcu::TestContext & testCtx,const char * groupName,const char * description,SSBOLayoutCase::BufferMode bufferMode,deUint32 features,int numCases,deUint32 baseSeed)439 static void createRandomCaseGroup (tcu::TestCaseGroup* parentGroup, tcu::TestContext& testCtx, const char* groupName, const char* description, SSBOLayoutCase::BufferMode bufferMode, deUint32 features, int numCases, deUint32 baseSeed)
440 {
441 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(testCtx, groupName, description);
442 parentGroup->addChild(group);
443
444 baseSeed += (deUint32)testCtx.getCommandLine().getBaseSeed();
445
446 for (int ndx = 0; ndx < numCases; ndx++)
447 group->addChild(new RandomSSBOLayoutCase(testCtx, de::toString(ndx).c_str(), "", bufferMode, features, (deUint32)ndx+baseSeed));
448 }
449
450 class BlockSingleStructCase : public SSBOLayoutCase
451 {
452 public:
BlockSingleStructCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)453 BlockSingleStructCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
454 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
455 , m_layoutFlags (layoutFlags)
456 , m_numInstances (numInstances)
457 {
458 StructType& typeS = m_interface.allocStruct("S");
459 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP)); // \todo [pyry] First member is unused.
460 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP), 4));
461 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
462
463 BufferBlock& block = m_interface.allocBlock("Block");
464 block.addMember(BufferVar("s", VarType(&typeS), ACCESS_READ|ACCESS_WRITE));
465 block.setFlags(m_layoutFlags);
466
467 if (m_numInstances > 0)
468 {
469 block.setInstanceName("block");
470 block.setArraySize(m_numInstances);
471 }
472
473 init();
474 }
475
476 private:
477 deUint32 m_layoutFlags;
478 int m_numInstances;
479 };
480
481 class BlockSingleStructArrayCase : public SSBOLayoutCase
482 {
483 public:
BlockSingleStructArrayCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)484 BlockSingleStructArrayCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
485 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
486 , m_layoutFlags (layoutFlags)
487 , m_numInstances (numInstances)
488 {
489 StructType& typeS = m_interface.allocStruct("S");
490 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
491 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP), 4));
492 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
493
494 BufferBlock& block = m_interface.allocBlock("Block");
495 block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_LOWP), 0 /* no access */));
496 block.addMember(BufferVar("s", VarType(VarType(&typeS), 3), ACCESS_READ|ACCESS_WRITE));
497 block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
498 block.setFlags(m_layoutFlags);
499
500 if (m_numInstances > 0)
501 {
502 block.setInstanceName("block");
503 block.setArraySize(m_numInstances);
504 }
505
506 init();
507 }
508
509 private:
510 deUint32 m_layoutFlags;
511 int m_numInstances;
512 };
513
514 class BlockSingleNestedStructCase : public SSBOLayoutCase
515 {
516 public:
BlockSingleNestedStructCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)517 BlockSingleNestedStructCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
518 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
519 , m_layoutFlags (layoutFlags)
520 , m_numInstances (numInstances)
521 {
522 StructType& typeS = m_interface.allocStruct("S");
523 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP));
524 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP), 4));
525 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
526
527 StructType& typeT = m_interface.allocStruct("T");
528 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP));
529 typeT.addMember("b", VarType(&typeS));
530
531 BufferBlock& block = m_interface.allocBlock("Block");
532 block.addMember(BufferVar("s", VarType(&typeS), ACCESS_READ));
533 block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_LOWP), 0 /* no access */));
534 block.addMember(BufferVar("t", VarType(&typeT), ACCESS_READ|ACCESS_WRITE));
535 block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP), ACCESS_WRITE));
536 block.setFlags(m_layoutFlags);
537
538 if (m_numInstances > 0)
539 {
540 block.setInstanceName("block");
541 block.setArraySize(m_numInstances);
542 }
543
544 init();
545 }
546
547 private:
548 deUint32 m_layoutFlags;
549 int m_numInstances;
550 };
551
552 class BlockSingleNestedStructArrayCase : public SSBOLayoutCase
553 {
554 public:
BlockSingleNestedStructArrayCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)555 BlockSingleNestedStructArrayCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
556 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
557 , m_layoutFlags (layoutFlags)
558 , m_numInstances (numInstances)
559 {
560 StructType& typeS = m_interface.allocStruct("S");
561 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP));
562 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, glu::PRECISION_MEDIUMP), 4));
563 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
564
565 StructType& typeT = m_interface.allocStruct("T");
566 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP));
567 typeT.addMember("b", VarType(VarType(&typeS), 3));
568
569 BufferBlock& block = m_interface.allocBlock("Block");
570 block.addMember(BufferVar("s", VarType(&typeS), ACCESS_WRITE));
571 block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_LOWP), 0 /* no access */));
572 block.addMember(BufferVar("t", VarType(VarType(&typeT), 2), ACCESS_READ));
573 block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP), ACCESS_READ|ACCESS_WRITE));
574 block.setFlags(m_layoutFlags);
575
576 if (m_numInstances > 0)
577 {
578 block.setInstanceName("block");
579 block.setArraySize(m_numInstances);
580 }
581
582 init();
583 }
584
585 private:
586 deUint32 m_layoutFlags;
587 int m_numInstances;
588 };
589
590 class BlockUnsizedStructArrayCase : public SSBOLayoutCase
591 {
592 public:
BlockUnsizedStructArrayCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)593 BlockUnsizedStructArrayCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
594 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
595 , m_layoutFlags (layoutFlags)
596 , m_numInstances (numInstances)
597 {
598 StructType& typeS = m_interface.allocStruct("S");
599 typeS.addMember("a", VarType(glu::TYPE_UINT_VEC2, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
600 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2X4, glu::PRECISION_MEDIUMP), 4));
601 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC3, glu::PRECISION_HIGHP));
602
603 BufferBlock& block = m_interface.allocBlock("Block");
604 block.addMember(BufferVar("u", VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_LOWP), 0 /* no access */));
605 block.addMember(BufferVar("v", VarType(glu::TYPE_UINT, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
606 block.addMember(BufferVar("s", VarType(VarType(&typeS), VarType::UNSIZED_ARRAY), ACCESS_READ|ACCESS_WRITE));
607 block.setFlags(m_layoutFlags);
608
609 if (m_numInstances > 0)
610 {
611 block.setInstanceName("block");
612 block.setArraySize(m_numInstances);
613 }
614
615 {
616 de::Random rnd(246);
617 for (int ndx = 0; ndx < (m_numInstances ? m_numInstances : 1); ndx++)
618 {
619 const int lastArrayLen = rnd.getInt(1, 5);
620 block.setLastUnsizedArraySize(ndx, lastArrayLen);
621 }
622 }
623
624 init();
625 }
626
627 private:
628 deUint32 m_layoutFlags;
629 int m_numInstances;
630 };
631
632 class Block2LevelUnsizedStructArrayCase : public SSBOLayoutCase
633 {
634 public:
Block2LevelUnsizedStructArrayCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)635 Block2LevelUnsizedStructArrayCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
636 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
637 , m_layoutFlags (layoutFlags)
638 , m_numInstances (numInstances)
639 {
640 StructType& typeS = m_interface.allocStruct("S");
641 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, glu::PRECISION_HIGHP));
642 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
643
644 BufferBlock& block = m_interface.allocBlock("Block");
645 block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_LOWP), 0 /* no access */));
646 block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
647 block.addMember(BufferVar("s", VarType(VarType(VarType(&typeS), 2), VarType::UNSIZED_ARRAY), ACCESS_READ|ACCESS_WRITE));
648 block.setFlags(m_layoutFlags);
649
650 if (m_numInstances > 0)
651 {
652 block.setInstanceName("block");
653 block.setArraySize(m_numInstances);
654 }
655
656 {
657 de::Random rnd(2344);
658 for (int ndx = 0; ndx < (m_numInstances ? m_numInstances : 1); ndx++)
659 {
660 const int lastArrayLen = rnd.getInt(1, 5);
661 block.setLastUnsizedArraySize(ndx, lastArrayLen);
662 }
663 }
664
665 init();
666 }
667
668 private:
669 deUint32 m_layoutFlags;
670 int m_numInstances;
671 };
672
673 class BlockUnsizedNestedStructArrayCase : public SSBOLayoutCase
674 {
675 public:
BlockUnsizedNestedStructArrayCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)676 BlockUnsizedNestedStructArrayCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
677 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
678 , m_layoutFlags (layoutFlags)
679 , m_numInstances (numInstances)
680 {
681 StructType& typeS = m_interface.allocStruct("S");
682 typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, glu::PRECISION_HIGHP));
683 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_MEDIUMP), 4));
684 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)); // \todo [pyry] UNUSED
685
686 StructType& typeT = m_interface.allocStruct("T");
687 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT4X3, glu::PRECISION_MEDIUMP));
688 typeT.addMember("b", VarType(VarType(&typeS), 3));
689 typeT.addMember("c", VarType(glu::TYPE_INT, glu::PRECISION_HIGHP));
690
691 BufferBlock& block = m_interface.allocBlock("Block");
692 block.addMember(BufferVar("s", VarType(&typeS), ACCESS_WRITE));
693 block.addMember(BufferVar("v", VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_LOWP), 0 /* no access */));
694 block.addMember(BufferVar("u", VarType(glu::TYPE_UINT, glu::PRECISION_HIGHP), ACCESS_READ|ACCESS_WRITE));
695 block.addMember(BufferVar("t", VarType(VarType(&typeT), VarType::UNSIZED_ARRAY), ACCESS_READ));
696 block.setFlags(m_layoutFlags);
697
698 if (m_numInstances > 0)
699 {
700 block.setInstanceName("block");
701 block.setArraySize(m_numInstances);
702 }
703
704 {
705 de::Random rnd(7921);
706 for (int ndx = 0; ndx < (m_numInstances ? m_numInstances : 1); ndx++)
707 {
708 const int lastArrayLen = rnd.getInt(1, 5);
709 block.setLastUnsizedArraySize(ndx, lastArrayLen);
710 }
711 }
712
713 init();
714 }
715
716 private:
717 deUint32 m_layoutFlags;
718 int m_numInstances;
719 };
720
721 class BlockMultiBasicTypesCase : public SSBOLayoutCase
722 {
723 public:
BlockMultiBasicTypesCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 flagsA,deUint32 flagsB,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)724 BlockMultiBasicTypesCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
725 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
726 , m_flagsA (flagsA)
727 , m_flagsB (flagsB)
728 , m_numInstances (numInstances)
729 {
730 BufferBlock& blockA = m_interface.allocBlock("BlockA");
731 blockA.addMember(BufferVar("a", VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), ACCESS_READ|ACCESS_WRITE));
732 blockA.addMember(BufferVar("b", VarType(glu::TYPE_UINT_VEC3, glu::PRECISION_LOWP), 0 /* no access */));
733 blockA.addMember(BufferVar("c", VarType(glu::TYPE_FLOAT_MAT2, glu::PRECISION_MEDIUMP), ACCESS_READ));
734 blockA.setInstanceName("blockA");
735 blockA.setFlags(m_flagsA);
736
737 BufferBlock& blockB = m_interface.allocBlock("BlockB");
738 blockB.addMember(BufferVar("a", VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
739 blockB.addMember(BufferVar("b", VarType(glu::TYPE_INT_VEC2, glu::PRECISION_LOWP), ACCESS_READ));
740 blockB.addMember(BufferVar("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), 0 /* no access */));
741 blockB.addMember(BufferVar("d", VarType(glu::TYPE_BOOL, glu::PRECISION_LAST), ACCESS_READ|ACCESS_WRITE));
742 blockB.setInstanceName("blockB");
743 blockB.setFlags(m_flagsB);
744
745 if (m_numInstances > 0)
746 {
747 blockA.setArraySize(m_numInstances);
748 blockB.setArraySize(m_numInstances);
749 }
750
751 init();
752 }
753
754 private:
755 deUint32 m_flagsA;
756 deUint32 m_flagsB;
757 int m_numInstances;
758 };
759
760 class BlockMultiNestedStructCase : public SSBOLayoutCase
761 {
762 public:
BlockMultiNestedStructCase(tcu::TestContext & testCtx,const char * name,const char * description,deUint32 flagsA,deUint32 flagsB,BufferMode bufferMode,int numInstances,MatrixLoadFlags matrixLoadFlag)763 BlockMultiNestedStructCase (tcu::TestContext& testCtx, const char* name, const char* description, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances, MatrixLoadFlags matrixLoadFlag)
764 : SSBOLayoutCase (testCtx, name, description, bufferMode, matrixLoadFlag)
765 , m_flagsA (flagsA)
766 , m_flagsB (flagsB)
767 , m_numInstances (numInstances)
768 {
769 StructType& typeS = m_interface.allocStruct("S");
770 typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, glu::PRECISION_LOWP));
771 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, glu::PRECISION_MEDIUMP), 4));
772 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
773
774 StructType& typeT = m_interface.allocStruct("T");
775 typeT.addMember("a", VarType(glu::TYPE_UINT, glu::PRECISION_MEDIUMP)); // \todo [pyry] UNUSED
776 typeT.addMember("b", VarType(&typeS));
777 typeT.addMember("c", VarType(glu::TYPE_BOOL_VEC4, glu::PRECISION_LAST));
778
779 BufferBlock& blockA = m_interface.allocBlock("BlockA");
780 blockA.addMember(BufferVar("a", VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), ACCESS_READ|ACCESS_WRITE));
781 blockA.addMember(BufferVar("b", VarType(&typeS), ACCESS_WRITE));
782 blockA.addMember(BufferVar("c", VarType(glu::TYPE_UINT_VEC3, glu::PRECISION_LOWP), 0 /* no access */));
783 blockA.setInstanceName("blockA");
784 blockA.setFlags(m_flagsA);
785
786 BufferBlock& blockB = m_interface.allocBlock("BlockB");
787 blockB.addMember(BufferVar("a", VarType(glu::TYPE_FLOAT_MAT2, glu::PRECISION_MEDIUMP), ACCESS_WRITE));
788 blockB.addMember(BufferVar("b", VarType(&typeT), ACCESS_READ|ACCESS_WRITE));
789 blockB.addMember(BufferVar("c", VarType(glu::TYPE_BOOL_VEC4, glu::PRECISION_LAST), 0 /* no access */));
790 blockB.addMember(BufferVar("d", VarType(glu::TYPE_BOOL, glu::PRECISION_LAST), ACCESS_READ|ACCESS_WRITE));
791 blockB.setInstanceName("blockB");
792 blockB.setFlags(m_flagsB);
793
794 if (m_numInstances > 0)
795 {
796 blockA.setArraySize(m_numInstances);
797 blockB.setArraySize(m_numInstances);
798 }
799
800 init();
801 }
802
803 private:
804 deUint32 m_flagsA;
805 deUint32 m_flagsB;
806 int m_numInstances;
807 };
808
809 // unsized_array_length
810
811 struct UnsizedArrayCaseParams
812 {
813 int elementSize;
814 vk::VkDeviceSize bufferSize;
815 bool useMinBufferOffset;
816 vk::VkDeviceSize bufferBindLength;
817 const char* name;
818 };
819
createUnsizedArrayLengthProgs(SourceCollections & dst,UnsizedArrayCaseParams)820 void createUnsizedArrayLengthProgs (SourceCollections& dst, UnsizedArrayCaseParams)
821 {
822 dst.glslSources.add("comp") << glu::ComputeSource(
823 "#version 310 es\n"
824 "layout(set=0, binding=0, std430) readonly buffer x {\n"
825 " int xs[];\n"
826 "};\n"
827 "layout(set=0, binding=1, std430) writeonly buffer y {\n"
828 " int observed_size;\n"
829 "};\n"
830 "layout(local_size_x=1) in;\n"
831 "void main (void) {\n"
832 " observed_size = xs.length();\n"
833 "}\n");
834 }
835
ssboUnsizedArrayLengthTest(Context & context,UnsizedArrayCaseParams params)836 tcu::TestStatus ssboUnsizedArrayLengthTest (Context& context, UnsizedArrayCaseParams params)
837 {
838 const DeviceInterface& vk = context.getDeviceInterface();
839 const VkDevice device = context.getDevice();
840 const VkQueue queue = context.getUniversalQueue();
841 Allocator& allocator = context.getDefaultAllocator();
842
843 DescriptorSetLayoutBuilder builder;
844 builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); // input buffer
845 builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); // result buffer
846
847 const Unique<VkDescriptorSetLayout> descriptorSetLayout (builder.build(vk, device));
848 const Unique<VkDescriptorPool> descriptorPool (vk::DescriptorPoolBuilder()
849 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u)
850 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
851
852 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
853 {
854 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
855 DE_NULL,
856 (VkPipelineLayoutCreateFlags)0,
857 1, // setLayoutCount,
858 &descriptorSetLayout.get(), // pSetLayouts
859 0, // pushConstantRangeCount
860 DE_NULL, // pPushConstantRanges
861 };
862 const Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, device, &pipelineLayoutCreateInfo));
863
864 const Unique<VkShaderModule> computeModule (createShaderModule(vk, device, context.getBinaryCollection().get("comp"), (VkShaderModuleCreateFlags)0u));
865
866 const VkPipelineShaderStageCreateInfo shaderCreateInfo =
867 {
868 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
869 DE_NULL,
870 (VkPipelineShaderStageCreateFlags)0,
871 VK_SHADER_STAGE_COMPUTE_BIT, // stage
872 *computeModule, // shader
873 "main",
874 DE_NULL, // pSpecializationInfo
875 };
876
877 const VkComputePipelineCreateInfo pipelineCreateInfo =
878 {
879 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
880 DE_NULL,
881 0u, // flags
882 shaderCreateInfo, // cs
883 *pipelineLayout, // layout
884 (vk::VkPipeline)0, // basePipelineHandle
885 0u, // basePipelineIndex
886 };
887
888 const Unique<VkPipeline> pipeline (createComputePipeline(vk, device, (VkPipelineCache)0u, &pipelineCreateInfo));
889
890 // Input buffer
891 const VkBufferCreateInfo inputBufferCreateInfo =
892 {
893 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
894 DE_NULL,
895 0, // flags
896 (VkDeviceSize) params.bufferSize, // size
897 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage TODO: also test _DYNAMIC case.
898 VK_SHARING_MODE_EXCLUSIVE,
899 0u, // queueFamilyCount
900 DE_NULL, // pQueueFamilyIndices
901 };
902 const Unique<VkBuffer> inputBuffer (createBuffer(vk, device, &inputBufferCreateInfo));
903 const VkMemoryRequirements inputBufferRequirements = getBufferMemoryRequirements(vk, device, *inputBuffer);
904 const de::MovePtr<Allocation> inputBufferMemory = allocator.allocate(inputBufferRequirements, MemoryRequirement::HostVisible);
905
906 VK_CHECK(vk.bindBufferMemory(device, *inputBuffer, inputBufferMemory->getMemory(), inputBufferMemory->getOffset()));
907 // Note: don't care about the contents of the input buffer -- we only determine a size.
908
909 // Output buffer
910 const VkBufferCreateInfo outputBufferCreateInfo =
911 {
912 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
913 DE_NULL,
914 0,
915 (VkDeviceSize) 4,
916 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
917 VK_SHARING_MODE_EXCLUSIVE,
918 0u,
919 DE_NULL,
920 };
921 const Unique<VkBuffer> outputBuffer (createBuffer(vk, device, &outputBufferCreateInfo));
922 const VkMemoryRequirements outputBufferRequirements= getBufferMemoryRequirements(vk, device, *outputBuffer);
923 const de::MovePtr<Allocation> outputBufferMemory = allocator.allocate(outputBufferRequirements, MemoryRequirement::HostVisible);
924
925 VK_CHECK(vk.bindBufferMemory(device, *outputBuffer, outputBufferMemory->getMemory(), outputBufferMemory->getOffset()));
926
927 // Initialize output buffer contents
928 const VkMappedMemoryRange range =
929 {
930 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType
931 DE_NULL, // pNext
932 outputBufferMemory->getMemory(), // memory
933 0, // offset
934 VK_WHOLE_SIZE, // size
935 };
936 int * outputBufferPtr = (int *)outputBufferMemory->getHostPtr();
937 *outputBufferPtr = -1;
938 VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &range));
939
940 // Build descriptor set
941 vk::VkDeviceSize bufferBindOffset = 0;
942 if (params.useMinBufferOffset)
943 {
944 const VkPhysicalDeviceLimits deviceLimits = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
945 bufferBindOffset = deviceLimits.minStorageBufferOffsetAlignment;
946 }
947
948 const VkDescriptorBufferInfo inputBufferDesc = makeDescriptorBufferInfo(*inputBuffer, bufferBindOffset, params.bufferBindLength);
949 const VkDescriptorBufferInfo outputBufferDesc = makeDescriptorBufferInfo(*outputBuffer, 0u, VK_WHOLE_SIZE);
950
951 const VkDescriptorSetAllocateInfo descAllocInfo =
952 {
953 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
954 DE_NULL,
955 *descriptorPool, // pool
956 1u, // setLayoutCount
957 &descriptorSetLayout.get(), // pSetLayouts
958 };
959 const Unique<VkDescriptorSet> descSet (allocateDescriptorSet(vk, device, &descAllocInfo));
960
961 DescriptorSetUpdateBuilder()
962 .writeSingle(*descSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputBufferDesc)
963 .writeSingle(*descSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferDesc)
964 .update(vk, device);
965
966 const VkCommandPoolCreateInfo cmdPoolParams =
967 {
968 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
969 DE_NULL, // pNext
970 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
971 context.getUniversalQueueFamilyIndex(), // queueFamilyIndex
972 };
973 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolParams));
974
975 // Command buffer
976 const VkCommandBufferAllocateInfo cmdBufParams =
977 {
978 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
979 DE_NULL, // pNext
980 *cmdPool, // pool
981 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
982 1u, // bufferCount
983 };
984 const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, device, &cmdBufParams));
985
986 // Record commands
987 beginCommandBuffer(vk, *cmdBuf);
988
989 vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
990 vk.cmdBindDescriptorSets(*cmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descSet.get(), 0u, DE_NULL);
991 vk.cmdDispatch(*cmdBuf, 1, 1, 1);
992
993 const VkMemoryBarrier barrier =
994 {
995 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
996 DE_NULL, // pNext
997 VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask
998 VK_ACCESS_HOST_READ_BIT, // dstAccessMask
999 };
1000 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 1, &barrier, 0, DE_NULL, 0, DE_NULL);
1001
1002 endCommandBuffer(vk, *cmdBuf);
1003
1004 submitCommandsAndWait(vk, device, queue, cmdBuf.get());
1005
1006 // Read back output buffer contents
1007 VK_CHECK(vk.invalidateMappedMemoryRanges(device, 1, &range));
1008
1009 // Expected number of elements in array at end of storage buffer
1010 const VkDeviceSize boundLength = params.bufferBindLength == VK_WHOLE_SIZE
1011 ? params.bufferSize - bufferBindOffset
1012 : params.bufferBindLength;
1013 const int expectedResult = (int)(boundLength / params.elementSize);
1014 const int actualResult = *outputBufferPtr;
1015
1016 context.getTestContext().getLog()
1017 << tcu::TestLog::Message
1018 << "Buffer size " << params.bufferSize
1019 << " offset " << bufferBindOffset
1020 << " length " << params.bufferBindLength
1021 << " element size " << params.elementSize
1022 << " expected array size: " << expectedResult
1023 << " actual array size: " << actualResult
1024 << tcu::TestLog::EndMessage;
1025
1026 if (expectedResult == actualResult)
1027 return tcu::TestStatus::pass("Got expected array size");
1028 else
1029 return tcu::TestStatus::fail("Mismatch array size");
1030 }
1031
1032 class SSBOLayoutTests : public tcu::TestCaseGroup
1033 {
1034 public:
1035 SSBOLayoutTests (tcu::TestContext& testCtx);
1036 ~SSBOLayoutTests (void);
1037
1038 void init (void);
1039
1040 private:
1041 SSBOLayoutTests (const SSBOLayoutTests& other);
1042 SSBOLayoutTests& operator= (const SSBOLayoutTests& other);
1043 };
1044
1045
SSBOLayoutTests(tcu::TestContext & testCtx)1046 SSBOLayoutTests::SSBOLayoutTests (tcu::TestContext& testCtx)
1047 : TestCaseGroup(testCtx, "layout", "SSBO Layout Tests")
1048 {
1049 }
1050
~SSBOLayoutTests(void)1051 SSBOLayoutTests::~SSBOLayoutTests (void)
1052 {
1053 }
1054
init(void)1055 void SSBOLayoutTests::init (void)
1056 {
1057 static const glu::DataType basicTypes[] =
1058 {
1059 glu::TYPE_FLOAT,
1060 glu::TYPE_FLOAT_VEC2,
1061 glu::TYPE_FLOAT_VEC3,
1062 glu::TYPE_FLOAT_VEC4,
1063 glu::TYPE_INT,
1064 glu::TYPE_INT_VEC2,
1065 glu::TYPE_INT_VEC3,
1066 glu::TYPE_INT_VEC4,
1067 glu::TYPE_UINT,
1068 glu::TYPE_UINT_VEC2,
1069 glu::TYPE_UINT_VEC3,
1070 glu::TYPE_UINT_VEC4,
1071 glu::TYPE_BOOL,
1072 glu::TYPE_BOOL_VEC2,
1073 glu::TYPE_BOOL_VEC3,
1074 glu::TYPE_BOOL_VEC4,
1075 glu::TYPE_FLOAT_MAT2,
1076 glu::TYPE_FLOAT_MAT3,
1077 glu::TYPE_FLOAT_MAT4,
1078 glu::TYPE_FLOAT_MAT2X3,
1079 glu::TYPE_FLOAT_MAT2X4,
1080 glu::TYPE_FLOAT_MAT3X2,
1081 glu::TYPE_FLOAT_MAT3X4,
1082 glu::TYPE_FLOAT_MAT4X2,
1083 glu::TYPE_FLOAT_MAT4X3,
1084 glu::TYPE_UINT8,
1085 glu::TYPE_UINT8_VEC2,
1086 glu::TYPE_UINT8_VEC3,
1087 glu::TYPE_UINT8_VEC4,
1088 glu::TYPE_INT8,
1089 glu::TYPE_INT8_VEC2,
1090 glu::TYPE_INT8_VEC3,
1091 glu::TYPE_INT8_VEC4,
1092 glu::TYPE_UINT16,
1093 glu::TYPE_UINT16_VEC2,
1094 glu::TYPE_UINT16_VEC3,
1095 glu::TYPE_UINT16_VEC4,
1096 glu::TYPE_INT16,
1097 glu::TYPE_INT16_VEC2,
1098 glu::TYPE_INT16_VEC3,
1099 glu::TYPE_INT16_VEC4,
1100 glu::TYPE_FLOAT16,
1101 glu::TYPE_FLOAT16_VEC2,
1102 glu::TYPE_FLOAT16_VEC3,
1103 glu::TYPE_FLOAT16_VEC4,
1104 };
1105
1106 static const struct
1107 {
1108 const char* name;
1109 deUint32 flags;
1110 } layoutFlags[] =
1111 {
1112 { "std140", LAYOUT_STD140 },
1113 { "std430", LAYOUT_STD430 },
1114 { "scalar", LAYOUT_SCALAR },
1115 };
1116
1117 static const struct
1118 {
1119 const char* name;
1120 deUint32 flags;
1121 } matrixFlags[] =
1122 {
1123 { "row_major", LAYOUT_ROW_MAJOR },
1124 { "column_major", LAYOUT_COLUMN_MAJOR }
1125 };
1126
1127 static const struct
1128 {
1129 const char* name;
1130 SSBOLayoutCase::BufferMode mode;
1131 } bufferModes[] =
1132 {
1133 { "per_block_buffer", SSBOLayoutCase::BUFFERMODE_PER_BLOCK },
1134 { "single_buffer", SSBOLayoutCase::BUFFERMODE_SINGLE }
1135 };
1136
1137 // ssbo.single_basic_type
1138 {
1139 tcu::TestCaseGroup* singleBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_type", "Single basic variable in single buffer");
1140 addChild(singleBasicTypeGroup);
1141
1142 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1143 {
1144 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1145 singleBasicTypeGroup->addChild(layoutGroup);
1146
1147 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1148 {
1149 glu::DataType type = basicTypes[basicTypeNdx];
1150 const char* typeName = glu::getDataTypeName(type);
1151
1152 if (!glu::dataTypeSupportsPrecisionModifier(type))
1153 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, typeName, "", VarType(type, glu::PRECISION_LAST), layoutFlags[layoutFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1154 else
1155 {
1156 for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
1157 {
1158 const glu::Precision precision = glu::Precision(precNdx);
1159 const string caseName = string(glu::getPrecisionName(precision)) + "_" + typeName;
1160
1161 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, caseName.c_str(), "", VarType(type, precision), layoutFlags[layoutFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1162 }
1163 }
1164
1165 if (glu::isDataTypeMatrix(type))
1166 {
1167 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1168 {
1169 for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
1170 {
1171 const glu::Precision precision = glu::Precision(precNdx);
1172 const string caseName = string(matrixFlags[matFlagNdx].name) + "_" + string(glu::getPrecisionName(precision)) + "_" + typeName;
1173
1174 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, caseName.c_str(), "", glu::VarType(type, precision), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1175 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (caseName + "_comp_access").c_str(), "", glu::VarType(type, precision), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, 0, LOAD_MATRIX_COMPONENTS));
1176 }
1177 }
1178 }
1179 }
1180 }
1181 }
1182
1183 // ssbo.single_basic_array
1184 {
1185 tcu::TestCaseGroup* singleBasicArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_array", "Single basic array variable in single buffer");
1186 addChild(singleBasicArrayGroup);
1187
1188 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1189 {
1190 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1191 singleBasicArrayGroup->addChild(layoutGroup);
1192
1193 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1194 {
1195 glu::DataType type = basicTypes[basicTypeNdx];
1196 const char* typeName = glu::getDataTypeName(type);
1197 const int arraySize = 3;
1198
1199 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, typeName, "",
1200 VarType(VarType(type, !glu::dataTypeSupportsPrecisionModifier(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP), arraySize),
1201 layoutFlags[layoutFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1202
1203 if (glu::isDataTypeMatrix(type))
1204 {
1205 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1206 {
1207 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
1208 VarType(VarType(type, glu::PRECISION_HIGHP), arraySize),
1209 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1210 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName + "_comp_access").c_str(), "",
1211 VarType(VarType(type, glu::PRECISION_HIGHP), arraySize),
1212 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, 0, LOAD_MATRIX_COMPONENTS));
1213 }
1214 }
1215 }
1216 }
1217 }
1218
1219 // ssbo.basic_unsized_array
1220 {
1221 tcu::TestCaseGroup* basicUnsizedArray = new tcu::TestCaseGroup(m_testCtx, "basic_unsized_array", "Basic unsized array tests");
1222 addChild(basicUnsizedArray);
1223
1224 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1225 {
1226 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1227 basicUnsizedArray->addChild(layoutGroup);
1228
1229 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1230 {
1231 glu::DataType type = basicTypes[basicTypeNdx];
1232 const char* typeName = glu::getDataTypeName(type);
1233 const int arraySize = 19;
1234
1235 layoutGroup->addChild(new BlockBasicUnsizedArrayCase(m_testCtx, typeName, "",
1236 VarType(type, !glu::dataTypeSupportsPrecisionModifier(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP),
1237 arraySize, layoutFlags[layoutFlagNdx].flags, LOAD_FULL_MATRIX));
1238
1239 if (glu::isDataTypeMatrix(type))
1240 {
1241 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1242 {
1243 layoutGroup->addChild(new BlockBasicUnsizedArrayCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
1244 VarType(type, glu::PRECISION_HIGHP), arraySize,
1245 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, LOAD_FULL_MATRIX));
1246 layoutGroup->addChild(new BlockBasicUnsizedArrayCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName + "_comp_access").c_str(), "",
1247 VarType(type, glu::PRECISION_HIGHP), arraySize,
1248 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, LOAD_MATRIX_COMPONENTS));
1249 }
1250 }
1251 }
1252 }
1253 }
1254
1255 // ssbo.2_level_array
1256 {
1257 tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level nested array");
1258 addChild(nestedArrayGroup);
1259
1260 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1261 {
1262 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1263 nestedArrayGroup->addChild(layoutGroup);
1264
1265 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1266 {
1267 glu::DataType type = basicTypes[basicTypeNdx];
1268 const char* typeName = glu::getDataTypeName(type);
1269 const int childSize = 3;
1270 const int parentSize = 4;
1271 const VarType childType (VarType(type, !glu::dataTypeSupportsPrecisionModifier(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP), childSize);
1272 const VarType fullType (childType, parentSize);
1273
1274 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, typeName, "", fullType, layoutFlags[layoutFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1275
1276 if (glu::isDataTypeMatrix(type))
1277 {
1278 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1279 {
1280 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
1281 fullType,
1282 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1283 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName + "_comp_access").c_str(), "",
1284 fullType,
1285 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, 0, LOAD_MATRIX_COMPONENTS));
1286 }
1287 }
1288 }
1289 }
1290 }
1291
1292 // ssbo.3_level_array
1293 {
1294 tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level nested array");
1295 addChild(nestedArrayGroup);
1296
1297 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1298 {
1299 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1300 nestedArrayGroup->addChild(layoutGroup);
1301
1302 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1303 {
1304 glu::DataType type = basicTypes[basicTypeNdx];
1305 const char* typeName = glu::getDataTypeName(type);
1306 const int childSize0 = 3;
1307 const int childSize1 = 2;
1308 const int parentSize = 4;
1309 const VarType childType0 (VarType(type, !glu::dataTypeSupportsPrecisionModifier(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP), childSize0);
1310 const VarType childType1 (childType0, childSize1);
1311 const VarType fullType (childType1, parentSize);
1312
1313 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, typeName, "", fullType, layoutFlags[layoutFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1314
1315 if (glu::isDataTypeMatrix(type))
1316 {
1317 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1318 {
1319 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
1320 fullType,
1321 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, 0, LOAD_FULL_MATRIX));
1322 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName + "_comp_access").c_str(), "",
1323 fullType,
1324 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, 0, LOAD_MATRIX_COMPONENTS));
1325 }
1326 }
1327 }
1328 }
1329 }
1330
1331 // ssbo.3_level_unsized_array
1332 {
1333 tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "3_level_unsized_array", "3-level nested array, top-level array unsized");
1334 addChild(nestedArrayGroup);
1335
1336 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1337 {
1338 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1339 nestedArrayGroup->addChild(layoutGroup);
1340
1341 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1342 {
1343 glu::DataType type = basicTypes[basicTypeNdx];
1344 const char* typeName = glu::getDataTypeName(type);
1345 const int childSize0 = 2;
1346 const int childSize1 = 4;
1347 const int parentSize = 3;
1348 const VarType childType0 (VarType(type, !glu::dataTypeSupportsPrecisionModifier(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP), childSize0);
1349 const VarType childType1 (childType0, childSize1);
1350
1351 layoutGroup->addChild(new BlockBasicUnsizedArrayCase(m_testCtx, typeName, "", childType1, parentSize, layoutFlags[layoutFlagNdx].flags, LOAD_FULL_MATRIX));
1352
1353 if (glu::isDataTypeMatrix(type))
1354 {
1355 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1356 {
1357 layoutGroup->addChild(new BlockBasicUnsizedArrayCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
1358 childType1, parentSize,
1359 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, LOAD_FULL_MATRIX));
1360 layoutGroup->addChild(new BlockBasicUnsizedArrayCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName + "_comp_access").c_str(), "",
1361 childType1, parentSize,
1362 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags, LOAD_MATRIX_COMPONENTS));
1363 }
1364 }
1365 }
1366 }
1367 }
1368
1369 // ssbo.single_struct
1370 {
1371 tcu::TestCaseGroup* singleStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct", "Single struct in uniform block");
1372 addChild(singleStructGroup);
1373
1374 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1375 {
1376 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1377 singleStructGroup->addChild(modeGroup);
1378
1379 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1380 {
1381 for (int isArray = 0; isArray < 2; isArray++)
1382 {
1383 const deUint32 caseFlags = layoutFlags[layoutFlagNdx].flags;
1384 string caseName = layoutFlags[layoutFlagNdx].name;
1385
1386 if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1387 continue; // Doesn't make sense to add this variant.
1388
1389 if (isArray)
1390 caseName += "_instance_array";
1391
1392 modeGroup->addChild(new BlockSingleStructCase(m_testCtx, caseName.c_str(), "", caseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1393 modeGroup->addChild(new BlockSingleStructCase(m_testCtx, (caseName + "_comp_access").c_str(), "", caseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1394 }
1395 }
1396 }
1397 }
1398
1399 // ssbo.single_struct_array
1400 {
1401 tcu::TestCaseGroup* singleStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct_array", "Struct array in one uniform block");
1402 addChild(singleStructArrayGroup);
1403
1404 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1405 {
1406 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1407 singleStructArrayGroup->addChild(modeGroup);
1408
1409 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1410 {
1411 for (int isArray = 0; isArray < 2; isArray++)
1412 {
1413 std::string baseName = layoutFlags[layoutFlagNdx].name;
1414 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
1415
1416 if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1417 continue; // Doesn't make sense to add this variant.
1418
1419 if (isArray)
1420 baseName += "_instance_array";
1421
1422 modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1423 modeGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1424 }
1425 }
1426 }
1427 }
1428
1429 // ssbo.single_nested_struct
1430 {
1431 tcu::TestCaseGroup* singleNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct", "Nested struct in one uniform block");
1432 addChild(singleNestedStructGroup);
1433
1434 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1435 {
1436 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1437 singleNestedStructGroup->addChild(modeGroup);
1438
1439 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1440 {
1441 for (int isArray = 0; isArray < 2; isArray++)
1442 {
1443 std::string baseName = layoutFlags[layoutFlagNdx].name;
1444 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
1445
1446 if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1447 continue; // Doesn't make sense to add this variant.
1448
1449 if (isArray)
1450 baseName += "_instance_array";
1451
1452 modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1453 modeGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1454 }
1455 }
1456 }
1457 }
1458
1459 // ssbo.single_nested_struct_array
1460 {
1461 tcu::TestCaseGroup* singleNestedStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array", "Nested struct array in one uniform block");
1462 addChild(singleNestedStructArrayGroup);
1463
1464 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1465 {
1466 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1467 singleNestedStructArrayGroup->addChild(modeGroup);
1468
1469 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1470 {
1471 for (int isArray = 0; isArray < 2; isArray++)
1472 {
1473 std::string baseName = layoutFlags[layoutFlagNdx].name;
1474 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
1475
1476 if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1477 continue; // Doesn't make sense to add this variant.
1478
1479 if (isArray)
1480 baseName += "_instance_array";
1481
1482 modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1483 modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1484 }
1485 }
1486 }
1487 }
1488
1489 // ssbo.unsized_struct_array
1490 {
1491 tcu::TestCaseGroup* singleStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "unsized_struct_array", "Unsized struct array in one uniform block");
1492 addChild(singleStructArrayGroup);
1493
1494 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1495 {
1496 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1497 singleStructArrayGroup->addChild(modeGroup);
1498
1499 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1500 {
1501 for (int isArray = 0; isArray < 2; isArray++)
1502 {
1503 std::string baseName = layoutFlags[layoutFlagNdx].name;
1504 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
1505
1506 if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1507 continue; // Doesn't make sense to add this variant.
1508
1509 if (isArray)
1510 baseName += "_instance_array";
1511
1512 modeGroup->addChild(new BlockUnsizedStructArrayCase(m_testCtx, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1513 modeGroup->addChild(new BlockUnsizedStructArrayCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1514 }
1515 }
1516 }
1517 }
1518
1519 // ssbo.2_level_unsized_struct_array
1520 {
1521 tcu::TestCaseGroup* structArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_unsized_struct_array", "Unsized 2-level struct array in one uniform block");
1522 addChild(structArrayGroup);
1523
1524 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1525 {
1526 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1527 structArrayGroup->addChild(modeGroup);
1528
1529 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1530 {
1531 for (int isArray = 0; isArray < 2; isArray++)
1532 {
1533 std::string baseName = layoutFlags[layoutFlagNdx].name;
1534 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
1535
1536 if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1537 continue; // Doesn't make sense to add this variant.
1538
1539 if (isArray)
1540 baseName += "_instance_array";
1541
1542 modeGroup->addChild(new Block2LevelUnsizedStructArrayCase(m_testCtx, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1543 modeGroup->addChild(new Block2LevelUnsizedStructArrayCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1544 }
1545 }
1546 }
1547 }
1548
1549 // ssbo.unsized_nested_struct_array
1550 {
1551 tcu::TestCaseGroup* singleNestedStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "unsized_nested_struct_array", "Unsized, nested struct array in one uniform block");
1552 addChild(singleNestedStructArrayGroup);
1553
1554 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1555 {
1556 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1557 singleNestedStructArrayGroup->addChild(modeGroup);
1558
1559 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1560 {
1561 for (int isArray = 0; isArray < 2; isArray++)
1562 {
1563 std::string baseName = layoutFlags[layoutFlagNdx].name;
1564 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
1565
1566 if (bufferModes[modeNdx].mode == SSBOLayoutCase::BUFFERMODE_SINGLE && isArray == 0)
1567 continue; // Doesn't make sense to add this variant.
1568
1569 if (isArray)
1570 baseName += "_instance_array";
1571
1572 modeGroup->addChild(new BlockUnsizedNestedStructArrayCase(m_testCtx, baseName.c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1573 modeGroup->addChild(new BlockUnsizedNestedStructArrayCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1574 }
1575 }
1576 }
1577 }
1578
1579 // ssbo.instance_array_basic_type
1580 {
1581 tcu::TestCaseGroup* instanceArrayBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type", "Single basic variable in instance array");
1582 addChild(instanceArrayBasicTypeGroup);
1583
1584 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1585 {
1586 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
1587 instanceArrayBasicTypeGroup->addChild(layoutGroup);
1588
1589 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
1590 {
1591 glu::DataType type = basicTypes[basicTypeNdx];
1592 const char* typeName = glu::getDataTypeName(type);
1593 const int numInstances = 3;
1594
1595 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, typeName, "",
1596 VarType(type, !glu::dataTypeSupportsPrecisionModifier(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP),
1597 layoutFlags[layoutFlagNdx].flags, numInstances, LOAD_FULL_MATRIX));
1598
1599 if (glu::isDataTypeMatrix(type))
1600 {
1601 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
1602 {
1603 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), "",
1604 VarType(type, glu::PRECISION_HIGHP), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags,
1605 numInstances, LOAD_FULL_MATRIX));
1606 layoutGroup->addChild(new BlockBasicTypeCase(m_testCtx, (string(matrixFlags[matFlagNdx].name) + "_" + typeName + "_comp_access").c_str(), "",
1607 VarType(type, glu::PRECISION_HIGHP), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags,
1608 numInstances, LOAD_MATRIX_COMPONENTS));
1609 }
1610 }
1611 }
1612 }
1613 }
1614
1615 // ssbo.multi_basic_types
1616 {
1617 tcu::TestCaseGroup* multiBasicTypesGroup = new tcu::TestCaseGroup(m_testCtx, "multi_basic_types", "Multiple buffers with basic types");
1618 addChild(multiBasicTypesGroup);
1619
1620 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1621 {
1622 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1623 multiBasicTypesGroup->addChild(modeGroup);
1624
1625 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1626 {
1627 for (int isArray = 0; isArray < 2; isArray++)
1628 {
1629 std::string baseName = layoutFlags[layoutFlagNdx].name;
1630 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
1631
1632 if (isArray)
1633 baseName += "_instance_array";
1634
1635 modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName.c_str(), "", baseFlags, baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1636 modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1637 }
1638 }
1639
1640 for (int isArray = 0; isArray < 2; isArray++)
1641 {
1642 std::string baseName = "relaxed_block";
1643 deUint32 baseFlags = LAYOUT_RELAXED;
1644
1645 if (isArray)
1646 baseName += "_instance_array";
1647
1648 modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName.c_str(), "", baseFlags, baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1649 modeGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1650 }
1651 }
1652 }
1653
1654 // ssbo.multi_nested_struct
1655 {
1656 tcu::TestCaseGroup* multiNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct", "Multiple buffers with nested structs");
1657 addChild(multiNestedStructGroup);
1658
1659 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
1660 {
1661 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
1662 multiNestedStructGroup->addChild(modeGroup);
1663
1664 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
1665 {
1666 for (int isArray = 0; isArray < 2; isArray++)
1667 {
1668 std::string baseName = layoutFlags[layoutFlagNdx].name;
1669 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
1670
1671 if (isArray)
1672 baseName += "_instance_array";
1673
1674 modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName.c_str(), "", baseFlags, baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_FULL_MATRIX));
1675 modeGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, (baseName + "_comp_access").c_str(), "", baseFlags, baseFlags, bufferModes[modeNdx].mode, isArray ? 3 : 0, LOAD_MATRIX_COMPONENTS));
1676 }
1677 }
1678 }
1679 }
1680
1681 // ssbo.random
1682 {
1683 const deUint32 allStdLayouts = FEATURE_STD140_LAYOUT|FEATURE_STD430_LAYOUT;
1684 const deUint32 allBasicTypes = FEATURE_VECTORS|FEATURE_MATRICES;
1685 const deUint32 unused = FEATURE_UNUSED_MEMBERS|FEATURE_UNUSED_VARS;
1686 const deUint32 unsized = FEATURE_UNSIZED_ARRAYS;
1687 const deUint32 matFlags = FEATURE_MATRIX_LAYOUT;
1688 const deUint32 allButRelaxed = ~FEATURE_RELAXED_LAYOUT & ~FEATURE_16BIT_STORAGE & ~FEATURE_8BIT_STORAGE & ~FEATURE_SCALAR_LAYOUT;
1689 const deUint32 allRelaxed = FEATURE_VECTORS|FEATURE_RELAXED_LAYOUT|FEATURE_INSTANCE_ARRAYS;
1690 const deUint32 allScalar = ~FEATURE_RELAXED_LAYOUT & ~allStdLayouts & ~FEATURE_16BIT_STORAGE & ~FEATURE_8BIT_STORAGE;
1691
1692 tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
1693 addChild(randomGroup);
1694
1695 for (int i = 0; i < 3; ++i)
1696 {
1697
1698 tcu::TestCaseGroup* group = randomGroup;
1699 if (i == 1)
1700 {
1701 group = new tcu::TestCaseGroup(m_testCtx, "16bit", "16bit storage");
1702 randomGroup->addChild(group);
1703 }
1704 else if (i == 2)
1705 {
1706 group = new tcu::TestCaseGroup(m_testCtx, "8bit", "18bit storage");
1707 randomGroup->addChild(group);
1708 }
1709 const deUint32 use16BitStorage = i == 1 ? FEATURE_16BIT_STORAGE : 0;
1710 const deUint32 use8BitStorage = i == 2 ? FEATURE_8BIT_STORAGE : 0;
1711
1712 // Basic types.
1713 createRandomCaseGroup(group, m_testCtx, "scalar_types", "Scalar types only, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused, 25, 0);
1714 createRandomCaseGroup(group, m_testCtx, "vector_types", "Scalar and vector types only, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|FEATURE_VECTORS, 25, 25);
1715 createRandomCaseGroup(group, m_testCtx, "basic_types", "All basic types, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags, 25, 50);
1716 createRandomCaseGroup(group, m_testCtx, "basic_arrays", "Arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags|FEATURE_ARRAYS, 25, 50);
1717 createRandomCaseGroup(group, m_testCtx, "unsized_arrays", "Unsized arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags|unsized|FEATURE_ARRAYS, 25, 50);
1718 createRandomCaseGroup(group, m_testCtx, "arrays_of_arrays", "Arrays of arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags|unsized|FEATURE_ARRAYS|FEATURE_ARRAYS_OF_ARRAYS, 25, 950);
1719
1720 createRandomCaseGroup(group, m_testCtx, "basic_instance_arrays", "Basic instance arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags|unsized|FEATURE_INSTANCE_ARRAYS, 25, 75);
1721 createRandomCaseGroup(group, m_testCtx, "nested_structs", "Nested structs, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags|unsized|FEATURE_STRUCTS, 25, 100);
1722 createRandomCaseGroup(group, m_testCtx, "nested_structs_arrays", "Nested structs, arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags|unsized|FEATURE_STRUCTS|FEATURE_ARRAYS|FEATURE_ARRAYS_OF_ARRAYS, 25, 150);
1723 createRandomCaseGroup(group, m_testCtx, "nested_structs_instance_arrays", "Nested structs, instance arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags|unsized|FEATURE_STRUCTS|FEATURE_INSTANCE_ARRAYS, 25, 125);
1724 createRandomCaseGroup(group, m_testCtx, "nested_structs_arrays_instance_arrays", "Nested structs, instance arrays, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allStdLayouts|unused|allBasicTypes|matFlags|unsized|FEATURE_STRUCTS|FEATURE_ARRAYS|FEATURE_ARRAYS_OF_ARRAYS|FEATURE_INSTANCE_ARRAYS, 25, 175);
1725 createRandomCaseGroup(group, m_testCtx, "all_per_block_buffers", "All random features, per-block buffers", SSBOLayoutCase::BUFFERMODE_PER_BLOCK, use8BitStorage|use16BitStorage|allButRelaxed, 50, 200);
1726 createRandomCaseGroup(group, m_testCtx, "all_shared_buffer", "All random features, shared buffer", SSBOLayoutCase::BUFFERMODE_SINGLE, use8BitStorage|use16BitStorage|allButRelaxed, 50, 250);
1727
1728 createRandomCaseGroup(group, m_testCtx, "relaxed", "VK_KHR_relaxed_block_layout", SSBOLayoutCase::BUFFERMODE_SINGLE, use8BitStorage|use16BitStorage|allRelaxed, 100, deInt32Hash(313));
1729 createRandomCaseGroup(group, m_testCtx, "scalar", "VK_EXT_scalar_block_layout", SSBOLayoutCase::BUFFERMODE_SINGLE, use8BitStorage|use16BitStorage|allScalar, 100, deInt32Hash(313));
1730 }
1731 }
1732 }
1733
createUnsizedArrayTests(tcu::TestCaseGroup * testGroup)1734 void createUnsizedArrayTests (tcu::TestCaseGroup* testGroup)
1735 {
1736 const UnsizedArrayCaseParams subcases[] =
1737 {
1738 { 4, 256, false, 256, "float_no_offset_explicit_size" },
1739 { 4, 256, false, VK_WHOLE_SIZE, "float_no_offset_whole_size" },
1740 { 4, 512, true, 32, "float_offset_explicit_size" },
1741 { 4, 512, true, VK_WHOLE_SIZE, "float_offset_whole_size" },
1742 };
1743
1744 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(subcases); ndx++)
1745 {
1746 const UnsizedArrayCaseParams& params = subcases[ndx];
1747 addFunctionCaseWithPrograms<UnsizedArrayCaseParams>(testGroup, params.name, "", createUnsizedArrayLengthProgs, ssboUnsizedArrayLengthTest, params);
1748 }
1749 }
1750
1751 } // anonymous
1752
createTests(tcu::TestContext & testCtx)1753 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
1754 {
1755 de::MovePtr<tcu::TestCaseGroup> ssboTestGroup (new tcu::TestCaseGroup(testCtx, "ssbo", "Shader Storage Buffer Object Tests"));
1756
1757 ssboTestGroup->addChild(new SSBOLayoutTests(testCtx));
1758 addTestGroup(ssboTestGroup.get(), "unsized_array_length", "SSBO unsized array length tests", createUnsizedArrayTests);
1759
1760 return ssboTestGroup.release();
1761 }
1762
1763 } // ssbo
1764 } // vkt
1765