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