1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Basic Layout Binding Tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fLayoutBindingTests.hpp" 25 26 #include "gluShaderProgram.hpp" 27 #include "gluPixelTransfer.hpp" 28 #include "gluTextureUtil.hpp" 29 30 #include "glwFunctions.hpp" 31 #include "glwEnums.hpp" 32 33 #include "tcuSurface.hpp" 34 #include "tcuTestLog.hpp" 35 #include "tcuTexture.hpp" 36 #include "tcuTextureUtil.hpp" 37 #include "tcuImageCompare.hpp" 38 #include "tcuStringTemplate.hpp" 39 #include "tcuRenderTarget.hpp" 40 41 #include "deString.h" 42 #include "deStringUtil.hpp" 43 #include "deRandom.hpp" 44 45 using tcu::TestLog; 46 using tcu::Vec2; 47 using tcu::Vec3; 48 using tcu::Vec4; 49 50 namespace deqp 51 { 52 namespace gles31 53 { 54 namespace Functional 55 { 56 namespace 57 { 58 59 enum TestType 60 { 61 TESTTYPE_BINDING_SINGLE = 0, 62 TESTTYPE_BINDING_MAX, 63 TESTTYPE_BINDING_MULTIPLE, 64 TESTTYPE_BINDING_ARRAY, 65 TESTTYPE_BINDING_MAX_ARRAY, 66 67 TESTTYPE_BINDING_LAST, 68 }; 69 70 enum ShaderType 71 { 72 SHADERTYPE_VERTEX = 0, 73 SHADERTYPE_FRAGMENT, 74 SHADERTYPE_BOTH, 75 76 SHADERTYPE_LAST, 77 }; 78 79 enum 80 { 81 MAX_UNIFORM_MULTIPLE_INSTANCES = 7, 82 MAX_UNIFORM_ARRAY_SIZE = 7, 83 }; 84 85 std::string generateVertexShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody) 86 { 87 static const char* const s_simpleVertexShaderSource = "#version 310 es\n" 88 "in highp vec4 a_position;\n" 89 "void main (void)\n" 90 "{\n" 91 " gl_Position = a_position;\n" 92 "}\n"; 93 94 switch (shaderType) 95 { 96 case SHADERTYPE_VERTEX: 97 case SHADERTYPE_BOTH: 98 { 99 std::ostringstream vertexShaderSource; 100 vertexShaderSource << "#version 310 es\n" 101 << "in highp vec4 a_position;\n" 102 << "out highp vec4 v_color;\n" 103 << "uniform highp int u_arrayNdx;\n\n" 104 << shaderUniformDeclarations << "\n" 105 << "void main (void)\n" 106 << "{\n" 107 << " highp vec4 color;\n\n" 108 << shaderBody << "\n" 109 << " v_color = color;\n" 110 << " gl_Position = a_position;\n" 111 << "}\n"; 112 113 return vertexShaderSource.str(); 114 } 115 116 case SHADERTYPE_FRAGMENT: 117 return s_simpleVertexShaderSource; 118 119 default: 120 DE_ASSERT(false); 121 return ""; 122 } 123 } 124 125 std::string generateFragmentShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody) 126 { 127 static const char* const s_simpleFragmentShaderSource = "#version 310 es\n" 128 "in highp vec4 v_color;\n" 129 "layout(location = 0) out highp vec4 fragColor;\n" 130 "void main (void)\n" 131 "{\n" 132 " fragColor = v_color;\n" 133 "}\n"; 134 135 switch (shaderType) 136 { 137 case SHADERTYPE_VERTEX: 138 return s_simpleFragmentShaderSource; 139 140 case SHADERTYPE_FRAGMENT: 141 { 142 std::ostringstream fragmentShaderSource; 143 fragmentShaderSource << "#version 310 es\n" 144 << "layout(location = 0) out highp vec4 fragColor;\n" 145 << "uniform highp int u_arrayNdx;\n\n" 146 << shaderUniformDeclarations << "\n" 147 << "void main (void)\n" 148 << "{\n" 149 << " highp vec4 color;\n\n" 150 << shaderBody << "\n" 151 << " fragColor = color;\n" 152 << "}\n"; 153 154 return fragmentShaderSource.str(); 155 } 156 case SHADERTYPE_BOTH: 157 { 158 std::ostringstream fragmentShaderSource; 159 fragmentShaderSource << "#version 310 es\n" 160 << "in highp vec4 v_color;\n" 161 << "layout(location = 0) out highp vec4 fragColor;\n" 162 << "uniform highp int u_arrayNdx;\n\n" 163 << shaderUniformDeclarations << "\n" 164 << "void main (void)\n" 165 << "{\n" 166 << " if (v_color.x > 2.0) discard;\n" 167 << " highp vec4 color;\n\n" 168 << shaderBody << "\n" 169 << " fragColor = color;\n" 170 << "}\n"; 171 172 return fragmentShaderSource.str(); 173 } 174 175 default: 176 DE_ASSERT(false); 177 return ""; 178 } 179 } 180 181 std::string getUniformName (const std::string& name, int declNdx) 182 { 183 return name + de::toString(declNdx); 184 } 185 186 std::string getUniformName (const std::string& name, int declNdx, int arrNdx) 187 { 188 return name + de::toString(declNdx) + "[" + de::toString(arrNdx) + "]"; 189 } 190 191 Vec4 getRandomColor (de::Random& rnd) 192 { 193 const float r = rnd.getFloat(0.2f, 0.9f); 194 const float g = rnd.getFloat(0.2f, 0.9f); 195 const float b = rnd.getFloat(0.2f, 0.9f); 196 return Vec4(r, g, b, 1.0f); 197 } 198 199 class LayoutBindingRenderCase : public TestCase 200 { 201 public: 202 enum 203 { 204 TEST_RENDER_WIDTH = 256, 205 TEST_RENDER_HEIGHT = 256, 206 TEST_TEXTURE_SIZE = 1, 207 }; 208 209 LayoutBindingRenderCase (Context& context, 210 const char* name, 211 const char* desc, 212 ShaderType shaderType, 213 TestType testType, 214 glw::GLenum maxBindingPointEnum, 215 glw::GLenum maxVertexUnitsEnum, 216 glw::GLenum maxFragmentUnitsEnum, 217 glw::GLenum maxCombinedUnitsEnum, 218 const std::string& uniformName); 219 virtual ~LayoutBindingRenderCase (void); 220 221 virtual void init (void); 222 virtual void deinit (void); 223 224 protected: 225 virtual glu::ShaderProgram* generateShaders (void) const = 0; 226 227 void initRenderState (void); 228 bool drawAndVerifyResult (const Vec4& expectedColor); 229 void setTestResult (bool queryTestPassed, bool imageTestPassed); 230 231 const glu::ShaderProgram* m_program; 232 const ShaderType m_shaderType; 233 const TestType m_testType; 234 const std::string m_uniformName; 235 236 const glw::GLenum m_maxBindingPointEnum; 237 const glw::GLenum m_maxVertexUnitsEnum; 238 const glw::GLenum m_maxFragmentUnitsEnum; 239 const glw::GLenum m_maxCombinedUnitsEnum; 240 241 glw::GLuint m_vertexBuffer; 242 glw::GLuint m_indexBuffer; 243 glw::GLint m_shaderProgramLoc; 244 glw::GLint m_shaderProgramPosLoc; 245 glw::GLint m_shaderProgramArrayNdxLoc; 246 glw::GLint m_numBindings; 247 248 std::vector<glw::GLint> m_bindings; 249 250 private: 251 void initBindingPoints (int minBindingPoint, int numBindingPoints); 252 }; 253 254 LayoutBindingRenderCase::LayoutBindingRenderCase (Context& context, 255 const char* name, 256 const char* desc, 257 ShaderType shaderType, 258 TestType testType, 259 glw::GLenum maxBindingPointEnum, 260 glw::GLenum maxVertexUnitsEnum, 261 glw::GLenum maxFragmentUnitsEnum, 262 glw::GLenum maxCombinedUnitsEnum, 263 const std::string& uniformName) 264 : TestCase (context, name, desc) 265 , m_program (DE_NULL) 266 , m_shaderType (shaderType) 267 , m_testType (testType) 268 , m_uniformName (uniformName) 269 , m_maxBindingPointEnum (maxBindingPointEnum) 270 , m_maxVertexUnitsEnum (maxVertexUnitsEnum) 271 , m_maxFragmentUnitsEnum (maxFragmentUnitsEnum) 272 , m_maxCombinedUnitsEnum (maxCombinedUnitsEnum) 273 , m_vertexBuffer (0) 274 , m_indexBuffer (0) 275 , m_shaderProgramLoc (0) 276 , m_shaderProgramPosLoc (0) 277 , m_shaderProgramArrayNdxLoc (0) 278 , m_numBindings (0) 279 { 280 } 281 282 LayoutBindingRenderCase::~LayoutBindingRenderCase (void) 283 { 284 deinit(); 285 } 286 287 void LayoutBindingRenderCase::init (void) 288 { 289 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 290 291 { 292 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 293 glw::GLint numBindingPoints = 0; // Number of available binding points 294 glw::GLint maxVertexUnits = 0; // Available uniforms in the vertex shader 295 glw::GLint maxFragmentUnits = 0; // Available uniforms in the fragment shader 296 glw::GLint maxCombinedUnits = 0; // Available uniforms in all the shader stages combined 297 glw::GLint maxUnits = 0; // Maximum available uniforms for this test 298 299 gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits); 300 gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits); 301 gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits); 302 gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints); 303 GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed"); 304 305 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits << tcu::TestLog::EndMessage; 306 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits << tcu::TestLog::EndMessage; 307 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits << tcu::TestLog::EndMessage; 308 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum binding point for uniform type: " << numBindingPoints-1 << tcu::TestLog::EndMessage; 309 310 // Select maximum number of uniforms used for the test 311 switch (m_shaderType) 312 { 313 case SHADERTYPE_VERTEX: 314 maxUnits = maxVertexUnits; 315 break; 316 317 case SHADERTYPE_FRAGMENT: 318 maxUnits = maxFragmentUnits; 319 break; 320 321 case SHADERTYPE_BOTH: 322 maxUnits = maxCombinedUnits/2; 323 break; 324 325 default: 326 DE_ASSERT(false); 327 } 328 329 // Select the number of uniforms (= bindings) used for this test 330 switch (m_testType) 331 { 332 case TESTTYPE_BINDING_SINGLE: 333 case TESTTYPE_BINDING_MAX: 334 m_numBindings = 1; 335 break; 336 337 case TESTTYPE_BINDING_MULTIPLE: 338 if (maxUnits < 2) 339 throw tcu::NotSupportedError("Not enough uniforms available for test"); 340 m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_MULTIPLE_INSTANCES, maxUnits)); 341 break; 342 343 case TESTTYPE_BINDING_ARRAY: 344 case TESTTYPE_BINDING_MAX_ARRAY: 345 if (maxUnits < 2) 346 throw tcu::NotSupportedError("Not enough uniforms available for test"); 347 m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits)); 348 break; 349 350 default: 351 DE_ASSERT(false); 352 } 353 354 // Check that we have enough uniforms in different shaders to perform the tests 355 if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_BOTH)) && (maxVertexUnits < m_numBindings) ) 356 throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test"); 357 if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_BOTH)) && (maxFragmentUnits < m_numBindings) ) 358 throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test"); 359 if ( (m_shaderType == SHADERTYPE_BOTH) && (maxCombinedUnits < m_numBindings*2) ) 360 throw tcu::NotSupportedError("Not enough uniforms available for test"); 361 362 // Check that we have enough binding points to perform the tests 363 if (numBindingPoints < m_numBindings) 364 throw tcu::NotSupportedError("Not enough binding points available for test"); 365 366 // Initialize the binding points i.e. populate the two binding point vectors 367 initBindingPoints(0, numBindingPoints); 368 } 369 370 // Generate the shader program - note: this must be done after deciding the binding points 371 DE_ASSERT(!m_program); 372 m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shaders" << tcu::TestLog::EndMessage; 373 m_program = generateShaders(); 374 m_testCtx.getLog() << *m_program; 375 376 if (!m_program->isOk()) 377 throw tcu::TestError("Shader compile failed"); 378 379 // Setup vertex and index buffers 380 { 381 // Get attribute and uniform locations 382 const deUint32 program = m_program->getProgram(); 383 384 m_shaderProgramPosLoc = gl.getAttribLocation(program, "a_position"); 385 m_shaderProgramArrayNdxLoc = gl.getUniformLocation(program, "u_arrayNdx"); 386 m_vertexBuffer = 0; 387 m_indexBuffer = 0; 388 389 // Setup buffers so that we render one quad covering the whole viewport 390 const Vec3 vertices[] = 391 { 392 Vec3(-1.0f, -1.0f, +1.0f), 393 Vec3(+1.0f, -1.0f, +1.0f), 394 Vec3(+1.0f, +1.0f, +1.0f), 395 Vec3(-1.0f, +1.0f, +1.0f), 396 }; 397 398 const deUint16 indices[] = 399 { 400 0, 1, 2, 401 0, 2, 3, 402 }; 403 404 TCU_CHECK((m_shaderProgramPosLoc >= 0) && (m_shaderProgramArrayNdxLoc >= 0)); 405 406 // Generate and bind index buffer 407 gl.genBuffers(1, &m_indexBuffer); 408 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer); 409 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (DE_LENGTH_OF_ARRAY(indices)*(glw::GLsizeiptr)sizeof(indices[0])), &indices[0], GL_STATIC_DRAW); 410 GLU_EXPECT_NO_ERROR(gl.getError(), "Index buffer setup failed"); 411 412 // Generate and bind vertex buffer 413 gl.genBuffers(1, &m_vertexBuffer); 414 gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); 415 gl.bufferData(GL_ARRAY_BUFFER, (DE_LENGTH_OF_ARRAY(vertices)*(glw::GLsizeiptr)sizeof(vertices[0])), &vertices[0], GL_STATIC_DRAW); 416 gl.enableVertexAttribArray(m_shaderProgramPosLoc); 417 gl.vertexAttribPointer(m_shaderProgramPosLoc, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL); 418 GLU_EXPECT_NO_ERROR(gl.getError(), "Vertex buffer setup failed"); 419 } 420 } 421 422 void LayoutBindingRenderCase::deinit (void) 423 { 424 if (m_program) 425 { 426 delete m_program; 427 m_program = DE_NULL; 428 } 429 430 if (m_shaderProgramPosLoc) 431 m_context.getRenderContext().getFunctions().disableVertexAttribArray(m_shaderProgramPosLoc); 432 433 if (m_vertexBuffer) 434 { 435 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_vertexBuffer); 436 m_context.getRenderContext().getFunctions().bindBuffer(GL_ARRAY_BUFFER, 0); 437 } 438 439 if (m_indexBuffer) 440 { 441 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBuffer); 442 m_context.getRenderContext().getFunctions().bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 443 } 444 } 445 446 void LayoutBindingRenderCase::initBindingPoints (int minBindingPoint, int numBindingPoints) 447 { 448 de::Random rnd(deStringHash(getName()) ^ 0xff23a4); 449 450 switch (m_testType) 451 { 452 case TESTTYPE_BINDING_SINGLE: 453 { 454 const int bpoint = rnd.getInt(minBindingPoint, numBindingPoints-1); 455 m_bindings.push_back(bpoint); 456 break; 457 } 458 459 case TESTTYPE_BINDING_MAX: 460 m_bindings.push_back(numBindingPoints-1); 461 break; 462 463 case TESTTYPE_BINDING_MULTIPLE: 464 { 465 // Choose multiple unique binding points from the low and high end of available binding points 466 std::vector<deUint32> lowBindingPoints; 467 std::vector<deUint32> highBindingPoints; 468 469 for (int bpoint = 0; bpoint < numBindingPoints/2; ++bpoint) 470 lowBindingPoints.push_back(bpoint); 471 for (int bpoint = numBindingPoints/2; bpoint < numBindingPoints; ++bpoint) 472 highBindingPoints.push_back(bpoint); 473 474 rnd.shuffle(lowBindingPoints.begin(), lowBindingPoints.end()); 475 rnd.shuffle(highBindingPoints.begin(), highBindingPoints.end()); 476 477 for (int ndx = 0; ndx < m_numBindings; ++ndx) 478 { 479 if (ndx%2 == 0) 480 { 481 const int bpoint = lowBindingPoints.back(); 482 lowBindingPoints.pop_back(); 483 m_bindings.push_back(bpoint); 484 } 485 else 486 { 487 const int bpoint = highBindingPoints.back(); 488 highBindingPoints.pop_back(); 489 m_bindings.push_back(bpoint); 490 } 491 492 } 493 break; 494 } 495 496 case TESTTYPE_BINDING_ARRAY: 497 { 498 const glw::GLint binding = rnd.getInt(minBindingPoint, numBindingPoints-m_numBindings); 499 for (int ndx = 0; ndx < m_numBindings; ++ndx) 500 m_bindings.push_back(binding+ndx); 501 break; 502 } 503 504 case TESTTYPE_BINDING_MAX_ARRAY: 505 { 506 const glw::GLint binding = numBindingPoints-m_numBindings; 507 for (int ndx = 0; ndx < m_numBindings; ++ndx) 508 m_bindings.push_back(binding+ndx); 509 break; 510 } 511 512 default: 513 DE_ASSERT(false); 514 } 515 } 516 517 void LayoutBindingRenderCase::initRenderState (void) 518 { 519 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 520 521 gl.useProgram(m_program->getProgram()); 522 gl.viewport(0, 0, TEST_RENDER_WIDTH, TEST_RENDER_HEIGHT); 523 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 524 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set render state"); 525 } 526 527 bool LayoutBindingRenderCase::drawAndVerifyResult (const Vec4& expectedColor) 528 { 529 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 530 const tcu::RGBA threshold = m_context.getRenderContext().getRenderTarget().getPixelFormat().getColorThreshold(); 531 tcu::Surface reference (TEST_RENDER_WIDTH, TEST_RENDER_HEIGHT); 532 533 gl.clear(GL_COLOR_BUFFER_BIT); 534 535 // Draw 536 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL); 537 GLU_EXPECT_NO_ERROR(gl.getError(), "Drawing failed"); 538 539 // Verify 540 tcu::Surface result(TEST_RENDER_WIDTH, TEST_RENDER_HEIGHT); 541 m_testCtx.getLog() << TestLog::Message << "Reading pixels" << TestLog::EndMessage; 542 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); 543 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed"); 544 545 tcu::clear(reference.getAccess(), expectedColor); 546 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output image" << tcu::TestLog::EndMessage; 547 548 return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Render result", "Result verification", reference, result, threshold, tcu::COMPARE_LOG_RESULT); 549 } 550 551 void LayoutBindingRenderCase::setTestResult (bool queryTestPassed, bool imageTestPassed) 552 { 553 if (queryTestPassed && imageTestPassed) 554 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 555 else if (!queryTestPassed && !imageTestPassed) 556 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more binding point queries and image comparisons failed"); 557 else if (!queryTestPassed) 558 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more binding point queries failed"); 559 else 560 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more image comparisons failed"); 561 } 562 563 class LayoutBindingNegativeCase : public TestCase 564 { 565 public: 566 enum ErrorType 567 { 568 ERRORTYPE_OVER_MAX_UNITS = 0, 569 ERRORTYPE_LESS_THAN_ZERO, 570 ERRORTYPE_CONTRADICTORY, 571 572 ERRORTYPE_LAST, 573 }; 574 575 LayoutBindingNegativeCase (Context& context, 576 const char* name, 577 const char* desc, 578 ShaderType shaderType, 579 TestType testType, 580 ErrorType errorType, 581 glw::GLenum maxBindingPointEnum, 582 glw::GLenum maxVertexUnitsEnum, 583 glw::GLenum maxFragmentUnitsEnum, 584 glw::GLenum maxCombinedUnitsEnum, 585 const std::string& uniformName); 586 virtual ~LayoutBindingNegativeCase (void); 587 588 virtual void init (void); 589 virtual void deinit (void); 590 virtual IterateResult iterate (void); 591 592 protected: 593 virtual glu::ShaderProgram* generateShaders (void) const = 0; 594 595 const glu::ShaderProgram* m_program; 596 const ShaderType m_shaderType; 597 const TestType m_testType; 598 const ErrorType m_errorType; 599 const glw::GLenum m_maxBindingPointEnum; 600 const glw::GLenum m_maxVertexUnitsEnum; 601 const glw::GLenum m_maxFragmentUnitsEnum; 602 const glw::GLenum m_maxCombinedUnitsEnum; 603 const std::string m_uniformName; 604 glw::GLint m_numBindings; 605 std::vector<glw::GLint> m_vertexShaderBinding; 606 std::vector<glw::GLint> m_fragmentShaderBinding; 607 608 private: 609 void initBindingPoints (int minBindingPoint, int numBindingPoints); 610 }; 611 612 LayoutBindingNegativeCase::LayoutBindingNegativeCase (Context& context, 613 const char* name, 614 const char* desc, 615 ShaderType shaderType, 616 TestType testType, 617 ErrorType errorType, 618 glw::GLenum maxBindingPointEnum, 619 glw::GLenum maxVertexUnitsEnum, 620 glw::GLenum maxFragmentUnitsEnum, 621 glw::GLenum maxCombinedUnitsEnum, 622 const std::string& uniformName) 623 : TestCase (context, name, desc) 624 , m_program (DE_NULL) 625 , m_shaderType (shaderType) 626 , m_testType (testType) 627 , m_errorType (errorType) 628 , m_maxBindingPointEnum (maxBindingPointEnum) 629 , m_maxVertexUnitsEnum (maxVertexUnitsEnum) 630 , m_maxFragmentUnitsEnum (maxFragmentUnitsEnum) 631 , m_maxCombinedUnitsEnum (maxCombinedUnitsEnum) 632 , m_uniformName (uniformName) 633 , m_numBindings (0) 634 { 635 } 636 637 LayoutBindingNegativeCase::~LayoutBindingNegativeCase (void) 638 { 639 deinit(); 640 } 641 642 void LayoutBindingNegativeCase::init (void) 643 { 644 // Decide appropriate binding points for the vertex and fragment shaders 645 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 646 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 647 glw::GLint numBindingPoints = 0; // Number of binding points 648 glw::GLint maxVertexUnits = 0; // Available uniforms in the vertex shader 649 glw::GLint maxFragmentUnits = 0; // Available uniforms in the fragment shader 650 glw::GLint maxCombinedUnits = 0; // Available uniforms in all the shader stages combined 651 glw::GLint maxUnits = 0; // Maximum available uniforms for this test 652 653 gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits); 654 gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits); 655 gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits); 656 gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints); 657 GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed"); 658 659 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits << tcu::TestLog::EndMessage; 660 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits << tcu::TestLog::EndMessage; 661 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits << tcu::TestLog::EndMessage; 662 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum binding point for uniform type: " << numBindingPoints-1 << tcu::TestLog::EndMessage; 663 664 // Select maximum number of uniforms used for the test 665 switch (m_shaderType) 666 { 667 case SHADERTYPE_VERTEX: 668 maxUnits = maxVertexUnits; 669 break; 670 671 case SHADERTYPE_FRAGMENT: 672 maxUnits = maxFragmentUnits; 673 break; 674 675 case SHADERTYPE_BOTH: 676 maxUnits = maxCombinedUnits/2; 677 break; 678 679 default: 680 DE_ASSERT(false); 681 } 682 683 // Select the number of uniforms (= bindings) used for this test 684 switch (m_testType) 685 { 686 case TESTTYPE_BINDING_SINGLE: 687 case TESTTYPE_BINDING_MAX: 688 m_numBindings = 1; 689 break; 690 691 case TESTTYPE_BINDING_MULTIPLE: 692 case TESTTYPE_BINDING_ARRAY: 693 case TESTTYPE_BINDING_MAX_ARRAY: 694 if (maxUnits < 2) 695 throw tcu::NotSupportedError("Not enough uniforms available for test"); 696 m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits)); 697 break; 698 699 default: 700 DE_ASSERT(false); 701 } 702 703 // Check that we have enough uniforms in different shaders to perform the tests 704 if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_BOTH)) && (maxVertexUnits < m_numBindings) ) 705 throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test"); 706 if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_BOTH)) && (maxFragmentUnits < m_numBindings) ) 707 throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test"); 708 if ( (m_shaderType == SHADERTYPE_BOTH) && (maxCombinedUnits < m_numBindings*2) ) 709 throw tcu::NotSupportedError("Not enough uniforms available for test"); 710 711 // Check that we have enough binding points to perform the tests 712 if (numBindingPoints < m_numBindings) 713 throw tcu::NotSupportedError("Not enough binding points available for test"); 714 715 // Initialize the binding points i.e. populate the two binding point vectors 716 initBindingPoints(0, numBindingPoints); 717 718 // Generate the shader program - note: this must be done after deciding the binding points 719 DE_ASSERT(!m_program); 720 m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shaders" << tcu::TestLog::EndMessage; 721 m_program = generateShaders(); 722 m_testCtx.getLog() << *m_program; 723 } 724 725 void LayoutBindingNegativeCase::deinit (void) 726 { 727 if (m_program) 728 { 729 delete m_program; 730 m_program = DE_NULL; 731 } 732 } 733 734 TestCase::IterateResult LayoutBindingNegativeCase::iterate (void) 735 { 736 bool pass = false; 737 std::string failMessage; 738 739 switch (m_errorType) 740 { 741 case ERRORTYPE_CONTRADICTORY: // Contradictory binding points should cause a link-time error 742 if (!(m_program->getProgramInfo()).linkOk) 743 pass = true; 744 failMessage = "Test failed - expected a link-time error"; 745 break; 746 747 case ERRORTYPE_LESS_THAN_ZERO: // Out of bounds binding points should cause a compile-time error 748 case ERRORTYPE_OVER_MAX_UNITS: 749 if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk || !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT)).compileOk) 750 pass = true; 751 failMessage = "Test failed - expected a compile-time error"; 752 break; 753 754 default: 755 DE_ASSERT(false); 756 } 757 758 if (pass) 759 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 760 else 761 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, failMessage.c_str()); 762 763 return STOP; 764 } 765 766 void LayoutBindingNegativeCase::initBindingPoints (int minBindingPoint, int numBindingPoints) 767 { 768 de::Random rnd(deStringHash(getName()) ^ 0xff23a4); 769 770 switch (m_errorType) 771 { 772 case ERRORTYPE_OVER_MAX_UNITS: // Select a binding point that is 1 over the maximum 773 { 774 m_vertexShaderBinding.push_back(numBindingPoints+1-m_numBindings); 775 m_fragmentShaderBinding.push_back(numBindingPoints+1-m_numBindings); 776 break; 777 } 778 779 case ERRORTYPE_LESS_THAN_ZERO: // Select a random negative binding point 780 { 781 const glw::GLint binding = -rnd.getInt(1, numBindingPoints-m_numBindings); 782 m_vertexShaderBinding.push_back(binding); 783 m_fragmentShaderBinding.push_back(binding); 784 break; 785 } 786 787 case ERRORTYPE_CONTRADICTORY: // Select two valid, but contradictory binding points 788 { 789 m_vertexShaderBinding.push_back(minBindingPoint); 790 m_fragmentShaderBinding.push_back(numBindingPoints-m_numBindings); 791 break; 792 } 793 794 default: 795 DE_ASSERT(false); 796 } 797 798 // In case we are testing with multiple uniforms populate the rest of the binding points 799 for (int ndx = 1; ndx < m_numBindings; ++ndx) 800 { 801 m_vertexShaderBinding.push_back(m_vertexShaderBinding.front()+ndx); 802 m_fragmentShaderBinding.push_back(m_fragmentShaderBinding.front()+ndx); 803 } 804 } 805 806 class SamplerBindingRenderCase : public LayoutBindingRenderCase 807 { 808 public: 809 SamplerBindingRenderCase (Context& context, const char* name, const char* desc, ShaderType shaderType, TestType testType, glw::GLenum samplerType, glw::GLenum textureType); 810 ~SamplerBindingRenderCase (void); 811 812 void init (void); 813 void deinit (void); 814 IterateResult iterate (void); 815 816 private: 817 glu::ShaderProgram* generateShaders (void) const; 818 glu::DataType getSamplerTexCoordType (void) const; 819 void initializeTexture (glw::GLint bindingPoint, glw::GLint textureName, const Vec4& color) const; 820 821 const glw::GLenum m_samplerType; 822 const glw::GLenum m_textureType; 823 824 std::vector<glw::GLuint> m_textures; 825 std::vector<Vec4> m_textureColors; 826 }; 827 828 829 SamplerBindingRenderCase::SamplerBindingRenderCase (Context& context, 830 const char* name, 831 const char* desc, 832 ShaderType shaderType, 833 TestType testType, 834 glw::GLenum samplerType, 835 glw::GLenum textureType) 836 : LayoutBindingRenderCase (context, name, desc, shaderType, testType, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, "u_sampler") 837 , m_samplerType (samplerType) 838 , m_textureType (textureType) 839 { 840 } 841 842 SamplerBindingRenderCase::~SamplerBindingRenderCase (void) 843 { 844 deinit(); 845 } 846 847 void SamplerBindingRenderCase::init (void) 848 { 849 LayoutBindingRenderCase::init(); 850 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 851 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 852 853 854 // Initialize texture resources 855 m_textures = std::vector<glw::GLuint>(m_numBindings, 0); 856 857 // Texture colors 858 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 859 m_textureColors.push_back(getRandomColor(rnd)); 860 861 // Textures 862 gl.genTextures((glw::GLsizei)m_textures.size(), &m_textures[0]); 863 864 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 865 initializeTexture(m_bindings[texNdx], m_textures[texNdx], m_textureColors[texNdx]); 866 867 gl.activeTexture(GL_TEXTURE0); 868 } 869 870 void SamplerBindingRenderCase::deinit(void) 871 { 872 LayoutBindingRenderCase::deinit(); 873 874 // Clean up texture data 875 for (int i = 0; i < (int)m_textures.size(); ++i) 876 { 877 if (m_textures[i]) 878 { 879 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_textures[i]); 880 m_context.getRenderContext().getFunctions().bindTexture(m_textureType, 0); 881 } 882 } 883 } 884 885 TestCase::IterateResult SamplerBindingRenderCase::iterate (void) 886 { 887 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 888 const int iterations = m_numBindings; 889 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 890 bool imageTestPassed = true; 891 bool queryTestPassed = true; 892 893 // Set the viewport and enable the shader program 894 initRenderState(); 895 896 for (int iterNdx = 0; iterNdx < iterations; ++iterNdx) 897 { 898 // Set the uniform value indicating the current array index 899 gl.uniform1i(m_shaderProgramArrayNdxLoc, iterNdx); 900 901 // Query binding point 902 const std::string name = arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx); 903 const glw::GLint binding = m_bindings[iterNdx]; 904 glw::GLint val = -1; 905 906 gl.getUniformiv(m_program->getProgram(), gl.getUniformLocation(m_program->getProgram(), name.c_str()), &val); 907 m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage; 908 GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed"); 909 910 // Draw and verify 911 if (val != binding) 912 queryTestPassed = false; 913 if (!drawAndVerifyResult(m_textureColors[iterNdx])) 914 imageTestPassed = false; 915 } 916 917 setTestResult(queryTestPassed, imageTestPassed); 918 return STOP; 919 } 920 921 glu::ShaderProgram* SamplerBindingRenderCase::generateShaders (void) const 922 { 923 std::ostringstream shaderUniformDecl; 924 std::ostringstream shaderBody; 925 926 const std::string texCoordType = glu::getDataTypeName(getSamplerTexCoordType()); 927 const std::string samplerType = glu::getDataTypeName(glu::getDataTypeFromGLType(m_samplerType)); 928 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY) ? true : false; 929 const int numDeclarations = arrayInstance ? 1 : m_numBindings; 930 931 // Generate the uniform declarations for the vertex and fragment shaders 932 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 933 { 934 shaderUniformDecl << "layout(binding = " << m_bindings[declNdx] << ") uniform highp " << samplerType << " " 935 << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 936 } 937 938 // Generate the shader body for the vertex and fragment shaders 939 for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx) 940 { 941 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 942 << " {\n" 943 << " color = texture(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0.5));\n" 944 << " }\n"; 945 } 946 947 shaderBody << " else\n" 948 << " {\n" 949 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 950 << " }\n"; 951 952 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 953 << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())) 954 << glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))); 955 } 956 957 void SamplerBindingRenderCase::initializeTexture (glw::GLint bindingPoint, glw::GLint textureName, const Vec4& color) const 958 { 959 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 960 961 gl.activeTexture(GL_TEXTURE0 + bindingPoint); 962 gl.bindTexture(m_textureType, textureName); 963 gl.texParameteri(m_textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 964 965 switch (m_textureType) 966 { 967 case GL_TEXTURE_2D: 968 { 969 tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 970 tcu::clear(level.getAccess(), color); 971 glu::texImage2D(m_context.getRenderContext(), m_textureType, 0, GL_RGBA8, level.getAccess()); 972 break; 973 } 974 975 case GL_TEXTURE_3D: 976 { 977 tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 978 tcu::clear(level.getAccess(), color); 979 glu::texImage3D(m_context.getRenderContext(), m_textureType, 0, GL_RGBA8, level.getAccess()); 980 break; 981 } 982 983 default: 984 DE_ASSERT(false); 985 } 986 987 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture initialization failed"); 988 } 989 990 glu::DataType SamplerBindingRenderCase::getSamplerTexCoordType (void) const 991 { 992 switch (m_samplerType) 993 { 994 case GL_SAMPLER_2D: 995 return glu::TYPE_FLOAT_VEC2; 996 997 case GL_SAMPLER_3D: 998 return glu::TYPE_FLOAT_VEC3; 999 1000 default: 1001 DE_ASSERT(false); 1002 return glu::TYPE_INVALID; 1003 } 1004 } 1005 1006 1007 class SamplerBindingNegativeCase : public LayoutBindingNegativeCase 1008 { 1009 public: 1010 SamplerBindingNegativeCase (Context& context, 1011 const char* name, 1012 const char* desc, 1013 ShaderType shaderType, 1014 TestType testType, 1015 ErrorType errorType, 1016 glw::GLenum samplerType); 1017 ~SamplerBindingNegativeCase (void); 1018 1019 private: 1020 glu::ShaderProgram* generateShaders (void) const; 1021 glu::DataType getSamplerTexCoordType (void) const; 1022 1023 const glw::GLenum m_samplerType; 1024 }; 1025 1026 SamplerBindingNegativeCase::SamplerBindingNegativeCase (Context& context, 1027 const char* name, 1028 const char* desc, 1029 ShaderType shaderType, 1030 TestType testType, 1031 ErrorType errorType, 1032 glw::GLenum samplerType) 1033 : LayoutBindingNegativeCase (context, name, desc, shaderType, testType, errorType, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, "u_sampler") 1034 , m_samplerType (samplerType) 1035 { 1036 } 1037 1038 SamplerBindingNegativeCase::~SamplerBindingNegativeCase (void) 1039 { 1040 LayoutBindingNegativeCase::deinit(); 1041 } 1042 1043 glu::ShaderProgram* SamplerBindingNegativeCase::generateShaders (void) const 1044 { 1045 std::ostringstream vertexUniformDecl; 1046 std::ostringstream fragmentUniformDecl; 1047 std::ostringstream shaderBody; 1048 1049 const std::string texCoordType = glu::getDataTypeName(getSamplerTexCoordType()); 1050 const std::string samplerType = glu::getDataTypeName(glu::getDataTypeFromGLType(m_samplerType)); 1051 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1052 const int numDeclarations = arrayInstance ? 1 : m_numBindings; 1053 1054 // Generate the uniform declarations for the vertex and fragment shaders 1055 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1056 { 1057 vertexUniformDecl << "layout(binding = " << m_vertexShaderBinding[declNdx] << ") uniform highp " << samplerType 1058 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1059 fragmentUniformDecl << "layout(binding = " << m_fragmentShaderBinding[declNdx] << ") uniform highp " << samplerType 1060 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1061 } 1062 1063 // Generate the shader body for the vertex and fragment shaders 1064 for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx) 1065 { 1066 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1067 << " {\n" 1068 << " color = texture(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0.5));\n" 1069 << " }\n"; 1070 } 1071 1072 shaderBody << " else\n" 1073 << " {\n" 1074 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1075 << " }\n"; 1076 1077 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1078 << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str())) 1079 << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()))); 1080 } 1081 1082 glu::DataType SamplerBindingNegativeCase::getSamplerTexCoordType(void) const 1083 { 1084 switch (m_samplerType) 1085 { 1086 case GL_SAMPLER_2D: 1087 return glu::TYPE_FLOAT_VEC2; 1088 1089 case GL_SAMPLER_3D: 1090 return glu::TYPE_FLOAT_VEC3; 1091 1092 default: 1093 DE_ASSERT(false); 1094 return glu::TYPE_INVALID; 1095 } 1096 } 1097 1098 class ImageBindingRenderCase : public LayoutBindingRenderCase 1099 { 1100 public: 1101 ImageBindingRenderCase (Context& context, 1102 const char* name, 1103 const char* desc, 1104 ShaderType shaderType, 1105 TestType testType, 1106 glw::GLenum imageType, 1107 glw::GLenum textureType); 1108 ~ImageBindingRenderCase (void); 1109 1110 void init (void); 1111 void deinit (void); 1112 IterateResult iterate (void); 1113 1114 private: 1115 glu::ShaderProgram* generateShaders (void) const; 1116 void initializeImage (glw::GLint imageBindingPoint, glw::GLint textureBindingPoint, glw::GLint textureName, const Vec4& color) const; 1117 glu::DataType getImageTexCoordType (void) const; 1118 1119 const glw::GLenum m_imageType; 1120 const glw::GLenum m_textureType; 1121 1122 std::vector<glw::GLuint> m_textures; 1123 std::vector<Vec4> m_textureColors; 1124 }; 1125 1126 1127 ImageBindingRenderCase::ImageBindingRenderCase (Context& context, 1128 const char* name, 1129 const char* desc, 1130 ShaderType shaderType, 1131 TestType testType, 1132 glw::GLenum imageType, 1133 glw::GLenum textureType) 1134 : LayoutBindingRenderCase (context, name, desc, shaderType, testType, GL_MAX_IMAGE_UNITS, GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS, GL_MAX_COMBINED_IMAGE_UNIFORMS, "u_image") 1135 , m_imageType (imageType) 1136 , m_textureType (textureType) 1137 { 1138 } 1139 1140 ImageBindingRenderCase::~ImageBindingRenderCase (void) 1141 { 1142 deinit(); 1143 } 1144 1145 void ImageBindingRenderCase::init (void) 1146 { 1147 LayoutBindingRenderCase::init(); 1148 1149 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1150 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 1151 1152 // Initialize image / texture resources 1153 m_textures = std::vector<glw::GLuint>(m_numBindings, 0); 1154 1155 // Texture colors 1156 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 1157 m_textureColors.push_back(getRandomColor(rnd)); 1158 1159 // Image textures 1160 gl.genTextures(m_numBindings, &m_textures[0]); 1161 1162 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 1163 initializeImage(m_bindings[texNdx], texNdx, m_textures[texNdx], m_textureColors[texNdx]); 1164 } 1165 1166 void ImageBindingRenderCase::deinit (void) 1167 { 1168 LayoutBindingRenderCase::deinit(); 1169 1170 // Clean up texture data 1171 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 1172 { 1173 if (m_textures[texNdx]) 1174 { 1175 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_textures[texNdx]); 1176 m_context.getRenderContext().getFunctions().bindTexture(m_textureType, 0); 1177 } 1178 } 1179 } 1180 1181 TestCase::IterateResult ImageBindingRenderCase::iterate (void) 1182 { 1183 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1184 const int iterations = m_numBindings; 1185 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1186 bool queryTestPassed = true; 1187 bool imageTestPassed = true; 1188 1189 // Set the viewport and enable the shader program 1190 initRenderState(); 1191 1192 for (int iterNdx = 0; iterNdx < iterations; ++iterNdx) 1193 { 1194 // Set the uniform value indicating the current array index 1195 gl.uniform1i(m_shaderProgramArrayNdxLoc, iterNdx); 1196 1197 const std::string name = (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx)); 1198 const glw::GLint binding = m_bindings[iterNdx]; 1199 glw::GLint val = -1; 1200 1201 gl.getUniformiv(m_program->getProgram(), gl.getUniformLocation(m_program->getProgram(), name.c_str()), &val); 1202 m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage; 1203 GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed"); 1204 1205 // Draw and verify 1206 if (val != binding) 1207 queryTestPassed = false; 1208 if (!drawAndVerifyResult(m_textureColors[iterNdx])) 1209 imageTestPassed = false; 1210 } 1211 1212 setTestResult(queryTestPassed, imageTestPassed); 1213 return STOP; 1214 } 1215 1216 void ImageBindingRenderCase::initializeImage (glw::GLint imageBindingPoint, glw::GLint textureBindingPoint, glw::GLint textureName, const Vec4& color) const 1217 { 1218 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1219 1220 gl.activeTexture(GL_TEXTURE0 + textureBindingPoint); 1221 gl.bindTexture(m_textureType, textureName); 1222 gl.texParameteri(m_textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1223 1224 switch (m_textureType) 1225 { 1226 case GL_TEXTURE_2D: 1227 { 1228 tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 1229 tcu::clear(level.getAccess(), color); 1230 gl.texStorage2D(m_textureType, 1, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 1231 gl.texSubImage2D(m_textureType, 0, 0, 0, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, level.getAccess().getDataPtr()); 1232 break; 1233 } 1234 1235 case GL_TEXTURE_3D: 1236 { 1237 tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 1238 tcu::clear(level.getAccess(), color); 1239 gl.texStorage3D(m_textureType, 1, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 1240 gl.texSubImage3D(m_textureType, 0, 0, 0, 0, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, level.getAccess().getDataPtr()); 1241 break; 1242 } 1243 1244 default: 1245 DE_ASSERT(false); 1246 } 1247 1248 gl.bindTexture(m_textureType, 0); 1249 gl.bindImageTexture(imageBindingPoint, textureName, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA8); 1250 GLU_EXPECT_NO_ERROR(gl.getError(), "Image initialization failed"); 1251 } 1252 1253 glu::ShaderProgram* ImageBindingRenderCase::generateShaders (void) const 1254 { 1255 std::ostringstream shaderUniformDecl; 1256 std::ostringstream shaderBody; 1257 1258 const std::string texCoordType = glu::getDataTypeName(getImageTexCoordType()); 1259 const std::string imageType = glu::getDataTypeName(glu::getDataTypeFromGLType(m_imageType)); 1260 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY) ? true : false; 1261 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1262 1263 // Generate the uniform declarations for the vertex and fragment shaders 1264 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1265 { 1266 shaderUniformDecl << "layout(rgba8, binding = " << m_bindings[declNdx] << ") uniform readonly highp " << imageType 1267 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1268 } 1269 1270 // Generate the shader body for the vertex and fragment shaders 1271 for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx) 1272 { 1273 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1274 << " {\n" 1275 << " color = imageLoad(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0));\n" 1276 << " }\n"; 1277 } 1278 1279 shaderBody << " else\n" 1280 << " {\n" 1281 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1282 << " }\n"; 1283 1284 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1285 << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())) 1286 << glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))); 1287 } 1288 1289 glu::DataType ImageBindingRenderCase::getImageTexCoordType(void) const 1290 { 1291 switch (m_imageType) 1292 { 1293 case GL_IMAGE_2D: 1294 return glu::TYPE_INT_VEC2; 1295 1296 case GL_IMAGE_3D: 1297 return glu::TYPE_INT_VEC3; 1298 1299 default: 1300 DE_ASSERT(false); 1301 return glu::TYPE_INVALID; 1302 } 1303 } 1304 1305 1306 class ImageBindingNegativeCase : public LayoutBindingNegativeCase 1307 { 1308 public: 1309 ImageBindingNegativeCase (Context& context, 1310 const char* name, 1311 const char* desc, 1312 ShaderType shaderType, 1313 TestType testType, 1314 ErrorType errorType, 1315 glw::GLenum imageType); 1316 ~ImageBindingNegativeCase (void); 1317 1318 private: 1319 glu::ShaderProgram* generateShaders (void) const; 1320 glu::DataType getImageTexCoordType (void) const; 1321 1322 const glw::GLenum m_imageType; 1323 }; 1324 1325 ImageBindingNegativeCase::ImageBindingNegativeCase (Context& context, 1326 const char* name, 1327 const char* desc, 1328 ShaderType shaderType, 1329 TestType testType, 1330 ErrorType errorType, 1331 glw::GLenum imageType) 1332 : LayoutBindingNegativeCase (context, name, desc, shaderType, testType, errorType, GL_MAX_IMAGE_UNITS, GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS, GL_MAX_COMBINED_IMAGE_UNIFORMS, "u_image") 1333 , m_imageType (imageType) 1334 { 1335 } 1336 1337 ImageBindingNegativeCase::~ImageBindingNegativeCase (void) 1338 { 1339 deinit(); 1340 } 1341 1342 glu::ShaderProgram* ImageBindingNegativeCase::generateShaders (void) const 1343 { 1344 std::ostringstream vertexUniformDecl; 1345 std::ostringstream fragmentUniformDecl; 1346 std::ostringstream shaderBody; 1347 1348 const std::string texCoordType = glu::getDataTypeName(getImageTexCoordType()); 1349 const std::string imageType = glu::getDataTypeName(glu::getDataTypeFromGLType(m_imageType)); 1350 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1351 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1352 1353 // Generate the uniform declarations for the vertex and fragment shaders 1354 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1355 { 1356 vertexUniformDecl << "layout(rgba8, binding = " << m_vertexShaderBinding[declNdx] << ") uniform readonly highp " << imageType 1357 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1358 fragmentUniformDecl << "layout(rgba8, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform readonly highp " << imageType 1359 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1360 } 1361 1362 // Generate the shader body for the vertex and fragment shaders 1363 for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx) 1364 { 1365 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1366 << " {\n" 1367 << " color = imageLoad(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0));\n" 1368 << " }\n"; 1369 } 1370 1371 shaderBody << " else\n" 1372 << " {\n" 1373 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1374 << " }\n"; 1375 1376 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1377 << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str())) 1378 << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()))); 1379 } 1380 1381 glu::DataType ImageBindingNegativeCase::getImageTexCoordType(void) const 1382 { 1383 switch (m_imageType) 1384 { 1385 case GL_IMAGE_2D: 1386 return glu::TYPE_INT_VEC2; 1387 1388 case GL_IMAGE_3D: 1389 return glu::TYPE_INT_VEC3; 1390 1391 default: 1392 DE_ASSERT(false); 1393 return glu::TYPE_INVALID; 1394 } 1395 } 1396 1397 1398 class UBOBindingRenderCase : public LayoutBindingRenderCase 1399 { 1400 public: 1401 UBOBindingRenderCase (Context& context, 1402 const char* name, 1403 const char* desc, 1404 ShaderType shaderType, 1405 TestType testType); 1406 ~UBOBindingRenderCase (void); 1407 1408 void init (void); 1409 void deinit (void); 1410 IterateResult iterate (void); 1411 1412 private: 1413 glu::ShaderProgram* generateShaders (void) const; 1414 1415 std::vector<deUint32> m_buffers; 1416 std::vector<Vec4> m_expectedColors; 1417 }; 1418 1419 UBOBindingRenderCase::UBOBindingRenderCase (Context& context, 1420 const char* name, 1421 const char* desc, 1422 ShaderType shaderType, 1423 TestType testType) 1424 : LayoutBindingRenderCase (context, name, desc, shaderType, testType, GL_MAX_UNIFORM_BUFFER_BINDINGS, GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, GL_MAX_COMBINED_UNIFORM_BLOCKS, "ColorBlock") 1425 { 1426 } 1427 1428 UBOBindingRenderCase::~UBOBindingRenderCase (void) 1429 { 1430 deinit(); 1431 } 1432 1433 void UBOBindingRenderCase::init (void) 1434 { 1435 LayoutBindingRenderCase::init(); 1436 1437 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1438 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 1439 1440 // Initialize UBOs and related data 1441 m_buffers = std::vector<glw::GLuint>(m_numBindings, 0); 1442 gl.genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]); 1443 1444 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1445 { 1446 m_expectedColors.push_back(getRandomColor(rnd)); 1447 m_expectedColors.push_back(getRandomColor(rnd)); 1448 } 1449 1450 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1451 { 1452 gl.bindBuffer(GL_UNIFORM_BUFFER, m_buffers[bufNdx]); 1453 gl.bufferData(GL_UNIFORM_BUFFER, 2*sizeof(Vec4), &(m_expectedColors[2*bufNdx]), GL_STATIC_DRAW); 1454 gl.bindBufferBase(GL_UNIFORM_BUFFER, m_bindings[bufNdx], m_buffers[bufNdx]); 1455 } 1456 1457 GLU_EXPECT_NO_ERROR(gl.getError(), "UBO setup failed"); 1458 } 1459 1460 void UBOBindingRenderCase::deinit (void) 1461 { 1462 LayoutBindingRenderCase::deinit(); 1463 1464 // Clean up UBO data 1465 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1466 { 1467 if (m_buffers[bufNdx]) 1468 { 1469 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffers[bufNdx]); 1470 m_context.getRenderContext().getFunctions().bindBuffer(GL_UNIFORM_BUFFER, 0); 1471 } 1472 } 1473 } 1474 1475 TestCase::IterateResult UBOBindingRenderCase::iterate (void) 1476 { 1477 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1478 const int iterations = m_numBindings; 1479 const glw::GLenum prop = GL_BUFFER_BINDING; 1480 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1481 bool queryTestPassed = true; 1482 bool imageTestPassed = true; 1483 1484 // Set the viewport and enable the shader program 1485 initRenderState(); 1486 1487 for (int iterNdx = 0; iterNdx < iterations; ++iterNdx) 1488 { 1489 // Query binding point 1490 const std::string name = (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx)); 1491 const glw::GLint binding = m_bindings[iterNdx]; 1492 glw::GLint val = -1; 1493 1494 gl.getProgramResourceiv(m_program->getProgram(), GL_UNIFORM_BLOCK, gl.getProgramResourceIndex(m_program->getProgram(), GL_UNIFORM_BLOCK, name.c_str() ), 1, &prop, 1, DE_NULL, &val); 1495 m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage; 1496 GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed"); 1497 1498 if (val != binding) 1499 queryTestPassed = false; 1500 1501 // Draw twice to render both colors within the UBO 1502 for (int drawCycle = 0; drawCycle < 2; ++drawCycle) 1503 { 1504 // Set the uniform indicating the array index to be used and set the expected color 1505 const int arrayNdx = iterNdx*2 + drawCycle; 1506 gl.uniform1i(m_shaderProgramArrayNdxLoc, arrayNdx); 1507 1508 if (!drawAndVerifyResult(m_expectedColors[arrayNdx])) 1509 imageTestPassed = false; 1510 } 1511 } 1512 1513 setTestResult(queryTestPassed, imageTestPassed); 1514 return STOP; 1515 } 1516 1517 glu::ShaderProgram* UBOBindingRenderCase::generateShaders (void) const 1518 { 1519 std::ostringstream shaderUniformDecl; 1520 std::ostringstream shaderBody; 1521 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1522 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1523 1524 // Generate the uniform declarations for the vertex and fragment shaders 1525 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1526 { 1527 shaderUniformDecl << "layout(std140, binding = " << m_bindings[declNdx] << ") uniform " 1528 << getUniformName(m_uniformName, declNdx) << "\n" 1529 << "{\n" 1530 << " highp vec4 color1;\n" 1531 << " highp vec4 color2;\n" 1532 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1533 } 1534 1535 // Generate the shader body for the vertex and fragment shaders 1536 for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx) // Multiply by two to cover cases for both colors for each UBO 1537 { 1538 const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2)); 1539 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1540 << " {\n" 1541 << " color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n" 1542 << " }\n"; 1543 } 1544 1545 shaderBody << " else\n" 1546 << " {\n" 1547 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1548 << " }\n"; 1549 1550 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1551 << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())) 1552 << glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))); 1553 } 1554 1555 1556 class UBOBindingNegativeCase : public LayoutBindingNegativeCase 1557 { 1558 public: 1559 UBOBindingNegativeCase (Context& context, 1560 const char* name, 1561 const char* desc, 1562 ShaderType shaderType, 1563 TestType testType, 1564 ErrorType errorType); 1565 ~UBOBindingNegativeCase (void); 1566 1567 private: 1568 glu::ShaderProgram* generateShaders (void) const; 1569 }; 1570 1571 UBOBindingNegativeCase::UBOBindingNegativeCase (Context& context, 1572 const char* name, 1573 const char* desc, 1574 ShaderType shaderType, 1575 TestType testType, 1576 ErrorType errorType) 1577 : LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType, GL_MAX_UNIFORM_BUFFER_BINDINGS, GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, GL_MAX_COMBINED_UNIFORM_BLOCKS, "ColorBlock") 1578 { 1579 } 1580 1581 UBOBindingNegativeCase::~UBOBindingNegativeCase (void) 1582 { 1583 deinit(); 1584 } 1585 1586 glu::ShaderProgram* UBOBindingNegativeCase::generateShaders (void) const 1587 { 1588 std::ostringstream vertexUniformDecl; 1589 std::ostringstream fragmentUniformDecl; 1590 std::ostringstream shaderBody; 1591 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1592 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1593 1594 // Generate the uniform declarations for the vertex and fragment shaders 1595 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1596 { 1597 vertexUniformDecl << "layout(std140, binding = " << m_vertexShaderBinding[declNdx] << ") uniform " 1598 << getUniformName(m_uniformName, declNdx) << "\n" 1599 << "{\n" 1600 << " highp vec4 color1;\n" 1601 << " highp vec4 color2;\n" 1602 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1603 1604 fragmentUniformDecl << "layout(std140, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform " 1605 << getUniformName(m_uniformName, declNdx) << "\n" 1606 << "{\n" 1607 << " highp vec4 color1;\n" 1608 << " highp vec4 color2;\n" 1609 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1610 } 1611 1612 // Generate the shader body for the vertex and fragment shaders 1613 for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx) // Multiply by two to cover cases for both colors for each UBO 1614 { 1615 const std::string uname = (arrayInstance ? getUniformName("colors", 0, m_numBindings) : getUniformName("colors", bindNdx/2)); 1616 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1617 << " {\n" 1618 << " color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n" 1619 << " }\n"; 1620 } 1621 1622 shaderBody << " else\n" 1623 << " {\n" 1624 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1625 << " }\n"; 1626 1627 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1628 << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str())) 1629 << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()))); 1630 } 1631 1632 1633 class SSBOBindingRenderCase : public LayoutBindingRenderCase 1634 { 1635 public: 1636 SSBOBindingRenderCase (Context& context, 1637 const char* name, 1638 const char* desc, 1639 ShaderType shaderType, 1640 TestType testType); 1641 ~SSBOBindingRenderCase (void); 1642 1643 void init (void); 1644 void deinit (void); 1645 IterateResult iterate (void); 1646 1647 private: 1648 glu::ShaderProgram* generateShaders (void) const; 1649 1650 std::vector<glw::GLuint> m_buffers; 1651 std::vector<Vec4> m_expectedColors; 1652 }; 1653 1654 SSBOBindingRenderCase::SSBOBindingRenderCase (Context& context, 1655 const char* name, 1656 const char* desc, 1657 ShaderType shaderType, 1658 TestType testType) 1659 : LayoutBindingRenderCase (context, name, desc, shaderType, testType, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, "ColorBuffer") 1660 { 1661 } 1662 1663 SSBOBindingRenderCase::~SSBOBindingRenderCase (void) 1664 { 1665 deinit(); 1666 } 1667 1668 void SSBOBindingRenderCase::init (void) 1669 { 1670 LayoutBindingRenderCase::init(); 1671 1672 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1673 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 1674 1675 // Initialize SSBOs and related data 1676 m_buffers = std::vector<glw::GLuint>(m_numBindings, 0); 1677 gl.genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]); 1678 1679 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1680 { 1681 m_expectedColors.push_back(getRandomColor(rnd)); 1682 m_expectedColors.push_back(getRandomColor(rnd)); 1683 } 1684 1685 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1686 { 1687 gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffers[bufNdx]); 1688 gl.bufferData(GL_SHADER_STORAGE_BUFFER, 2*sizeof(Vec4), &(m_expectedColors[2*bufNdx]), GL_STATIC_DRAW); 1689 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, m_bindings[bufNdx], m_buffers[bufNdx]); 1690 } 1691 1692 GLU_EXPECT_NO_ERROR(gl.getError(), "SSBO setup failed"); 1693 } 1694 1695 void SSBOBindingRenderCase::deinit (void) 1696 { 1697 LayoutBindingRenderCase::deinit(); 1698 1699 // Clean up SSBO data 1700 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1701 { 1702 if (m_buffers[bufNdx]) 1703 { 1704 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffers[bufNdx]); 1705 m_context.getRenderContext().getFunctions().bindBuffer(GL_SHADER_STORAGE_BUFFER, 0); 1706 m_buffers[bufNdx] = 0; 1707 } 1708 } 1709 } 1710 1711 TestCase::IterateResult SSBOBindingRenderCase::iterate (void) 1712 { 1713 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1714 const int iterations = m_numBindings; 1715 const glw::GLenum prop = GL_BUFFER_BINDING; 1716 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1717 bool queryTestPassed = true; 1718 bool imageTestPassed = true; 1719 1720 initRenderState(); 1721 1722 for (int iterNdx = 0; iterNdx < iterations; ++iterNdx) 1723 { 1724 // Query binding point 1725 const std::string name = (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx)); 1726 const glw::GLint binding = m_bindings[iterNdx]; 1727 glw::GLint val = -1; 1728 1729 gl.getProgramResourceiv(m_program->getProgram(), GL_SHADER_STORAGE_BLOCK, gl.getProgramResourceIndex(m_program->getProgram(), GL_SHADER_STORAGE_BLOCK, name.c_str() ), 1, &prop, 1, DE_NULL, &val); 1730 m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage; 1731 GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed"); 1732 1733 if (val != binding) 1734 queryTestPassed = false; 1735 1736 // Draw twice to render both colors within the SSBO 1737 for (int drawCycle = 0; drawCycle < 2; ++drawCycle) 1738 { 1739 // Set the uniform indicating the array index to be used and set the expected color 1740 const int arrayNdx = iterNdx*2 + drawCycle; 1741 gl.uniform1i(m_shaderProgramArrayNdxLoc, arrayNdx); 1742 1743 if (!drawAndVerifyResult(m_expectedColors[arrayNdx])) 1744 imageTestPassed = false; 1745 } 1746 } 1747 1748 setTestResult(queryTestPassed, imageTestPassed); 1749 return STOP; 1750 } 1751 1752 glu::ShaderProgram* SSBOBindingRenderCase::generateShaders (void) const 1753 { 1754 std::ostringstream shaderUniformDecl; 1755 std::ostringstream shaderBody; 1756 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1757 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1758 1759 // Generate the uniform declarations for the vertex and fragment shaders 1760 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1761 { 1762 shaderUniformDecl << "layout(std140, binding = " << m_bindings[declNdx] << ") buffer " 1763 << getUniformName(m_uniformName, declNdx) << "\n" 1764 << "{\n" 1765 << " highp vec4 color1;\n" 1766 << " highp vec4 color2;\n" 1767 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1768 } 1769 1770 // Generate the shader body for the vertex and fragment shaders 1771 for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx) // Multiply by two to cover cases for both colors for each UBO 1772 { 1773 const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2)); 1774 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1775 << " {\n" 1776 << " color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n" 1777 << " }\n"; 1778 } 1779 1780 shaderBody << " else\n" 1781 << " {\n" 1782 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1783 << " }\n"; 1784 1785 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1786 << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())) 1787 << glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))); 1788 } 1789 1790 1791 class SSBOBindingNegativeCase : public LayoutBindingNegativeCase 1792 { 1793 public: 1794 SSBOBindingNegativeCase (Context& context, 1795 const char* name, 1796 const char* desc, 1797 ShaderType shaderType, 1798 TestType testType, 1799 ErrorType errorType); 1800 ~SSBOBindingNegativeCase (void); 1801 1802 private: 1803 glu::ShaderProgram* generateShaders (void) const; 1804 }; 1805 1806 SSBOBindingNegativeCase::SSBOBindingNegativeCase (Context& context, 1807 const char* name, 1808 const char* desc, 1809 ShaderType shaderType, 1810 TestType testType, 1811 ErrorType errorType) 1812 : LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, "ColorBuffer") 1813 { 1814 } 1815 1816 SSBOBindingNegativeCase::~SSBOBindingNegativeCase (void) 1817 { 1818 deinit(); 1819 } 1820 1821 glu::ShaderProgram* SSBOBindingNegativeCase::generateShaders (void) const 1822 { 1823 std::ostringstream vertexUniformDecl; 1824 std::ostringstream fragmentUniformDecl; 1825 std::ostringstream shaderBody; 1826 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1827 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1828 1829 // Generate the uniform declarations for the vertex and fragment shaders 1830 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1831 { 1832 vertexUniformDecl << "layout(std140, binding = " << m_vertexShaderBinding[declNdx] << ") buffer " 1833 << getUniformName(m_uniformName, declNdx) << "\n" 1834 << "{\n" 1835 << " highp vec4 color1;\n" 1836 << " highp vec4 color2;\n" 1837 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1838 1839 fragmentUniformDecl << "layout(std140, binding = " << m_fragmentShaderBinding[declNdx] << ") buffer " 1840 << getUniformName(m_uniformName, declNdx) << "\n" 1841 << "{\n" 1842 << " highp vec4 color1;\n" 1843 << " highp vec4 color2;\n" 1844 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1845 } 1846 1847 // Generate the shader body for the vertex and fragment shaders 1848 for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx) // Multiply by two to cover cases for both colors for each UBO 1849 { 1850 const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2)); 1851 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1852 << " {\n" 1853 << " color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n" 1854 << " }\n"; 1855 } 1856 1857 shaderBody << " else\n" 1858 << " {\n" 1859 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1860 << " }\n"; 1861 1862 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1863 << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str())) 1864 << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()))); 1865 } 1866 1867 1868 } // Anonymous 1869 1870 LayoutBindingTests::LayoutBindingTests (Context& context) 1871 : TestCaseGroup (context, "layout_binding", "Layout binding tests") 1872 { 1873 } 1874 1875 LayoutBindingTests::~LayoutBindingTests (void) 1876 { 1877 } 1878 1879 void LayoutBindingTests::init (void) 1880 { 1881 // Render test groups 1882 tcu::TestCaseGroup* const samplerBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Test sampler layout binding"); 1883 tcu::TestCaseGroup* const sampler2dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler2d", "Test sampler2d layout binding"); 1884 tcu::TestCaseGroup* const sampler3dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler3d", "Test sampler3d layout binding"); 1885 1886 tcu::TestCaseGroup* const imageBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image", "Test image layout binding"); 1887 tcu::TestCaseGroup* const image2dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image2d", "Test image2d layout binding"); 1888 tcu::TestCaseGroup* const image3dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image3d", "Test image3d layout binding"); 1889 1890 tcu::TestCaseGroup* const UBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ubo", "Test UBO layout binding"); 1891 tcu::TestCaseGroup* const SSBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ssbo", "Test SSBO layout binding"); 1892 1893 // Negative test groups 1894 tcu::TestCaseGroup* const negativeBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "negative", "Test layout binding with invalid bindings"); 1895 1896 tcu::TestCaseGroup* const negativeSamplerBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Test sampler layout binding with invalid bindings"); 1897 tcu::TestCaseGroup* const negativeSampler2dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler2d", "Test sampler2d layout binding with invalid bindings"); 1898 tcu::TestCaseGroup* const negativeSampler3dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler3d", "Test sampler3d layout binding with invalid bindings"); 1899 1900 tcu::TestCaseGroup* const negativeImageBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image", "Test image layout binding with invalid bindings"); 1901 tcu::TestCaseGroup* const negativeImage2dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image2d", "Test image2d layout binding with invalid bindings"); 1902 tcu::TestCaseGroup* const negativeImage3dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image3d", "Test image3d layout binding with invalid bindings"); 1903 1904 tcu::TestCaseGroup* const negativeUBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ubo", "Test UBO layout binding with invalid bindings"); 1905 tcu::TestCaseGroup* const negativeSSBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ssbo", "Test SSBO layout binding with invalid bindings"); 1906 1907 static const struct RenderTestType 1908 { 1909 ShaderType shaderType; 1910 TestType testType; 1911 std::string name; 1912 std::string descPostfix; 1913 } s_renderTestTypes[] = 1914 { 1915 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, "vertex_binding_single", "a single instance" }, 1916 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_MAX, "vertex_binding_max", "maximum binding point" }, 1917 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_MULTIPLE, "vertex_binding_multiple", "multiple instances"}, 1918 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, "vertex_binding_array", "an array instance" }, 1919 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_MAX_ARRAY, "vertex_binding_max_array", "an array instance with maximum binding point" }, 1920 1921 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, "fragment_binding_single", "a single instance" }, 1922 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MAX, "fragment_binding_max", "maximum binding point" }, 1923 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MULTIPLE, "fragment_binding_multiple", "multiple instances"}, 1924 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, "fragment_binding_array", "an array instance" }, 1925 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MAX_ARRAY, "fragment_binding_max_array", "an array instance with maximum binding point" }, 1926 }; 1927 1928 static const struct NegativeTestType 1929 { 1930 ShaderType shaderType; 1931 TestType testType; 1932 LayoutBindingNegativeCase::ErrorType errorType; 1933 std::string name; 1934 std::string descPostfix; 1935 } s_negativeTestTypes[] = 1936 { 1937 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "vertex_binding_over_max", "over maximum binding point"}, 1938 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "fragment_binding_over_max", "over maximum binding point"}, 1939 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "vertex_binding_neg", "negative binding point"}, 1940 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "fragment_binding_neg", "negative binding point"}, 1941 1942 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "vertex_binding_over_max_array", "over maximum binding point"}, 1943 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "fragment_binding_over_max_array", "over maximum binding point"}, 1944 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "vertex_binding_neg_array", "negative binding point"}, 1945 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "fragment_binding_neg_array", "negative binding point"}, 1946 1947 { SHADERTYPE_BOTH, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY, "binding_contradictory", "contradictory binding points"}, 1948 { SHADERTYPE_BOTH, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY, "binding_contradictory_array", "contradictory binding points"}, 1949 }; 1950 1951 // Render tests 1952 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_renderTestTypes); ++testNdx) 1953 { 1954 const RenderTestType& test = s_renderTestTypes[testNdx]; 1955 1956 // Render sampler binding tests 1957 sampler2dBindingTestGroup->addChild(new SamplerBindingRenderCase(m_context, test.name.c_str(), ("Sampler2D layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType, GL_SAMPLER_2D, GL_TEXTURE_2D)); 1958 sampler3dBindingTestGroup->addChild(new SamplerBindingRenderCase(m_context, test.name.c_str(), ("Sampler3D layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType, GL_SAMPLER_3D, GL_TEXTURE_3D)); 1959 1960 // Render image binding tests 1961 image2dBindingTestGroup->addChild(new ImageBindingRenderCase(m_context, test.name.c_str(), ("Image2D layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType, GL_IMAGE_2D, GL_TEXTURE_2D)); 1962 image3dBindingTestGroup->addChild(new ImageBindingRenderCase(m_context, test.name.c_str(), ("Image3D layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType, GL_IMAGE_3D, GL_TEXTURE_3D)); 1963 1964 // Render UBO binding tests 1965 UBOBindingTestGroup->addChild(new UBOBindingRenderCase(m_context, test.name.c_str(), ("UBO layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType)); 1966 1967 // Render SSBO binding tests 1968 SSBOBindingTestGroup->addChild(new SSBOBindingRenderCase(m_context, test.name.c_str(), ("SSBO layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType)); 1969 } 1970 1971 // Negative binding tests 1972 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_negativeTestTypes); ++testNdx) 1973 { 1974 const NegativeTestType& test = s_negativeTestTypes[testNdx]; 1975 1976 // Negative sampler binding tests 1977 negativeSampler2dBindingTestGroup->addChild(new SamplerBindingNegativeCase(m_context, test.name.c_str(), ("Invalid sampler2d layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType, GL_SAMPLER_2D)); 1978 negativeSampler3dBindingTestGroup->addChild(new SamplerBindingNegativeCase(m_context, test.name.c_str(), ("Invalid sampler3d layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType, GL_SAMPLER_3D)); 1979 1980 // Negative image binding tests 1981 negativeImage2dBindingTestGroup->addChild(new ImageBindingNegativeCase(m_context, test.name.c_str(), ("Invalid image2d layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType, GL_IMAGE_2D)); 1982 negativeImage3dBindingTestGroup->addChild(new ImageBindingNegativeCase(m_context, test.name.c_str(), ("Invalid image3d layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType, GL_IMAGE_3D)); 1983 1984 // Negative UBO binding tests 1985 negativeUBOBindingTestGroup->addChild(new UBOBindingNegativeCase(m_context, test.name.c_str(), ("Invalid UBO layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType)); 1986 1987 // Negative SSBO binding tests 1988 negativeSSBOBindingTestGroup->addChild(new SSBOBindingNegativeCase(m_context, test.name.c_str(), ("Invalid SSBO layout binding using " + test.descPostfix).c_str(), test.shaderType, test.testType, test.errorType)); 1989 } 1990 1991 samplerBindingTestGroup->addChild(sampler2dBindingTestGroup); 1992 samplerBindingTestGroup->addChild(sampler3dBindingTestGroup); 1993 1994 imageBindingTestGroup->addChild(image2dBindingTestGroup); 1995 imageBindingTestGroup->addChild(image3dBindingTestGroup); 1996 1997 negativeSamplerBindingTestGroup->addChild(negativeSampler2dBindingTestGroup); 1998 negativeSamplerBindingTestGroup->addChild(negativeSampler3dBindingTestGroup); 1999 2000 negativeImageBindingTestGroup->addChild(negativeImage2dBindingTestGroup); 2001 negativeImageBindingTestGroup->addChild(negativeImage3dBindingTestGroup); 2002 2003 negativeBindingTestGroup->addChild(negativeSamplerBindingTestGroup); 2004 negativeBindingTestGroup->addChild(negativeUBOBindingTestGroup); 2005 negativeBindingTestGroup->addChild(negativeSSBOBindingTestGroup); 2006 negativeBindingTestGroup->addChild(negativeImageBindingTestGroup); 2007 2008 addChild(samplerBindingTestGroup); 2009 addChild(UBOBindingTestGroup); 2010 addChild(SSBOBindingTestGroup); 2011 addChild(imageBindingTestGroup); 2012 addChild(negativeBindingTestGroup); 2013 } 2014 2015 } // Functional 2016 } // gles31 2017 } // deqp 2018