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