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