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 45using tcu::TestLog; 46using tcu::Vec2; 47using tcu::Vec3; 48using tcu::Vec4; 49 50namespace deqp 51{ 52namespace gles31 53{ 54namespace Functional 55{ 56namespace 57{ 58 59enum 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 70enum ShaderType 71{ 72 SHADERTYPE_VERTEX = 0, 73 SHADERTYPE_FRAGMENT, 74 SHADERTYPE_BOTH, 75 76 SHADERTYPE_LAST, 77}; 78 79enum 80{ 81 MAX_UNIFORM_MULTIPLE_INSTANCES = 7, 82 MAX_UNIFORM_ARRAY_SIZE = 7, 83}; 84 85std::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 125std::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 181std::string getUniformName (const std::string& name, int declNdx) 182{ 183 return name + de::toString(declNdx); 184} 185 186std::string getUniformName (const std::string& name, int declNdx, int arrNdx) 187{ 188 return name + de::toString(declNdx) + "[" + de::toString(arrNdx) + "]"; 189} 190 191Vec4 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 199class LayoutBindingRenderCase : public TestCase 200{ 201public: 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 224protected: 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 250private: 251 void initBindingPoints (int minBindingPoint, int numBindingPoints); 252}; 253 254LayoutBindingRenderCase::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 282LayoutBindingRenderCase::~LayoutBindingRenderCase (void) 283{ 284 deinit(); 285} 286 287void 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 422void 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 446void 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 517void 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 527bool LayoutBindingRenderCase::drawAndVerifyResult (const Vec4& expectedColor) 528{ 529 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 530 tcu::Surface reference (TEST_RENDER_WIDTH, TEST_RENDER_HEIGHT); 531 532 // the point of these test is to check layout_binding. For this purpose, we can use quite 533 // large thresholds. 534 const tcu::RGBA surfaceThreshold = m_context.getRenderContext().getRenderTarget().getPixelFormat().getColorThreshold(); 535 const tcu::RGBA compareThreshold = tcu::RGBA(de::clamp(2 * surfaceThreshold.getRed(), 0, 255), 536 de::clamp(2 * surfaceThreshold.getGreen(), 0, 255), 537 de::clamp(2 * surfaceThreshold.getBlue(), 0, 255), 538 de::clamp(2 * surfaceThreshold.getAlpha(), 0, 255)); 539 540 gl.clear(GL_COLOR_BUFFER_BIT); 541 542 // Draw 543 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL); 544 GLU_EXPECT_NO_ERROR(gl.getError(), "Drawing failed"); 545 546 // Verify 547 tcu::Surface result(TEST_RENDER_WIDTH, TEST_RENDER_HEIGHT); 548 m_testCtx.getLog() << TestLog::Message << "Reading pixels" << TestLog::EndMessage; 549 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); 550 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed"); 551 552 tcu::clear(reference.getAccess(), expectedColor); 553 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output image, fragment output color is " << expectedColor << tcu::TestLog::EndMessage; 554 555 return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Render result", "Result verification", reference, result, compareThreshold, tcu::COMPARE_LOG_RESULT); 556} 557 558void LayoutBindingRenderCase::setTestResult (bool queryTestPassed, bool imageTestPassed) 559{ 560 if (queryTestPassed && imageTestPassed) 561 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 562 else if (!queryTestPassed && !imageTestPassed) 563 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more binding point queries and image comparisons failed"); 564 else if (!queryTestPassed) 565 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more binding point queries failed"); 566 else 567 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more image comparisons failed"); 568} 569 570class LayoutBindingNegativeCase : public TestCase 571{ 572public: 573 enum ErrorType 574 { 575 ERRORTYPE_OVER_MAX_UNITS = 0, 576 ERRORTYPE_LESS_THAN_ZERO, 577 ERRORTYPE_CONTRADICTORY, 578 579 ERRORTYPE_LAST, 580 }; 581 582 LayoutBindingNegativeCase (Context& context, 583 const char* name, 584 const char* desc, 585 ShaderType shaderType, 586 TestType testType, 587 ErrorType errorType, 588 glw::GLenum maxBindingPointEnum, 589 glw::GLenum maxVertexUnitsEnum, 590 glw::GLenum maxFragmentUnitsEnum, 591 glw::GLenum maxCombinedUnitsEnum, 592 const std::string& uniformName); 593 virtual ~LayoutBindingNegativeCase (void); 594 595 virtual void init (void); 596 virtual void deinit (void); 597 virtual IterateResult iterate (void); 598 599protected: 600 virtual glu::ShaderProgram* generateShaders (void) const = 0; 601 602 const glu::ShaderProgram* m_program; 603 const ShaderType m_shaderType; 604 const TestType m_testType; 605 const ErrorType m_errorType; 606 const glw::GLenum m_maxBindingPointEnum; 607 const glw::GLenum m_maxVertexUnitsEnum; 608 const glw::GLenum m_maxFragmentUnitsEnum; 609 const glw::GLenum m_maxCombinedUnitsEnum; 610 const std::string m_uniformName; 611 glw::GLint m_numBindings; 612 std::vector<glw::GLint> m_vertexShaderBinding; 613 std::vector<glw::GLint> m_fragmentShaderBinding; 614 615private: 616 void initBindingPoints (int minBindingPoint, int numBindingPoints); 617}; 618 619LayoutBindingNegativeCase::LayoutBindingNegativeCase (Context& context, 620 const char* name, 621 const char* desc, 622 ShaderType shaderType, 623 TestType testType, 624 ErrorType errorType, 625 glw::GLenum maxBindingPointEnum, 626 glw::GLenum maxVertexUnitsEnum, 627 glw::GLenum maxFragmentUnitsEnum, 628 glw::GLenum maxCombinedUnitsEnum, 629 const std::string& uniformName) 630 : TestCase (context, name, desc) 631 , m_program (DE_NULL) 632 , m_shaderType (shaderType) 633 , m_testType (testType) 634 , m_errorType (errorType) 635 , m_maxBindingPointEnum (maxBindingPointEnum) 636 , m_maxVertexUnitsEnum (maxVertexUnitsEnum) 637 , m_maxFragmentUnitsEnum (maxFragmentUnitsEnum) 638 , m_maxCombinedUnitsEnum (maxCombinedUnitsEnum) 639 , m_uniformName (uniformName) 640 , m_numBindings (0) 641{ 642} 643 644LayoutBindingNegativeCase::~LayoutBindingNegativeCase (void) 645{ 646 deinit(); 647} 648 649void LayoutBindingNegativeCase::init (void) 650{ 651 // Decide appropriate binding points for the vertex and fragment shaders 652 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 653 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 654 glw::GLint numBindingPoints = 0; // Number of binding points 655 glw::GLint maxVertexUnits = 0; // Available uniforms in the vertex shader 656 glw::GLint maxFragmentUnits = 0; // Available uniforms in the fragment shader 657 glw::GLint maxCombinedUnits = 0; // Available uniforms in all the shader stages combined 658 glw::GLint maxUnits = 0; // Maximum available uniforms for this test 659 660 gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits); 661 gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits); 662 gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits); 663 gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints); 664 GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed"); 665 666 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits << tcu::TestLog::EndMessage; 667 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits << tcu::TestLog::EndMessage; 668 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits << tcu::TestLog::EndMessage; 669 m_testCtx.getLog() << tcu::TestLog::Message << "Maximum binding point for uniform type: " << numBindingPoints-1 << tcu::TestLog::EndMessage; 670 671 // Select maximum number of uniforms used for the test 672 switch (m_shaderType) 673 { 674 case SHADERTYPE_VERTEX: 675 maxUnits = maxVertexUnits; 676 break; 677 678 case SHADERTYPE_FRAGMENT: 679 maxUnits = maxFragmentUnits; 680 break; 681 682 case SHADERTYPE_BOTH: 683 maxUnits = de::min(de::min(maxVertexUnits, maxFragmentUnits), maxCombinedUnits/2); 684 break; 685 686 default: 687 DE_ASSERT(false); 688 } 689 690 // Select the number of uniforms (= bindings) used for this test 691 switch (m_testType) 692 { 693 case TESTTYPE_BINDING_SINGLE: 694 case TESTTYPE_BINDING_MAX: 695 m_numBindings = 1; 696 break; 697 698 case TESTTYPE_BINDING_MULTIPLE: 699 case TESTTYPE_BINDING_ARRAY: 700 case TESTTYPE_BINDING_MAX_ARRAY: 701 if (m_errorType == ERRORTYPE_CONTRADICTORY) 702 { 703 // leave room for contradictory case 704 if (maxUnits < 3) 705 throw tcu::NotSupportedError("Not enough uniforms available for test"); 706 m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits-1)); 707 } 708 else 709 { 710 if (maxUnits < 2) 711 throw tcu::NotSupportedError("Not enough uniforms available for test"); 712 m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits)); 713 } 714 break; 715 716 default: 717 DE_ASSERT(false); 718 } 719 720 // Check that we have enough uniforms in different shaders to perform the tests 721 if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_BOTH)) && (maxVertexUnits < m_numBindings) ) 722 throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test"); 723 if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_BOTH)) && (maxFragmentUnits < m_numBindings) ) 724 throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test"); 725 if ( (m_shaderType == SHADERTYPE_BOTH) && (maxCombinedUnits < m_numBindings*2) ) 726 throw tcu::NotSupportedError("Not enough uniforms available for test"); 727 728 // Check that we have enough binding points to perform the tests 729 if (numBindingPoints < m_numBindings) 730 throw tcu::NotSupportedError("Not enough binding points available for test"); 731 if (m_errorType == ERRORTYPE_CONTRADICTORY && numBindingPoints == m_numBindings) 732 throw tcu::NotSupportedError("Not enough binding points available for test"); 733 734 // Initialize the binding points i.e. populate the two binding point vectors 735 initBindingPoints(0, numBindingPoints); 736 737 // Generate the shader program - note: this must be done after deciding the binding points 738 DE_ASSERT(!m_program); 739 m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shaders" << tcu::TestLog::EndMessage; 740 m_program = generateShaders(); 741 m_testCtx.getLog() << *m_program; 742} 743 744void LayoutBindingNegativeCase::deinit (void) 745{ 746 if (m_program) 747 { 748 delete m_program; 749 m_program = DE_NULL; 750 } 751} 752 753TestCase::IterateResult LayoutBindingNegativeCase::iterate (void) 754{ 755 bool pass = false; 756 std::string failMessage; 757 758 switch (m_errorType) 759 { 760 case ERRORTYPE_CONTRADICTORY: // Contradictory binding points should cause a link-time error 761 if (!(m_program->getProgramInfo()).linkOk) 762 pass = true; 763 failMessage = "Test failed - expected a link-time error"; 764 break; 765 766 case ERRORTYPE_LESS_THAN_ZERO: // Out of bounds binding points should cause a compile-time error 767 case ERRORTYPE_OVER_MAX_UNITS: 768 if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk || !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT)).compileOk) 769 pass = true; 770 failMessage = "Test failed - expected a compile-time error"; 771 break; 772 773 default: 774 DE_ASSERT(false); 775 } 776 777 if (pass) 778 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 779 else 780 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, failMessage.c_str()); 781 782 return STOP; 783} 784 785void LayoutBindingNegativeCase::initBindingPoints (int minBindingPoint, int numBindingPoints) 786{ 787 de::Random rnd(deStringHash(getName()) ^ 0xff23a4); 788 789 switch (m_errorType) 790 { 791 case ERRORTYPE_OVER_MAX_UNITS: // Select a binding point that is 1 over the maximum 792 { 793 m_vertexShaderBinding.push_back(numBindingPoints+1-m_numBindings); 794 m_fragmentShaderBinding.push_back(numBindingPoints+1-m_numBindings); 795 break; 796 } 797 798 case ERRORTYPE_LESS_THAN_ZERO: // Select a random negative binding point 799 { 800 const glw::GLint binding = -rnd.getInt(1, m_numBindings); 801 m_vertexShaderBinding.push_back(binding); 802 m_fragmentShaderBinding.push_back(binding); 803 break; 804 } 805 806 case ERRORTYPE_CONTRADICTORY: // Select two valid, but contradictory binding points 807 { 808 m_vertexShaderBinding.push_back(minBindingPoint); 809 m_fragmentShaderBinding.push_back((minBindingPoint+1)%numBindingPoints); 810 DE_ASSERT(m_vertexShaderBinding.back() != m_fragmentShaderBinding.back()); 811 break; 812 } 813 814 default: 815 DE_ASSERT(false); 816 } 817 818 // In case we are testing with multiple uniforms populate the rest of the binding points 819 for (int ndx = 1; ndx < m_numBindings; ++ndx) 820 { 821 m_vertexShaderBinding.push_back(m_vertexShaderBinding.front()+ndx); 822 m_fragmentShaderBinding.push_back(m_fragmentShaderBinding.front()+ndx); 823 } 824} 825 826class SamplerBindingRenderCase : public LayoutBindingRenderCase 827{ 828public: 829 SamplerBindingRenderCase (Context& context, const char* name, const char* desc, ShaderType shaderType, TestType testType, glw::GLenum samplerType, glw::GLenum textureType); 830 ~SamplerBindingRenderCase (void); 831 832 void init (void); 833 void deinit (void); 834 IterateResult iterate (void); 835 836private: 837 glu::ShaderProgram* generateShaders (void) const; 838 glu::DataType getSamplerTexCoordType (void) const; 839 void initializeTexture (glw::GLint bindingPoint, glw::GLint textureName, const Vec4& color) const; 840 841 const glw::GLenum m_samplerType; 842 const glw::GLenum m_textureType; 843 844 std::vector<glw::GLuint> m_textures; 845 std::vector<Vec4> m_textureColors; 846}; 847 848 849SamplerBindingRenderCase::SamplerBindingRenderCase (Context& context, 850 const char* name, 851 const char* desc, 852 ShaderType shaderType, 853 TestType testType, 854 glw::GLenum samplerType, 855 glw::GLenum textureType) 856 : 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") 857 , m_samplerType (samplerType) 858 , m_textureType (textureType) 859{ 860} 861 862SamplerBindingRenderCase::~SamplerBindingRenderCase (void) 863{ 864 deinit(); 865} 866 867void SamplerBindingRenderCase::init (void) 868{ 869 LayoutBindingRenderCase::init(); 870 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 871 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 872 873 874 // Initialize texture resources 875 m_textures = std::vector<glw::GLuint>(m_numBindings, 0); 876 877 // Texture colors 878 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 879 m_textureColors.push_back(getRandomColor(rnd)); 880 881 // Textures 882 gl.genTextures((glw::GLsizei)m_textures.size(), &m_textures[0]); 883 884 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 885 initializeTexture(m_bindings[texNdx], m_textures[texNdx], m_textureColors[texNdx]); 886 887 gl.activeTexture(GL_TEXTURE0); 888} 889 890void SamplerBindingRenderCase::deinit(void) 891{ 892 LayoutBindingRenderCase::deinit(); 893 894 // Clean up texture data 895 for (int i = 0; i < (int)m_textures.size(); ++i) 896 { 897 if (m_textures[i]) 898 { 899 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_textures[i]); 900 m_context.getRenderContext().getFunctions().bindTexture(m_textureType, 0); 901 } 902 } 903} 904 905TestCase::IterateResult SamplerBindingRenderCase::iterate (void) 906{ 907 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 908 const int iterations = m_numBindings; 909 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 910 bool imageTestPassed = true; 911 bool queryTestPassed = true; 912 913 // Set the viewport and enable the shader program 914 initRenderState(); 915 916 for (int iterNdx = 0; iterNdx < iterations; ++iterNdx) 917 { 918 // Set the uniform value indicating the current array index 919 gl.uniform1i(m_shaderProgramArrayNdxLoc, iterNdx); 920 921 // Query binding point 922 const std::string name = arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx); 923 const glw::GLint binding = m_bindings[iterNdx]; 924 glw::GLint val = -1; 925 926 gl.getUniformiv(m_program->getProgram(), gl.getUniformLocation(m_program->getProgram(), name.c_str()), &val); 927 m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage; 928 GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed"); 929 930 // Draw and verify 931 if (val != binding) 932 queryTestPassed = false; 933 if (!drawAndVerifyResult(m_textureColors[iterNdx])) 934 imageTestPassed = false; 935 } 936 937 setTestResult(queryTestPassed, imageTestPassed); 938 return STOP; 939} 940 941glu::ShaderProgram* SamplerBindingRenderCase::generateShaders (void) const 942{ 943 std::ostringstream shaderUniformDecl; 944 std::ostringstream shaderBody; 945 946 const std::string texCoordType = glu::getDataTypeName(getSamplerTexCoordType()); 947 const std::string samplerType = glu::getDataTypeName(glu::getDataTypeFromGLType(m_samplerType)); 948 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY) ? true : false; 949 const int numDeclarations = arrayInstance ? 1 : m_numBindings; 950 951 // Generate the uniform declarations for the vertex and fragment shaders 952 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 953 { 954 shaderUniformDecl << "layout(binding = " << m_bindings[declNdx] << ") uniform highp " << samplerType << " " 955 << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 956 } 957 958 // Generate the shader body for the vertex and fragment shaders 959 for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx) 960 { 961 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 962 << " {\n" 963 << " color = texture(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0.5));\n" 964 << " }\n"; 965 } 966 967 shaderBody << " else\n" 968 << " {\n" 969 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 970 << " }\n"; 971 972 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 973 << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())) 974 << glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))); 975} 976 977void SamplerBindingRenderCase::initializeTexture (glw::GLint bindingPoint, glw::GLint textureName, const Vec4& color) const 978{ 979 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 980 981 gl.activeTexture(GL_TEXTURE0 + bindingPoint); 982 gl.bindTexture(m_textureType, textureName); 983 gl.texParameteri(m_textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 984 985 switch (m_textureType) 986 { 987 case GL_TEXTURE_2D: 988 { 989 tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 990 tcu::clear(level.getAccess(), color); 991 glu::texImage2D(m_context.getRenderContext(), m_textureType, 0, GL_RGBA8, level.getAccess()); 992 break; 993 } 994 995 case GL_TEXTURE_3D: 996 { 997 tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 998 tcu::clear(level.getAccess(), color); 999 glu::texImage3D(m_context.getRenderContext(), m_textureType, 0, GL_RGBA8, level.getAccess()); 1000 break; 1001 } 1002 1003 default: 1004 DE_ASSERT(false); 1005 } 1006 1007 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture initialization failed"); 1008} 1009 1010glu::DataType SamplerBindingRenderCase::getSamplerTexCoordType (void) const 1011{ 1012 switch (m_samplerType) 1013 { 1014 case GL_SAMPLER_2D: 1015 return glu::TYPE_FLOAT_VEC2; 1016 1017 case GL_SAMPLER_3D: 1018 return glu::TYPE_FLOAT_VEC3; 1019 1020 default: 1021 DE_ASSERT(false); 1022 return glu::TYPE_INVALID; 1023 } 1024} 1025 1026 1027class SamplerBindingNegativeCase : public LayoutBindingNegativeCase 1028{ 1029public: 1030 SamplerBindingNegativeCase (Context& context, 1031 const char* name, 1032 const char* desc, 1033 ShaderType shaderType, 1034 TestType testType, 1035 ErrorType errorType, 1036 glw::GLenum samplerType); 1037 ~SamplerBindingNegativeCase (void); 1038 1039private: 1040 glu::ShaderProgram* generateShaders (void) const; 1041 glu::DataType getSamplerTexCoordType (void) const; 1042 1043 const glw::GLenum m_samplerType; 1044}; 1045 1046SamplerBindingNegativeCase::SamplerBindingNegativeCase (Context& context, 1047 const char* name, 1048 const char* desc, 1049 ShaderType shaderType, 1050 TestType testType, 1051 ErrorType errorType, 1052 glw::GLenum samplerType) 1053 : 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") 1054 , m_samplerType (samplerType) 1055{ 1056} 1057 1058SamplerBindingNegativeCase::~SamplerBindingNegativeCase (void) 1059{ 1060 LayoutBindingNegativeCase::deinit(); 1061} 1062 1063glu::ShaderProgram* SamplerBindingNegativeCase::generateShaders (void) const 1064{ 1065 std::ostringstream vertexUniformDecl; 1066 std::ostringstream fragmentUniformDecl; 1067 std::ostringstream shaderBody; 1068 1069 const std::string texCoordType = glu::getDataTypeName(getSamplerTexCoordType()); 1070 const std::string samplerType = glu::getDataTypeName(glu::getDataTypeFromGLType(m_samplerType)); 1071 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1072 const int numDeclarations = arrayInstance ? 1 : m_numBindings; 1073 1074 // Generate the uniform declarations for the vertex and fragment shaders 1075 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1076 { 1077 vertexUniformDecl << "layout(binding = " << m_vertexShaderBinding[declNdx] << ") uniform highp " << samplerType 1078 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1079 fragmentUniformDecl << "layout(binding = " << m_fragmentShaderBinding[declNdx] << ") uniform highp " << samplerType 1080 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1081 } 1082 1083 // Generate the shader body for the vertex and fragment shaders 1084 for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx) 1085 { 1086 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1087 << " {\n" 1088 << " color = texture(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0.5));\n" 1089 << " }\n"; 1090 } 1091 1092 shaderBody << " else\n" 1093 << " {\n" 1094 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1095 << " }\n"; 1096 1097 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1098 << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str())) 1099 << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()))); 1100} 1101 1102glu::DataType SamplerBindingNegativeCase::getSamplerTexCoordType(void) const 1103{ 1104 switch (m_samplerType) 1105 { 1106 case GL_SAMPLER_2D: 1107 return glu::TYPE_FLOAT_VEC2; 1108 1109 case GL_SAMPLER_3D: 1110 return glu::TYPE_FLOAT_VEC3; 1111 1112 default: 1113 DE_ASSERT(false); 1114 return glu::TYPE_INVALID; 1115 } 1116} 1117 1118class ImageBindingRenderCase : public LayoutBindingRenderCase 1119{ 1120public: 1121 ImageBindingRenderCase (Context& context, 1122 const char* name, 1123 const char* desc, 1124 ShaderType shaderType, 1125 TestType testType, 1126 glw::GLenum imageType, 1127 glw::GLenum textureType); 1128 ~ImageBindingRenderCase (void); 1129 1130 void init (void); 1131 void deinit (void); 1132 IterateResult iterate (void); 1133 1134private: 1135 glu::ShaderProgram* generateShaders (void) const; 1136 void initializeImage (glw::GLint imageBindingPoint, glw::GLint textureBindingPoint, glw::GLint textureName, const Vec4& color) const; 1137 glu::DataType getImageTexCoordType (void) const; 1138 1139 const glw::GLenum m_imageType; 1140 const glw::GLenum m_textureType; 1141 1142 std::vector<glw::GLuint> m_textures; 1143 std::vector<Vec4> m_textureColors; 1144}; 1145 1146 1147ImageBindingRenderCase::ImageBindingRenderCase (Context& context, 1148 const char* name, 1149 const char* desc, 1150 ShaderType shaderType, 1151 TestType testType, 1152 glw::GLenum imageType, 1153 glw::GLenum textureType) 1154 : 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") 1155 , m_imageType (imageType) 1156 , m_textureType (textureType) 1157{ 1158} 1159 1160ImageBindingRenderCase::~ImageBindingRenderCase (void) 1161{ 1162 deinit(); 1163} 1164 1165void ImageBindingRenderCase::init (void) 1166{ 1167 LayoutBindingRenderCase::init(); 1168 1169 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1170 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 1171 1172 // Initialize image / texture resources 1173 m_textures = std::vector<glw::GLuint>(m_numBindings, 0); 1174 1175 // Texture colors 1176 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 1177 m_textureColors.push_back(getRandomColor(rnd)); 1178 1179 // Image textures 1180 gl.genTextures(m_numBindings, &m_textures[0]); 1181 1182 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 1183 initializeImage(m_bindings[texNdx], texNdx, m_textures[texNdx], m_textureColors[texNdx]); 1184} 1185 1186void ImageBindingRenderCase::deinit (void) 1187{ 1188 LayoutBindingRenderCase::deinit(); 1189 1190 // Clean up texture data 1191 for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx) 1192 { 1193 if (m_textures[texNdx]) 1194 { 1195 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_textures[texNdx]); 1196 m_context.getRenderContext().getFunctions().bindTexture(m_textureType, 0); 1197 } 1198 } 1199} 1200 1201TestCase::IterateResult ImageBindingRenderCase::iterate (void) 1202{ 1203 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1204 const int iterations = m_numBindings; 1205 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1206 bool queryTestPassed = true; 1207 bool imageTestPassed = true; 1208 1209 // Set the viewport and enable the shader program 1210 initRenderState(); 1211 1212 for (int iterNdx = 0; iterNdx < iterations; ++iterNdx) 1213 { 1214 // Set the uniform value indicating the current array index 1215 gl.uniform1i(m_shaderProgramArrayNdxLoc, iterNdx); 1216 1217 const std::string name = (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx)); 1218 const glw::GLint binding = m_bindings[iterNdx]; 1219 glw::GLint val = -1; 1220 1221 gl.getUniformiv(m_program->getProgram(), gl.getUniformLocation(m_program->getProgram(), name.c_str()), &val); 1222 m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage; 1223 GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed"); 1224 1225 // Draw and verify 1226 if (val != binding) 1227 queryTestPassed = false; 1228 if (!drawAndVerifyResult(m_textureColors[iterNdx])) 1229 imageTestPassed = false; 1230 } 1231 1232 setTestResult(queryTestPassed, imageTestPassed); 1233 return STOP; 1234} 1235 1236void ImageBindingRenderCase::initializeImage (glw::GLint imageBindingPoint, glw::GLint textureBindingPoint, glw::GLint textureName, const Vec4& color) const 1237{ 1238 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1239 1240 gl.activeTexture(GL_TEXTURE0 + textureBindingPoint); 1241 gl.bindTexture(m_textureType, textureName); 1242 gl.texParameteri(m_textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1243 1244 switch (m_textureType) 1245 { 1246 case GL_TEXTURE_2D: 1247 { 1248 tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 1249 tcu::clear(level.getAccess(), color); 1250 gl.texStorage2D(m_textureType, 1, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 1251 gl.texSubImage2D(m_textureType, 0, 0, 0, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, level.getAccess().getDataPtr()); 1252 break; 1253 } 1254 1255 case GL_TEXTURE_3D: 1256 { 1257 tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 1258 tcu::clear(level.getAccess(), color); 1259 gl.texStorage3D(m_textureType, 1, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE); 1260 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()); 1261 break; 1262 } 1263 1264 default: 1265 DE_ASSERT(false); 1266 } 1267 1268 gl.bindTexture(m_textureType, 0); 1269 gl.bindImageTexture(imageBindingPoint, textureName, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA8); 1270 GLU_EXPECT_NO_ERROR(gl.getError(), "Image initialization failed"); 1271} 1272 1273glu::ShaderProgram* ImageBindingRenderCase::generateShaders (void) const 1274{ 1275 std::ostringstream shaderUniformDecl; 1276 std::ostringstream shaderBody; 1277 1278 const std::string texCoordType = glu::getDataTypeName(getImageTexCoordType()); 1279 const std::string imageType = glu::getDataTypeName(glu::getDataTypeFromGLType(m_imageType)); 1280 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY) ? true : false; 1281 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1282 1283 // Generate the uniform declarations for the vertex and fragment shaders 1284 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1285 { 1286 shaderUniformDecl << "layout(rgba8, binding = " << m_bindings[declNdx] << ") uniform readonly highp " << imageType 1287 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1288 } 1289 1290 // Generate the shader body for the vertex and fragment shaders 1291 for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx) 1292 { 1293 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1294 << " {\n" 1295 << " color = imageLoad(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0));\n" 1296 << " }\n"; 1297 } 1298 1299 shaderBody << " else\n" 1300 << " {\n" 1301 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1302 << " }\n"; 1303 1304 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1305 << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())) 1306 << glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))); 1307} 1308 1309glu::DataType ImageBindingRenderCase::getImageTexCoordType(void) const 1310{ 1311 switch (m_imageType) 1312 { 1313 case GL_IMAGE_2D: 1314 return glu::TYPE_INT_VEC2; 1315 1316 case GL_IMAGE_3D: 1317 return glu::TYPE_INT_VEC3; 1318 1319 default: 1320 DE_ASSERT(false); 1321 return glu::TYPE_INVALID; 1322 } 1323} 1324 1325 1326class ImageBindingNegativeCase : public LayoutBindingNegativeCase 1327{ 1328public: 1329 ImageBindingNegativeCase (Context& context, 1330 const char* name, 1331 const char* desc, 1332 ShaderType shaderType, 1333 TestType testType, 1334 ErrorType errorType, 1335 glw::GLenum imageType); 1336 ~ImageBindingNegativeCase (void); 1337 1338private: 1339 glu::ShaderProgram* generateShaders (void) const; 1340 glu::DataType getImageTexCoordType (void) const; 1341 1342 const glw::GLenum m_imageType; 1343}; 1344 1345ImageBindingNegativeCase::ImageBindingNegativeCase (Context& context, 1346 const char* name, 1347 const char* desc, 1348 ShaderType shaderType, 1349 TestType testType, 1350 ErrorType errorType, 1351 glw::GLenum imageType) 1352 : 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") 1353 , m_imageType (imageType) 1354{ 1355} 1356 1357ImageBindingNegativeCase::~ImageBindingNegativeCase (void) 1358{ 1359 deinit(); 1360} 1361 1362glu::ShaderProgram* ImageBindingNegativeCase::generateShaders (void) const 1363{ 1364 std::ostringstream vertexUniformDecl; 1365 std::ostringstream fragmentUniformDecl; 1366 std::ostringstream shaderBody; 1367 1368 const std::string texCoordType = glu::getDataTypeName(getImageTexCoordType()); 1369 const std::string imageType = glu::getDataTypeName(glu::getDataTypeFromGLType(m_imageType)); 1370 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1371 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1372 1373 // Generate the uniform declarations for the vertex and fragment shaders 1374 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1375 { 1376 vertexUniformDecl << "layout(rgba8, binding = " << m_vertexShaderBinding[declNdx] << ") uniform readonly highp " << imageType 1377 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1378 fragmentUniformDecl << "layout(rgba8, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform readonly highp " << imageType 1379 << " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n"; 1380 } 1381 1382 // Generate the shader body for the vertex and fragment shaders 1383 for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx) 1384 { 1385 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1386 << " {\n" 1387 << " color = imageLoad(" << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) : getUniformName(m_uniformName, bindNdx)) << ", " << texCoordType << "(0));\n" 1388 << " }\n"; 1389 } 1390 1391 shaderBody << " else\n" 1392 << " {\n" 1393 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1394 << " }\n"; 1395 1396 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1397 << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str())) 1398 << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()))); 1399} 1400 1401glu::DataType ImageBindingNegativeCase::getImageTexCoordType(void) const 1402{ 1403 switch (m_imageType) 1404 { 1405 case GL_IMAGE_2D: 1406 return glu::TYPE_INT_VEC2; 1407 1408 case GL_IMAGE_3D: 1409 return glu::TYPE_INT_VEC3; 1410 1411 default: 1412 DE_ASSERT(false); 1413 return glu::TYPE_INVALID; 1414 } 1415} 1416 1417 1418class UBOBindingRenderCase : public LayoutBindingRenderCase 1419{ 1420public: 1421 UBOBindingRenderCase (Context& context, 1422 const char* name, 1423 const char* desc, 1424 ShaderType shaderType, 1425 TestType testType); 1426 ~UBOBindingRenderCase (void); 1427 1428 void init (void); 1429 void deinit (void); 1430 IterateResult iterate (void); 1431 1432private: 1433 glu::ShaderProgram* generateShaders (void) const; 1434 1435 std::vector<deUint32> m_buffers; 1436 std::vector<Vec4> m_expectedColors; 1437}; 1438 1439UBOBindingRenderCase::UBOBindingRenderCase (Context& context, 1440 const char* name, 1441 const char* desc, 1442 ShaderType shaderType, 1443 TestType testType) 1444 : 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") 1445{ 1446} 1447 1448UBOBindingRenderCase::~UBOBindingRenderCase (void) 1449{ 1450 deinit(); 1451} 1452 1453void UBOBindingRenderCase::init (void) 1454{ 1455 LayoutBindingRenderCase::init(); 1456 1457 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1458 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 1459 1460 // Initialize UBOs and related data 1461 m_buffers = std::vector<glw::GLuint>(m_numBindings, 0); 1462 gl.genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]); 1463 1464 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1465 { 1466 m_expectedColors.push_back(getRandomColor(rnd)); 1467 m_expectedColors.push_back(getRandomColor(rnd)); 1468 } 1469 1470 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1471 { 1472 gl.bindBuffer(GL_UNIFORM_BUFFER, m_buffers[bufNdx]); 1473 gl.bufferData(GL_UNIFORM_BUFFER, 2*sizeof(Vec4), &(m_expectedColors[2*bufNdx]), GL_STATIC_DRAW); 1474 gl.bindBufferBase(GL_UNIFORM_BUFFER, m_bindings[bufNdx], m_buffers[bufNdx]); 1475 } 1476 1477 GLU_EXPECT_NO_ERROR(gl.getError(), "UBO setup failed"); 1478} 1479 1480void UBOBindingRenderCase::deinit (void) 1481{ 1482 LayoutBindingRenderCase::deinit(); 1483 1484 // Clean up UBO data 1485 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1486 { 1487 if (m_buffers[bufNdx]) 1488 { 1489 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffers[bufNdx]); 1490 m_context.getRenderContext().getFunctions().bindBuffer(GL_UNIFORM_BUFFER, 0); 1491 } 1492 } 1493} 1494 1495TestCase::IterateResult UBOBindingRenderCase::iterate (void) 1496{ 1497 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1498 const int iterations = m_numBindings; 1499 const glw::GLenum prop = GL_BUFFER_BINDING; 1500 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1501 bool queryTestPassed = true; 1502 bool imageTestPassed = true; 1503 1504 // Set the viewport and enable the shader program 1505 initRenderState(); 1506 1507 for (int iterNdx = 0; iterNdx < iterations; ++iterNdx) 1508 { 1509 // Query binding point 1510 const std::string name = (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx)); 1511 const glw::GLint binding = m_bindings[iterNdx]; 1512 glw::GLint val = -1; 1513 1514 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); 1515 m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage; 1516 GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed"); 1517 1518 if (val != binding) 1519 queryTestPassed = false; 1520 1521 // Draw twice to render both colors within the UBO 1522 for (int drawCycle = 0; drawCycle < 2; ++drawCycle) 1523 { 1524 // Set the uniform indicating the array index to be used and set the expected color 1525 const int arrayNdx = iterNdx*2 + drawCycle; 1526 gl.uniform1i(m_shaderProgramArrayNdxLoc, arrayNdx); 1527 1528 if (!drawAndVerifyResult(m_expectedColors[arrayNdx])) 1529 imageTestPassed = false; 1530 } 1531 } 1532 1533 setTestResult(queryTestPassed, imageTestPassed); 1534 return STOP; 1535} 1536 1537glu::ShaderProgram* UBOBindingRenderCase::generateShaders (void) const 1538{ 1539 std::ostringstream shaderUniformDecl; 1540 std::ostringstream shaderBody; 1541 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1542 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1543 1544 // Generate the uniform declarations for the vertex and fragment shaders 1545 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1546 { 1547 shaderUniformDecl << "layout(std140, binding = " << m_bindings[declNdx] << ") uniform " 1548 << getUniformName(m_uniformName, declNdx) << "\n" 1549 << "{\n" 1550 << " highp vec4 color1;\n" 1551 << " highp vec4 color2;\n" 1552 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1553 } 1554 1555 // Generate the shader body for the vertex and fragment shaders 1556 for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx) // Multiply by two to cover cases for both colors for each UBO 1557 { 1558 const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2)); 1559 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1560 << " {\n" 1561 << " color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n" 1562 << " }\n"; 1563 } 1564 1565 shaderBody << " else\n" 1566 << " {\n" 1567 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1568 << " }\n"; 1569 1570 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1571 << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())) 1572 << glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))); 1573} 1574 1575 1576class UBOBindingNegativeCase : public LayoutBindingNegativeCase 1577{ 1578public: 1579 UBOBindingNegativeCase (Context& context, 1580 const char* name, 1581 const char* desc, 1582 ShaderType shaderType, 1583 TestType testType, 1584 ErrorType errorType); 1585 ~UBOBindingNegativeCase (void); 1586 1587private: 1588 glu::ShaderProgram* generateShaders (void) const; 1589}; 1590 1591UBOBindingNegativeCase::UBOBindingNegativeCase (Context& context, 1592 const char* name, 1593 const char* desc, 1594 ShaderType shaderType, 1595 TestType testType, 1596 ErrorType errorType) 1597 : 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") 1598{ 1599} 1600 1601UBOBindingNegativeCase::~UBOBindingNegativeCase (void) 1602{ 1603 deinit(); 1604} 1605 1606glu::ShaderProgram* UBOBindingNegativeCase::generateShaders (void) const 1607{ 1608 std::ostringstream vertexUniformDecl; 1609 std::ostringstream fragmentUniformDecl; 1610 std::ostringstream shaderBody; 1611 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1612 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1613 1614 // Generate the uniform declarations for the vertex and fragment shaders 1615 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1616 { 1617 vertexUniformDecl << "layout(std140, binding = " << m_vertexShaderBinding[declNdx] << ") uniform " 1618 << getUniformName(m_uniformName, declNdx) << "\n" 1619 << "{\n" 1620 << " highp vec4 color1;\n" 1621 << " highp vec4 color2;\n" 1622 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1623 1624 fragmentUniformDecl << "layout(std140, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform " 1625 << getUniformName(m_uniformName, declNdx) << "\n" 1626 << "{\n" 1627 << " highp vec4 color1;\n" 1628 << " highp vec4 color2;\n" 1629 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1630 } 1631 1632 // Generate the shader body for the vertex and fragment shaders 1633 for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx) // Multiply by two to cover cases for both colors for each UBO 1634 { 1635 const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2)); 1636 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1637 << " {\n" 1638 << " color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n" 1639 << " }\n"; 1640 } 1641 1642 shaderBody << " else\n" 1643 << " {\n" 1644 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1645 << " }\n"; 1646 1647 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1648 << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str())) 1649 << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()))); 1650} 1651 1652 1653class SSBOBindingRenderCase : public LayoutBindingRenderCase 1654{ 1655public: 1656 SSBOBindingRenderCase (Context& context, 1657 const char* name, 1658 const char* desc, 1659 ShaderType shaderType, 1660 TestType testType); 1661 ~SSBOBindingRenderCase (void); 1662 1663 void init (void); 1664 void deinit (void); 1665 IterateResult iterate (void); 1666 1667private: 1668 glu::ShaderProgram* generateShaders (void) const; 1669 1670 std::vector<glw::GLuint> m_buffers; 1671 std::vector<Vec4> m_expectedColors; 1672}; 1673 1674SSBOBindingRenderCase::SSBOBindingRenderCase (Context& context, 1675 const char* name, 1676 const char* desc, 1677 ShaderType shaderType, 1678 TestType testType) 1679 : 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") 1680{ 1681} 1682 1683SSBOBindingRenderCase::~SSBOBindingRenderCase (void) 1684{ 1685 deinit(); 1686} 1687 1688void SSBOBindingRenderCase::init (void) 1689{ 1690 LayoutBindingRenderCase::init(); 1691 1692 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1693 de::Random rnd (deStringHash(getName()) ^ 0xff23a4); 1694 1695 // Initialize SSBOs and related data 1696 m_buffers = std::vector<glw::GLuint>(m_numBindings, 0); 1697 gl.genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]); 1698 1699 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1700 { 1701 m_expectedColors.push_back(getRandomColor(rnd)); 1702 m_expectedColors.push_back(getRandomColor(rnd)); 1703 } 1704 1705 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1706 { 1707 gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffers[bufNdx]); 1708 gl.bufferData(GL_SHADER_STORAGE_BUFFER, 2*sizeof(Vec4), &(m_expectedColors[2*bufNdx]), GL_STATIC_DRAW); 1709 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, m_bindings[bufNdx], m_buffers[bufNdx]); 1710 } 1711 1712 GLU_EXPECT_NO_ERROR(gl.getError(), "SSBO setup failed"); 1713} 1714 1715void SSBOBindingRenderCase::deinit (void) 1716{ 1717 LayoutBindingRenderCase::deinit(); 1718 1719 // Clean up SSBO data 1720 for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx) 1721 { 1722 if (m_buffers[bufNdx]) 1723 { 1724 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffers[bufNdx]); 1725 m_context.getRenderContext().getFunctions().bindBuffer(GL_SHADER_STORAGE_BUFFER, 0); 1726 m_buffers[bufNdx] = 0; 1727 } 1728 } 1729} 1730 1731TestCase::IterateResult SSBOBindingRenderCase::iterate (void) 1732{ 1733 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1734 const int iterations = m_numBindings; 1735 const glw::GLenum prop = GL_BUFFER_BINDING; 1736 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1737 bool queryTestPassed = true; 1738 bool imageTestPassed = true; 1739 1740 initRenderState(); 1741 1742 for (int iterNdx = 0; iterNdx < iterations; ++iterNdx) 1743 { 1744 // Query binding point 1745 const std::string name = (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx)); 1746 const glw::GLint binding = m_bindings[iterNdx]; 1747 glw::GLint val = -1; 1748 1749 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); 1750 m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val << " == " << binding << tcu::TestLog::EndMessage; 1751 GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed"); 1752 1753 if (val != binding) 1754 queryTestPassed = false; 1755 1756 // Draw twice to render both colors within the SSBO 1757 for (int drawCycle = 0; drawCycle < 2; ++drawCycle) 1758 { 1759 // Set the uniform indicating the array index to be used and set the expected color 1760 const int arrayNdx = iterNdx*2 + drawCycle; 1761 gl.uniform1i(m_shaderProgramArrayNdxLoc, arrayNdx); 1762 1763 if (!drawAndVerifyResult(m_expectedColors[arrayNdx])) 1764 imageTestPassed = false; 1765 } 1766 } 1767 1768 setTestResult(queryTestPassed, imageTestPassed); 1769 return STOP; 1770} 1771 1772glu::ShaderProgram* SSBOBindingRenderCase::generateShaders (void) const 1773{ 1774 std::ostringstream shaderUniformDecl; 1775 std::ostringstream shaderBody; 1776 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1777 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1778 1779 // Generate the uniform declarations for the vertex and fragment shaders 1780 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1781 { 1782 shaderUniformDecl << "layout(std140, binding = " << m_bindings[declNdx] << ") buffer " 1783 << getUniformName(m_uniformName, declNdx) << "\n" 1784 << "{\n" 1785 << " highp vec4 color1;\n" 1786 << " highp vec4 color2;\n" 1787 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1788 } 1789 1790 // Generate the shader body for the vertex and fragment shaders 1791 for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx) // Multiply by two to cover cases for both colors for each UBO 1792 { 1793 const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2)); 1794 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1795 << " {\n" 1796 << " color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n" 1797 << " }\n"; 1798 } 1799 1800 shaderBody << " else\n" 1801 << " {\n" 1802 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1803 << " }\n"; 1804 1805 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1806 << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str())) 1807 << glu::FragmentSource(generateFragmentShader(m_shaderType, shaderUniformDecl.str(), shaderBody.str()))); 1808} 1809 1810 1811class SSBOBindingNegativeCase : public LayoutBindingNegativeCase 1812{ 1813public: 1814 SSBOBindingNegativeCase (Context& context, 1815 const char* name, 1816 const char* desc, 1817 ShaderType shaderType, 1818 TestType testType, 1819 ErrorType errorType); 1820 ~SSBOBindingNegativeCase (void); 1821 1822private: 1823 glu::ShaderProgram* generateShaders (void) const; 1824}; 1825 1826SSBOBindingNegativeCase::SSBOBindingNegativeCase (Context& context, 1827 const char* name, 1828 const char* desc, 1829 ShaderType shaderType, 1830 TestType testType, 1831 ErrorType errorType) 1832 : 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") 1833{ 1834} 1835 1836SSBOBindingNegativeCase::~SSBOBindingNegativeCase (void) 1837{ 1838 deinit(); 1839} 1840 1841glu::ShaderProgram* SSBOBindingNegativeCase::generateShaders (void) const 1842{ 1843 std::ostringstream vertexUniformDecl; 1844 std::ostringstream fragmentUniformDecl; 1845 std::ostringstream shaderBody; 1846 const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY); 1847 const int numDeclarations = (arrayInstance ? 1 : m_numBindings); 1848 1849 // Generate the uniform declarations for the vertex and fragment shaders 1850 for (int declNdx = 0; declNdx < numDeclarations; ++declNdx) 1851 { 1852 vertexUniformDecl << "layout(std140, binding = " << m_vertexShaderBinding[declNdx] << ") buffer " 1853 << getUniformName(m_uniformName, declNdx) << "\n" 1854 << "{\n" 1855 << " highp vec4 color1;\n" 1856 << " highp vec4 color2;\n" 1857 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1858 1859 fragmentUniformDecl << "layout(std140, binding = " << m_fragmentShaderBinding[declNdx] << ") buffer " 1860 << getUniformName(m_uniformName, declNdx) << "\n" 1861 << "{\n" 1862 << " highp vec4 color1;\n" 1863 << " highp vec4 color2;\n" 1864 << "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n"; 1865 } 1866 1867 // Generate the shader body for the vertex and fragment shaders 1868 for (int bindNdx = 0; bindNdx < m_numBindings*2; ++bindNdx) // Multiply by two to cover cases for both colors for each UBO 1869 { 1870 const std::string uname = (arrayInstance ? getUniformName("colors", 0, bindNdx/2) : getUniformName("colors", bindNdx/2)); 1871 shaderBody << " " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx) << ")\n" 1872 << " {\n" 1873 << " color = " << uname << (bindNdx%2 == 0 ? ".color1" : ".color2") << ";\n" 1874 << " }\n"; 1875 } 1876 1877 shaderBody << " else\n" 1878 << " {\n" 1879 << " color = vec4(0.0, 0.0, 0.0, 1.0);\n" 1880 << " }\n"; 1881 1882 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 1883 << glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str())) 1884 << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()))); 1885} 1886 1887 1888} // Anonymous 1889 1890LayoutBindingTests::LayoutBindingTests (Context& context) 1891 : TestCaseGroup (context, "layout_binding", "Layout binding tests") 1892{ 1893} 1894 1895LayoutBindingTests::~LayoutBindingTests (void) 1896{ 1897} 1898 1899void LayoutBindingTests::init (void) 1900{ 1901 // Render test groups 1902 tcu::TestCaseGroup* const samplerBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Test sampler layout binding"); 1903 tcu::TestCaseGroup* const sampler2dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler2d", "Test sampler2d layout binding"); 1904 tcu::TestCaseGroup* const sampler3dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler3d", "Test sampler3d layout binding"); 1905 1906 tcu::TestCaseGroup* const imageBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image", "Test image layout binding"); 1907 tcu::TestCaseGroup* const image2dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image2d", "Test image2d layout binding"); 1908 tcu::TestCaseGroup* const image3dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image3d", "Test image3d layout binding"); 1909 1910 tcu::TestCaseGroup* const UBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ubo", "Test UBO layout binding"); 1911 tcu::TestCaseGroup* const SSBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ssbo", "Test SSBO layout binding"); 1912 1913 // Negative test groups 1914 tcu::TestCaseGroup* const negativeBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "negative", "Test layout binding with invalid bindings"); 1915 1916 tcu::TestCaseGroup* const negativeSamplerBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Test sampler layout binding with invalid bindings"); 1917 tcu::TestCaseGroup* const negativeSampler2dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler2d", "Test sampler2d layout binding with invalid bindings"); 1918 tcu::TestCaseGroup* const negativeSampler3dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "sampler3d", "Test sampler3d layout binding with invalid bindings"); 1919 1920 tcu::TestCaseGroup* const negativeImageBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image", "Test image layout binding with invalid bindings"); 1921 tcu::TestCaseGroup* const negativeImage2dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image2d", "Test image2d layout binding with invalid bindings"); 1922 tcu::TestCaseGroup* const negativeImage3dBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "image3d", "Test image3d layout binding with invalid bindings"); 1923 1924 tcu::TestCaseGroup* const negativeUBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ubo", "Test UBO layout binding with invalid bindings"); 1925 tcu::TestCaseGroup* const negativeSSBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ssbo", "Test SSBO layout binding with invalid bindings"); 1926 1927 static const struct RenderTestType 1928 { 1929 ShaderType shaderType; 1930 TestType testType; 1931 std::string name; 1932 std::string descPostfix; 1933 } s_renderTestTypes[] = 1934 { 1935 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, "vertex_binding_single", "a single instance" }, 1936 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_MAX, "vertex_binding_max", "maximum binding point" }, 1937 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_MULTIPLE, "vertex_binding_multiple", "multiple instances"}, 1938 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, "vertex_binding_array", "an array instance" }, 1939 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_MAX_ARRAY, "vertex_binding_max_array", "an array instance with maximum binding point" }, 1940 1941 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, "fragment_binding_single", "a single instance" }, 1942 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MAX, "fragment_binding_max", "maximum binding point" }, 1943 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MULTIPLE, "fragment_binding_multiple", "multiple instances"}, 1944 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, "fragment_binding_array", "an array instance" }, 1945 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MAX_ARRAY, "fragment_binding_max_array", "an array instance with maximum binding point" }, 1946 }; 1947 1948 static const struct NegativeTestType 1949 { 1950 ShaderType shaderType; 1951 TestType testType; 1952 LayoutBindingNegativeCase::ErrorType errorType; 1953 std::string name; 1954 std::string descPostfix; 1955 } s_negativeTestTypes[] = 1956 { 1957 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "vertex_binding_over_max", "over maximum binding point"}, 1958 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "fragment_binding_over_max", "over maximum binding point"}, 1959 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "vertex_binding_neg", "negative binding point"}, 1960 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "fragment_binding_neg", "negative binding point"}, 1961 1962 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "vertex_binding_over_max_array", "over maximum binding point"}, 1963 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS, "fragment_binding_over_max_array", "over maximum binding point"}, 1964 { SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "vertex_binding_neg_array", "negative binding point"}, 1965 { SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO, "fragment_binding_neg_array", "negative binding point"}, 1966 1967 { SHADERTYPE_BOTH, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY, "binding_contradictory", "contradictory binding points"}, 1968 { SHADERTYPE_BOTH, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY, "binding_contradictory_array", "contradictory binding points"}, 1969 }; 1970 1971 // Render tests 1972 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_renderTestTypes); ++testNdx) 1973 { 1974 const RenderTestType& test = s_renderTestTypes[testNdx]; 1975 1976 // Render sampler binding tests 1977 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)); 1978 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)); 1979 1980 // Render image binding tests 1981 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)); 1982 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)); 1983 1984 // Render UBO binding tests 1985 UBOBindingTestGroup->addChild(new UBOBindingRenderCase(m_context, test.name.c_str(), ("UBO layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType)); 1986 1987 // Render SSBO binding tests 1988 SSBOBindingTestGroup->addChild(new SSBOBindingRenderCase(m_context, test.name.c_str(), ("SSBO layout binding with " + test.descPostfix).c_str(), test.shaderType, test.testType)); 1989 } 1990 1991 // Negative binding tests 1992 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_negativeTestTypes); ++testNdx) 1993 { 1994 const NegativeTestType& test = s_negativeTestTypes[testNdx]; 1995 1996 // Negative sampler binding tests 1997 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)); 1998 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)); 1999 2000 // Negative image binding tests 2001 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)); 2002 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)); 2003 2004 // Negative UBO binding tests 2005 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)); 2006 2007 // Negative SSBO binding tests 2008 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)); 2009 } 2010 2011 samplerBindingTestGroup->addChild(sampler2dBindingTestGroup); 2012 samplerBindingTestGroup->addChild(sampler3dBindingTestGroup); 2013 2014 imageBindingTestGroup->addChild(image2dBindingTestGroup); 2015 imageBindingTestGroup->addChild(image3dBindingTestGroup); 2016 2017 negativeSamplerBindingTestGroup->addChild(negativeSampler2dBindingTestGroup); 2018 negativeSamplerBindingTestGroup->addChild(negativeSampler3dBindingTestGroup); 2019 2020 negativeImageBindingTestGroup->addChild(negativeImage2dBindingTestGroup); 2021 negativeImageBindingTestGroup->addChild(negativeImage3dBindingTestGroup); 2022 2023 negativeBindingTestGroup->addChild(negativeSamplerBindingTestGroup); 2024 negativeBindingTestGroup->addChild(negativeUBOBindingTestGroup); 2025 negativeBindingTestGroup->addChild(negativeSSBOBindingTestGroup); 2026 negativeBindingTestGroup->addChild(negativeImageBindingTestGroup); 2027 2028 addChild(samplerBindingTestGroup); 2029 addChild(UBOBindingTestGroup); 2030 addChild(SSBOBindingTestGroup); 2031 addChild(imageBindingTestGroup); 2032 addChild(negativeBindingTestGroup); 2033} 2034 2035} // Functional 2036} // gles31 2037} // deqp 2038