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