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