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