1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 The Khronos Group Inc. 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 22 */ /*-------------------------------------------------------------------*/ 23 #include "es31cLayoutBindingTests.hpp" 24 25 #include "tcuRenderTarget.hpp" 26 #include "tcuStringTemplate.hpp" 27 #include "tcuSurface.hpp" 28 #include "tcuTestLog.hpp" 29 #include "tcuTexture.hpp" 30 #include "tcuTextureUtil.hpp" 31 32 #include "deRandom.hpp" 33 #include "deStringUtil.hpp" 34 35 #include "glwDefs.hpp" 36 #include "glwEnums.hpp" 37 #include "glwFunctions.hpp" 38 39 #include "gluDrawUtil.hpp" 40 #include "gluPixelTransfer.hpp" 41 #include "gluShaderProgram.hpp" 42 #include "gluTexture.hpp" 43 #include "gluTextureUtil.hpp" 44 45 namespace glcts 46 { 47 48 //========================================================================= 49 //= typedefs 50 //========================================================================= 51 typedef std::string String; 52 typedef std::map<String, String> StringMap; 53 typedef std::map<String, glw::GLint> StringIntMap; 54 typedef std::map<glw::GLint, glw::GLint> IntIntMap; 55 typedef std::vector<String> StringVector; 56 typedef std::vector<int> IntVector; 57 58 typedef std::map<int, glu::Texture2D*> Texture2DMap; 59 typedef std::map<int, glu::Texture2DArray*> Texture2DArrayMap; 60 typedef std::map<int, glu::Texture3D*> Texture3DMap; 61 62 //========================================================================= 63 //= utility classes 64 //========================================================================= 65 66 //= string stream that saves some typing 67 class StringStream : public std::ostringstream 68 { 69 public: 70 void reset() 71 { 72 clear(); 73 str(""); 74 } 75 }; 76 77 class LayoutBindingProgram; 78 79 class IProgramContextSupplier 80 { 81 public: 82 virtual ~IProgramContextSupplier() 83 { 84 } 85 virtual Context& getContext() = 0; 86 virtual const LayoutBindingParameters& getTestParameters() = 0; 87 virtual eStageType getStage() = 0; 88 virtual const String& getSource(eStageType stage) = 0; 89 virtual LayoutBindingProgram* createProgram() = 0; 90 }; 91 92 class LayoutBindingProgram 93 { 94 public: 95 LayoutBindingProgram(IProgramContextSupplier& contextSupplier) 96 : m_contextSupplier(contextSupplier) 97 , m_context(contextSupplier.getContext().getRenderContext()) 98 , m_stage(contextSupplier.getStage()) 99 , m_testParams(contextSupplier.getTestParameters()) 100 , m_gl(contextSupplier.getContext().getRenderContext().getFunctions()) 101 { 102 if (getStage() != ComputeShader) 103 m_program = new glu::ShaderProgram( 104 m_context, glu::makeVtxFragSources(m_contextSupplier.getSource(VertexShader).c_str(), 105 m_contextSupplier.getSource(FragmentShader).c_str())); 106 else 107 m_program = new glu::ShaderProgram( 108 m_context, 109 glu::ProgramSources() << glu::ComputeSource(m_contextSupplier.getSource(ComputeShader).c_str())); 110 } 111 virtual ~LayoutBindingProgram() 112 { 113 delete m_program; 114 } 115 116 class LayoutBindingProgramAutoPtr 117 { 118 public: 119 LayoutBindingProgramAutoPtr(IProgramContextSupplier& contextSupplier) 120 { 121 m_program = contextSupplier.createProgram(); 122 } 123 ~LayoutBindingProgramAutoPtr() 124 { 125 delete m_program; 126 } 127 LayoutBindingProgram* operator->() 128 { 129 return m_program; 130 } 131 132 private: 133 LayoutBindingProgram* m_program; 134 }; 135 136 String getErrorLog(bool dumpShaders = false) 137 { 138 StringStream errLog; 139 140 if (getStage() != ComputeShader) 141 { 142 const glu::ShaderInfo& fragmentShaderInfo = m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT); 143 const glu::ShaderInfo& vertexShaderInfo = m_program->getShaderInfo(glu::SHADERTYPE_VERTEX); 144 145 if (!fragmentShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders) 146 { 147 errLog << "### dump of " << stageToName(FragmentShader) << "###\n"; 148 String msg((dumpShaders ? "Fragment shader should not have compiled" : 149 "Vertex shader compile failed while testing ")); 150 errLog << "Fragment shader compile failed while testing " << stageToName(getStage()) << ": " 151 << fragmentShaderInfo.infoLog << "\n"; 152 errLog << m_contextSupplier.getSource(FragmentShader); 153 } 154 if (!vertexShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders) 155 { 156 errLog << "### dump of " << stageToName(VertexShader) << "###\n"; 157 String msg((dumpShaders ? "Vertex shader should not have compiled" : 158 "Vertex shader compile failed while testing ")); 159 errLog << msg << stageToName(getStage()) << ": " << vertexShaderInfo.infoLog << "\n"; 160 errLog << m_contextSupplier.getSource(VertexShader); 161 } 162 } 163 else 164 { 165 const glu::ShaderInfo& computeShaderInfo = m_program->getShaderInfo(glu::SHADERTYPE_COMPUTE); 166 167 if (!computeShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders) 168 { 169 errLog << "### dump of " << stageToName(ComputeShader) << "###\n"; 170 String msg((dumpShaders ? "Compute shader should not have compiled" : 171 "Compute shader compile failed while testing ")); 172 errLog << msg << stageToName(ComputeShader) << ": " << computeShaderInfo.infoLog << "\n"; 173 errLog << m_contextSupplier.getSource(ComputeShader); 174 } 175 } 176 if (!m_program->getProgramInfo().linkOk) 177 { 178 getStage(); 179 errLog << "Linking failed while testing " << stageToName(getStage()) << ": " 180 << m_program->getProgramInfo().infoLog << "\n"; 181 errLog << "### other stages ###\n"; 182 switch (getStage()) 183 { 184 case FragmentShader: 185 errLog << "### dump of " << stageToName(VertexShader) << "###\n"; 186 errLog << m_contextSupplier.getSource(VertexShader); 187 break; 188 case VertexShader: 189 errLog << "### dump of " << stageToName(FragmentShader) << "###\n"; 190 errLog << stageToName(FragmentShader) << "\n"; 191 errLog << m_contextSupplier.getSource(FragmentShader); 192 break; 193 case ComputeShader: 194 errLog << "### dump of " << stageToName(ComputeShader) << "###\n"; 195 errLog << stageToName(ComputeShader) << "\n"; 196 errLog << m_contextSupplier.getSource(ComputeShader); 197 break; 198 default: 199 DE_ASSERT(0); 200 break; 201 } 202 } 203 return errLog.str(); 204 } 205 206 private: 207 IProgramContextSupplier& m_contextSupplier; 208 209 const glu::RenderContext& m_context; 210 const eStageType m_stage; // shader stage currently tested 211 const LayoutBindingParameters& m_testParams; // parameters for shader generation (table at end of file) 212 const glw::Functions& m_gl; 213 214 glu::ShaderProgram* m_program; 215 216 private: 217 StringIntMap getUniformLocations(StringVector args) const 218 { 219 StringVector::iterator it; 220 StringIntMap locations; 221 bool passed = true; 222 223 for (it = args.begin(); it != args.end(); it++) 224 { 225 const char* name = (*it).c_str(); 226 glw::GLint location = m_gl.getUniformLocation(getProgram(), name); 227 passed &= (0 <= location); 228 if (passed) 229 { 230 locations[name] = location; 231 } 232 } 233 234 return locations; 235 } 236 237 public: 238 glw::GLint getProgram() const 239 { 240 return m_program->getProgram(); 241 } 242 243 const glw::Functions& gl() const 244 { 245 return m_gl; 246 } 247 248 virtual eStageType getStage() const 249 { 250 return m_stage; 251 } 252 253 String stageToName(eStageType stage) const 254 { 255 switch (stage) 256 { 257 case FragmentShader: 258 return "FragmentShader"; 259 case VertexShader: 260 return "VertexShader"; 261 case ComputeShader: 262 return "ComputeShader"; 263 default: 264 DE_ASSERT(0); 265 break; 266 } 267 return String(); 268 } 269 270 bool error() const 271 { 272 return (m_gl.getError() == GL_NO_ERROR); 273 } 274 275 bool compiledAndLinked() const 276 { 277 if (getStage() != ComputeShader) 278 return m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk && 279 m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk && m_program->getProgramInfo().linkOk; 280 281 return m_program->getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk && m_program->getProgramInfo().linkOk; 282 } 283 284 virtual StringIntMap getBindingPoints(StringVector args) const 285 { 286 StringIntMap bindingPoints; 287 288 StringIntMap locations = getUniformLocations(args); 289 if (!locations.empty()) 290 { 291 glw::GLint bindingPoint; 292 for (StringIntMap::iterator it = locations.begin(); it != locations.end(); it++) 293 { 294 glw::GLint location = it->second; 295 m_gl.getUniformiv(getProgram(), location, &bindingPoint); 296 bool hasNoError = (GL_NO_ERROR == m_gl.getError()); 297 if (hasNoError) 298 { 299 bindingPoints[it->first] = bindingPoint; 300 } 301 } 302 } 303 return bindingPoints; 304 } 305 306 virtual bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const 307 { 308 bool bNoError = true; 309 310 StringIntMap locations = getUniformLocations(list); 311 if (!locations.empty()) 312 { 313 for (StringIntMap::iterator it = locations.begin(); it != locations.end(); it++) 314 { 315 m_gl.uniform1i(it->second, bindingPoint); 316 bNoError &= (GL_NO_ERROR == m_gl.getError()); 317 } 318 } 319 return bNoError; 320 } 321 322 virtual StringIntMap getOffsets(StringVector /*args*/) const 323 { 324 return StringIntMap(); 325 } 326 }; 327 328 class LayoutBindingTestResult 329 { 330 public: 331 LayoutBindingTestResult(bool passed = true, const String& reason = String(), bool notRunforThisContext = false) 332 : m_passed(passed), m_notRunForThisContext(notRunforThisContext), m_reason(reason) 333 { 334 } 335 336 public: 337 bool testPassed() const 338 { 339 return m_passed; 340 } 341 342 String getReason() const 343 { 344 return m_reason; 345 } 346 347 bool runForThisContext() const 348 { 349 return !m_notRunForThisContext; 350 } 351 352 private: 353 bool m_passed; 354 bool m_notRunForThisContext; 355 String m_reason; 356 }; 357 358 class IntegerConstant 359 { 360 public: 361 enum Literals 362 { 363 decimal = 0, 364 decimal_u, 365 decimal_U, 366 octal, 367 octal_u, 368 octal_U, 369 hex_x, 370 hex_X, 371 hex_u, 372 hex_u_X, 373 hex_U, 374 hex_U_X, 375 last 376 }; 377 378 public: 379 IntegerConstant(Literals lit, int ai) : asInt(ai) 380 { 381 StringStream s; 382 switch (lit) 383 { 384 case decimal: 385 s << asInt; 386 break; 387 case decimal_u: 388 s << asInt << "u"; 389 break; 390 case decimal_U: 391 s << asInt << "U"; 392 break; 393 case octal: 394 s << "0" << std::oct << asInt; 395 break; 396 case octal_u: 397 s << "0" << std::oct << asInt << "u"; 398 break; 399 case octal_U: 400 s << "0" << std::oct << asInt << "U"; 401 break; 402 case hex_x: 403 s << "0x" << std::hex << asInt; 404 break; 405 case hex_X: 406 s << "0X" << std::hex << asInt; 407 break; 408 case hex_u: 409 s << "0x" << std::hex << asInt << "u"; 410 break; 411 case hex_u_X: 412 s << "0X" << std::hex << asInt << "u"; 413 break; 414 case hex_U: 415 s << "0x" << std::hex << asInt << "U"; 416 break; 417 case hex_U_X: 418 s << "0X" << std::hex << asInt << "U"; 419 break; 420 case last: 421 default: 422 DE_ASSERT(0); 423 } 424 425 asString = s.str(); 426 } 427 428 public: 429 String asString; 430 int asInt; 431 }; 432 433 //***************************************************************************** 434 class LayoutBindingBaseCase : public TestCase, public IProgramContextSupplier 435 { 436 public: 437 LayoutBindingBaseCase(Context& context, const char* name, const char* description, StageType stage, 438 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion); 439 virtual ~LayoutBindingBaseCase(void); 440 441 IterateResult iterate(void); 442 443 // overrideable subtests 444 virtual LayoutBindingTestResult binding_basic_default(void); 445 virtual LayoutBindingTestResult binding_basic_explicit(void); 446 virtual LayoutBindingTestResult binding_basic_multiple(void); 447 virtual LayoutBindingTestResult binding_basic_render(void); 448 virtual LayoutBindingTestResult binding_integer_constant(void); 449 virtual LayoutBindingTestResult binding_integer_constant_expression(void); 450 virtual LayoutBindingTestResult binding_array_size(void); 451 virtual LayoutBindingTestResult binding_array_implicit(void); 452 virtual LayoutBindingTestResult binding_array_multiple(void); 453 virtual LayoutBindingTestResult binding_api_update(void); 454 virtual LayoutBindingTestResult binding_compilation_errors(void); 455 virtual LayoutBindingTestResult binding_link_errors(void); 456 virtual LayoutBindingTestResult binding_examples(void); 457 virtual LayoutBindingTestResult binding_mixed_order(void); 458 459 private: 460 // drawTest normal vs. compute 461 typedef LayoutBindingTestResult (LayoutBindingBaseCase::*LayoutBindingDrawTestPtr)(glw::GLint program, int binding); 462 463 LayoutBindingDrawTestPtr m_drawTest; 464 465 // pointer type for subtests 466 typedef LayoutBindingTestResult (LayoutBindingBaseCase::*LayoutBindingSubTestPtr)(); 467 468 // test table entry 469 struct LayoutBindingSubTest 470 { 471 char const* name; 472 char const* description; 473 LayoutBindingSubTestPtr test; 474 }; 475 476 // IProgramContextSupplier interface 477 protected: 478 const LayoutBindingParameters& getTestParameters() 479 { 480 return m_testParams; 481 } 482 483 const glu::RenderContext& getRenderContext() 484 { 485 return m_context.getRenderContext(); 486 } 487 488 virtual eStageType getStage() 489 { 490 return m_stage.type; 491 } 492 493 const String& getSource(eStageType stage) 494 { 495 return m_sources[stage]; 496 } 497 498 Context& getContext() 499 { 500 return m_context; 501 } 502 503 const glw::Functions& gl() 504 { 505 return m_context.getRenderContext().getFunctions(); 506 } 507 508 bool needsPrecision() const 509 { 510 if (isContextTypeES(m_context.getRenderContext().getType()) || m_glslVersion == glu::GLSL_VERSION_450) 511 { 512 return (m_testParams.surface_type != UniformBlock) && (m_testParams.surface_type != ShaderStorageBuffer); 513 } 514 else 515 { 516 return (m_testParams.surface_type != UniformBlock) && (m_testParams.surface_type != ShaderStorageBuffer) && 517 (m_testParams.surface_type != AtomicCounter) && (m_testParams.surface_type != Image); 518 } 519 } 520 521 protected: 522 std::vector<int> makeSparseRange(int maxElement, int minElement = 0) const 523 { 524 static float rangeT[] = { 0.0f, 0.1f, 0.5f, 0.6f, 0.9f, 1.0f }; 525 std::vector<float> rangeTemplate = makeVector(rangeT); 526 float max = rangeTemplate.back(); 527 float range = (float)((maxElement - 1) - minElement); 528 529 std::vector<int> result; 530 for (std::vector<float>::iterator it = rangeTemplate.begin(); it != rangeTemplate.end(); it++) 531 { 532 float e = *it; 533 e = (e * range) / max; 534 result.insert(result.end(), minElement + (int)e); 535 } 536 return result; 537 } 538 539 glu::GLSLVersion getGLSLVersion() 540 { 541 return m_glslVersion; 542 } 543 544 bool isStage(eStageType stage) 545 { 546 return (stage == m_stage.type); 547 } 548 549 void setTemplateParam(eStageType stage, const char* param, const String& value) 550 { 551 m_templateParams[stage][param] = value.c_str(); 552 } 553 554 void setTemplateParam(const char* param, const String& value) 555 { 556 setTemplateParam(m_stage.type, param, value); 557 } 558 559 void updateTemplate(eStageType stage) 560 { 561 m_sources[stage] = tcu::StringTemplate(m_templates[stage]).specialize(m_templateParams[stage]); 562 } 563 564 void updateTemplate() 565 { 566 updateTemplate(m_stage.type); 567 } 568 569 template <class T0, class T1> 570 String generateLog(const String& msg, T0 result, T1 expected) 571 { 572 StringStream s; 573 s << msg << " expected: " << expected << " actual: " << result << "\n"; 574 s << getSource(VertexShader) << "\n"; 575 s << getSource(FragmentShader) << "\n"; 576 return s.str(); 577 } 578 579 private: 580 std::vector<LayoutBindingSubTest> m_tests; 581 582 void init(void) 583 { 584 m_drawTest = 585 (getStage() == ComputeShader) ? &LayoutBindingBaseCase::drawTestCompute : &LayoutBindingBaseCase::drawTest; 586 587 #define MAKE_TEST_ENTRY(__subtest_name__) { #__subtest_name__, "", &LayoutBindingBaseCase::__subtest_name__ } 588 LayoutBindingSubTest tests[] = { 589 MAKE_TEST_ENTRY(binding_basic_default), MAKE_TEST_ENTRY(binding_basic_explicit), 590 MAKE_TEST_ENTRY(binding_basic_multiple), MAKE_TEST_ENTRY(binding_basic_render), 591 MAKE_TEST_ENTRY(binding_integer_constant), MAKE_TEST_ENTRY(binding_integer_constant_expression), 592 MAKE_TEST_ENTRY(binding_array_size), MAKE_TEST_ENTRY(binding_array_implicit), 593 MAKE_TEST_ENTRY(binding_array_multiple), MAKE_TEST_ENTRY(binding_api_update), 594 MAKE_TEST_ENTRY(binding_compilation_errors), MAKE_TEST_ENTRY(binding_link_errors), 595 MAKE_TEST_ENTRY(binding_examples), MAKE_TEST_ENTRY(binding_mixed_order) 596 }; 597 m_tests = makeVector(tests); 598 599 m_uniformDeclTemplate = "${LAYOUT}${KEYWORD}${UNIFORM_TYPE}${UNIFORM_BLOCK_NAME}${UNIFORM_BLOCK}${UNIFORM_" 600 "INSTANCE_NAME}${UNIFORM_ARRAY};\n"; 601 602 m_expectedColor = tcu::Vec4(0.0, 1.0f, 0.0f, 1.0f); 603 604 switch (getTestParameters().texture_type) 605 { 606 case TwoD: 607 { 608 // 2D 609 glu::ImmutableTexture2D* texture2D = 610 new glu::ImmutableTexture2D(getContext().getRenderContext(), GL_RGBA8, 2, 2); 611 612 texture2D->getRefTexture().allocLevel(0); 613 tcu::clear(texture2D->getRefTexture().getLevel(0), m_expectedColor); 614 texture2D->upload(); 615 616 if (m_textures2D.find(0) != m_textures2D.end()) 617 { 618 delete m_textures2D[0]; 619 } 620 621 m_textures2D[0] = texture2D; 622 } 623 break; 624 case TwoDArray: 625 { 626 // 2DArray 627 glu::Texture2DArray* texture2DArray = 628 new glu::Texture2DArray(getContext().getRenderContext(), GL_RGBA8, 2, 2, 1); 629 630 texture2DArray->getRefTexture().allocLevel(0); 631 tcu::clear(texture2DArray->getRefTexture().getLevel(0), m_expectedColor); 632 texture2DArray->upload(); 633 634 if (m_textures2DArray.find(0) != m_textures2DArray.end()) 635 { 636 delete m_textures2DArray[0]; 637 } 638 639 m_textures2DArray[0] = texture2DArray; 640 } 641 break; 642 // 3D 643 case ThreeD: 644 { 645 glu::Texture3D* texture3D = new glu::Texture3D(getContext().getRenderContext(), GL_RGBA8, 2, 2, 1); 646 647 texture3D->getRefTexture().allocLevel(0); 648 tcu::clear(texture3D->getRefTexture().getLevel(0), m_expectedColor); 649 texture3D->upload(); 650 651 if (m_textures3D.find(0) != m_textures3D.end()) 652 { 653 delete m_textures3D[0]; 654 } 655 656 m_textures3D[0] = texture3D; 657 } 658 break; 659 case None: 660 // test case where no texture allocation is needed 661 break; 662 default: 663 DE_ASSERT(0); 664 break; 665 } 666 } 667 668 String initDefaultVSContext() 669 { 670 m_templates[VertexShader] = "${VERSION}" 671 "layout(location=0) in vec2 inPosition;\n" 672 "${UNIFORM_DECL}\n" 673 "flat out ${OUT_VAR_TYPE} fragColor;\n" 674 "${OPTIONAL_FUNCTION_BLOCK}\n" 675 "void main(void)\n" 676 "{\n" 677 " ${OUT_ASSIGNMENT} ${UNIFORM_ACCESS}\n" 678 " gl_Position = vec4(inPosition, 0.0, 1.0);\n" 679 "}\n"; 680 681 StringMap& args = m_templateParams[VertexShader]; 682 // some samplers and all images don't have default precision qualifier (sampler3D) 683 // so append a precision default in all sampler and image cases. 684 StringStream s; 685 s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n"; 686 s << "precision highp float;\n"; 687 if (needsPrecision()) 688 { 689 s << "precision highp " << getTestParameters().uniform_type << ";\n"; 690 } 691 692 args["VERSION"] = s.str(); 693 args["UNIFORM_DECL"] = ""; 694 args["OPTIONAL_FUNCTION_BLOCK"] = ""; 695 args["UNIFORM_ACCESS"] = ""; 696 args["OUT_ASSIGNMENT"] = "fragColor ="; 697 args["OUT_VAR_TYPE"] = getTestParameters().vector_type; 698 args["OUT_VAR"] = "fragColor"; 699 if (m_stage.type != VertexShader) 700 { 701 args["OUT_ASSIGNMENT"] = ""; 702 } 703 return tcu::StringTemplate(m_templates[VertexShader]).specialize(args); 704 } 705 706 String initDefaultFSContext() 707 { 708 // build fragment shader 709 m_templates[FragmentShader] = "${VERSION}" 710 "layout(location=0) out ${OUT_VAR_TYPE} ${OUT_VAR};\n" 711 "flat in ${OUT_VAR_TYPE} fragColor;\n" 712 "${UNIFORM_DECL}\n" 713 "${OPTIONAL_FUNCTION_BLOCK}\n" 714 "void main(void)\n" 715 "{\n" 716 " ${OUT_ASSIGNMENT} ${UNIFORM_ACCESS}\n" 717 "}\n"; 718 719 StringMap& args = m_templateParams[FragmentShader]; 720 // samplers and images don't have default precision qualifier 721 StringStream s; 722 s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n"; 723 s << "precision highp float;\n"; 724 if (needsPrecision()) 725 { 726 s << "precision highp " << getTestParameters().uniform_type << ";\n"; 727 } 728 args["VERSION"] = s.str(); 729 args["OUT_VAR_TYPE"] = getTestParameters().vector_type; 730 args["UNIFORM_ACCESS"] = "vec4(0.0,0.0,0.0,0.0);"; 731 args["UNIFORM_DECL"] = ""; 732 args["OPTIONAL_FUNCTION_BLOCK"] = ""; 733 args["OUT_ASSIGNMENT"] = "outColor ="; 734 args["OUT_VAR"] = "outColor"; 735 // must have a linkage between stage and fragment shader 736 // that the compiler can't optimize away 737 if (FragmentShader != m_stage.type) 738 { 739 args["UNIFORM_ACCESS"] = "fragColor;"; 740 } 741 return tcu::StringTemplate(m_templates[FragmentShader]).specialize(args); 742 } 743 744 String initDefaultCSContext() 745 { 746 // build compute shader 747 m_templates[ComputeShader] = "${VERSION}" 748 "${UNIFORM_DECL}\n" 749 "${OPTIONAL_FUNCTION_BLOCK}\n" 750 "void main(void)\n" 751 "{\n" 752 " ${OUT_VAR_TYPE} tmp = ${UNIFORM_ACCESS}\n" 753 " ${OUT_ASSIGNMENT} tmp ${OUT_END}\n" 754 "}\n"; 755 756 StringMap& args = m_templateParams[ComputeShader]; 757 // images don't have default precision qualifier 758 StringStream s; 759 s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n"; 760 s << "layout (local_size_x = 1) in;\n" 761 "precision highp float;\n"; 762 if (needsPrecision()) 763 { 764 s << "precision highp " << getTestParameters().uniform_type << ";\n"; 765 } 766 767 // bindings are per uniform type... 768 if (getTestParameters().surface_type == Image) 769 { 770 s << "layout(binding=0, std430) buffer outData {\n" 771 " " 772 << getTestParameters().vector_type << " outColor;\n" 773 "};\n"; 774 args["OUT_ASSIGNMENT"] = "outColor ="; 775 args["OUT_END"] = ";"; 776 } 777 else 778 { 779 s << "layout(binding=0, rgba8) uniform highp writeonly image2D outImage;\n"; 780 args["OUT_ASSIGNMENT"] = "imageStore(outImage, ivec2(0), "; 781 args["OUT_END"] = ");"; 782 } 783 args["VERSION"] = s.str(); 784 args["OUT_VAR_TYPE"] = getTestParameters().vector_type; 785 args["UNIFORM_ACCESS"] = "vec4(0.0,0.0,0.0,0.0);"; 786 args["UNIFORM_DECL"] = ""; 787 args["OPTIONAL_FUNCTION_BLOCK"] = ""; 788 789 return tcu::StringTemplate(m_templates[ComputeShader]).specialize(args); 790 } 791 792 protected: 793 String buildUniformDecl(const String& keyword, const String& layout, const String& uniform_type, 794 const String& uniform_block_name, const String& uniform_block, 795 const String& uniform_instance, const String& uniform_array) const 796 { 797 StringMap args; 798 setArg(args["LAYOUT"], layout); 799 setArg(args["KEYWORD"], keyword); 800 if (uniform_block_name.empty()) 801 setArg(args["UNIFORM_TYPE"], uniform_type); 802 else 803 args["UNIFORM_TYPE"] = ""; 804 if (!uniform_instance.empty() && !uniform_block_name.empty()) 805 setArg(args["UNIFORM_BLOCK_NAME"], uniform_block_name + "_block"); 806 else 807 setArg(args["UNIFORM_BLOCK_NAME"], uniform_block_name); 808 setArg(args["UNIFORM_BLOCK"], uniform_block); 809 if ((uniform_block_name.empty() && uniform_block.empty()) || !uniform_array.empty()) 810 args["UNIFORM_INSTANCE_NAME"] = uniform_instance; 811 else 812 args["UNIFORM_INSTANCE_NAME"] = ""; 813 args["UNIFORM_ARRAY"] = uniform_array; 814 return tcu::StringTemplate(m_uniformDeclTemplate).specialize(args); 815 } 816 817 virtual String getDefaultUniformName(int idx = 0) 818 { 819 StringStream s; 820 s << "uniform" << idx; 821 return s.str(); 822 } 823 824 virtual String buildUniformName(String& var) 825 { 826 std::ostringstream s; 827 s << var; 828 return s.str(); 829 } 830 831 virtual String buildLayout(const String& binding) 832 { 833 std::ostringstream s; 834 if (!binding.empty()) 835 s << "layout(binding=" << binding << ") "; 836 return s.str(); 837 } 838 839 virtual String buildLayout(int binding) 840 { 841 std::ostringstream bindingStr; 842 bindingStr << binding; 843 return buildLayout(bindingStr.str()); 844 } 845 846 virtual String buildAccess(const String& var) 847 { 848 std::ostringstream s; 849 s << getTestParameters().access_function << "(" << var << "," << getTestParameters().coord_vector_type << "(0)" 850 << ")"; 851 return s.str(); 852 } 853 854 virtual String buildBlockName(const String& /*name*/) 855 { 856 return String(); 857 } 858 859 virtual String buildBlock(const String& /*name*/, const String& /*type*/ = String("float")) 860 { 861 return String(); 862 } 863 864 virtual String buildArray(int idx) 865 { 866 StringStream s; 867 s << "[" << idx << "]"; 868 return s.str(); 869 } 870 871 virtual String buildArrayAccess(int uniform, int idx) 872 { 873 StringStream s; 874 s << getDefaultUniformName(uniform) << buildArray(idx); 875 if (!buildBlockName(getDefaultUniformName()).empty()) 876 { 877 s << "." << getDefaultUniformName(uniform); 878 } 879 return s.str(); 880 } 881 882 // return max. binding point allowed 883 virtual int maxBindings() 884 { 885 int units = 0; 886 887 if (getTestParameters().surface_type == Image) 888 { 889 gl().getIntegerv(GL_MAX_IMAGE_UNITS, &units); 890 } 891 else 892 { 893 gl().getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &units); 894 } 895 896 return units; 897 } 898 899 // return max. array size allowed 900 virtual int maxArraySize() 901 { 902 int units = 0; 903 904 if (getTestParameters().surface_type == Image) 905 { 906 switch (m_stage.type) 907 { 908 case VertexShader: 909 gl().getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &units); 910 break; 911 case FragmentShader: 912 gl().getIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &units); 913 break; 914 default: 915 DE_ASSERT(0); 916 break; 917 } 918 } 919 else 920 { 921 switch (m_stage.type) 922 { 923 case VertexShader: 924 gl().getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &units); 925 break; 926 case FragmentShader: 927 gl().getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units); 928 break; 929 default: 930 DE_ASSERT(0); 931 break; 932 } 933 } 934 935 return units; 936 } 937 938 virtual bool isSupported() 939 { 940 return (maxArraySize() > 0); 941 } 942 943 virtual void bind(int binding) 944 { 945 glw::GLint texTarget = 0; 946 glw::GLint texName = 0; 947 948 switch (getTestParameters().texture_type) 949 { 950 case TwoD: 951 texTarget = GL_TEXTURE_2D; 952 texName = m_textures2D[0]->getGLTexture(); 953 break; 954 case TwoDArray: 955 texTarget = GL_TEXTURE_2D_ARRAY; 956 texName = m_textures2DArray[0]->getGLTexture(); 957 break; 958 case ThreeD: 959 texTarget = GL_TEXTURE_3D; 960 texName = m_textures3D[0]->getGLTexture(); 961 break; 962 default: 963 DE_ASSERT(0); 964 break; 965 } 966 967 switch (getTestParameters().surface_type) 968 { 969 case Texture: 970 gl().activeTexture(GL_TEXTURE0 + binding); 971 gl().bindTexture(texTarget, texName); 972 gl().texParameteri(texTarget, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(tcu::Sampler::CLAMP_TO_EDGE)); 973 gl().texParameteri(texTarget, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(tcu::Sampler::CLAMP_TO_EDGE)); 974 gl().texParameteri(texTarget, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(tcu::Sampler::NEAREST)); 975 gl().texParameteri(texTarget, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(tcu::Sampler::NEAREST)); 976 break; 977 case Image: 978 gl().bindImageTexture(binding, texName, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); 979 break; 980 default: 981 DE_ASSERT(0); 982 break; 983 } 984 } 985 986 virtual void unbind(int binding) 987 { 988 glw::GLint texTarget = 0; 989 990 switch (getTestParameters().texture_type) 991 { 992 case TwoD: 993 texTarget = GL_TEXTURE_2D; 994 break; 995 case TwoDArray: 996 texTarget = GL_TEXTURE_2D_ARRAY; 997 break; 998 case ThreeD: 999 texTarget = GL_TEXTURE_3D; 1000 break; 1001 default: 1002 DE_ASSERT(0); 1003 break; 1004 } 1005 1006 switch (getTestParameters().surface_type) 1007 { 1008 case Texture: 1009 gl().activeTexture(GL_TEXTURE0 + binding); 1010 gl().bindTexture(texTarget, 0); 1011 break; 1012 case Image: 1013 gl().bindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F); 1014 break; 1015 default: 1016 DE_ASSERT(0); 1017 break; 1018 } 1019 } 1020 1021 virtual LayoutBindingTestResult drawTest(glw::GLint program, int binding); 1022 virtual LayoutBindingTestResult drawTestCompute(glw::GLint program, int binding); 1023 1024 // allocate resources needed for all subtests, i.e. textures 1025 virtual void setupTest() 1026 { 1027 } 1028 1029 // cleanup resources needed for all subtests 1030 virtual void teardownTest() 1031 { 1032 for (Texture2DMap::iterator it = m_textures2D.begin(); it != m_textures2D.end(); it++) 1033 { 1034 delete it->second; 1035 } 1036 m_textures2D.clear(); 1037 1038 for (Texture2DArrayMap::iterator it = m_textures2DArray.begin(); it != m_textures2DArray.end(); it++) 1039 { 1040 delete it->second; 1041 } 1042 m_textures2DArray.clear(); 1043 1044 for (Texture3DMap::iterator it = m_textures3D.begin(); it != m_textures3D.end(); it++) 1045 { 1046 delete it->second; 1047 } 1048 m_textures3D.clear(); 1049 } 1050 1051 private: 1052 // appends a space to the argument (make shader source pretty) 1053 void setArg(String& arg, const String& value) const 1054 { 1055 if (!value.empty()) 1056 arg = value + String(" "); 1057 else 1058 arg = String(); 1059 } 1060 1061 private: 1062 LayoutBindingParameters m_testParams; 1063 StageType m_stage; 1064 1065 std::map<eStageType, String> m_sources; 1066 std::map<eStageType, StringMap> m_templateParams; 1067 std::map<eStageType, const char*> m_templates; 1068 1069 Texture2DMap m_textures2D; 1070 Texture2DArrayMap m_textures2DArray; 1071 Texture3DMap m_textures3D; 1072 tcu::Vec4 m_expectedColor; 1073 1074 const char* m_uniformDeclTemplate; 1075 1076 glu::GLSLVersion m_glslVersion; 1077 }; 1078 1079 LayoutBindingBaseCase::LayoutBindingBaseCase(Context& context, const char* name, const char* description, 1080 StageType stage, LayoutBindingParameters& samplerType, 1081 glu::GLSLVersion glslVersion) 1082 : TestCase(context, name, description) 1083 , m_drawTest(DE_NULL) 1084 , m_testParams(samplerType) 1085 , m_stage(stage) 1086 , m_uniformDeclTemplate(DE_NULL) 1087 , m_glslVersion(glslVersion) 1088 { 1089 } 1090 1091 LayoutBindingBaseCase::~LayoutBindingBaseCase(void) 1092 { 1093 teardownTest(); 1094 } 1095 1096 LayoutBindingBaseCase::IterateResult LayoutBindingBaseCase::iterate(void) 1097 { 1098 tcu::TestLog& log = m_context.getTestContext().getLog(); 1099 bool passed = true; 1100 1101 if (!isSupported()) 1102 { 1103 log << tcu::TestLog::Section("NotSupported", ""); 1104 log << tcu::TestLog::Message << "This test was not run as minimum requirements were not met." 1105 << tcu::TestLog::EndMessage; 1106 log << tcu::TestLog::EndSection; 1107 getContext().getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "NotSupported"); 1108 return STOP; 1109 } 1110 1111 // init test case (create shader templates and textures) 1112 init(); 1113 1114 // allocate resources for all subtests 1115 setupTest(); 1116 1117 for (std::vector<LayoutBindingSubTest>::iterator it = m_tests.begin(); it != m_tests.end(); it++) 1118 { 1119 // need to reset templates and their args to a clean state before every 1120 // test to avoid bleeding. 1121 m_sources[VertexShader] = initDefaultVSContext(); 1122 m_sources[FragmentShader] = initDefaultFSContext(); 1123 m_sources[ComputeShader] = initDefaultCSContext(); 1124 1125 LayoutBindingTestResult result = ((*this).*((*it).test))(); 1126 if (!result.testPassed()) 1127 { 1128 log << tcu::TestLog::Section((*it).name, (*it).description); 1129 log << tcu::TestLog::Message << result.getReason() << tcu::TestLog::EndMessage; 1130 log << tcu::TestLog::EndSection; 1131 } 1132 if (!result.runForThisContext()) 1133 { 1134 log << tcu::TestLog::Section((*it).name, (*it).description); 1135 log << tcu::TestLog::Message << "This test was not run for this context as it does not apply." 1136 << tcu::TestLog::EndMessage; 1137 log << tcu::TestLog::EndSection; 1138 } 1139 passed &= result.testPassed(); 1140 } 1141 1142 // cleanup resources 1143 teardownTest(); 1144 1145 /*========================================================================= 1146 TEST results 1147 =========================================================================*/ 1148 1149 getContext().getTestContext().setTestResult(passed ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 1150 passed ? "Pass" : "Fail"); 1151 1152 return STOP; 1153 } 1154 1155 /*========================================================================= 1156 // bind resource to specified binding point and program and 1157 // dispatch a computation, read back image at (0,0) 1158 =========================================================================*/ 1159 LayoutBindingTestResult LayoutBindingBaseCase::drawTestCompute(glw::GLint program, int binding) 1160 { 1161 const glw::Functions& l_gl = getContext().getRenderContext().getFunctions(); 1162 bool passed = true; 1163 1164 DE_TEST_ASSERT(getStage() == ComputeShader); 1165 1166 l_gl.useProgram(program); 1167 1168 deUint32 fb_or_ssb; 1169 1170 if (getTestParameters().surface_type == Image) 1171 { 1172 bind(binding); 1173 1174 glw::GLfloat buffer[4] = { 0.1f, 0.2f, 0.3f, 0.4f }; 1175 l_gl.genBuffers(1, &fb_or_ssb); 1176 l_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, fb_or_ssb); 1177 1178 l_gl.bufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(glw::GLfloat), buffer, GL_DYNAMIC_COPY); 1179 1180 l_gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, fb_or_ssb); 1181 1182 l_gl.dispatchCompute(1, 1, 1); 1183 l_gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1184 1185 tcu::Vec4 pixel = 1186 *(tcu::Vec4*)l_gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(glw::GLfloat), GL_MAP_READ_BIT); 1187 l_gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 1188 1189 l_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0); 1190 l_gl.deleteBuffers(1, &fb_or_ssb); 1191 1192 unbind(binding); 1193 1194 tcu::Vec4 expected(0.0f, 1.0f, 0.0f, 1.0f); 1195 passed = (pixel == expected); 1196 if (!passed) 1197 { 1198 return LayoutBindingTestResult(passed, generateLog(String("drawTestCompute failed"), expected, pixel)); 1199 } 1200 } 1201 else 1202 { 1203 deUint32 something = 0x01020304, tex; 1204 1205 l_gl.genTextures(1, &tex); 1206 l_gl.bindTexture(GL_TEXTURE_2D, tex); 1207 l_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1208 l_gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); 1209 l_gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &something); 1210 1211 bind(binding); 1212 1213 l_gl.bindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); 1214 1215 l_gl.dispatchCompute(1, 1, 1); 1216 l_gl.memoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); 1217 1218 l_gl.bindImageTexture(0, 0, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); 1219 1220 l_gl.genFramebuffers(1, &fb_or_ssb); 1221 l_gl.bindFramebuffer(GL_FRAMEBUFFER, fb_or_ssb); 1222 l_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); 1223 1224 l_gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &something); 1225 1226 l_gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 1227 l_gl.deleteFramebuffers(1, &fb_or_ssb); 1228 l_gl.deleteTextures(1, &tex); 1229 1230 unbind(binding); 1231 1232 const deUint32 expected = 0xff00ff00; 1233 passed = (expected == something); 1234 if (!passed) 1235 { 1236 return LayoutBindingTestResult( 1237 passed, generateLog(String("drawTestCompute failed"), tcu::RGBA(expected), tcu::RGBA(something))); 1238 } 1239 } 1240 1241 return passed; 1242 } 1243 1244 /*========================================================================= 1245 // bind resource to specified binding point and program and 1246 // return result of comparison of rendered pixel at (0,0) with expected 1247 =========================================================================*/ 1248 LayoutBindingTestResult LayoutBindingBaseCase::drawTest(glw::GLint program, int binding) 1249 { 1250 const glw::Functions& GL = getContext().getRenderContext().getFunctions(); 1251 const tcu::RenderTarget& renderTarget = getContext().getRenderContext().getRenderTarget(); 1252 glw::GLuint viewportW = renderTarget.getWidth(); 1253 glw::GLuint viewportH = renderTarget.getHeight(); 1254 tcu::Surface renderedFrame(viewportW, viewportH); 1255 bool passed = true; 1256 1257 DE_TEST_ASSERT(getStage() != ComputeShader); 1258 1259 GL.viewport(0, 0, viewportW, viewportH); 1260 GL.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1261 GL.clear(GL_COLOR_BUFFER_BIT); 1262 1263 static const float position[] = { 1264 -1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f, 1265 }; 1266 static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 }; 1267 1268 GL.useProgram(program); 1269 1270 bind(binding); 1271 1272 static const glu::VertexArrayBinding vertexArrays[] = { 1273 glu::va::Float("inPosition", 2, 4, 0, &position[0]), 1274 }; 1275 glu::draw(getContext().getRenderContext(), program, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], 1276 glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); 1277 1278 glu::readPixels(getContext().getRenderContext(), 0, 0, renderedFrame.getAccess()); 1279 1280 tcu::RGBA pixel = renderedFrame.getPixel(0, 0); 1281 1282 passed = (pixel == tcu::RGBA(m_expectedColor)); 1283 1284 unbind(binding); 1285 1286 if (!passed) 1287 { 1288 return LayoutBindingTestResult(passed, 1289 generateLog(String("drawTest failed"), m_expectedColor, pixel.getPacked())); 1290 } 1291 1292 return true; 1293 } 1294 1295 //== verify that binding point is default w/o layout binding 1296 LayoutBindingTestResult LayoutBindingBaseCase::binding_basic_default() 1297 { 1298 bool passed = true; 1299 1300 StringStream s; 1301 s << buildAccess(getDefaultUniformName()) << ";\n"; 1302 setTemplateParam("UNIFORM_ACCESS", s.str()); 1303 1304 String decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String()), 1305 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1306 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1307 setTemplateParam("UNIFORM_DECL", decl); 1308 updateTemplate(); 1309 1310 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1311 passed &= program->compiledAndLinked(); 1312 if (!passed) 1313 { 1314 return LayoutBindingTestResult(passed, program->getErrorLog()); 1315 } 1316 1317 StringVector list; 1318 const String& u = buildBlockName(getDefaultUniformName()); 1319 if (!u.empty()) 1320 list.push_back(u + "_block"); 1321 else 1322 list.push_back(getDefaultUniformName()); 1323 1324 StringIntMap bindingPoints = program->getBindingPoints(list); 1325 1326 passed &= bindingPoints.size() == list.size() && (bindingPoints[u] == 0); 1327 if (!passed) 1328 { 1329 return LayoutBindingTestResult(passed, 1330 generateLog(String("binding point did not match default"), bindingPoints[u], 0)); 1331 } 1332 1333 return true; 1334 } 1335 1336 //== verify that binding point has specified value 1337 LayoutBindingTestResult LayoutBindingBaseCase::binding_basic_explicit() 1338 { 1339 bool passed = true; 1340 1341 { 1342 StringStream s; 1343 s << buildAccess(getDefaultUniformName()) << ";\n"; 1344 setTemplateParam("UNIFORM_ACCESS", s.str()); 1345 } 1346 1347 std::vector<int> bindings = makeSparseRange(maxBindings()); 1348 for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++) 1349 { 1350 int binding = *it; 1351 String decl = 1352 buildUniformDecl(String(getTestParameters().keyword), buildLayout(binding), 1353 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1354 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1355 setTemplateParam("UNIFORM_DECL", decl); 1356 updateTemplate(); 1357 1358 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1359 passed &= program->compiledAndLinked(); 1360 if (!passed) 1361 { 1362 return LayoutBindingTestResult(passed, program->getErrorLog()); 1363 } 1364 1365 StringVector list; 1366 const String& s = buildBlockName(getDefaultUniformName()); 1367 if (!s.empty()) 1368 list.push_back(s + "_block"); 1369 else 1370 list.push_back(getDefaultUniformName()); 1371 1372 StringIntMap bindingPoints = program->getBindingPoints(list); 1373 passed &= bindingPoints.size() == list.size() && (binding == bindingPoints[list[0]]); 1374 if (!passed) 1375 { 1376 return LayoutBindingTestResult( 1377 passed, generateLog(String("binding point did not match default"), bindingPoints[list[0]], binding)); 1378 } 1379 } 1380 return true; 1381 } 1382 1383 //== verify that binding works with multiple samplers (same binding points) 1384 LayoutBindingTestResult LayoutBindingBaseCase::binding_basic_multiple() 1385 { 1386 bool passed = true; 1387 1388 glw::GLint baseBindingPoint = maxBindings() - 1; 1389 1390 String decl0 = buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint), 1391 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1392 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1393 String decl1 = buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint), 1394 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName(1)), 1395 buildBlock(getDefaultUniformName(1)), getDefaultUniformName(1), String()); 1396 setTemplateParam("UNIFORM_DECL", decl0 + decl1); 1397 1398 StringStream s; 1399 s << buildAccess(getDefaultUniformName()) << " + " << buildAccess(getDefaultUniformName(1)) << ";\n"; 1400 setTemplateParam("UNIFORM_ACCESS", s.str()); 1401 updateTemplate(); 1402 1403 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1404 passed &= program->compiledAndLinked(); 1405 if (!passed) 1406 { 1407 return LayoutBindingTestResult(passed, program->getErrorLog()); 1408 } 1409 1410 StringVector list; 1411 String u = buildBlockName(getDefaultUniformName()); 1412 if (!u.empty()) 1413 list.push_back(u + "_block"); 1414 else 1415 list.push_back(getDefaultUniformName()); 1416 1417 u = buildBlockName(getDefaultUniformName(1)); 1418 if (!u.empty()) 1419 list.push_back(u + "_block"); 1420 else 1421 list.push_back(getDefaultUniformName(1)); 1422 1423 StringIntMap bindingPoints = program->getBindingPoints(list); 1424 passed &= (baseBindingPoint == bindingPoints[list[0]]) && (baseBindingPoint == bindingPoints[list[1]]); 1425 if (!passed) 1426 { 1427 String err; 1428 err = generateLog(String("binding point did not match default"), bindingPoints[list[0]], baseBindingPoint); 1429 err += generateLog(String("binding point did not match default"), bindingPoints[list[1]], baseBindingPoint); 1430 return LayoutBindingTestResult(passed, err); 1431 } 1432 1433 return true; 1434 } 1435 1436 //== verify that binding point has specified value 1437 LayoutBindingTestResult LayoutBindingBaseCase::binding_basic_render() 1438 { 1439 bool passed = true; 1440 1441 StringStream s; 1442 s << buildAccess(getDefaultUniformName()) << ";\n"; 1443 setTemplateParam("UNIFORM_ACCESS", s.str()); 1444 1445 std::vector<int> bindings = makeSparseRange(maxBindings()); 1446 for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++) 1447 { 1448 int binding = *it; 1449 String decl = 1450 buildUniformDecl(String(getTestParameters().keyword), buildLayout(binding), 1451 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1452 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1453 setTemplateParam("UNIFORM_DECL", decl); 1454 updateTemplate(); 1455 1456 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1457 passed &= program->compiledAndLinked(); 1458 if (!passed) 1459 { 1460 return LayoutBindingTestResult(passed, program->getErrorLog()); 1461 } 1462 1463 LayoutBindingTestResult drawTestResult = ((*this).*(m_drawTest))(program->getProgram(), binding); 1464 if (!drawTestResult.testPassed()) 1465 { 1466 return LayoutBindingTestResult(drawTestResult.testPassed(), drawTestResult.getReason()); 1467 } 1468 } 1469 return true; 1470 } 1471 1472 LayoutBindingTestResult LayoutBindingBaseCase::binding_integer_constant() 1473 { 1474 bool passed = true; 1475 std::vector<int> integers = makeSparseRange(maxBindings(), 0); 1476 1477 std::vector<IntegerConstant> integerConstants; 1478 for (int idx = 0; idx < IntegerConstant::last; idx++) 1479 { 1480 for (IntVector::iterator it = integers.begin(); it != integers.end(); it++) 1481 { 1482 integerConstants.push_back(IntegerConstant((IntegerConstant::Literals)idx, (*it))); 1483 } 1484 } 1485 1486 //== verify that binding point can be set with integer constant 1487 for (std::vector<IntegerConstant>::iterator it = integerConstants.begin(); it != integerConstants.end(); it++) 1488 { 1489 String& intConst = (*it).asString; 1490 1491 String decl = 1492 buildUniformDecl(String(getTestParameters().keyword), buildLayout(intConst), 1493 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1494 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1495 setTemplateParam("UNIFORM_DECL", decl); 1496 1497 StringStream s; 1498 s << buildAccess(getDefaultUniformName()) << ";\n"; 1499 setTemplateParam("UNIFORM_ACCESS", s.str()); 1500 updateTemplate(); 1501 1502 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1503 passed &= program->compiledAndLinked(); 1504 if (!passed) 1505 { 1506 return LayoutBindingTestResult(passed, program->getErrorLog()); 1507 } 1508 1509 StringVector list; 1510 const String& u = buildBlockName(getDefaultUniformName()); 1511 if (!u.empty()) 1512 list.push_back(u + "_block"); 1513 else 1514 list.push_back(getDefaultUniformName()); 1515 1516 StringIntMap bindingPoints = program->getBindingPoints(list); 1517 passed &= ((*it).asInt == bindingPoints[list[0]]); 1518 if (!passed) 1519 { 1520 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"), 1521 bindingPoints[list[0]], (*it).asInt)); 1522 } 1523 } 1524 1525 //== verify that binding point can be set with integer constant resulting from a preprocessor substitution 1526 for (std::vector<IntegerConstant>::iterator it = integerConstants.begin(); it != integerConstants.end(); it++) 1527 { 1528 String& intConst = (*it).asString; 1529 1530 StringStream s; 1531 s << "#define INT_CONST " << intConst << std::endl; 1532 1533 String decl = 1534 buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("INT_CONST")), 1535 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1536 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1537 setTemplateParam("UNIFORM_DECL", s.str() + decl); 1538 1539 s.reset(); 1540 s << buildAccess(getDefaultUniformName()) << ";\n"; 1541 setTemplateParam("UNIFORM_ACCESS", s.str()); 1542 updateTemplate(); 1543 1544 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1545 passed &= program->compiledAndLinked(); 1546 if (!passed) 1547 { 1548 return LayoutBindingTestResult(passed, program->getErrorLog()); 1549 } 1550 1551 StringVector list; 1552 const String& u = buildBlockName(getDefaultUniformName()); 1553 if (!u.empty()) 1554 list.push_back(u + "_block"); 1555 else 1556 list.push_back(getDefaultUniformName()); 1557 1558 StringIntMap bindingPoints = program->getBindingPoints(list); 1559 passed &= ((*it).asInt == bindingPoints[list[0]]); 1560 if (!passed) 1561 { 1562 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"), 1563 bindingPoints[list[0]], (*it).asInt)); 1564 } 1565 } 1566 1567 return true; 1568 } 1569 1570 //== test integer constant expressions 1571 //== only for GL 1572 LayoutBindingTestResult LayoutBindingBaseCase::binding_integer_constant_expression() 1573 { 1574 bool passed = true; 1575 if (getGLSLVersion() == glu::GLSL_VERSION_310_ES) 1576 return LayoutBindingTestResult(passed, String(), true); 1577 1578 return LayoutBindingTestResult(passed, String(), true); 1579 } 1580 1581 //== test different sized arrays 1582 LayoutBindingTestResult LayoutBindingBaseCase::binding_array_size(void) 1583 { 1584 bool passed = true; 1585 1586 std::vector<int> arraySizes = makeSparseRange(maxArraySize(), 1); 1587 for (std::vector<int>::iterator it = arraySizes.begin(); it < arraySizes.end(); it++) 1588 { 1589 int arraySize = *it; 1590 String decl = 1591 buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings() - arraySize - 1), 1592 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1593 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize)); 1594 setTemplateParam("UNIFORM_DECL", decl); 1595 1596 StringStream s; 1597 for (int idx = 0; idx < arraySize; idx++) 1598 { 1599 s << (idx ? " + " : "") << buildAccess(buildArrayAccess(0, idx)); 1600 } 1601 s << ";\n"; 1602 setTemplateParam("UNIFORM_ACCESS", s.str()); 1603 updateTemplate(); 1604 1605 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1606 passed &= program->compiledAndLinked(); 1607 if (!passed) 1608 { 1609 return LayoutBindingTestResult(passed, program->getErrorLog()); 1610 } 1611 1612 StringVector list; 1613 for (int idx = 0; idx < arraySize; idx++) 1614 { 1615 std::ostringstream texUnitStr; 1616 texUnitStr << getDefaultUniformName(); 1617 const String& u = buildBlockName(getDefaultUniformName()); 1618 if (!u.empty()) 1619 texUnitStr << "_block"; 1620 texUnitStr << buildArray(idx); 1621 list.push_back(texUnitStr.str()); 1622 } 1623 1624 StringIntMap bindingPoints = program->getBindingPoints(list); 1625 for (int idx = 0; idx < arraySize; idx++) 1626 { 1627 passed &= (((maxBindings() - arraySize - 1) + idx) == bindingPoints[list[idx]]); 1628 if (!passed) 1629 { 1630 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"), 1631 bindingPoints[list[idx]], 1632 (maxBindings() - arraySize - 1) + idx)); 1633 } 1634 } 1635 } 1636 1637 return LayoutBindingTestResult(passed, String()); 1638 } 1639 1640 //== verify first element takes binding point specified in binding and 1641 //== subsequent entries take the next consecutive units 1642 LayoutBindingTestResult LayoutBindingBaseCase::binding_array_implicit(void) 1643 { 1644 bool passed = true; 1645 1646 std::vector<int> bindings = makeSparseRange(maxBindings(), 0); 1647 for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++) 1648 { 1649 int baseBindingPoint = *it; 1650 int arraySize = std::min(maxBindings() - baseBindingPoint, 4); 1651 1652 String decl = 1653 buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint), 1654 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1655 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize)); 1656 setTemplateParam("UNIFORM_DECL", decl); 1657 1658 StringStream s; 1659 for (int idx = 0; idx < arraySize; idx++) 1660 { 1661 s << (idx ? " + " : "") << buildAccess(buildArrayAccess(0, idx)); 1662 } 1663 s << ";\n"; 1664 setTemplateParam("UNIFORM_ACCESS", s.str()); 1665 updateTemplate(); 1666 1667 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1668 passed &= program->compiledAndLinked(); 1669 if (!passed) 1670 { 1671 return LayoutBindingTestResult(passed, program->getErrorLog()); 1672 } 1673 StringVector list; 1674 for (int idx = 0; idx < arraySize; idx++) 1675 { 1676 std::ostringstream texUnitStr; 1677 texUnitStr << getDefaultUniformName(); 1678 const String& u = buildBlockName(getDefaultUniformName()); 1679 if (!u.empty()) 1680 texUnitStr << "_block"; 1681 texUnitStr << buildArray(idx); 1682 list.push_back(texUnitStr.str()); 1683 } 1684 1685 StringIntMap bindingPoints = program->getBindingPoints(list); 1686 for (int idx = 0; idx < arraySize; idx++) 1687 { 1688 passed &= ((baseBindingPoint + idx) == bindingPoints[list[idx]]); 1689 if (!passed) 1690 { 1691 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"), 1692 bindingPoints[list[idx]], (baseBindingPoint + idx))); 1693 } 1694 } 1695 } 1696 return LayoutBindingTestResult(passed, String()); 1697 } 1698 1699 //== multiple arrays :verify first element takes binding point specified in binding and 1700 //== subsequent entries take the next consecutive units 1701 LayoutBindingTestResult LayoutBindingBaseCase::binding_array_multiple(void) 1702 { 1703 bool passed = true; 1704 1705 // two arrays, limit max. binding to one 1706 std::vector<int> bindings = makeSparseRange(maxBindings() - 2, 0); 1707 for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++) 1708 { 1709 int baseBindingPoint = *it; 1710 1711 // total distance from current binding point to end of binding range 1712 // split over two arrays, making sure that the array sizes don't 1713 // exceed max. array sizes per stage 1714 int arraySize = (maxBindings() - baseBindingPoint - 1) / 2; 1715 arraySize = std::min(arraySize, maxArraySize() / 2); 1716 1717 StringStream s; 1718 String decl = 1719 buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint), 1720 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1721 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize)); 1722 String another_decl = 1723 buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint), 1724 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName(1)), 1725 buildBlock(getDefaultUniformName(1)), getDefaultUniformName(1), buildArray(arraySize)); 1726 setTemplateParam("UNIFORM_DECL", decl + another_decl); 1727 1728 s.reset(); 1729 for (int uniform = 0; uniform < 2; uniform++) 1730 { 1731 for (int idx = 0; idx < arraySize; idx++) 1732 { 1733 s << ((idx | uniform) ? " + " : "") << buildAccess(buildArrayAccess(uniform, idx)); 1734 } 1735 } 1736 s << ";\n"; 1737 setTemplateParam("UNIFORM_ACCESS", s.str()); 1738 updateTemplate(); 1739 1740 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1741 passed &= program->compiledAndLinked(); 1742 if (!passed) 1743 { 1744 return LayoutBindingTestResult(passed, program->getErrorLog()); 1745 } 1746 1747 StringVector list; 1748 for (int uniform = 0; uniform < 2; uniform++) 1749 { 1750 list.clear(); 1751 for (int idx = 0; idx < arraySize; idx++) 1752 { 1753 std::ostringstream texUnitStr; 1754 texUnitStr << getDefaultUniformName(uniform); 1755 const String& u = buildBlockName(getDefaultUniformName(uniform)); 1756 if (!u.empty()) 1757 texUnitStr << "_block"; 1758 texUnitStr << buildArray(idx); 1759 list.push_back(texUnitStr.str()); 1760 } 1761 1762 StringIntMap bindingPoints = program->getBindingPoints(list); 1763 for (int idx = 0; idx < arraySize; idx++) 1764 { 1765 passed &= ((baseBindingPoint + idx) == bindingPoints[list[idx]]); 1766 if (!passed) 1767 { 1768 return LayoutBindingTestResult(passed, 1769 generateLog(String("binding point did not match default"), 1770 bindingPoints[list[idx]], (baseBindingPoint + idx))); 1771 } 1772 } 1773 } 1774 } 1775 return LayoutBindingTestResult(passed, String()); 1776 } 1777 1778 //== verify that explicit binding point can be changed via API 1779 LayoutBindingTestResult LayoutBindingBaseCase::binding_api_update(void) 1780 { 1781 bool passed = true; 1782 1783 String decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(1), 1784 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1785 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1786 setTemplateParam("UNIFORM_DECL", decl); 1787 1788 StringStream s; 1789 s << buildAccess(getDefaultUniformName()) << ";\n"; 1790 setTemplateParam("UNIFORM_ACCESS", s.str()); 1791 updateTemplate(); 1792 1793 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1794 passed &= program->compiledAndLinked(); 1795 if (!passed) 1796 { 1797 return LayoutBindingTestResult(passed, program->getErrorLog()); 1798 } 1799 1800 StringVector list; 1801 const String& u = buildBlockName(getDefaultUniformName()); 1802 if (!u.empty()) 1803 list.push_back(u + "_block"); 1804 else 1805 list.push_back(getDefaultUniformName()); 1806 1807 StringIntMap bindingPoints = program->getBindingPoints(list); 1808 1809 gl().useProgram(program->getProgram()); 1810 program->setBindingPoints(list, maxBindings() - 1); 1811 gl().useProgram(0); 1812 1813 bindingPoints = program->getBindingPoints(list); 1814 1815 passed &= bindingPoints[list[0]] == (maxBindings() - 1); 1816 if (!passed) 1817 { 1818 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"), 1819 bindingPoints[list[0]], maxBindings() - 1)); 1820 } 1821 1822 return LayoutBindingTestResult(passed, String()); 1823 } 1824 1825 LayoutBindingTestResult LayoutBindingBaseCase::binding_compilation_errors(void) 1826 { 1827 bool passed = true; 1828 String decl; 1829 1830 // verify "uniform float var;" doesn't compile 1831 { 1832 StringStream s; 1833 s << getTestParameters().vector_type << "(0.0);"; 1834 1835 setTemplateParam("UNIFORM_ACCESS", s.str()); 1836 s.reset(); 1837 s << "layout(binding=0) " 1838 << "uniform float tex0;"; 1839 setTemplateParam("UNIFORM_DECL", s.str()); 1840 updateTemplate(); 1841 1842 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1843 passed &= !program->compiledAndLinked(); 1844 if (!passed) 1845 { 1846 return LayoutBindingTestResult(passed, program->getErrorLog(true)); 1847 } 1848 } 1849 1850 // verify that non-constant integer expression in binding fails 1851 { 1852 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("0.0")), 1853 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1854 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1855 setTemplateParam("UNIFORM_DECL", decl); 1856 updateTemplate(); 1857 1858 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1859 passed &= !program->compiledAndLinked(); 1860 if (!passed) 1861 { 1862 return LayoutBindingTestResult(passed, program->getErrorLog(true)); 1863 } 1864 } 1865 1866 { 1867 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("-1")), 1868 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1869 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1870 setTemplateParam("UNIFORM_DECL", decl); 1871 updateTemplate(); 1872 1873 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1874 passed &= !program->compiledAndLinked(); 1875 if (!passed) 1876 { 1877 return LayoutBindingTestResult(passed, program->getErrorLog(true)); 1878 } 1879 } 1880 { 1881 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings()), 1882 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1883 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1884 setTemplateParam("UNIFORM_DECL", decl); 1885 updateTemplate(); 1886 1887 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1888 passed &= !program->compiledAndLinked(); 1889 if (!passed) 1890 { 1891 return LayoutBindingTestResult(passed, program->getErrorLog(true)); 1892 } 1893 } 1894 { 1895 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings()), 1896 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1897 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1898 setTemplateParam("UNIFORM_DECL", decl); 1899 1900 StringStream s; 1901 s << "vec4(0.0);\n"; 1902 setTemplateParam("UNIFORM_ACCESS", s.str()); 1903 updateTemplate(); 1904 1905 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1906 passed &= !program->compiledAndLinked(); 1907 if (!passed) 1908 { 1909 return LayoutBindingTestResult(passed, program->getErrorLog(true)); 1910 } 1911 } 1912 return LayoutBindingTestResult(passed, String()); 1913 } 1914 1915 LayoutBindingTestResult LayoutBindingBaseCase::binding_link_errors(void) 1916 { 1917 bool passed = true; 1918 1919 // same sampler with different binding in two compilation units 1920 if (isStage(VertexShader)) 1921 { 1922 String decl = 1923 buildUniformDecl(String(getTestParameters().keyword), buildLayout(1), 1924 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1925 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1926 setTemplateParam(VertexShader, "UNIFORM_DECL", decl); 1927 1928 setTemplateParam(VertexShader, "OUT_ASSIGNMENT", String("fragColor =")); 1929 1930 StringStream s; 1931 s << buildAccess(getDefaultUniformName()) << ";\n"; 1932 setTemplateParam(VertexShader, "UNIFORM_ACCESS", s.str()); 1933 updateTemplate(VertexShader); 1934 1935 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(3), 1936 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 1937 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 1938 setTemplateParam(FragmentShader, "UNIFORM_DECL", decl); 1939 1940 s.reset(); 1941 s << "fragColor + " << buildAccess(getDefaultUniformName()) << ";\n"; 1942 setTemplateParam(FragmentShader, "UNIFORM_ACCESS", s.str()); 1943 updateTemplate(FragmentShader); 1944 1945 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 1946 passed = !program->compiledAndLinked(); 1947 if (!passed) 1948 { 1949 return LayoutBindingTestResult(passed, program->getErrorLog(true)); 1950 } 1951 } 1952 1953 return LayoutBindingTestResult(passed, String()); 1954 } 1955 1956 // this subtest is generically empty. Overwritten in test cases as needed. 1957 LayoutBindingTestResult LayoutBindingBaseCase::binding_examples(void) 1958 { 1959 return true; 1960 } 1961 1962 // just for image and atomic counter cases 1963 LayoutBindingTestResult LayoutBindingBaseCase::binding_mixed_order(void) 1964 { 1965 return true; 1966 } 1967 1968 //========================================================================= 1969 // test case Sampler layout binding 1970 //========================================================================= 1971 class SamplerLayoutBindingCase : public LayoutBindingBaseCase 1972 1973 { 1974 public: 1975 SamplerLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage, 1976 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion); 1977 ~SamplerLayoutBindingCase(void); 1978 1979 private: 1980 /*virtual*/ 1981 LayoutBindingProgram* createProgram() 1982 { 1983 return new LayoutBindingProgram(*this); 1984 } 1985 1986 /*virtual*/ 1987 String getDefaultUniformName(int idx = 0) 1988 { 1989 StringStream s; 1990 1991 s << "sampler" << idx; 1992 return s.str(); 1993 } 1994 1995 /*virtual*/ 1996 String buildLayout(const String& binding) 1997 { 1998 std::ostringstream s; 1999 if (!binding.empty()) 2000 s << "layout(binding=" << binding << ") "; 2001 return s.str(); 2002 } 2003 2004 virtual int maxBindings() 2005 { 2006 int units = 0; 2007 gl().getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &units); 2008 return units; 2009 } 2010 2011 // return max. array size allowed 2012 virtual int maxArraySize() 2013 { 2014 int units = 0; 2015 2016 switch (getStage()) 2017 { 2018 case VertexShader: 2019 gl().getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &units); 2020 break; 2021 case FragmentShader: 2022 gl().getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units); 2023 break; 2024 case ComputeShader: 2025 gl().getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &units); 2026 break; 2027 default: 2028 DE_ASSERT(0); 2029 break; 2030 } 2031 2032 return units; 2033 } 2034 }; 2035 2036 SamplerLayoutBindingCase::SamplerLayoutBindingCase(Context& context, const char* name, const char* description, 2037 StageType stage, LayoutBindingParameters& samplerType, 2038 glu::GLSLVersion glslVersion) 2039 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion) 2040 { 2041 } 2042 2043 SamplerLayoutBindingCase::~SamplerLayoutBindingCase(void) 2044 { 2045 } 2046 2047 //========================================================================= 2048 // test case Image layout binding 2049 //========================================================================= 2050 class ImageLayoutBindingCase : public LayoutBindingBaseCase 2051 2052 { 2053 public: 2054 ImageLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage, 2055 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion); 2056 ~ImageLayoutBindingCase(void); 2057 2058 private: 2059 class ImageLayoutBindingProgram : public LayoutBindingProgram 2060 { 2061 public: 2062 ImageLayoutBindingProgram(IProgramContextSupplier& contextSupplier) : LayoutBindingProgram(contextSupplier) 2063 { 2064 } 2065 }; 2066 2067 private: 2068 // IProgramContextSupplier 2069 /*virtual*/ 2070 LayoutBindingProgram* createProgram() 2071 { 2072 return new ImageLayoutBindingProgram(*this); 2073 } 2074 2075 private: 2076 /*virtual*/ 2077 String getDefaultUniformName(int idx = 0) 2078 { 2079 StringStream s; 2080 s << "image" << idx; 2081 return s.str(); 2082 } 2083 2084 /*virtual*/ 2085 String buildLayout(const String& binding) 2086 { 2087 std::ostringstream s; 2088 if (!binding.empty()) 2089 s << "layout(binding=" << binding << ", rgba8) readonly "; 2090 else 2091 s << "layout(rgba8) readonly "; 2092 return s.str(); 2093 } 2094 2095 /*virtual*/ 2096 int maxBindings() 2097 { 2098 int units = 0; 2099 gl().getIntegerv(GL_MAX_IMAGE_UNITS, &units); 2100 return units; 2101 } 2102 2103 /*virtual*/ 2104 int maxArraySize() 2105 { 2106 int units = 0; 2107 switch (getStage()) 2108 { 2109 case VertexShader: 2110 gl().getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &units); 2111 break; 2112 case FragmentShader: 2113 gl().getIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &units); 2114 break; 2115 case ComputeShader: 2116 gl().getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &units); 2117 break; 2118 default: 2119 DE_ASSERT(0); 2120 break; 2121 } 2122 return units; 2123 } 2124 2125 private: 2126 //virtual LayoutBindingTestResult binding_basic_default (void); 2127 //virtual LayoutBindingTestResult binding_basic_explicit (void); 2128 //virtual LayoutBindingTestResult binding_basic_multiple (void); 2129 //virtual LayoutBindingTestResult binding_basic_render (void); 2130 //virtual LayoutBindingTestResult binding_integer_constant (void); 2131 //virtual LayoutBindingTestResult binding_integer_constant_expression (void); 2132 //virtual LayoutBindingTestResult binding_array_size (void); 2133 //virtual LayoutBindingTestResult binding_array_implicit (void); 2134 //virtual LayoutBindingTestResult binding_array_multiple (void); 2135 /*virtual*/ 2136 LayoutBindingTestResult binding_api_update(void) 2137 { 2138 // only for GL 2139 if (getGLSLVersion() == glu::GLSL_VERSION_310_ES) 2140 return LayoutBindingTestResult(true, String(), true); 2141 2142 return LayoutBindingBaseCase::binding_api_update(); 2143 } 2144 //virtual LayoutBindingTestResult binding_compilation_errors (void); 2145 //virtual LayoutBindingTestResult binding_link_errors (void); 2146 //virtual LayoutBindingTestResult binding_link_examples (void); 2147 /*virtual*/ 2148 LayoutBindingTestResult binding_mixed_order(void) 2149 { 2150 bool passed = true; 2151 2152 { 2153 StringStream s; 2154 s << buildAccess(getDefaultUniformName()) << ";\n"; 2155 setTemplateParam("UNIFORM_ACCESS", s.str()); 2156 2157 String decl = 2158 buildUniformDecl(String(getTestParameters().keyword), String("layout(binding=0, rgba8) readonly"), 2159 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 2160 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 2161 setTemplateParam("UNIFORM_DECL", decl); 2162 updateTemplate(); 2163 2164 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2165 passed &= program->compiledAndLinked(); 2166 if (!passed) 2167 { 2168 return LayoutBindingTestResult(passed, program->getErrorLog()); 2169 } 2170 } 2171 { 2172 String decl = 2173 buildUniformDecl(String(getTestParameters().keyword), String("layout(r32f, binding=0) readonly"), 2174 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 2175 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 2176 setTemplateParam("UNIFORM_DECL", decl); 2177 updateTemplate(); 2178 2179 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2180 passed &= program->compiledAndLinked(); 2181 if (!passed) 2182 { 2183 return LayoutBindingTestResult(passed, program->getErrorLog()); 2184 } 2185 } 2186 2187 return true; 2188 } 2189 }; 2190 2191 ImageLayoutBindingCase::ImageLayoutBindingCase(Context& context, const char* name, const char* description, 2192 StageType stage, LayoutBindingParameters& samplerType, 2193 glu::GLSLVersion glslVersion) 2194 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion) 2195 { 2196 } 2197 2198 ImageLayoutBindingCase::~ImageLayoutBindingCase(void) 2199 { 2200 } 2201 2202 //========================================================================= 2203 // test case Atomic counter binding 2204 //========================================================================= 2205 class AtomicCounterLayoutBindingCase : public LayoutBindingBaseCase 2206 2207 { 2208 public: 2209 AtomicCounterLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage, 2210 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion); 2211 ~AtomicCounterLayoutBindingCase(void) 2212 { 2213 } 2214 2215 private: 2216 class AtomicCounterLayoutBindingProgram : public LayoutBindingProgram 2217 { 2218 public: 2219 AtomicCounterLayoutBindingProgram(IProgramContextSupplier& contextSupplier) 2220 : LayoutBindingProgram(contextSupplier) 2221 { 2222 } 2223 2224 private: 2225 /*virtual*/ 2226 StringIntMap getBindingPoints(StringVector args) const 2227 { 2228 StringIntMap bindingPoints; 2229 2230 for (StringVector::iterator it = args.begin(); it != args.end(); it++) 2231 { 2232 glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM, (*it).c_str()); 2233 if (idx != GL_INVALID_INDEX) 2234 { 2235 glw::GLenum param = GL_ATOMIC_COUNTER_BUFFER_INDEX; 2236 glw::GLint atomic_counter_buffer_idx = -1; 2237 gl().getProgramResourceiv(getProgram(), GL_UNIFORM, idx, 1, ¶m, 1, NULL, 2238 &atomic_counter_buffer_idx); 2239 bool hasNoError = (GL_NO_ERROR == gl().getError()) && (-1 != atomic_counter_buffer_idx); 2240 if (!hasNoError) 2241 continue; 2242 2243 param = GL_BUFFER_BINDING; 2244 glw::GLint value = -1; 2245 gl().getProgramResourceiv(getProgram(), GL_ATOMIC_COUNTER_BUFFER, atomic_counter_buffer_idx, 1, 2246 ¶m, 1, NULL, &value); 2247 hasNoError = (GL_NO_ERROR == gl().getError()) && (-1 != value); 2248 if (!hasNoError) 2249 continue; 2250 2251 bindingPoints[*it] = value; 2252 } 2253 } 2254 return bindingPoints; 2255 } 2256 2257 /*virtual*/ 2258 StringIntMap getOffsets(StringVector args) const 2259 { 2260 StringIntMap bindingPoints; 2261 2262 for (StringVector::iterator it = args.begin(); it != args.end(); it++) 2263 { 2264 glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM, (*it).c_str()); 2265 if (idx != GL_INVALID_INDEX) 2266 { 2267 glw::GLenum param = GL_OFFSET; 2268 glw::GLint value = -1; 2269 gl().getProgramResourceiv(getProgram(), GL_UNIFORM, idx, 1, ¶m, 1, NULL, &value); 2270 bool hasNoError = (GL_NO_ERROR == gl().getError()); 2271 if (hasNoError) 2272 { 2273 bindingPoints[*it] = value; 2274 } 2275 } 2276 } 2277 return bindingPoints; 2278 } 2279 }; 2280 2281 private: 2282 // IProgramContextSupplier 2283 /*virtual*/ 2284 LayoutBindingProgram* createProgram() 2285 { 2286 return new AtomicCounterLayoutBindingProgram(*this); 2287 } 2288 2289 private: 2290 /*virtual*/ 2291 String getDefaultUniformName(int idx = 0) 2292 { 2293 StringStream s; 2294 s << "atomic" << idx; 2295 return s.str(); 2296 } 2297 2298 /*virtual*/ 2299 String buildAccess(const String& var) 2300 { 2301 std::ostringstream s; 2302 s << "vec4(float(atomicCounter(" << var << ")), 1.0, 0.0, 1.0)"; 2303 return s.str(); 2304 } 2305 2306 int maxBindings() 2307 { 2308 int units = 0; 2309 gl().getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &units); 2310 return units; 2311 } 2312 2313 // return max. array size allowed 2314 int maxArraySize() 2315 { 2316 int units = 0; 2317 switch (getStage()) 2318 { 2319 case FragmentShader: 2320 gl().getIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &units); 2321 break; 2322 case VertexShader: 2323 gl().getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &units); 2324 break; 2325 case ComputeShader: 2326 gl().getIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &units); 2327 break; 2328 default: 2329 DE_ASSERT(0); 2330 break; 2331 } 2332 return units; 2333 } 2334 2335 //========================================================================= 2336 // sub-tests overrides 2337 //========================================================================= 2338 private: 2339 LayoutBindingTestResult binding_basic_default(void) 2340 { 2341 return true; 2342 } 2343 //virtual LayoutBindingTestResult binding_basic_explicit (void); 2344 //virtual LayoutBindingTestResult binding_basic_multiple (void); 2345 LayoutBindingTestResult binding_basic_render(void) 2346 { 2347 return true; 2348 } 2349 //virtual LayoutBindingTestResult binding_integer_constant (void); 2350 /*virtual*/ 2351 LayoutBindingTestResult binding_array_size(void) 2352 { 2353 bool passed = true; 2354 2355 //== test different sized arrays 2356 std::vector<int> arraySizes = makeSparseRange(maxArraySize(), 1); 2357 for (std::vector<int>::iterator it = arraySizes.begin(); it < arraySizes.end(); it++) 2358 { 2359 int arraySize = *it; 2360 StringStream s; 2361 s << "[" << arraySize << "]"; 2362 String decl = 2363 buildUniformDecl(String(getTestParameters().keyword), buildLayout(0), 2364 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 2365 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize)); 2366 setTemplateParam("UNIFORM_DECL", decl); 2367 2368 s.reset(); 2369 // build a function that accesses the whole array 2370 s << "float accumulate(void)\n"; 2371 s << "{\n"; 2372 s << " float acc = 0.0;\n"; 2373 s << " for(int i=0; i < " << arraySize << " ; i++)\n"; 2374 s << " acc = float(atomicCounter(" << getDefaultUniformName() << "[i]));\n"; 2375 s << " return acc;\n"; 2376 s << "}\n"; 2377 2378 setTemplateParam("OPTIONAL_FUNCTION_BLOCK", s.str()); 2379 2380 s.reset(); 2381 s << "vec4(accumulate(), 1.0, 0.0, 1.0);\n"; 2382 setTemplateParam("UNIFORM_ACCESS", s.str()); 2383 updateTemplate(); 2384 2385 setTemplateParam("OPTIONAL_FUNCTION_BLOCK", String()); 2386 2387 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2388 passed &= program->compiledAndLinked(); 2389 if (!passed) 2390 { 2391 return LayoutBindingTestResult(passed, program->getErrorLog()); 2392 } 2393 2394 StringVector list; 2395 std::ostringstream texUnitStr; 2396 texUnitStr << getDefaultUniformName() << "[0]"; 2397 list.push_back(texUnitStr.str()); 2398 2399 StringIntMap bindingPoints = program->getBindingPoints(list); 2400 passed &= (0 == bindingPoints[list[0]]); 2401 if (!passed) 2402 { 2403 return LayoutBindingTestResult( 2404 passed, generateLog(String("binding point did not match default"), bindingPoints[list[0]], 1)); 2405 } 2406 } 2407 2408 return LayoutBindingTestResult(passed, String()); 2409 } 2410 LayoutBindingTestResult binding_array_implicit(void) 2411 { 2412 return true; 2413 } 2414 LayoutBindingTestResult binding_array_multiple(void) 2415 { 2416 return true; 2417 } 2418 LayoutBindingTestResult binding_api_update(void) 2419 { 2420 return true; 2421 } 2422 //virtual LayoutBindingTestResult binding_compilation_errors (void); 2423 //virtual LayoutBindingTestResult binding_link_errors (void); 2424 2425 LayoutBindingTestResult binding_examples_many_bindings(void) 2426 { 2427 int max_bindings = 0; 2428 2429 if (isStage(VertexShader)) 2430 { 2431 gl().getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &max_bindings); 2432 } 2433 else if (isStage(FragmentShader)) 2434 { 2435 gl().getIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &max_bindings); 2436 } 2437 else 2438 { 2439 gl().getIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &max_bindings); 2440 } 2441 2442 // example 1 in atomic counter CTS spec ac-binding-examples 2443 { 2444 bool passed = true; 2445 StringStream s; 2446 s << buildAccess(getDefaultUniformName()) << ";\n"; 2447 setTemplateParam("UNIFORM_ACCESS", s.str()); 2448 2449 s.reset(); 2450 s << "layout(binding=2, offset=4) uniform atomic_uint;\n"; 2451 s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2452 setTemplateParam("UNIFORM_DECL", s.str()); 2453 updateTemplate(); 2454 2455 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2456 passed &= program->compiledAndLinked(); 2457 if (!passed) 2458 { 2459 return LayoutBindingTestResult(passed, program->getErrorLog()); 2460 } 2461 2462 StringVector list; 2463 list.push_back(getDefaultUniformName()); 2464 2465 StringIntMap offsets = program->getOffsets(list); 2466 passed &= (4 == offsets[list[0]]); 2467 if (!passed) 2468 { 2469 return LayoutBindingTestResult( 2470 passed, generateLog(String("offset did not match requested"), offsets[list[0]], 1)); 2471 } 2472 } 2473 2474 // example 2 in atomic counter CTS spec ac-binding-examples 2475 if (max_bindings >= 2) 2476 { 2477 bool passed = true; 2478 StringStream s; 2479 s << buildAccess(getDefaultUniformName()) << ";\n"; 2480 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n"; 2481 s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n"; 2482 s << "+" << buildAccess(getDefaultUniformName(3)) << ";\n"; 2483 setTemplateParam("UNIFORM_ACCESS", s.str()); 2484 2485 s.reset(); 2486 s << "layout(binding=3, offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2487 s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName(1) << ";\n"; 2488 s << "layout(binding=3) uniform atomic_uint " << getDefaultUniformName(2) << ";\n"; 2489 s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName(3) << ";\n"; 2490 setTemplateParam("UNIFORM_DECL", s.str()); 2491 updateTemplate(); 2492 2493 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2494 passed &= program->compiledAndLinked(); 2495 if (!passed) 2496 { 2497 return LayoutBindingTestResult(passed, program->getErrorLog()); 2498 } 2499 2500 StringVector list; 2501 list.push_back(getDefaultUniformName()); 2502 list.push_back(getDefaultUniformName(1)); 2503 list.push_back(getDefaultUniformName(2)); 2504 list.push_back(getDefaultUniformName(3)); 2505 2506 StringIntMap offsets = program->getOffsets(list); 2507 IntVector expected; 2508 expected.insert(expected.end(), 4); 2509 expected.insert(expected.end(), 0); 2510 expected.insert(expected.end(), 8); 2511 expected.insert(expected.end(), 4); 2512 for (unsigned int idx = 0; idx < list.size(); idx++) 2513 { 2514 passed &= (expected[idx] == offsets[list[idx]]); 2515 if (!passed) 2516 { 2517 return LayoutBindingTestResult( 2518 passed, generateLog(String("offset of") + String(list[idx]) + String("did not match requested"), 2519 offsets[list[idx]], 4)); 2520 } 2521 } 2522 } 2523 2524 // example 3 in atomic counter CTS spec ac-binding-examples 2525 { 2526 bool passed = true; 2527 StringStream s; 2528 s << buildAccess(getDefaultUniformName()) << ";\n"; 2529 setTemplateParam("UNIFORM_ACCESS", s.str()); 2530 2531 s.reset(); 2532 s << "layout(binding=2, offset=4) uniform atomic_uint;\n"; 2533 s << "layout(offset=8) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2534 setTemplateParam("UNIFORM_DECL", s.str()); 2535 updateTemplate(); 2536 2537 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2538 passed &= program->compiledAndLinked(); 2539 if (passed) 2540 { 2541 return LayoutBindingTestResult(!passed, String("should not compile")); 2542 } 2543 } 2544 2545 // example 4 in atomic counter CTS spec ac-binding-examples 2546 { 2547 bool passed = true; 2548 StringStream s; 2549 s << buildAccess(getDefaultUniformName()) << ";\n"; 2550 setTemplateParam("UNIFORM_ACCESS", s.str()); 2551 2552 s.reset(); 2553 s << "layout(offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2554 setTemplateParam("UNIFORM_DECL", s.str()); 2555 updateTemplate(); 2556 2557 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2558 passed &= program->compiledAndLinked(); 2559 if (passed) 2560 { 2561 return LayoutBindingTestResult(!passed, String("should not compile")); 2562 } 2563 } 2564 2565 // example 5 in atomic counter CTS spec ac-binding-examples 2566 // first check working example, then amend it with an error 2567 if (max_bindings >= 2) 2568 { 2569 for (int pass = 0; pass < 2; pass++) 2570 { 2571 bool passed = true; 2572 2573 StringStream s; 2574 s << buildAccess(getDefaultUniformName()) << ";\n"; 2575 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n"; 2576 if (pass) 2577 s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n"; 2578 setTemplateParam("UNIFORM_ACCESS", s.str()); 2579 2580 s.reset(); 2581 s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2582 s << "layout(binding=2, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n"; 2583 if (pass) 2584 s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName(2) << ";\n"; 2585 setTemplateParam("UNIFORM_DECL", s.str()); 2586 updateTemplate(); 2587 2588 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2589 passed &= program->compiledAndLinked(); 2590 if (pass != 0) 2591 { 2592 if (passed) 2593 { 2594 return LayoutBindingTestResult(passed, program->getErrorLog()); 2595 } 2596 } 2597 else 2598 { 2599 if (!passed) 2600 { 2601 return LayoutBindingTestResult(passed, String("should not compile")); 2602 } 2603 } 2604 } 2605 } 2606 2607 // example 6 in atomic counter CTS spec ac-binding-examples 2608 // first check working example, then amend it with an error 2609 if (max_bindings >= 2) 2610 { 2611 for (int pass = 0; pass < 2; pass++) 2612 { 2613 bool passed = true; 2614 2615 StringStream s; 2616 s << buildAccess(getDefaultUniformName()) << ";\n"; 2617 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n"; 2618 if (pass) 2619 s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n"; 2620 setTemplateParam("UNIFORM_ACCESS", s.str()); 2621 2622 s.reset(); 2623 s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2624 s << "layout(binding=2, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n"; 2625 if (pass) 2626 s << "layout(binding=1, offset=2) uniform atomic_uint " << getDefaultUniformName(2) << ";\n"; 2627 setTemplateParam("UNIFORM_DECL", s.str()); 2628 updateTemplate(); 2629 2630 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2631 passed &= program->compiledAndLinked(); 2632 if (pass != 0) 2633 { 2634 if (passed) 2635 { 2636 return LayoutBindingTestResult(passed, program->getErrorLog()); 2637 } 2638 } 2639 else 2640 { 2641 if (!passed) 2642 { 2643 return LayoutBindingTestResult(passed, String("should not compile")); 2644 } 2645 } 2646 } 2647 } 2648 2649 return true; 2650 } 2651 2652 LayoutBindingTestResult binding_examples_one_binding(void) 2653 { 2654 // example 1 in atomic counter CTS spec ac-binding-examples 2655 { 2656 bool passed = true; 2657 StringStream s; 2658 s << buildAccess(getDefaultUniformName()) << ";\n"; 2659 setTemplateParam("UNIFORM_ACCESS", s.str()); 2660 2661 s.reset(); 2662 s << "layout(binding=0, offset=4) uniform atomic_uint;\n"; 2663 s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2664 setTemplateParam("UNIFORM_DECL", s.str()); 2665 updateTemplate(); 2666 2667 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2668 passed &= program->compiledAndLinked(); 2669 if (!passed) 2670 { 2671 return LayoutBindingTestResult(passed, program->getErrorLog()); 2672 } 2673 2674 StringVector list; 2675 list.push_back(getDefaultUniformName()); 2676 2677 StringIntMap offsets = program->getOffsets(list); 2678 passed &= (4 == offsets[list[0]]); 2679 if (!passed) 2680 { 2681 return LayoutBindingTestResult( 2682 passed, generateLog(String("offset did not match requested"), offsets[list[0]], 1)); 2683 } 2684 } 2685 2686 // example 2 in atomic counter CTS spec ac-binding-examples 2687 { 2688 bool passed = true; 2689 StringStream s; 2690 s << buildAccess(getDefaultUniformName()) << ";\n"; 2691 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n"; 2692 s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n"; 2693 s << "+" << buildAccess(getDefaultUniformName(3)) << ";\n"; 2694 setTemplateParam("UNIFORM_ACCESS", s.str()); 2695 2696 s.reset(); 2697 s << "layout(binding=0, offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2698 s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n"; 2699 s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(2) << ";\n"; 2700 s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(3) << ";\n"; 2701 setTemplateParam("UNIFORM_DECL", s.str()); 2702 updateTemplate(); 2703 2704 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2705 passed &= program->compiledAndLinked(); 2706 if (!passed) 2707 { 2708 return LayoutBindingTestResult(passed, program->getErrorLog()); 2709 } 2710 2711 StringVector list; 2712 list.push_back(getDefaultUniformName()); 2713 list.push_back(getDefaultUniformName(1)); 2714 list.push_back(getDefaultUniformName(2)); 2715 list.push_back(getDefaultUniformName(3)); 2716 2717 StringIntMap offsets = program->getOffsets(list); 2718 IntVector expected; 2719 expected.insert(expected.end(), 4); 2720 expected.insert(expected.end(), 8); 2721 expected.insert(expected.end(), 12); 2722 expected.insert(expected.end(), 16); 2723 for (unsigned int idx = 0; idx < list.size(); idx++) 2724 { 2725 passed &= (expected[idx] == offsets[list[idx]]); 2726 if (!passed) 2727 { 2728 return LayoutBindingTestResult( 2729 passed, generateLog(String("offset of") + String(list[idx]) + String("did not match requested"), 2730 offsets[list[idx]], expected[idx])); 2731 } 2732 } 2733 } 2734 2735 // example 3 in atomic counter CTS spec ac-binding-examples 2736 { 2737 bool passed = true; 2738 StringStream s; 2739 s << buildAccess(getDefaultUniformName()) << ";\n"; 2740 setTemplateParam("UNIFORM_ACCESS", s.str()); 2741 2742 s.reset(); 2743 s << "layout(binding=0, offset=4) uniform atomic_uint;\n"; 2744 s << "layout(offset=8) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2745 setTemplateParam("UNIFORM_DECL", s.str()); 2746 updateTemplate(); 2747 2748 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2749 passed &= program->compiledAndLinked(); 2750 if (passed) 2751 { 2752 return LayoutBindingTestResult(!passed, String("should not compile")); 2753 } 2754 } 2755 2756 // example 4 in atomic counter CTS spec ac-binding-examples 2757 { 2758 bool passed = true; 2759 StringStream s; 2760 s << buildAccess(getDefaultUniformName()) << ";\n"; 2761 setTemplateParam("UNIFORM_ACCESS", s.str()); 2762 2763 s.reset(); 2764 s << "layout(offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2765 setTemplateParam("UNIFORM_DECL", s.str()); 2766 updateTemplate(); 2767 2768 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2769 passed &= program->compiledAndLinked(); 2770 if (passed) 2771 { 2772 return LayoutBindingTestResult(!passed, String("should not compile")); 2773 } 2774 } 2775 2776 // example 5 in atomic counter CTS spec ac-binding-examples 2777 // first check working example, then amend it with an error 2778 for (int pass = 0; pass < 2; pass++) 2779 { 2780 bool passed = true; 2781 2782 StringStream s; 2783 s << buildAccess(getDefaultUniformName()) << ";\n"; 2784 if (pass) 2785 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n"; 2786 setTemplateParam("UNIFORM_ACCESS", s.str()); 2787 2788 s.reset(); 2789 s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2790 if (pass) 2791 s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n"; 2792 setTemplateParam("UNIFORM_DECL", s.str()); 2793 updateTemplate(); 2794 2795 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2796 passed &= program->compiledAndLinked(); 2797 if (pass != 0) 2798 { 2799 if (passed) 2800 { 2801 return LayoutBindingTestResult(passed, program->getErrorLog()); 2802 } 2803 } 2804 else 2805 { 2806 if (!passed) 2807 { 2808 return LayoutBindingTestResult(passed, String("should not compile")); 2809 } 2810 } 2811 } 2812 2813 // example 6 in atomic counter CTS spec ac-binding-examples 2814 // first check working example, then amend it with an error 2815 for (int pass = 0; pass < 2; pass++) 2816 { 2817 bool passed = true; 2818 2819 StringStream s; 2820 s << buildAccess(getDefaultUniformName()) << ";\n"; 2821 if (pass) 2822 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n"; 2823 setTemplateParam("UNIFORM_ACCESS", s.str()); 2824 2825 s.reset(); 2826 s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n"; 2827 if (pass) 2828 s << "layout(binding=0, offset=2) uniform atomic_uint " << getDefaultUniformName(1) << ";\n"; 2829 setTemplateParam("UNIFORM_DECL", s.str()); 2830 updateTemplate(); 2831 2832 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2833 passed &= program->compiledAndLinked(); 2834 if (pass != 0) 2835 { 2836 if (passed) 2837 { 2838 return LayoutBindingTestResult(passed, program->getErrorLog()); 2839 } 2840 } 2841 else 2842 { 2843 if (!passed) 2844 { 2845 return LayoutBindingTestResult(passed, String("should not compile")); 2846 } 2847 } 2848 } 2849 2850 return true; 2851 } 2852 2853 /*virtual*/ 2854 LayoutBindingTestResult binding_examples(void) 2855 { 2856 if (maxBindings() >= 4) 2857 { 2858 return binding_examples_many_bindings(); 2859 } 2860 else 2861 { 2862 return binding_examples_one_binding(); 2863 } 2864 } 2865 2866 /*virtual*/ 2867 LayoutBindingTestResult binding_mixed_order(void) 2868 { 2869 bool passed = true; 2870 2871 { 2872 StringStream s; 2873 s << buildAccess(getDefaultUniformName()) << ";\n"; 2874 setTemplateParam("UNIFORM_ACCESS", s.str()); 2875 2876 String decl = 2877 buildUniformDecl(String(getTestParameters().keyword), String("layout(binding=0, offset=0)"), 2878 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 2879 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 2880 setTemplateParam("UNIFORM_DECL", decl); 2881 updateTemplate(); 2882 2883 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2884 passed &= program->compiledAndLinked(); 2885 if (!passed) 2886 { 2887 return LayoutBindingTestResult(passed, program->getErrorLog()); 2888 } 2889 } 2890 { 2891 String decl = 2892 buildUniformDecl(String(getTestParameters().keyword), String("layout(offset=0, binding=0)"), 2893 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()), 2894 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String()); 2895 setTemplateParam("UNIFORM_DECL", decl); 2896 updateTemplate(); 2897 2898 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this); 2899 passed &= program->compiledAndLinked(); 2900 if (!passed) 2901 { 2902 return LayoutBindingTestResult(passed, program->getErrorLog()); 2903 } 2904 } 2905 2906 return true; 2907 } 2908 }; 2909 2910 AtomicCounterLayoutBindingCase::AtomicCounterLayoutBindingCase(Context& context, const char* name, 2911 const char* description, StageType stage, 2912 LayoutBindingParameters& samplerType, 2913 glu::GLSLVersion glslVersion) 2914 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion) 2915 { 2916 } 2917 2918 //========================================================================= 2919 // test case Uniform blocks binding 2920 //========================================================================= 2921 class UniformBlocksLayoutBindingCase : public LayoutBindingBaseCase 2922 2923 { 2924 public: 2925 UniformBlocksLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage, 2926 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion); 2927 ~UniformBlocksLayoutBindingCase(void); 2928 2929 private: 2930 class UniformBlocksLayoutBindingProgram : public LayoutBindingProgram 2931 { 2932 public: 2933 UniformBlocksLayoutBindingProgram(IProgramContextSupplier& contextSupplier) 2934 : LayoutBindingProgram(contextSupplier) 2935 { 2936 } 2937 2938 ~UniformBlocksLayoutBindingProgram() 2939 { 2940 } 2941 2942 private: 2943 /*virtual*/ 2944 StringIntMap getBindingPoints(StringVector args) const 2945 { 2946 StringIntMap bindingPoints; 2947 2948 for (StringVector::iterator it = args.begin(); it != args.end(); it++) 2949 { 2950 glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM_BLOCK, (*it).c_str()); 2951 if (idx != glw::GLuint(-1)) 2952 { 2953 glw::GLenum param = GL_BUFFER_BINDING; 2954 glw::GLint value = -1; 2955 gl().getProgramResourceiv(getProgram(), GL_UNIFORM_BLOCK, idx, 1, ¶m, 1, NULL, &value); 2956 bool hasNoError = (GL_NO_ERROR == gl().getError()); 2957 if (hasNoError) 2958 { 2959 bindingPoints[*it] = value; 2960 } 2961 } 2962 } 2963 2964 return bindingPoints; 2965 } 2966 2967 /*virtual*/ 2968 bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const 2969 { 2970 bool bNoError = true; 2971 2972 for (StringVector::iterator it = list.begin(); it != list.end(); it++) 2973 { 2974 glw::GLuint blockIndex = gl().getUniformBlockIndex(getProgram(), (*it).c_str()); 2975 if (blockIndex == GL_INVALID_INDEX) 2976 2977 { 2978 return false; 2979 } 2980 gl().uniformBlockBinding(getProgram(), blockIndex, bindingPoint); 2981 } 2982 return bNoError; 2983 } 2984 }; 2985 2986 private: 2987 // IProgramContextSupplier 2988 /*virtual*/ 2989 LayoutBindingProgram* createProgram() 2990 { 2991 return new UniformBlocksLayoutBindingProgram(*this); 2992 } 2993 2994 private: 2995 /*virtual*/ 2996 String buildBlockName(const String& name) 2997 { 2998 2999 return name; 3000 } 3001 3002 /*virtual*/ 3003 String buildBlock(const String& name, const String& type) 3004 { 3005 3006 std::ostringstream s; 3007 s << "{"; 3008 s << type << " " << name << "_a; "; 3009 s << type << " " << name << "_b; "; 3010 s << "}"; 3011 return s.str(); 3012 } 3013 3014 /*virtual*/ 3015 String buildAccess(const String& var) 3016 { 3017 std::ostringstream s; 3018 s << "vec4(0.0, " << var << "_a, 0.0, 1.0) + vec4(0.0, " << var << "_b, 0.0, 1.0)"; 3019 return s.str(); 3020 } 3021 3022 /*virtual*/ 3023 String buildLayout(const String& binding) 3024 { 3025 std::ostringstream s; 3026 if (!binding.empty()) 3027 s << "layout(binding=" << binding << ", std140) "; 3028 else 3029 s << "layout(std140) "; 3030 return s.str(); 3031 } 3032 3033 /*virtual*/ 3034 int maxBindings() 3035 { 3036 int units = 0; 3037 gl().getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &units); 3038 return units; 3039 } 3040 3041 // return max. array size allowed 3042 /*virtual*/ 3043 int maxArraySize() 3044 { 3045 int units = 0; 3046 switch (getStage()) 3047 { 3048 case FragmentShader: 3049 gl().getIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &units); 3050 break; 3051 case VertexShader: 3052 gl().getIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &units); 3053 break; 3054 case ComputeShader: 3055 gl().getIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &units); 3056 break; 3057 default: 3058 DE_ASSERT(0); 3059 break; 3060 } 3061 return units; 3062 } 3063 3064 /*virtual*/ 3065 void bind(int binding) 3066 { 3067 gl().bindBufferBase(GL_UNIFORM_BUFFER, binding, m_buffername); 3068 } 3069 3070 /*virtual*/ 3071 void unbind(int binding) 3072 { 3073 gl().bindBufferBase(GL_UNIFORM_BUFFER, binding, 0); 3074 } 3075 3076 /*virtual*/ 3077 void setupTest(void) 3078 { 3079 const float f[2] = { 0.25f, 0.75f }; 3080 gl().genBuffers(1, &m_buffername); 3081 gl().bindBuffer(GL_UNIFORM_BUFFER, m_buffername); 3082 gl().bufferData(GL_UNIFORM_BUFFER, sizeof(f), f, GL_STATIC_DRAW); 3083 } 3084 3085 /*virtual*/ 3086 void teardownTest(void) 3087 { 3088 gl().bindBuffer(GL_UNIFORM_BUFFER, 0); 3089 gl().deleteBuffers(1, &m_buffername); 3090 } 3091 3092 private: 3093 glw::GLuint m_buffername; 3094 }; 3095 3096 UniformBlocksLayoutBindingCase::UniformBlocksLayoutBindingCase(Context& context, const char* name, 3097 const char* description, StageType stage, 3098 LayoutBindingParameters& samplerType, 3099 glu::GLSLVersion glslVersion) 3100 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion), m_buffername(0) 3101 { 3102 } 3103 3104 UniformBlocksLayoutBindingCase::~UniformBlocksLayoutBindingCase() 3105 { 3106 } 3107 3108 //***************************************************************************** 3109 3110 //========================================================================= 3111 // test case Shader storage buffer binding 3112 //========================================================================= 3113 class ShaderStorageBufferLayoutBindingCase : public LayoutBindingBaseCase 3114 { 3115 public: 3116 ShaderStorageBufferLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage, 3117 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion); 3118 ~ShaderStorageBufferLayoutBindingCase(void); 3119 3120 private: 3121 class ShaderStorageBufferLayoutBindingProgram : public LayoutBindingProgram 3122 { 3123 public: 3124 ShaderStorageBufferLayoutBindingProgram(IProgramContextSupplier& contextSupplier) 3125 : LayoutBindingProgram(contextSupplier) 3126 { 3127 } 3128 3129 ~ShaderStorageBufferLayoutBindingProgram() 3130 { 3131 } 3132 //******************************************************************************* 3133 // overwritten virtual methods 3134 private: 3135 /*virtual*/ 3136 StringIntMap getBindingPoints(StringVector args) const 3137 { 3138 StringIntMap bindingPoints; 3139 3140 for (StringVector::iterator it = args.begin(); it != args.end(); it++) 3141 { 3142 glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_SHADER_STORAGE_BLOCK, (*it).c_str()); 3143 if (idx != GL_INVALID_INDEX) 3144 { 3145 glw::GLenum param = GL_BUFFER_BINDING; 3146 glw::GLint value = -1; 3147 gl().getProgramResourceiv(getProgram(), GL_SHADER_STORAGE_BLOCK, idx, 1, ¶m, 1, NULL, &value); 3148 bool hasNoError = (GL_NO_ERROR == gl().getError()); 3149 if (hasNoError) 3150 { 3151 bindingPoints[*it] = value; 3152 } 3153 } 3154 } 3155 3156 return bindingPoints; 3157 } 3158 3159 /*virtual*/ 3160 bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const 3161 { 3162 for (StringVector::iterator it = list.begin(); it != list.end(); it++) 3163 { 3164 glw::GLuint blockIndex = 3165 gl().getProgramResourceIndex(getProgram(), GL_SHADER_STORAGE_BLOCK, (*it).c_str()); 3166 if (blockIndex == GL_INVALID_INDEX) 3167 { 3168 return false; 3169 } 3170 gl().shaderStorageBlockBinding(getProgram(), blockIndex, bindingPoint); 3171 } 3172 return true; 3173 } 3174 }; 3175 3176 private: 3177 // IProgramContextSupplier 3178 /*virtual*/ 3179 LayoutBindingProgram* createProgram() 3180 { 3181 return new ShaderStorageBufferLayoutBindingProgram(*this); 3182 } 3183 3184 private: 3185 /*virtual*/ 3186 String buildLayout(const String& binding) 3187 { 3188 std::ostringstream s; 3189 if (!binding.empty()) 3190 s << "layout(binding=" << binding << ", std430) "; 3191 else 3192 s << "layout(std430) "; 3193 return s.str(); 3194 } 3195 3196 /*virtual*/ 3197 String getDefaultUniformName(int idx = 0) 3198 { 3199 StringStream s; 3200 3201 s << "buffer" << idx; 3202 return s.str(); 3203 } 3204 /*virtual*/ 3205 String buildBlockName(const String& name) 3206 { 3207 return name; 3208 } 3209 3210 /*virtual*/ 3211 String buildBlock(const String& name, const String& type) 3212 { 3213 std::ostringstream s; 3214 s << "{"; 3215 s << type << " " << name << "_a[2];\n"; 3216 s << "}"; 3217 return s.str(); 3218 } 3219 3220 /*virtual*/ 3221 String buildAccess(const String& var) 3222 { 3223 std::ostringstream s; 3224 s << "vec4(0.0, " << var << "_a[0] + " << var << "_a[1], 0.0, 1.0)"; 3225 return s.str(); 3226 } 3227 3228 int maxBindings() 3229 { 3230 int units = 0; 3231 gl().getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &units); 3232 return units; 3233 } 3234 3235 // return max. array size allowed 3236 int maxArraySize() 3237 { 3238 int units = 0; 3239 switch (getStage()) 3240 { 3241 case FragmentShader: 3242 gl().getIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &units); 3243 break; 3244 case VertexShader: 3245 gl().getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &units); 3246 break; 3247 case ComputeShader: 3248 gl().getIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &units); 3249 break; 3250 default: 3251 DE_ASSERT(0); 3252 break; 3253 } 3254 return units; 3255 } 3256 3257 /*virtual*/ 3258 void bind(int binding) 3259 { 3260 gl().bindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, m_buffername); 3261 } 3262 3263 /*virtual*/ 3264 void unbind(int binding) 3265 { 3266 gl().bindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, 0); 3267 } 3268 3269 /*virtual*/ 3270 void setupTest(void) 3271 { 3272 const float f[2] = { 0.25f, 0.75f }; 3273 gl().genBuffers(1, &m_buffername); 3274 gl().bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffername); 3275 gl().bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(f), f, GL_STATIC_DRAW); 3276 } 3277 3278 /*virtual*/ 3279 void teardownTest(void) 3280 { 3281 gl().bindBuffer(GL_SHADER_STORAGE_BUFFER, 0); 3282 gl().deleteBuffers(1, &m_buffername); 3283 } 3284 3285 //========================================================================= 3286 // sub-tests overrides 3287 //========================================================================= 3288 private: 3289 private: 3290 //virtual LayoutBindingTestResult binding_basic_default (void); 3291 //virtual LayoutBindingTestResult binding_basic_explicit (void); 3292 //virtual LayoutBindingTestResult binding_basic_multiple (void); 3293 //virtual LayoutBindingTestResult binding_basic_render (void); 3294 //virtual LayoutBindingTestResult binding_integer_constant (void); 3295 //virtual LayoutBindingTestResult binding_integer_constant_expression (void); 3296 //virtual LayoutBindingTestResult binding_array_size (void); 3297 //virtual LayoutBindingTestResult binding_array_implicit (void); 3298 //virtual LayoutBindingTestResult binding_array_multiple (void); 3299 /*virtual*/ 3300 LayoutBindingTestResult binding_api_update(void) 3301 { 3302 // only for GL 3303 if (getGLSLVersion() == glu::GLSL_VERSION_310_ES) 3304 return LayoutBindingTestResult(true, String(), true); 3305 3306 return LayoutBindingBaseCase::binding_api_update(); 3307 } 3308 //virtual LayoutBindingTestResult binding_compilation_errors (void); 3309 //virtual LayoutBindingTestResult binding_link_errors (void); 3310 //virtual LayoutBindingTestResult binding_examples (void); 3311 3312 private: 3313 glw::GLuint m_buffername; 3314 }; 3315 3316 ShaderStorageBufferLayoutBindingCase::ShaderStorageBufferLayoutBindingCase(Context& context, const char* name, 3317 const char* description, StageType stage, 3318 LayoutBindingParameters& samplerType, 3319 glu::GLSLVersion glslVersion) 3320 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion), m_buffername(0) 3321 { 3322 } 3323 3324 ShaderStorageBufferLayoutBindingCase::~ShaderStorageBufferLayoutBindingCase() 3325 { 3326 } 3327 3328 //***************************************************************************** 3329 3330 LayoutBindingTests::LayoutBindingTests(Context& context, glu::GLSLVersion glslVersion) 3331 : TestCaseGroup(context, "layout_binding", "Layout Binding LayoutBindingSubTest"), m_glslVersion(glslVersion) 3332 { 3333 } 3334 3335 LayoutBindingTests::~LayoutBindingTests(void) 3336 { 3337 } 3338 3339 StageType LayoutBindingTests::stageTypes[] = { 3340 { "ComputeShader", ComputeShader }, 3341 { "FragmentShader", FragmentShader }, 3342 { "VertexShader", VertexShader }, 3343 }; 3344 3345 // uniform_type must match vector_type, i.e. isampler2D=>ivec4 3346 LayoutBindingParameters LayoutBindingTests::test_args[] = { 3347 { "uniform", Texture, TwoD, "vec4", "sampler2D", "vec2", "texture" }, 3348 { "uniform", Texture, ThreeD, "vec4", "sampler3D", "vec3", "texture" }, 3349 { "uniform", Texture, TwoDArray, "vec4", "sampler2DArray", "vec3", "texture" }, 3350 { "uniform", Image, TwoD, "vec4", "image2D", "ivec2", "imageLoad" }, 3351 { "uniform", AtomicCounter, TwoD, "vec4", "atomic_uint", "vec3", "atomic" }, 3352 { "uniform", UniformBlock, None, "vec4", "block", "vec3", "block" }, 3353 { "buffer", ShaderStorageBuffer, None, "vec4", "buffer", "vec3", "atomicAdd" }, 3354 }; 3355 3356 // create test name which must be unique or dEQP framework will throw 3357 // example: sampler2D_layout_binding_vec4_texture_0 3358 String LayoutBindingTests::createTestName(const StageType& stageType, const LayoutBindingParameters& testArgs) 3359 { 3360 StringStream s; 3361 s << testArgs.uniform_type; 3362 s << "_layout_binding_"; 3363 s << testArgs.access_function << "_"; 3364 s << stageType.name; 3365 return s.str(); 3366 } 3367 3368 void LayoutBindingTests::init(void) 3369 { 3370 std::vector<StageType> stages = makeVector(stageTypes); 3371 std::vector<LayoutBindingParameters> samplers = makeVector(test_args); 3372 for (std::vector<StageType>::iterator stagesIter = stages.begin(); stagesIter != stages.end(); stagesIter++) 3373 { 3374 for (std::vector<LayoutBindingParameters>::iterator testArgsIter = samplers.begin(); 3375 testArgsIter != samplers.end(); testArgsIter++) 3376 { 3377 String testName = createTestName(*stagesIter, *testArgsIter); 3378 switch ((*testArgsIter).surface_type) 3379 { 3380 case Texture: 3381 addChild(new SamplerLayoutBindingCase(m_context, testName.c_str(), 3382 "test sampler layout binding functionality", *stagesIter, 3383 *testArgsIter, m_glslVersion)); 3384 break; 3385 case Image: 3386 addChild(new ImageLayoutBindingCase(m_context, testName.c_str(), 3387 "test image layout binding functionality", *stagesIter, 3388 *testArgsIter, m_glslVersion)); 3389 break; 3390 case AtomicCounter: 3391 addChild(new AtomicCounterLayoutBindingCase(m_context, testName.c_str(), 3392 "test atomic counters layout binding functionality", 3393 *stagesIter, *testArgsIter, m_glslVersion)); 3394 break; 3395 case UniformBlock: 3396 addChild(new UniformBlocksLayoutBindingCase(m_context, testName.c_str(), 3397 "test uniform block layout binding functionality", 3398 *stagesIter, *testArgsIter, m_glslVersion)); 3399 break; 3400 case ShaderStorageBuffer: 3401 addChild(new ShaderStorageBufferLayoutBindingCase( 3402 m_context, testName.c_str(), "test shader storage buffer layout binding functionality", *stagesIter, 3403 *testArgsIter, m_glslVersion)); 3404 break; 3405 default: 3406 DE_ASSERT(0); 3407 break; 3408 } 3409 } 3410 } 3411 } 3412 3413 } // glcts 3414