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