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