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 Program interface query tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fProgramInterfaceQueryTests.hpp" 25 #include "es31fProgramInterfaceQueryTestCase.hpp" 26 #include "es31fProgramInterfaceDefinition.hpp" 27 #include "es31fProgramInterfaceDefinitionUtil.hpp" 28 #include "tcuTestLog.hpp" 29 #include "gluShaderProgram.hpp" 30 #include "gluVarTypeUtil.hpp" 31 #include "gluStrUtil.hpp" 32 #include "glwFunctions.hpp" 33 #include "glwEnums.hpp" 34 #include "deRandom.hpp" 35 #include "deString.h" 36 #include "deStringUtil.hpp" 37 #include "deSharedPtr.hpp" 38 #include "deUniquePtr.hpp" 39 #include "deSTLUtil.hpp" 40 41 #include <set> 42 #include <map> 43 44 namespace deqp 45 { 46 namespace gles31 47 { 48 namespace Functional 49 { 50 namespace 51 { 52 53 static bool stringEndsWith (const std::string& str, const std::string& suffix) 54 { 55 if (suffix.length() > str.length()) 56 return false; 57 else 58 return str.substr(str.length() - suffix.length()) == suffix; 59 } 60 61 static int getTypeSize (glu::DataType type) 62 { 63 if (type == glu::TYPE_FLOAT) 64 return 4; 65 else if (type == glu::TYPE_INT || type == glu::TYPE_UINT) 66 return 4; 67 else if (type == glu::TYPE_BOOL) 68 return 4; // uint 69 70 DE_ASSERT(false); 71 return 0; 72 } 73 74 static int getVarTypeSize (const glu::VarType& type) 75 { 76 if (type.isBasicType()) 77 return glu::getDataTypeScalarSize(type.getBasicType()) * getTypeSize(glu::getDataTypeScalarType(type.getBasicType())); 78 else if (type.isStructType()) 79 { 80 int size = 0; 81 for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx) 82 size += getVarTypeSize(type.getStructPtr()->getMember(ndx).getType()); 83 return size; 84 } 85 else if (type.isArrayType()) 86 { 87 if (type.getArraySize() == glu::VarType::UNSIZED_ARRAY) 88 return getVarTypeSize(type.getElementType()); 89 else 90 return type.getArraySize() * getVarTypeSize(type.getElementType()); 91 } 92 else 93 { 94 DE_ASSERT(false); 95 return 0; 96 } 97 } 98 99 static std::string convertGLTypeNameToTestName (const char* glName) 100 { 101 // vectors and matrices are fine as is 102 { 103 if (deStringBeginsWith(glName, "vec") == DE_TRUE || 104 deStringBeginsWith(glName, "ivec") == DE_TRUE || 105 deStringBeginsWith(glName, "uvec") == DE_TRUE || 106 deStringBeginsWith(glName, "bvec") == DE_TRUE || 107 deStringBeginsWith(glName, "mat") == DE_TRUE) 108 return std::string(glName); 109 } 110 111 // convert camel case to use underscore 112 { 113 std::ostringstream buf; 114 std::istringstream name (glName); 115 bool mergeNextToken = false; 116 bool previousTokenWasDigit = false; 117 118 while (!name.eof()) 119 { 120 std::ostringstream token; 121 122 while (name.peek() != EOF) 123 { 124 if ((de::isDigit((char)name.peek()) || de::isUpper((char)name.peek())) && token.tellp()) 125 break; 126 127 token << de::toLower((char)name.get()); 128 } 129 130 if (buf.str().empty() || mergeNextToken) 131 buf << token.str(); 132 else 133 buf << '_' << token.str(); 134 135 // Single char causes next char to be merged (don't split initialisms or acronyms) unless it is 'D' after a number (split to ..._2d_acronym_aa 136 mergeNextToken = false; 137 if (token.tellp() == (std::streamoff)1) 138 { 139 if (!previousTokenWasDigit || token.str()[0] != 'd') 140 mergeNextToken = true; 141 142 previousTokenWasDigit = de::isDigit(token.str()[0]); 143 } 144 else 145 previousTokenWasDigit = false; 146 } 147 148 return buf.str(); 149 } 150 } 151 152 static glw::GLenum getProgramInterfaceGLEnum (ProgramInterface interface) 153 { 154 static const glw::GLenum s_enums[] = 155 { 156 GL_UNIFORM, // PROGRAMINTERFACE_UNIFORM 157 GL_UNIFORM_BLOCK, // PROGRAMINTERFACE_UNIFORM_BLOCK 158 GL_ATOMIC_COUNTER_BUFFER, // PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER 159 GL_PROGRAM_INPUT, // PROGRAMINTERFACE_PROGRAM_INPUT 160 GL_PROGRAM_OUTPUT, // PROGRAMINTERFACE_PROGRAM_OUTPUT 161 GL_TRANSFORM_FEEDBACK_VARYING, // PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING 162 GL_BUFFER_VARIABLE, // PROGRAMINTERFACE_BUFFER_VARIABLE 163 GL_SHADER_STORAGE_BLOCK, // PROGRAMINTERFACE_SHADER_STORAGE_BLOCK 164 }; 165 166 return de::getSizedArrayElement<PROGRAMINTERFACE_LAST>(s_enums, interface); 167 168 } 169 170 namespace ResourceDefinition 171 { 172 173 class Node 174 { 175 public: 176 enum NodeType 177 { 178 TYPE_PROGRAM = 0, 179 TYPE_SHADER, 180 TYPE_DEFAULT_BLOCK, 181 TYPE_VARIABLE, 182 TYPE_INTERFACE_BLOCK, 183 TYPE_ARRAY_ELEMENT, 184 TYPE_STRUCT_MEMBER, 185 TYPE_STORAGE_QUALIFIER, 186 TYPE_LAYOUT_QUALIFIER, 187 TYPE_SHADER_SET, 188 TYPE_INTERPOLATION_QUALIFIER, 189 TYPE_TRANSFORM_FEEDBACK_TARGET, 190 191 TYPE_LAST 192 }; 193 194 typedef de::SharedPtr<const Node, de::DefaultDeleter<const Node>, false> SharedPtr; 195 196 Node (NodeType type, const SharedPtr& enclosingNode) : m_type(type), m_enclosingNode(enclosingNode) { DE_ASSERT(type < TYPE_LAST); } 197 virtual ~Node (void) { } 198 199 inline const Node* getEnclosingNode (void) const { return m_enclosingNode.get(); } 200 inline NodeType getType (void) const { return m_type; } 201 202 private: 203 const NodeType m_type; 204 const SharedPtr m_enclosingNode; 205 }; 206 207 class Program : public Node 208 { 209 public: 210 Program (bool separable = false) 211 : Node (TYPE_PROGRAM, SharedPtr()) 212 , m_separable (separable) 213 { 214 } 215 216 const bool m_separable; 217 }; 218 219 class Shader : public Node 220 { 221 public: 222 Shader (const SharedPtr& enclosingNode, glu::ShaderType type, glu::GLSLVersion version) 223 : Node (TYPE_SHADER, enclosingNode) 224 , m_type (type) 225 , m_version (version) 226 { 227 DE_ASSERT(enclosingNode->getType() == TYPE_PROGRAM); 228 } 229 230 const glu::ShaderType m_type; 231 const glu::GLSLVersion m_version; 232 }; 233 234 class DefaultBlock : public Node 235 { 236 public: 237 DefaultBlock (const SharedPtr& enclosing) 238 : Node(TYPE_DEFAULT_BLOCK, enclosing) 239 { 240 // enclosed by the shader 241 DE_ASSERT(enclosing->getType() == TYPE_SHADER || 242 enclosing->getType() == TYPE_SHADER_SET); 243 } 244 }; 245 246 class StorageQualifier : public Node 247 { 248 public: 249 StorageQualifier (const SharedPtr& enclosing, glu::Storage storage) 250 : Node (TYPE_STORAGE_QUALIFIER, enclosing) 251 , m_storage (storage) 252 { 253 // not a part of any block 254 DE_ASSERT(enclosing->getType() == TYPE_DEFAULT_BLOCK); 255 } 256 257 const glu::Storage m_storage; 258 }; 259 260 class Variable : public Node 261 { 262 public: 263 Variable (const SharedPtr& enclosing, glu::DataType dataType) 264 : Node (TYPE_VARIABLE, enclosing) 265 , m_dataType (dataType) 266 { 267 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER || 268 enclosing->getType() == TYPE_LAYOUT_QUALIFIER || 269 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER || 270 enclosing->getType() == TYPE_INTERFACE_BLOCK || 271 enclosing->getType() == TYPE_ARRAY_ELEMENT || 272 enclosing->getType() == TYPE_STRUCT_MEMBER || 273 enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET); 274 } 275 276 const glu::DataType m_dataType; 277 }; 278 279 class InterfaceBlock : public Node 280 { 281 public: 282 InterfaceBlock (const SharedPtr& enclosing, bool named) 283 : Node (TYPE_INTERFACE_BLOCK, enclosing) 284 , m_named (named) 285 { 286 // Must be qualified 287 const Node* storageNode = enclosing.get(); 288 while (storageNode->getType() == TYPE_ARRAY_ELEMENT || storageNode->getType() == TYPE_LAYOUT_QUALIFIER) 289 storageNode = storageNode->getEnclosingNode(); 290 291 DE_ASSERT(storageNode->getType() == TYPE_STORAGE_QUALIFIER); 292 DE_UNREF(storageNode); 293 } 294 295 const bool m_named; 296 }; 297 298 class ArrayElement : public Node 299 { 300 public: 301 ArrayElement (const SharedPtr& enclosing, int arraySize = DEFAULT_SIZE) 302 : Node (TYPE_ARRAY_ELEMENT, enclosing) 303 , m_arraySize (arraySize) 304 { 305 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER || 306 enclosing->getType() == TYPE_LAYOUT_QUALIFIER || 307 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER || 308 enclosing->getType() == TYPE_INTERFACE_BLOCK || 309 enclosing->getType() == TYPE_ARRAY_ELEMENT || 310 enclosing->getType() == TYPE_STRUCT_MEMBER || 311 enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET); 312 } 313 314 const int m_arraySize; 315 316 enum 317 { 318 DEFAULT_SIZE = -1, 319 UNSIZED_ARRAY = -2, 320 }; 321 }; 322 323 class StructMember : public Node 324 { 325 public: 326 StructMember (const SharedPtr& enclosing) 327 : Node(TYPE_STRUCT_MEMBER, enclosing) 328 { 329 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER || 330 enclosing->getType() == TYPE_LAYOUT_QUALIFIER || 331 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER || 332 enclosing->getType() == TYPE_INTERFACE_BLOCK || 333 enclosing->getType() == TYPE_ARRAY_ELEMENT || 334 enclosing->getType() == TYPE_STRUCT_MEMBER || 335 enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET); 336 } 337 }; 338 339 class LayoutQualifier : public Node 340 { 341 public: 342 LayoutQualifier (const SharedPtr& enclosing, const glu::Layout& layout) 343 : Node (TYPE_LAYOUT_QUALIFIER, enclosing) 344 , m_layout (layout) 345 { 346 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER || 347 enclosing->getType() == TYPE_LAYOUT_QUALIFIER || 348 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER || 349 enclosing->getType() == TYPE_DEFAULT_BLOCK || 350 enclosing->getType() == TYPE_INTERFACE_BLOCK); 351 } 352 353 const glu::Layout m_layout; 354 }; 355 356 class InterpolationQualifier : public Node 357 { 358 public: 359 InterpolationQualifier (const SharedPtr& enclosing, const glu::Interpolation& interpolation) 360 : Node (TYPE_INTERPOLATION_QUALIFIER, enclosing) 361 , m_interpolation (interpolation) 362 { 363 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER || 364 enclosing->getType() == TYPE_LAYOUT_QUALIFIER || 365 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER || 366 enclosing->getType() == TYPE_DEFAULT_BLOCK || 367 enclosing->getType() == TYPE_INTERFACE_BLOCK); 368 } 369 370 const glu::Interpolation m_interpolation; 371 }; 372 373 class ShaderSet : public Node 374 { 375 public: 376 ShaderSet (const SharedPtr& enclosing, glu::GLSLVersion version); 377 378 void setStage (glu::ShaderType type, bool referencing); 379 bool isStagePresent (glu::ShaderType stage) const; 380 bool isStageReferencing (glu::ShaderType stage) const; 381 382 const glu::GLSLVersion m_version; 383 private: 384 bool m_stagePresent[glu::SHADERTYPE_LAST]; 385 bool m_stageReferencing[glu::SHADERTYPE_LAST]; 386 }; 387 388 ShaderSet::ShaderSet (const SharedPtr& enclosing, glu::GLSLVersion version) 389 : Node (TYPE_SHADER_SET, enclosing) 390 , m_version (version) 391 { 392 DE_ASSERT(enclosing->getType() == TYPE_PROGRAM); 393 394 deMemset(m_stagePresent, 0, sizeof(m_stagePresent)); 395 deMemset(m_stageReferencing, 0, sizeof(m_stageReferencing)); 396 } 397 398 void ShaderSet::setStage (glu::ShaderType type, bool referencing) 399 { 400 m_stagePresent[type] = true; 401 m_stageReferencing[type] = referencing; 402 } 403 404 bool ShaderSet::isStagePresent (glu::ShaderType stage) const 405 { 406 DE_ASSERT(stage < glu::SHADERTYPE_LAST); 407 return m_stagePresent[stage]; 408 } 409 410 bool ShaderSet::isStageReferencing (glu::ShaderType stage) const 411 { 412 DE_ASSERT(stage < glu::SHADERTYPE_LAST); 413 return m_stageReferencing[stage]; 414 } 415 416 class TransformFeedbackTarget : public Node 417 { 418 public: 419 TransformFeedbackTarget (const SharedPtr& enclosing, const char* builtinVarName = DE_NULL) 420 : Node (TYPE_TRANSFORM_FEEDBACK_TARGET, enclosing) 421 , m_builtinVarName (builtinVarName) 422 { 423 } 424 425 const char* const m_builtinVarName; 426 }; 427 428 } // ResourceDefinition 429 430 static glu::Precision getDataTypeDefaultPrecision (const glu::DataType& type) 431 { 432 if (glu::isDataTypeBoolOrBVec(type)) 433 return glu::PRECISION_LAST; 434 else if (glu::isDataTypeScalarOrVector(type) || glu::isDataTypeMatrix(type)) 435 return glu::PRECISION_HIGHP; 436 else if (glu::isDataTypeSampler(type)) 437 return glu::PRECISION_HIGHP; 438 else if (glu::isDataTypeImage(type)) 439 return glu::PRECISION_HIGHP; 440 else if (type == glu::TYPE_UINT_ATOMIC_COUNTER) 441 return glu::PRECISION_HIGHP; 442 443 DE_ASSERT(false); 444 return glu::PRECISION_LAST; 445 } 446 447 static de::MovePtr<ProgramInterfaceDefinition::Program> generateProgramDefinitionFromResource (const ResourceDefinition::Node* resource) 448 { 449 de::MovePtr<ProgramInterfaceDefinition::Program> program (new ProgramInterfaceDefinition::Program()); 450 const ResourceDefinition::Node* head = resource; 451 452 if (head->getType() == ResourceDefinition::Node::TYPE_VARIABLE) 453 { 454 DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource)); 455 456 enum BindingType 457 { 458 BINDING_VARIABLE, 459 BINDING_INTERFACE_BLOCK, 460 BINDING_DEFAULT_BLOCK 461 }; 462 463 int structNdx = 0; 464 int autoAssignArraySize = 0; 465 const glu::DataType basicType = static_cast<const ResourceDefinition::Variable*>(resource)->m_dataType; 466 BindingType boundObject = BINDING_VARIABLE; 467 glu::VariableDeclaration variable (glu::VarType(basicType, getDataTypeDefaultPrecision(basicType)), "target"); 468 glu::InterfaceBlock interfaceBlock; 469 ProgramInterfaceDefinition::DefaultBlock defaultBlock; 470 std::vector<std::string> feedbackTargetVaryingPath; 471 bool feedbackTargetSet = false; 472 473 // image specific 474 if (glu::isDataTypeImage(basicType)) 475 { 476 variable.memoryAccessQualifierBits |= glu::MEMORYACCESSQUALIFIER_READONLY_BIT; 477 variable.layout.binding = 1; 478 479 if (basicType >= glu::TYPE_IMAGE_2D && basicType <= glu::TYPE_IMAGE_3D) 480 variable.layout.format = glu::FORMATLAYOUT_RGBA8; 481 else if (basicType >= glu::TYPE_INT_IMAGE_2D && basicType <= glu::TYPE_INT_IMAGE_3D) 482 variable.layout.format = glu::FORMATLAYOUT_RGBA8I; 483 else if (basicType >= glu::TYPE_UINT_IMAGE_2D && basicType <= glu::TYPE_UINT_IMAGE_3D) 484 variable.layout.format = glu::FORMATLAYOUT_RGBA8UI; 485 else 486 DE_ASSERT(false); 487 } 488 489 // atomic counter specific 490 if (basicType == glu::TYPE_UINT_ATOMIC_COUNTER) 491 variable.layout.binding = 1; 492 493 for (head = head->getEnclosingNode(); head; head = head->getEnclosingNode()) 494 { 495 if (head->getType() == ResourceDefinition::Node::TYPE_STORAGE_QUALIFIER) 496 { 497 const ResourceDefinition::StorageQualifier* qualifier = static_cast<const ResourceDefinition::StorageQualifier*>(head); 498 499 DE_ASSERT(dynamic_cast<const ResourceDefinition::StorageQualifier*>(head)); 500 501 if (boundObject == BINDING_VARIABLE) 502 { 503 DE_ASSERT(variable.storage == glu::STORAGE_LAST); 504 variable.storage = qualifier->m_storage; 505 } 506 else if (boundObject == BINDING_INTERFACE_BLOCK) 507 { 508 DE_ASSERT(interfaceBlock.storage == glu::STORAGE_LAST); 509 interfaceBlock.storage = qualifier->m_storage; 510 } 511 else 512 DE_ASSERT(false); 513 } 514 else if (head->getType() == ResourceDefinition::Node::TYPE_LAYOUT_QUALIFIER) 515 { 516 const ResourceDefinition::LayoutQualifier* qualifier = static_cast<const ResourceDefinition::LayoutQualifier*>(head); 517 glu::Layout* targetLayout = DE_NULL; 518 519 DE_ASSERT(dynamic_cast<const ResourceDefinition::LayoutQualifier*>(head)); 520 521 if (boundObject == BINDING_VARIABLE) 522 targetLayout = &variable.layout; 523 else if (boundObject == BINDING_INTERFACE_BLOCK) 524 targetLayout = &interfaceBlock.layout; 525 else 526 DE_ASSERT(false); 527 528 if (qualifier->m_layout.location != -1) 529 targetLayout->location = qualifier->m_layout.location; 530 531 if (qualifier->m_layout.binding != -1) 532 targetLayout->binding = qualifier->m_layout.binding; 533 534 if (qualifier->m_layout.offset != -1) 535 targetLayout->offset = qualifier->m_layout.offset; 536 537 if (qualifier->m_layout.format != glu::FORMATLAYOUT_LAST) 538 targetLayout->format = qualifier->m_layout.format; 539 540 if (qualifier->m_layout.matrixOrder != glu::MATRIXORDER_LAST) 541 targetLayout->matrixOrder = qualifier->m_layout.matrixOrder; 542 } 543 else if (head->getType() == ResourceDefinition::Node::TYPE_INTERPOLATION_QUALIFIER) 544 { 545 const ResourceDefinition::InterpolationQualifier* qualifier = static_cast<const ResourceDefinition::InterpolationQualifier*>(head); 546 547 DE_ASSERT(dynamic_cast<const ResourceDefinition::InterpolationQualifier*>(head)); 548 549 if (boundObject == BINDING_VARIABLE) 550 variable.interpolation = qualifier->m_interpolation; 551 else 552 DE_ASSERT(false); 553 } 554 else if (head->getType() == ResourceDefinition::Node::TYPE_ARRAY_ELEMENT) 555 { 556 DE_ASSERT(dynamic_cast<const ResourceDefinition::ArrayElement*>(head)); 557 558 const ResourceDefinition::ArrayElement* arrayElement = static_cast<const ResourceDefinition::ArrayElement*>(head); 559 int arraySize; 560 561 // Vary array size per level 562 if (arrayElement->m_arraySize == ResourceDefinition::ArrayElement::DEFAULT_SIZE) 563 { 564 if (--autoAssignArraySize <= 1) 565 autoAssignArraySize = 3; 566 567 arraySize = autoAssignArraySize; 568 } 569 else if (arrayElement->m_arraySize == ResourceDefinition::ArrayElement::UNSIZED_ARRAY) 570 arraySize = glu::VarType::UNSIZED_ARRAY; 571 else 572 arraySize = arrayElement->m_arraySize; 573 574 if (boundObject == BINDING_VARIABLE) 575 variable.varType = glu::VarType(variable.varType, arraySize); 576 else if (boundObject == BINDING_INTERFACE_BLOCK) 577 interfaceBlock.dimensions.push_back(arraySize); 578 else 579 DE_ASSERT(false); 580 581 if (feedbackTargetSet) 582 feedbackTargetVaryingPath.back().append("[0]"); 583 } 584 else if (head->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER) 585 { 586 DE_ASSERT(dynamic_cast<const ResourceDefinition::StructMember*>(head)); 587 DE_ASSERT(boundObject == BINDING_VARIABLE); 588 589 // Struct members cannot contain any qualifiers except precision 590 DE_ASSERT(variable.interpolation == glu::INTERPOLATION_LAST); 591 DE_ASSERT(variable.layout == glu::Layout()); 592 DE_ASSERT(variable.memoryAccessQualifierBits == 0); 593 DE_ASSERT(variable.storage == glu::STORAGE_LAST); 594 595 { 596 glu::StructType* structPtr = new glu::StructType(("StructType" + de::toString(structNdx++)).c_str()); 597 structPtr->addMember(variable.name.c_str(), variable.varType); 598 599 variable = glu::VariableDeclaration(glu::VarType(structPtr), "target"); 600 } 601 602 if (feedbackTargetSet) 603 feedbackTargetVaryingPath.push_back("target"); 604 } 605 else if (head->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK) 606 { 607 DE_ASSERT(dynamic_cast<const ResourceDefinition::InterfaceBlock*>(head)); 608 DE_ASSERT(boundObject == BINDING_VARIABLE); 609 610 const bool named = static_cast<const ResourceDefinition::InterfaceBlock*>(head)->m_named; 611 612 boundObject = BINDING_INTERFACE_BLOCK; 613 614 interfaceBlock.interfaceName = "TargetInterface"; 615 interfaceBlock.instanceName = (named) ? ("targetInstance") : (""); 616 interfaceBlock.variables.push_back(variable); 617 618 if (feedbackTargetSet && !interfaceBlock.instanceName.empty()) 619 feedbackTargetVaryingPath.push_back(interfaceBlock.interfaceName); 620 } 621 else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK) 622 { 623 DE_ASSERT(dynamic_cast<const ResourceDefinition::DefaultBlock*>(head)); 624 DE_ASSERT(boundObject == BINDING_VARIABLE || boundObject == BINDING_INTERFACE_BLOCK); 625 626 if (boundObject == BINDING_VARIABLE) 627 defaultBlock.variables.push_back(variable); 628 else if (boundObject == BINDING_INTERFACE_BLOCK) 629 defaultBlock.interfaceBlocks.push_back(interfaceBlock); 630 else 631 DE_ASSERT(false); 632 633 boundObject = BINDING_DEFAULT_BLOCK; 634 } 635 else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER) 636 { 637 DE_ASSERT(dynamic_cast<const ResourceDefinition::Shader*>(head)); 638 639 const ResourceDefinition::Shader* shaderDef = static_cast<const ResourceDefinition::Shader*>(head); 640 ProgramInterfaceDefinition::Shader* shader = program->addShader(shaderDef->m_type, shaderDef->m_version); 641 642 shader->getDefaultBlock() = defaultBlock; 643 } 644 else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER_SET) 645 { 646 DE_ASSERT(dynamic_cast<const ResourceDefinition::ShaderSet*>(head)); 647 648 const ResourceDefinition::ShaderSet* shaderDef = static_cast<const ResourceDefinition::ShaderSet*>(head); 649 650 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType) 651 { 652 if (shaderDef->isStagePresent((glu::ShaderType)shaderType)) 653 { 654 ProgramInterfaceDefinition::Shader* shader = program->addShader((glu::ShaderType)shaderType, shaderDef->m_version); 655 656 if (shaderDef->isStageReferencing((glu::ShaderType)shaderType)) 657 shader->getDefaultBlock() = defaultBlock; 658 } 659 } 660 } 661 else if (head->getType() == ResourceDefinition::Node::TYPE_PROGRAM) 662 { 663 DE_ASSERT(dynamic_cast<const ResourceDefinition::Program*>(head)); 664 665 const ResourceDefinition::Program* programDef = static_cast<const ResourceDefinition::Program*>(head); 666 667 program->setSeparable(programDef->m_separable); 668 669 DE_ASSERT(feedbackTargetSet == !feedbackTargetVaryingPath.empty()); 670 if (!feedbackTargetVaryingPath.empty()) 671 { 672 std::ostringstream buf; 673 674 for (std::vector<std::string>::reverse_iterator it = feedbackTargetVaryingPath.rbegin(); it != feedbackTargetVaryingPath.rend(); ++it) 675 { 676 if (it != feedbackTargetVaryingPath.rbegin()) 677 buf << "."; 678 buf << *it; 679 } 680 681 program->addTransformFeedbackVarying(buf.str()); 682 program->setTransformFeedbackMode(GL_INTERLEAVED_ATTRIBS); 683 } 684 break; 685 } 686 else if (head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET) 687 { 688 DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(head)); 689 690 const ResourceDefinition::TransformFeedbackTarget* feedbackTarget = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(head); 691 692 DE_ASSERT(feedbackTarget->m_builtinVarName == DE_NULL); 693 DE_UNREF(feedbackTarget); 694 695 feedbackTargetSet = true; 696 feedbackTargetVaryingPath.push_back(variable.name); 697 } 698 else 699 { 700 DE_ASSERT(DE_FALSE); 701 break; 702 } 703 } 704 } 705 else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK || 706 head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET) 707 { 708 const char* feedbackTargetVaryingName = DE_NULL; 709 710 // empty default block 711 712 for (; head; head = head->getEnclosingNode()) 713 { 714 if (head->getType() == ResourceDefinition::Node::TYPE_SHADER) 715 { 716 DE_ASSERT(dynamic_cast<const ResourceDefinition::Shader*>(head)); 717 718 const ResourceDefinition::Shader* shaderDef = static_cast<const ResourceDefinition::Shader*>(head); 719 720 program->addShader(shaderDef->m_type, shaderDef->m_version); 721 } 722 else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER_SET) 723 { 724 DE_ASSERT(dynamic_cast<const ResourceDefinition::ShaderSet*>(head)); 725 726 const ResourceDefinition::ShaderSet* shaderDef = static_cast<const ResourceDefinition::ShaderSet*>(head); 727 728 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType) 729 if (shaderDef->isStagePresent((glu::ShaderType)shaderType)) 730 program->addShader((glu::ShaderType)shaderType, shaderDef->m_version); 731 } 732 else if (head->getType() == ResourceDefinition::Node::TYPE_PROGRAM) 733 { 734 DE_ASSERT(dynamic_cast<const ResourceDefinition::Program*>(head)); 735 736 const ResourceDefinition::Program* programDef = static_cast<const ResourceDefinition::Program*>(head); 737 738 program->setSeparable(programDef->m_separable); 739 if (feedbackTargetVaryingName) 740 { 741 program->addTransformFeedbackVarying(std::string(feedbackTargetVaryingName)); 742 program->setTransformFeedbackMode(GL_INTERLEAVED_ATTRIBS); 743 } 744 break; 745 } 746 else if (head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET) 747 { 748 DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(head)); 749 750 const ResourceDefinition::TransformFeedbackTarget* feedbackTarget = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(head); 751 752 DE_ASSERT(feedbackTarget->m_builtinVarName != DE_NULL); 753 754 feedbackTargetVaryingName = feedbackTarget->m_builtinVarName; 755 } 756 else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK) 757 { 758 } 759 else 760 { 761 DE_ASSERT(DE_FALSE); 762 break; 763 } 764 } 765 } 766 767 return program; 768 } 769 770 static void checkAndLogProgram (const glu::ShaderProgram& program, const ProgramInterfaceDefinition::Program* programDefinition, const glw::Functions& gl, tcu::TestLog& log) 771 { 772 const tcu::ScopedLogSection section(log, "Program", "Program"); 773 774 log << program; 775 if (!program.isOk()) 776 { 777 log << tcu::TestLog::Message << "Program build failed, checking if program exceeded implementation limits" << tcu::TestLog::EndMessage; 778 checkProgramResourceUsage(programDefinition, gl, log); 779 780 // within limits 781 throw tcu::TestError("could not build program"); 782 } 783 } 784 785 // Resource list query case 786 787 class ResourceListTestCase : public TestCase 788 { 789 public: 790 ResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramInterface& interface, const char* name = DE_NULL); 791 ~ResourceListTestCase (void); 792 793 protected: 794 void deinit (void); 795 IterateResult iterate (void); 796 797 void queryResourceList (std::vector<std::string>& dst, glw::GLuint program); 798 bool verifyResourceList (const std::vector<std::string>& resourceList, const std::vector<std::string>& expectedResources); 799 bool verifyResourceIndexQuery (const std::vector<std::string>& resourceList, const std::vector<std::string>& referenceResources, glw::GLuint program); 800 bool verifyMaxNameLength (const std::vector<std::string>& referenceResourceList, glw::GLuint program); 801 802 static std::string genTestCaseName (const ResourceDefinition::Node*); 803 804 const ProgramInterface m_programInterface; 805 ResourceDefinition::Node::SharedPtr m_targetResource; 806 }; 807 808 ResourceListTestCase::ResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramInterface& interface, const char* name) 809 : TestCase (context, (name == DE_NULL) ? (genTestCaseName(targetResource.get()).c_str()) : (name), "") 810 , m_programInterface (interface) 811 , m_targetResource (targetResource) 812 { 813 // GL_ATOMIC_COUNTER_BUFFER: no resource names 814 DE_ASSERT(m_programInterface != PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER); 815 } 816 817 ResourceListTestCase::~ResourceListTestCase (void) 818 { 819 deinit(); 820 } 821 822 void ResourceListTestCase::deinit (void) 823 { 824 m_targetResource.clear(); 825 } 826 827 ResourceListTestCase::IterateResult ResourceListTestCase::iterate (void) 828 { 829 const de::UniquePtr<ProgramInterfaceDefinition::Program> programDefinition (generateProgramDefinitionFromResource(m_targetResource.get())); 830 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(programDefinition.get())); 831 832 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 833 checkAndLogProgram(program, programDefinition.get(), m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 834 835 // Check resource list 836 { 837 const tcu::ScopedLogSection section (m_testCtx.getLog(), "ResourceList", "Resource list"); 838 std::vector<std::string> resourceList; 839 std::vector<std::string> expectedResources; 840 841 queryResourceList(resourceList, program.getProgram()); 842 expectedResources = getProgramInterfaceResourceList(programDefinition.get(), m_programInterface); 843 844 // verify the list and the expected list match 845 846 if (!verifyResourceList(resourceList, expectedResources)) 847 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid resource list"); 848 849 // verify GetProgramResourceIndex() matches the indices of the list 850 851 if (!verifyResourceIndexQuery(resourceList, expectedResources, program.getProgram())) 852 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GetProgramResourceIndex returned unexpected values"); 853 854 // Verify MAX_NAME_LENGTH 855 if (!verifyMaxNameLength(resourceList, program.getProgram())) 856 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "MAX_NAME_LENGTH invalid"); 857 } 858 859 return STOP; 860 } 861 862 void ResourceListTestCase::queryResourceList (std::vector<std::string>& dst, glw::GLuint program) 863 { 864 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 865 const glw::GLenum programInterface = getProgramInterfaceGLEnum(m_programInterface); 866 glw::GLint numActiveResources = 0; 867 glw::GLint maxNameLength = 0; 868 std::vector<char> buffer; 869 870 m_testCtx.getLog() << tcu::TestLog::Message << "Querying " << glu::getProgramInterfaceName(programInterface) << " interface:" << tcu::TestLog::EndMessage; 871 872 gl.getProgramInterfaceiv(program, programInterface, GL_ACTIVE_RESOURCES, &numActiveResources); 873 gl.getProgramInterfaceiv(program, programInterface, GL_MAX_NAME_LENGTH, &maxNameLength); 874 GLU_EXPECT_NO_ERROR(gl.getError(), "query interface"); 875 876 m_testCtx.getLog() << tcu::TestLog::Message 877 << "\tGL_ACTIVE_RESOURCES = " << numActiveResources << "\n" 878 << "\tGL_MAX_NAME_LENGTH = " << maxNameLength 879 << tcu::TestLog::EndMessage; 880 881 m_testCtx.getLog() << tcu::TestLog::Message << "Querying all active resources" << tcu::TestLog::EndMessage; 882 883 buffer.resize(maxNameLength+1, '\0'); 884 885 for (int resourceNdx = 0; resourceNdx < numActiveResources; ++resourceNdx) 886 { 887 glw::GLint written = 0; 888 889 gl.getProgramResourceName(program, programInterface, resourceNdx, maxNameLength, &written, &buffer[0]); 890 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource name"); 891 892 dst.push_back(std::string(&buffer[0], written)); 893 } 894 } 895 896 bool ResourceListTestCase::verifyResourceList (const std::vector<std::string>& resourceList, const std::vector<std::string>& expectedResources) 897 { 898 bool error = false; 899 900 // Log and compare resource lists 901 902 m_testCtx.getLog() << tcu::TestLog::Message << "GL returned resources:" << tcu::TestLog::EndMessage; 903 904 for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx) 905 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << ndx << ": " << resourceList[ndx] << tcu::TestLog::EndMessage; 906 907 m_testCtx.getLog() << tcu::TestLog::Message << "Expected list of resources:" << tcu::TestLog::EndMessage; 908 909 for (int ndx = 0; ndx < (int)expectedResources.size(); ++ndx) 910 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << ndx << ": " << expectedResources[ndx] << tcu::TestLog::EndMessage; 911 912 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying resource list contents." << tcu::TestLog::EndMessage; 913 914 for (int ndx = 0; ndx < (int)expectedResources.size(); ++ndx) 915 { 916 if (!de::contains(resourceList.begin(), resourceList.end(), expectedResources[ndx])) 917 { 918 m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource list did not contain active resource " << expectedResources[ndx] << tcu::TestLog::EndMessage; 919 error = true; 920 } 921 } 922 923 for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx) 924 { 925 if (!de::contains(expectedResources.begin(), expectedResources.end(), resourceList[ndx])) 926 { 927 // Ignore all builtin variables, mismatch causes errors otherwise 928 if (deStringBeginsWith(resourceList[ndx].c_str(), "gl_") == DE_FALSE) 929 { 930 m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource list contains unexpected resource name " << resourceList[ndx] << tcu::TestLog::EndMessage; 931 error = true; 932 } 933 else 934 m_testCtx.getLog() << tcu::TestLog::Message << "Note, resource list contains unknown built-in " << resourceList[ndx] << ". This variable is ignored." << tcu::TestLog::EndMessage; 935 } 936 } 937 938 return !error; 939 } 940 941 bool ResourceListTestCase::verifyResourceIndexQuery (const std::vector<std::string>& resourceList, const std::vector<std::string>& referenceResources, glw::GLuint program) 942 { 943 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 944 const glw::GLenum programInterface = getProgramInterfaceGLEnum(m_programInterface); 945 bool error = false; 946 947 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying GetProgramResourceIndex returns correct indices for resource names." << tcu::TestLog::EndMessage; 948 949 for (int ndx = 0; ndx < (int)referenceResources.size(); ++ndx) 950 { 951 const glw::GLuint index = gl.getProgramResourceIndex(program, programInterface, referenceResources[ndx].c_str()); 952 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index"); 953 954 if (index == GL_INVALID_INDEX) 955 { 956 m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource \"" << referenceResources[ndx] << "\" got index GL_INVALID_INDEX." << tcu::TestLog::EndMessage; 957 error = true; 958 } 959 else if ((int)index >= (int)resourceList.size()) 960 { 961 m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource \"" << referenceResources[ndx] << "\" got index " << index << " (larger or equal to GL_ACTIVE_RESOURCES)." << tcu::TestLog::EndMessage; 962 error = true; 963 } 964 else if (resourceList[index] != referenceResources[ndx]) 965 { 966 m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource \"" << referenceResources[ndx] << "\" got index (index = " << index << ") of another resource (" << resourceList[index] << ")." << tcu::TestLog::EndMessage; 967 error = true; 968 } 969 } 970 971 // Query for "name" should match "name[0]" except for XFB 972 973 if (m_programInterface != PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING) 974 { 975 for (int ndx = 0; ndx < (int)referenceResources.size(); ++ndx) 976 { 977 if (stringEndsWith(referenceResources[ndx], "[0]")) 978 { 979 const std::string queryString = referenceResources[ndx].substr(0, referenceResources[ndx].length()-3); 980 const glw::GLuint index = gl.getProgramResourceIndex(program, programInterface, queryString.c_str()); 981 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index"); 982 983 if (index == GL_INVALID_INDEX) 984 { 985 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for \"" << queryString << "\" resulted in index GL_INVALID_INDEX." << tcu::TestLog::EndMessage; 986 error = true; 987 } 988 else if ((int)index >= (int)resourceList.size()) 989 { 990 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for \"" << queryString << "\" resulted in index " << index << " (larger or equal to GL_ACTIVE_RESOURCES)." << tcu::TestLog::EndMessage; 991 error = true; 992 } 993 else if (resourceList[index] != queryString + "[0]") 994 { 995 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for \"" << queryString << "\" got index (index = " << index << ") of another resource (\"" << resourceList[index] << "\")." << tcu::TestLog::EndMessage; 996 error = true; 997 } 998 } 999 } 1000 } 1001 1002 return !error; 1003 } 1004 1005 bool ResourceListTestCase::verifyMaxNameLength (const std::vector<std::string>& resourceList, glw::GLuint program) 1006 { 1007 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1008 const glw::GLenum programInterface = getProgramInterfaceGLEnum(m_programInterface); 1009 glw::GLint maxNameLength = 0; 1010 glw::GLint expectedMaxNameLength = 0; 1011 1012 gl.getProgramInterfaceiv(program, programInterface, GL_MAX_NAME_LENGTH, &maxNameLength); 1013 GLU_EXPECT_NO_ERROR(gl.getError(), "query interface"); 1014 1015 for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx) 1016 expectedMaxNameLength = de::max(expectedMaxNameLength, (int)resourceList[ndx].size() + 1); 1017 1018 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying MAX_NAME_LENGTH, expecting " << expectedMaxNameLength << " (i.e. consistent with the queried resource list)" << tcu::TestLog::EndMessage; 1019 1020 if (expectedMaxNameLength != maxNameLength) 1021 { 1022 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got " << maxNameLength << tcu::TestLog::EndMessage; 1023 return false; 1024 } 1025 1026 return true; 1027 } 1028 1029 std::string ResourceListTestCase::genTestCaseName (const ResourceDefinition::Node* root) 1030 { 1031 std::ostringstream buf; 1032 buf << "var"; 1033 1034 for (const ResourceDefinition::Node* node = root; node; node = node->getEnclosingNode()) 1035 { 1036 if (node->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER) 1037 buf << "_struct"; 1038 if (node->getType() == ResourceDefinition::Node::TYPE_ARRAY_ELEMENT) 1039 buf << "_array"; 1040 } 1041 1042 return buf.str(); 1043 } 1044 1045 // Resouce property query case 1046 1047 class ResourceTestCase : public ProgramInterfaceQueryTestCase 1048 { 1049 public: 1050 ResourceTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramResourceQueryTestTarget& queryTarget, const char* name = DE_NULL); 1051 ~ResourceTestCase (void); 1052 1053 private: 1054 void init (void); 1055 void deinit (void); 1056 ProgramInterfaceDefinition::Program* getProgramDefinition (void); 1057 std::vector<std::string> getQueryTargetResources (void); 1058 1059 static std::string genTestCaseName (const ResourceDefinition::Node*); 1060 static std::string genMultilineDescription (const ResourceDefinition::Node*); 1061 1062 ResourceDefinition::Node::SharedPtr m_targetResource; 1063 ProgramInterfaceDefinition::Program* m_program; 1064 std::vector<std::string> m_targetResources; 1065 }; 1066 1067 ResourceTestCase::ResourceTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramResourceQueryTestTarget& queryTarget, const char* name) 1068 : ProgramInterfaceQueryTestCase (context, (name == DE_NULL) ? (genTestCaseName(targetResource.get()).c_str()) : (name), "", queryTarget) 1069 , m_targetResource (targetResource) 1070 , m_program (DE_NULL) 1071 { 1072 } 1073 1074 ResourceTestCase::~ResourceTestCase (void) 1075 { 1076 deinit(); 1077 } 1078 1079 void ResourceTestCase::init (void) 1080 { 1081 m_testCtx.getLog() 1082 << tcu::TestLog::Message 1083 << genMultilineDescription(m_targetResource.get()) 1084 << tcu::TestLog::EndMessage; 1085 1086 // Program 1087 { 1088 // Generate interface with target resource 1089 m_program = generateProgramDefinitionFromResource(m_targetResource.get()).release(); 1090 m_targetResources = getProgramInterfaceResourceList(m_program, getTargetInterface()); 1091 } 1092 } 1093 1094 void ResourceTestCase::deinit (void) 1095 { 1096 m_targetResource.clear(); 1097 1098 delete m_program; 1099 m_program = DE_NULL; 1100 1101 m_targetResources = std::vector<std::string>(); 1102 } 1103 1104 ProgramInterfaceDefinition::Program* ResourceTestCase::getProgramDefinition (void) 1105 { 1106 return m_program; 1107 } 1108 1109 std::vector<std::string> ResourceTestCase::getQueryTargetResources (void) 1110 { 1111 return m_targetResources; 1112 } 1113 1114 std::string ResourceTestCase::genTestCaseName (const ResourceDefinition::Node* resource) 1115 { 1116 if (resource->getType() == ResourceDefinition::Node::TYPE_VARIABLE) 1117 { 1118 DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource)); 1119 1120 const ResourceDefinition::Variable* variable = static_cast<const ResourceDefinition::Variable*>(resource); 1121 1122 return convertGLTypeNameToTestName(glu::getDataTypeName(variable->m_dataType)); 1123 } 1124 1125 DE_ASSERT(false); 1126 return ""; 1127 } 1128 1129 std::string ResourceTestCase::genMultilineDescription (const ResourceDefinition::Node* resource) 1130 { 1131 if (resource->getType() == ResourceDefinition::Node::TYPE_VARIABLE) 1132 { 1133 DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource)); 1134 1135 const ResourceDefinition::Variable* varDef = static_cast<const ResourceDefinition::Variable*>(resource); 1136 std::ostringstream buf; 1137 std::ostringstream structureDescriptor; 1138 std::string uniformType; 1139 1140 for (const ResourceDefinition::Node* node = resource; node; node = node->getEnclosingNode()) 1141 { 1142 if (node->getType() == ResourceDefinition::Node::TYPE_STORAGE_QUALIFIER) 1143 { 1144 DE_ASSERT(dynamic_cast<const ResourceDefinition::StorageQualifier*>(node)); 1145 1146 const ResourceDefinition::StorageQualifier* storageDef = static_cast<const ResourceDefinition::StorageQualifier*>(node); 1147 1148 uniformType = std::string(" ") + glu::getStorageName(storageDef->m_storage); 1149 structureDescriptor << "\n\tdeclared as " << glu::getStorageName(storageDef->m_storage); 1150 } 1151 1152 if (node->getType() == ResourceDefinition::Node::TYPE_ARRAY_ELEMENT) 1153 structureDescriptor << "\n\tarray"; 1154 1155 if (node->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER) 1156 structureDescriptor << "\n\tin a struct"; 1157 1158 if (node->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK) 1159 structureDescriptor << "\n\tin the default block"; 1160 1161 if (node->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK) 1162 structureDescriptor << "\n\tin an interface block"; 1163 } 1164 1165 buf << "Querying properties of " << glu::getDataTypeName(varDef->m_dataType) << uniformType << " variable.\n" 1166 << "Variable is:\n" 1167 << "\t" << glu::getDataTypeName(varDef->m_dataType) 1168 << structureDescriptor.str(); 1169 1170 return buf.str(); 1171 } 1172 else if (resource->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET) 1173 { 1174 DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(resource)); 1175 1176 const ResourceDefinition::TransformFeedbackTarget* xfbDef = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(resource); 1177 1178 DE_ASSERT(xfbDef->m_builtinVarName); 1179 1180 return std::string("Querying properties of a builtin variable ") + xfbDef->m_builtinVarName; 1181 } 1182 1183 DE_ASSERT(false); 1184 return DE_NULL; 1185 } 1186 1187 class ResourceNameBufferLimitCase : public TestCase 1188 { 1189 public: 1190 ResourceNameBufferLimitCase (Context& context, const char* name, const char* description); 1191 ~ResourceNameBufferLimitCase (void); 1192 1193 private: 1194 IterateResult iterate (void); 1195 }; 1196 1197 ResourceNameBufferLimitCase::ResourceNameBufferLimitCase (Context& context, const char* name, const char* description) 1198 : TestCase(context, name, description) 1199 { 1200 } 1201 1202 ResourceNameBufferLimitCase::~ResourceNameBufferLimitCase (void) 1203 { 1204 } 1205 1206 ResourceNameBufferLimitCase::IterateResult ResourceNameBufferLimitCase::iterate (void) 1207 { 1208 static const char* const computeSource = "#version 310 es\n" 1209 "layout(local_size_x = 1) in;\n" 1210 "uniform highp int u_uniformWithALongName;\n" 1211 "writeonly buffer OutputBufferBlock { highp int b_output_int; };\n" 1212 "void main ()\n" 1213 "{\n" 1214 " b_output_int = u_uniformWithALongName;\n" 1215 "}\n"; 1216 1217 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1218 const glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(computeSource)); 1219 glw::GLuint uniformIndex; 1220 1221 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1222 1223 // Log program 1224 { 1225 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program"); 1226 1227 m_testCtx.getLog() << program; 1228 if (!program.isOk()) 1229 throw tcu::TestError("could not build program"); 1230 } 1231 1232 uniformIndex = gl.getProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_uniformWithALongName"); 1233 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index"); 1234 1235 if (uniformIndex == GL_INVALID_INDEX) 1236 throw tcu::TestError("Uniform u_uniformWithALongName resource index was GL_INVALID_INDEX"); 1237 1238 // Query with different sized buffers, len("u_uniformWithALongName") == 22 1239 1240 { 1241 static const struct 1242 { 1243 const char* description; 1244 int querySize; 1245 bool returnLength; 1246 } querySizes[] = 1247 { 1248 { "Query to larger buffer", 24, true }, 1249 { "Query to buffer the same size", 23, true }, 1250 { "Query to one byte too small buffer", 22, true }, 1251 { "Query to one byte buffer", 1, true }, 1252 { "Query to zero sized buffer", 0, true }, 1253 { "Query to one byte too small buffer, null length argument", 22, false }, 1254 { "Query to one byte buffer, null length argument", 1, false }, 1255 { "Query to zero sized buffer, null length argument", 0, false }, 1256 }; 1257 1258 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(querySizes); ++ndx) 1259 { 1260 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Query", querySizes[ndx].description); 1261 const int uniformNameLen = 22; 1262 const int expectedWriteLen = (querySizes[ndx].querySize != 0) ? (de::min(uniformNameLen, (querySizes[ndx].querySize - 1))) : (0); 1263 char buffer [26]; 1264 glw::GLsizei written = -1; 1265 1266 // One byte for guard 1267 DE_ASSERT((int)sizeof(buffer) > querySizes[ndx].querySize); 1268 1269 deMemset(buffer, 'x', sizeof(buffer)); 1270 1271 if (querySizes[ndx].querySize) 1272 m_testCtx.getLog() 1273 << tcu::TestLog::Message 1274 << "Querying uniform name to a buffer of size " << querySizes[ndx].querySize 1275 << ", expecting query to write " << expectedWriteLen << " bytes followed by a null terminator" 1276 << tcu::TestLog::EndMessage; 1277 else 1278 m_testCtx.getLog() 1279 << tcu::TestLog::Message 1280 << "Querying uniform name to a buffer of size " << querySizes[ndx].querySize 1281 << ", expecting query to write 0 bytes" 1282 << tcu::TestLog::EndMessage; 1283 1284 gl.getProgramResourceName(program.getProgram(), GL_UNIFORM, uniformIndex, querySizes[ndx].querySize, (querySizes[ndx].returnLength) ? (&written) : (DE_NULL), buffer); 1285 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource name"); 1286 1287 if (querySizes[ndx].returnLength && written != expectedWriteLen) 1288 { 1289 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected write length of " << expectedWriteLen << ", got " << written << tcu::TestLog::EndMessage; 1290 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected write lenght"); 1291 } 1292 else if (querySizes[ndx].querySize != 0 && buffer[expectedWriteLen] != 0) 1293 { 1294 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected null terminator at " << expectedWriteLen << ", got dec=" << (int)buffer[expectedWriteLen] << tcu::TestLog::EndMessage; 1295 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Missing null terminator"); 1296 } 1297 else if (querySizes[ndx].querySize != 0 && buffer[expectedWriteLen+1] != 'x') 1298 { 1299 m_testCtx.getLog() << tcu::TestLog::Message << "Error, guard at index " << (expectedWriteLen+1) << " was modified, got dec=" << (int)buffer[expectedWriteLen+1] << tcu::TestLog::EndMessage; 1300 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Wrote over buffer size"); 1301 } 1302 else if (querySizes[ndx].querySize == 0 && buffer[0] != 'x') 1303 { 1304 m_testCtx.getLog() << tcu::TestLog::Message << "Error, buffer size was 0 but buffer contents were modified. At index 0 got dec=" << (int)buffer[0] << tcu::TestLog::EndMessage; 1305 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents were modified"); 1306 } 1307 } 1308 } 1309 1310 return STOP; 1311 } 1312 1313 class ResourceQueryBufferLimitCase : public TestCase 1314 { 1315 public: 1316 ResourceQueryBufferLimitCase (Context& context, const char* name, const char* description); 1317 ~ResourceQueryBufferLimitCase (void); 1318 1319 private: 1320 IterateResult iterate (void); 1321 }; 1322 1323 ResourceQueryBufferLimitCase::ResourceQueryBufferLimitCase (Context& context, const char* name, const char* description) 1324 : TestCase(context, name, description) 1325 { 1326 } 1327 1328 ResourceQueryBufferLimitCase::~ResourceQueryBufferLimitCase (void) 1329 { 1330 } 1331 1332 ResourceQueryBufferLimitCase::IterateResult ResourceQueryBufferLimitCase::iterate (void) 1333 { 1334 static const char* const computeSource = "#version 310 es\n" 1335 "layout(local_size_x = 1) in;\n" 1336 "uniform highp int u_uniform;\n" 1337 "writeonly buffer OutputBufferBlock { highp int b_output_int; };\n" 1338 "void main ()\n" 1339 "{\n" 1340 " b_output_int = u_uniform;\n" 1341 "}\n"; 1342 1343 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1344 const glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(computeSource)); 1345 glw::GLuint uniformIndex; 1346 1347 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1348 1349 // Log program 1350 { 1351 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program"); 1352 1353 m_testCtx.getLog() << program; 1354 if (!program.isOk()) 1355 throw tcu::TestError("could not build program"); 1356 } 1357 1358 uniformIndex = gl.getProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_uniform"); 1359 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index"); 1360 1361 if (uniformIndex == GL_INVALID_INDEX) 1362 throw tcu::TestError("Uniform u_uniform resource index was GL_INVALID_INDEX"); 1363 1364 // Query uniform properties 1365 1366 { 1367 static const struct 1368 { 1369 const char* description; 1370 int numProps; 1371 int bufferSize; 1372 bool returnLength; 1373 } querySizes[] = 1374 { 1375 { "Query to a larger buffer", 2, 3, true }, 1376 { "Query to too small a buffer", 3, 2, true }, 1377 { "Query to zero sized buffer", 3, 0, true }, 1378 { "Query to a larger buffer, null length argument", 2, 3, false }, 1379 { "Query to too small a buffer, null length argument", 3, 2, false }, 1380 { "Query to zero sized buffer, null length argument", 3, 0, false }, 1381 }; 1382 1383 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(querySizes); ++ndx) 1384 { 1385 const tcu::ScopedLogSection section (m_testCtx.getLog(), "QueryToLarger", querySizes[ndx].description); 1386 const glw::GLenum props[] = { GL_LOCATION, GL_LOCATION, GL_LOCATION }; 1387 const int expectedWriteLen = de::min(querySizes[ndx].bufferSize, querySizes[ndx].numProps); 1388 int params[] = { 255, 255, 255, 255 }; 1389 glw::GLsizei written = -1; 1390 1391 DE_ASSERT(querySizes[ndx].numProps <= DE_LENGTH_OF_ARRAY(props)); 1392 DE_ASSERT(querySizes[ndx].bufferSize < DE_LENGTH_OF_ARRAY(params)); // leave at least one element for overflow detection 1393 1394 m_testCtx.getLog() 1395 << tcu::TestLog::Message 1396 << "Querying " << querySizes[ndx].numProps << " uniform prop(s) to a buffer with size " << querySizes[ndx].bufferSize << ". Expecting query to return " << expectedWriteLen << " prop(s)" 1397 << tcu::TestLog::EndMessage; 1398 1399 gl.getProgramResourceiv(program.getProgram(), GL_UNIFORM, uniformIndex, querySizes[ndx].numProps, props, querySizes[ndx].bufferSize, (querySizes[ndx].returnLength) ? (&written) : (DE_NULL), params); 1400 GLU_EXPECT_NO_ERROR(gl.getError(), "query program resources"); 1401 1402 if (querySizes[ndx].returnLength && written != expectedWriteLen) 1403 { 1404 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected write length of " << expectedWriteLen << ", got " << written << tcu::TestLog::EndMessage; 1405 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected write lenght"); 1406 } 1407 else if (params[expectedWriteLen] != 255) 1408 { 1409 m_testCtx.getLog() << tcu::TestLog::Message << "Error, guard at index " << (expectedWriteLen) << " was modified. Was 255 before call, got dec=" << params[expectedWriteLen] << tcu::TestLog::EndMessage; 1410 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Wrote over buffer size"); 1411 } 1412 } 1413 } 1414 1415 return STOP; 1416 } 1417 1418 class InterfaceBlockBaseCase : public TestCase 1419 { 1420 public: 1421 enum CaseType 1422 { 1423 CASE_NAMED_BLOCK = 0, 1424 CASE_UNNAMED_BLOCK, 1425 CASE_BLOCK_ARRAY, 1426 1427 CASE_LAST 1428 }; 1429 1430 InterfaceBlockBaseCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType); 1431 ~InterfaceBlockBaseCase (void); 1432 1433 private: 1434 void init (void); 1435 void deinit (void); 1436 1437 protected: 1438 const glu::Storage m_storage; 1439 const CaseType m_caseType; 1440 ProgramInterfaceDefinition::Program* m_program; 1441 }; 1442 1443 InterfaceBlockBaseCase::InterfaceBlockBaseCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType) 1444 : TestCase (context, name, description) 1445 , m_storage (storage) 1446 , m_caseType (caseType) 1447 , m_program (DE_NULL) 1448 { 1449 DE_ASSERT(storage == glu::STORAGE_UNIFORM || storage == glu::STORAGE_BUFFER); 1450 } 1451 1452 InterfaceBlockBaseCase::~InterfaceBlockBaseCase (void) 1453 { 1454 deinit(); 1455 } 1456 1457 void InterfaceBlockBaseCase::init (void) 1458 { 1459 ProgramInterfaceDefinition::Shader* shader; 1460 1461 m_program = new ProgramInterfaceDefinition::Program(); 1462 shader = m_program->addShader(glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES); 1463 1464 // PrecedingInterface 1465 { 1466 glu::InterfaceBlock precedingInterfaceBlock; 1467 1468 precedingInterfaceBlock.interfaceName = "PrecedingInterface"; 1469 precedingInterfaceBlock.layout.binding = 0; 1470 precedingInterfaceBlock.storage = m_storage; 1471 precedingInterfaceBlock.instanceName = "precedingInstance"; 1472 1473 precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "precedingMember")); 1474 1475 // Unsized array type 1476 if (m_storage == glu::STORAGE_BUFFER) 1477 precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY), "precedingMemberUnsizedArray")); 1478 else 1479 precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 2), "precedingMemberArray")); 1480 1481 shader->getDefaultBlock().interfaceBlocks.push_back(precedingInterfaceBlock); 1482 } 1483 1484 // TargetInterface 1485 { 1486 glu::InterfaceBlock targetInterfaceBlock; 1487 1488 targetInterfaceBlock.interfaceName = "TargetInterface"; 1489 targetInterfaceBlock.layout.binding = 1; 1490 targetInterfaceBlock.storage = m_storage; 1491 1492 if (m_caseType == CASE_UNNAMED_BLOCK) 1493 targetInterfaceBlock.instanceName = ""; 1494 else 1495 targetInterfaceBlock.instanceName = "targetInstance"; 1496 1497 if (m_caseType == CASE_BLOCK_ARRAY) 1498 targetInterfaceBlock.dimensions.push_back(2); 1499 1500 // Basic type 1501 { 1502 targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "blockMemberBasic")); 1503 } 1504 1505 // Array type 1506 { 1507 targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 3), "blockMemberArray")); 1508 } 1509 1510 // Struct type 1511 { 1512 glu::StructType* structPtr = new glu::StructType("StructType"); 1513 structPtr->addMember("structMemberBasic", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)); 1514 structPtr->addMember("structMemberArray", glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 2)); 1515 1516 targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(structPtr), 2), "blockMemberStruct")); 1517 } 1518 1519 // Unsized array type 1520 if (m_storage == glu::STORAGE_BUFFER) 1521 targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY), "blockMemberUnsizedArray")); 1522 1523 shader->getDefaultBlock().interfaceBlocks.push_back(targetInterfaceBlock); 1524 } 1525 1526 // TrailingInterface 1527 { 1528 glu::InterfaceBlock trailingInterfaceBlock; 1529 1530 trailingInterfaceBlock.interfaceName = "TrailingInterface"; 1531 trailingInterfaceBlock.layout.binding = 3; 1532 trailingInterfaceBlock.storage = m_storage; 1533 trailingInterfaceBlock.instanceName = "trailingInstance"; 1534 trailingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "trailingMember")); 1535 1536 shader->getDefaultBlock().interfaceBlocks.push_back(trailingInterfaceBlock); 1537 } 1538 1539 DE_ASSERT(m_program->isValid()); 1540 } 1541 1542 void InterfaceBlockBaseCase::deinit (void) 1543 { 1544 delete m_program; 1545 m_program = DE_NULL; 1546 } 1547 1548 class InterfaceBlockActiveVariablesTestCase : public InterfaceBlockBaseCase 1549 { 1550 public: 1551 InterfaceBlockActiveVariablesTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType); 1552 1553 private: 1554 IterateResult iterate (void); 1555 }; 1556 1557 InterfaceBlockActiveVariablesTestCase::InterfaceBlockActiveVariablesTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType) 1558 : InterfaceBlockBaseCase(context, name, description, storage, caseType) 1559 { 1560 } 1561 1562 InterfaceBlockActiveVariablesTestCase::IterateResult InterfaceBlockActiveVariablesTestCase::iterate (void) 1563 { 1564 const ProgramInterface programInterface = (m_storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : 1565 (m_storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) : 1566 (PROGRAMINTERFACE_LAST); 1567 const glw::GLenum programGLInterfaceValue = getProgramInterfaceGLEnum(programInterface); 1568 const glw::GLenum programMemberInterfaceValue = (m_storage == glu::STORAGE_UNIFORM) ? (GL_UNIFORM) : 1569 (m_storage == glu::STORAGE_BUFFER) ? (GL_BUFFER_VARIABLE) : 1570 (0); 1571 const std::vector<std::string> blockNames = getProgramInterfaceResourceList(m_program, programInterface); 1572 glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program)); 1573 int expectedMaxNumActiveVariables = 0; 1574 1575 DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST); 1576 1577 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1578 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 1579 1580 // Verify all blocks 1581 1582 for (int blockNdx = 0; blockNdx < (int)blockNames.size(); ++blockNdx) 1583 { 1584 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Block", "Block \"" + blockNames[blockNdx] + "\""); 1585 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1586 const glw::GLuint resourceNdx = gl.getProgramResourceIndex(program.getProgram(), programGLInterfaceValue, blockNames[blockNdx].c_str()); 1587 glw::GLint numActiveResources; 1588 std::vector<std::string> activeResourceNames; 1589 1590 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index"); 1591 1592 if (resourceNdx == GL_INVALID_INDEX) 1593 { 1594 m_testCtx.getLog() << tcu::TestLog::Message << "Error, getProgramResourceIndex returned GL_INVALID_INDEX for \"" << blockNames[blockNdx] << "\"" << tcu::TestLog::EndMessage; 1595 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Resource not found"); 1596 continue; 1597 } 1598 1599 // query block information 1600 1601 { 1602 const glw::GLenum props[] = { GL_NUM_ACTIVE_VARIABLES }; 1603 glw::GLint retBuffer[2] = { -1, -1 }; 1604 glw::GLint written = -1; 1605 1606 gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, DE_LENGTH_OF_ARRAY(props), props, 1, &written, retBuffer); 1607 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_NUM_ACTIVE_VARIABLES"); 1608 1609 numActiveResources = retBuffer[0]; 1610 expectedMaxNumActiveVariables = de::max(expectedMaxNumActiveVariables, numActiveResources); 1611 m_testCtx.getLog() << tcu::TestLog::Message << "NUM_ACTIVE_VARIABLES = " << numActiveResources << tcu::TestLog::EndMessage; 1612 1613 if (written == -1 || retBuffer[0] == -1) 1614 { 1615 m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for NUM_ACTIVE_VARIABLES did not return a value" << tcu::TestLog::EndMessage; 1616 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for NUM_ACTIVE_VARIABLES failed"); 1617 continue; 1618 } 1619 else if (retBuffer[1] != -1) 1620 { 1621 m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for NUM_ACTIVE_VARIABLES returned too many values" << tcu::TestLog::EndMessage; 1622 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for NUM_ACTIVE_VARIABLES returned too many values"); 1623 continue; 1624 } 1625 else if (retBuffer[0] < 0) 1626 { 1627 m_testCtx.getLog() << tcu::TestLog::Message << "Error, NUM_ACTIVE_VARIABLES < 0" << tcu::TestLog::EndMessage; 1628 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "NUM_ACTIVE_VARIABLES < 0"); 1629 continue; 1630 } 1631 } 1632 1633 // query block variable information 1634 1635 { 1636 const glw::GLenum props[] = { GL_ACTIVE_VARIABLES }; 1637 std::vector<glw::GLint> activeVariableIndices (numActiveResources + 1, -1); // Allocate one extra trailing to detect wrong write lengths 1638 glw::GLint written = -1; 1639 1640 gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, DE_LENGTH_OF_ARRAY(props), props, (glw::GLsizei)activeVariableIndices.size(), &written, &activeVariableIndices[0]); 1641 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_ACTIVE_VARIABLES"); 1642 1643 if (written == -1) 1644 { 1645 m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for GL_ACTIVE_VARIABLES did not return any values" << tcu::TestLog::EndMessage; 1646 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES failed"); 1647 continue; 1648 } 1649 else if (written != numActiveResources) 1650 { 1651 m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for GL_ACTIVE_VARIABLES did not return NUM_ACTIVE_VARIABLES values" << tcu::TestLog::EndMessage; 1652 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES returned invalid number of values"); 1653 continue; 1654 } 1655 else if (activeVariableIndices.back() != -1) 1656 { 1657 m_testCtx.getLog() << tcu::TestLog::Message << "Error, GL_ACTIVE_VARIABLES query return buffer trailing guard value was modified, getProgramResourceiv returned more than NUM_ACTIVE_VARIABLES values" << tcu::TestLog::EndMessage; 1658 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES returned too many values"); 1659 continue; 1660 } 1661 1662 // log indices 1663 { 1664 tcu::MessageBuilder builder(&m_testCtx.getLog()); 1665 1666 builder << "Active variable indices: {"; 1667 for (int varNdx = 0; varNdx < numActiveResources; ++varNdx) 1668 { 1669 if (varNdx) 1670 builder << ", "; 1671 builder << activeVariableIndices[varNdx]; 1672 } 1673 builder << "}" << tcu::TestLog::EndMessage; 1674 } 1675 1676 // collect names 1677 1678 activeResourceNames.resize(numActiveResources); 1679 1680 for (int varNdx = 0; varNdx < numActiveResources; ++varNdx) 1681 { 1682 const glw::GLenum nameProp = GL_NAME_LENGTH; 1683 glw::GLint nameLength = -1; 1684 std::vector<char> nameBuffer; 1685 1686 written = -1; 1687 gl.getProgramResourceiv(program.getProgram(), programMemberInterfaceValue, activeVariableIndices[varNdx], 1, &nameProp, 1, &written, &nameLength); 1688 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_NAME_LENGTH"); 1689 1690 if (nameLength <= 0 || written <= 0) 1691 { 1692 m_testCtx.getLog() << tcu::TestLog::Message << "Error, GL_NAME_LENGTH query failed" << tcu::TestLog::EndMessage; 1693 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GL_NAME_LENGTH query failed"); 1694 continue; 1695 } 1696 1697 nameBuffer.resize(nameLength + 2, 'X'); // allocate more than required 1698 written = -1; 1699 gl.getProgramResourceName(program.getProgram(), programMemberInterfaceValue, activeVariableIndices[varNdx], nameLength+1, &written, &nameBuffer[0]); 1700 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceName"); 1701 1702 if (written <= 0) 1703 { 1704 m_testCtx.getLog() << tcu::TestLog::Message << "Error, name query failed, no data written" << tcu::TestLog::EndMessage; 1705 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "name query failed"); 1706 continue; 1707 } 1708 else if (written > nameLength) 1709 { 1710 m_testCtx.getLog() << tcu::TestLog::Message << "Error, name query failed, query returned too much data" << tcu::TestLog::EndMessage; 1711 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "name query failed"); 1712 continue; 1713 } 1714 1715 activeResourceNames[varNdx] = std::string(&nameBuffer[0], written); 1716 } 1717 1718 // log collected names 1719 { 1720 tcu::MessageBuilder builder(&m_testCtx.getLog()); 1721 1722 builder << "Active variables:\n"; 1723 for (int varNdx = 0; varNdx < numActiveResources; ++varNdx) 1724 builder << "\t" << activeResourceNames[varNdx] << "\n"; 1725 builder << tcu::TestLog::EndMessage; 1726 } 1727 } 1728 1729 // verify names 1730 { 1731 glu::InterfaceBlock* block = DE_NULL; 1732 const std::string blockName = glu::parseVariableName(blockNames[blockNdx].c_str()); 1733 std::vector<std::string> referenceList; 1734 1735 for (int interfaceNdx = 0; interfaceNdx < (int)m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx) 1736 { 1737 if (m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName) 1738 { 1739 block = &m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx]; 1740 break; 1741 } 1742 } 1743 1744 if (!block) 1745 throw tcu::InternalError("could not find block referenced in the reference resource list"); 1746 1747 // generate reference list 1748 1749 referenceList = getProgramInterfaceBlockMemberResourceList(*block); 1750 { 1751 tcu::MessageBuilder builder(&m_testCtx.getLog()); 1752 1753 builder << "Expected variable names:\n"; 1754 for (int varNdx = 0; varNdx < (int)referenceList.size(); ++varNdx) 1755 builder << "\t" << referenceList[varNdx] << "\n"; 1756 builder << tcu::TestLog::EndMessage; 1757 } 1758 1759 // compare lists 1760 { 1761 bool listsIdentical = true; 1762 1763 for (int ndx = 0; ndx < (int)referenceList.size(); ++ndx) 1764 { 1765 if (!de::contains(activeResourceNames.begin(), activeResourceNames.end(), referenceList[ndx])) 1766 { 1767 m_testCtx.getLog() << tcu::TestLog::Message << "Error, variable name list did not contain active variable " << referenceList[ndx] << tcu::TestLog::EndMessage; 1768 listsIdentical = false; 1769 } 1770 } 1771 1772 for (int ndx = 0; ndx < (int)activeResourceNames.size(); ++ndx) 1773 { 1774 if (!de::contains(referenceList.begin(), referenceList.end(), activeResourceNames[ndx])) 1775 { 1776 m_testCtx.getLog() << tcu::TestLog::Message << "Error, variable name list contains unexpected resource \"" << activeResourceNames[ndx] << "\"" << tcu::TestLog::EndMessage; 1777 listsIdentical = false; 1778 } 1779 } 1780 1781 if (listsIdentical) 1782 m_testCtx.getLog() << tcu::TestLog::Message << "Lists identical" << tcu::TestLog::EndMessage; 1783 else 1784 { 1785 m_testCtx.getLog() << tcu::TestLog::Message << "Error, invalid active variable list" << tcu::TestLog::EndMessage; 1786 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid active variable list"); 1787 continue; 1788 } 1789 } 1790 } 1791 } 1792 1793 // Max num active variables 1794 { 1795 const tcu::ScopedLogSection section (m_testCtx.getLog(), "MaxNumActiveVariables", "MAX_NUM_ACTIVE_VARIABLES"); 1796 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1797 glw::GLint maxNumActiveVariables = -1; 1798 1799 gl.getProgramInterfaceiv(program.getProgram(), programGLInterfaceValue, GL_MAX_NUM_ACTIVE_VARIABLES, &maxNumActiveVariables); 1800 GLU_EXPECT_NO_ERROR(gl.getError(), "query MAX_NUM_ACTIVE_VARIABLES"); 1801 1802 m_testCtx.getLog() << tcu::TestLog::Message << "MAX_NUM_ACTIVE_VARIABLES = " << maxNumActiveVariables << tcu::TestLog::EndMessage; 1803 1804 if (expectedMaxNumActiveVariables != maxNumActiveVariables) 1805 { 1806 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected MAX_NUM_ACTIVE_VARIABLES" << tcu::TestLog::EndMessage; 1807 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected MAX_NUM_ACTIVE_VARIABLES"); 1808 } 1809 else 1810 m_testCtx.getLog() << tcu::TestLog::Message << "MAX_NUM_ACTIVE_VARIABLES valid" << tcu::TestLog::EndMessage; 1811 } 1812 1813 return STOP; 1814 } 1815 1816 class InterfaceBlockDataSizeTestCase : public InterfaceBlockBaseCase 1817 { 1818 public: 1819 InterfaceBlockDataSizeTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType); 1820 1821 private: 1822 IterateResult iterate (void); 1823 int getBlockMinDataSize (const std::string& blockName) const; 1824 int getBlockMinDataSize (const glu::InterfaceBlock& block) const; 1825 }; 1826 1827 InterfaceBlockDataSizeTestCase::InterfaceBlockDataSizeTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType) 1828 : InterfaceBlockBaseCase(context, name, description, storage, caseType) 1829 { 1830 } 1831 1832 InterfaceBlockDataSizeTestCase::IterateResult InterfaceBlockDataSizeTestCase::iterate (void) 1833 { 1834 const ProgramInterface programInterface = (m_storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : 1835 (m_storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) : 1836 (PROGRAMINTERFACE_LAST); 1837 const glw::GLenum programGLInterfaceValue = getProgramInterfaceGLEnum(programInterface); 1838 const std::vector<std::string> blockNames = getProgramInterfaceResourceList(m_program, programInterface); 1839 glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program)); 1840 1841 DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST); 1842 1843 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1844 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 1845 1846 // Verify all blocks 1847 for (int blockNdx = 0; blockNdx < (int)blockNames.size(); ++blockNdx) 1848 { 1849 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Block", "Block \"" + blockNames[blockNdx] + "\""); 1850 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1851 const glw::GLuint resourceNdx = gl.getProgramResourceIndex(program.getProgram(), programGLInterfaceValue, blockNames[blockNdx].c_str()); 1852 const int expectedMinDataSize = getBlockMinDataSize(blockNames[blockNdx]); 1853 glw::GLint queryDataSize = -1; 1854 1855 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index"); 1856 1857 if (resourceNdx == GL_INVALID_INDEX) 1858 { 1859 m_testCtx.getLog() << tcu::TestLog::Message << "Error, getProgramResourceIndex returned GL_INVALID_INDEX for \"" << blockNames[blockNdx] << "\"" << tcu::TestLog::EndMessage; 1860 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Resource not found"); 1861 continue; 1862 } 1863 1864 // query 1865 { 1866 const glw::GLenum prop = GL_BUFFER_DATA_SIZE; 1867 1868 gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, 1, &prop, 1, DE_NULL, &queryDataSize); 1869 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource BUFFER_DATA_SIZE"); 1870 } 1871 1872 m_testCtx.getLog() 1873 << tcu::TestLog::Message 1874 << "BUFFER_DATA_SIZE = " << queryDataSize << "\n" 1875 << "Buffer data size with tight packing: " << expectedMinDataSize 1876 << tcu::TestLog::EndMessage; 1877 1878 if (queryDataSize < expectedMinDataSize) 1879 { 1880 m_testCtx.getLog() << tcu::TestLog::Message << "Error, buffer size was less than minimum buffer data size" << tcu::TestLog::EndMessage; 1881 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer data size invalid"); 1882 continue; 1883 } 1884 else 1885 m_testCtx.getLog() << tcu::TestLog::Message << "Buffer size valid" << tcu::TestLog::EndMessage; 1886 } 1887 1888 return STOP; 1889 } 1890 1891 int InterfaceBlockDataSizeTestCase::getBlockMinDataSize (const std::string& blockFullName) const 1892 { 1893 const std::string blockName = glu::parseVariableName(blockFullName.c_str()); 1894 1895 for (int interfaceNdx = 0; interfaceNdx < (int)m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx) 1896 { 1897 if (m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName && 1898 m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].storage == m_storage) 1899 return getBlockMinDataSize(m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx]); 1900 } 1901 1902 DE_ASSERT(false); 1903 return -1; 1904 } 1905 1906 class AtomicCounterCase : public TestCase 1907 { 1908 public: 1909 AtomicCounterCase (Context& context, const char* name, const char* description); 1910 ~AtomicCounterCase (void); 1911 1912 private: 1913 void init (void); 1914 void deinit (void); 1915 1916 protected: 1917 int getNumAtomicCounterBuffers (void) const; 1918 int getMaxNumActiveVariables (void) const; 1919 int getBufferVariableCount (int binding) const; 1920 int getBufferMinimumDataSize (int binding) const; 1921 1922 ProgramInterfaceDefinition::Program* m_program; 1923 }; 1924 1925 AtomicCounterCase::AtomicCounterCase (Context& context, const char* name, const char* description) 1926 : TestCase (context, name, description) 1927 , m_program (DE_NULL) 1928 { 1929 } 1930 1931 AtomicCounterCase::~AtomicCounterCase (void) 1932 { 1933 deinit(); 1934 } 1935 1936 void AtomicCounterCase::init (void) 1937 { 1938 ProgramInterfaceDefinition::Shader* shader; 1939 1940 m_program = new ProgramInterfaceDefinition::Program(); 1941 shader = m_program->addShader(glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES); 1942 1943 { 1944 glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding1_counter1", glu::STORAGE_UNIFORM); 1945 decl.layout.binding = 1; 1946 shader->getDefaultBlock().variables.push_back(decl); 1947 } 1948 { 1949 glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding1_counter2", glu::STORAGE_UNIFORM); 1950 decl.layout.binding = 1; 1951 decl.layout.offset = 8; 1952 1953 shader->getDefaultBlock().variables.push_back(decl); 1954 } 1955 { 1956 glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding2_counter1", glu::STORAGE_UNIFORM); 1957 decl.layout.binding = 2; 1958 shader->getDefaultBlock().variables.push_back(decl); 1959 } 1960 1961 DE_ASSERT(m_program->isValid()); 1962 } 1963 1964 void AtomicCounterCase::deinit (void) 1965 { 1966 delete m_program; 1967 m_program = DE_NULL; 1968 } 1969 1970 int AtomicCounterCase::getNumAtomicCounterBuffers (void) const 1971 { 1972 std::set<int> buffers; 1973 1974 for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx) 1975 { 1976 if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() && 1977 glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType())) 1978 { 1979 buffers.insert(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding); 1980 } 1981 } 1982 1983 return (int)buffers.size(); 1984 } 1985 1986 int AtomicCounterCase::getMaxNumActiveVariables (void) const 1987 { 1988 int maxVars = 0; 1989 std::map<int,int> numBufferVars; 1990 1991 for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx) 1992 { 1993 if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() && 1994 glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType())) 1995 { 1996 const int binding = m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding; 1997 1998 if (numBufferVars.find(binding) == numBufferVars.end()) 1999 numBufferVars[binding] = 1; 2000 else 2001 ++numBufferVars[binding]; 2002 } 2003 } 2004 2005 for (std::map<int,int>::const_iterator it = numBufferVars.begin(); it != numBufferVars.end(); ++it) 2006 maxVars = de::max(maxVars, it->second); 2007 2008 return maxVars; 2009 } 2010 2011 int AtomicCounterCase::getBufferVariableCount (int binding) const 2012 { 2013 int numVars = 0; 2014 2015 for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx) 2016 { 2017 if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() && 2018 glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()) && 2019 m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding == binding) 2020 ++numVars; 2021 } 2022 2023 return numVars; 2024 } 2025 2026 int AtomicCounterCase::getBufferMinimumDataSize (int binding) const 2027 { 2028 int minSize = -1; 2029 int currentOffset = 0; 2030 2031 for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx) 2032 { 2033 if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() && 2034 glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()) && 2035 m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding == binding) 2036 { 2037 const int thisOffset = (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.offset != -1) ? (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.offset) : (currentOffset); 2038 currentOffset = thisOffset + 4; 2039 2040 minSize = de::max(minSize, thisOffset + 4); 2041 } 2042 } 2043 2044 return minSize; 2045 } 2046 2047 class AtomicCounterResourceListCase : public AtomicCounterCase 2048 { 2049 public: 2050 AtomicCounterResourceListCase (Context& context, const char* name, const char* description); 2051 2052 private: 2053 IterateResult iterate (void); 2054 }; 2055 2056 AtomicCounterResourceListCase::AtomicCounterResourceListCase (Context& context, const char* name, const char* description) 2057 : AtomicCounterCase(context, name, description) 2058 { 2059 } 2060 2061 AtomicCounterResourceListCase::IterateResult AtomicCounterResourceListCase::iterate (void) 2062 { 2063 const glu::ShaderProgram program(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program)); 2064 2065 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2066 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2067 2068 { 2069 const tcu::ScopedLogSection section (m_testCtx.getLog(), "ActiveResources", "ACTIVE_RESOURCES"); 2070 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2071 glw::GLint numActiveResources = -1; 2072 const int numExpectedActiveResources = 2; // 2 buffer bindings 2073 2074 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying ACTIVE_RESOURCES, expecting " << numExpectedActiveResources << tcu::TestLog::EndMessage; 2075 2076 gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numActiveResources); 2077 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_ACTIVE_RESOURCES"); 2078 2079 m_testCtx.getLog() << tcu::TestLog::Message << "ACTIVE_RESOURCES = " << numActiveResources << tcu::TestLog::EndMessage; 2080 2081 if (numActiveResources != numExpectedActiveResources) 2082 { 2083 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected ACTIVE_RESOURCES" << tcu::TestLog::EndMessage; 2084 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected ACTIVE_RESOURCES"); 2085 } 2086 else 2087 m_testCtx.getLog() << tcu::TestLog::Message << "ACTIVE_RESOURCES valid" << tcu::TestLog::EndMessage; 2088 } 2089 2090 return STOP; 2091 } 2092 2093 class AtomicCounterActiveVariablesCase : public AtomicCounterCase 2094 { 2095 public: 2096 AtomicCounterActiveVariablesCase (Context& context, const char* name, const char* description); 2097 2098 private: 2099 IterateResult iterate (void); 2100 }; 2101 2102 AtomicCounterActiveVariablesCase::AtomicCounterActiveVariablesCase (Context& context, const char* name, const char* description) 2103 : AtomicCounterCase(context, name, description) 2104 { 2105 } 2106 2107 AtomicCounterActiveVariablesCase::IterateResult AtomicCounterActiveVariablesCase::iterate (void) 2108 { 2109 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2110 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program)); 2111 const int numAtomicBuffers = getNumAtomicCounterBuffers(); 2112 const int expectedMaxNumActiveVariables = getMaxNumActiveVariables(); 2113 2114 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2115 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2116 2117 // check active variables 2118 { 2119 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Interface", "ATOMIC_COUNTER_BUFFER interface"); 2120 glw::GLint queryActiveResources = -1; 2121 glw::GLint queryMaxNumActiveVariables = -1; 2122 2123 gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &queryActiveResources); 2124 gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, &queryMaxNumActiveVariables); 2125 GLU_EXPECT_NO_ERROR(gl.getError(), "query interface"); 2126 2127 m_testCtx.getLog() 2128 << tcu::TestLog::Message 2129 << "GL_ACTIVE_RESOURCES = " << queryActiveResources << "\n" 2130 << "GL_MAX_NUM_ACTIVE_VARIABLES = " << queryMaxNumActiveVariables << "\n" 2131 << tcu::TestLog::EndMessage; 2132 2133 if (queryActiveResources != numAtomicBuffers) 2134 { 2135 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected GL_ACTIVE_RESOURCES, expected " << numAtomicBuffers << tcu::TestLog::EndMessage; 2136 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected GL_ACTIVE_RESOURCES"); 2137 } 2138 2139 if (queryMaxNumActiveVariables != expectedMaxNumActiveVariables) 2140 { 2141 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected GL_MAX_NUM_ACTIVE_VARIABLES, expected " << expectedMaxNumActiveVariables << tcu::TestLog::EndMessage; 2142 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected GL_MAX_NUM_ACTIVE_VARIABLES"); 2143 } 2144 } 2145 2146 // Check each buffer 2147 for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx) 2148 { 2149 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx)); 2150 std::vector<glw::GLint> activeVariables; 2151 std::vector<std::string> memberNames; 2152 2153 // Find active variables 2154 { 2155 const glw::GLenum numActiveVariablesProp = GL_NUM_ACTIVE_VARIABLES; 2156 const glw::GLenum activeVariablesProp = GL_ACTIVE_VARIABLES; 2157 glw::GLint numActiveVariables = -2; 2158 glw::GLint written = -1; 2159 2160 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &numActiveVariablesProp, 1, &written, &numActiveVariables); 2161 GLU_EXPECT_NO_ERROR(gl.getError(), "query num active variables"); 2162 2163 if (numActiveVariables <= 0) 2164 { 2165 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected NUM_ACTIVE_VARIABLES: " << numActiveVariables << tcu::TestLog::EndMessage; 2166 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected NUM_ACTIVE_VARIABLES"); 2167 continue; 2168 } 2169 2170 if (written <= 0) 2171 { 2172 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for NUM_ACTIVE_VARIABLES returned no values" << tcu::TestLog::EndMessage; 2173 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "NUM_ACTIVE_VARIABLES query failed"); 2174 continue; 2175 } 2176 2177 m_testCtx.getLog() << tcu::TestLog::Message << "GL_NUM_ACTIVE_VARIABLES = " << numActiveVariables << tcu::TestLog::EndMessage; 2178 2179 written = -1; 2180 activeVariables.resize(numActiveVariables + 1, -2); 2181 2182 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &activeVariablesProp, numActiveVariables, &written, &activeVariables[0]); 2183 GLU_EXPECT_NO_ERROR(gl.getError(), "query active variables"); 2184 2185 if (written != numActiveVariables) 2186 { 2187 m_testCtx.getLog() << tcu::TestLog::Message << "Error, unexpected number of ACTIVE_VARIABLES, NUM_ACTIVE_VARIABLES = " << numActiveVariables << ", query returned " << written << " values" << tcu::TestLog::EndMessage; 2188 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected ACTIVE_VARIABLES"); 2189 continue; 2190 } 2191 2192 if (activeVariables.back() != -2) 2193 { 2194 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for ACTIVE_VARIABLES wrote over target buffer bounds" << tcu::TestLog::EndMessage; 2195 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "ACTIVE_VARIABLES query failed"); 2196 continue; 2197 } 2198 2199 activeVariables.pop_back(); 2200 } 2201 2202 // log indices 2203 { 2204 tcu::MessageBuilder builder(&m_testCtx.getLog()); 2205 2206 builder << "Active variable indices: {"; 2207 for (int varNdx = 0; varNdx < (int)activeVariables.size(); ++varNdx) 2208 { 2209 if (varNdx) 2210 builder << ", "; 2211 builder << activeVariables[varNdx]; 2212 } 2213 builder << "}" << tcu::TestLog::EndMessage; 2214 } 2215 2216 // collect member names 2217 for (int ndx = 0; ndx < (int)activeVariables.size(); ++ndx) 2218 { 2219 const glw::GLenum nameLengthProp = GL_NAME_LENGTH; 2220 glw::GLint nameLength = -1; 2221 glw::GLint written = -1; 2222 std::vector<char> nameBuf; 2223 2224 gl.getProgramResourceiv(program.getProgram(), GL_UNIFORM, activeVariables[ndx], 1, &nameLengthProp, 1, &written, &nameLength); 2225 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer variable name length"); 2226 2227 if (written <= 0 || nameLength == -1) 2228 { 2229 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for GL_NAME_LENGTH returned no values" << tcu::TestLog::EndMessage; 2230 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GL_NAME_LENGTH query failed"); 2231 continue; 2232 } 2233 2234 nameBuf.resize(nameLength + 2, 'X'); // +2 to tolerate potential off-by-ones in some implementations, name queries will check these cases better 2235 written = -1; 2236 2237 gl.getProgramResourceName(program.getProgram(), GL_UNIFORM, activeVariables[ndx], (int)nameBuf.size(), &written, &nameBuf[0]); 2238 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer variable name"); 2239 2240 if (written <= 0) 2241 { 2242 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for resource name returned no name" << tcu::TestLog::EndMessage; 2243 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Name query failed"); 2244 continue; 2245 } 2246 2247 memberNames.push_back(std::string(&nameBuf[0], written)); 2248 } 2249 2250 // log names 2251 { 2252 tcu::MessageBuilder builder(&m_testCtx.getLog()); 2253 2254 builder << "Active variables:\n"; 2255 for (int varNdx = 0; varNdx < (int)memberNames.size(); ++varNdx) 2256 { 2257 builder << "\t" << memberNames[varNdx] << "\n"; 2258 } 2259 builder << tcu::TestLog::EndMessage; 2260 } 2261 2262 // check names are all in the same buffer 2263 { 2264 bool bindingsValid = true; 2265 2266 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying names" << tcu::TestLog::EndMessage; 2267 2268 for (int nameNdx = 0; nameNdx < (int)memberNames.size(); ++nameNdx) 2269 { 2270 int prevBinding = -1; 2271 2272 for (int varNdx = 0; varNdx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++varNdx) 2273 { 2274 if (m_program->getShaders()[0]->getDefaultBlock().variables[varNdx].name == memberNames[nameNdx]) 2275 { 2276 const int varBinding = m_program->getShaders()[0]->getDefaultBlock().variables[varNdx].layout.binding; 2277 2278 if (prevBinding == -1 || prevBinding == varBinding) 2279 prevBinding = varBinding; 2280 else 2281 bindingsValid = false; 2282 } 2283 } 2284 2285 if (prevBinding == -1) 2286 { 2287 m_testCtx.getLog() << tcu::TestLog::Message << "Error, could not find variable with name \"" << memberNames[nameNdx] << "\"" << tcu::TestLog::EndMessage; 2288 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Variable name invalid"); 2289 } 2290 else if (getBufferVariableCount(prevBinding) != (int)memberNames.size()) 2291 { 2292 m_testCtx.getLog() 2293 << tcu::TestLog::Message 2294 << "Error, unexpected variable count for binding " << prevBinding 2295 << ". Expected " << getBufferVariableCount(prevBinding) << ", got " << (int)memberNames.size() 2296 << tcu::TestLog::EndMessage; 2297 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Variable names invalid"); 2298 } 2299 } 2300 2301 if (!bindingsValid) 2302 { 2303 m_testCtx.getLog() << tcu::TestLog::Message << "Error, all resource do not share the same buffer" << tcu::TestLog::EndMessage; 2304 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Active variables invalid"); 2305 continue; 2306 } 2307 } 2308 } 2309 2310 return STOP; 2311 } 2312 2313 class AtomicCounterBufferBindingCase : public AtomicCounterCase 2314 { 2315 public: 2316 AtomicCounterBufferBindingCase (Context& context, const char* name, const char* description); 2317 2318 private: 2319 IterateResult iterate (void); 2320 }; 2321 2322 AtomicCounterBufferBindingCase::AtomicCounterBufferBindingCase (Context& context, const char* name, const char* description) 2323 : AtomicCounterCase(context, name, description) 2324 { 2325 } 2326 2327 AtomicCounterBufferBindingCase::IterateResult AtomicCounterBufferBindingCase::iterate (void) 2328 { 2329 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2330 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program)); 2331 const int numAtomicBuffers = getNumAtomicCounterBuffers(); 2332 2333 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2334 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2335 2336 // check every buffer 2337 for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx) 2338 { 2339 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx)); 2340 const glw::GLenum bufferBindingProp = GL_BUFFER_BINDING; 2341 glw::GLint bufferBinding = -1; 2342 glw::GLint written = -1; 2343 2344 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &bufferBindingProp, 1, &written, &bufferBinding); 2345 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding"); 2346 2347 if (written <= 0) 2348 { 2349 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for BUFFER_BINDING returned no values." << tcu::TestLog::EndMessage; 2350 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "BUFFER_BINDING query failed"); 2351 } 2352 2353 m_testCtx.getLog() << tcu::TestLog::Message << "GL_BUFFER_BINDING = " << bufferBinding << tcu::TestLog::EndMessage; 2354 2355 // no such buffer binding? 2356 if (getBufferVariableCount(bufferBinding) == 0) 2357 { 2358 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_BINDING = " << bufferBinding << ", but such buffer does not exist." << tcu::TestLog::EndMessage; 2359 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING"); 2360 } 2361 } 2362 2363 return STOP; 2364 } 2365 2366 class AtomicCounterBufferDataSizeCase : public AtomicCounterCase 2367 { 2368 public: 2369 AtomicCounterBufferDataSizeCase (Context& context, const char* name, const char* description); 2370 2371 private: 2372 IterateResult iterate (void); 2373 }; 2374 2375 AtomicCounterBufferDataSizeCase::AtomicCounterBufferDataSizeCase (Context& context, const char* name, const char* description) 2376 : AtomicCounterCase(context, name, description) 2377 { 2378 } 2379 2380 AtomicCounterBufferDataSizeCase::IterateResult AtomicCounterBufferDataSizeCase::iterate (void) 2381 { 2382 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2383 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program)); 2384 const int numAtomicBuffers = getNumAtomicCounterBuffers(); 2385 2386 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2387 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2388 2389 // check every buffer 2390 for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx) 2391 { 2392 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx)); 2393 const glw::GLenum props[] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE }; 2394 glw::GLint values[] = { -1, -1 }; 2395 glw::GLint written = -1; 2396 int bufferMinDataSize; 2397 2398 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, DE_LENGTH_OF_ARRAY(props), props, DE_LENGTH_OF_ARRAY(values), &written, values); 2399 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding"); 2400 2401 if (written != 2) 2402 { 2403 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for (BUFFER_BINDING, BUFFER_DATA_SIZE) returned " << written << " value(s)." << tcu::TestLog::EndMessage; 2404 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed"); 2405 continue; 2406 } 2407 2408 m_testCtx.getLog() 2409 << tcu::TestLog::Message 2410 << "GL_BUFFER_BINDING = " << values[0] << "\n" 2411 << "GL_BUFFER_DATA_SIZE = " << values[1] 2412 << tcu::TestLog::EndMessage; 2413 2414 bufferMinDataSize = getBufferMinimumDataSize(values[0]); 2415 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying data size, expected greater than or equal to " << bufferMinDataSize << tcu::TestLog::EndMessage; 2416 2417 // no such buffer binding? 2418 if (bufferMinDataSize == -1) 2419 { 2420 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_BINDING = " << values[0] << ", but such buffer does not exist." << tcu::TestLog::EndMessage; 2421 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING"); 2422 } 2423 else if (values[1] < bufferMinDataSize) 2424 { 2425 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_DATA_SIZE = " << values[1] << ", expected greater than or equal to " << bufferMinDataSize << tcu::TestLog::EndMessage; 2426 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING"); 2427 } 2428 else 2429 m_testCtx.getLog() << tcu::TestLog::Message << "Data size valid" << tcu::TestLog::EndMessage; 2430 } 2431 2432 return STOP; 2433 } 2434 2435 class AtomicCounterReferencedByCase : public TestCase 2436 { 2437 public: 2438 AtomicCounterReferencedByCase (Context& context, const char* name, const char* description, deUint32 presentStagesMask, deUint32 activeStagesMask); 2439 ~AtomicCounterReferencedByCase (void); 2440 2441 private: 2442 void init (void); 2443 void deinit (void); 2444 IterateResult iterate (void); 2445 2446 const deUint32 m_presentStagesMask; 2447 const deUint32 m_activeStagesMask; 2448 ProgramInterfaceDefinition::Program* m_program; 2449 }; 2450 2451 AtomicCounterReferencedByCase::AtomicCounterReferencedByCase (Context& context, const char* name, const char* description, deUint32 presentStagesMask, deUint32 activeStagesMask) 2452 : TestCase (context, name, description) 2453 , m_presentStagesMask (presentStagesMask) 2454 , m_activeStagesMask (activeStagesMask) 2455 , m_program (DE_NULL) 2456 { 2457 DE_ASSERT((activeStagesMask & presentStagesMask) == activeStagesMask); 2458 } 2459 2460 AtomicCounterReferencedByCase::~AtomicCounterReferencedByCase (void) 2461 { 2462 deinit(); 2463 } 2464 2465 void AtomicCounterReferencedByCase::init (void) 2466 { 2467 glu::VariableDeclaration atomicVar(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "targetCounter", glu::STORAGE_UNIFORM); 2468 2469 atomicVar.layout.binding = 1; 2470 2471 m_program = new ProgramInterfaceDefinition::Program(); 2472 m_program->setSeparable(((m_presentStagesMask & (1 << glu::SHADERTYPE_VERTEX)) != 0) != ((m_presentStagesMask & (1 << glu::SHADERTYPE_FRAGMENT)) != 0)); 2473 2474 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType) 2475 { 2476 if (m_activeStagesMask & (1 << shaderType)) 2477 m_program->addShader((glu::ShaderType)shaderType, glu::GLSL_VERSION_310_ES)->getDefaultBlock().variables.push_back(atomicVar); 2478 else if (m_presentStagesMask & (1 << shaderType)) 2479 m_program->addShader((glu::ShaderType)shaderType, glu::GLSL_VERSION_310_ES); 2480 } 2481 2482 DE_ASSERT(m_program->isValid()); 2483 } 2484 2485 void AtomicCounterReferencedByCase::deinit (void) 2486 { 2487 delete m_program; 2488 m_program = DE_NULL; 2489 } 2490 2491 AtomicCounterReferencedByCase::IterateResult AtomicCounterReferencedByCase::iterate (void) 2492 { 2493 static const struct 2494 { 2495 glw::GLenum propName; 2496 glu::ShaderType shaderType; 2497 } targetProps[] = 2498 { 2499 { GL_REFERENCED_BY_VERTEX_SHADER, glu::SHADERTYPE_VERTEX }, 2500 { GL_REFERENCED_BY_FRAGMENT_SHADER, glu::SHADERTYPE_FRAGMENT }, 2501 { GL_REFERENCED_BY_COMPUTE_SHADER, glu::SHADERTYPE_COMPUTE }, 2502 }; 2503 2504 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2505 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program)); 2506 2507 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2508 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2509 2510 // check props 2511 for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(targetProps); ++propNdx) 2512 { 2513 const glw::GLenum prop = targetProps[propNdx].propName; 2514 const glw::GLint expected = ((m_activeStagesMask & (1 << targetProps[propNdx].shaderType)) != 0) ? (GL_TRUE) : (GL_FALSE); 2515 glw::GLint value = -1; 2516 glw::GLint written = -1; 2517 2518 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying " << glu::getProgramResourcePropertyName(prop) << ", expecting " << glu::getBooleanName(expected) << tcu::TestLog::EndMessage; 2519 2520 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, 0, 1, &prop, 1, &written, &value); 2521 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding"); 2522 2523 if (written != 1) 2524 { 2525 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for referenced_by_* returned invalid number of values." << tcu::TestLog::EndMessage; 2526 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed"); 2527 continue; 2528 } 2529 2530 m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramResourcePropertyName(prop) << " = " << glu::getBooleanStr(value) << tcu::TestLog::EndMessage; 2531 2532 if (value != expected) 2533 { 2534 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected value" << tcu::TestLog::EndMessage; 2535 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected property value"); 2536 continue; 2537 } 2538 } 2539 2540 return STOP; 2541 } 2542 2543 class ProgramInputOutputReferencedByCase : public TestCase 2544 { 2545 public: 2546 enum CaseType 2547 { 2548 CASE_VERTEX_FRAGMENT = 0, 2549 CASE_SEPARABLE_VERTEX, 2550 CASE_SEPARABLE_FRAGMENT, 2551 2552 CASE_LAST 2553 }; 2554 ProgramInputOutputReferencedByCase (Context& context, const char* name, const char* description, glu::Storage targetStorage, CaseType caseType); 2555 ~ProgramInputOutputReferencedByCase (void); 2556 2557 private: 2558 void init (void); 2559 void deinit (void); 2560 IterateResult iterate (void); 2561 2562 const CaseType m_caseType; 2563 const glu::Storage m_targetStorage; 2564 ProgramInterfaceDefinition::Program* m_program; 2565 }; 2566 2567 ProgramInputOutputReferencedByCase::ProgramInputOutputReferencedByCase (Context& context, const char* name, const char* description, glu::Storage targetStorage, CaseType caseType) 2568 : TestCase (context, name, description) 2569 , m_caseType (caseType) 2570 , m_targetStorage (targetStorage) 2571 , m_program (DE_NULL) 2572 { 2573 DE_ASSERT(caseType < CASE_LAST); 2574 } 2575 2576 ProgramInputOutputReferencedByCase::~ProgramInputOutputReferencedByCase (void) 2577 { 2578 deinit(); 2579 } 2580 2581 void ProgramInputOutputReferencedByCase::init (void) 2582 { 2583 m_program = new ProgramInterfaceDefinition::Program(); 2584 2585 if (m_caseType == CASE_SEPARABLE_VERTEX || m_caseType == CASE_SEPARABLE_FRAGMENT) 2586 { 2587 const std::string varName = (m_targetStorage == glu::STORAGE_IN) ? ("shaderInput") : ("shaderOutput"); 2588 const glu::VariableDeclaration targetDecl (glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), varName, m_targetStorage); 2589 2590 m_program->setSeparable(true); 2591 m_program->addShader((m_caseType == CASE_SEPARABLE_VERTEX) ? (glu::SHADERTYPE_VERTEX) : (glu::SHADERTYPE_FRAGMENT), glu::GLSL_VERSION_310_ES)->getDefaultBlock().variables.push_back(targetDecl); 2592 } 2593 else if (m_caseType == CASE_VERTEX_FRAGMENT) 2594 { 2595 ProgramInterfaceDefinition::Shader* vertex = m_program->addShader(glu::SHADERTYPE_VERTEX, glu::GLSL_VERSION_310_ES); 2596 ProgramInterfaceDefinition::Shader* fragment = m_program->addShader(glu::SHADERTYPE_FRAGMENT, glu::GLSL_VERSION_310_ES); 2597 2598 m_program->setSeparable(false); 2599 2600 vertex->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "shaderInput", glu::STORAGE_IN)); 2601 vertex->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "shaderOutput", glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(1))); 2602 2603 fragment->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "shaderInput", glu::STORAGE_IN, glu::INTERPOLATION_LAST, glu::Layout(1))); 2604 fragment->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "shaderOutput", glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(0))); 2605 } 2606 else 2607 DE_ASSERT(false); 2608 2609 DE_ASSERT(m_program->isValid()); 2610 } 2611 2612 void ProgramInputOutputReferencedByCase::deinit (void) 2613 { 2614 delete m_program; 2615 m_program = DE_NULL; 2616 } 2617 2618 ProgramInputOutputReferencedByCase::IterateResult ProgramInputOutputReferencedByCase::iterate (void) 2619 { 2620 static const struct 2621 { 2622 glw::GLenum propName; 2623 glu::ShaderType shaderType; 2624 } targetProps[] = 2625 { 2626 { GL_REFERENCED_BY_VERTEX_SHADER, glu::SHADERTYPE_VERTEX }, 2627 { GL_REFERENCED_BY_FRAGMENT_SHADER, glu::SHADERTYPE_FRAGMENT }, 2628 { GL_REFERENCED_BY_COMPUTE_SHADER, glu::SHADERTYPE_COMPUTE }, 2629 }; 2630 2631 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2632 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program)); 2633 const std::string targetResourceName = (m_targetStorage == glu::STORAGE_IN) ? ("shaderInput") : ("shaderOutput"); 2634 const glw::GLenum programGLInterface = (m_targetStorage == glu::STORAGE_IN) ? (GL_PROGRAM_INPUT) : (GL_PROGRAM_OUTPUT); 2635 glw::GLuint resourceIndex; 2636 2637 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2638 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2639 2640 // find target resource index 2641 2642 resourceIndex = gl.getProgramResourceIndex(program.getProgram(), programGLInterface, targetResourceName.c_str()); 2643 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index"); 2644 2645 if (resourceIndex == GL_INVALID_INDEX) 2646 { 2647 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for resource \"" << targetResourceName << "\" index returned invalid index." << tcu::TestLog::EndMessage; 2648 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "could not find target resource"); 2649 return STOP; 2650 } 2651 2652 // check props 2653 for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(targetProps); ++propNdx) 2654 { 2655 const glw::GLenum prop = targetProps[propNdx].propName; 2656 const bool vertexPresent = (m_caseType == CASE_VERTEX_FRAGMENT) || (m_caseType == CASE_SEPARABLE_VERTEX); 2657 const bool fragmentPresent = (m_caseType == CASE_VERTEX_FRAGMENT) || (m_caseType == CASE_SEPARABLE_FRAGMENT); 2658 const bool expected = (m_targetStorage == glu::STORAGE_IN) ? 2659 ((vertexPresent) ? (targetProps[propNdx].shaderType == glu::SHADERTYPE_VERTEX) : (targetProps[propNdx].shaderType == glu::SHADERTYPE_FRAGMENT)) : 2660 ((fragmentPresent) ? (targetProps[propNdx].shaderType == glu::SHADERTYPE_FRAGMENT) : (targetProps[propNdx].shaderType == glu::SHADERTYPE_VERTEX)); 2661 glw::GLint value = -1; 2662 glw::GLint written = -1; 2663 2664 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying " << glu::getProgramResourcePropertyName(prop) << ", expecting " << ((expected) ? ("TRUE") : ("FALSE")) << tcu::TestLog::EndMessage; 2665 2666 gl.getProgramResourceiv(program.getProgram(), programGLInterface, resourceIndex, 1, &prop, 1, &written, &value); 2667 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding"); 2668 2669 if (written != 1) 2670 { 2671 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for referenced_by_* returned invalid number of values." << tcu::TestLog::EndMessage; 2672 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed"); 2673 continue; 2674 } 2675 2676 m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramResourcePropertyName(prop) << " = " << glu::getBooleanStr(value) << tcu::TestLog::EndMessage; 2677 2678 if (value != ((expected) ? (GL_TRUE) : (GL_FALSE))) 2679 { 2680 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected value" << tcu::TestLog::EndMessage; 2681 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected property value"); 2682 continue; 2683 } 2684 } 2685 2686 return STOP; 2687 } 2688 2689 class FeedbackResourceListTestCase : public ResourceListTestCase 2690 { 2691 public: 2692 FeedbackResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& resource, const char* name); 2693 ~FeedbackResourceListTestCase (void); 2694 2695 private: 2696 IterateResult iterate (void); 2697 }; 2698 2699 FeedbackResourceListTestCase::FeedbackResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& resource, const char* name) 2700 : ResourceListTestCase(context, resource, PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, name) 2701 { 2702 } 2703 2704 FeedbackResourceListTestCase::~FeedbackResourceListTestCase (void) 2705 { 2706 deinit(); 2707 } 2708 2709 FeedbackResourceListTestCase::IterateResult FeedbackResourceListTestCase::iterate (void) 2710 { 2711 const de::UniquePtr<ProgramInterfaceDefinition::Program> programDefinition (generateProgramDefinitionFromResource(m_targetResource.get())); 2712 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(programDefinition.get())); 2713 2714 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2715 2716 // Feedback varyings 2717 { 2718 tcu::MessageBuilder builder(&m_testCtx.getLog()); 2719 builder << "Transform feedback varyings: {"; 2720 for (int ndx = 0; ndx < (int)programDefinition->getTransformFeedbackVaryings().size(); ++ndx) 2721 { 2722 if (ndx) 2723 builder << ", "; 2724 builder << "\"" << programDefinition->getTransformFeedbackVaryings()[ndx] << "\""; 2725 } 2726 builder << "}" << tcu::TestLog::EndMessage; 2727 } 2728 2729 checkAndLogProgram(program, programDefinition.get(), m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2730 2731 // Check resource list 2732 { 2733 const tcu::ScopedLogSection section (m_testCtx.getLog(), "ResourceList", "Resource list"); 2734 std::vector<std::string> resourceList; 2735 std::vector<std::string> expectedResources; 2736 2737 queryResourceList(resourceList, program.getProgram()); 2738 expectedResources = getProgramInterfaceResourceList(programDefinition.get(), m_programInterface); 2739 2740 // verify the list and the expected list match 2741 2742 if (!verifyResourceList(resourceList, expectedResources)) 2743 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid resource list"); 2744 2745 // verify GetProgramResourceIndex() matches the indices of the list 2746 2747 if (!verifyResourceIndexQuery(resourceList, expectedResources, program.getProgram())) 2748 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GetProgramResourceIndex returned unexpected values"); 2749 2750 // Verify MAX_NAME_LENGTH 2751 if (!verifyMaxNameLength(resourceList, program.getProgram())) 2752 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "MAX_NAME_LENGTH invalid"); 2753 } 2754 2755 return STOP; 2756 } 2757 2758 int InterfaceBlockDataSizeTestCase::getBlockMinDataSize (const glu::InterfaceBlock& block) const 2759 { 2760 int dataSize = 0; 2761 2762 for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx) 2763 dataSize += getVarTypeSize(block.variables[ndx].varType); 2764 2765 return dataSize; 2766 } 2767 2768 static bool isDataTypeLayoutQualified (glu::DataType type) 2769 { 2770 return glu::isDataTypeImage(type) || glu::isDataTypeAtomicCounter(type); 2771 } 2772 2773 static void generateVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3, bool createTestGroup = true) 2774 { 2775 static const struct 2776 { 2777 int level; 2778 glu::DataType dataType; 2779 } variableTypes[] = 2780 { 2781 { 0, glu::TYPE_FLOAT }, 2782 { 1, glu::TYPE_INT }, 2783 { 1, glu::TYPE_UINT }, 2784 { 1, glu::TYPE_BOOL }, 2785 2786 { 3, glu::TYPE_FLOAT_VEC2 }, 2787 { 1, glu::TYPE_FLOAT_VEC3 }, 2788 { 1, glu::TYPE_FLOAT_VEC4 }, 2789 2790 { 3, glu::TYPE_INT_VEC2 }, 2791 { 2, glu::TYPE_INT_VEC3 }, 2792 { 3, glu::TYPE_INT_VEC4 }, 2793 2794 { 3, glu::TYPE_UINT_VEC2 }, 2795 { 2, glu::TYPE_UINT_VEC3 }, 2796 { 3, glu::TYPE_UINT_VEC4 }, 2797 2798 { 3, glu::TYPE_BOOL_VEC2 }, 2799 { 2, glu::TYPE_BOOL_VEC3 }, 2800 { 3, glu::TYPE_BOOL_VEC4 }, 2801 2802 { 2, glu::TYPE_FLOAT_MAT2 }, 2803 { 3, glu::TYPE_FLOAT_MAT2X3 }, 2804 { 3, glu::TYPE_FLOAT_MAT2X4 }, 2805 { 2, glu::TYPE_FLOAT_MAT3X2 }, 2806 { 2, glu::TYPE_FLOAT_MAT3 }, 2807 { 3, glu::TYPE_FLOAT_MAT3X4 }, 2808 { 2, glu::TYPE_FLOAT_MAT4X2 }, 2809 { 3, glu::TYPE_FLOAT_MAT4X3 }, 2810 { 2, glu::TYPE_FLOAT_MAT4 }, 2811 }; 2812 2813 tcu::TestCaseGroup* group; 2814 2815 if (createTestGroup) 2816 { 2817 group = new tcu::TestCaseGroup(context.getTestContext(), "basic_type", "Basic variable"); 2818 targetGroup->addChild(group); 2819 } 2820 else 2821 group = targetGroup; 2822 2823 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx) 2824 { 2825 if (variableTypes[ndx].level <= expandLevel) 2826 { 2827 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType)); 2828 group->addChild(new ResourceTestCase(context, variable, queryTarget)); 2829 } 2830 } 2831 } 2832 2833 static void generateOpaqueTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3, bool createTestGroup = true) 2834 { 2835 static const struct 2836 { 2837 int level; 2838 glu::DataType dataType; 2839 } variableTypes[] = 2840 { 2841 { 0, glu::TYPE_SAMPLER_2D }, 2842 { 2, glu::TYPE_SAMPLER_CUBE }, 2843 { 1, glu::TYPE_SAMPLER_2D_ARRAY }, 2844 { 1, glu::TYPE_SAMPLER_3D }, 2845 { 2, glu::TYPE_SAMPLER_2D_SHADOW }, 2846 { 3, glu::TYPE_SAMPLER_CUBE_SHADOW }, 2847 { 3, glu::TYPE_SAMPLER_2D_ARRAY_SHADOW }, 2848 { 1, glu::TYPE_INT_SAMPLER_2D }, 2849 { 3, glu::TYPE_INT_SAMPLER_CUBE }, 2850 { 3, glu::TYPE_INT_SAMPLER_2D_ARRAY }, 2851 { 3, glu::TYPE_INT_SAMPLER_3D }, 2852 { 2, glu::TYPE_UINT_SAMPLER_2D }, 2853 { 3, glu::TYPE_UINT_SAMPLER_CUBE }, 2854 { 3, glu::TYPE_UINT_SAMPLER_2D_ARRAY }, 2855 { 3, glu::TYPE_UINT_SAMPLER_3D }, 2856 { 2, glu::TYPE_SAMPLER_2D_MULTISAMPLE }, 2857 { 2, glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE }, 2858 { 3, glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE }, 2859 { 1, glu::TYPE_IMAGE_2D }, 2860 { 3, glu::TYPE_IMAGE_CUBE }, 2861 { 3, glu::TYPE_IMAGE_2D_ARRAY }, 2862 { 3, glu::TYPE_IMAGE_3D }, 2863 { 3, glu::TYPE_INT_IMAGE_2D }, 2864 { 3, glu::TYPE_INT_IMAGE_CUBE }, 2865 { 1, glu::TYPE_INT_IMAGE_2D_ARRAY }, 2866 { 3, glu::TYPE_INT_IMAGE_3D }, 2867 { 2, glu::TYPE_UINT_IMAGE_2D }, 2868 { 3, glu::TYPE_UINT_IMAGE_CUBE }, 2869 { 3, glu::TYPE_UINT_IMAGE_2D_ARRAY }, 2870 { 3, glu::TYPE_UINT_IMAGE_3D }, 2871 { 1, glu::TYPE_UINT_ATOMIC_COUNTER }, 2872 }; 2873 2874 bool isStructMember = false; 2875 2876 // Requirements 2877 for (const ResourceDefinition::Node* node = parentStructure.get(); node; node = node->getEnclosingNode()) 2878 { 2879 // Don't insert inside a interface block 2880 if (node->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK) 2881 return; 2882 2883 isStructMember |= (node->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER); 2884 } 2885 2886 // Add cases 2887 { 2888 tcu::TestCaseGroup* group; 2889 2890 if (createTestGroup) 2891 { 2892 group = new tcu::TestCaseGroup(context.getTestContext(), "opaque_type", "Opaque types"); 2893 targetGroup->addChild(group); 2894 } 2895 else 2896 group = targetGroup; 2897 2898 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx) 2899 { 2900 if (variableTypes[ndx].level > expandLevel) 2901 continue; 2902 2903 // Layout qualifiers are not allowed on struct members 2904 if (isDataTypeLayoutQualified(variableTypes[ndx].dataType) && isStructMember) 2905 continue; 2906 2907 { 2908 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType)); 2909 group->addChild(new ResourceTestCase(context, variable, queryTarget)); 2910 } 2911 } 2912 } 2913 } 2914 2915 static void generateCompoundVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3); 2916 2917 static void generateVariableArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3) 2918 { 2919 if (expandLevel > 0) 2920 { 2921 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 2922 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays"); 2923 2924 targetGroup->addChild(blockGroup); 2925 2926 // Arrays of basic variables 2927 generateVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel, expandLevel != 1); 2928 2929 // Arrays of opaque types 2930 generateOpaqueTypeCases(context, arrayElement, blockGroup, queryTarget, expandLevel, expandLevel != 1); 2931 2932 // Arrays of arrays 2933 generateVariableArrayCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1); 2934 2935 // Arrays of structs 2936 generateCompoundVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1); 2937 } 2938 } 2939 2940 static void generateCompoundVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel) 2941 { 2942 if (expandLevel > 0) 2943 { 2944 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 2945 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "struct", "Structs"); 2946 2947 targetGroup->addChild(blockGroup); 2948 2949 // Struct containing basic variable 2950 generateVariableCases(context, structMember, blockGroup, queryTarget, expandLevel, expandLevel != 1); 2951 2952 // Struct containing opaque types 2953 generateOpaqueTypeCases(context, structMember, blockGroup, queryTarget, expandLevel, expandLevel != 1); 2954 2955 // Struct containing arrays 2956 generateVariableArrayCases(context, structMember, blockGroup, queryTarget, expandLevel-1); 2957 2958 // Struct containing struct 2959 generateCompoundVariableCases(context, structMember, blockGroup, queryTarget, expandLevel-1); 2960 } 2961 } 2962 2963 // Resource list cases 2964 2965 enum BlockFlags 2966 { 2967 BLOCKFLAG_DEFAULT = 0x01, 2968 BLOCKFLAG_NAMED = 0x02, 2969 BLOCKFLAG_UNNAMED = 0x04, 2970 BLOCKFLAG_ARRAY = 0x08, 2971 2972 BLOCKFLAG_ALL = 0x0F 2973 }; 2974 2975 static void generateUniformCaseBlocks (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, deUint32 blockFlags, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const)) 2976 { 2977 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 2978 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM)); 2979 2980 // .default_block 2981 if (blockFlags & BLOCKFLAG_DEFAULT) 2982 { 2983 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "default_block", "Default block"); 2984 targetGroup->addChild(blockGroup); 2985 2986 blockContentGenerator(context, uniform, blockGroup); 2987 } 2988 2989 // .named_block 2990 if (blockFlags & BLOCKFLAG_NAMED) 2991 { 2992 const ResourceDefinition::Node::SharedPtr block(new ResourceDefinition::InterfaceBlock(uniform, true)); 2993 2994 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "named_block", "Named uniform block"); 2995 targetGroup->addChild(blockGroup); 2996 2997 blockContentGenerator(context, block, blockGroup); 2998 } 2999 3000 // .unnamed_block 3001 if (blockFlags & BLOCKFLAG_UNNAMED) 3002 { 3003 const ResourceDefinition::Node::SharedPtr block(new ResourceDefinition::InterfaceBlock(uniform, false)); 3004 3005 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "unnamed_block", "Unnamed uniform block"); 3006 targetGroup->addChild(blockGroup); 3007 3008 blockContentGenerator(context, block, blockGroup); 3009 } 3010 3011 // .block_array 3012 if (blockFlags & BLOCKFLAG_ARRAY) 3013 { 3014 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(uniform)); 3015 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 3016 3017 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "block_array", "Uniform block array"); 3018 targetGroup->addChild(blockGroup); 3019 3020 blockContentGenerator(context, block, blockGroup); 3021 } 3022 } 3023 3024 static void generateBufferBackedResourceListBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, int depth) 3025 { 3026 // variable 3027 { 3028 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, glu::TYPE_FLOAT_VEC4)); 3029 targetGroup->addChild(new ResourceListTestCase(context, variable, interface)); 3030 } 3031 3032 // struct 3033 if (depth > 0) 3034 { 3035 const ResourceDefinition::Node::SharedPtr structMember(new ResourceDefinition::StructMember(parentStructure)); 3036 generateBufferBackedResourceListBlockContentCases(context, structMember, targetGroup, interface, depth - 1); 3037 } 3038 3039 // array 3040 if (depth > 0) 3041 { 3042 const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure)); 3043 generateBufferBackedResourceListBlockContentCases(context, arrayElement, targetGroup, interface, depth - 1); 3044 } 3045 } 3046 3047 static void generateBufferBackedVariableAggregateTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, ProgramResourcePropFlags targetProp, glu::DataType dataType, const std::string& nameSuffix, int depth) 3048 { 3049 // variable 3050 { 3051 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, dataType)); 3052 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, targetProp), ("var" + nameSuffix).c_str())); 3053 } 3054 3055 // struct 3056 if (depth > 0) 3057 { 3058 const ResourceDefinition::Node::SharedPtr structMember(new ResourceDefinition::StructMember(parentStructure)); 3059 generateBufferBackedVariableAggregateTypeCases(context, structMember, targetGroup, interface, targetProp, dataType, "_struct" + nameSuffix, depth - 1); 3060 } 3061 3062 // array 3063 if (depth > 0) 3064 { 3065 const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure)); 3066 generateBufferBackedVariableAggregateTypeCases(context, arrayElement, targetGroup, interface, targetProp, dataType, "_array" + nameSuffix, depth - 1); 3067 } 3068 } 3069 3070 static void generateUniformResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 3071 { 3072 generateBufferBackedResourceListBlockContentCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, 4); 3073 } 3074 3075 static void generateUniformBlockArraySizeContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 3076 { 3077 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ARRAY_SIZE); 3078 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK); 3079 const bool namedNonArrayBlock = isInterfaceBlock && 3080 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named && 3081 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT; 3082 3083 if (!isInterfaceBlock || namedNonArrayBlock) 3084 { 3085 // .types 3086 { 3087 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types"); 3088 targetGroup->addChild(blockGroup); 3089 3090 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 2, false); 3091 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 2, false); 3092 } 3093 3094 // aggregates 3095 { 3096 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types"); 3097 targetGroup->addChild(blockGroup); 3098 3099 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_ARRAY_SIZE, glu::TYPE_FLOAT, "", 3); 3100 } 3101 } 3102 else 3103 { 3104 // aggregates 3105 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, queryTarget.interface, PROGRAMRESOURCEPROP_ARRAY_SIZE, glu::TYPE_FLOAT, "", 2); 3106 } 3107 } 3108 3109 static void generateBufferBackedArrayStrideTypeAggregateSubCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const std::string& namePrefix, ProgramInterface interface, glu::DataType type, int expandLevel) 3110 { 3111 // case 3112 { 3113 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, type)); 3114 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_ARRAY_STRIDE), namePrefix.c_str())); 3115 } 3116 3117 if (expandLevel > 0) 3118 { 3119 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3120 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 3121 3122 // _struct 3123 generateBufferBackedArrayStrideTypeAggregateSubCases(context, structMember, targetGroup, namePrefix + "_struct", interface, type, expandLevel - 1); 3124 3125 // _array 3126 generateBufferBackedArrayStrideTypeAggregateSubCases(context, arrayElement, targetGroup, namePrefix + "_array", interface, type, expandLevel - 1); 3127 } 3128 } 3129 3130 static void generateBufferBackedArrayStrideTypeAggregateCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, glu::DataType type, int expandLevel, bool includeBaseCase) 3131 { 3132 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3133 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 3134 const std::string namePrefix = glu::getDataTypeName(type); 3135 3136 if (expandLevel == 0 || includeBaseCase) 3137 { 3138 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, type)); 3139 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_ARRAY_STRIDE), namePrefix.c_str())); 3140 } 3141 if (expandLevel >= 1) 3142 { 3143 // _struct 3144 if (!glu::isDataTypeAtomicCounter(type)) 3145 generateBufferBackedArrayStrideTypeAggregateSubCases(context, structMember, targetGroup, namePrefix + "_struct", interface, type, expandLevel - 1); 3146 3147 // _array 3148 generateBufferBackedArrayStrideTypeAggregateSubCases(context, arrayElement, targetGroup, namePrefix + "_array", interface, type, expandLevel - 1); 3149 } 3150 } 3151 3152 static void generateUniformBlockArrayStrideContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 3153 { 3154 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ARRAY_STRIDE); 3155 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK); 3156 const bool namedNonArrayBlock = isInterfaceBlock && 3157 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named && 3158 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT; 3159 3160 if (!isInterfaceBlock || namedNonArrayBlock) 3161 { 3162 // .types 3163 { 3164 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types"); 3165 targetGroup->addChild(blockGroup); 3166 3167 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 2, false); 3168 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 2, false); 3169 } 3170 3171 // .aggregates 3172 { 3173 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types"); 3174 targetGroup->addChild(blockGroup); 3175 3176 // .sampler_2d_* 3177 if (!isInterfaceBlock) 3178 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_SAMPLER_2D, 1, false); 3179 3180 // .atomic_counter_* 3181 if (!isInterfaceBlock) 3182 { 3183 const ResourceDefinition::Node::SharedPtr layout(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0))); 3184 generateBufferBackedArrayStrideTypeAggregateCases(context, layout, blockGroup, queryTarget.interface, glu::TYPE_UINT_ATOMIC_COUNTER, 1, false); 3185 } 3186 3187 // .float_* 3188 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_FLOAT, 2, false); 3189 3190 // .bool_* 3191 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_BOOL, 1, false); 3192 3193 // .bvec3_* 3194 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_BOOL_VEC3, 2, false); 3195 3196 // .vec3_* 3197 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_FLOAT_VEC3, 2, false); 3198 3199 // .ivec2_* 3200 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_INT_VEC3, 2, false); 3201 } 3202 } 3203 else 3204 { 3205 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1); 3206 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1); 3207 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1); 3208 } 3209 } 3210 3211 static void generateUniformBlockLocationContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 3212 { 3213 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_LOCATION); 3214 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK); 3215 3216 if (!isInterfaceBlock) 3217 { 3218 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 3); 3219 generateOpaqueTypeCases(context, parentStructure, targetGroup, queryTarget, 3); 3220 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 2); 3221 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 2); 3222 } 3223 else 3224 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1, false); 3225 } 3226 3227 static void generateUniformBlockBlockIndexContents (Context& context, tcu::TestCaseGroup* const targetGroup) 3228 { 3229 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 3230 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 3231 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 3232 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM)); 3233 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(uniform, glu::Layout(-1, 0))); 3234 3235 // .default_block 3236 { 3237 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(uniform, glu::TYPE_FLOAT_VEC4)); 3238 3239 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "default_block")); 3240 } 3241 3242 // .named_block 3243 { 3244 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, true)); 3245 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4)); 3246 3247 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "named_block")); 3248 } 3249 3250 // .unnamed_block 3251 { 3252 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, false)); 3253 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4)); 3254 3255 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "unnamed_block")); 3256 } 3257 3258 // .block_array 3259 { 3260 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding)); 3261 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 3262 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4)); 3263 3264 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "block_array")); 3265 } 3266 } 3267 3268 static void generateUniformBlockAtomicCounterBufferIndexContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 3269 { 3270 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ATOMIC_COUNTER_BUFFER_INDEX); 3271 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK); 3272 3273 if (!isInterfaceBlock) 3274 { 3275 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 3); 3276 generateOpaqueTypeCases(context, parentStructure, targetGroup, queryTarget, 3); 3277 3278 // .array 3279 { 3280 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 3281 const ResourceDefinition::Node::SharedPtr arrayArrayElement (new ResourceDefinition::ArrayElement(arrayElement)); 3282 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER)); 3283 const ResourceDefinition::Node::SharedPtr elementvariable (new ResourceDefinition::Variable(arrayArrayElement, glu::TYPE_UINT_ATOMIC_COUNTER)); 3284 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays"); 3285 3286 targetGroup->addChild(blockGroup); 3287 3288 blockGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "var_array")); 3289 blockGroup->addChild(new ResourceTestCase(context, elementvariable, queryTarget, "var_array_array")); 3290 } 3291 } 3292 else 3293 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1, false); 3294 } 3295 3296 static void generateUniformBlockNameLengthContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 3297 { 3298 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK); 3299 const bool namedNonArrayBlock = isInterfaceBlock && 3300 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named && 3301 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT; 3302 3303 if (!isInterfaceBlock || namedNonArrayBlock) 3304 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 2); 3305 else 3306 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 1); 3307 } 3308 3309 static void generateUniformBlockTypeContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 3310 { 3311 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_TYPE); 3312 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK); 3313 const bool namedNonArrayBlock = isInterfaceBlock && 3314 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named && 3315 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT; 3316 3317 if (!isInterfaceBlock || namedNonArrayBlock) 3318 { 3319 // .types 3320 { 3321 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types"); 3322 targetGroup->addChild(blockGroup); 3323 3324 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false); 3325 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false); 3326 } 3327 3328 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1); 3329 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1); 3330 3331 } 3332 else 3333 { 3334 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1); 3335 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1); 3336 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1); 3337 } 3338 } 3339 3340 static void generateUniformBlockOffsetContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 3341 { 3342 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_OFFSET); 3343 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK); 3344 const bool namedNonArrayBlock = isInterfaceBlock && 3345 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named && 3346 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT; 3347 3348 if (!isInterfaceBlock) 3349 { 3350 // .types 3351 { 3352 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types"); 3353 targetGroup->addChild(blockGroup); 3354 3355 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false); 3356 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false); 3357 } 3358 3359 // .aggregates 3360 { 3361 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types"); 3362 targetGroup->addChild(blockGroup); 3363 3364 // .atomic_uint_struct 3365 // .atomic_uint_array 3366 { 3367 const ResourceDefinition::Node::SharedPtr offset (new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, 4))); 3368 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(offset)); 3369 const ResourceDefinition::Node::SharedPtr elementVariable (new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER)); 3370 3371 blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "atomic_uint_array")); 3372 } 3373 3374 // .float_array 3375 // .float_struct 3376 { 3377 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3378 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 3379 const ResourceDefinition::Node::SharedPtr memberVariable (new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT)); 3380 const ResourceDefinition::Node::SharedPtr elementVariable (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT)); 3381 3382 blockGroup->addChild(new ResourceTestCase(context, memberVariable, queryTarget, "float_struct")); 3383 blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "float_array")); 3384 } 3385 } 3386 } 3387 else if (namedNonArrayBlock) 3388 { 3389 // .types 3390 { 3391 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types"); 3392 targetGroup->addChild(blockGroup); 3393 3394 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false); 3395 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false); 3396 } 3397 3398 // .aggregates 3399 { 3400 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types"); 3401 targetGroup->addChild(blockGroup); 3402 3403 // .float_array 3404 // .float_struct 3405 { 3406 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3407 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::StructMember(parentStructure)); 3408 const ResourceDefinition::Node::SharedPtr memberVariable (new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT)); 3409 const ResourceDefinition::Node::SharedPtr elementVariable (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT)); 3410 3411 blockGroup->addChild(new ResourceTestCase(context, memberVariable, queryTarget, "float_struct")); 3412 blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "float_array")); 3413 } 3414 } 3415 } 3416 else 3417 { 3418 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1); 3419 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1); 3420 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1); 3421 } 3422 } 3423 3424 static void generateMatrixVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, bool createTestGroup = true, int expandLevel = 2) 3425 { 3426 static const struct 3427 { 3428 int priority; 3429 glu::DataType type; 3430 } variableTypes[] = 3431 { 3432 { 0, glu::TYPE_FLOAT_MAT2 }, 3433 { 1, glu::TYPE_FLOAT_MAT2X3 }, 3434 { 2, glu::TYPE_FLOAT_MAT2X4 }, 3435 { 2, glu::TYPE_FLOAT_MAT3X2 }, 3436 { 1, glu::TYPE_FLOAT_MAT3 }, 3437 { 0, glu::TYPE_FLOAT_MAT3X4 }, 3438 { 2, glu::TYPE_FLOAT_MAT4X2 }, 3439 { 1, glu::TYPE_FLOAT_MAT4X3 }, 3440 { 0, glu::TYPE_FLOAT_MAT4 }, 3441 }; 3442 3443 tcu::TestCaseGroup* group; 3444 3445 if (createTestGroup) 3446 { 3447 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "matrix", "Basic matrix type"); 3448 targetGroup->addChild(blockGroup); 3449 group = blockGroup; 3450 } 3451 else 3452 group = targetGroup; 3453 3454 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx) 3455 { 3456 if (variableTypes[ndx].priority < expandLevel) 3457 { 3458 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].type)); 3459 group->addChild(new ResourceTestCase(context, variable, queryTarget)); 3460 } 3461 } 3462 } 3463 3464 static void generateMatrixStructCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel); 3465 3466 static void generateMatrixArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel) 3467 { 3468 if (expandLevel > 0) 3469 { 3470 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 3471 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays"); 3472 3473 targetGroup->addChild(blockGroup); 3474 3475 // Arrays of basic variables 3476 generateMatrixVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel != 1, expandLevel); 3477 3478 // Arrays of arrays 3479 generateMatrixArrayCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1); 3480 3481 // Arrays of structs 3482 generateMatrixStructCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1); 3483 } 3484 } 3485 3486 static void generateMatrixStructCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel) 3487 { 3488 if (expandLevel > 0) 3489 { 3490 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3491 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "struct", "Structs"); 3492 3493 targetGroup->addChild(blockGroup); 3494 3495 // Struct containing basic variable 3496 generateMatrixVariableCases(context, structMember, blockGroup, queryTarget, expandLevel != 1, expandLevel); 3497 3498 // Struct containing arrays 3499 generateMatrixArrayCases(context, structMember, blockGroup, queryTarget, expandLevel-1); 3500 3501 // Struct containing struct 3502 generateMatrixStructCases(context, structMember, blockGroup, queryTarget, expandLevel-1); 3503 } 3504 } 3505 3506 static void generateUniformMatrixOrderCaseBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, bool extendedBasicTypeCases, bool opaqueCases) 3507 { 3508 static const struct 3509 { 3510 const char* name; 3511 glu::MatrixOrder order; 3512 } qualifiers[] = 3513 { 3514 { "no_qualifier", glu::MATRIXORDER_LAST }, 3515 { "row_major", glu::MATRIXORDER_ROW_MAJOR }, 3516 { "column_major", glu::MATRIXORDER_COLUMN_MAJOR }, 3517 }; 3518 3519 const ProgramResourceQueryTestTarget queryTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR); 3520 3521 for (int qualifierNdx = 0; qualifierNdx < DE_LENGTH_OF_ARRAY(qualifiers); ++qualifierNdx) 3522 { 3523 // Add layout qualifiers only for block members 3524 if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST || parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK) 3525 { 3526 ResourceDefinition::Node::SharedPtr subStructure = parentStructure; 3527 tcu::TestCaseGroup* const qualifierGroup = new tcu::TestCaseGroup(context.getTestContext(), qualifiers[qualifierNdx].name, ""); 3528 3529 targetGroup->addChild(qualifierGroup); 3530 3531 if (qualifiers[qualifierNdx].order != glu::MATRIXORDER_LAST) 3532 { 3533 glu::Layout layout; 3534 layout.matrixOrder = qualifiers[qualifierNdx].order; 3535 subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout)); 3536 } 3537 3538 if (extendedBasicTypeCases && qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST) 3539 { 3540 // .types 3541 { 3542 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", ""); 3543 qualifierGroup->addChild(blockGroup); 3544 3545 generateVariableCases(context, subStructure, blockGroup, queryTarget, 1, false); 3546 generateMatrixVariableCases(context, subStructure, blockGroup, queryTarget, false); 3547 if (opaqueCases) 3548 generateOpaqueTypeCases(context, subStructure, blockGroup, queryTarget, 2, false); 3549 } 3550 3551 // .aggregates 3552 { 3553 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", ""); 3554 qualifierGroup->addChild(blockGroup); 3555 3556 generateBufferBackedVariableAggregateTypeCases(context, subStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1); 3557 } 3558 } 3559 else 3560 { 3561 generateBufferBackedVariableAggregateTypeCases(context, subStructure, qualifierGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1); 3562 } 3563 } 3564 } 3565 } 3566 3567 static void generateUniformMatrixStrideCaseBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, bool extendedBasicTypeCases, bool opaqueCases) 3568 { 3569 static const struct 3570 { 3571 const char* name; 3572 glu::MatrixOrder order; 3573 } qualifiers[] = 3574 { 3575 { "no_qualifier", glu::MATRIXORDER_LAST }, 3576 { "row_major", glu::MATRIXORDER_ROW_MAJOR }, 3577 { "column_major", glu::MATRIXORDER_COLUMN_MAJOR }, 3578 }; 3579 3580 const ProgramResourceQueryTestTarget queryTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_MATRIX_STRIDE); 3581 3582 for (int qualifierNdx = 0; qualifierNdx < DE_LENGTH_OF_ARRAY(qualifiers); ++qualifierNdx) 3583 { 3584 // Add layout qualifiers only for block members 3585 if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST || parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK) 3586 { 3587 ResourceDefinition::Node::SharedPtr subStructure = parentStructure; 3588 tcu::TestCaseGroup* const qualifierGroup = new tcu::TestCaseGroup(context.getTestContext(), qualifiers[qualifierNdx].name, ""); 3589 3590 targetGroup->addChild(qualifierGroup); 3591 3592 if (qualifiers[qualifierNdx].order != glu::MATRIXORDER_LAST) 3593 { 3594 glu::Layout layout; 3595 layout.matrixOrder = qualifiers[qualifierNdx].order; 3596 subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout)); 3597 } 3598 3599 if (extendedBasicTypeCases) 3600 { 3601 // .types 3602 // .matrix 3603 if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST) 3604 { 3605 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", ""); 3606 qualifierGroup->addChild(blockGroup); 3607 3608 generateVariableCases(context, subStructure, blockGroup, queryTarget, 1, false); 3609 generateMatrixVariableCases(context, subStructure, blockGroup, queryTarget, false); 3610 if (opaqueCases) 3611 generateOpaqueTypeCases(context, subStructure, blockGroup, queryTarget, 2, false); 3612 } 3613 else 3614 generateMatrixVariableCases(context, subStructure, qualifierGroup, queryTarget); 3615 3616 // .aggregates 3617 { 3618 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", ""); 3619 qualifierGroup->addChild(blockGroup); 3620 3621 generateBufferBackedVariableAggregateTypeCases(context, subStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1); 3622 } 3623 } 3624 else 3625 generateBufferBackedVariableAggregateTypeCases(context, subStructure, qualifierGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1); 3626 } 3627 } 3628 } 3629 3630 static void generateUniformMatrixCaseBlocks (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const, bool, bool)) 3631 { 3632 static const struct 3633 { 3634 const char* name; 3635 const char* description; 3636 bool block; 3637 bool namedBlock; 3638 bool extendedBasicTypeCases; 3639 glu::MatrixOrder order; 3640 } children[] = 3641 { 3642 { "default_block", "Default block", false, true, true, glu::MATRIXORDER_LAST }, 3643 { "named_block", "Named uniform block", true, true, true, glu::MATRIXORDER_LAST }, 3644 { "named_block_row_major", "Named uniform block", true, true, false, glu::MATRIXORDER_ROW_MAJOR }, 3645 { "named_block_col_major", "Named uniform block", true, true, false, glu::MATRIXORDER_COLUMN_MAJOR }, 3646 { "unnamed_block", "Unnamed uniform block", true, false, false, glu::MATRIXORDER_LAST }, 3647 { "unnamed_block_row_major", "Unnamed uniform block", true, false, false, glu::MATRIXORDER_ROW_MAJOR }, 3648 { "unnamed_block_col_major", "Unnamed uniform block", true, false, false, glu::MATRIXORDER_COLUMN_MAJOR }, 3649 }; 3650 3651 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 3652 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM)); 3653 3654 for (int childNdx = 0; childNdx < (int)DE_LENGTH_OF_ARRAY(children); ++childNdx) 3655 { 3656 ResourceDefinition::Node::SharedPtr subStructure = uniform; 3657 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), children[childNdx].name, children[childNdx].description); 3658 const bool addOpaqueCases = children[childNdx].extendedBasicTypeCases && !children[childNdx].block; 3659 3660 targetGroup->addChild(blockGroup); 3661 3662 if (children[childNdx].order != glu::MATRIXORDER_LAST) 3663 { 3664 glu::Layout layout; 3665 layout.matrixOrder = children[childNdx].order; 3666 subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout)); 3667 } 3668 3669 if (children[childNdx].block) 3670 subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(subStructure, children[childNdx].namedBlock)); 3671 3672 blockContentGenerator(context, subStructure, blockGroup, children[childNdx].extendedBasicTypeCases, addOpaqueCases); 3673 } 3674 } 3675 3676 static void generateBufferReferencedByShaderInterfaceBlockCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, bool extendedCases) 3677 { 3678 const bool isDefaultBlock = (parentStructure->getType() != ResourceDefinition::Node::TYPE_INTERFACE_BLOCK); 3679 3680 // .float 3681 // .float_array 3682 // .float_struct 3683 { 3684 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(parentStructure, glu::TYPE_FLOAT)); 3685 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 3686 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3687 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT)); 3688 const ResourceDefinition::Node::SharedPtr variableStruct (new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT)); 3689 3690 targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "float")); 3691 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_array")); 3692 targetGroup->addChild(new ResourceTestCase(context, variableStruct, queryTarget, "float_struct")); 3693 } 3694 3695 // .sampler 3696 // .sampler_array 3697 // .sampler_struct 3698 if (isDefaultBlock) 3699 { 3700 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0))); 3701 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_SAMPLER_2D)); 3702 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(layout)); 3703 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3704 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(arrayElement, glu::TYPE_SAMPLER_2D)); 3705 const ResourceDefinition::Node::SharedPtr variableStruct (new ResourceDefinition::Variable(structMember, glu::TYPE_SAMPLER_2D)); 3706 3707 targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "sampler")); 3708 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "sampler_array")); 3709 targetGroup->addChild(new ResourceTestCase(context, variableStruct, queryTarget, "sampler_struct")); 3710 } 3711 3712 // .atomic_uint 3713 // .atomic_uint_array 3714 if (isDefaultBlock) 3715 { 3716 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0))); 3717 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_UINT_ATOMIC_COUNTER)); 3718 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(layout)); 3719 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER)); 3720 3721 targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "atomic_uint")); 3722 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "atomic_uint_array")); 3723 } 3724 3725 if (extendedCases) 3726 { 3727 // .float_array_struct 3728 { 3729 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3730 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(structMember)); 3731 const ResourceDefinition::Node::SharedPtr variableArrayStruct (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT)); 3732 3733 targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_array_struct")); 3734 } 3735 3736 // .float_struct_array 3737 { 3738 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 3739 const ResourceDefinition::Node::SharedPtr arrayStructMember (new ResourceDefinition::StructMember(arrayElement)); 3740 const ResourceDefinition::Node::SharedPtr variableArrayStruct (new ResourceDefinition::Variable(arrayStructMember, glu::TYPE_FLOAT)); 3741 3742 targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_struct_array")); 3743 } 3744 3745 // .float_array_array 3746 { 3747 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 3748 const ResourceDefinition::Node::SharedPtr subArrayElement (new ResourceDefinition::ArrayElement(arrayElement)); 3749 const ResourceDefinition::Node::SharedPtr variableArrayStruct (new ResourceDefinition::Variable(subArrayElement, glu::TYPE_FLOAT)); 3750 3751 targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_array_array")); 3752 } 3753 3754 // .float_struct_struct 3755 { 3756 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 3757 const ResourceDefinition::Node::SharedPtr subStructMember (new ResourceDefinition::StructMember(structMember)); 3758 const ResourceDefinition::Node::SharedPtr variableArrayStruct (new ResourceDefinition::Variable(subStructMember, glu::TYPE_FLOAT)); 3759 3760 targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_struct_struct")); 3761 } 3762 3763 if (queryTarget.interface == PROGRAMINTERFACE_BUFFER_VARIABLE) 3764 { 3765 const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY)); 3766 3767 // .float_unsized_array 3768 { 3769 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT)); 3770 3771 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_unsized_array")); 3772 } 3773 3774 // .float_unsized_struct_array 3775 { 3776 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(arrayElement)); 3777 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT)); 3778 3779 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_unsized_struct_array")); 3780 } 3781 } 3782 } 3783 } 3784 3785 static void generateUniformReferencedByShaderSingleBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, int expandLevel) 3786 { 3787 DE_UNREF(expandLevel); 3788 3789 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 3790 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM)); 3791 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER); 3792 const bool singleShaderCase = parentStructure->getType() == ResourceDefinition::Node::TYPE_SHADER; 3793 3794 // .default_block 3795 { 3796 TestCaseGroup* const blockGroup = new TestCaseGroup(context, "default_block", ""); 3797 targetGroup->addChild(blockGroup); 3798 3799 generateBufferReferencedByShaderInterfaceBlockCases(context, uniform, blockGroup, queryTarget, singleShaderCase); 3800 } 3801 3802 // .named_block 3803 { 3804 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(uniform, true)); 3805 TestCaseGroup* const blockGroup = new TestCaseGroup(context, "uniform_block", ""); 3806 3807 targetGroup->addChild(blockGroup); 3808 3809 generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, singleShaderCase); 3810 } 3811 3812 // .unnamed_block 3813 { 3814 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(uniform, false)); 3815 TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unnamed_block", ""); 3816 3817 targetGroup->addChild(blockGroup); 3818 3819 generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, false); 3820 } 3821 3822 // .block_array 3823 { 3824 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(uniform)); 3825 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 3826 TestCaseGroup* const blockGroup = new TestCaseGroup(context, "block_array", ""); 3827 3828 targetGroup->addChild(blockGroup); 3829 3830 generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, false); 3831 } 3832 } 3833 3834 static void generateReferencedByShaderCaseBlocks (Context& context, tcu::TestCaseGroup* const targetGroup, void (*generateBlockContent)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, int expandLevel)) 3835 { 3836 static const struct 3837 { 3838 const char* name; 3839 glu::ShaderType stage; 3840 int expandLevel; 3841 } singleStageCases[] = 3842 { 3843 { "compute", glu::SHADERTYPE_COMPUTE, 3 }, 3844 { "separable_vertex", glu::SHADERTYPE_VERTEX, 2 }, 3845 { "separable_fragment", glu::SHADERTYPE_FRAGMENT, 2 }, 3846 }; 3847 3848 static const struct 3849 { 3850 const char* name; 3851 deUint32 stagesPresent; 3852 deUint32 stagesReferencing; 3853 int expandLevel; 3854 } multiStageCases[] = 3855 { 3856 { "vertex_fragment", (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT), (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT), 3 }, 3857 { "vertex_fragment_only_fragment", (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT), (1 << glu::SHADERTYPE_FRAGMENT), 2 }, 3858 { "vertex_fragment_only_vertex", (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT), (1 << glu::SHADERTYPE_VERTEX), 2 }, 3859 }; 3860 3861 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleStageCases); ++ndx) 3862 { 3863 TestCaseGroup* const blockGroup = new TestCaseGroup(context, singleStageCases[ndx].name, ""); 3864 const bool programSeparable = (singleStageCases[ndx].stage != glu::SHADERTYPE_COMPUTE); 3865 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(programSeparable)); 3866 const ResourceDefinition::Node::SharedPtr stage (new ResourceDefinition::Shader(program, singleStageCases[ndx].stage, glu::GLSL_VERSION_310_ES)); 3867 3868 targetGroup->addChild(blockGroup); 3869 3870 generateBlockContent(context, stage, blockGroup, singleStageCases[ndx].expandLevel); 3871 } 3872 3873 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(multiStageCases); ++ndx) 3874 { 3875 TestCaseGroup* const blockGroup = new TestCaseGroup(context, multiStageCases[ndx].name, ""); 3876 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 3877 ResourceDefinition::ShaderSet* shaderSet = new ResourceDefinition::ShaderSet(program, glu::GLSL_VERSION_310_ES); 3878 3879 targetGroup->addChild(blockGroup); 3880 3881 for (int shaderBit = 0; shaderBit < glu::SHADERTYPE_LAST; ++shaderBit) 3882 { 3883 const int stageMask = (1 << shaderBit); 3884 const bool stagePresent = (multiStageCases[ndx].stagesPresent & stageMask) != 0; 3885 const bool stageReferencing = (multiStageCases[ndx].stagesReferencing & stageMask) != 0; 3886 3887 DE_ASSERT(stagePresent || !stageReferencing); 3888 3889 if (stagePresent) 3890 shaderSet->setStage((glu::ShaderType)shaderBit, stageReferencing); 3891 } 3892 3893 { 3894 const ResourceDefinition::Node::SharedPtr shaders(shaderSet); 3895 3896 generateBlockContent(context, shaders, blockGroup, multiStageCases[ndx].expandLevel); 3897 } 3898 } 3899 } 3900 3901 static glu::DataType generateRandomDataType (de::Random& rnd, bool excludeOpaqueTypes) 3902 { 3903 static const glu::DataType s_types[] = 3904 { 3905 glu::TYPE_FLOAT, 3906 glu::TYPE_INT, 3907 glu::TYPE_UINT, 3908 glu::TYPE_BOOL, 3909 glu::TYPE_FLOAT_VEC2, 3910 glu::TYPE_FLOAT_VEC3, 3911 glu::TYPE_FLOAT_VEC4, 3912 glu::TYPE_INT_VEC2, 3913 glu::TYPE_INT_VEC3, 3914 glu::TYPE_INT_VEC4, 3915 glu::TYPE_UINT_VEC2, 3916 glu::TYPE_UINT_VEC3, 3917 glu::TYPE_UINT_VEC4, 3918 glu::TYPE_BOOL_VEC2, 3919 glu::TYPE_BOOL_VEC3, 3920 glu::TYPE_BOOL_VEC4, 3921 glu::TYPE_FLOAT_MAT2, 3922 glu::TYPE_FLOAT_MAT2X3, 3923 glu::TYPE_FLOAT_MAT2X4, 3924 glu::TYPE_FLOAT_MAT3X2, 3925 glu::TYPE_FLOAT_MAT3, 3926 glu::TYPE_FLOAT_MAT3X4, 3927 glu::TYPE_FLOAT_MAT4X2, 3928 glu::TYPE_FLOAT_MAT4X3, 3929 glu::TYPE_FLOAT_MAT4, 3930 3931 glu::TYPE_SAMPLER_2D, 3932 glu::TYPE_SAMPLER_CUBE, 3933 glu::TYPE_SAMPLER_2D_ARRAY, 3934 glu::TYPE_SAMPLER_3D, 3935 glu::TYPE_SAMPLER_2D_SHADOW, 3936 glu::TYPE_SAMPLER_CUBE_SHADOW, 3937 glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, 3938 glu::TYPE_INT_SAMPLER_2D, 3939 glu::TYPE_INT_SAMPLER_CUBE, 3940 glu::TYPE_INT_SAMPLER_2D_ARRAY, 3941 glu::TYPE_INT_SAMPLER_3D, 3942 glu::TYPE_UINT_SAMPLER_2D, 3943 glu::TYPE_UINT_SAMPLER_CUBE, 3944 glu::TYPE_UINT_SAMPLER_2D_ARRAY, 3945 glu::TYPE_UINT_SAMPLER_3D, 3946 glu::TYPE_SAMPLER_2D_MULTISAMPLE, 3947 glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE, 3948 glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE, 3949 glu::TYPE_IMAGE_2D, 3950 glu::TYPE_IMAGE_CUBE, 3951 glu::TYPE_IMAGE_2D_ARRAY, 3952 glu::TYPE_IMAGE_3D, 3953 glu::TYPE_INT_IMAGE_2D, 3954 glu::TYPE_INT_IMAGE_CUBE, 3955 glu::TYPE_INT_IMAGE_2D_ARRAY, 3956 glu::TYPE_INT_IMAGE_3D, 3957 glu::TYPE_UINT_IMAGE_2D, 3958 glu::TYPE_UINT_IMAGE_CUBE, 3959 glu::TYPE_UINT_IMAGE_2D_ARRAY, 3960 glu::TYPE_UINT_IMAGE_3D, 3961 glu::TYPE_UINT_ATOMIC_COUNTER 3962 }; 3963 3964 for (;;) 3965 { 3966 const glu::DataType type = s_types[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_types)-1)]; 3967 3968 if (!excludeOpaqueTypes || 3969 glu::isDataTypeScalarOrVector(type) || 3970 glu::isDataTypeMatrix(type)) 3971 return type; 3972 } 3973 } 3974 3975 static ResourceDefinition::Node::SharedPtr generateRandomVariableDefinition (de::Random& rnd, const ResourceDefinition::Node::SharedPtr& parentStructure, glu::DataType baseType, const glu::Layout& layout, bool allowUnsized) 3976 { 3977 const int maxNesting = 4; 3978 ResourceDefinition::Node::SharedPtr currentStructure = parentStructure; 3979 const bool canBeInsideAStruct = layout.binding == -1 && !isDataTypeLayoutQualified(baseType); 3980 3981 for (int nestNdx = 0; nestNdx < maxNesting; ++nestNdx) 3982 { 3983 if (allowUnsized && nestNdx == 0 && rnd.getFloat() < 0.2) 3984 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY)); 3985 else if (rnd.getFloat() < 0.3 && canBeInsideAStruct) 3986 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StructMember(currentStructure)); 3987 else if (rnd.getFloat() < 0.3) 3988 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure)); 3989 else 3990 break; 3991 } 3992 3993 return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Variable(currentStructure, baseType)); 3994 } 3995 3996 static ResourceDefinition::Node::SharedPtr generateRandomShaderSet (de::Random& rnd) 3997 { 3998 if (rnd.getFloat() < 0.5f) 3999 { 4000 // compute only 4001 const ResourceDefinition::Node::SharedPtr program(new ResourceDefinition::Program()); 4002 return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 4003 } 4004 else if (rnd.getFloat() < 0.5f) 4005 { 4006 // vertex and fragment 4007 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 4008 ResourceDefinition::ShaderSet* shaderSet = new ResourceDefinition::ShaderSet(program, glu::GLSL_VERSION_310_ES); 4009 4010 if (rnd.getBool()) 4011 { 4012 shaderSet->setStage(glu::SHADERTYPE_VERTEX, true); 4013 shaderSet->setStage(glu::SHADERTYPE_FRAGMENT, rnd.getBool()); 4014 } 4015 else 4016 { 4017 shaderSet->setStage(glu::SHADERTYPE_VERTEX, rnd.getBool()); 4018 shaderSet->setStage(glu::SHADERTYPE_FRAGMENT, true); 4019 } 4020 4021 return ResourceDefinition::Node::SharedPtr(shaderSet); 4022 } 4023 else 4024 { 4025 // separate vertex or fragment 4026 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true)); 4027 const glu::ShaderType shaderType = (rnd.getBool()) ? (glu::SHADERTYPE_VERTEX) : (glu::SHADERTYPE_FRAGMENT); 4028 4029 return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Shader(program, shaderType, glu::GLSL_VERSION_310_ES)); 4030 } 4031 } 4032 4033 static glu::Layout generateRandomUniformBlockLayout (de::Random& rnd) 4034 { 4035 glu::Layout layout; 4036 4037 if (rnd.getBool()) 4038 layout.binding = rnd.getInt(0, 5); 4039 4040 if (rnd.getBool()) 4041 layout.matrixOrder = (rnd.getBool()) ? (glu::MATRIXORDER_COLUMN_MAJOR) : (glu::MATRIXORDER_ROW_MAJOR); 4042 4043 return layout; 4044 } 4045 4046 static glu::Layout generateRandomBufferBlockLayout (de::Random& rnd) 4047 { 4048 return generateRandomUniformBlockLayout(rnd); 4049 } 4050 4051 static glu::Layout generateRandomVariableLayout (de::Random& rnd, glu::DataType type, bool interfaceBlockMember) 4052 { 4053 glu::Layout layout; 4054 4055 if ((glu::isDataTypeAtomicCounter(type) || glu::isDataTypeImage(type) || glu::isDataTypeSampler(type)) && rnd.getBool()) 4056 layout.binding = rnd.getInt(0, 5); 4057 4058 if (glu::isDataTypeAtomicCounter(type) && rnd.getBool()) 4059 layout.offset = rnd.getInt(0, 3) * 4; 4060 4061 if (glu::isDataTypeMatrix(type) && interfaceBlockMember && rnd.getBool()) 4062 layout.matrixOrder = (rnd.getBool()) ? (glu::MATRIXORDER_COLUMN_MAJOR) : (glu::MATRIXORDER_ROW_MAJOR); 4063 4064 return layout; 4065 } 4066 4067 static void generateUniformRandomCase (Context& context, tcu::TestCaseGroup* const targetGroup, int index) 4068 { 4069 de::Random rnd (index * 0x12345); 4070 const ResourceDefinition::Node::SharedPtr shader = generateRandomShaderSet(rnd); 4071 const bool interfaceBlock = rnd.getBool(); 4072 const glu::DataType type = generateRandomDataType(rnd, interfaceBlock); 4073 const glu::Layout layout = generateRandomVariableLayout(rnd, type, interfaceBlock); 4074 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 4075 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM)); 4076 ResourceDefinition::Node::SharedPtr currentStructure = uniform; 4077 4078 if (interfaceBlock) 4079 { 4080 const bool namedBlock = rnd.getBool(); 4081 4082 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, generateRandomUniformBlockLayout(rnd))); 4083 4084 if (namedBlock && rnd.getBool()) 4085 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure)); 4086 4087 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(currentStructure, namedBlock)); 4088 } 4089 4090 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, layout)); 4091 currentStructure = generateRandomVariableDefinition(rnd, currentStructure, type, layout, false); 4092 4093 targetGroup->addChild(new ResourceTestCase(context, currentStructure, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_UNIFORM_INTERFACE_MASK), de::toString(index).c_str())); 4094 } 4095 4096 static void generateUniformCaseRandomCases (Context& context, tcu::TestCaseGroup* const targetGroup) 4097 { 4098 const int numCases = 40; 4099 4100 for (int ndx = 0; ndx < numCases; ++ndx) 4101 generateUniformRandomCase(context, targetGroup, ndx); 4102 } 4103 4104 class UniformInterfaceTestGroup : public TestCaseGroup 4105 { 4106 public: 4107 UniformInterfaceTestGroup (Context& context); 4108 void init (void); 4109 }; 4110 4111 UniformInterfaceTestGroup::UniformInterfaceTestGroup (Context& context) 4112 : TestCaseGroup(context, "uniform", "Uniform interace") 4113 { 4114 } 4115 4116 void UniformInterfaceTestGroup::init (void) 4117 { 4118 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 4119 const ResourceDefinition::Node::SharedPtr computeShader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 4120 4121 // .resource_list 4122 { 4123 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list"); 4124 addChild(blockGroup); 4125 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformResourceListBlockContents); 4126 } 4127 4128 // .array_size 4129 { 4130 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Query array size"); 4131 addChild(blockGroup); 4132 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockArraySizeContents); 4133 } 4134 4135 // .array_stride 4136 { 4137 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_stride", "Query array stride"); 4138 addChild(blockGroup); 4139 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockArrayStrideContents); 4140 } 4141 4142 // .atomic_counter_buffer_index 4143 { 4144 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "atomic_counter_buffer_index", "Query atomic counter buffer index"); 4145 addChild(blockGroup); 4146 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_DEFAULT | BLOCKFLAG_NAMED, generateUniformBlockAtomicCounterBufferIndexContents); 4147 } 4148 4149 // .block_index 4150 { 4151 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "block_index", "Query block index"); 4152 addChild(blockGroup); 4153 generateUniformBlockBlockIndexContents(m_context, blockGroup); 4154 } 4155 4156 // .location 4157 { 4158 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Query location"); 4159 addChild(blockGroup); 4160 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_DEFAULT | BLOCKFLAG_NAMED | BLOCKFLAG_UNNAMED, generateUniformBlockLocationContents); 4161 } 4162 4163 // .matrix_row_major 4164 { 4165 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "matrix_row_major", "Query matrix row_major"); 4166 addChild(blockGroup); 4167 generateUniformMatrixCaseBlocks(m_context, computeShader, blockGroup, generateUniformMatrixOrderCaseBlockContentCases); 4168 } 4169 4170 // .matrix_stride 4171 { 4172 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "matrix_stride", "Query matrix stride"); 4173 addChild(blockGroup); 4174 generateUniformMatrixCaseBlocks(m_context, computeShader, blockGroup, generateUniformMatrixStrideCaseBlockContentCases); 4175 } 4176 4177 // .name_length 4178 { 4179 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Query name length"); 4180 addChild(blockGroup); 4181 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockNameLengthContents); 4182 } 4183 4184 // .offset 4185 { 4186 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "offset", "Query offset"); 4187 addChild(blockGroup); 4188 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockOffsetContents); 4189 } 4190 4191 // .referenced_by_shader 4192 { 4193 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by_shader", "Query referenced by shader"); 4194 addChild(blockGroup); 4195 generateReferencedByShaderCaseBlocks(m_context, blockGroup, generateUniformReferencedByShaderSingleBlockContentCases); 4196 } 4197 4198 // .type 4199 { 4200 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Query type"); 4201 addChild(blockGroup); 4202 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockTypeContents); 4203 } 4204 4205 // .random 4206 { 4207 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random"); 4208 addChild(blockGroup); 4209 generateUniformCaseRandomCases(m_context, blockGroup); 4210 } 4211 } 4212 4213 static void generateBufferBackedInterfaceResourceListCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, const char* blockName) 4214 { 4215 targetGroup->addChild(new ResourceListTestCase(context, targetResource, interface, blockName)); 4216 } 4217 4218 static void generateBufferBackedInterfaceNameLengthCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, const char* blockName) 4219 { 4220 targetGroup->addChild(new ResourceTestCase(context, targetResource, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_NAME_LENGTH), blockName)); 4221 } 4222 4223 static void generateBufferBackedInterfaceResourceBasicBlockTypes (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const, ProgramInterface interface, const char* blockName)) 4224 { 4225 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 4226 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 4227 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 4228 const ResourceDefinition::Node::SharedPtr storageQualifier (new ResourceDefinition::StorageQualifier(defaultBlock, storage)); 4229 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(storageQualifier, glu::Layout(-1, 1))); 4230 const ProgramInterface programInterface = (storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK); 4231 4232 // .named_block 4233 { 4234 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(binding, true)); 4235 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4236 4237 blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "named_block"); 4238 } 4239 4240 // .unnamed_block 4241 { 4242 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(binding, false)); 4243 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4244 4245 blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "unnamed_block"); 4246 } 4247 4248 // .block_array 4249 { 4250 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding, 3)); 4251 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 4252 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4253 4254 blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "block_array"); 4255 } 4256 4257 // .block_array_single_element 4258 { 4259 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding, 1)); 4260 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 4261 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4262 4263 blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "block_array_single_element"); 4264 } 4265 } 4266 4267 static void generateBufferBackedInterfaceResourceBufferBindingCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage) 4268 { 4269 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 4270 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 4271 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 4272 const ResourceDefinition::Node::SharedPtr storageQualifier (new ResourceDefinition::StorageQualifier(defaultBlock, storage)); 4273 4274 for (int ndx = 0; ndx < 2; ++ndx) 4275 { 4276 const bool explicitBinding = (ndx == 1); 4277 const int bindingNdx = (explicitBinding) ? (1) : (-1); 4278 const std::string nameSuffix = (explicitBinding) ? ("_explicit_binding") : (""); 4279 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(storageQualifier, glu::Layout(-1, bindingNdx))); 4280 const ProgramInterface programInterface = (storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK); 4281 4282 // .named_block* 4283 { 4284 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(binding, true)); 4285 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4286 4287 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("named_block" + nameSuffix).c_str())); 4288 } 4289 4290 // .unnamed_block* 4291 { 4292 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(binding, false)); 4293 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4294 4295 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("unnamed_block" + nameSuffix).c_str())); 4296 } 4297 4298 // .block_array* 4299 { 4300 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding, 3)); 4301 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 4302 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4303 4304 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("block_array" + nameSuffix).c_str())); 4305 } 4306 } 4307 } 4308 4309 template <glu::Storage Storage> 4310 static void generateBufferBlockReferencedByShaderSingleBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel) 4311 { 4312 const ProgramInterface programInterface = (Storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : 4313 (Storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) : 4314 (PROGRAMINTERFACE_LAST); 4315 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4316 const ResourceDefinition::Node::SharedPtr storage (new ResourceDefinition::StorageQualifier(defaultBlock, Storage)); 4317 4318 DE_UNREF(expandLevel); 4319 4320 DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST); 4321 4322 // .named_block 4323 { 4324 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(storage, true)); 4325 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4326 4327 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "named_block")); 4328 } 4329 4330 // .unnamed_block 4331 { 4332 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(storage, false)); 4333 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4334 4335 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "unnamed_block")); 4336 } 4337 4338 // .block_array 4339 { 4340 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(storage, 3)); 4341 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 4342 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3)); 4343 4344 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "block_array")); 4345 } 4346 } 4347 4348 static void generateBufferBackedInterfaceResourceActiveVariablesCase (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage) 4349 { 4350 targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "named_block", "Named block", storage, InterfaceBlockActiveVariablesTestCase::CASE_NAMED_BLOCK)); 4351 targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "unnamed_block", "Unnamed block", storage, InterfaceBlockActiveVariablesTestCase::CASE_UNNAMED_BLOCK)); 4352 targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "block_array", "Block array", storage, InterfaceBlockActiveVariablesTestCase::CASE_BLOCK_ARRAY)); 4353 } 4354 4355 static void generateBufferBackedInterfaceResourceBufferDataSizeCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage) 4356 { 4357 targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "named_block", "Named block", storage, InterfaceBlockDataSizeTestCase::CASE_NAMED_BLOCK)); 4358 targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "unnamed_block", "Unnamed block", storage, InterfaceBlockDataSizeTestCase::CASE_UNNAMED_BLOCK)); 4359 targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "block_array", "Block array", storage, InterfaceBlockDataSizeTestCase::CASE_BLOCK_ARRAY)); 4360 } 4361 4362 class BufferBackedBlockInterfaceTestGroup : public TestCaseGroup 4363 { 4364 public: 4365 BufferBackedBlockInterfaceTestGroup (Context& context, glu::Storage interfaceBlockStorage); 4366 void init (void); 4367 4368 private: 4369 static const char* getGroupName (glu::Storage storage); 4370 static const char* getGroupDescription (glu::Storage storage); 4371 4372 const glu::Storage m_storage; 4373 }; 4374 4375 BufferBackedBlockInterfaceTestGroup::BufferBackedBlockInterfaceTestGroup(Context& context, glu::Storage storage) 4376 : TestCaseGroup (context, getGroupName(storage), getGroupDescription(storage)) 4377 , m_storage (storage) 4378 { 4379 DE_ASSERT(storage == glu::STORAGE_BUFFER || storage == glu::STORAGE_UNIFORM); 4380 } 4381 4382 void BufferBackedBlockInterfaceTestGroup::init (void) 4383 { 4384 // .resource_list 4385 { 4386 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list"); 4387 addChild(blockGroup); 4388 generateBufferBackedInterfaceResourceBasicBlockTypes(m_context, blockGroup, m_storage, generateBufferBackedInterfaceResourceListCase); 4389 } 4390 4391 // .active_variables 4392 { 4393 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "active_variables", "Active variables"); 4394 addChild(blockGroup); 4395 generateBufferBackedInterfaceResourceActiveVariablesCase(m_context, blockGroup, m_storage); 4396 } 4397 4398 // .buffer_binding 4399 { 4400 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "buffer_binding", "Buffer binding"); 4401 addChild(blockGroup); 4402 generateBufferBackedInterfaceResourceBufferBindingCases(m_context, blockGroup, m_storage); 4403 } 4404 4405 // .buffer_data_size 4406 { 4407 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "buffer_data_size", "Buffer data size"); 4408 addChild(blockGroup); 4409 generateBufferBackedInterfaceResourceBufferDataSizeCases(m_context, blockGroup, m_storage); 4410 } 4411 4412 // .name_length 4413 { 4414 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length"); 4415 addChild(blockGroup); 4416 generateBufferBackedInterfaceResourceBasicBlockTypes(m_context, blockGroup, m_storage, generateBufferBackedInterfaceNameLengthCase); 4417 } 4418 4419 // .referenced_by 4420 { 4421 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Referenced by shader"); 4422 addChild(blockGroup); 4423 4424 if (m_storage == glu::STORAGE_UNIFORM) 4425 generateReferencedByShaderCaseBlocks(m_context, blockGroup, generateBufferBlockReferencedByShaderSingleBlockContentCases<glu::STORAGE_UNIFORM>); 4426 else if (m_storage == glu::STORAGE_BUFFER) 4427 generateReferencedByShaderCaseBlocks(m_context, blockGroup, generateBufferBlockReferencedByShaderSingleBlockContentCases<glu::STORAGE_BUFFER>); 4428 else 4429 DE_ASSERT(false); 4430 } 4431 } 4432 4433 const char* BufferBackedBlockInterfaceTestGroup::getGroupName (glu::Storage storage) 4434 { 4435 switch (storage) 4436 { 4437 case glu::STORAGE_UNIFORM: return "uniform_block"; 4438 case glu::STORAGE_BUFFER: return "shader_storage_block"; 4439 default: 4440 DE_ASSERT("false"); 4441 return DE_NULL; 4442 } 4443 } 4444 4445 const char* BufferBackedBlockInterfaceTestGroup::getGroupDescription (glu::Storage storage) 4446 { 4447 switch (storage) 4448 { 4449 case glu::STORAGE_UNIFORM: return "Uniform block interface"; 4450 case glu::STORAGE_BUFFER: return "Shader storage block interface"; 4451 default: 4452 DE_ASSERT("false"); 4453 return DE_NULL; 4454 } 4455 } 4456 4457 class AtomicCounterTestGroup : public TestCaseGroup 4458 { 4459 public: 4460 AtomicCounterTestGroup (Context& context); 4461 void init (void); 4462 }; 4463 4464 AtomicCounterTestGroup::AtomicCounterTestGroup (Context& context) 4465 : TestCaseGroup(context, "atomic_counter_buffer", "Atomic counter buffer") 4466 { 4467 } 4468 4469 void AtomicCounterTestGroup::init (void) 4470 { 4471 // .resource_list 4472 addChild(new AtomicCounterResourceListCase(m_context, "resource_list", "Resource list")); 4473 4474 // .active_variables 4475 addChild(new AtomicCounterActiveVariablesCase(m_context, "active_variables", "Active variables")); 4476 4477 // .buffer_binding 4478 addChild(new AtomicCounterBufferBindingCase(m_context, "buffer_binding", "Buffer binding")); 4479 4480 // .buffer_data_size 4481 addChild(new AtomicCounterBufferDataSizeCase(m_context, "buffer_data_size", "Buffer binding")); 4482 4483 // .referenced_by 4484 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_compute", "", (1 << glu::SHADERTYPE_COMPUTE), (1 << glu::SHADERTYPE_COMPUTE))); 4485 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_vertex", "", (1 << glu::SHADERTYPE_VERTEX), (1 << glu::SHADERTYPE_VERTEX))); 4486 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_fragment", "", (1 << glu::SHADERTYPE_FRAGMENT), (1 << glu::SHADERTYPE_FRAGMENT))); 4487 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_vertex_fragment", "", (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT), (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT))); 4488 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_vertex_fragment_only_fragment", "", (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT), (1 << glu::SHADERTYPE_FRAGMENT))); 4489 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_vertex_fragment_only_vertex", "", (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT), (1 << glu::SHADERTYPE_VERTEX))); 4490 } 4491 4492 static void generateProgramInputOutputShaderCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, bool withCompute, bool inputCase, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, deUint32)) 4493 { 4494 // .vertex_fragment 4495 { 4496 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "vertex_fragment", "Vertex and fragment"); 4497 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(false)); 4498 ResourceDefinition::ShaderSet* shaderSetPtr = new ResourceDefinition::ShaderSet(program, glu::GLSL_VERSION_310_ES); 4499 const ResourceDefinition::Node::SharedPtr shaderSet (shaderSetPtr); 4500 4501 shaderSetPtr->setStage(glu::SHADERTYPE_VERTEX, inputCase); 4502 shaderSetPtr->setStage(glu::SHADERTYPE_FRAGMENT, !inputCase); 4503 4504 targetGroup->addChild(blockGroup); 4505 4506 blockContentGenerator(context, shaderSet, blockGroup, (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT)); 4507 } 4508 4509 // .separable_vertex 4510 { 4511 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "separable_vertex", "Separable vertex"); 4512 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true)); 4513 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_VERTEX, glu::GLSL_VERSION_310_ES)); 4514 4515 targetGroup->addChild(blockGroup); 4516 4517 blockContentGenerator(context, shader, blockGroup, (1 << glu::SHADERTYPE_VERTEX)); 4518 } 4519 4520 // .separable_fragment 4521 { 4522 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "separable_fragment", "Separable fragment"); 4523 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true)); 4524 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_FRAGMENT, glu::GLSL_VERSION_310_ES)); 4525 4526 targetGroup->addChild(blockGroup); 4527 4528 blockContentGenerator(context, shader, blockGroup, (1 << glu::SHADERTYPE_FRAGMENT)); 4529 } 4530 4531 // .compute 4532 if (withCompute) 4533 { 4534 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "compute", "Compute"); 4535 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true)); 4536 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 4537 4538 targetGroup->addChild(blockGroup); 4539 4540 blockContentGenerator(context, shader, blockGroup, (1 << glu::SHADERTYPE_COMPUTE)); 4541 } 4542 } 4543 4544 static void generateProgramInputResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask) 4545 { 4546 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4547 const ResourceDefinition::Node::SharedPtr input (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_IN)); 4548 4549 // .empty 4550 targetGroup->addChild(new ResourceListTestCase(context, defaultBlock, PROGRAMINTERFACE_PROGRAM_INPUT, "empty")); 4551 4552 // vertex first stage 4553 if (presentShadersMask & (1 << glu::SHADERTYPE_VERTEX)) 4554 { 4555 // .var 4556 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4)); 4557 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_INPUT)); 4558 } 4559 4560 // fragment first stage 4561 if (presentShadersMask == (1 << glu::SHADERTYPE_FRAGMENT)) 4562 { 4563 // .var 4564 { 4565 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4)); 4566 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_INPUT)); 4567 } 4568 // .var_struct 4569 { 4570 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(input)); 4571 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 4572 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_INPUT)); 4573 } 4574 // .var_array 4575 { 4576 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input)); 4577 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4578 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_INPUT)); 4579 } 4580 } 4581 } 4582 4583 static void generateProgramOutputResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask) 4584 { 4585 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4586 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT)); 4587 4588 // .empty 4589 targetGroup->addChild(new ResourceListTestCase(context, defaultBlock, PROGRAMINTERFACE_PROGRAM_OUTPUT, "empty")); 4590 4591 // vertex last stage 4592 if (presentShadersMask == (1 << glu::SHADERTYPE_VERTEX)) 4593 { 4594 // .var 4595 { 4596 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4)); 4597 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT)); 4598 } 4599 // .var_struct 4600 { 4601 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output)); 4602 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 4603 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT)); 4604 } 4605 // .var_array 4606 { 4607 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output)); 4608 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4609 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT)); 4610 } 4611 } 4612 4613 // fragment last stage 4614 if (presentShadersMask & (1 << glu::SHADERTYPE_FRAGMENT)) 4615 { 4616 // .var 4617 { 4618 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4)); 4619 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT)); 4620 } 4621 // .var_array 4622 { 4623 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output)); 4624 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4625 targetGroup->addChild(new ResourceListTestCase(context, variable, PROGRAMINTERFACE_PROGRAM_OUTPUT)); 4626 } 4627 } 4628 } 4629 4630 template <ProgramResourcePropFlags TargetProp> 4631 static void generateProgramInputBasicBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask) 4632 { 4633 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4634 const ResourceDefinition::Node::SharedPtr input (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_IN)); 4635 4636 // vertex first stage 4637 if (presentShadersMask & (1 << glu::SHADERTYPE_VERTEX)) 4638 { 4639 // .var 4640 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4)); 4641 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, TargetProp), "var")); 4642 } 4643 4644 // fragment first stage 4645 if (presentShadersMask == (1 << glu::SHADERTYPE_FRAGMENT)) 4646 { 4647 // .var 4648 { 4649 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4)); 4650 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, TargetProp), "var")); 4651 } 4652 // .var_struct 4653 { 4654 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(input)); 4655 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 4656 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, TargetProp), "var_struct")); 4657 } 4658 // .var_array 4659 { 4660 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input)); 4661 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4662 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, TargetProp), "var_array")); 4663 } 4664 } 4665 } 4666 4667 template <ProgramResourcePropFlags TargetProp> 4668 static void generateProgramOutputBasicBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask) 4669 { 4670 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4671 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT)); 4672 4673 // vertex last stage 4674 if (presentShadersMask == (1 << glu::SHADERTYPE_VERTEX)) 4675 { 4676 // .var 4677 { 4678 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4)); 4679 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var")); 4680 } 4681 // .var_struct 4682 { 4683 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output)); 4684 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 4685 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var_struct")); 4686 } 4687 // .var_array 4688 { 4689 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output)); 4690 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4691 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var_array")); 4692 } 4693 } 4694 4695 // fragment last stage 4696 if (presentShadersMask & (1 << glu::SHADERTYPE_FRAGMENT)) 4697 { 4698 // .var 4699 { 4700 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4)); 4701 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var")); 4702 } 4703 // .var_array 4704 { 4705 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output)); 4706 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4707 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, TargetProp), "var_array")); 4708 } 4709 } 4710 } 4711 4712 static void generateProgramInputLocationBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask) 4713 { 4714 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4715 const ResourceDefinition::Node::SharedPtr input (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_IN)); 4716 4717 // vertex first stage 4718 if (presentShadersMask & (1 << glu::SHADERTYPE_VERTEX)) 4719 { 4720 // .var 4721 { 4722 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4)); 4723 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var")); 4724 } 4725 // .var_explicit_location 4726 { 4727 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2))); 4728 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4)); 4729 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location")); 4730 } 4731 } 4732 4733 // fragment first stage 4734 if (presentShadersMask == (1 << glu::SHADERTYPE_FRAGMENT)) 4735 { 4736 // .var 4737 { 4738 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4)); 4739 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var")); 4740 } 4741 // .var_explicit_location 4742 { 4743 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2))); 4744 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4)); 4745 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location")); 4746 } 4747 // .var_struct 4748 { 4749 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(input)); 4750 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 4751 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct")); 4752 } 4753 // .var_struct_explicit_location 4754 { 4755 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2))); 4756 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(layout)); 4757 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 4758 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct_explicit_location")); 4759 } 4760 // .var_array 4761 { 4762 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input)); 4763 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4764 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array")); 4765 } 4766 // .var_array_explicit_location 4767 { 4768 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2))); 4769 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout)); 4770 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4771 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location")); 4772 } 4773 } 4774 } 4775 4776 static void generateProgramOutputLocationBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask) 4777 { 4778 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4779 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT)); 4780 4781 // vertex last stage 4782 if (presentShadersMask == (1 << glu::SHADERTYPE_VERTEX)) 4783 { 4784 // .var 4785 { 4786 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4)); 4787 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var")); 4788 } 4789 // .var_explicit_location 4790 { 4791 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2))); 4792 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4)); 4793 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location")); 4794 } 4795 // .var_struct 4796 { 4797 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output)); 4798 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 4799 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct")); 4800 } 4801 // .var_struct_explicit_location 4802 { 4803 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2))); 4804 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(layout)); 4805 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 4806 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct_explicit_location")); 4807 } 4808 // .var_array 4809 { 4810 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output)); 4811 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4812 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array")); 4813 } 4814 // .var_array_explicit_location 4815 { 4816 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2))); 4817 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout)); 4818 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4819 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location")); 4820 } 4821 } 4822 4823 // fragment last stage 4824 if (presentShadersMask & (1 << glu::SHADERTYPE_FRAGMENT)) 4825 { 4826 // .var 4827 { 4828 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4)); 4829 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var")); 4830 } 4831 // .var_explicit_location 4832 { 4833 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2))); 4834 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4)); 4835 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location")); 4836 } 4837 // .var_array 4838 { 4839 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output)); 4840 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4841 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array")); 4842 } 4843 // .var_array_explicit_location 4844 { 4845 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(1))); 4846 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout)); 4847 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 4848 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location")); 4849 } 4850 } 4851 } 4852 4853 static void generateProgramInputOutputReferencedByCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage) 4854 { 4855 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_vertex_fragment", "", storage, ProgramInputOutputReferencedByCase::CASE_VERTEX_FRAGMENT)); 4856 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_vertex", "", storage, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_VERTEX)); 4857 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_fragment", "", storage, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_FRAGMENT)); 4858 } 4859 4860 static void generateProgramInputTypeBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup) 4861 { 4862 static const glu::DataType variableTypes[] = 4863 { 4864 glu::TYPE_FLOAT, 4865 glu::TYPE_INT, 4866 glu::TYPE_UINT, 4867 4868 glu::TYPE_FLOAT_VEC2, 4869 glu::TYPE_FLOAT_VEC3, 4870 glu::TYPE_FLOAT_VEC4, 4871 4872 glu::TYPE_INT_VEC2, 4873 glu::TYPE_INT_VEC3, 4874 glu::TYPE_INT_VEC4, 4875 4876 glu::TYPE_UINT_VEC2, 4877 glu::TYPE_UINT_VEC3, 4878 glu::TYPE_UINT_VEC4, 4879 4880 glu::TYPE_FLOAT_MAT2, 4881 glu::TYPE_FLOAT_MAT2X3, 4882 glu::TYPE_FLOAT_MAT2X4, 4883 glu::TYPE_FLOAT_MAT3X2, 4884 glu::TYPE_FLOAT_MAT3, 4885 glu::TYPE_FLOAT_MAT3X4, 4886 glu::TYPE_FLOAT_MAT4X2, 4887 glu::TYPE_FLOAT_MAT4X3, 4888 glu::TYPE_FLOAT_MAT4, 4889 }; 4890 4891 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx) 4892 { 4893 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx])); 4894 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_TYPE))); 4895 } 4896 } 4897 4898 static void generateProgramInputTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask) 4899 { 4900 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4901 const ResourceDefinition::Node::SharedPtr input (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_IN)); 4902 4903 // vertex first stage 4904 if (presentShadersMask & (1 << glu::SHADERTYPE_VERTEX)) 4905 { 4906 // Only basic types (and no booleans) 4907 generateProgramInputTypeBasicTypeCases(context, input, targetGroup); 4908 } 4909 4910 // fragment first stage 4911 if (presentShadersMask == (1 << glu::SHADERTYPE_FRAGMENT)) 4912 { 4913 const ResourceDefinition::Node::SharedPtr flatShading(new ResourceDefinition::InterpolationQualifier(input, glu::INTERPOLATION_FLAT)); 4914 4915 // Only basic types, arrays of basic types, struct of basic types (and no booleans) 4916 { 4917 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types"); 4918 targetGroup->addChild(blockGroup); 4919 generateProgramInputTypeBasicTypeCases(context, flatShading, blockGroup); 4920 } 4921 { 4922 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(flatShading)); 4923 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Array types"); 4924 4925 targetGroup->addChild(blockGroup); 4926 generateProgramInputTypeBasicTypeCases(context, arrayElement, blockGroup); 4927 } 4928 { 4929 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(flatShading)); 4930 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "struct", "Struct types"); 4931 4932 targetGroup->addChild(blockGroup); 4933 generateProgramInputTypeBasicTypeCases(context, structMember, blockGroup); 4934 } 4935 } 4936 } 4937 4938 static void generateProgramOutputTypeBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool addMatrixCases) 4939 { 4940 static const glu::DataType variableTypes[] = 4941 { 4942 glu::TYPE_FLOAT, 4943 glu::TYPE_INT, 4944 glu::TYPE_UINT, 4945 4946 glu::TYPE_FLOAT_VEC2, 4947 glu::TYPE_FLOAT_VEC3, 4948 glu::TYPE_FLOAT_VEC4, 4949 4950 glu::TYPE_INT_VEC2, 4951 glu::TYPE_INT_VEC3, 4952 glu::TYPE_INT_VEC4, 4953 4954 glu::TYPE_UINT_VEC2, 4955 glu::TYPE_UINT_VEC3, 4956 glu::TYPE_UINT_VEC4, 4957 4958 glu::TYPE_FLOAT_MAT2, 4959 glu::TYPE_FLOAT_MAT2X3, 4960 glu::TYPE_FLOAT_MAT2X4, 4961 glu::TYPE_FLOAT_MAT3X2, 4962 glu::TYPE_FLOAT_MAT3, 4963 glu::TYPE_FLOAT_MAT3X4, 4964 glu::TYPE_FLOAT_MAT4X2, 4965 glu::TYPE_FLOAT_MAT4X3, 4966 glu::TYPE_FLOAT_MAT4, 4967 }; 4968 4969 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx) 4970 { 4971 if (addMatrixCases || !glu::isDataTypeMatrix(variableTypes[ndx])) 4972 { 4973 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx])); 4974 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_TYPE))); 4975 } 4976 } 4977 } 4978 4979 static void generateProgramOutputTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask) 4980 { 4981 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 4982 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT)); 4983 4984 // vertex last stage 4985 if (presentShadersMask == (1 << glu::SHADERTYPE_VERTEX)) 4986 { 4987 const ResourceDefinition::Node::SharedPtr flatShading(new ResourceDefinition::InterpolationQualifier(output, glu::INTERPOLATION_FLAT)); 4988 4989 // Only basic types, arrays of basic types, struct of basic types (and no booleans) 4990 { 4991 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types"); 4992 targetGroup->addChild(blockGroup); 4993 generateProgramOutputTypeBasicTypeCases(context, flatShading, blockGroup, true); 4994 } 4995 { 4996 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(flatShading)); 4997 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Array types"); 4998 4999 targetGroup->addChild(blockGroup); 5000 generateProgramOutputTypeBasicTypeCases(context, arrayElement, blockGroup, true); 5001 } 5002 { 5003 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(flatShading)); 5004 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "struct", "Struct types"); 5005 5006 targetGroup->addChild(blockGroup); 5007 generateProgramOutputTypeBasicTypeCases(context, structMember, blockGroup, true); 5008 } 5009 } 5010 5011 // fragment last stage 5012 if (presentShadersMask & (1 << glu::SHADERTYPE_FRAGMENT)) 5013 { 5014 // only basic type and basic type array (and no booleans or matrices) 5015 { 5016 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types"); 5017 targetGroup->addChild(blockGroup); 5018 generateProgramOutputTypeBasicTypeCases(context, output, blockGroup, false); 5019 } 5020 { 5021 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(output)); 5022 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Array types"); 5023 5024 targetGroup->addChild(blockGroup); 5025 generateProgramOutputTypeBasicTypeCases(context, arrayElement, blockGroup, false); 5026 } 5027 } 5028 } 5029 5030 class ProgramInputTestGroup : public TestCaseGroup 5031 { 5032 public: 5033 ProgramInputTestGroup (Context& context); 5034 void init (void); 5035 }; 5036 5037 ProgramInputTestGroup::ProgramInputTestGroup (Context& context) 5038 : TestCaseGroup(context, "program_input", "Program input") 5039 { 5040 } 5041 5042 void ProgramInputTestGroup::init (void) 5043 { 5044 // .resource_list 5045 { 5046 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list"); 5047 addChild(blockGroup); 5048 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, true, true, generateProgramInputResourceListBlockContents); 5049 } 5050 5051 // .array_size 5052 { 5053 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Array size"); 5054 addChild(blockGroup); 5055 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, true, generateProgramInputBasicBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>); 5056 } 5057 5058 // .location 5059 { 5060 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Location"); 5061 addChild(blockGroup); 5062 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, true, generateProgramInputLocationBlockContents); 5063 } 5064 5065 // .name_length 5066 { 5067 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length"); 5068 addChild(blockGroup); 5069 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, true, generateProgramInputBasicBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>); 5070 } 5071 5072 // .referenced_by 5073 { 5074 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Reference by shader"); 5075 addChild(blockGroup); 5076 generateProgramInputOutputReferencedByCases(m_context, blockGroup, glu::STORAGE_IN); 5077 } 5078 5079 // .type 5080 { 5081 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Type"); 5082 addChild(blockGroup); 5083 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, true, true, generateProgramInputTypeBlockContents); 5084 } 5085 } 5086 5087 class ProgramOutputTestGroup : public TestCaseGroup 5088 { 5089 public: 5090 ProgramOutputTestGroup (Context& context); 5091 void init (void); 5092 }; 5093 5094 ProgramOutputTestGroup::ProgramOutputTestGroup (Context& context) 5095 : TestCaseGroup(context, "program_output", "Program output") 5096 { 5097 } 5098 5099 void ProgramOutputTestGroup::init (void) 5100 { 5101 // .resource_list 5102 { 5103 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list"); 5104 addChild(blockGroup); 5105 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, true, false, generateProgramOutputResourceListBlockContents); 5106 } 5107 5108 // .array_size 5109 { 5110 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Array size"); 5111 addChild(blockGroup); 5112 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, false, generateProgramOutputBasicBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>); 5113 } 5114 5115 // .location 5116 { 5117 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Location"); 5118 addChild(blockGroup); 5119 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, false, generateProgramOutputLocationBlockContents); 5120 } 5121 5122 // .name_length 5123 { 5124 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length"); 5125 addChild(blockGroup); 5126 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, false, false, generateProgramOutputBasicBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>); 5127 } 5128 5129 // .referenced_by 5130 { 5131 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Reference by shader"); 5132 addChild(blockGroup); 5133 generateProgramInputOutputReferencedByCases(m_context, blockGroup, glu::STORAGE_OUT); 5134 } 5135 5136 // .type 5137 { 5138 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Type"); 5139 addChild(blockGroup); 5140 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, true, false, generateProgramOutputTypeBlockContents); 5141 } 5142 } 5143 5144 static void generateTransformFeedbackShaderCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*)) 5145 { 5146 // .vertex_fragment 5147 { 5148 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "vertex_fragment", "Vertex and fragment"); 5149 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(false)); 5150 ResourceDefinition::ShaderSet* shaderSetPtr = new ResourceDefinition::ShaderSet(program, glu::GLSL_VERSION_310_ES); 5151 const ResourceDefinition::Node::SharedPtr shaderSet (shaderSetPtr); 5152 5153 shaderSetPtr->setStage(glu::SHADERTYPE_VERTEX, true); 5154 shaderSetPtr->setStage(glu::SHADERTYPE_FRAGMENT, false); 5155 5156 targetGroup->addChild(blockGroup); 5157 5158 blockContentGenerator(context, shaderSet, blockGroup); 5159 } 5160 5161 // .separable_vertex 5162 { 5163 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "separable_vertex", "Separable vertex"); 5164 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true)); 5165 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_VERTEX, glu::GLSL_VERSION_310_ES)); 5166 5167 targetGroup->addChild(blockGroup); 5168 5169 blockContentGenerator(context, shader, blockGroup); 5170 } 5171 } 5172 5173 static void generateTransformFeedbackResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup) 5174 { 5175 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 5176 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT)); 5177 5178 // .builtin_gl_position 5179 { 5180 const ResourceDefinition::Node::SharedPtr xfbTarget(new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position")); 5181 targetGroup->addChild(new FeedbackResourceListTestCase(context, xfbTarget, "builtin_gl_position")); 5182 } 5183 // .default_block_basic_type 5184 { 5185 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output)); 5186 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4)); 5187 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_basic_type")); 5188 } 5189 // .default_block_struct 5190 { 5191 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output)); 5192 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(xfbTarget)); 5193 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 5194 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_struct")); 5195 } 5196 // .default_block_struct_member 5197 { 5198 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output)); 5199 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(structMbr)); 5200 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4)); 5201 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_struct_member")); 5202 } 5203 // .default_block_array 5204 { 5205 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output)); 5206 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(xfbTarget)); 5207 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 5208 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_array")); 5209 } 5210 // .default_block_array_element 5211 { 5212 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output)); 5213 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(arrayElem)); 5214 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4)); 5215 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_array_element")); 5216 } 5217 } 5218 5219 template <ProgramResourcePropFlags TargetProp> 5220 static void generateTransformFeedbackVariableBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup) 5221 { 5222 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 5223 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT)); 5224 5225 // .builtin_gl_position 5226 { 5227 const ResourceDefinition::Node::SharedPtr xfbTarget(new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position")); 5228 targetGroup->addChild(new ResourceTestCase(context, xfbTarget, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "builtin_gl_position")); 5229 } 5230 // .default_block_basic_type 5231 { 5232 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output)); 5233 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4)); 5234 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_basic_type")); 5235 } 5236 // .default_block_struct 5237 { 5238 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output)); 5239 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(xfbTarget)); 5240 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4)); 5241 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_struct")); 5242 } 5243 // .default_block_struct_member 5244 { 5245 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output)); 5246 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(structMbr)); 5247 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4)); 5248 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_struct_member")); 5249 } 5250 // .default_block_array 5251 { 5252 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output)); 5253 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(xfbTarget)); 5254 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4)); 5255 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_array")); 5256 } 5257 // .default_block_array_element 5258 { 5259 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output)); 5260 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(arrayElem)); 5261 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4)); 5262 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_array_element")); 5263 } 5264 } 5265 5266 static void generateTransformFeedbackVariableBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup) 5267 { 5268 static const glu::DataType variableTypes[] = 5269 { 5270 glu::TYPE_FLOAT, 5271 glu::TYPE_INT, 5272 glu::TYPE_UINT, 5273 5274 glu::TYPE_FLOAT_VEC2, 5275 glu::TYPE_FLOAT_VEC3, 5276 glu::TYPE_FLOAT_VEC4, 5277 5278 glu::TYPE_INT_VEC2, 5279 glu::TYPE_INT_VEC3, 5280 glu::TYPE_INT_VEC4, 5281 5282 glu::TYPE_UINT_VEC2, 5283 glu::TYPE_UINT_VEC3, 5284 glu::TYPE_UINT_VEC4, 5285 5286 glu::TYPE_FLOAT_MAT2, 5287 glu::TYPE_FLOAT_MAT2X3, 5288 glu::TYPE_FLOAT_MAT2X4, 5289 glu::TYPE_FLOAT_MAT3X2, 5290 glu::TYPE_FLOAT_MAT3, 5291 glu::TYPE_FLOAT_MAT3X4, 5292 glu::TYPE_FLOAT_MAT4X2, 5293 glu::TYPE_FLOAT_MAT4X3, 5294 glu::TYPE_FLOAT_MAT4, 5295 }; 5296 5297 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx) 5298 { 5299 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx])); 5300 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, PROGRAMRESOURCEPROP_TYPE))); 5301 } 5302 } 5303 5304 static void generateTransformFeedbackVariableTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup) 5305 { 5306 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 5307 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT)); 5308 const ResourceDefinition::Node::SharedPtr flatShading (new ResourceDefinition::InterpolationQualifier(output, glu::INTERPOLATION_FLAT)); 5309 5310 // Only builtins, basic types, arrays of basic types, struct of basic types (and no booleans) 5311 { 5312 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position")); 5313 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "builtin", "Built-in outputs"); 5314 5315 targetGroup->addChild(blockGroup); 5316 blockGroup->addChild(new ResourceTestCase(context, xfbTarget, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, PROGRAMRESOURCEPROP_TYPE), "gl_position")); 5317 } 5318 { 5319 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(flatShading)); 5320 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types"); 5321 5322 targetGroup->addChild(blockGroup); 5323 generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup); 5324 } 5325 { 5326 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(flatShading)); 5327 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(arrayElement)); 5328 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Array types"); 5329 5330 targetGroup->addChild(blockGroup); 5331 generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup); 5332 } 5333 { 5334 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(flatShading)); 5335 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(xfbTarget)); 5336 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "whole_array", "Whole array"); 5337 5338 targetGroup->addChild(blockGroup); 5339 generateTransformFeedbackVariableBasicTypeCases(context, arrayElement, blockGroup); 5340 } 5341 { 5342 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(flatShading)); 5343 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(structMember)); 5344 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "struct", "Struct types"); 5345 5346 targetGroup->addChild(blockGroup); 5347 generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup); 5348 } 5349 } 5350 5351 class TransformFeedbackVaryingTestGroup : public TestCaseGroup 5352 { 5353 public: 5354 TransformFeedbackVaryingTestGroup (Context& context); 5355 void init (void); 5356 }; 5357 5358 TransformFeedbackVaryingTestGroup::TransformFeedbackVaryingTestGroup (Context& context) 5359 : TestCaseGroup(context, "transform_feedback_varying", "Transform feedback varyings") 5360 { 5361 } 5362 5363 void TransformFeedbackVaryingTestGroup::init (void) 5364 { 5365 // .resource_list 5366 { 5367 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "resource_list", "Resource list"); 5368 addChild(blockGroup); 5369 generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, generateTransformFeedbackResourceListBlockContents); 5370 } 5371 5372 // .array_size 5373 { 5374 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_size", "Array size"); 5375 addChild(blockGroup); 5376 generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, generateTransformFeedbackVariableBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>); 5377 } 5378 5379 // .name_length 5380 { 5381 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "name_length", "Name length"); 5382 addChild(blockGroup); 5383 generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, generateTransformFeedbackVariableBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>); 5384 } 5385 5386 // .type 5387 { 5388 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "type", "Type"); 5389 addChild(blockGroup); 5390 generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, generateTransformFeedbackVariableTypeBlockContents); 5391 } 5392 } 5393 5394 static void generateBufferVariableBufferCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*)) 5395 { 5396 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 5397 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 5398 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 5399 const ResourceDefinition::Node::SharedPtr bufferStorage (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER)); 5400 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(bufferStorage, glu::Layout(-1, 0))); 5401 5402 // .named_block 5403 { 5404 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, true)); 5405 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "named_block", "Named block"); 5406 5407 targetGroup->addChild(blockGroup); 5408 5409 blockContentGenerator(context, buffer, blockGroup); 5410 } 5411 5412 // .unnamed_block 5413 { 5414 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, false)); 5415 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unnamed_block", "Unnamed block"); 5416 5417 targetGroup->addChild(blockGroup); 5418 5419 blockContentGenerator(context, buffer, blockGroup); 5420 } 5421 5422 // .block_array 5423 { 5424 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding)); 5425 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 5426 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "block_array", "Block array"); 5427 5428 targetGroup->addChild(blockGroup); 5429 5430 blockContentGenerator(context, buffer, blockGroup); 5431 } 5432 } 5433 5434 static void generateBufferVariableResourceListBlockContentsProxy (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 5435 { 5436 generateBufferBackedResourceListBlockContentCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, 4); 5437 } 5438 5439 static void generateBufferVariableArraySizeSubCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramResourcePropFlags targetProp, bool sizedArray, bool extendedCases) 5440 { 5441 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp); 5442 tcu::TestCaseGroup* aggregateGroup; 5443 5444 // .types 5445 if (extendedCases) 5446 { 5447 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types"); 5448 targetGroup->addChild(blockGroup); 5449 5450 generateVariableCases(context, parentStructure, blockGroup, queryTarget, (sizedArray) ? (2) : (1), false); 5451 } 5452 5453 // .aggregates 5454 if (extendedCases) 5455 { 5456 aggregateGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types"); 5457 targetGroup->addChild(aggregateGroup); 5458 } 5459 else 5460 aggregateGroup = targetGroup; 5461 5462 // .float_* 5463 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_FLOAT, (extendedCases && sizedArray) ? (2) : (1), !extendedCases); 5464 5465 // .bool_* 5466 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_BOOL, (extendedCases && sizedArray) ? (1) : (0), !extendedCases); 5467 5468 // .bvec3_* 5469 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_BOOL_VEC3, (extendedCases && sizedArray) ? (2) : (1), !extendedCases); 5470 5471 // .vec4_* 5472 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_FLOAT_VEC4, (extendedCases && sizedArray) ? (2) : (1), !extendedCases); 5473 5474 // .ivec2_* 5475 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_INT_VEC2, (extendedCases && sizedArray) ? (2) : (1), !extendedCases); 5476 } 5477 5478 template <ProgramResourcePropFlags TargetProp> 5479 static void generateBufferVariableArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup) 5480 { 5481 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp); 5482 const bool namedNonArrayBlock = static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named && parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT; 5483 5484 // .non_array 5485 if (namedNonArrayBlock) 5486 { 5487 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "non_array", "Non-array target"); 5488 targetGroup->addChild(blockGroup); 5489 5490 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 1, false); 5491 } 5492 5493 // .sized 5494 { 5495 const ResourceDefinition::Node::SharedPtr sized (new ResourceDefinition::ArrayElement(parentStructure)); 5496 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "sized", "Sized target"); 5497 targetGroup->addChild(blockGroup); 5498 5499 generateBufferVariableArraySizeSubCases(context, sized, blockGroup, TargetProp, true, namedNonArrayBlock); 5500 } 5501 5502 // .unsized 5503 { 5504 const ResourceDefinition::Node::SharedPtr unsized (new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY)); 5505 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unsized", "Unsized target"); 5506 targetGroup->addChild(blockGroup); 5507 5508 generateBufferVariableArraySizeSubCases(context, unsized, blockGroup, TargetProp, false, namedNonArrayBlock); 5509 } 5510 } 5511 5512 static void generateBufferVariableBlockIndexCases (Context& context, tcu::TestCaseGroup* const targetGroup) 5513 { 5514 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 5515 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 5516 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 5517 const ResourceDefinition::Node::SharedPtr bufferStorage (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER)); 5518 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(bufferStorage, glu::Layout(-1, 0))); 5519 5520 // .named_block 5521 { 5522 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, true)); 5523 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4)); 5524 5525 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "named_block")); 5526 } 5527 5528 // .unnamed_block 5529 { 5530 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, false)); 5531 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4)); 5532 5533 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "unnamed_block")); 5534 } 5535 5536 // .block_array 5537 { 5538 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding)); 5539 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 5540 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4)); 5541 5542 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "block_array")); 5543 } 5544 } 5545 5546 static void generateBufferVariableMatrixCaseBlocks (Context& context, tcu::TestCaseGroup* const targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, bool)) 5547 { 5548 static const struct 5549 { 5550 const char* name; 5551 const char* description; 5552 bool namedBlock; 5553 bool extendedBasicTypeCases; 5554 glu::MatrixOrder order; 5555 } children[] = 5556 { 5557 { "named_block", "Named uniform block", true, true, glu::MATRIXORDER_LAST }, 5558 { "named_block_row_major", "Named uniform block", true, false, glu::MATRIXORDER_ROW_MAJOR }, 5559 { "named_block_col_major", "Named uniform block", true, false, glu::MATRIXORDER_COLUMN_MAJOR }, 5560 { "unnamed_block", "Unnamed uniform block", false, false, glu::MATRIXORDER_LAST }, 5561 { "unnamed_block_row_major", "Unnamed uniform block", false, false, glu::MATRIXORDER_ROW_MAJOR }, 5562 { "unnamed_block_col_major", "Unnamed uniform block", false, false, glu::MATRIXORDER_COLUMN_MAJOR }, 5563 }; 5564 5565 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 5566 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 5567 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 5568 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER)); 5569 5570 for (int childNdx = 0; childNdx < (int)DE_LENGTH_OF_ARRAY(children); ++childNdx) 5571 { 5572 ResourceDefinition::Node::SharedPtr parentStructure = buffer; 5573 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, children[childNdx].name, children[childNdx].description); 5574 5575 targetGroup->addChild(blockGroup); 5576 5577 if (children[childNdx].order != glu::MATRIXORDER_LAST) 5578 { 5579 glu::Layout layout; 5580 layout.matrixOrder = children[childNdx].order; 5581 parentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(parentStructure, layout)); 5582 } 5583 5584 parentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(parentStructure, children[childNdx].namedBlock)); 5585 5586 blockContentGenerator(context, parentStructure, blockGroup, children[childNdx].extendedBasicTypeCases); 5587 } 5588 } 5589 5590 static void generateBufferVariableMatrixVariableBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, ProgramResourcePropFlags targetProp) 5591 { 5592 // all matrix types and some non-matrix 5593 5594 static const glu::DataType variableTypes[] = 5595 { 5596 glu::TYPE_FLOAT, 5597 glu::TYPE_INT_VEC3, 5598 glu::TYPE_FLOAT_MAT2, 5599 glu::TYPE_FLOAT_MAT2X3, 5600 glu::TYPE_FLOAT_MAT2X4, 5601 glu::TYPE_FLOAT_MAT3X2, 5602 glu::TYPE_FLOAT_MAT3, 5603 glu::TYPE_FLOAT_MAT3X4, 5604 glu::TYPE_FLOAT_MAT4X2, 5605 glu::TYPE_FLOAT_MAT4X3, 5606 glu::TYPE_FLOAT_MAT4, 5607 }; 5608 5609 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx) 5610 { 5611 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx])); 5612 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp))); 5613 } 5614 } 5615 5616 static void generateBufferVariableMatrixVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, ProgramResourcePropFlags targetProp) 5617 { 5618 // Basic aggregates 5619 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp, glu::TYPE_FLOAT_MAT3X2, "", 2); 5620 5621 // Unsized array 5622 { 5623 const ResourceDefinition::Node::SharedPtr unsized (new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY)); 5624 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(unsized, glu::TYPE_FLOAT_MAT3X2)); 5625 5626 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp), "var_unsized_array")); 5627 } 5628 } 5629 5630 template <ProgramResourcePropFlags TargetProp> 5631 static void generateBufferVariableMatrixCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool extendedTypeCases) 5632 { 5633 // .types 5634 if (extendedTypeCases) 5635 { 5636 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "types", "Types"); 5637 targetGroup->addChild(blockGroup); 5638 generateBufferVariableMatrixVariableBasicTypeCases(context, parentStructure, blockGroup, TargetProp); 5639 } 5640 5641 // .no_qualifier 5642 { 5643 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "no_qualifier", "No qualifier"); 5644 targetGroup->addChild(blockGroup); 5645 generateBufferVariableMatrixVariableCases(context, parentStructure, blockGroup, TargetProp); 5646 } 5647 5648 // .column_major 5649 { 5650 const ResourceDefinition::Node::SharedPtr matrixOrder(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, -1, glu::FORMATLAYOUT_LAST, glu::MATRIXORDER_COLUMN_MAJOR))); 5651 5652 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "column_major", "Column major qualifier"); 5653 targetGroup->addChild(blockGroup); 5654 generateBufferVariableMatrixVariableCases(context, matrixOrder, blockGroup, TargetProp); 5655 } 5656 5657 // .row_major 5658 { 5659 const ResourceDefinition::Node::SharedPtr matrixOrder(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, -1, glu::FORMATLAYOUT_LAST, glu::MATRIXORDER_ROW_MAJOR))); 5660 5661 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "row_major", "Row major qualifier"); 5662 targetGroup->addChild(blockGroup); 5663 generateBufferVariableMatrixVariableCases(context, matrixOrder, blockGroup, TargetProp); 5664 } 5665 } 5666 5667 static void generateBufferVariableNameLengthCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup) 5668 { 5669 // .sized 5670 { 5671 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "sized", "Sized target"); 5672 targetGroup->addChild(blockGroup); 5673 5674 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 3); 5675 } 5676 5677 // .unsized 5678 { 5679 const ResourceDefinition::Node::SharedPtr unsized (new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY)); 5680 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unsized", "Unsized target"); 5681 targetGroup->addChild(blockGroup); 5682 5683 generateBufferBackedVariableAggregateTypeCases(context, unsized, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 2); 5684 } 5685 } 5686 5687 static void generateBufferVariableOffsetCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup) 5688 { 5689 // .sized 5690 { 5691 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "sized", "Sized target"); 5692 targetGroup->addChild(blockGroup); 5693 5694 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_OFFSET, glu::TYPE_FLOAT, "", 3); 5695 } 5696 5697 // .unsized 5698 { 5699 const ResourceDefinition::Node::SharedPtr unsized (new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY)); 5700 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unsized", "Unsized target"); 5701 targetGroup->addChild(blockGroup); 5702 5703 generateBufferBackedVariableAggregateTypeCases(context, unsized, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_OFFSET, glu::TYPE_FLOAT, "", 2); 5704 } 5705 } 5706 5707 static void generateBufferVariableReferencedByBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel) 5708 { 5709 DE_UNREF(expandLevel); 5710 5711 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER); 5712 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure)); 5713 const ResourceDefinition::Node::SharedPtr storage (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER)); 5714 const bool singleShaderCase = parentStructure->getType() == ResourceDefinition::Node::TYPE_SHADER; 5715 5716 // .named_block 5717 { 5718 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(storage, true)); 5719 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "named_block", "Named block"); 5720 5721 targetGroup->addChild(blockGroup); 5722 5723 generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, singleShaderCase); 5724 } 5725 5726 // .unnamed_block 5727 { 5728 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(storage, false)); 5729 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unnamed_block", "Unnamed block"); 5730 5731 targetGroup->addChild(blockGroup); 5732 5733 generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, false); 5734 } 5735 5736 // .block_array 5737 { 5738 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(storage)); 5739 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(arrayElement, true)); 5740 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "block_array", "Block array"); 5741 5742 targetGroup->addChild(blockGroup); 5743 5744 generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, false); 5745 } 5746 } 5747 5748 template <ProgramResourcePropFlags TargetProp> 5749 static void generateBufferVariableTopLevelCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup) 5750 { 5751 // basic and aggregate types 5752 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp, glu::TYPE_FLOAT_VEC4, "", 3); 5753 5754 // basic and aggregate types in an unsized array 5755 { 5756 const ResourceDefinition::Node::SharedPtr unsized(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY)); 5757 5758 generateBufferBackedVariableAggregateTypeCases(context, unsized, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp, glu::TYPE_FLOAT_VEC4, "_unsized_array", 2); 5759 } 5760 } 5761 5762 static void generateBufferVariableTypeBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel) 5763 { 5764 static const struct 5765 { 5766 int level; 5767 glu::DataType dataType; 5768 } variableTypes[] = 5769 { 5770 { 0, glu::TYPE_FLOAT }, 5771 { 1, glu::TYPE_INT }, 5772 { 1, glu::TYPE_UINT }, 5773 { 1, glu::TYPE_BOOL }, 5774 5775 { 3, glu::TYPE_FLOAT_VEC2 }, 5776 { 1, glu::TYPE_FLOAT_VEC3 }, 5777 { 1, glu::TYPE_FLOAT_VEC4 }, 5778 5779 { 3, glu::TYPE_INT_VEC2 }, 5780 { 2, glu::TYPE_INT_VEC3 }, 5781 { 3, glu::TYPE_INT_VEC4 }, 5782 5783 { 3, glu::TYPE_UINT_VEC2 }, 5784 { 2, glu::TYPE_UINT_VEC3 }, 5785 { 3, glu::TYPE_UINT_VEC4 }, 5786 5787 { 3, glu::TYPE_BOOL_VEC2 }, 5788 { 2, glu::TYPE_BOOL_VEC3 }, 5789 { 3, glu::TYPE_BOOL_VEC4 }, 5790 5791 { 2, glu::TYPE_FLOAT_MAT2 }, 5792 { 3, glu::TYPE_FLOAT_MAT2X3 }, 5793 { 3, glu::TYPE_FLOAT_MAT2X4 }, 5794 { 2, glu::TYPE_FLOAT_MAT3X2 }, 5795 { 2, glu::TYPE_FLOAT_MAT3 }, 5796 { 3, glu::TYPE_FLOAT_MAT3X4 }, 5797 { 2, glu::TYPE_FLOAT_MAT4X2 }, 5798 { 3, glu::TYPE_FLOAT_MAT4X3 }, 5799 { 2, glu::TYPE_FLOAT_MAT4 }, 5800 }; 5801 5802 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx) 5803 { 5804 if (variableTypes[ndx].level <= expandLevel) 5805 { 5806 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType)); 5807 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_TYPE))); 5808 } 5809 } 5810 } 5811 5812 static void generateBufferVariableTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int depth = 3) 5813 { 5814 // .basic_type 5815 if (depth > 0) 5816 { 5817 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic type"); 5818 targetGroup->addChild(blockGroup); 5819 generateBufferVariableTypeBasicTypeCases(context, parentStructure, blockGroup, depth); 5820 } 5821 else 5822 { 5823 // flatten bottom-level 5824 generateBufferVariableTypeBasicTypeCases(context, parentStructure, targetGroup, depth); 5825 } 5826 5827 // .array 5828 if (depth > 0) 5829 { 5830 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure)); 5831 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Arrays"); 5832 5833 targetGroup->addChild(blockGroup); 5834 generateBufferVariableTypeCases(context, arrayElement, blockGroup, depth-1); 5835 } 5836 5837 // .struct 5838 if (depth > 0) 5839 { 5840 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure)); 5841 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "struct", "Structs"); 5842 5843 targetGroup->addChild(blockGroup); 5844 generateBufferVariableTypeCases(context, structMember, blockGroup, depth-1); 5845 } 5846 } 5847 5848 static void generateBufferVariableTypeBlock (Context& context, tcu::TestCaseGroup* targetGroup) 5849 { 5850 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program()); 5851 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glu::GLSL_VERSION_310_ES)); 5852 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 5853 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER)); 5854 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(buffer, true)); 5855 5856 generateBufferVariableTypeCases(context, block, targetGroup); 5857 } 5858 5859 static void generateBufferVariableRandomCase (Context& context, tcu::TestCaseGroup* const targetGroup, int index) 5860 { 5861 de::Random rnd (index * 0x12345); 5862 const ResourceDefinition::Node::SharedPtr shader = generateRandomShaderSet(rnd); 5863 const glu::DataType type = generateRandomDataType(rnd, true); 5864 const glu::Layout layout = generateRandomVariableLayout(rnd, type, true); 5865 const bool namedBlock = rnd.getBool(); 5866 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader)); 5867 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER)); 5868 ResourceDefinition::Node::SharedPtr currentStructure (new ResourceDefinition::LayoutQualifier(buffer, generateRandomBufferBlockLayout(rnd))); 5869 5870 if (namedBlock && rnd.getBool()) 5871 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure)); 5872 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(currentStructure, namedBlock)); 5873 5874 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, layout)); 5875 currentStructure = generateRandomVariableDefinition(rnd, currentStructure, type, layout, true); 5876 5877 targetGroup->addChild(new ResourceTestCase(context, currentStructure, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BUFFER_VARIABLE_MASK), de::toString(index).c_str())); 5878 } 5879 5880 static void generateBufferVariableRandomCases (Context& context, tcu::TestCaseGroup* const targetGroup) 5881 { 5882 const int numCases = 40; 5883 5884 for (int ndx = 0; ndx < numCases; ++ndx) 5885 generateBufferVariableRandomCase(context, targetGroup, ndx); 5886 } 5887 5888 class BufferVariableTestGroup : public TestCaseGroup 5889 { 5890 public: 5891 BufferVariableTestGroup (Context& context); 5892 void init (void); 5893 }; 5894 5895 BufferVariableTestGroup::BufferVariableTestGroup (Context& context) 5896 : TestCaseGroup(context, "buffer_variable", "Buffer variable") 5897 { 5898 } 5899 5900 void BufferVariableTestGroup::init (void) 5901 { 5902 // .resource_list 5903 { 5904 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "resource_list", "Resource list"); 5905 addChild(blockGroup); 5906 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableResourceListBlockContentsProxy); 5907 } 5908 5909 // .array_size 5910 { 5911 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_size", "Array size"); 5912 addChild(blockGroup); 5913 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableArrayCases<PROGRAMRESOURCEPROP_ARRAY_SIZE>); 5914 } 5915 5916 // .array_stride 5917 { 5918 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_stride", "Array stride"); 5919 addChild(blockGroup); 5920 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableArrayCases<PROGRAMRESOURCEPROP_ARRAY_STRIDE>); 5921 } 5922 5923 // .block_index 5924 { 5925 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "block_index", "Block index"); 5926 addChild(blockGroup); 5927 generateBufferVariableBlockIndexCases(m_context, blockGroup); 5928 } 5929 5930 // .is_row_major 5931 { 5932 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "is_row_major", "Is row major"); 5933 addChild(blockGroup); 5934 generateBufferVariableMatrixCaseBlocks(m_context, blockGroup, generateBufferVariableMatrixCases<PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR>); 5935 } 5936 5937 // .matrix_stride 5938 { 5939 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "matrix_stride", "Matrix stride"); 5940 addChild(blockGroup); 5941 generateBufferVariableMatrixCaseBlocks(m_context, blockGroup, generateBufferVariableMatrixCases<PROGRAMRESOURCEPROP_MATRIX_STRIDE>); 5942 } 5943 5944 // .name_length 5945 { 5946 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "name_length", "Name length"); 5947 addChild(blockGroup); 5948 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableNameLengthCases); 5949 } 5950 5951 // .offset 5952 { 5953 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "offset", "Offset"); 5954 addChild(blockGroup); 5955 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableOffsetCases); 5956 } 5957 5958 // .referenced_by 5959 { 5960 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "referenced_by", "Referenced by"); 5961 addChild(blockGroup); 5962 generateReferencedByShaderCaseBlocks(m_context, blockGroup, generateBufferVariableReferencedByBlockContents); 5963 } 5964 5965 // .top_level_array_size 5966 { 5967 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "top_level_array_size", "Top-level array size"); 5968 addChild(blockGroup); 5969 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableTopLevelCases<PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_SIZE>); 5970 } 5971 5972 // .top_level_array_stride 5973 { 5974 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "top_level_array_stride", "Top-level array stride"); 5975 addChild(blockGroup); 5976 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, generateBufferVariableTopLevelCases<PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_STRIDE>); 5977 } 5978 5979 // .type 5980 { 5981 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "type", "Type"); 5982 addChild(blockGroup); 5983 generateBufferVariableTypeBlock(m_context, blockGroup); 5984 } 5985 5986 // .random 5987 { 5988 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "random", "Random"); 5989 addChild(blockGroup); 5990 generateBufferVariableRandomCases(m_context, blockGroup); 5991 } 5992 } 5993 5994 } // anonymous 5995 5996 ProgramInterfaceQueryTests::ProgramInterfaceQueryTests (Context& context) 5997 : TestCaseGroup(context, "program_interface_query", "Program interface query tests") 5998 { 5999 } 6000 6001 ProgramInterfaceQueryTests::~ProgramInterfaceQueryTests (void) 6002 { 6003 } 6004 6005 void ProgramInterfaceQueryTests::init (void) 6006 { 6007 // Misc queries 6008 6009 // .buffer_limited_query 6010 { 6011 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "buffer_limited_query", "Queries limited by the buffer size"); 6012 6013 addChild(group); 6014 6015 group->addChild(new ResourceNameBufferLimitCase(m_context, "resource_name_query", "Test GetProgramResourceName with too small a buffer")); 6016 group->addChild(new ResourceQueryBufferLimitCase(m_context, "resource_query", "Test GetProgramResourceiv with too small a buffer")); 6017 } 6018 6019 // Interfaces 6020 6021 // .uniform 6022 addChild(new UniformInterfaceTestGroup(m_context)); 6023 6024 // .uniform_block 6025 addChild(new BufferBackedBlockInterfaceTestGroup(m_context, glu::STORAGE_UNIFORM)); 6026 6027 // .atomic_counter_buffer 6028 addChild(new AtomicCounterTestGroup(m_context)); 6029 6030 // .program_input 6031 addChild(new ProgramInputTestGroup(m_context)); 6032 6033 // .program_output 6034 addChild(new ProgramOutputTestGroup(m_context)); 6035 6036 // .transform_feedback_varying 6037 addChild(new TransformFeedbackVaryingTestGroup(m_context)); 6038 6039 // .buffer_variable 6040 addChild(new BufferVariableTestGroup(m_context)); 6041 6042 // .shader_storage_block 6043 addChild(new BufferBackedBlockInterfaceTestGroup(m_context, glu::STORAGE_BUFFER)); 6044 } 6045 6046 } // Functional 6047 } // gles31 6048 } // deqp 6049