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