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