1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 /** 25 * \file gl4cShaderSubroutineTests.cpp 26 * \brief Implements conformance tests for "Shader Subroutine" functionality. 27 */ /*-------------------------------------------------------------------*/ 28 29 #include "gl4cShaderSubroutineTests.hpp" 30 #include "gluContextInfo.hpp" 31 #include "glwEnums.hpp" 32 #include "glwFunctions.hpp" 33 #include "tcuMatrix.hpp" 34 #include <cmath> 35 #include <cstring> 36 #include <deMath.h> 37 38 using namespace glw; 39 40 namespace gl4cts 41 { 42 namespace ShaderSubroutine 43 { 44 /** Constructor. 45 * 46 * @param context CTS context. 47 **/ 48 Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context) 49 { 50 } 51 52 /** Destructor 53 * 54 **/ 55 Utils::buffer::~buffer() 56 { 57 if (0 != m_id) 58 { 59 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 60 61 gl.deleteBuffers(1, &m_id); 62 m_id = 0; 63 } 64 } 65 66 /** Execute BindBufferRange 67 * 68 * @param target <target> parameter 69 * @param index <index> parameter 70 * @param offset <offset> parameter 71 * @param size <size> parameter 72 **/ 73 void Utils::buffer::bindRange(glw::GLenum target, glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) 74 { 75 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 76 77 gl.bindBufferRange(target, index, m_id, offset, size); 78 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange"); 79 } 80 81 /** Execute GenBuffer 82 * 83 **/ 84 void Utils::buffer::generate() 85 { 86 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 87 88 gl.genBuffers(1, &m_id); 89 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 90 } 91 92 /** Execute BufferData 93 * 94 * @param target <target> parameter 95 * @param size <size> parameter 96 * @param data <data> parameter 97 * @param usage <usage> parameter 98 **/ 99 void Utils::buffer::update(glw::GLenum target, glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage) 100 { 101 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 102 103 gl.bindBuffer(target, m_id); 104 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer"); 105 106 gl.bufferData(target, size, data, usage); 107 GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData"); 108 } 109 110 /** Constructor 111 * 112 * @param context CTS context 113 **/ 114 Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context) 115 { 116 /* Nothing to be done here */ 117 } 118 119 /** Destructor 120 * 121 **/ 122 Utils::framebuffer::~framebuffer() 123 { 124 if (0 != m_id) 125 { 126 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 127 128 gl.deleteFramebuffers(1, &m_id); 129 m_id = 0; 130 } 131 } 132 133 /** Attach texture to specified attachment 134 * 135 * @param attachment Attachment 136 * @param texture_id Texture id 137 * @param width Texture width 138 * @param height Texture height 139 **/ 140 void Utils::framebuffer::attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width, 141 glw::GLuint height) 142 { 143 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 144 145 bind(); 146 147 gl.bindTexture(GL_TEXTURE_2D, texture_id); 148 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 149 150 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture_id, 0 /* level */); 151 152 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D"); 153 154 gl.viewport(0 /* x */, 0 /* y */, width, height); 155 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); 156 } 157 158 /** Binds framebuffer to DRAW_FRAMEBUFFER 159 * 160 **/ 161 void Utils::framebuffer::bind() 162 { 163 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 164 165 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_id); 166 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer"); 167 } 168 169 /** Clear framebuffer 170 * 171 * @param mask <mask> parameter of glClear. Decides which shall be cleared 172 **/ 173 void Utils::framebuffer::clear(glw::GLenum mask) 174 { 175 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 176 177 gl.clear(mask); 178 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear"); 179 } 180 181 /** Specifie clear color 182 * 183 * @param red Red channel 184 * @param green Green channel 185 * @param blue Blue channel 186 * @param alpha Alpha channel 187 **/ 188 void Utils::framebuffer::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) 189 { 190 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 191 192 gl.clearColor(red, green, blue, alpha); 193 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor"); 194 } 195 196 /** Generate framebuffer 197 * 198 **/ 199 void Utils::framebuffer::generate() 200 { 201 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 202 203 gl.genFramebuffers(1, &m_id); 204 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers"); 205 } 206 207 const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9; 208 209 /** Constructor. 210 * 211 * @param context CTS context. 212 **/ 213 Utils::program::program(deqp::Context& context) 214 : m_compute_shader_id(0) 215 , m_fragment_shader_id(0) 216 , m_geometry_shader_id(0) 217 , m_program_object_id(0) 218 , m_tesselation_control_shader_id(0) 219 , m_tesselation_evaluation_shader_id(0) 220 , m_vertex_shader_id(0) 221 , m_context(context) 222 { 223 /* Nothing to be done here */ 224 } 225 226 /** Destructor 227 * 228 **/ 229 Utils::program::~program() 230 { 231 remove(); 232 } 233 234 /** Build program 235 * 236 * @param compute_shader_code Compute shader source code 237 * @param fragment_shader_code Fragment shader source code 238 * @param geometry_shader_code Geometry shader source code 239 * @param tesselation_control_shader_code Tesselation control shader source code 240 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code 241 * @param vertex_shader_code Vertex shader source code 242 * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback 243 * @param n_varying_names Number of varyings to be captured with transfrom feedback 244 * @param is_separable Selects if monolithis or separable program should be built. Defaults to false 245 **/ 246 void Utils::program::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code, 247 const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code, 248 const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code, 249 const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable) 250 { 251 /* GL entry points */ 252 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 253 254 /* Create shader objects and compile */ 255 if (0 != compute_shader_code) 256 { 257 m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER); 258 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 259 260 compile(m_compute_shader_id, compute_shader_code); 261 } 262 263 if (0 != fragment_shader_code) 264 { 265 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 266 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 267 268 compile(m_fragment_shader_id, fragment_shader_code); 269 } 270 271 if (0 != geometry_shader_code) 272 { 273 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER); 274 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 275 276 compile(m_geometry_shader_id, geometry_shader_code); 277 } 278 279 if (0 != tesselation_control_shader_code) 280 { 281 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER); 282 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 283 284 compile(m_tesselation_control_shader_id, tesselation_control_shader_code); 285 } 286 287 if (0 != tesselation_evaluation_shader_code) 288 { 289 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER); 290 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 291 292 compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code); 293 } 294 295 if (0 != vertex_shader_code) 296 { 297 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 298 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 299 300 compile(m_vertex_shader_id, vertex_shader_code); 301 } 302 303 /* Create program object */ 304 m_program_object_id = gl.createProgram(); 305 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram"); 306 307 /* Set up captyured varyings' names */ 308 if (0 != n_varying_names) 309 { 310 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS); 311 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings"); 312 } 313 314 /* Set separable parameter */ 315 if (true == is_separable) 316 { 317 gl.programParameteri(m_program_object_id, GL_PROGRAM_SEPARABLE, GL_TRUE); 318 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri"); 319 } 320 321 /* Link program */ 322 link(); 323 } 324 325 /** Compile shader 326 * 327 * @param shader_id Shader object id 328 * @param shader_code Shader source code 329 **/ 330 void Utils::program::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const 331 { 332 /* GL entry points */ 333 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 334 335 /* Compilation status */ 336 glw::GLint status = GL_FALSE; 337 338 /* Set source code */ 339 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0); 340 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource"); 341 342 /* Compile */ 343 gl.compileShader(shader_id); 344 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader"); 345 346 /* Get compilation status */ 347 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status); 348 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 349 350 /* Log compilation error */ 351 if (GL_TRUE != status) 352 { 353 glw::GLint length = 0; 354 std::vector<glw::GLchar> message; 355 356 /* Error log length */ 357 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length); 358 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 359 360 /* Prepare storage */ 361 message.resize(length); 362 363 /* Get error log */ 364 gl.getShaderInfoLog(shader_id, length, 0, &message[0]); 365 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog"); 366 367 /* Log */ 368 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n" 369 << &message[0] << "\nShader source\n" 370 << shader_code << tcu::TestLog::EndMessage; 371 372 TCU_FAIL("Failed to compile shader"); 373 } 374 } 375 376 /** Checks whether the tested driver supports GL_ARB_get_program_binary 377 * 378 * @return true if the extension is supported and, also, at least one binary format. 379 **/ 380 bool Utils::program::isProgramBinarySupported() const 381 { 382 glw::GLint n_program_binary_formats = 0; 383 384 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 385 386 if (m_context.getContextInfo().isExtensionSupported("GL_ARB_get_program_binary")) 387 { 388 gl.getIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &n_program_binary_formats); 389 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed."); 390 } 391 392 return n_program_binary_formats > 0; 393 } 394 395 /** Create program from provided binary 396 * 397 * @param binary Buffer with binary form of program 398 * @param binary_format Format of <binary> data 399 **/ 400 void Utils::program::createFromBinary(const std::vector<GLubyte>& binary, GLenum binary_format) 401 { 402 /* GL entry points */ 403 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 404 405 /* Create program object */ 406 m_program_object_id = gl.createProgram(); 407 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram"); 408 409 gl.programBinary(m_program_object_id, binary_format, &binary[0], (GLsizei)binary.size()); 410 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramBinary"); 411 } 412 413 /** Get binary form of program 414 * 415 * @param binary Buffer for binary data 416 * @param binary_format Format of binary data 417 **/ 418 void Utils::program::getBinary(std::vector<GLubyte>& binary, GLenum& binary_format) const 419 { 420 /* GL entry points */ 421 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 422 423 /* Get binary size */ 424 GLint length = 0; 425 gl.getProgramiv(m_program_object_id, GL_PROGRAM_BINARY_LENGTH, &length); 426 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 427 428 /* Allocate storage */ 429 binary.resize(length); 430 431 /* Get binary */ 432 gl.getProgramBinary(m_program_object_id, (GLsizei)binary.size(), &length, &binary_format, &binary[0]); 433 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramBinary"); 434 } 435 436 /** Get subroutine index 437 * 438 * @param subroutine_name Subroutine name 439 * 440 * @return Index of subroutine 441 **/ 442 GLuint Utils::program::getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const 443 { 444 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 445 GLuint index = -1; 446 447 index = gl.getSubroutineIndex(m_program_object_id, shader_stage, subroutine_name); 448 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex"); 449 450 if (GL_INVALID_INDEX == index) 451 { 452 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine: " << subroutine_name 453 << " is not available" << tcu::TestLog::EndMessage; 454 455 TCU_FAIL("Subroutine is not available"); 456 } 457 458 return index; 459 } 460 461 /** Get subroutine uniform location 462 * 463 * @param uniform_name Subroutine uniform name 464 * 465 * @return Location of subroutine uniform 466 **/ 467 GLint Utils::program::getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const 468 { 469 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 470 GLint location = -1; 471 472 location = gl.getSubroutineUniformLocation(m_program_object_id, shader_stage, uniform_name); 473 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation"); 474 475 if (-1 == location) 476 { 477 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine uniform: " << uniform_name 478 << " is not available" << tcu::TestLog::EndMessage; 479 480 TCU_FAIL("Subroutine uniform is not available"); 481 } 482 483 return location; 484 } 485 486 /** Get uniform location 487 * 488 * @param uniform_name Subroutine uniform name 489 * 490 * @return Location of uniform 491 **/ 492 GLint Utils::program::getUniformLocation(const glw::GLchar* uniform_name) const 493 { 494 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 495 GLint location = -1; 496 497 location = gl.getUniformLocation(m_program_object_id, uniform_name); 498 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation"); 499 500 if (-1 == location) 501 { 502 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name 503 << " is not available" << tcu::TestLog::EndMessage; 504 505 TCU_FAIL("Uniform is not available"); 506 } 507 508 return location; 509 } 510 511 /** Attach shaders and link program 512 * 513 **/ 514 void Utils::program::link() const 515 { 516 /* GL entry points */ 517 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 518 519 /* Link status */ 520 glw::GLint status = GL_FALSE; 521 522 /* Attach shaders */ 523 if (0 != m_compute_shader_id) 524 { 525 gl.attachShader(m_program_object_id, m_compute_shader_id); 526 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 527 } 528 529 if (0 != m_fragment_shader_id) 530 { 531 gl.attachShader(m_program_object_id, m_fragment_shader_id); 532 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 533 } 534 535 if (0 != m_geometry_shader_id) 536 { 537 gl.attachShader(m_program_object_id, m_geometry_shader_id); 538 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 539 } 540 541 if (0 != m_tesselation_control_shader_id) 542 { 543 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id); 544 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 545 } 546 547 if (0 != m_tesselation_evaluation_shader_id) 548 { 549 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id); 550 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 551 } 552 553 if (0 != m_vertex_shader_id) 554 { 555 gl.attachShader(m_program_object_id, m_vertex_shader_id); 556 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 557 } 558 559 /* Link */ 560 gl.linkProgram(m_program_object_id); 561 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram"); 562 563 /* Get link status */ 564 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status); 565 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 566 567 /* Log link error */ 568 if (GL_TRUE != status) 569 { 570 glw::GLint length = 0; 571 std::vector<glw::GLchar> message; 572 573 /* Get error log length */ 574 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length); 575 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 576 577 message.resize(length); 578 579 /* Get error log */ 580 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]); 581 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog"); 582 583 /* Log */ 584 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n" 585 << &message[0] << tcu::TestLog::EndMessage; 586 587 TCU_FAIL("Failed to link program"); 588 } 589 } 590 591 /** Delete program object and all attached shaders 592 * 593 **/ 594 void Utils::program::remove() 595 { 596 /* GL entry points */ 597 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 598 599 /* Make sure program object is no longer used by GL */ 600 gl.useProgram(0); 601 602 /* Clean program object */ 603 if (0 != m_program_object_id) 604 { 605 gl.deleteProgram(m_program_object_id); 606 m_program_object_id = 0; 607 } 608 609 /* Clean shaders */ 610 if (0 != m_compute_shader_id) 611 { 612 gl.deleteShader(m_compute_shader_id); 613 m_compute_shader_id = 0; 614 } 615 616 if (0 != m_fragment_shader_id) 617 { 618 gl.deleteShader(m_fragment_shader_id); 619 m_fragment_shader_id = 0; 620 } 621 622 if (0 != m_geometry_shader_id) 623 { 624 gl.deleteShader(m_geometry_shader_id); 625 m_geometry_shader_id = 0; 626 } 627 628 if (0 != m_tesselation_control_shader_id) 629 { 630 gl.deleteShader(m_tesselation_control_shader_id); 631 m_tesselation_control_shader_id = 0; 632 } 633 634 if (0 != m_tesselation_evaluation_shader_id) 635 { 636 gl.deleteShader(m_tesselation_evaluation_shader_id); 637 m_tesselation_evaluation_shader_id = 0; 638 } 639 640 if (0 != m_vertex_shader_id) 641 { 642 gl.deleteShader(m_vertex_shader_id); 643 m_vertex_shader_id = 0; 644 } 645 } 646 647 /** Execute UseProgram 648 * 649 **/ 650 void Utils::program::use() const 651 { 652 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 653 654 gl.useProgram(m_program_object_id); 655 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 656 } 657 658 /** Constructor. 659 * 660 * @param context CTS context. 661 **/ 662 Utils::texture::texture(deqp::Context& context) : m_id(0), m_context(context) 663 { 664 /* Nothing to done here */ 665 } 666 667 /** Destructor 668 * 669 **/ 670 Utils::texture::~texture() 671 { 672 if (0 != m_id) 673 { 674 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 675 676 gl.deleteTextures(1, &m_id); 677 m_id = 0; 678 } 679 } 680 681 /** Bind texture to GL_TEXTURE_2D 682 * 683 **/ 684 void Utils::texture::bind() 685 { 686 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 687 688 gl.bindTexture(GL_TEXTURE_2D, m_id); 689 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 690 } 691 692 /** Create 2d texture 693 * 694 * @param width Width of texture 695 * @param height Height of texture 696 * @param internal_format Internal format of texture 697 **/ 698 void Utils::texture::create(glw::GLuint width, glw::GLuint height, glw::GLenum internal_format) 699 { 700 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 701 702 gl.genTextures(1, &m_id); 703 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); 704 705 bind(); 706 707 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, internal_format, width, height); 708 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); 709 } 710 711 /** Get contents of texture 712 * 713 * @param format Format of image 714 * @param type Type of image 715 * @param out_data Buffer for image 716 **/ 717 void Utils::texture::get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data) 718 { 719 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 720 721 bind(); 722 723 gl.getTexImage(GL_TEXTURE_2D, 0, format, type, out_data); 724 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage"); 725 } 726 727 /** Update contents of texture 728 * 729 * @param width Width of texture 730 * @param height Height of texture 731 * @param format Format of data 732 * @param type Type of data 733 * @param data Buffer with image 734 **/ 735 void Utils::texture::update(glw::GLuint width, glw::GLuint height, glw::GLenum format, glw::GLenum type, 736 glw::GLvoid* data) 737 { 738 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 739 740 bind(); 741 742 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, width, height, format, type, data); 743 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 744 } 745 746 /** Constructor. 747 * 748 * @param context CTS context. 749 **/ 750 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context) 751 { 752 } 753 754 /** Destructor 755 * 756 **/ 757 Utils::vertexArray::~vertexArray() 758 { 759 if (0 != m_id) 760 { 761 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 762 763 gl.deleteVertexArrays(1, &m_id); 764 765 m_id = 0; 766 } 767 } 768 769 /** Execute BindVertexArray 770 * 771 **/ 772 void Utils::vertexArray::bind() 773 { 774 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 775 776 gl.bindVertexArray(m_id); 777 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray"); 778 } 779 780 /** Execute GenVertexArrays 781 * 782 **/ 783 void Utils::vertexArray::generate() 784 { 785 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 786 787 gl.genVertexArrays(1, &m_id); 788 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); 789 } 790 791 /** Builds a program object consisting of up to 5 shader stages 792 * (vertex/tessellation control/tessellation evaluation/geometry/fragment). 793 * The shaders are attached to the program object, then compiled. Finally, 794 * the program object is linked. 795 * 796 * XFB can be optionally configured for the program object. 797 * 798 * Should an error be reported by GL implementation, a TestError 799 * exception will be thrown. 800 * 801 * @param gl OpenGL functions from the active rendering context. 802 * @param vs_body Body to use for the vertex shader. Can be an empty string. 803 * @param tc_body Body to use for the tessellation control shader. Can be 804 * an empty string. 805 * @param te_body Body to use for the tessellation evaluation shader. Can be 806 * an empty string. 807 * @param gs_body Body to use for the geometry shader. Can be an empty string. 808 * @param fs_body Body to use for the fragment shader. Can be an empty string. 809 * @param xfb_varyings An array of names of varyings to use for XFB. Can be NULL. 810 * @param n_xfb_varyings Amount of XFB varyings defined in @param xfb_varyings.Can be 0. 811 * @param out_vs_id Deref will be used to store GL id of a generated vertex shader. 812 * Can be NULL in which case no vertex shader will be used for the 813 * program object. 814 * @param out_tc_id Deref will be used to store GL id of a generated tess control shader. 815 * Can be NULL in which case no tess control shader will be used for the 816 * program object. 817 * @param out_te_id Deref will be used to store GL id of a generated tess evaluation shader. 818 * Can be NULL in which case no tess evaluation shader will be used for the 819 * program object. 820 * @param out_gs_id Deref will be used to store GL id of a generated geometry shader. 821 * Can be NULL in which case no geometry shader will be used for the 822 * program object. 823 * @param out_fs_id Deref will be used to store GL id of a generated fragment shader. 824 * Can be NULL in which case no fragment shader will be used for the 825 * program object. 826 * @param out_po_id Deref will be used to store GL id of a generated program object. 827 * Must not be NULL. 828 * 829 * @return true if the program was built successfully, false otherwise. 830 * */ 831 bool Utils::buildProgram(const glw::Functions& gl, const std::string& vs_body, const std::string& tc_body, 832 const std::string& te_body, const std::string& gs_body, const std::string& fs_body, 833 const glw::GLchar** xfb_varyings, const unsigned int& n_xfb_varyings, glw::GLuint* out_vs_id, 834 glw::GLuint* out_tc_id, glw::GLuint* out_te_id, glw::GLuint* out_gs_id, glw::GLuint* out_fs_id, 835 glw::GLuint* out_po_id) 836 { 837 bool result = false; 838 839 /* Link the program object */ 840 glw::GLint link_status = GL_FALSE; 841 842 /* Create objects, set up shader bodies and attach all requested shaders to the program object */ 843 *out_po_id = gl.createProgram(); 844 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 845 846 if (out_vs_id != DE_NULL) 847 { 848 const char* vs_body_raw_ptr = vs_body.c_str(); 849 850 *out_vs_id = gl.createShader(GL_VERTEX_SHADER); 851 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 852 853 gl.attachShader(*out_po_id, *out_vs_id); 854 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 855 856 gl.shaderSource(*out_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */); 857 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 858 } 859 860 if (out_tc_id != DE_NULL) 861 { 862 const char* tc_body_raw_ptr = tc_body.c_str(); 863 864 *out_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER); 865 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 866 867 gl.attachShader(*out_po_id, *out_tc_id); 868 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 869 870 gl.shaderSource(*out_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */); 871 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 872 } 873 874 if (out_te_id != DE_NULL) 875 { 876 const char* te_body_raw_ptr = te_body.c_str(); 877 878 *out_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER); 879 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 880 881 gl.attachShader(*out_po_id, *out_te_id); 882 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 883 884 gl.shaderSource(*out_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */); 885 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 886 } 887 888 if (out_gs_id != DE_NULL) 889 { 890 const char* gs_body_raw_ptr = gs_body.c_str(); 891 892 *out_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 893 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 894 895 gl.attachShader(*out_po_id, *out_gs_id); 896 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 897 898 gl.shaderSource(*out_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */); 899 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 900 } 901 902 if (out_fs_id != DE_NULL) 903 { 904 const char* fs_body_raw_ptr = fs_body.c_str(); 905 906 *out_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 907 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 908 909 gl.attachShader(*out_po_id, *out_fs_id); 910 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 911 912 gl.shaderSource(*out_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */); 913 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 914 } 915 916 /* Compile all shaders */ 917 const glw::GLuint so_ids[] = { (out_vs_id != DE_NULL) ? *out_vs_id : 0, (out_tc_id != DE_NULL) ? *out_tc_id : 0, 918 (out_te_id != DE_NULL) ? *out_te_id : 0, (out_gs_id != DE_NULL) ? *out_gs_id : 0, 919 (out_fs_id != DE_NULL) ? *out_fs_id : 0 }; 920 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]); 921 922 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id) 923 { 924 glw::GLuint so_id = so_ids[n_so_id]; 925 926 if (so_id != 0) 927 { 928 glw::GLint compile_status = GL_FALSE; 929 930 gl.compileShader(so_id); 931 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 932 933 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); 934 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 935 936 if (compile_status != GL_TRUE) 937 { 938 goto end; 939 } 940 } /* if (so_id != 0) */ 941 } /* for (all shader objects) */ 942 943 /* Set up XFB */ 944 if (xfb_varyings != NULL) 945 { 946 gl.transformFeedbackVaryings(*out_po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS); 947 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed."); 948 } 949 950 gl.linkProgram(*out_po_id); 951 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 952 953 gl.getProgramiv(*out_po_id, GL_LINK_STATUS, &link_status); 954 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 955 956 if (link_status != GL_TRUE) 957 { 958 goto end; 959 } 960 961 /* All done */ 962 result = true; 963 964 end: 965 return result; 966 } 967 968 /** Retrieves base variable type for user-specified variable type 969 * (eg. float for vec4) 970 * 971 * @param variable_type Variable type to use for the query. 972 * 973 * @return As per description. 974 **/ 975 Utils::_variable_type Utils::getBaseVariableType(const _variable_type& variable_type) 976 { 977 _variable_type result = VARIABLE_TYPE_UNKNOWN; 978 979 switch (variable_type) 980 { 981 case VARIABLE_TYPE_BOOL: 982 case VARIABLE_TYPE_BVEC2: 983 case VARIABLE_TYPE_BVEC3: 984 case VARIABLE_TYPE_BVEC4: 985 { 986 result = VARIABLE_TYPE_BOOL; 987 988 break; 989 } 990 991 case VARIABLE_TYPE_DOUBLE: 992 case VARIABLE_TYPE_DVEC2: 993 case VARIABLE_TYPE_DVEC3: 994 case VARIABLE_TYPE_DVEC4: 995 { 996 result = VARIABLE_TYPE_DOUBLE; 997 998 break; 999 } 1000 1001 case VARIABLE_TYPE_FLOAT: 1002 case VARIABLE_TYPE_MAT2: 1003 case VARIABLE_TYPE_MAT2X3: 1004 case VARIABLE_TYPE_MAT2X4: 1005 case VARIABLE_TYPE_MAT3: 1006 case VARIABLE_TYPE_MAT3X2: 1007 case VARIABLE_TYPE_MAT3X4: 1008 case VARIABLE_TYPE_MAT4: 1009 case VARIABLE_TYPE_MAT4X2: 1010 case VARIABLE_TYPE_MAT4X3: 1011 case VARIABLE_TYPE_VEC2: 1012 case VARIABLE_TYPE_VEC3: 1013 case VARIABLE_TYPE_VEC4: 1014 { 1015 result = VARIABLE_TYPE_FLOAT; 1016 1017 break; 1018 } 1019 1020 case VARIABLE_TYPE_INT: 1021 case VARIABLE_TYPE_IVEC2: 1022 case VARIABLE_TYPE_IVEC3: 1023 case VARIABLE_TYPE_IVEC4: 1024 { 1025 result = VARIABLE_TYPE_INT; 1026 1027 break; 1028 } 1029 1030 case VARIABLE_TYPE_UINT: 1031 case VARIABLE_TYPE_UVEC2: 1032 case VARIABLE_TYPE_UVEC3: 1033 case VARIABLE_TYPE_UVEC4: 1034 { 1035 result = VARIABLE_TYPE_UINT; 1036 1037 break; 1038 } 1039 1040 default: 1041 { 1042 TCU_FAIL("Unrecognized variable type"); 1043 } 1044 } /* switch (variable_type) */ 1045 1046 return result; 1047 } 1048 1049 /** Retrieves size of a single component (in bytes) for user-specified 1050 * variable type. 1051 * 1052 * @param variable_type Variable type to use for the query. 1053 * 1054 * @return As per description. 1055 **/ 1056 unsigned int Utils::getComponentSizeForVariableType(const _variable_type& variable_type) 1057 { 1058 _variable_type base_variable_type = getBaseVariableType(variable_type); 1059 unsigned int result = 0; 1060 1061 switch (base_variable_type) 1062 { 1063 case VARIABLE_TYPE_BOOL: 1064 result = sizeof(bool); 1065 break; 1066 case VARIABLE_TYPE_DOUBLE: 1067 result = sizeof(double); 1068 break; 1069 case VARIABLE_TYPE_FLOAT: 1070 result = sizeof(float); 1071 break; 1072 case VARIABLE_TYPE_INT: 1073 result = sizeof(int); 1074 break; 1075 case VARIABLE_TYPE_UINT: 1076 result = sizeof(unsigned int); 1077 break; 1078 1079 default: 1080 { 1081 TCU_FAIL("Unrecognized base variable type"); 1082 } 1083 } /* switch (variable_type) */ 1084 1085 return result; 1086 } 1087 1088 /** Retrieves a GLenum value corresponding to internal shader stage 1089 * representation. 1090 * 1091 * @param shader_stage Shader stage to user for the query. 1092 * 1093 * @return Requested value or GL_NONE if the stage was not recognized. 1094 **/ 1095 glw::GLenum Utils::getGLenumForShaderStage(const _shader_stage& shader_stage) 1096 { 1097 glw::GLenum result = GL_NONE; 1098 1099 switch (shader_stage) 1100 { 1101 case SHADER_STAGE_VERTEX: 1102 result = GL_VERTEX_SHADER; 1103 break; 1104 case SHADER_STAGE_TESSELLATION_CONTROL: 1105 result = GL_TESS_CONTROL_SHADER; 1106 break; 1107 case SHADER_STAGE_TESSELLATION_EVALUATION: 1108 result = GL_TESS_EVALUATION_SHADER; 1109 break; 1110 case SHADER_STAGE_GEOMETRY: 1111 result = GL_GEOMETRY_SHADER; 1112 break; 1113 case SHADER_STAGE_FRAGMENT: 1114 result = GL_FRAGMENT_SHADER; 1115 break; 1116 1117 default: 1118 { 1119 TCU_FAIL("Unrecognized shader stage requested"); 1120 } 1121 } /* switch (shader_stage) */ 1122 1123 return result; 1124 } 1125 1126 /** Retrieves number of components that user-specified variable type supports. 1127 * 1128 * @param variable_type GLSL variable type to use for the query. 1129 * 1130 * @return As per description. 1131 **/ 1132 unsigned int Utils::getNumberOfComponentsForVariableType(const _variable_type& variable_type) 1133 { 1134 unsigned int result = 0; 1135 1136 switch (variable_type) 1137 { 1138 case VARIABLE_TYPE_BOOL: 1139 case VARIABLE_TYPE_DOUBLE: 1140 case VARIABLE_TYPE_FLOAT: 1141 case VARIABLE_TYPE_INT: 1142 case VARIABLE_TYPE_UINT: 1143 { 1144 result = 1; 1145 1146 break; 1147 } 1148 1149 case VARIABLE_TYPE_BVEC2: 1150 case VARIABLE_TYPE_DVEC2: 1151 case VARIABLE_TYPE_IVEC2: 1152 case VARIABLE_TYPE_UVEC2: 1153 case VARIABLE_TYPE_VEC2: 1154 { 1155 result = 2; 1156 1157 break; 1158 } 1159 1160 case VARIABLE_TYPE_BVEC3: 1161 case VARIABLE_TYPE_DVEC3: 1162 case VARIABLE_TYPE_IVEC3: 1163 case VARIABLE_TYPE_UVEC3: 1164 case VARIABLE_TYPE_VEC3: 1165 { 1166 result = 3; 1167 1168 break; 1169 } 1170 1171 case VARIABLE_TYPE_BVEC4: 1172 case VARIABLE_TYPE_DVEC4: 1173 case VARIABLE_TYPE_IVEC4: 1174 case VARIABLE_TYPE_MAT2: 1175 case VARIABLE_TYPE_UVEC4: 1176 case VARIABLE_TYPE_VEC4: 1177 { 1178 result = 4; 1179 1180 break; 1181 } 1182 1183 case VARIABLE_TYPE_MAT2X3: 1184 case VARIABLE_TYPE_MAT3X2: 1185 { 1186 result = 6; 1187 1188 break; 1189 } 1190 1191 case VARIABLE_TYPE_MAT2X4: 1192 case VARIABLE_TYPE_MAT4X2: 1193 { 1194 result = 8; 1195 1196 break; 1197 } 1198 1199 case VARIABLE_TYPE_MAT3: 1200 { 1201 result = 9; 1202 1203 break; 1204 } 1205 1206 case VARIABLE_TYPE_MAT3X4: 1207 case VARIABLE_TYPE_MAT4X3: 1208 { 1209 result = 12; 1210 1211 break; 1212 } 1213 1214 case VARIABLE_TYPE_MAT4: 1215 { 1216 result = 16; 1217 1218 break; 1219 } 1220 1221 default: 1222 break; 1223 } /* switch (variable_type) */ 1224 1225 return result; 1226 } 1227 1228 /** Retrieves a literal defining user-specified shader stage enum. 1229 * 1230 * @param shader_stage Shader stage to use for the query. 1231 * 1232 * @return Requested string or "?" if the stage was not recognized. 1233 **/ 1234 std::string Utils::getShaderStageString(const _shader_stage& shader_stage) 1235 { 1236 std::string result = "?"; 1237 1238 switch (shader_stage) 1239 { 1240 case SHADER_STAGE_FRAGMENT: 1241 result = "Fragment Shader"; 1242 break; 1243 case SHADER_STAGE_GEOMETRY: 1244 result = "Geometry Shader"; 1245 break; 1246 case SHADER_STAGE_TESSELLATION_CONTROL: 1247 result = "Tessellation Control Shader"; 1248 break; 1249 case SHADER_STAGE_TESSELLATION_EVALUATION: 1250 result = "Tessellation Evaluation Shader"; 1251 break; 1252 case SHADER_STAGE_VERTEX: 1253 result = "Vertex Shader"; 1254 break; 1255 1256 default: 1257 { 1258 TCU_FAIL("Unrecognized shader stage"); 1259 } 1260 } /* switch (shader_stage) */ 1261 1262 return result; 1263 } 1264 1265 /** Retrieves a literal defining user-specified shader stage enum. 1266 * 1267 * @param shader_stage_glenum Shader stage to use for the query. 1268 * 1269 * @return Requested string or "?" if the stage was not recognized. 1270 **/ 1271 std::string Utils::getShaderStageStringFromGLEnum(const glw::GLenum shader_stage_glenum) 1272 { 1273 std::string result = "?"; 1274 1275 switch (shader_stage_glenum) 1276 { 1277 case GL_FRAGMENT_SHADER: 1278 result = "Fragment Shader"; 1279 break; 1280 case GL_GEOMETRY_SHADER: 1281 result = "Geometry Shader"; 1282 break; 1283 case GL_TESS_CONTROL_SHADER: 1284 result = "Tessellation Control Shader"; 1285 break; 1286 case GL_TESS_EVALUATION_SHADER: 1287 result = "Tessellation Evaluation Shader"; 1288 break; 1289 case GL_VERTEX_SHADER: 1290 result = "Vertex Shader"; 1291 break; 1292 1293 default: 1294 { 1295 TCU_FAIL("Unrecognized shader string"); 1296 } 1297 } /* switch (shader_stage_glenum) */ 1298 1299 return result; 1300 } 1301 1302 /** Returns string that represents program interface name 1303 * 1304 * @param program_interface Program interface 1305 * 1306 * @return String representation of known program interface 1307 **/ 1308 const GLchar* Utils::programInterfaceToStr(glw::GLenum program_interface) 1309 { 1310 const GLchar* string = "Unknown program interface"; 1311 1312 switch (program_interface) 1313 { 1314 case GL_VERTEX_SUBROUTINE: 1315 string = "GL_VERTEX_SUBROUTINE"; 1316 break; 1317 case GL_VERTEX_SUBROUTINE_UNIFORM: 1318 string = "GL_VERTEX_SUBROUTINE_UNIFORM"; 1319 break; 1320 default: 1321 TCU_FAIL("Not implemented"); 1322 break; 1323 }; 1324 1325 return string; 1326 } 1327 1328 /** Returns string that represents pname's name 1329 * 1330 * @param pname pname 1331 * 1332 * @return String representation of known pnames 1333 **/ 1334 const GLchar* Utils::pnameToStr(glw::GLenum pname) 1335 { 1336 const GLchar* string = "Unknown pname"; 1337 1338 switch (pname) 1339 { 1340 case GL_ACTIVE_SUBROUTINE_UNIFORMS: 1341 string = "GL_ACTIVE_SUBROUTINE_UNIFORMS"; 1342 break; 1343 case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS: 1344 string = "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"; 1345 break; 1346 case GL_ACTIVE_SUBROUTINES: 1347 string = "GL_ACTIVE_SUBROUTINES"; 1348 break; 1349 case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH: 1350 string = "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"; 1351 break; 1352 case GL_ACTIVE_SUBROUTINE_MAX_LENGTH: 1353 string = "GL_ACTIVE_SUBROUTINE_MAX_LENGTH"; 1354 break; 1355 case GL_NUM_COMPATIBLE_SUBROUTINES: 1356 string = "GL_NUM_COMPATIBLE_SUBROUTINES"; 1357 break; 1358 case GL_UNIFORM_SIZE: 1359 string = "GL_UNIFORM_SIZE"; 1360 break; 1361 case GL_COMPATIBLE_SUBROUTINES: 1362 string = "GL_COMPATIBLE_SUBROUTINES"; 1363 break; 1364 case GL_UNIFORM_NAME_LENGTH: 1365 string = "GL_UNIFORM_NAME_LENGTH"; 1366 break; 1367 case GL_ACTIVE_RESOURCES: 1368 string = "GL_ACTIVE_RESOURCES"; 1369 break; 1370 case GL_MAX_NAME_LENGTH: 1371 string = "GL_MAX_NAME_LENGTH"; 1372 break; 1373 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES: 1374 string = "GL_MAX_NUM_COMPATIBLE_SUBROUTINES"; 1375 break; 1376 case GL_NAME_LENGTH: 1377 string = "GL_NAME_LENGTH"; 1378 break; 1379 case GL_ARRAY_SIZE: 1380 string = "GL_ARRAY_SIZE"; 1381 break; 1382 case GL_LOCATION: 1383 string = "GL_LOCATION"; 1384 break; 1385 default: 1386 TCU_FAIL("Not implemented"); 1387 break; 1388 }; 1389 1390 return string; 1391 } 1392 1393 bool Utils::compare(const glw::GLfloat& left, const glw::GLfloat& right) 1394 { 1395 static const glw::GLfloat m_epsilon = 0.00001f; 1396 1397 if (m_epsilon < std::abs(right - left)) 1398 { 1399 return false; 1400 } 1401 else 1402 { 1403 return true; 1404 } 1405 } 1406 1407 /** Returns a variable type enum corresponding to user-specified base variable type 1408 * and the number of components it should support. 1409 * 1410 * @param base_variable_type Base variable type to use for the query. 1411 * @param n_components Number of components to consider for the query. 1412 * 1413 * @return As per description. 1414 **/ 1415 Utils::_variable_type Utils::getVariableTypeFromProperties(const _variable_type& base_variable_type, 1416 const unsigned int& n_components) 1417 { 1418 _variable_type result = VARIABLE_TYPE_UNKNOWN; 1419 1420 switch (base_variable_type) 1421 { 1422 case VARIABLE_TYPE_BOOL: 1423 { 1424 switch (n_components) 1425 { 1426 case 1: 1427 result = VARIABLE_TYPE_BOOL; 1428 break; 1429 case 2: 1430 result = VARIABLE_TYPE_BVEC2; 1431 break; 1432 case 3: 1433 result = VARIABLE_TYPE_BVEC3; 1434 break; 1435 case 4: 1436 result = VARIABLE_TYPE_BVEC4; 1437 break; 1438 1439 default: 1440 { 1441 TCU_FAIL("Unsupported number of components requested"); 1442 } 1443 } /* switch (n_components) */ 1444 1445 break; 1446 } 1447 1448 case VARIABLE_TYPE_DOUBLE: 1449 { 1450 switch (n_components) 1451 { 1452 case 1: 1453 result = VARIABLE_TYPE_DOUBLE; 1454 break; 1455 case 2: 1456 result = VARIABLE_TYPE_DVEC2; 1457 break; 1458 case 3: 1459 result = VARIABLE_TYPE_DVEC3; 1460 break; 1461 case 4: 1462 result = VARIABLE_TYPE_DVEC4; 1463 break; 1464 1465 default: 1466 { 1467 TCU_FAIL("Unsupported number of components requested"); 1468 } 1469 } /* switch (n_components) */ 1470 1471 break; 1472 } 1473 1474 case VARIABLE_TYPE_FLOAT: 1475 { 1476 switch (n_components) 1477 { 1478 case 1: 1479 result = VARIABLE_TYPE_FLOAT; 1480 break; 1481 case 2: 1482 result = VARIABLE_TYPE_VEC2; 1483 break; 1484 case 3: 1485 result = VARIABLE_TYPE_VEC3; 1486 break; 1487 case 4: 1488 result = VARIABLE_TYPE_VEC4; 1489 break; 1490 1491 default: 1492 { 1493 TCU_FAIL("Unsupported number of components requested"); 1494 } 1495 } /* switch (n_components) */ 1496 1497 break; 1498 } 1499 1500 case VARIABLE_TYPE_INT: 1501 { 1502 switch (n_components) 1503 { 1504 case 1: 1505 result = VARIABLE_TYPE_INT; 1506 break; 1507 case 2: 1508 result = VARIABLE_TYPE_IVEC2; 1509 break; 1510 case 3: 1511 result = VARIABLE_TYPE_IVEC3; 1512 break; 1513 case 4: 1514 result = VARIABLE_TYPE_IVEC4; 1515 break; 1516 1517 default: 1518 { 1519 TCU_FAIL("Unsupported number of components requested"); 1520 } 1521 } /* switch (n_components) */ 1522 1523 break; 1524 } 1525 1526 case VARIABLE_TYPE_UINT: 1527 { 1528 switch (n_components) 1529 { 1530 case 1: 1531 result = VARIABLE_TYPE_UINT; 1532 break; 1533 case 2: 1534 result = VARIABLE_TYPE_UVEC2; 1535 break; 1536 case 3: 1537 result = VARIABLE_TYPE_UVEC3; 1538 break; 1539 case 4: 1540 result = VARIABLE_TYPE_UVEC4; 1541 break; 1542 1543 default: 1544 { 1545 TCU_FAIL("Unsupported number of components requested"); 1546 } 1547 } /* switch (n_components) */ 1548 1549 break; 1550 } 1551 1552 default: 1553 { 1554 TCU_FAIL("Unrecognized base variable type"); 1555 } 1556 } /* switch (base_variable_type) */ 1557 1558 return result; 1559 } 1560 1561 /** Returns a GLSL literal corresponding to user-specified variable type. 1562 * 1563 * @param variable_type Variable type to use for the query. 1564 * 1565 * @return As per description or [?] if @param variable_type was not 1566 * recognized. 1567 **/ 1568 std::string Utils::getVariableTypeGLSLString(const _variable_type& variable_type) 1569 { 1570 std::string result = "[?]"; 1571 1572 switch (variable_type) 1573 { 1574 case VARIABLE_TYPE_BOOL: 1575 result = "bool"; 1576 break; 1577 case VARIABLE_TYPE_BVEC2: 1578 result = "bvec2"; 1579 break; 1580 case VARIABLE_TYPE_BVEC3: 1581 result = "bvec3"; 1582 break; 1583 case VARIABLE_TYPE_BVEC4: 1584 result = "bvec4"; 1585 break; 1586 case VARIABLE_TYPE_DOUBLE: 1587 result = "double"; 1588 break; 1589 case VARIABLE_TYPE_DVEC2: 1590 result = "dvec2"; 1591 break; 1592 case VARIABLE_TYPE_DVEC3: 1593 result = "dvec3"; 1594 break; 1595 case VARIABLE_TYPE_DVEC4: 1596 result = "dvec4"; 1597 break; 1598 case VARIABLE_TYPE_FLOAT: 1599 result = "float"; 1600 break; 1601 case VARIABLE_TYPE_INT: 1602 result = "int"; 1603 break; 1604 case VARIABLE_TYPE_IVEC2: 1605 result = "ivec2"; 1606 break; 1607 case VARIABLE_TYPE_IVEC3: 1608 result = "ivec3"; 1609 break; 1610 case VARIABLE_TYPE_IVEC4: 1611 result = "ivec4"; 1612 break; 1613 case VARIABLE_TYPE_MAT2: 1614 result = "mat2"; 1615 break; 1616 case VARIABLE_TYPE_MAT2X3: 1617 result = "mat2x3"; 1618 break; 1619 case VARIABLE_TYPE_MAT2X4: 1620 result = "mat2x4"; 1621 break; 1622 case VARIABLE_TYPE_MAT3: 1623 result = "mat3"; 1624 break; 1625 case VARIABLE_TYPE_MAT3X2: 1626 result = "mat3x2"; 1627 break; 1628 case VARIABLE_TYPE_MAT3X4: 1629 result = "mat3x4"; 1630 break; 1631 case VARIABLE_TYPE_MAT4: 1632 result = "mat4"; 1633 break; 1634 case VARIABLE_TYPE_MAT4X2: 1635 result = "mat4x2"; 1636 break; 1637 case VARIABLE_TYPE_MAT4X3: 1638 result = "mat4x3"; 1639 break; 1640 case VARIABLE_TYPE_UINT: 1641 result = "uint"; 1642 break; 1643 case VARIABLE_TYPE_UVEC2: 1644 result = "uvec2"; 1645 break; 1646 case VARIABLE_TYPE_UVEC3: 1647 result = "uvec3"; 1648 break; 1649 case VARIABLE_TYPE_UVEC4: 1650 result = "uvec4"; 1651 break; 1652 case VARIABLE_TYPE_VEC2: 1653 result = "vec2"; 1654 break; 1655 case VARIABLE_TYPE_VEC3: 1656 result = "vec3"; 1657 break; 1658 case VARIABLE_TYPE_VEC4: 1659 result = "vec4"; 1660 break; 1661 1662 default: 1663 { 1664 TCU_FAIL("Unrecognized variable type"); 1665 } 1666 } /* switch (variable_type) */ 1667 1668 return result; 1669 } 1670 1671 /** Constructor. 1672 * 1673 * @param context Rendering context. 1674 * 1675 **/ 1676 APITest1::APITest1(deqp::Context& context) 1677 : TestCase(context, "min_maxes", "Verifies the implementation returns valid GL_MAX_SUBROUTINE* pnames " 1678 "which meet the minimum maximum requirements enforced by the spec.") 1679 , m_has_test_passed(true) 1680 { 1681 /* Left blank intentionally */ 1682 } 1683 1684 /** Executes test iteration. 1685 * 1686 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 1687 */ 1688 tcu::TestNode::IterateResult APITest1::iterate() 1689 { 1690 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1691 1692 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 1693 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 1694 { 1695 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 1696 } 1697 1698 /* Iterate over all pnames */ 1699 const struct 1700 { 1701 glw::GLenum pname; 1702 const char* pname_string; 1703 glw::GLint min_value; 1704 } pnames[] = { { GL_MAX_SUBROUTINES, "GL_MAX_SUBROUTINES", 256 }, 1705 { GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS", 1024 } }; 1706 const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]); 1707 1708 for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname) 1709 { 1710 glw::GLboolean bool_value = GL_FALSE; 1711 glw::GLdouble double_value = 0.0; 1712 glw::GLfloat float_value = 0.0f; 1713 glw::GLint int_value = 0; 1714 glw::GLint64 int64_value = 0; 1715 const glw::GLint min_value = pnames[n_pname].min_value; 1716 const glw::GLenum& pname = pnames[n_pname].pname; 1717 const char* pname_string = pnames[n_pname].pname_string; 1718 1719 /* Retrieve the pname values */ 1720 gl.getBooleanv(pname, &bool_value); 1721 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() call failed."); 1722 1723 gl.getDoublev(pname, &double_value); 1724 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetDoublev() call failed."); 1725 1726 gl.getFloatv(pname, &float_value); 1727 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed."); 1728 1729 gl.getIntegerv(pname, &int_value); 1730 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed."); 1731 1732 gl.getInteger64v(pname, &int64_value); 1733 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v() call failed."); 1734 1735 /* Make sure the value reported meets the min max requirement */ 1736 if (int_value < min_value) 1737 { 1738 m_testCtx.getLog() << tcu::TestLog::Message << "GL implementation reports a value of [" << int_value 1739 << "]" 1740 " for property [" 1741 << pname_string << "]" 1742 ", whereas the min max for the property is [" 1743 << min_value << "]." << tcu::TestLog::EndMessage; 1744 1745 m_has_test_passed = false; 1746 } 1747 1748 /* Verify the other getters reported valid values */ 1749 const float epsilon = 1e-5f; 1750 1751 if (((int_value == 0) && (bool_value == GL_TRUE)) || ((int_value != 0) && (bool_value != GL_TRUE))) 1752 { 1753 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid boolean value [" << bool_value 1754 << "]" 1755 " reported for property [" 1756 << pname_string << "]" 1757 " (int value:[" 1758 << int_value << "])" << tcu::TestLog::EndMessage; 1759 1760 m_has_test_passed = false; 1761 } 1762 1763 if (de::abs(double_value - (double)int_value) > epsilon) 1764 { 1765 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid double value [" << double_value 1766 << "]" 1767 " reported for property [" 1768 << pname_string << "]" 1769 " (int value:[" 1770 << int_value << "])" << tcu::TestLog::EndMessage; 1771 1772 m_has_test_passed = false; 1773 } 1774 1775 if (de::abs(float_value - (float)int_value) > epsilon) 1776 { 1777 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid float value [" << float_value 1778 << "]" 1779 " reported for property [" 1780 << pname_string << "]" 1781 " (int value:[" 1782 << int_value << "])" << tcu::TestLog::EndMessage; 1783 1784 m_has_test_passed = false; 1785 } 1786 1787 if (int64_value != int_value) 1788 { 1789 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid 64-bit integer value [" << float_value 1790 << "]" 1791 " reported for property [" 1792 << pname_string << "]" 1793 " (int value:[" 1794 << int_value << "])" << tcu::TestLog::EndMessage; 1795 1796 m_has_test_passed = false; 1797 } 1798 } /* for (all pnames) */ 1799 1800 if (m_has_test_passed) 1801 { 1802 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1803 } 1804 else 1805 { 1806 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1807 } 1808 1809 return STOP; 1810 } 1811 1812 /** Constructor. 1813 * 1814 * @param context Rendering context. 1815 * 1816 **/ 1817 APITest2::APITest2(deqp::Context& context) 1818 : TestCase(context, "name_getters", "Verifies glGetActiveSubroutineName() and glGetActiveSubroutineUniformName() " 1819 "functions work correctly.") 1820 , m_buffer(DE_NULL) 1821 , m_has_test_passed(true) 1822 , m_po_id(0) 1823 , m_subroutine_name1("subroutine1") 1824 , m_subroutine_name2("subroutine2") 1825 , m_subroutine_uniform_name("data_provider") 1826 , m_vs_id(0) 1827 { 1828 /* Left blank intentionally */ 1829 } 1830 1831 /** Destroys all ES objects that may have been created during test initialization, 1832 * as well as releases any buffers that may have been allocated during the process. 1833 */ 1834 void APITest2::deinit() 1835 { 1836 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1837 1838 if (m_buffer != DE_NULL) 1839 { 1840 delete[] m_buffer; 1841 1842 m_buffer = DE_NULL; 1843 } 1844 1845 if (m_po_id != 0) 1846 { 1847 gl.deleteProgram(m_po_id); 1848 1849 m_po_id = 0; 1850 } 1851 1852 if (m_vs_id != 0) 1853 { 1854 gl.deleteShader(m_vs_id); 1855 1856 m_vs_id = 0; 1857 } 1858 } 1859 1860 /** Returns body of a vertex shader that should be used for the test. 1861 * 1862 * @return As per description. 1863 **/ 1864 std::string APITest2::getVertexShaderBody() 1865 { 1866 return "#version 400\n" 1867 "\n" 1868 "#extension GL_ARB_shader_subroutine : require\n" 1869 "\n" 1870 "subroutine int ExampleSubroutineType(int example_argument);\n" 1871 "\n" 1872 "subroutine(ExampleSubroutineType) int subroutine1(int example_argument)\n" 1873 "{\n" 1874 " return 1;\n" 1875 "}\n" 1876 "\n" 1877 "subroutine(ExampleSubroutineType) int subroutine2(int example_argument)\n" 1878 "{\n" 1879 " return 2;\n" 1880 "}\n" 1881 "\n" 1882 "subroutine uniform ExampleSubroutineType data_provider;\n" 1883 "\n" 1884 "void main()\n" 1885 "{\n" 1886 " gl_Position = vec4(float(data_provider(0)), vec3(1) );\n" 1887 "}\n"; 1888 } 1889 1890 /** Initializes all ES objects required to run the test. */ 1891 void APITest2::initTest() 1892 { 1893 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1894 1895 /* Generate program & shader objects */ 1896 m_po_id = gl.createProgram(); 1897 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1898 1899 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call(s) failed."); 1900 1901 /* Attach the shader to the program object */ 1902 gl.attachShader(m_po_id, m_vs_id); 1903 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 1904 1905 /* Compile the shader */ 1906 glw::GLint compile_status = GL_FALSE; 1907 std::string vs_body = getVertexShaderBody(); 1908 const char* vs_body_raw_ptr = vs_body.c_str(); 1909 1910 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */); 1911 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 1912 1913 gl.compileShader(m_vs_id); 1914 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 1915 1916 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); 1917 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 1918 1919 if (compile_status != GL_TRUE) 1920 { 1921 TCU_FAIL("Shader compilation failed."); 1922 } 1923 1924 /* Try to link the program object */ 1925 glw::GLint link_status = GL_FALSE; 1926 1927 gl.linkProgram(m_po_id); 1928 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 1929 1930 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 1931 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 1932 1933 if (link_status != GL_TRUE) 1934 { 1935 TCU_FAIL("Program linking failed."); 1936 } 1937 1938 /* Perform a few sanity checks */ 1939 glw::GLint n_active_subroutines = 0; 1940 glw::GLint n_active_subroutine_uniforms = 0; 1941 1942 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines); 1943 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms); 1944 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call failed."); 1945 1946 if (n_active_subroutines != 2 /* subroutines declared in vertex shader */) 1947 { 1948 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid amount of active subroutines reported; expected: 2," 1949 " reported:" 1950 << n_active_subroutines << tcu::TestLog::EndMessage; 1951 1952 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINES property value."); 1953 } 1954 1955 if (n_active_subroutine_uniforms != 1) 1956 { 1957 m_testCtx.getLog() << tcu::TestLog::Message 1958 << "Invalid amount of active subroutine uniforms reported: expected: 1," 1959 " reported: " 1960 << n_active_subroutine_uniforms << tcu::TestLog::EndMessage; 1961 1962 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORMS property value."); 1963 } 1964 } 1965 1966 /** Executes test iteration. 1967 * 1968 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 1969 */ 1970 tcu::TestNode::IterateResult APITest2::iterate() 1971 { 1972 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 1973 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 1974 { 1975 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 1976 } 1977 1978 /* Initialize a test program object */ 1979 initTest(); 1980 1981 /* Verify glGetActiveSubroutineName() works correctly */ 1982 verifyGLGetActiveSubroutineNameFunctionality(); 1983 1984 /* Verify glGetActiveSubroutineUniformName() works correctly */ 1985 verifyGLGetActiveSubroutineUniformNameFunctionality(); 1986 1987 /* Done */ 1988 if (m_has_test_passed) 1989 { 1990 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1991 } 1992 else 1993 { 1994 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1995 } 1996 1997 return STOP; 1998 } 1999 2000 /** Verifies glGetActiveSubroutineName() behaves as per GL_ARB_shader_subroutine 2001 * specification. 2002 **/ 2003 void APITest2::verifyGLGetActiveSubroutineNameFunctionality() 2004 { 2005 GLsizei expected_length1 = (GLsizei)strlen(m_subroutine_name1) + 1; 2006 GLsizei expected_length2 = (GLsizei)strlen(m_subroutine_name1) + 1; 2007 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2008 GLsizei reported_length = 0; 2009 2010 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, /* index */ 2011 0, /* bufsize */ 2012 DE_NULL, /* length */ 2013 DE_NULL); /* name */ 2014 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed."); 2015 2016 gl.getProgramInterfaceiv(m_po_id, GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, &reported_length); 2017 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed."); 2018 2019 if ((reported_length != expected_length1) && (reported_length != expected_length2)) 2020 { 2021 m_testCtx.getLog() << tcu::TestLog::Message 2022 << "Invalid active subroutine name length reported:" << reported_length 2023 << ", instead of: " << expected_length1 << " or " << expected_length2 2024 << tcu::TestLog::EndMessage; 2025 2026 TCU_FAIL("Incorrect length of active subroutine name"); 2027 } 2028 2029 m_buffer = new glw::GLchar[reported_length]; 2030 2031 memset(m_buffer, 0, reported_length); 2032 2033 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, reported_length, DE_NULL, /* length */ 2034 m_buffer); 2035 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed."); 2036 2037 if (strcmp(m_buffer, m_subroutine_name1) != 0 && strcmp(m_buffer, m_subroutine_name2) != 0) 2038 { 2039 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine name reported:[" << m_buffer 2040 << "]" 2041 " instead of:[" 2042 << m_subroutine_name1 << "]" 2043 " or:[" 2044 << m_subroutine_name2 << "]." << tcu::TestLog::EndMessage; 2045 2046 TCU_FAIL("Invalid active subroutine name reported."); 2047 } 2048 2049 delete[] m_buffer; 2050 m_buffer = DE_NULL; 2051 } 2052 2053 /** Verifies glGetActiveSubroutineUniformName() behaves as per GL_ARB_shader_subroutine 2054 * specification. 2055 **/ 2056 void APITest2::verifyGLGetActiveSubroutineUniformNameFunctionality() 2057 { 2058 GLsizei expected_length = (GLsizei)strlen(m_subroutine_uniform_name); 2059 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2060 GLsizei reported_length = 0; 2061 2062 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */ 2063 0, /* bufsize */ 2064 DE_NULL, /* length */ 2065 DE_NULL); /* name */ 2066 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed."); 2067 2068 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */ 2069 0, /* bufsize */ 2070 &reported_length, DE_NULL); /* name */ 2071 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed."); 2072 2073 // reported_length is the actual number of characters written into <name> 2074 // If <bufSize> is 0, reported_length should be 0 2075 if (reported_length != 0) 2076 { 2077 m_testCtx.getLog() << tcu::TestLog::Message 2078 << "Invalid active subroutine uniform name length reported:" << reported_length 2079 << ", instead of: " << 0 << tcu::TestLog::EndMessage; 2080 2081 TCU_FAIL("Incorrect length of active subroutine uniform name"); 2082 } 2083 2084 m_buffer = new glw::GLchar[expected_length + 1]; 2085 2086 memset(m_buffer, 0, expected_length + 1); 2087 2088 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, expected_length + 1, &reported_length, m_buffer); 2089 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformName() call failed."); 2090 2091 if (reported_length != expected_length) 2092 { 2093 m_testCtx.getLog() << tcu::TestLog::Message 2094 << "Invalid active subroutine uniform name length reported:" << reported_length 2095 << ", instead of: " << expected_length << tcu::TestLog::EndMessage; 2096 2097 TCU_FAIL("Incorrect length of active subroutine uniform name"); 2098 } 2099 2100 if (strcmp(m_buffer, m_subroutine_uniform_name) != 0) 2101 { 2102 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine uniform name reported:[" << m_buffer 2103 << "]" 2104 " instead of:[" 2105 << m_subroutine_uniform_name << "]" << tcu::TestLog::EndMessage; 2106 2107 TCU_FAIL("Invalid active subroutine uniform name reported."); 2108 } 2109 2110 delete[] m_buffer; 2111 m_buffer = DE_NULL; 2112 } 2113 2114 /** Constructor. 2115 * 2116 * @param context Rendering context. 2117 * 2118 **/ 2119 FunctionalTest1_2::FunctionalTest1_2(deqp::Context& context) 2120 : TestCase(context, "two_subroutines_single_subroutine_uniform", 2121 "Verifies the subroutines work correctly in a vertex shader for" 2122 " bool/float/int/uint/double/*vec*/*mat* argument and return types") 2123 , m_has_test_passed(true) 2124 , m_po_id(0) 2125 , m_po_getter0_subroutine_index(GL_INVALID_INDEX) 2126 , m_po_getter1_subroutine_index(GL_INVALID_INDEX) 2127 , m_po_subroutine_uniform_index(-1) 2128 , m_xfb_bo_id(0) 2129 , m_vao_id(0) 2130 , m_vs_id(0) 2131 { 2132 /* Left blank intentionally */ 2133 } 2134 2135 /** Destroys all ES objects that may have been created during test initialization, 2136 * as well as releases any buffers that may have been allocated during the process. 2137 */ 2138 void FunctionalTest1_2::deinit() 2139 { 2140 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2141 2142 deinitTestIteration(); 2143 2144 if (m_xfb_bo_id != 0) 2145 { 2146 gl.deleteBuffers(1, &m_xfb_bo_id); 2147 2148 m_xfb_bo_id = 0; 2149 } 2150 2151 if (m_vao_id != 0) 2152 { 2153 gl.deleteVertexArrays(1, &m_vao_id); 2154 2155 m_vao_id = 0; 2156 } 2157 } 2158 2159 /** Deinitializes GL objects that are iteration-specific */ 2160 void FunctionalTest1_2::deinitTestIteration() 2161 { 2162 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2163 2164 if (m_po_id != 0) 2165 { 2166 gl.deleteProgram(m_po_id); 2167 2168 m_po_id = 0; 2169 } 2170 2171 if (m_vs_id != 0) 2172 { 2173 gl.deleteShader(m_vs_id); 2174 2175 m_vs_id = 0; 2176 } 2177 } 2178 2179 /** Executes a single test iteration using user-specified test case propertiesz. 2180 * 2181 * @param test-case Test case descriptor. 2182 * 2183 * @return true if the test iteration passed, false otherwise. 2184 **/ 2185 bool FunctionalTest1_2::executeTestIteration(const _test_case& test_case) 2186 { 2187 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2188 bool result = true; 2189 2190 /* Build the test program */ 2191 std::string empty_body; 2192 std::string vs_body = getVertexShaderBody(test_case.variable_type, test_case.array_size); 2193 const glw::GLchar* xfb_varyings[] = { "result" }; 2194 const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]); 2195 2196 if (!Utils::buildProgram(gl, vs_body, empty_body, empty_body, empty_body, empty_body, xfb_varyings, n_xfb_varyings, 2197 &m_vs_id, NULL, /* out_tc_id */ 2198 NULL, /* out_te_id */ 2199 NULL, /* out_gs_id */ 2200 NULL, &m_po_id)) 2201 { 2202 TCU_FAIL("Test program failed to build."); 2203 } 2204 2205 /* Retrieve subroutine locations */ 2206 m_po_getter0_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter0"); 2207 m_po_getter1_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter1"); 2208 2209 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 2210 2211 if (m_po_getter0_subroutine_index == GL_INVALID_INDEX || m_po_getter1_subroutine_index == GL_INVALID_INDEX) 2212 { 2213 TCU_FAIL("At least one subroutine is considered inactive which is invalid."); 2214 } 2215 2216 /* Retrieve subroutine uniform location */ 2217 m_po_subroutine_uniform_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "colorGetterUniform"); 2218 2219 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call failed."); 2220 2221 if (m_po_subroutine_uniform_index == -1) 2222 { 2223 TCU_FAIL("Subroutine uniform is considered inactive which is invalid."); 2224 } 2225 2226 /* Set up XFB BO storage */ 2227 const Utils::_variable_type base_variable_type = Utils::getBaseVariableType(test_case.variable_type); 2228 unsigned int iteration_xfb_bo_size = Utils::getComponentSizeForVariableType(base_variable_type) * 2229 Utils::getNumberOfComponentsForVariableType(test_case.variable_type); 2230 unsigned int total_xfb_bo_size = 0; 2231 2232 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2233 { 2234 /* Boolean varyings are not supported by OpenGL. Instead, we use ints to output 2235 * boolean values. */ 2236 iteration_xfb_bo_size = static_cast<unsigned int>(iteration_xfb_bo_size * sizeof(int)); 2237 } 2238 2239 total_xfb_bo_size = iteration_xfb_bo_size * 2 /* subroutines we will be testing */; 2240 2241 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, total_xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW); 2242 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 2243 2244 /* Activate test program object */ 2245 gl.useProgram(m_po_id); 2246 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2247 2248 /* Run two iterations. Each iteration should invoke different subroutine. */ 2249 const glw::GLuint subroutine_indices[] = { m_po_getter0_subroutine_index, m_po_getter1_subroutine_index }; 2250 const unsigned int n_subroutine_indices = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 2251 2252 for (unsigned int n_subroutine_index = 0; n_subroutine_index < n_subroutine_indices; ++n_subroutine_index) 2253 { 2254 /* Configure which subroutine should be used for the draw call */ 2255 glw::GLuint current_subroutine_index = subroutine_indices[n_subroutine_index]; 2256 2257 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, ¤t_subroutine_index); 2258 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed."); 2259 2260 /* Update XFB binding so that we do not overwrite data XFBed in previous iterations */ 2261 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 2262 m_xfb_bo_id, iteration_xfb_bo_size * n_subroutine_index, iteration_xfb_bo_size); 2263 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() call failed."); 2264 2265 /* Draw a single point */ 2266 gl.beginTransformFeedback(GL_POINTS); 2267 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 2268 { 2269 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 2270 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 2271 } 2272 gl.endTransformFeedback(); 2273 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 2274 } /* for (all subroutine indices) */ 2275 2276 /* Map the BO storage into process space */ 2277 const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 2278 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 2279 2280 result &= verifyXFBData(xfb_data_ptr, test_case.variable_type); 2281 2282 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 2283 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffeR() call failed."); 2284 2285 return result; 2286 } 2287 2288 /** Retrieves body of a vertex shader that should be used to verify 2289 * subroutine support, given user-specified test iteration properties. 2290 * 2291 * @param variable_type GLSL type that should be used for argument and 2292 * return type definition in a subroutine. This setting 2293 * also affects type of the only output variable in the shader. 2294 * @param array_size 1 if non-arrayed arguments/return types should be tested; 2295 * 2 if arrayed arguments/return types should be tested. 2296 * 2297 * @return Requested string. 2298 **/ 2299 std::string FunctionalTest1_2::getVertexShaderBody(const Utils::_variable_type& variable_type, unsigned int array_size) 2300 { 2301 Utils::_variable_type base_variable_type = Utils::getBaseVariableType(variable_type); 2302 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 2303 std::stringstream result_sstream; 2304 std::string variable_type_glsl = Utils::getVariableTypeGLSLString(variable_type); 2305 std::stringstream variable_type_glsl_array_sstream; 2306 std::stringstream variable_type_glsl_arrayed_sstream; 2307 2308 variable_type_glsl_arrayed_sstream << variable_type_glsl; 2309 2310 if (array_size > 1) 2311 { 2312 variable_type_glsl_array_sstream << "[" << array_size << "]"; 2313 variable_type_glsl_arrayed_sstream << variable_type_glsl_array_sstream.str(); 2314 } 2315 2316 /* Form pre-amble */ 2317 result_sstream << "#version 400\n" 2318 "\n" 2319 "#extension GL_ARB_shader_subroutine : require\n"; 2320 2321 if (variable_type == Utils::VARIABLE_TYPE_DOUBLE) 2322 { 2323 result_sstream << "#extension GL_ARB_gpu_shader_fp64 : require\n"; 2324 } 2325 2326 /* Form subroutine type declaration */ 2327 result_sstream << "\n" 2328 "subroutine " 2329 << variable_type_glsl_arrayed_sstream.str() << " colorGetter(in " << variable_type_glsl 2330 << " in_value" << variable_type_glsl_array_sstream.str() << ");\n" 2331 "\n"; 2332 2333 /* Declare getter functions */ 2334 for (int n_getter = 0; n_getter < 2; ++n_getter) 2335 { 2336 result_sstream << "subroutine(colorGetter) " << variable_type_glsl_arrayed_sstream.str() << " getter" 2337 << n_getter << "(in " << variable_type_glsl << " in_value" 2338 << variable_type_glsl_array_sstream.str() << ")\n" 2339 "{\n"; 2340 2341 if (array_size > 1) 2342 { 2343 result_sstream << variable_type_glsl << " temp" << variable_type_glsl_array_sstream.str() << ";\n"; 2344 } 2345 2346 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2347 { 2348 if (array_size > 1) 2349 { 2350 for (unsigned int array_index = 0; array_index < array_size; ++array_index) 2351 { 2352 result_sstream << " temp[" << array_index << "]" 2353 " = " 2354 << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "") 2355 << "(in_value[" << array_index << "]);\n"; 2356 } 2357 2358 result_sstream << " return temp;\n"; 2359 } 2360 else 2361 { 2362 result_sstream << " return " 2363 << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "") 2364 << "(in_value);\n"; 2365 } 2366 } /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */ 2367 else 2368 { 2369 if (array_size > 1) 2370 { 2371 for (unsigned int array_index = 0; array_index < array_size; ++array_index) 2372 { 2373 result_sstream << " temp[" << array_index << "]" 2374 " = in_value[" 2375 << array_index << "] + " << (n_getter + 1) << ";\n"; 2376 } 2377 2378 result_sstream << " return temp;\n"; 2379 } 2380 else 2381 { 2382 result_sstream << " return (in_value + " << (n_getter + 1) << ");\n"; 2383 } 2384 } 2385 2386 result_sstream << "}\n"; 2387 } /* for (both getter functions) */ 2388 2389 /* Declare subroutine uniform */ 2390 result_sstream << "subroutine uniform colorGetter colorGetterUniform;\n" 2391 "\n"; 2392 2393 /* Declare output variable */ 2394 result_sstream << "out "; 2395 2396 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2397 { 2398 Utils::_variable_type result_as_int_variable_type = 2399 Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components); 2400 std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type); 2401 2402 result_sstream << variable_type_glsl_as_int; 2403 } 2404 else 2405 { 2406 result_sstream << variable_type_glsl; 2407 } 2408 2409 result_sstream << " result;\n" 2410 "\n"; 2411 2412 /* Declare main(): prepare input argument for the subroutine function */ 2413 result_sstream << "void main()\n" 2414 "{\n" 2415 " " 2416 << variable_type_glsl << " temp"; 2417 2418 if (array_size > 1) 2419 { 2420 result_sstream << "[" << array_size << "]"; 2421 }; 2422 2423 result_sstream << ";\n"; 2424 2425 for (unsigned int array_index = 0; array_index < array_size; ++array_index) 2426 { 2427 result_sstream << " temp"; 2428 2429 if (array_size > 1) 2430 { 2431 result_sstream << "[" << array_index << "]"; 2432 } 2433 2434 result_sstream << " = " << variable_type_glsl << "("; 2435 2436 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2437 { 2438 result_sstream << "true"; 2439 } 2440 else 2441 { 2442 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 2443 { 2444 result_sstream << "3"; 2445 2446 if (n_component != (n_variable_type_components - 1)) 2447 { 2448 result_sstream << ", "; 2449 } 2450 } /* for (all components) */ 2451 } 2452 2453 result_sstream << ");\n"; 2454 } /* for (all array indices) */ 2455 2456 /* Declare main(): call the subroutine. Verify the input and write the result 2457 * to the output variable. 2458 **/ 2459 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2460 { 2461 Utils::_variable_type result_as_int_variable_type = 2462 Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components); 2463 std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type); 2464 2465 result_sstream << variable_type_glsl_arrayed_sstream.str() << " subroutine_result = colorGetterUniform(temp);\n" 2466 "result = "; 2467 2468 for (unsigned int array_index = 0; array_index < array_size; ++array_index) 2469 { 2470 if (variable_type_glsl == "bool") 2471 result_sstream << "bool(subroutine_result"; 2472 else 2473 result_sstream << "all(subroutine_result"; 2474 2475 if (array_size > 1) 2476 { 2477 result_sstream << "[" << array_index << "]"; 2478 } 2479 2480 result_sstream << ")"; 2481 2482 if (array_index != (array_size - 1)) 2483 { 2484 result_sstream << "&& "; 2485 } 2486 } 2487 2488 result_sstream << " == true ? " << variable_type_glsl_as_int << "(1) : " << variable_type_glsl_as_int << "(0);"; 2489 } 2490 else 2491 { 2492 if (array_size > 1) 2493 { 2494 DE_ASSERT(array_size == 2); 2495 2496 result_sstream << variable_type_glsl << " subroutine_result" << variable_type_glsl_array_sstream.str() 2497 << " = colorGetterUniform(temp);\n" 2498 "\n" 2499 "if (subroutine_result[0] == subroutine_result[1]) result = subroutine_result[0];\n" 2500 "else\n" 2501 "result = " 2502 << variable_type_glsl << "(-1);\n"; 2503 } 2504 else 2505 { 2506 result_sstream << "result = colorGetterUniform(temp);\n"; 2507 } 2508 } 2509 2510 /* All done */ 2511 result_sstream << "}\n"; 2512 2513 return result_sstream.str(); 2514 } 2515 2516 /** Initializes all GL objects required to run the test. */ 2517 void FunctionalTest1_2::initTest() 2518 { 2519 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2520 2521 /* Generate buffer object to hold result XFB data */ 2522 gl.genBuffers(1, &m_xfb_bo_id); 2523 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 2524 2525 /* Set up XFB BO bindings */ 2526 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 2527 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 2528 2529 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 2530 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 2531 2532 /* Generate VAO to use for the draw calls */ 2533 gl.genVertexArrays(1, &m_vao_id); 2534 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 2535 2536 gl.bindVertexArray(m_vao_id); 2537 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 2538 } 2539 2540 /** Executes test iteration. 2541 * 2542 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 2543 */ 2544 tcu::TestNode::IterateResult FunctionalTest1_2::iterate() 2545 { 2546 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 2547 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 2548 { 2549 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 2550 } 2551 2552 /* Initialize a test program object */ 2553 initTest(); 2554 2555 /* Construct test case descriptors: first, iIerate over all 2556 * variable types we want to cover */ 2557 const Utils::_variable_type variable_types[] = { 2558 Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_BVEC2, Utils::VARIABLE_TYPE_BVEC3, 2559 Utils::VARIABLE_TYPE_BVEC4, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, 2560 Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_IVEC3, 2561 Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_MAT2X3, 2562 Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_MAT3X2, 2563 Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_MAT4X2, 2564 Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_UVEC2, 2565 Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_VEC2, 2566 Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_VEC4 2567 }; 2568 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]); 2569 2570 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type) 2571 { 2572 Utils::_variable_type current_variable_type = variable_types[n_variable_type]; 2573 2574 /* We need to test both arrayed and non-arrayed arguments */ 2575 for (unsigned int array_size = 1; array_size < 3; ++array_size) 2576 { 2577 /* Exclude double variables if the relevant extension is unavailable */ 2578 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64") && 2579 current_variable_type == Utils::VARIABLE_TYPE_DOUBLE) 2580 { 2581 continue; 2582 } 2583 2584 /* Form the descriptor */ 2585 _test_case test_case; 2586 2587 test_case.array_size = array_size; 2588 test_case.variable_type = current_variable_type; 2589 2590 /* Store the test case descriptor */ 2591 m_test_cases.push_back(test_case); 2592 } /* for (both arrayed and non-arrayed arguments) */ 2593 } /* for (all variable types) */ 2594 2595 /* Iterate over all test cases and execute the test */ 2596 for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end(); 2597 ++test_case_iterator) 2598 { 2599 const _test_case& test_case = *test_case_iterator; 2600 2601 m_has_test_passed &= executeTestIteration(test_case); 2602 2603 /* Release GL objects that were created during the execution */ 2604 deinitTestIteration(); 2605 } /* for (all test cases) */ 2606 2607 /* Done */ 2608 if (m_has_test_passed) 2609 { 2610 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2611 } 2612 else 2613 { 2614 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2615 } 2616 2617 return STOP; 2618 } 2619 2620 /** Verifies data that has been XFBed out by the vertex shader. 2621 * 2622 * @param xfb_data Buffer holding the data. 2623 * @param variable_type GLSL type used for the test iteration 2624 * that generated the data at @param xfb_data. 2625 * 2626 * @return true if the data was found to be valid, false if it 2627 * was detected to be incorrect. 2628 **/ 2629 bool FunctionalTest1_2::verifyXFBData(const void* xfb_data, const Utils::_variable_type& variable_type) 2630 { 2631 const Utils::_variable_type base_variable_type = Utils::getBaseVariableType(variable_type); 2632 const float epsilon = 1e-5f; 2633 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 2634 bool result = true; 2635 const unsigned char* traveller_ptr = (const unsigned char*)xfb_data; 2636 2637 /* Boolean arguments/return types are tested with a slightly different shader so we 2638 * need to test them in a separate code-path. 2639 */ 2640 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2641 { 2642 /* 0 should be returned when getter0 is used, 1 otherwise */ 2643 const unsigned int ref_values[] = { 0, 1 }; 2644 const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]); 2645 2646 for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value) 2647 { 2648 const unsigned int ref_value = ref_values[n_ref_value]; 2649 2650 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 2651 { 2652 int* result_value_ptr = (int*)(traveller_ptr); 2653 2654 if (*result_value_ptr != (int)ref_value) 2655 { 2656 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using " 2657 "[" 2658 << Utils::getVariableTypeGLSLString(variable_type) << "]" 2659 << " argument/return types (" 2660 "expected:[" 2661 << ref_value << "], found:[" << *result_value_ptr << "])" 2662 << tcu::TestLog::EndMessage; 2663 2664 result = false; 2665 break; 2666 } 2667 2668 traveller_ptr += sizeof(int); 2669 } /* for (all components) */ 2670 } /* for (all reference values) */ 2671 } /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */ 2672 else 2673 { 2674 /* 4 should be returned when getter0 is used, 5 otherwise */ 2675 const unsigned int ref_values[] = { 4, 5 }; 2676 const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]); 2677 2678 for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value) 2679 { 2680 const unsigned int ref_value = ref_values[n_ref_value]; 2681 2682 DE_ASSERT( 2683 base_variable_type == Utils::VARIABLE_TYPE_DOUBLE || base_variable_type == Utils::VARIABLE_TYPE_FLOAT || 2684 base_variable_type == Utils::VARIABLE_TYPE_INT || base_variable_type == Utils::VARIABLE_TYPE_UINT); 2685 2686 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 2687 { 2688 const double* double_value_ptr = (double*)traveller_ptr; 2689 const float* float_value_ptr = (float*)traveller_ptr; 2690 const int* int_value_ptr = (int*)traveller_ptr; 2691 2692 switch (base_variable_type) 2693 { 2694 case Utils::VARIABLE_TYPE_DOUBLE: 2695 { 2696 if (de::abs(*double_value_ptr - (double)ref_value) > epsilon) 2697 { 2698 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using " 2699 "[" 2700 << Utils::getVariableTypeGLSLString(variable_type) << "]" 2701 << " argument/return types (" 2702 "expected:[" 2703 << ref_value << "], found:[" << *double_value_ptr << "])" 2704 << tcu::TestLog::EndMessage; 2705 2706 result = false; 2707 } 2708 2709 traveller_ptr += sizeof(double); 2710 break; 2711 } 2712 2713 case Utils::VARIABLE_TYPE_FLOAT: 2714 { 2715 if (de::abs(*float_value_ptr - (float)ref_value) > epsilon) 2716 { 2717 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using " 2718 "[" 2719 << Utils::getVariableTypeGLSLString(variable_type) << "]" 2720 << " argument/return types (" 2721 "expected:[" 2722 << ref_value << "], found:[" << *float_value_ptr << "])" 2723 << tcu::TestLog::EndMessage; 2724 2725 result = false; 2726 } 2727 2728 traveller_ptr += sizeof(float); 2729 break; 2730 } 2731 2732 case Utils::VARIABLE_TYPE_INT: 2733 case Utils::VARIABLE_TYPE_UINT: 2734 { 2735 if (*int_value_ptr != (int)ref_value) 2736 { 2737 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using " 2738 "[" 2739 << Utils::getVariableTypeGLSLString(variable_type) << "]" 2740 << " argument/return types (" 2741 "expected:[" 2742 << ref_value << "], found:[" << *int_value_ptr << "])" 2743 << tcu::TestLog::EndMessage; 2744 2745 result = false; 2746 } 2747 2748 traveller_ptr += sizeof(int); 2749 break; 2750 } 2751 2752 default: 2753 break; 2754 } /* switch (base_variable_type) */ 2755 } /* for (all components) */ 2756 } /* for (all reference values) */ 2757 } 2758 2759 return result; 2760 } 2761 2762 /** Constructor 2763 * 2764 * @param context CTS context 2765 **/ 2766 FunctionalTest3_4::FunctionalTest3_4(deqp::Context& context) 2767 : TestCase(context, "four_subroutines_with_two_uniforms", "Verify Get* API and draw calls") 2768 , m_n_active_subroutine_uniforms(0) 2769 , m_n_active_subroutine_uniform_locations(0) 2770 , m_n_active_subroutines(0) 2771 , m_n_active_subroutine_uniform_name_length(0) 2772 , m_n_active_subroutine_name_length(0) 2773 , m_n_active_subroutine_uniform_size(0) 2774 { 2775 /* Nothing to be done here */ 2776 } 2777 2778 /** Execute test 2779 * 2780 * @return tcu::TestNode::STOP 2781 **/ 2782 tcu::TestNode::IterateResult FunctionalTest3_4::iterate() 2783 { 2784 static const glw::GLchar* vertex_shader_code = 2785 "#version 400 core\n" 2786 "#extension GL_ARB_shader_subroutine : require\n" 2787 "\n" 2788 "precision highp float;\n" 2789 "\n" 2790 "// Sub routine type declaration\n" 2791 "subroutine vec4 routine_type(in vec4 iparam);\n" 2792 "\n" 2793 "// Sub routine definitions\n" 2794 "subroutine(routine_type) vec4 inverse_order(in vec4 iparam)\n" 2795 "{\n" 2796 " return iparam.wzyx;\n" 2797 "}\n" 2798 "\n" 2799 "subroutine(routine_type) vec4 negate(in vec4 iparam)\n" 2800 "{\n" 2801 " return -iparam;\n" 2802 "}\n" 2803 "\n" 2804 "subroutine(routine_type) vec4 inverse(in vec4 iparam)\n" 2805 "{\n" 2806 " return 1 / iparam;\n" 2807 "}\n" 2808 "\n" 2809 "subroutine(routine_type) vec4 square(in vec4 iparam)\n" 2810 "{\n" 2811 " return iparam * iparam;\n" 2812 "}\n" 2813 "\n" 2814 "// Sub routine uniforms\n" 2815 "subroutine uniform routine_type first_routine;\n" 2816 "subroutine uniform routine_type second_routine;\n" 2817 "\n" 2818 "// Input data\n" 2819 "uniform vec4 input_data;\n" 2820 "\n" 2821 "// Output\n" 2822 "out vec4 out_input_data;\n" 2823 "out vec4 out_result_from_first_routine;\n" 2824 "out vec4 out_result_from_second_routine;\n" 2825 "out vec4 out_result_from_combined_routines;\n" 2826 "out vec4 out_result_from_routines_combined_in_reveresed_order;\n" 2827 "\n" 2828 "void main()\n" 2829 "{\n" 2830 " out_input_data = input_data;\n" 2831 " out_result_from_first_routine = first_routine(input_data);\n" 2832 " out_result_from_second_routine = second_routine(input_data);\n" 2833 " out_result_from_combined_routines = second_routine(first_routine(input_data));\n" 2834 " out_result_from_routines_combined_in_reveresed_order = first_routine(second_routine(input_data));\n" 2835 "}\n" 2836 "\n"; 2837 2838 static const GLchar* varying_names[] = { 2839 "out_input_data", 2840 "out_result_from_first_routine", 2841 "out_result_from_second_routine", 2842 "out_result_from_combined_routines", 2843 "out_result_from_routines_combined_in_reveresed_order", 2844 }; 2845 2846 static const GLchar* subroutine_uniform_names[] = { "first_routine", "second_routine" }; 2847 2848 static const GLchar* subroutine_names[] = { "inverse_order", "negate", "inverse", "square" }; 2849 2850 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]); 2851 static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */; 2852 2853 static const GLuint inverse_order_routine_index = 0; 2854 static const GLuint negate_routine_index = 1; 2855 static const GLuint inverse_routine_index = 2; 2856 static const GLuint square_routine_index = 3; 2857 2858 /* Test data */ 2859 static const Utils::vec4<GLfloat> inverse_order_negate_data[5] = { 2860 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2861 Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), 2862 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), 2863 }; 2864 2865 static const Utils::vec4<GLfloat> inverse_order_inverse_data[5] = { 2866 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2867 Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f), 2868 Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f), 2869 }; 2870 2871 static const Utils::vec4<GLfloat> inverse_order_square_data[5] = { 2872 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2873 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), 2874 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), 2875 }; 2876 2877 static const Utils::vec4<GLfloat> negate_inverse_data[5] = { 2878 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2879 Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f), 2880 Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f), 2881 }; 2882 2883 static const Utils::vec4<GLfloat> negate_square_data[5] = { 2884 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2885 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), 2886 Utils::vec4<GLfloat>(-4.0f, -1.0f, -1.0f, -4.0f), 2887 }; 2888 2889 static const Utils::vec4<GLfloat> inverse_square_data[5] = { 2890 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), 2891 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f), 2892 Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f), 2893 }; 2894 2895 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 2896 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 2897 { 2898 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 2899 } 2900 2901 m_n_active_subroutine_uniforms = 2; 2902 m_n_active_subroutine_uniform_locations = 2; 2903 m_n_active_subroutines = 4; 2904 m_n_active_subroutine_uniform_name_length = 0; 2905 m_n_active_subroutine_name_length = 0; 2906 m_n_active_subroutine_uniform_size = 1; 2907 2908 /* GL objects */ 2909 Utils::program program(m_context); 2910 Utils::buffer transform_feedback_buffer(m_context); 2911 Utils::vertexArray vao(m_context); 2912 2913 bool result = true; 2914 2915 /* Calculate max name lengths for subroutines and subroutine uniforms */ 2916 for (GLint i = 0; i < m_n_active_subroutine_uniforms; ++i) 2917 { 2918 const GLsizei length = (GLsizei)strlen(subroutine_uniform_names[i]); 2919 2920 if (length > m_n_active_subroutine_uniform_name_length) 2921 { 2922 m_n_active_subroutine_uniform_name_length = length; 2923 } 2924 } 2925 2926 for (GLint i = 0; i < m_n_active_subroutines; ++i) 2927 { 2928 const GLsizei length = (GLsizei)strlen(subroutine_names[i]); 2929 2930 if (length > m_n_active_subroutine_name_length) 2931 { 2932 m_n_active_subroutine_name_length = length; 2933 } 2934 } 2935 2936 /* Init */ 2937 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names, 2938 n_varyings); 2939 2940 vao.generate(); 2941 vao.bind(); 2942 2943 transform_feedback_buffer.generate(); 2944 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 2945 GL_DYNAMIC_COPY); 2946 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 2947 2948 program.use(); 2949 2950 /* Inspect Get* API */ 2951 if ((false == inspectProgramStageiv(program.m_program_object_id)) || 2952 (false == inspectActiveSubroutineUniformiv(program.m_program_object_id, subroutine_uniform_names)) || 2953 (false == inspectActiveSubroutineUniformName(program.m_program_object_id, subroutine_uniform_names)) || 2954 (false == inspectActiveSubroutineName(program.m_program_object_id, subroutine_names)) || 2955 (false == 2956 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, false))) 2957 { 2958 result = false; 2959 } 2960 2961 /* Inspect GetProgram* API */ 2962 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query")) 2963 { 2964 if ((false == inspectProgramInterfaceiv(program.m_program_object_id)) || 2965 (false == 2966 inspectProgramResourceiv(program.m_program_object_id, subroutine_names, subroutine_uniform_names)) || 2967 (false == 2968 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, true))) 2969 { 2970 result = false; 2971 } 2972 } 2973 2974 /* Test shader execution */ 2975 if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 2976 subroutine_names[negate_routine_index], subroutine_uniform_names, inverse_order_negate_data, 2977 false)) || 2978 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 2979 subroutine_names[inverse_routine_index], subroutine_uniform_names, 2980 inverse_order_inverse_data, false)) || 2981 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 2982 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_order_square_data, 2983 false)) || 2984 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index], 2985 subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data, 2986 false)) || 2987 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index], 2988 subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data, 2989 false)) || 2990 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index], 2991 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data, 2992 false))) 2993 { 2994 result = false; 2995 } 2996 2997 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query")) 2998 { 2999 if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 3000 subroutine_names[negate_routine_index], subroutine_uniform_names, 3001 inverse_order_negate_data, true)) || 3002 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 3003 subroutine_names[inverse_routine_index], subroutine_uniform_names, 3004 inverse_order_inverse_data, true)) || 3005 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 3006 subroutine_names[square_routine_index], subroutine_uniform_names, 3007 inverse_order_square_data, true)) || 3008 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index], 3009 subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data, 3010 true)) || 3011 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index], 3012 subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data, 3013 true)) || 3014 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index], 3015 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data, 3016 true))) 3017 { 3018 result = false; 3019 } 3020 } 3021 3022 /* Done */ 3023 if (true == result) 3024 { 3025 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3026 } 3027 else 3028 { 3029 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3030 } 3031 3032 return tcu::TestNode::STOP; 3033 } 3034 3035 /** Verify result of getProgramStageiv 3036 * 3037 * @param program_id Program object id 3038 * @param pname <pname> parameter for getProgramStageiv 3039 * @param expected Expected value 3040 * 3041 * @return true if result is equal to expected value, flase otherwise 3042 **/ 3043 bool FunctionalTest3_4::checkProgramStageiv(glw::GLuint program_id, glw::GLenum pname, glw::GLint expected) const 3044 { 3045 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3046 GLint value = 0; 3047 3048 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, pname, &value); 3049 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3050 3051 if (expected != value) 3052 { 3053 m_context.getTestContext().getLog() << tcu::TestLog::Message 3054 << "Error. Invalid result. Function: getProgramStageiv. " 3055 << "pname: " << Utils::pnameToStr(pname) << ". " 3056 << "Result: " << value << ". " 3057 << "Expected: " << expected << "." << tcu::TestLog::EndMessage; 3058 3059 return false; 3060 } 3061 else 3062 { 3063 return true; 3064 } 3065 } 3066 3067 /** Verify result of getProgramResourceiv 3068 * 3069 * @param program_id Program object id 3070 * @param program_interface Program interface 3071 * @param pname <pname> parameter for getProgramStageiv 3072 * @param resource_name Resource name 3073 * @param expected Expected value 3074 * 3075 * @return true if result is equal to expected value, false otherwise 3076 **/ 3077 bool FunctionalTest3_4::checkProgramResourceiv(GLuint program_id, GLenum program_interface, GLenum pname, 3078 const glw::GLchar* resource_name, GLint expected) const 3079 { 3080 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3081 GLuint index = gl.getProgramResourceIndex(program_id, program_interface, resource_name); 3082 GLint value = 0; 3083 3084 if (GL_INVALID_INDEX == index) 3085 { 3086 return false; 3087 } 3088 3089 gl.getProgramResourceiv(program_id, program_interface, index, 1, &pname, 1, 0, &value); 3090 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceiv"); 3091 3092 if (expected != value) 3093 { 3094 m_context.getTestContext().getLog() 3095 << tcu::TestLog::Message << "Error. Invalid result. Function: getProgramResourceiv. " 3096 << "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". " 3097 << "Resource name: " << resource_name << ". " 3098 << "Property: " << Utils::pnameToStr(pname) << ". " 3099 << "Result: " << value << ". " 3100 << "Expected: " << expected << "." << tcu::TestLog::EndMessage; 3101 3102 return false; 3103 } 3104 else 3105 { 3106 return true; 3107 } 3108 } 3109 3110 /** Verify result of getProgramInterfaceiv 3111 * 3112 * @param program_id Program object id 3113 * @param program_interface Program interface 3114 * @param pname <pname> parameter for getProgramStageiv 3115 * @param expected Expected value 3116 * 3117 * @return true if result is equal to expected value, flase otherwise 3118 **/ 3119 bool FunctionalTest3_4::checkProgramInterfaceiv(GLuint program_id, GLenum program_interface, GLenum pname, 3120 GLint expected) const 3121 { 3122 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3123 GLint value = 0; 3124 3125 gl.getProgramInterfaceiv(program_id, program_interface, pname, &value); 3126 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInterfaceiv"); 3127 3128 if (expected != value) 3129 { 3130 m_context.getTestContext().getLog() 3131 << tcu::TestLog::Message << "Error. Invalid result. Function: getProgramInterfaceiv. " 3132 << "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". " 3133 << "pname: " << Utils::pnameToStr(pname) << ". " 3134 << "Result: " << value << ". " 3135 << "Expected: " << expected << "." << tcu::TestLog::EndMessage; 3136 3137 return false; 3138 } 3139 else 3140 { 3141 return true; 3142 } 3143 } 3144 3145 /** Verify result of getActiveSubroutineUniformiv 3146 * 3147 * @param program_id Program object id 3148 * @param index <index> parameter for getActiveSubroutineUniformiv 3149 * @param pname <pname> parameter for getActiveSubroutineUniformiv 3150 * @param expected Expected value 3151 * 3152 * @return true if result is equal to expected value, flase otherwise 3153 **/ 3154 bool FunctionalTest3_4::checkActiveSubroutineUniformiv(GLuint program_id, GLuint index, GLenum pname, 3155 GLint expected) const 3156 { 3157 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3158 GLint value = 0; 3159 3160 gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, index, pname, &value); 3161 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv"); 3162 3163 if (expected != value) 3164 { 3165 m_context.getTestContext().getLog() << tcu::TestLog::Message 3166 << "Error. Invalid result. Function: getActiveSubroutineUniformiv. " 3167 << "idnex: " << index << ". " 3168 << "pname: " << Utils::pnameToStr(pname) << ". " 3169 << "Result: " << value << ". " 3170 << "Expected: " << expected << "." << tcu::TestLog::EndMessage; 3171 3172 return false; 3173 } 3174 else 3175 { 3176 return true; 3177 } 3178 } 3179 3180 /** Returns index of program resource 3181 * 3182 * @param program_id Program object id 3183 * @param program_interface Program interface 3184 * @param resource_name Name of resource 3185 * 3186 * @return Index of specified resource 3187 **/ 3188 GLuint FunctionalTest3_4::getProgramResourceIndex(GLuint program_id, GLenum program_interface, 3189 const glw::GLchar* resource_name) const 3190 { 3191 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3192 GLuint index = gl.getProgramResourceIndex(program_id, program_interface, resource_name); 3193 3194 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceIndex"); 3195 3196 if (GL_INVALID_INDEX == index) 3197 { 3198 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Program resource is not available. " 3199 << "Program interface: " << Utils::programInterfaceToStr(program_interface) 3200 << ". " 3201 << "Resource name: " << resource_name << "." << tcu::TestLog::EndMessage; 3202 } 3203 3204 return index; 3205 } 3206 3207 /** Get subroutine index 3208 * 3209 * @param program_id Program object id 3210 * @param subroutine_name Subroutine name 3211 * @param use_program_query If true getProgramResourceIndex is used, otherwise getSubroutineIndex 3212 * 3213 * @return Index of subroutine 3214 **/ 3215 GLuint FunctionalTest3_4::getSubroutineIndex(GLuint program_id, const glw::GLchar* subroutine_name, 3216 bool use_program_query) const 3217 { 3218 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3219 GLuint index = -1; 3220 3221 if (false == use_program_query) 3222 { 3223 index = gl.getSubroutineIndex(program_id, GL_VERTEX_SHADER, subroutine_name); 3224 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex"); 3225 } 3226 else 3227 { 3228 index = gl.getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE, subroutine_name); 3229 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex"); 3230 } 3231 3232 if (GL_INVALID_INDEX == index) 3233 { 3234 TCU_FAIL("Subroutine is not available"); 3235 } 3236 3237 return index; 3238 } 3239 3240 /** Get subroutine uniform location 3241 * 3242 * @param program_id Program object id 3243 * @param uniform_name Subroutine uniform name 3244 * @param use_program_query If true getProgramResourceLocation is used, otherwise getSubroutineUniformLocation 3245 * 3246 * @return Location of subroutine uniform 3247 **/ 3248 GLint FunctionalTest3_4::getSubroutineUniformLocation(GLuint program_id, const glw::GLchar* uniform_name, 3249 bool use_program_query) const 3250 { 3251 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3252 GLint location = -1; 3253 3254 if (false == use_program_query) 3255 { 3256 location = gl.getSubroutineUniformLocation(program_id, GL_VERTEX_SHADER, uniform_name); 3257 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation"); 3258 } 3259 else 3260 { 3261 location = gl.getProgramResourceLocation(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name); 3262 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceLocation"); 3263 } 3264 3265 if (-1 == location) 3266 { 3267 TCU_FAIL("Subroutine uniform is not available"); 3268 } 3269 3270 return location; 3271 } 3272 3273 /** Test if getProgramStageiv results are as expected 3274 * 3275 * @param program_id Program object id 3276 * 3277 * @result false in case of invalid result for any pname, true otherwise 3278 **/ 3279 bool FunctionalTest3_4::inspectProgramStageiv(glw::GLuint program_id) const 3280 { 3281 bool result = true; 3282 3283 const inspectionDetails details[] = { 3284 { GL_ACTIVE_SUBROUTINE_UNIFORMS, m_n_active_subroutine_uniforms }, 3285 { GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, m_n_active_subroutine_uniform_locations }, 3286 { GL_ACTIVE_SUBROUTINES, m_n_active_subroutines }, 3287 { GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH, m_n_active_subroutine_uniform_name_length + 1 }, 3288 { GL_ACTIVE_SUBROUTINE_MAX_LENGTH, m_n_active_subroutine_name_length + 1 } 3289 }; 3290 const GLuint n_details = sizeof(details) / sizeof(details[0]); 3291 3292 for (GLuint i = 0; i < n_details; ++i) 3293 { 3294 if (false == checkProgramStageiv(program_id, details[i].pname, details[i].expected_value)) 3295 { 3296 result = false; 3297 } 3298 } 3299 3300 return result; 3301 } 3302 3303 /** Test if checkProgramInterfaceiv results are as expected 3304 * 3305 * @param program_id Program object id 3306 * 3307 * @result false in case of invalid result for any pname, true otherwise 3308 **/ 3309 bool FunctionalTest3_4::inspectProgramInterfaceiv(glw::GLuint program_id) const 3310 { 3311 bool result = true; 3312 3313 const inspectionDetailsForProgramInterface details[] = { 3314 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, m_n_active_subroutine_uniforms }, 3315 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, m_n_active_subroutine_uniform_name_length + 1 }, 3316 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines }, 3317 { GL_VERTEX_SUBROUTINE, GL_ACTIVE_RESOURCES, m_n_active_subroutines }, 3318 { GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, m_n_active_subroutine_name_length + 1 } 3319 }; 3320 const GLuint n_details = sizeof(details) / sizeof(details[0]); 3321 3322 for (GLuint i = 0; i < n_details; ++i) 3323 { 3324 if (false == checkProgramInterfaceiv(program_id, details[i].program_interface, details[i].pname, 3325 details[i].expected_value)) 3326 { 3327 result = false; 3328 } 3329 } 3330 3331 return result; 3332 } 3333 3334 /** Test if checkProgramResourceiv results are as expected 3335 * 3336 * @param program_id Program object id 3337 * @param subroutine_names Array of subroutine names 3338 * @param uniform_names Array of uniform names 3339 * 3340 * @result false in case of invalid result for any pname, true otherwise 3341 **/ 3342 bool FunctionalTest3_4::inspectProgramResourceiv(GLuint program_id, const GLchar** subroutine_names, 3343 const GLchar** uniform_names) const 3344 { 3345 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3346 bool result = true; 3347 3348 for (GLint subroutine = 0; subroutine < m_n_active_subroutines; ++subroutine) 3349 { 3350 const GLchar* subroutine_name = subroutine_names[subroutine]; 3351 const GLint length = (GLint)strlen(subroutine_name) + 1; 3352 3353 if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE, GL_NAME_LENGTH, subroutine_name, length)) 3354 { 3355 result = false; 3356 } 3357 } 3358 3359 inspectionDetails details[] = { 3360 { GL_NAME_LENGTH, 0 }, 3361 { GL_ARRAY_SIZE, 1 }, 3362 { GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines }, 3363 { GL_LOCATION, 0 }, 3364 }; 3365 const GLuint n_details = sizeof(details) / sizeof(details[0]); 3366 3367 for (GLint uniform = 0; uniform < m_n_active_subroutine_uniforms; ++uniform) 3368 { 3369 const GLchar* uniform_name = uniform_names[uniform]; 3370 const GLint length = (GLint)strlen(uniform_name) + 1; 3371 const GLint location = getSubroutineUniformLocation(program_id, uniform_name, true); 3372 3373 details[0].expected_value = length; 3374 details[3].expected_value = location; 3375 3376 for (GLuint i = 0; i < n_details; ++i) 3377 { 3378 if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, details[i].pname, 3379 uniform_name, details[i].expected_value)) 3380 { 3381 result = false; 3382 } 3383 } 3384 3385 /* Check compatible subroutines */ 3386 GLuint index = getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name); 3387 3388 if (GL_INVALID_INDEX != index) 3389 { 3390 std::vector<GLint> compatible_subroutines; 3391 GLint index_sum = 0; 3392 GLenum prop = GL_COMPATIBLE_SUBROUTINES; 3393 3394 compatible_subroutines.resize(m_n_active_subroutines); 3395 3396 gl.getProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, index, 1, &prop, m_n_active_subroutines, 3397 0, &compatible_subroutines[0]); 3398 3399 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv"); 3400 3401 /* Expected indices are 0, 1, 2, ... N */ 3402 for (GLint i = 0; i < m_n_active_subroutines; ++i) 3403 { 3404 index_sum += compatible_subroutines[i]; 3405 } 3406 3407 /* Sum of E1, ..., EN = (E1 + EN) * N / 2 */ 3408 if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum) 3409 { 3410 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 3411 3412 message << "Error. Invalid result. Function: getProgramResourceiv. " 3413 << "Program interface: GL_VERTEX_SUBROUTINE_UNIFORM. " 3414 << "Resource name: " << uniform_name << ". " 3415 << "Property: GL_COMPATIBLE_SUBROUTINES. " 3416 << "Results: "; 3417 3418 for (GLint i = 1; i < m_n_active_subroutines; ++i) 3419 { 3420 message << compatible_subroutines[i]; 3421 } 3422 3423 message << tcu::TestLog::EndMessage; 3424 3425 result = false; 3426 } 3427 } 3428 } 3429 3430 return result; 3431 } 3432 3433 /** Test if getActiveSubroutineUniformiv results are as expected 3434 * 3435 * @param program_id Program object id 3436 * @param uniform_names Array of subroutine uniform names available in program 3437 * 3438 * @result false in case of invalid result for any pname, true otherwise 3439 **/ 3440 bool FunctionalTest3_4::inspectActiveSubroutineUniformiv(GLuint program_id, const GLchar** uniform_names) const 3441 { 3442 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3443 bool result = true; 3444 GLint n_active_subroutine_uniforms = 0; 3445 3446 inspectionDetails details[] = { 3447 { GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines }, 3448 { GL_UNIFORM_SIZE, m_n_active_subroutine_uniform_size }, 3449 { GL_UNIFORM_NAME_LENGTH, 0 }, 3450 }; 3451 const GLuint n_details = sizeof(details) / sizeof(details[0]); 3452 3453 /* Get amount of active subroutine uniforms */ 3454 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms); 3455 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3456 3457 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform) 3458 { 3459 GLint name_length = (GLint)strlen(uniform_names[uniform]); 3460 3461 details[2].expected_value = name_length + 1; 3462 3463 /* Checks from "details" */ 3464 for (GLuint i = 0; i < n_details; ++i) 3465 { 3466 if (false == 3467 checkActiveSubroutineUniformiv(program_id, uniform, details[i].pname, details[i].expected_value)) 3468 { 3469 result = false; 3470 } 3471 } 3472 3473 /* Check compatible subroutines */ 3474 std::vector<GLint> compatible_subroutines; 3475 compatible_subroutines.resize(m_n_active_subroutines); 3476 GLint index_sum = 0; 3477 3478 gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, uniform, GL_COMPATIBLE_SUBROUTINES, 3479 &compatible_subroutines[0]); 3480 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv"); 3481 3482 /* Expected indices are 0, 1, 2, ... N */ 3483 for (GLint i = 0; i < m_n_active_subroutines; ++i) 3484 { 3485 index_sum += compatible_subroutines[i]; 3486 } 3487 3488 /* Sum of E1, ..., EN = (E1 + EN) * N / 2 */ 3489 if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum) 3490 { 3491 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 3492 3493 message << "Error. Invalid result. Function: getActiveSubroutineUniformiv. idnex: " << uniform 3494 << ". pname: " << Utils::pnameToStr(GL_COMPATIBLE_SUBROUTINES) << ". Results: "; 3495 3496 for (GLint i = 1; i < m_n_active_subroutines; ++i) 3497 { 3498 message << compatible_subroutines[i]; 3499 } 3500 3501 message << tcu::TestLog::EndMessage; 3502 3503 result = false; 3504 } 3505 } 3506 3507 return result; 3508 } 3509 3510 /** Test if getActiveSubroutineUniformName results are as expected 3511 * 3512 * @param program_id Program object id 3513 * @param uniform_names Array of subroutine uniform names available in program 3514 * 3515 * @result false in case of invalid result, true otherwise 3516 **/ 3517 bool FunctionalTest3_4::inspectActiveSubroutineUniformName(GLuint program_id, const GLchar** uniform_names) const 3518 { 3519 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3520 bool result = true; 3521 GLint n_active_subroutine_uniforms = 0; 3522 std::vector<GLchar> active_uniform_name; 3523 3524 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms); 3525 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3526 3527 active_uniform_name.resize(m_n_active_subroutine_uniform_name_length + 1); 3528 3529 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform) 3530 { 3531 bool is_name_ok = false; 3532 3533 gl.getActiveSubroutineUniformName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_uniform_name.size(), 3534 0 /* length */, &active_uniform_name[0]); 3535 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveSubroutineUniformName"); 3536 3537 for (GLint name = 0; name < n_active_subroutine_uniforms; ++name) 3538 { 3539 if (0 == strcmp(uniform_names[name], &active_uniform_name[0])) 3540 { 3541 is_name_ok = true; 3542 break; 3543 } 3544 } 3545 3546 if (false == is_name_ok) 3547 { 3548 m_context.getTestContext().getLog() 3549 << tcu::TestLog::Message 3550 << "Error. Invalid result. Function: getActiveSubroutineUniformName. idnex: " << uniform 3551 << ". Result: " << &active_uniform_name[0] << tcu::TestLog::EndMessage; 3552 3553 result = false; 3554 break; 3555 } 3556 } 3557 3558 return result; 3559 } 3560 3561 /** Test if getActiveSubroutineUniformName results are as expected 3562 * 3563 * @param program_id Program object id 3564 * @param subroutine_names Array of subroutine names available in program 3565 * 3566 * @result false in case of invalid result, true otherwise 3567 **/ 3568 bool FunctionalTest3_4::inspectActiveSubroutineName(GLuint program_id, const GLchar** subroutine_names) const 3569 { 3570 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3571 bool result = true; 3572 GLint n_active_subroutines = 0; 3573 std::vector<GLchar> active_subroutine_name; 3574 3575 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines); 3576 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3577 3578 active_subroutine_name.resize(m_n_active_subroutine_name_length + 1); 3579 3580 for (GLint uniform = 0; uniform < n_active_subroutines; ++uniform) 3581 { 3582 bool is_name_ok = false; 3583 3584 gl.getActiveSubroutineName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_subroutine_name.size(), 3585 0 /* length */, &active_subroutine_name[0]); 3586 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineName"); 3587 3588 for (GLint name = 0; name < n_active_subroutines; ++name) 3589 { 3590 if (0 == strcmp(subroutine_names[name], &active_subroutine_name[0])) 3591 { 3592 is_name_ok = true; 3593 break; 3594 } 3595 } 3596 3597 if (false == is_name_ok) 3598 { 3599 m_context.getTestContext().getLog() 3600 << tcu::TestLog::Message 3601 << "Error. Invalid result. Function: getActiveSubroutineName. idnex: " << uniform 3602 << ". Result: " << &active_subroutine_name[0] << tcu::TestLog::EndMessage; 3603 3604 result = false; 3605 break; 3606 } 3607 } 3608 3609 return result; 3610 } 3611 3612 /** Test if it is possible to "bind" all subroutines uniforms with all subroutines 3613 * 3614 * @param program_id Program object id 3615 * @param subroutine_names Array of subroutine names available in program 3616 * @param uniform_names Array of subroutine uniform names available in program 3617 * 3618 * @result false in case of invalid result, true otherwise 3619 **/ 3620 bool FunctionalTest3_4::inspectSubroutineBinding(GLuint program_id, const GLchar** subroutine_names, 3621 const GLchar** uniform_names, bool use_program_query) const 3622 { 3623 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3624 bool result = true; 3625 GLint n_active_subroutines = 0; 3626 GLint n_active_subroutine_uniforms = 0; 3627 std::vector<GLuint> subroutine_uniforms; 3628 GLuint queried_subroutine_index = 0; 3629 3630 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines); 3631 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3632 3633 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms); 3634 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3635 3636 subroutine_uniforms.resize(n_active_subroutine_uniforms); 3637 3638 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform) 3639 { 3640 GLuint uniform_location = getSubroutineUniformLocation(program_id, uniform_names[uniform], use_program_query); 3641 3642 for (GLint routine = 0; routine < n_active_subroutines; ++routine) 3643 { 3644 GLuint routine_index = getSubroutineIndex(program_id, subroutine_names[routine], use_program_query); 3645 3646 subroutine_uniforms[uniform] = routine_index; 3647 3648 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_active_subroutine_uniforms, &subroutine_uniforms[0]); 3649 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 3650 3651 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, uniform_location, &queried_subroutine_index); 3652 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv"); 3653 3654 if (queried_subroutine_index != routine_index) 3655 { 3656 m_context.getTestContext().getLog() 3657 << tcu::TestLog::Message << "Error. Invalid result. Function: gl.getUniformSubroutineuiv." 3658 << " Subroutine uniform: " << uniform << ", name: " << uniform_names[uniform] 3659 << ", location: " << uniform_location << ". Subroutine: " << routine 3660 << ", name: " << subroutine_names[routine] << ", index: " << routine_index 3661 << ". Result: " << queried_subroutine_index << tcu::TestLog::EndMessage; 3662 3663 result = false; 3664 } 3665 } 3666 } 3667 3668 return result; 3669 } 3670 3671 /** Execute draw call and verify results 3672 * 3673 * @param program_id Program object id 3674 * @param first_routine_name Name of subroutine that shall be used aas first_routine 3675 * @param second_routine_name Name of subroutine that shall be used aas second_routine 3676 * @param uniform_names Name of uniforms 3677 * @param expected_results Test data. [0] is used as input data. All are used as expected_results 3678 * @param use_program_query If true GetProgram* API will be used 3679 * 3680 * @return false in case of invalid result, true otherwise 3681 **/ 3682 bool FunctionalTest3_4::testDraw(GLuint program_id, const GLchar* first_routine_name, const GLchar* second_routine_name, 3683 const GLchar** uniform_names, const Utils::vec4<GLfloat> expected_results[5], 3684 bool use_program_query) const 3685 { 3686 static const GLuint n_varyings = 5; 3687 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3688 bool result = true; 3689 GLuint subroutine_uniforms[2] = { 0 }; 3690 3691 /* Get subroutine uniform locations */ 3692 GLint first_routine_location = getSubroutineUniformLocation(program_id, uniform_names[0], use_program_query); 3693 3694 GLint second_routine_location = getSubroutineUniformLocation(program_id, uniform_names[1], use_program_query); 3695 3696 /* Get subroutine indices */ 3697 GLuint first_routine_index = getSubroutineIndex(program_id, first_routine_name, use_program_query); 3698 3699 GLuint second_routine_index = getSubroutineIndex(program_id, second_routine_name, use_program_query); 3700 3701 /* Map uniforms with subroutines */ 3702 subroutine_uniforms[first_routine_location] = first_routine_index; 3703 subroutine_uniforms[second_routine_location] = second_routine_index; 3704 3705 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 2 /* number of uniforms */, &subroutine_uniforms[0]); 3706 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 3707 3708 /* Get location of input_data */ 3709 GLint input_data_location = gl.getUniformLocation(program_id, "input_data"); 3710 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation"); 3711 3712 if (-1 == input_data_location) 3713 { 3714 TCU_FAIL("Uniform is not available"); 3715 } 3716 3717 /* Set up input_data */ 3718 gl.uniform4f(input_data_location, expected_results[0].m_x, expected_results[0].m_y, expected_results[0].m_z, 3719 expected_results[0].m_w); 3720 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 3721 3722 /* Execute draw call with transform feedback */ 3723 gl.beginTransformFeedback(GL_POINTS); 3724 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 3725 3726 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 3727 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 3728 3729 gl.endTransformFeedback(); 3730 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 3731 3732 /* Verify results */ 3733 GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 3734 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 3735 3736 Utils::vec4<GLfloat> results[5]; 3737 3738 results[0].m_x = feedback_data[0]; 3739 results[0].m_y = feedback_data[1]; 3740 results[0].m_z = feedback_data[2]; 3741 results[0].m_w = feedback_data[3]; 3742 3743 results[1].m_x = feedback_data[4]; 3744 results[1].m_y = feedback_data[5]; 3745 results[1].m_z = feedback_data[6]; 3746 results[1].m_w = feedback_data[7]; 3747 3748 results[2].m_x = feedback_data[8]; 3749 results[2].m_y = feedback_data[9]; 3750 results[2].m_z = feedback_data[10]; 3751 results[2].m_w = feedback_data[11]; 3752 3753 results[3].m_x = feedback_data[12]; 3754 results[3].m_y = feedback_data[13]; 3755 results[3].m_z = feedback_data[14]; 3756 results[3].m_w = feedback_data[15]; 3757 3758 results[4].m_x = feedback_data[16]; 3759 results[4].m_y = feedback_data[17]; 3760 results[4].m_z = feedback_data[18]; 3761 results[4].m_w = feedback_data[19]; 3762 3763 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3764 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 3765 3766 for (GLuint i = 0; i < n_varyings; ++i) 3767 { 3768 result = result && (results[i] == expected_results[i]); 3769 } 3770 3771 if (false == result) 3772 { 3773 m_context.getTestContext().getLog() << tcu::TestLog::Message 3774 << "Error. Invalid result. First routine: " << first_routine_name 3775 << ". Second routine: " << second_routine_name << tcu::TestLog::EndMessage; 3776 3777 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 3778 3779 message << "Results:"; 3780 3781 for (GLuint i = 0; i < n_varyings; ++i) 3782 { 3783 results[i].log(message); 3784 } 3785 3786 message << tcu::TestLog::EndMessage; 3787 3788 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 3789 3790 message << "Expected:"; 3791 3792 for (GLuint i = 0; i < n_varyings; ++i) 3793 { 3794 expected_results[i].log(message); 3795 } 3796 3797 message << tcu::TestLog::EndMessage; 3798 } 3799 3800 return result; 3801 } 3802 3803 /** Constructor 3804 * 3805 * @param context CTS context 3806 **/ 3807 FunctionalTest5::FunctionalTest5(deqp::Context& context) 3808 : TestCase(context, "eight_subroutines_four_uniforms", "Verify multiple subroutine sets") 3809 { 3810 } 3811 3812 /** Execute test 3813 * 3814 * @return tcu::TestNode::STOP 3815 **/ 3816 tcu::TestNode::IterateResult FunctionalTest5::iterate() 3817 { 3818 static const GLchar* vertex_shader_code = 3819 "#version 400 core\n" 3820 "#extension GL_ARB_shader_subroutine : require\n" 3821 "\n" 3822 "precision highp float;\n" 3823 "\n" 3824 "// Subroutine types\n" 3825 "subroutine vec4 routine_type_1(in vec4 left, in vec4 right);\n" 3826 "subroutine vec4 routine_type_2(in vec4 iparam);\n" 3827 "subroutine vec4 routine_type_3(in vec4 a, in vec4 b, in vec4 c);\n" 3828 "subroutine bvec4 routine_type_4(in vec4 left, in vec4 right);\n" 3829 "\n" 3830 "// Subroutine definitions\n" 3831 "// 1st type\n" 3832 "subroutine(routine_type_1) vec4 add(in vec4 left, in vec4 right)\n" 3833 "{\n" 3834 " return left + right;\n" 3835 "}\n" 3836 "\n" 3837 "subroutine(routine_type_1) vec4 subtract(in vec4 left, in vec4 right)\n" 3838 "{\n" 3839 " return left - right;\n" 3840 "}\n" 3841 "\n" 3842 "// 2nd type\n" 3843 "subroutine(routine_type_2) vec4 square(in vec4 iparam)\n" 3844 "{\n" 3845 " return iparam * iparam;\n" 3846 "}\n" 3847 "\n" 3848 "subroutine(routine_type_2) vec4 square_root(in vec4 iparam)\n" 3849 "{\n" 3850 " return sqrt(iparam);\n" 3851 "}\n" 3852 "\n" 3853 "// 3rd type\n" 3854 "subroutine(routine_type_3) vec4 do_fma(in vec4 a, in vec4 b, in vec4 c)\n" 3855 "{\n" 3856 " return fma(a, b, c);\n" 3857 "}\n" 3858 "\n" 3859 "subroutine(routine_type_3) vec4 blend(in vec4 a, in vec4 b, in vec4 c)\n" 3860 "{\n" 3861 " return c * a + (vec4(1) - c) * b;\n" 3862 "}\n" 3863 "\n" 3864 "// 4th type\n" 3865 "subroutine(routine_type_4) bvec4 are_equal(in vec4 left, in vec4 right)\n" 3866 "{\n" 3867 " return equal(left, right);\n" 3868 "}\n" 3869 "\n" 3870 "subroutine(routine_type_4) bvec4 are_greater(in vec4 left, in vec4 right)\n" 3871 "{\n" 3872 " return greaterThan(left, right);\n" 3873 "}\n" 3874 "\n" 3875 "// Sub routine uniforms\n" 3876 "subroutine uniform routine_type_1 first_routine;\n" 3877 "subroutine uniform routine_type_2 second_routine;\n" 3878 "subroutine uniform routine_type_3 third_routine;\n" 3879 "subroutine uniform routine_type_4 fourth_routine;\n" 3880 "\n" 3881 "// Input data\n" 3882 "uniform vec4 first_input;\n" 3883 "uniform vec4 second_input;\n" 3884 "uniform vec4 third_input;\n" 3885 "\n" 3886 "// Output\n" 3887 "out vec4 out_result_from_first_routine;\n" 3888 "out vec4 out_result_from_second_routine;\n" 3889 "out vec4 out_result_from_third_routine;\n" 3890 "out uvec4 out_result_from_fourth_routine;\n" 3891 "\n" 3892 "void main()\n" 3893 "{\n" 3894 " out_result_from_first_routine = first_routine (first_input, second_input);\n" 3895 " out_result_from_second_routine = second_routine(first_input);\n" 3896 " out_result_from_third_routine = third_routine (first_input, second_input, third_input);\n" 3897 " out_result_from_fourth_routine = uvec4(fourth_routine(first_input, second_input));\n" 3898 "}\n" 3899 "\n"; 3900 3901 static const GLchar* subroutine_names[4][2] = { 3902 { "add", "subtract" }, { "square", "square_root" }, { "do_fma", "blend" }, { "are_equal", "are_greater" } 3903 }; 3904 3905 static const GLchar* subroutine_uniform_names[4][1] = { 3906 { "first_routine" }, { "second_routine" }, { "third_routine" }, { "fourth_routine" } 3907 }; 3908 3909 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 3910 static const GLuint n_subroutines_per_type = sizeof(subroutine_names[0]) / sizeof(subroutine_names[0][0]); 3911 static const GLuint n_subroutine_uniforms_per_type = 3912 sizeof(subroutine_uniform_names[0]) / sizeof(subroutine_uniform_names[0][0]); 3913 3914 static const GLchar* uniform_names[] = { "first_input", "second_input", "third_input" }; 3915 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]); 3916 3917 static const GLchar* varying_names[] = { "out_result_from_first_routine", "out_result_from_second_routine", 3918 "out_result_from_third_routine", "out_result_from_fourth_routine" }; 3919 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]); 3920 static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */; 3921 3922 /* Test data */ 3923 static const Utils::vec4<GLfloat> input_data[3] = { Utils::vec4<GLfloat>(1.0f, 4.0f, 9.0f, 16.0f), 3924 Utils::vec4<GLfloat>(16.0f, 9.0f, 4.0f, 1.0f), 3925 Utils::vec4<GLfloat>(0.25f, 0.5f, 0.75f, 1.0f) }; 3926 3927 static const Utils::vec4<GLfloat> expected_result_from_first_routine[2] = { 3928 Utils::vec4<GLfloat>(17.0f, 13.0f, 13.0f, 17.0f), Utils::vec4<GLfloat>(-15.0f, -5.0f, 5.0f, 15.0f) 3929 }; 3930 3931 static const Utils::vec4<GLfloat> expected_result_from_second_routine[2] = { 3932 Utils::vec4<GLfloat>(1.0f, 16.0f, 81.0f, 256.0f), Utils::vec4<GLfloat>(1.0f, 2.0f, 3.0f, 4.0f) 3933 }; 3934 3935 static const Utils::vec4<GLfloat> expected_result_from_third_routine[2] = { 3936 Utils::vec4<GLfloat>(16.25f, 36.5f, 36.75f, 17.0f), Utils::vec4<GLfloat>(12.25f, 6.5f, 7.75f, 16.0f) 3937 }; 3938 3939 static const Utils::vec4<GLuint> expected_result_from_fourth_routine[2] = { Utils::vec4<GLuint>(0, 0, 0, 0), 3940 Utils::vec4<GLuint>(0, 0, 1, 1) }; 3941 3942 /* All combinations of subroutines */ 3943 static const GLuint subroutine_combinations[][4] = { 3944 { 0, 0, 0, 0 }, { 0, 0, 0, 1 }, { 0, 0, 1, 0 }, { 0, 0, 1, 1 }, { 0, 1, 0, 0 }, { 0, 1, 0, 1 }, 3945 { 0, 1, 1, 0 }, { 0, 1, 1, 1 }, { 1, 0, 0, 0 }, { 1, 0, 0, 1 }, { 1, 0, 1, 0 }, { 1, 0, 1, 1 }, 3946 { 1, 1, 0, 0 }, { 1, 1, 0, 1 }, { 1, 1, 1, 0 }, { 1, 1, 1, 1 } 3947 }; 3948 static const GLuint n_subroutine_combinations = 3949 sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]); 3950 3951 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 3952 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 3953 { 3954 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 3955 } 3956 3957 /* Result */ 3958 bool result = true; 3959 3960 /* GL objects */ 3961 Utils::program program(m_context); 3962 Utils::buffer transform_feedback_buffer(m_context); 3963 Utils::vertexArray vao(m_context); 3964 3965 /* Init GL objects */ 3966 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names, 3967 n_varyings); 3968 3969 program.use(); 3970 3971 vao.generate(); 3972 vao.bind(); 3973 3974 transform_feedback_buffer.generate(); 3975 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 3976 GL_DYNAMIC_COPY); 3977 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 3978 3979 /* Get subroutine uniform locations and subroutine indices */ 3980 for (GLuint type = 0; type < n_subroutine_types; ++type) 3981 { 3982 for (GLuint uniform = 0; uniform < n_subroutine_uniforms_per_type; ++uniform) 3983 { 3984 m_subroutine_uniform_locations[type][uniform] = 3985 program.getSubroutineUniformLocation(subroutine_uniform_names[type][uniform], GL_VERTEX_SHADER); 3986 } 3987 3988 for (GLuint routine = 0; routine < n_subroutines_per_type; ++routine) 3989 { 3990 m_subroutine_indices[type][routine] = 3991 program.getSubroutineIndex(subroutine_names[type][routine], GL_VERTEX_SHADER); 3992 } 3993 } 3994 3995 /* Get uniform locations */ 3996 for (GLuint i = 0; i < n_uniform_names; ++i) 3997 { 3998 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]); 3999 } 4000 4001 /* Draw with each routine combination */ 4002 for (GLuint i = 0; i < n_subroutine_combinations; ++i) 4003 { 4004 Utils::vec4<GLfloat> first_routine_result; 4005 Utils::vec4<GLfloat> second_routine_result; 4006 Utils::vec4<GLfloat> third_routine_result; 4007 Utils::vec4<GLuint> fourth_routine_result; 4008 4009 testDraw(subroutine_combinations[i], input_data, first_routine_result, second_routine_result, 4010 third_routine_result, fourth_routine_result); 4011 4012 if (false == verify(first_routine_result, second_routine_result, third_routine_result, fourth_routine_result, 4013 expected_result_from_first_routine[subroutine_combinations[i][0]], 4014 expected_result_from_second_routine[subroutine_combinations[i][1]], 4015 expected_result_from_third_routine[subroutine_combinations[i][2]], 4016 expected_result_from_fourth_routine[subroutine_combinations[i][3]])) 4017 { 4018 logError(subroutine_names, subroutine_combinations[i], input_data, first_routine_result, 4019 second_routine_result, third_routine_result, fourth_routine_result, 4020 expected_result_from_first_routine[subroutine_combinations[i][0]], 4021 expected_result_from_second_routine[subroutine_combinations[i][1]], 4022 expected_result_from_third_routine[subroutine_combinations[i][2]], 4023 expected_result_from_fourth_routine[subroutine_combinations[i][3]]); 4024 4025 result = false; 4026 } 4027 } 4028 4029 /* Done */ 4030 if (true == result) 4031 { 4032 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4033 } 4034 else 4035 { 4036 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4037 } 4038 4039 return tcu::TestNode::STOP; 4040 } 4041 4042 /** Log error message 4043 * 4044 * @param subroutine_names Array of subroutine names 4045 * @param subroutine_combination Combination of subroutines 4046 * @param input_data Input data 4047 * @param first_routine_result Result of first routine 4048 * @param second_routine_result Result of second routine 4049 * @param third_routine_result Result of third routine 4050 * @param fourth_routine_result Result of fourth routine 4051 * @param first_routine_expected_result Expected result of first routine 4052 * @param second_routine_expected_result Expected result of second routine 4053 * @param third_routine_expected_result Expected result of third routine 4054 * @param fourth_routine_expected_result Expected result of fourth routine 4055 **/ 4056 void FunctionalTest5::logError(const glw::GLchar* subroutine_names[4][2], const glw::GLuint subroutine_combination[4], 4057 const Utils::vec4<glw::GLfloat> input_data[3], 4058 const Utils::vec4<glw::GLfloat>& first_routine_result, 4059 const Utils::vec4<glw::GLfloat>& second_routine_result, 4060 const Utils::vec4<glw::GLfloat>& third_routine_result, 4061 const Utils::vec4<glw::GLuint>& fourth_routine_result, 4062 const Utils::vec4<glw::GLfloat>& first_routine_expected_result, 4063 const Utils::vec4<glw::GLfloat>& second_routine_expected_result, 4064 const Utils::vec4<glw::GLfloat>& third_routine_expected_result, 4065 const Utils::vec4<glw::GLuint>& fourth_routine_expected_result) const 4066 { 4067 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 4068 << tcu::TestLog::EndMessage; 4069 4070 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4071 4072 message << "Function: " << subroutine_names[0][subroutine_combination[0]] << "( "; 4073 input_data[0].log(message); 4074 message << ", "; 4075 input_data[1].log(message); 4076 message << " ). Result: "; 4077 first_routine_result.log(message); 4078 message << ". Expected: "; 4079 first_routine_expected_result.log(message); 4080 4081 message << tcu::TestLog::EndMessage; 4082 4083 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4084 4085 message << "Function: " << subroutine_names[1][subroutine_combination[1]] << "( "; 4086 input_data[0].log(message); 4087 message << " ). Result: "; 4088 second_routine_result.log(message); 4089 message << ". Expected: "; 4090 second_routine_expected_result.log(message); 4091 4092 message << tcu::TestLog::EndMessage; 4093 4094 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4095 4096 message << "Function: " << subroutine_names[2][subroutine_combination[2]] << "( "; 4097 input_data[0].log(message); 4098 message << ", "; 4099 input_data[1].log(message); 4100 message << ", "; 4101 input_data[2].log(message); 4102 message << "). Result: "; 4103 third_routine_result.log(message); 4104 message << ". Expected: "; 4105 third_routine_expected_result.log(message); 4106 4107 message << tcu::TestLog::EndMessage; 4108 4109 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4110 4111 message << "Function: " << subroutine_names[3][subroutine_combination[3]] << "( "; 4112 input_data[0].log(message); 4113 message << ", "; 4114 input_data[1].log(message); 4115 message << ", "; 4116 message << " ). Result: "; 4117 fourth_routine_result.log(message); 4118 message << ". Expected: "; 4119 fourth_routine_expected_result.log(message); 4120 4121 message << tcu::TestLog::EndMessage; 4122 } 4123 4124 /** Execute draw call and capture results 4125 * 4126 * @param subroutine_combination Combination of subroutines 4127 * @param input_data Input data 4128 * @param out_first_routine_result Result of first routine 4129 * @param out_second_routine_result Result of second routine 4130 * @param out_third_routine_result Result of third routine 4131 * @param out_fourth_routine_result Result of fourth routine 4132 **/ 4133 void FunctionalTest5::testDraw(const glw::GLuint subroutine_combination[4], 4134 const Utils::vec4<glw::GLfloat> input_data[3], 4135 Utils::vec4<glw::GLfloat>& out_first_routine_result, 4136 Utils::vec4<glw::GLfloat>& out_second_routine_result, 4137 Utils::vec4<glw::GLfloat>& out_third_routine_result, 4138 Utils::vec4<glw::GLuint>& out_fourth_routine_result) const 4139 { 4140 static const GLuint n_uniforms = sizeof(m_uniform_locations) / sizeof(m_uniform_locations[0]); 4141 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4142 GLuint subroutine_indices[4]; 4143 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 4144 4145 /* Prepare subroutine uniform data */ 4146 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 4147 { 4148 const GLuint location = m_subroutine_uniform_locations[i][0]; 4149 4150 subroutine_indices[location] = m_subroutine_indices[i][subroutine_combination[i]]; 4151 } 4152 4153 /* Set up subroutine uniforms */ 4154 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]); 4155 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 4156 4157 /* Set up input data uniforms */ 4158 for (GLuint i = 0; i < n_uniforms; ++i) 4159 { 4160 gl.uniform4f(m_uniform_locations[i], input_data[i].m_x, input_data[i].m_y, input_data[i].m_z, 4161 input_data[i].m_w); 4162 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 4163 } 4164 4165 /* Execute draw call with transform feedback */ 4166 gl.beginTransformFeedback(GL_POINTS); 4167 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 4168 4169 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 4170 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 4171 4172 gl.endTransformFeedback(); 4173 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 4174 4175 /* Capture results */ 4176 GLvoid* feedback_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 4177 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4178 4179 GLfloat* float_ptr = (GLfloat*)feedback_data; 4180 4181 /* First result */ 4182 out_first_routine_result.m_x = float_ptr[0]; 4183 out_first_routine_result.m_y = float_ptr[1]; 4184 out_first_routine_result.m_z = float_ptr[2]; 4185 out_first_routine_result.m_w = float_ptr[3]; 4186 4187 /* Second result */ 4188 out_second_routine_result.m_x = float_ptr[4]; 4189 out_second_routine_result.m_y = float_ptr[5]; 4190 out_second_routine_result.m_z = float_ptr[6]; 4191 out_second_routine_result.m_w = float_ptr[7]; 4192 4193 /* Third result */ 4194 out_third_routine_result.m_x = float_ptr[8]; 4195 out_third_routine_result.m_y = float_ptr[9]; 4196 out_third_routine_result.m_z = float_ptr[10]; 4197 out_third_routine_result.m_w = float_ptr[11]; 4198 4199 /* Fourth result */ 4200 GLuint* uint_ptr = (GLuint*)(float_ptr + 12); 4201 out_fourth_routine_result.m_x = uint_ptr[0]; 4202 out_fourth_routine_result.m_y = uint_ptr[1]; 4203 out_fourth_routine_result.m_z = uint_ptr[2]; 4204 out_fourth_routine_result.m_w = uint_ptr[3]; 4205 4206 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4207 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 4208 } 4209 4210 /** Verify if results match expected results 4211 * 4212 * @param first_routine_result Result of first routine 4213 * @param second_routine_result Result of second routine 4214 * @param third_routine_result Result of third routine 4215 * @param fourth_routine_result Result of fourth routine 4216 * @param first_routine_expected_result Expected result of first routine 4217 * @param second_routine_expected_result Expected result of second routine 4218 * @param third_routine_expected_result Expected result of third routine 4219 * @param fourth_routine_expected_result Expected result of fourth routine 4220 **/ 4221 bool FunctionalTest5::verify(const Utils::vec4<glw::GLfloat>& first_routine_result, 4222 const Utils::vec4<glw::GLfloat>& second_routine_result, 4223 const Utils::vec4<glw::GLfloat>& third_routine_result, 4224 const Utils::vec4<glw::GLuint>& fourth_routine_result, 4225 const Utils::vec4<glw::GLfloat>& first_routine_expected_result, 4226 const Utils::vec4<glw::GLfloat>& second_routine_expected_result, 4227 const Utils::vec4<glw::GLfloat>& third_routine_expected_result, 4228 const Utils::vec4<glw::GLuint>& fourth_routine_expected_result) const 4229 { 4230 bool result = true; 4231 4232 result = result && (first_routine_result == first_routine_expected_result); 4233 result = result && (second_routine_result == second_routine_expected_result); 4234 result = result && (third_routine_result == third_routine_expected_result); 4235 result = result && (fourth_routine_result == fourth_routine_expected_result); 4236 4237 return result; 4238 } 4239 4240 /** Constructor 4241 * 4242 * @param context CTS context 4243 **/ 4244 FunctionalTest6::FunctionalTest6(deqp::Context& context) 4245 : TestCase(context, "static_subroutine_call", "Verify that subroutine can be called in a static manner") 4246 { 4247 } 4248 4249 /** Execute test 4250 * 4251 * @return tcu::TestNode::STOP 4252 **/ 4253 tcu::TestNode::IterateResult FunctionalTest6::iterate() 4254 { 4255 static const GLchar* vertex_shader_code = "#version 400 core\n" 4256 "#extension GL_ARB_shader_subroutine : require\n" 4257 "\n" 4258 "precision highp float;\n" 4259 "\n" 4260 "// Subroutine type\n" 4261 "subroutine vec4 routine_type(in vec4 iparam);\n" 4262 "\n" 4263 "// Subroutine definition\n" 4264 "subroutine(routine_type) vec4 square(in vec4 iparam)\n" 4265 "{\n" 4266 " return iparam * iparam;\n" 4267 "}\n" 4268 "\n" 4269 "// Sub routine uniform\n" 4270 "subroutine uniform routine_type routine;\n" 4271 "\n" 4272 "// Input data\n" 4273 "uniform vec4 input_data;\n" 4274 "\n" 4275 "// Output\n" 4276 "out vec4 out_result;\n" 4277 "\n" 4278 "void main()\n" 4279 "{\n" 4280 " out_result = square(input_data);\n" 4281 "}\n" 4282 "\n"; 4283 4284 static const GLchar* varying_name = "out_result"; 4285 4286 /* Test data */ 4287 static const Utils::vec4<GLfloat> input_data(1.0f, 4.0f, 9.0f, 16.0f); 4288 4289 static const Utils::vec4<GLfloat> expected_result(1.0f, 16.0f, 81.0f, 256.0f); 4290 4291 static const GLuint transform_feedback_buffer_size = 4 * sizeof(GLfloat); 4292 4293 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 4294 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 4295 { 4296 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 4297 } 4298 4299 /* GL objects */ 4300 Utils::program program(m_context); 4301 Utils::buffer transform_feedback_buffer(m_context); 4302 Utils::vertexArray vao(m_context); 4303 4304 /* Init GL objects */ 4305 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name, 4306 1 /* n_varyings */); 4307 4308 program.use(); 4309 4310 vao.generate(); 4311 vao.bind(); 4312 4313 transform_feedback_buffer.generate(); 4314 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 4315 GL_DYNAMIC_COPY); 4316 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 4317 4318 /* Test */ 4319 { 4320 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4321 const GLint uniform_location = gl.getUniformLocation(program.m_program_object_id, "input_data"); 4322 4323 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation"); 4324 4325 if (-1 == uniform_location) 4326 { 4327 TCU_FAIL("Uniform is not available"); 4328 } 4329 4330 /* Set up input data uniforms */ 4331 gl.uniform4f(uniform_location, input_data.m_x, input_data.m_y, input_data.m_z, input_data.m_w); 4332 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 4333 4334 /* Execute draw call with transform feedback */ 4335 gl.beginTransformFeedback(GL_POINTS); 4336 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 4337 4338 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 4339 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 4340 4341 gl.endTransformFeedback(); 4342 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 4343 4344 /* Capture results */ 4345 GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 4346 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4347 4348 Utils::vec4<GLfloat> result(feedback_data[0], feedback_data[1], feedback_data[2], feedback_data[3]); 4349 4350 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4351 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 4352 4353 /* Verify */ 4354 if (expected_result == result) 4355 { 4356 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4357 } 4358 else 4359 { 4360 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 4361 << tcu::TestLog::EndMessage; 4362 4363 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4364 4365 message << "Function: square( "; 4366 input_data.log(message); 4367 message << " ). Result: "; 4368 result.log(message); 4369 message << ". Expected: "; 4370 expected_result.log(message); 4371 4372 message << tcu::TestLog::EndMessage; 4373 4374 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4375 } 4376 } 4377 4378 /* Done */ 4379 return tcu::TestNode::STOP; 4380 } 4381 4382 /** Constructor 4383 * 4384 * @param context CTS context 4385 **/ 4386 FunctionalTest7_8::FunctionalTest7_8(deqp::Context& context) 4387 : TestCase(context, "arrayed_subroutine_uniforms", "Verify that subroutine can be called in a static manner") 4388 { 4389 } 4390 4391 /** Execute test 4392 * 4393 * @return tcu::TestNode::STOP 4394 **/ 4395 tcu::TestNode::IterateResult FunctionalTest7_8::iterate() 4396 { 4397 static const GLchar* vertex_shader_code = 4398 "#version 400 core\n" 4399 "#extension GL_ARB_shader_subroutine : require\n" 4400 "\n" 4401 "precision highp float;\n" 4402 "\n" 4403 "// Subroutine type\n" 4404 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n" 4405 "\n" 4406 "// Subroutine definitions\n" 4407 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n" 4408 "{\n" 4409 " return left + right;\n" 4410 "}\n" 4411 "\n" 4412 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n" 4413 "{\n" 4414 " return left * right;\n" 4415 "}\n" 4416 "\n" 4417 "// Sub routine uniform\n" 4418 "subroutine uniform routine_type routine[4];\n" 4419 "\n" 4420 "// Input data\n" 4421 "uniform vec4 uni_left;\n" 4422 "uniform vec4 uni_right;\n" 4423 "uniform uvec4 uni_indices;\n" 4424 "\n" 4425 "// Output\n" 4426 "out vec4 out_combined;\n" 4427 "out vec4 out_combined_inverted;\n" 4428 "out vec4 out_constant;\n" 4429 "out vec4 out_constant_inverted;\n" 4430 "out vec4 out_dynamic;\n" 4431 "out vec4 out_dynamic_inverted;\n" 4432 "out vec4 out_loop;\n" 4433 "out uint out_array_length;\n" 4434 "\n" 4435 "void main()\n" 4436 "{\n" 4437 " out_combined = routine[3](routine[2](routine[1](routine[0](uni_left, uni_right), uni_right), " 4438 "uni_right), uni_right);\n" 4439 " out_combined_inverted = routine[0](routine[1](routine[2](routine[3](uni_left, uni_right), uni_right), " 4440 "uni_right), uni_right);\n" 4441 " \n" 4442 " out_constant = routine[3](routine[2](routine[1](routine[0](vec4(1, 2, 3, 4), vec4(-5, -6, -7, " 4443 "-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n" 4444 " out_constant_inverted = routine[0](routine[1](routine[2](routine[3](vec4(1, 2, 3, 4), vec4(-5, -6, -7, " 4445 "-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n" 4446 " \n" 4447 " out_dynamic = " 4448 "routine[uni_indices.w](routine[uni_indices.z](routine[uni_indices.y](routine[uni_indices.x](uni_left, " 4449 "uni_right), uni_right), uni_right), uni_right);\n" 4450 " out_dynamic_inverted = " 4451 "routine[uni_indices.x](routine[uni_indices.y](routine[uni_indices.z](routine[uni_indices.w](uni_left, " 4452 "uni_right), uni_right), uni_right), uni_right);\n" 4453 " \n" 4454 " out_loop = uni_left;\n" 4455 " for (uint i = 0u; i < routine.length(); ++i)\n" 4456 " {\n" 4457 " out_loop = routine[i](out_loop, uni_right);\n" 4458 " }\n" 4459 " \n" 4460 " out_array_length = routine.length() + 6 - (uni_indices.x + uni_indices.y + uni_indices.z + " 4461 "uni_indices.w);\n" 4462 "}\n" 4463 "\n"; 4464 4465 static const GLchar* subroutine_names[] = { 4466 "add", "multiply", 4467 }; 4468 static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 4469 4470 static const GLchar* subroutine_uniform_names[] = { "routine[0]", "routine[1]", "routine[2]", "routine[3]" }; 4471 static const GLuint n_subroutine_uniform_names = 4472 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]); 4473 4474 static const GLchar* uniform_names[] = { 4475 "uni_left", "uni_right", "uni_indices", 4476 }; 4477 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]); 4478 4479 static const GLchar* varying_names[] = { "out_combined", "out_combined_inverted", 4480 "out_constant", "out_constant_inverted", 4481 "out_dynamic", "out_dynamic_inverted", 4482 "out_loop", "out_array_length" }; 4483 4484 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]); 4485 static const GLuint transform_feedback_buffer_size = n_varyings * 4 * sizeof(GLfloat); 4486 4487 /* Test data */ 4488 static const Utils::vec4<GLfloat> uni_left(-1.0f, 0.75f, -0.5f, 0.25f); 4489 static const Utils::vec4<GLfloat> uni_right(1.0f, -0.75f, 0.5f, -0.25f); 4490 static const Utils::vec4<GLuint> uni_indices(1, 2, 0, 3); 4491 4492 static const GLuint subroutine_combinations[][4] = { 4493 { 0, 0, 0, 0 }, /* + + + + */ 4494 { 0, 0, 0, 1 }, /* + + + * */ 4495 { 0, 0, 1, 0 }, /* + + * + */ 4496 { 0, 0, 1, 1 }, /* + + * * */ 4497 { 0, 1, 0, 0 }, /* + * + + */ 4498 { 0, 1, 0, 1 }, /* + * + * */ 4499 { 0, 1, 1, 0 }, /* + * * + */ 4500 { 0, 1, 1, 1 }, /* + * * * */ 4501 { 1, 0, 0, 0 }, /* * + + + */ 4502 { 1, 0, 0, 1 }, /* * + + * */ 4503 { 1, 0, 1, 0 }, /* * + * + */ 4504 { 1, 0, 1, 1 }, /* * + * * */ 4505 { 1, 1, 0, 0 }, /* * * + + */ 4506 { 1, 1, 0, 1 }, /* * * + * */ 4507 { 1, 1, 1, 0 }, /* * * * + */ 4508 { 1, 1, 1, 1 } /* * * * * */ 4509 }; 4510 static const GLuint n_subroutine_combinations = 4511 sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]); 4512 4513 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 4514 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 4515 { 4516 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 4517 } 4518 4519 /* GL objects */ 4520 Utils::program program(m_context); 4521 Utils::buffer transform_feedback_buffer(m_context); 4522 Utils::vertexArray vao(m_context); 4523 4524 bool result = true; 4525 4526 /* Init GL objects */ 4527 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names, 4528 n_varyings); 4529 4530 program.use(); 4531 4532 vao.generate(); 4533 vao.bind(); 4534 4535 transform_feedback_buffer.generate(); 4536 4537 /* Get subroutine indices */ 4538 for (GLuint routine = 0; routine < n_subroutine_names; ++routine) 4539 { 4540 m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER); 4541 } 4542 4543 /* Get subroutine uniform locations */ 4544 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 4545 { 4546 m_subroutine_uniform_locations[uniform] = 4547 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER); 4548 } 4549 4550 /* Get uniform locations */ 4551 for (GLuint i = 0; i < n_uniform_names; ++i) 4552 { 4553 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]); 4554 } 4555 4556 /* Test */ 4557 for (GLuint i = 0; i < n_subroutine_combinations; ++i) 4558 { 4559 /* Clean */ 4560 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 4561 GL_DYNAMIC_COPY); 4562 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 4563 4564 /* Verify */ 4565 if (false == testDraw(subroutine_combinations[i], uni_left, uni_right, uni_indices)) 4566 { 4567 result = false; 4568 } 4569 } 4570 4571 if (true == result) 4572 { 4573 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4574 } 4575 else 4576 { 4577 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4578 } 4579 4580 /* Done */ 4581 return tcu::TestNode::STOP; 4582 } 4583 4584 /* Calculate result of function applied to operands 4585 * 4586 * @param function Function id, 0 is sum, 1 is multiplication 4587 * @param left Left operand 4588 * @param right Right operand 4589 * @param out Function result 4590 **/ 4591 void FunctionalTest7_8::calculate(glw::GLuint function, const Utils::vec4<glw::GLfloat>& left, 4592 const Utils::vec4<glw::GLfloat>& right, Utils::vec4<glw::GLfloat>& out) const 4593 { 4594 if (0 == function) 4595 { 4596 out.m_x = left.m_x + right.m_x; 4597 out.m_y = left.m_y + right.m_y; 4598 out.m_z = left.m_z + right.m_z; 4599 out.m_w = left.m_w + right.m_w; 4600 } 4601 else 4602 { 4603 out.m_x = left.m_x * right.m_x; 4604 out.m_y = left.m_y * right.m_y; 4605 out.m_z = left.m_z * right.m_z; 4606 out.m_w = left.m_w * right.m_w; 4607 } 4608 } 4609 4610 /** Calculate expected values for all operations 4611 * 4612 * @param combination Function combination, first applied function is at index [0] 4613 * @param left Left operand 4614 * @param right Right operand 4615 * @param indices Indices used by dynamic calls 4616 * @param out_combined Expected result of "combined" operation 4617 * @param out_combined_inverted Expected result of "combined_inverted" operation 4618 * @param out_constant Expected result of "constant" operation 4619 * @param out_constant_inverted Expected result of "constant_inverted" operation 4620 * @param out_dynamic Expected result of "dynamic" operation 4621 * @param out_dynamic_inverted Expected result of "out_dynamic_inverted" operation 4622 * @param out_loop Expected result of "loop" operation 4623 **/ 4624 void FunctionalTest7_8::calculate( 4625 const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, const Utils::vec4<glw::GLfloat>& right, 4626 const Utils::vec4<glw::GLuint>& indices, Utils::vec4<glw::GLfloat>& out_combined, 4627 Utils::vec4<glw::GLfloat>& out_combined_inverted, Utils::vec4<glw::GLfloat>& out_constant, 4628 Utils::vec4<glw::GLfloat>& out_constant_inverted, Utils::vec4<glw::GLfloat>& out_dynamic, 4629 Utils::vec4<glw::GLfloat>& out_dynamic_inverted, Utils::vec4<glw::GLfloat>& out_loop) const 4630 { 4631 /* Indices used by "dynamic" operations, range <0..4> */ 4632 const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y], 4633 combination[indices.m_z], combination[indices.m_w] }; 4634 4635 /* Values used by "constant" operations, come from shader code */ 4636 const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4), 4637 Utils::vec4<glw::GLfloat>(-5, -6, -7, -8), 4638 Utils::vec4<glw::GLfloat>(-1, -2, -3, -4), 4639 Utils::vec4<glw::GLfloat>(5, 6, 7, 8), 4640 Utils::vec4<glw::GLfloat>(1, 2, 3, 4) }; 4641 4642 /* Start values */ 4643 Utils::vec4<glw::GLfloat> combined = left; 4644 Utils::vec4<glw::GLfloat> combined_inverted = left; 4645 Utils::vec4<glw::GLfloat> constant = constant_values[0]; 4646 Utils::vec4<glw::GLfloat> constant_inverted = constant_values[0]; 4647 Utils::vec4<glw::GLfloat> dynamic = left; 4648 Utils::vec4<glw::GLfloat> dynamic_inverted = left; 4649 4650 /* Calculate expected results */ 4651 for (GLuint i = 0; i < 4; ++i) 4652 { 4653 GLuint function = combination[i]; 4654 GLuint function_inverted = combination[3 - i]; 4655 GLuint dynamic_function = dynamic_combination[i]; 4656 GLuint dynamic_function_inverted = dynamic_combination[3 - i]; 4657 4658 calculate(function, combined, right, combined); 4659 calculate(function_inverted, combined_inverted, right, combined_inverted); 4660 calculate(function, constant, constant_values[i + 1], constant); 4661 calculate(function_inverted, constant_inverted, constant_values[i + 1], constant_inverted); 4662 calculate(dynamic_function, dynamic, right, dynamic); 4663 calculate(dynamic_function_inverted, dynamic_inverted, right, dynamic_inverted); 4664 } 4665 4666 /* Store results */ 4667 out_combined = combined; 4668 out_combined_inverted = combined_inverted; 4669 out_constant = constant; 4670 out_constant_inverted = constant_inverted; 4671 out_dynamic = dynamic; 4672 out_dynamic_inverted = dynamic_inverted; 4673 out_loop = combined; 4674 } 4675 4676 /** Log error 4677 * 4678 * @param combination Operations combination 4679 * @param left Left operand 4680 * @param right Right operand 4681 * @param indices Inidices used by "dynamic" calls 4682 * @param vec4_expected Expected results 4683 * @param vec4_result Results 4684 * @param array_length Length of array 4685 * @param result Comparison results 4686 **/ 4687 void FunctionalTest7_8::logError(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, 4688 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices, 4689 const Utils::vec4<glw::GLfloat> vec4_expected[7], 4690 const Utils::vec4<glw::GLfloat> vec4_result[7], glw::GLuint array_length, 4691 bool result[7]) const 4692 { 4693 static const GLuint n_functions = 4; 4694 static const GLuint n_operations = 7; 4695 4696 /* Indices used by "dynamic" operations, range <0..4> */ 4697 const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y], 4698 combination[indices.m_z], combination[indices.m_w] }; 4699 4700 /* Function symbols */ 4701 GLchar functions[4]; 4702 GLchar functions_inverted[4]; 4703 GLchar functions_dynamic[4]; 4704 GLchar functions_dynamic_inverted[4]; 4705 4706 for (GLuint i = 0; i < n_functions; ++i) 4707 { 4708 GLchar function = (0 == combination[i]) ? '+' : '*'; 4709 GLchar dynamic_function = (0 == dynamic_combination[i]) ? '+' : '*'; 4710 4711 functions[i] = function; 4712 functions_inverted[n_functions - i - 1] = function; 4713 functions_dynamic[i] = dynamic_function; 4714 functions_dynamic_inverted[n_functions - i - 1] = dynamic_function; 4715 } 4716 4717 /* Values used by "constant" operations, come from shader code */ 4718 const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4), 4719 Utils::vec4<glw::GLfloat>(-5, -6, -7, -8), 4720 Utils::vec4<glw::GLfloat>(-1, -2, -3, -4), 4721 Utils::vec4<glw::GLfloat>(5, 6, 7, 8), 4722 Utils::vec4<glw::GLfloat>(1, 2, 3, 4) }; 4723 4724 /* Values used by non-"constant" operations */ 4725 Utils::vec4<glw::GLfloat> dynamic_values[5]; 4726 dynamic_values[0] = left; 4727 dynamic_values[1] = right; 4728 dynamic_values[2] = right; 4729 dynamic_values[3] = right; 4730 dynamic_values[4] = right; 4731 4732 /* For each operation */ 4733 for (GLuint i = 0; i < n_operations; ++i) 4734 { 4735 /* If result is failure */ 4736 if (false == result[i]) 4737 { 4738 const GLchar* description = 0; 4739 const Utils::vec4<glw::GLfloat>* input = 0; 4740 const GLchar* operation = 0; 4741 4742 switch (i) 4743 { 4744 case 0: 4745 description = "Call made with predefined array indices"; 4746 input = dynamic_values; 4747 operation = functions; 4748 break; 4749 case 1: 4750 description = "Call made with predefined array indices in inverted order"; 4751 input = dynamic_values; 4752 operation = functions_inverted; 4753 break; 4754 case 2: 4755 description = "Call made with predefined array indices, for constant values"; 4756 input = constant_values; 4757 operation = functions; 4758 break; 4759 case 3: 4760 description = "Call made with predefined array indices in inverted order, for constant values"; 4761 input = constant_values; 4762 operation = functions_inverted; 4763 break; 4764 case 4: 4765 description = "Call made with dynamic array indices"; 4766 input = dynamic_values; 4767 operation = functions_dynamic; 4768 break; 4769 case 5: 4770 description = "Call made with dynamic array indices in inverted order"; 4771 input = dynamic_values; 4772 operation = functions_dynamic_inverted; 4773 break; 4774 case 6: 4775 description = "Call made with loop"; 4776 input = dynamic_values; 4777 operation = functions; 4778 break; 4779 } 4780 4781 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 4782 << tcu::TestLog::EndMessage; 4783 4784 m_context.getTestContext().getLog() << tcu::TestLog::Message << description << tcu::TestLog::EndMessage; 4785 4786 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4787 4788 message << "Operation: (((("; 4789 input[0].log(message); 4790 for (GLuint function = 0; function < n_functions; ++function) 4791 { 4792 message << " " << operation[function] << " "; 4793 4794 input[function + 1].log(message); 4795 4796 message << ")"; 4797 } 4798 4799 message << tcu::TestLog::EndMessage; 4800 4801 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4802 4803 message << "Result: "; 4804 vec4_result[i].log(message); 4805 4806 message << tcu::TestLog::EndMessage; 4807 4808 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4809 4810 message << "Expected: "; 4811 vec4_expected[i].log(message); 4812 4813 message << tcu::TestLog::EndMessage; 4814 } 4815 4816 /* Check array length, it should be 4 */ 4817 if (4 != array_length) 4818 { 4819 m_context.getTestContext().getLog() << tcu::TestLog::Message 4820 << "Error. Invalid array length: " << array_length << ". Expected 4." 4821 << tcu::TestLog::EndMessage; 4822 } 4823 } 4824 } 4825 4826 /** Execute draw call and verifies captrued varyings 4827 * 4828 * @param combination Function combination, first applied function is at index [0] 4829 * @param left Left operand 4830 * @param right Right operand 4831 * @param indices Indices used by dynamic calls 4832 * 4833 * @return true if all results match expected values, false otherwise 4834 **/ 4835 bool FunctionalTest7_8::testDraw(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, 4836 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices) const 4837 { 4838 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4839 static const GLuint n_vec4_varyings = 7; 4840 bool result = true; 4841 GLuint subroutine_indices[4]; 4842 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 4843 4844 /* Prepare expected results */ 4845 Utils::vec4<glw::GLfloat> expected_results[7]; 4846 calculate(combination, left, right, indices, expected_results[0], expected_results[1], expected_results[2], 4847 expected_results[3], expected_results[4], expected_results[5], expected_results[6]); 4848 4849 /* Set up input data uniforms */ 4850 gl.uniform4f(m_uniform_locations[0], left.m_x, left.m_y, left.m_z, left.m_w); 4851 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 4852 4853 gl.uniform4f(m_uniform_locations[1], right.m_x, right.m_y, right.m_z, right.m_w); 4854 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 4855 4856 gl.uniform4ui(m_uniform_locations[2], indices.m_x, indices.m_y, indices.m_z, indices.m_w); 4857 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4ui"); 4858 4859 /* Prepare subroutine uniform data */ 4860 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 4861 { 4862 const GLuint location = m_subroutine_uniform_locations[i]; 4863 4864 subroutine_indices[location] = m_subroutine_indices[combination[i]]; 4865 } 4866 4867 /* Set up subroutine uniforms */ 4868 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]); 4869 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 4870 4871 /* Execute draw call with transform feedback */ 4872 gl.beginTransformFeedback(GL_POINTS); 4873 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 4874 4875 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 4876 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 4877 4878 gl.endTransformFeedback(); 4879 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 4880 4881 /* Capture results */ 4882 GLvoid* feedback_data = (GLvoid*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 4883 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4884 4885 Utils::vec4<GLfloat> vec4_results[7]; 4886 bool results[7]; 4887 GLfloat* float_data = (GLfloat*)feedback_data; 4888 for (GLuint i = 0; i < n_vec4_varyings; ++i) 4889 { 4890 vec4_results[i].m_x = float_data[i * 4 + 0]; 4891 vec4_results[i].m_y = float_data[i * 4 + 1]; 4892 vec4_results[i].m_z = float_data[i * 4 + 2]; 4893 vec4_results[i].m_w = float_data[i * 4 + 3]; 4894 } 4895 4896 GLuint* uint_data = (GLuint*)(float_data + (n_vec4_varyings)*4); 4897 GLuint array_length = uint_data[0]; 4898 4899 /* Unmap buffer */ 4900 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4901 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 4902 4903 /* Verification */ 4904 for (GLuint i = 0; i < n_vec4_varyings; ++i) 4905 { 4906 results[i] = (vec4_results[i] == expected_results[i]); 4907 result = result && results[i]; 4908 } 4909 4910 result = result && (4 == array_length); 4911 4912 /* Log error if any */ 4913 if (false == result) 4914 { 4915 logError(combination, left, right, indices, expected_results, vec4_results, array_length, results); 4916 } 4917 4918 /* Done */ 4919 return result; 4920 } 4921 4922 /** Constructor. 4923 * 4924 * @param context Rendering context. 4925 * 4926 **/ 4927 FunctionalTest9::FunctionalTest9(deqp::Context& context) 4928 : TestCase(context, "subroutines_3_subroutine_types_and_subroutine_uniforms_one_function", 4929 "Makes sure that program with one function associated with 3 different " 4930 "subroutine types and 3 subroutine uniforms using that function compiles " 4931 "and works as expected") 4932 , m_has_test_passed(true) 4933 , m_n_points_to_draw(16) /* arbitrary value */ 4934 , m_po_id(0) 4935 , m_vao_id(0) 4936 , m_vs_id(0) 4937 , m_xfb_bo_id(0) 4938 { 4939 /* Left blank intentionally */ 4940 } 4941 4942 /** De-initializes GL objects that may have been created during test execution. */ 4943 void FunctionalTest9::deinit() 4944 { 4945 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4946 4947 if (m_po_id != 0) 4948 { 4949 gl.deleteProgram(m_po_id); 4950 4951 m_po_id = 0; 4952 } 4953 4954 if (m_vao_id != 0) 4955 { 4956 gl.deleteVertexArrays(1, &m_vao_id); 4957 4958 m_vao_id = 0; 4959 } 4960 4961 if (m_vs_id != 0) 4962 { 4963 gl.deleteShader(m_vs_id); 4964 4965 m_vs_id = 0; 4966 } 4967 4968 if (m_xfb_bo_id != 0) 4969 { 4970 gl.deleteBuffers(1, &m_xfb_bo_id); 4971 4972 m_xfb_bo_id = 0; 4973 } 4974 } 4975 4976 /** Retrieves body of a vertex shader that should be used 4977 * for the testing purposes. 4978 **/ 4979 std::string FunctionalTest9::getVertexShaderBody() const 4980 { 4981 return "#version 400\n" 4982 "\n" 4983 "#extension GL_ARB_shader_subroutine : require\n" 4984 "\n" 4985 "subroutine void subroutineType1(inout float);\n" 4986 "subroutine void subroutineType2(inout float);\n" 4987 "subroutine void subroutineType3(inout float);\n" 4988 "\n" 4989 "subroutine(subroutineType1, subroutineType2, subroutineType3) void function(inout float result)\n" 4990 "{\n" 4991 " result += float(0.123) + float(gl_VertexID);\n" 4992 "}\n" 4993 "\n" 4994 "subroutine uniform subroutineType1 subroutine_uniform1;\n" 4995 "subroutine uniform subroutineType2 subroutine_uniform2;\n" 4996 "subroutine uniform subroutineType3 subroutine_uniform3;\n" 4997 "\n" 4998 "out vec4 result;\n" 4999 "\n" 5000 "void main()\n" 5001 "{\n" 5002 " result = vec4(0, 1, 2, 3);\n" 5003 "\n" 5004 " subroutine_uniform1(result.x);\n" 5005 " subroutine_uniform2(result.y);\n" 5006 " subroutine_uniform3(result.z);\n" 5007 "\n" 5008 " result.w += result.x + result.y + result.z;\n" 5009 "}\n"; 5010 } 5011 5012 /** Initializes all GL objects required to run the test. */ 5013 void FunctionalTest9::initTest() 5014 { 5015 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5016 5017 /* Set up program object */ 5018 const char* xfb_varyings[] = { "result" }; 5019 5020 const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]); 5021 if (!Utils::buildProgram(gl, getVertexShaderBody(), "", /* tc_body */ 5022 "", /* te_body */ 5023 "", /* gs_body */ 5024 "", /* fs_body */ 5025 xfb_varyings, n_xfb_varyings, &m_vs_id, DE_NULL, /* out_tc_id */ 5026 DE_NULL, /* out_te_id */ 5027 DE_NULL, /* out_gs_id */ 5028 DE_NULL, /* out_fs_id */ 5029 &m_po_id)) 5030 { 5031 TCU_FAIL("Program failed to link successfully"); 5032 } 5033 5034 /* Set up a buffer object we will use to hold XFB data */ 5035 const unsigned int xfb_bo_size = static_cast<unsigned int>(sizeof(float) * 4 /* components */ * m_n_points_to_draw); 5036 5037 gl.genBuffers(1, &m_xfb_bo_id); 5038 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 5039 5040 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 5041 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 5042 5043 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 5044 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 5045 5046 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL, /* data */ 5047 GL_STATIC_COPY); 5048 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 5049 5050 /* Generate & bind a VAO */ 5051 gl.genVertexArrays(1, &m_vao_id); 5052 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 5053 5054 gl.bindVertexArray(m_vao_id); 5055 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 5056 } 5057 5058 /** Executes test iteration. 5059 * 5060 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 5061 */ 5062 tcu::TestNode::IterateResult FunctionalTest9::iterate() 5063 { 5064 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5065 5066 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 5067 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 5068 { 5069 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 5070 } 5071 initTest(); 5072 5073 /* Issue a draw call to make use of the three subroutine uniforms that we've defined */ 5074 gl.useProgram(m_po_id); 5075 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 5076 5077 gl.beginTransformFeedback(GL_POINTS); 5078 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 5079 { 5080 gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw); 5081 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 5082 } 5083 gl.endTransformFeedback(); 5084 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 5085 5086 /* Map the XFB BO storage into process space */ 5087 const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 5088 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 5089 5090 verifyXFBData(xfb_data_ptr); 5091 5092 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5093 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 5094 5095 /* All done */ 5096 if (m_has_test_passed) 5097 { 5098 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5099 } 5100 else 5101 { 5102 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5103 } 5104 5105 return STOP; 5106 } 5107 5108 /** Verifies the data XFBed out by the vertex shader. Should the data 5109 * be found invalid, m_has_test_passed will be set to false. 5110 * 5111 * @param data_ptr XFB data. 5112 **/ 5113 void FunctionalTest9::verifyXFBData(const glw::GLvoid* data_ptr) 5114 { 5115 const float epsilon = 1e-5f; 5116 bool should_continue = true; 5117 const glw::GLfloat* traveller_ptr = (const glw::GLfloat*)data_ptr; 5118 5119 for (unsigned int n_point = 0; n_point < m_n_points_to_draw && should_continue; ++n_point) 5120 { 5121 tcu::Vec4 expected_result(0, 1, 2, 3); 5122 5123 for (unsigned int n_component = 0; n_component < 3 /* xyz */; ++n_component) 5124 { 5125 expected_result[n_component] += 0.123f + float(n_point); 5126 } 5127 5128 expected_result[3 /* w */] += expected_result[0] + expected_result[1] + expected_result[2]; 5129 5130 if (de::abs(expected_result[0] - traveller_ptr[0]) > epsilon || 5131 de::abs(expected_result[1] - traveller_ptr[1]) > epsilon || 5132 de::abs(expected_result[2] - traveller_ptr[2]) > epsilon || 5133 de::abs(expected_result[3] - traveller_ptr[3]) > epsilon) 5134 { 5135 m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data is invalid. Expected:" 5136 "(" 5137 << expected_result[0] << ", " << expected_result[1] << ", " << expected_result[2] << ", " 5138 << expected_result[3] << "), found:(" << traveller_ptr[0] << ", " << traveller_ptr[1] 5139 << ", " << traveller_ptr[2] << ", " << traveller_ptr[3] << ")." 5140 << tcu::TestLog::EndMessage; 5141 5142 m_has_test_passed = false; 5143 should_continue = false; 5144 } 5145 5146 traveller_ptr += 4; /* xyzw */ 5147 } /* for (all rendered points) */ 5148 } 5149 5150 /** Constructor 5151 * 5152 * @param context CTS context 5153 **/ 5154 FunctionalTest10::FunctionalTest10(deqp::Context& context) 5155 : TestCase(context, "arrays_of_arrays_of_uniforms", "Verify that arrays of arrays of uniforms works as expected") 5156 { 5157 } 5158 5159 /** Execute test 5160 * 5161 * @return tcu::TestNode::STOP 5162 **/ 5163 tcu::TestNode::IterateResult FunctionalTest10::iterate() 5164 { 5165 static const GLchar* vertex_shader_code = "#version 400 core\n" 5166 "#extension GL_ARB_arrays_of_arrays : require\n" 5167 "#extension GL_ARB_shader_subroutine : require\n" 5168 "\n" 5169 "precision highp float;\n" 5170 "\n" 5171 "// Subroutine type\n" 5172 "subroutine int routine_type(in int iparam);\n" 5173 "\n" 5174 "// Subroutine definitions\n" 5175 "subroutine(routine_type) int increment(in int iparam)\n" 5176 "{\n" 5177 " return iparam + 1;\n" 5178 "}\n" 5179 "\n" 5180 "subroutine(routine_type) int decrement(in int iparam)\n" 5181 "{\n" 5182 " return iparam - 1;\n" 5183 "}\n" 5184 "\n" 5185 "// Sub routine uniform\n" 5186 "subroutine uniform routine_type routine[4][4];\n" 5187 "\n" 5188 "// Output\n" 5189 "out int out_result;\n" 5190 "\n" 5191 "void main()\n" 5192 "{\n" 5193 " int result = 0;\n" 5194 " \n" 5195 " for (uint j = 0; j < routine.length(); ++j)\n" 5196 " {\n" 5197 " for (uint i = 0; i < routine[j].length(); ++i)\n" 5198 " {\n" 5199 " result = routine[j][i](result);\n" 5200 " }\n" 5201 " }\n" 5202 " \n" 5203 " out_result = result;\n" 5204 "}\n" 5205 "\n"; 5206 5207 static const GLchar* subroutine_names[] = { 5208 "increment", "decrement", 5209 }; 5210 static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 5211 5212 static const GLchar* subroutine_uniform_names[] = { 5213 "routine[0][0]", "routine[1][0]", "routine[2][0]", "routine[3][0]", "routine[0][1]", "routine[1][1]", 5214 "routine[2][1]", "routine[3][1]", "routine[0][2]", "routine[1][2]", "routine[2][2]", "routine[3][2]", 5215 "routine[0][3]", "routine[1][3]", "routine[2][3]", "routine[3][3]" 5216 }; 5217 static const GLuint n_subroutine_uniform_names = 5218 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]); 5219 5220 static const GLchar* varying_name = "out_result"; 5221 static const GLuint transform_feedback_buffer_size = sizeof(GLint); 5222 5223 static const GLuint configuration_increment[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 5224 5225 static const GLuint configuration_decrement[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 5226 5227 static const GLuint configuration_mix[16] = { 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1 }; 5228 5229 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 5230 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 5231 { 5232 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 5233 } 5234 5235 /* Do not execute the test if GL_ARB_arrays_of_arrays is not supported */ 5236 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_arrays_of_arrays")) 5237 { 5238 throw tcu::NotSupportedError("GL_ARB_arrays_of_arrays is not supported."); 5239 } 5240 5241 bool result = true; 5242 5243 /* GL objects */ 5244 Utils::program program(m_context); 5245 Utils::buffer transform_feedback_buffer(m_context); 5246 Utils::vertexArray vao(m_context); 5247 5248 /* Init GL objects */ 5249 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name, 5250 1 /* n_varyings */); 5251 5252 program.use(); 5253 5254 vao.generate(); 5255 vao.bind(); 5256 5257 transform_feedback_buffer.generate(); 5258 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 5259 GL_DYNAMIC_COPY); 5260 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 5261 5262 /* Get subroutine indices */ 5263 for (GLuint routine = 0; routine < n_subroutine_names; ++routine) 5264 { 5265 m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER); 5266 } 5267 5268 /* Get subroutine uniform locations */ 5269 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 5270 { 5271 m_subroutine_uniform_locations[uniform] = 5272 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER); 5273 } 5274 5275 /* Test */ 5276 GLint increment_result = testDraw(configuration_increment); 5277 GLint decrement_result = testDraw(configuration_decrement); 5278 GLint mix_result = testDraw(configuration_mix); 5279 5280 /* Verify */ 5281 if (16 != increment_result) 5282 { 5283 result = false; 5284 } 5285 5286 if (-16 != decrement_result) 5287 { 5288 result = false; 5289 } 5290 if (0 != mix_result) 5291 { 5292 result = false; 5293 } 5294 5295 /* Set test result */ 5296 if (true == result) 5297 { 5298 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5299 } 5300 else 5301 { 5302 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 5303 << " Incrementation applied 16 times: " << increment_result 5304 << ". Decrementation applied 16 times: " << decrement_result 5305 << ". Incrementation and decrementation applied 8 times: " << mix_result 5306 << tcu::TestLog::EndMessage; 5307 5308 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5309 } 5310 5311 /* Done */ 5312 return tcu::TestNode::STOP; 5313 } 5314 5315 /** Execute draw call and return captured varying 5316 * 5317 * @param routine_indices Configuration of subroutine uniforms 5318 * 5319 * @return Value of varying captured with transform feedback 5320 **/ 5321 GLint FunctionalTest10::testDraw(const GLuint routine_indices[16]) const 5322 { 5323 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5324 GLuint subroutine_indices[16]; 5325 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 5326 5327 /* Prepare subroutine uniform data */ 5328 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 5329 { 5330 const GLuint location = m_subroutine_uniform_locations[i]; 5331 5332 subroutine_indices[location] = m_subroutine_indices[routine_indices[i]]; 5333 } 5334 5335 /* Set up subroutine uniforms */ 5336 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]); 5337 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 5338 5339 /* Execute draw call with transform feedback */ 5340 gl.beginTransformFeedback(GL_POINTS); 5341 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 5342 5343 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 5344 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 5345 5346 gl.endTransformFeedback(); 5347 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 5348 5349 /* Capture results */ 5350 GLint* feedback_data = (GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 5351 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 5352 5353 GLint result = feedback_data[0]; 5354 5355 /* Unmap buffer */ 5356 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5357 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 5358 5359 return result; 5360 } 5361 5362 /* Definitions of constants used by FunctionalTest11 */ 5363 const GLuint FunctionalTest11::m_texture_height = 32; 5364 const GLuint FunctionalTest11::m_texture_width = 32; 5365 5366 /** Constructor 5367 * 5368 * @param context CTS context 5369 **/ 5370 FunctionalTest11::FunctionalTest11(deqp::Context& context) 5371 : TestCase(context, "globals_sampling_output_discard_function_calls", "Verify that global variables, texture " 5372 "sampling, fragment output, fragment discard " 5373 "and function calls work as expected") 5374 { 5375 } 5376 5377 /** Execute test 5378 * 5379 * @return tcu::TestNode::STOP 5380 **/ 5381 tcu::TestNode::IterateResult FunctionalTest11::iterate() 5382 { 5383 static const GLchar* fragment_shader_code = 5384 "#version 400 core\n" 5385 "#extension GL_ARB_shader_subroutine : require\n" 5386 "\n" 5387 "precision highp float;\n" 5388 "\n" 5389 "// Output\n" 5390 "layout(location = 0) out vec4 out_color;\n" 5391 "\n" 5392 "// Global variables\n" 5393 "vec4 success_color;\n" 5394 "vec4 failure_color;\n" 5395 "\n" 5396 "// Samplers\n" 5397 "uniform sampler2D sampler_1;\n" 5398 "uniform sampler2D sampler_2;\n" 5399 "\n" 5400 "// Functions\n" 5401 "bool are_same(in vec4 left, in vec4 right)\n" 5402 "{\n" 5403 " bvec4 result;\n" 5404 "\n" 5405 " result.x = (left.x == right.x);\n" 5406 " result.y = (left.y == right.y);\n" 5407 " result.z = (left.z == right.z);\n" 5408 " result.w = (left.w == right.w);\n" 5409 "\n" 5410 " return all(result);\n" 5411 "}\n" 5412 "\n" 5413 "bool are_different(in vec4 left, in vec4 right)\n" 5414 "{\n" 5415 " bvec4 result;\n" 5416 "\n" 5417 " result.x = (left.x != right.x);\n" 5418 " result.y = (left.y != right.y);\n" 5419 " result.z = (left.z != right.z);\n" 5420 " result.w = (left.w != right.w);\n" 5421 "\n" 5422 " return any(result);\n" 5423 "}\n" 5424 "\n" 5425 "// Subroutine types\n" 5426 "subroutine void discard_fragment_type(void);\n" 5427 "subroutine void set_global_colors_type(void);\n" 5428 "subroutine vec4 sample_texture_type(in vec2);\n" 5429 "subroutine bool comparison_type(in vec4 left, in vec4 right);\n" 5430 "subroutine void test_type(void);\n" 5431 "\n" 5432 "// Subroutine definitions\n" 5433 "// discard_fragment_type\n" 5434 "subroutine(discard_fragment_type) void discard_yes(void)\n" 5435 "{\n" 5436 " discard;\n" 5437 "}\n" 5438 "\n" 5439 "subroutine(discard_fragment_type) void discard_no(void)\n" 5440 "{\n" 5441 "}\n" 5442 "\n" 5443 "// set_global_colors_type\n" 5444 "subroutine(set_global_colors_type) void red_pass_blue_fail(void)\n" 5445 "{\n" 5446 " success_color = vec4(1, 0, 0, 1);\n" 5447 " failure_color = vec4(0, 0, 1, 1);\n" 5448 "}\n" 5449 "\n" 5450 "subroutine(set_global_colors_type) void blue_pass_red_fail(void)\n" 5451 "{\n" 5452 " success_color = vec4(0, 0, 1, 1);\n" 5453 " failure_color = vec4(1, 0, 0, 1);\n" 5454 "}\n" 5455 "\n" 5456 "// sample_texture_type\n" 5457 "subroutine(sample_texture_type) vec4 first_sampler(in vec2 coord)\n" 5458 "{\n" 5459 " return texture(sampler_1, coord);\n" 5460 "}\n" 5461 "\n" 5462 "subroutine(sample_texture_type) vec4 second_sampler(in vec2 coord)\n" 5463 "{\n" 5464 " return texture(sampler_2, coord);\n" 5465 "}\n" 5466 "\n" 5467 "// comparison_type\n" 5468 "subroutine(comparison_type) bool check_equal(in vec4 left, in vec4 right)\n" 5469 "{\n" 5470 " return are_same(left, right);\n" 5471 "}\n" 5472 "\n" 5473 "subroutine(comparison_type) bool check_not_equal(in vec4 left, in vec4 right)\n" 5474 "{\n" 5475 " return are_different(left, right);\n" 5476 "}\n" 5477 "\n" 5478 "// Subroutine uniforms\n" 5479 "subroutine uniform discard_fragment_type discard_fragment;\n" 5480 "subroutine uniform set_global_colors_type set_global_colors;\n" 5481 "subroutine uniform sample_texture_type sample_texture;\n" 5482 "subroutine uniform comparison_type compare;\n" 5483 "\n" 5484 "// Subroutine definitions\n" 5485 "// test_type\n" 5486 "subroutine(test_type) void test_with_discard(void)\n" 5487 "{\n" 5488 " discard_fragment();" 5489 "\n" 5490 " out_color = failure_color;\n" 5491 "\n" 5492 " set_global_colors();\n" 5493 "\n" 5494 " vec4 sampled_color = sample_texture(gl_PointCoord);\n" 5495 "\n" 5496 " bool comparison_result = compare(success_color, sampled_color);\n" 5497 "\n" 5498 " if (true == comparison_result)\n" 5499 " {\n" 5500 " out_color = success_color;\n" 5501 " }\n" 5502 " else\n" 5503 " {\n" 5504 " out_color = failure_color;\n" 5505 " }\n" 5506 "}\n" 5507 "\n" 5508 "subroutine(test_type) void test_without_discard(void)\n" 5509 "{\n" 5510 " set_global_colors();\n" 5511 "\n" 5512 " vec4 sampled_color = sample_texture(gl_PointCoord);\n" 5513 "\n" 5514 " bool comparison_result = compare(success_color, sampled_color);\n" 5515 "\n" 5516 " if (true == comparison_result)\n" 5517 " {\n" 5518 " out_color = success_color;\n" 5519 " }\n" 5520 " else\n" 5521 " {\n" 5522 " out_color = failure_color;\n" 5523 " }\n" 5524 "}\n" 5525 "\n" 5526 "// Subroutine uniforms\n" 5527 "subroutine uniform test_type test;\n" 5528 "\n" 5529 "void main()\n" 5530 "{\n" 5531 " // Set colors\n" 5532 " success_color = vec4(0.5, 0.5, 0.5, 0.5);\n" 5533 " failure_color = vec4(0.5, 0.5, 0.5, 0.5);\n" 5534 "\n" 5535 " test();\n" 5536 "}\n" 5537 "\n"; 5538 5539 static const GLchar* geometry_shader_code = "#version 400 core\n" 5540 "#extension GL_ARB_shader_subroutine : require\n" 5541 "\n" 5542 "precision highp float;\n" 5543 "\n" 5544 "layout(points) in;\n" 5545 "layout(triangle_strip, max_vertices = 4) out;\n" 5546 "\n" 5547 "void main()\n" 5548 "{\n" 5549 " gl_Position = vec4(-1, -1, 0, 1);\n" 5550 " EmitVertex();\n" 5551 " \n" 5552 " gl_Position = vec4(-1, 1, 0, 1);\n" 5553 " EmitVertex();\n" 5554 " \n" 5555 " gl_Position = vec4( 1, -1, 0, 1);\n" 5556 " EmitVertex();\n" 5557 " \n" 5558 " gl_Position = vec4( 1, 1, 0, 1);\n" 5559 " EmitVertex();\n" 5560 " \n" 5561 " EndPrimitive();\n" 5562 "}\n" 5563 "\n"; 5564 5565 static const GLchar* vertex_shader_code = "#version 400 core\n" 5566 "#extension GL_ARB_shader_subroutine : require\n" 5567 "\n" 5568 "precision highp float;\n" 5569 "\n" 5570 "void main()\n" 5571 "{\n" 5572 "}\n" 5573 "\n"; 5574 5575 static const GLchar* subroutine_names[][2] = { { "discard_yes", "discard_no" }, 5576 { "red_pass_blue_fail", "blue_pass_red_fail" }, 5577 { "first_sampler", "second_sampler" }, 5578 { "check_equal", "check_not_equal" }, 5579 { "test_with_discard", "test_without_discard" } }; 5580 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 5581 5582 static const GLchar* subroutine_uniform_names[] = { "discard_fragment", "set_global_colors", "sample_texture", 5583 "compare", "test" }; 5584 static const GLuint n_subroutine_uniform_names = 5585 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]); 5586 5587 static const GLchar* uniform_names[] = { 5588 "sampler_1", "sampler_2", 5589 }; 5590 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]); 5591 5592 /* Colors */ 5593 static const GLubyte blue_color[4] = { 0, 0, 255, 255 }; 5594 static const GLubyte clean_color[4] = { 0, 0, 0, 0 }; 5595 static const GLubyte red_color[4] = { 255, 0, 0, 255 }; 5596 5597 /* Configurations */ 5598 static const testConfiguration test_configurations[] = { 5599 testConfiguration( 5600 "Expect red color from 1st sampler", red_color, 1 /* discard_fragment : discard_no */, 5601 0 /* set_global_colors : red_pass_blue_fail */, 0 /* sample_texture : first_sampler */, 5602 0 /* compare : check_equal */, 0 /* test : test_with_discard */, 1 /* red */, 5603 0 /* blue */), 5604 5605 testConfiguration( 5606 "Test \"without discard\" option, expect no blue color from 2nd sampler", blue_color, 5607 0 /* discard_fragment : discard_yes */, 1 /* set_global_colors : blue_pass_red_fail */, 5608 1 /* sample_texture : second_sampler */, 1 /* compare : check_not_equal */, 5609 1 /* test : test_without_discard */, 0 /* blue */, 1 /* red */), 5610 5611 testConfiguration("Fragment shoud be discarded", clean_color, 0 /* discard_fragment : discard_yes */, 5612 0 /* set_global_colors : red_pass_blue_fail */, 5613 0 /* sample_texture : first_sampler */, 5614 0 /* compare : check_equal */, 5615 0 /* test : test_with_discard */, 1 /* red */, 0 /* blue */), 5616 5617 testConfiguration( 5618 "Expect blue color from 1st sampler", blue_color, 1 /* discard_fragment : discard_no */, 5619 1 /* set_global_colors : blue_pass_red_fail */, 0 /* sample_texture : first_sampler */, 5620 0 /* compare : check_equal */, 0 /* test : test_with_discard */, 5621 0 /* blue */, 1 /* red */), 5622 5623 testConfiguration( 5624 "Expect red color from 2nd sampler", red_color, 1 /* discard_fragment : discard_no */, 5625 0 /* set_global_colors : red_pass_blue_fail */, 1 /* sample_texture : second_sampler */, 5626 0 /* compare : check_equal */, 0 /* test : test_with_discard */, 5627 0 /* blue */, 1 /* red */), 5628 5629 testConfiguration( 5630 "Expect no blue color from 2nd sampler", blue_color, 1 /* discard_fragment : discard_no */, 5631 1 /* set_global_colors : blue_pass_red_fail */, 1 /* sample_texture : second_sampler */, 5632 1 /* compare : check_not_equal */, 0 /* test : test_with_discard */, 5633 0 /* blue */, 1 /* red */), 5634 }; 5635 static const GLuint n_test_cases = sizeof(test_configurations) / sizeof(test_configurations[0]); 5636 5637 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 5638 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 5639 { 5640 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 5641 } 5642 5643 /* GL objects */ 5644 Utils::texture blue_texture(m_context); 5645 Utils::texture color_texture(m_context); 5646 Utils::framebuffer framebuffer(m_context); 5647 Utils::program program(m_context); 5648 Utils::texture red_texture(m_context); 5649 Utils::vertexArray vao(m_context); 5650 5651 /* Init GL objects */ 5652 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */, 5653 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */); 5654 5655 program.use(); 5656 5657 vao.generate(); 5658 vao.bind(); 5659 5660 blue_texture.create(m_texture_width, m_texture_height, GL_RGBA8); 5661 color_texture.create(m_texture_width, m_texture_height, GL_RGBA8); 5662 red_texture.create(m_texture_width, m_texture_height, GL_RGBA8); 5663 5664 framebuffer.generate(); 5665 framebuffer.bind(); 5666 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height); 5667 5668 /* Get subroutine indices */ 5669 for (GLuint type = 0; type < n_subroutine_types; ++type) 5670 { 5671 m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_FRAGMENT_SHADER); 5672 m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_FRAGMENT_SHADER); 5673 } 5674 5675 /* Get subroutine uniform locations */ 5676 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 5677 { 5678 m_subroutine_uniform_locations[uniform] = 5679 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_FRAGMENT_SHADER); 5680 } 5681 5682 /* Get uniform locations */ 5683 for (GLuint i = 0; i < n_uniform_names; ++i) 5684 { 5685 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]); 5686 } 5687 5688 /* Prepare textures */ 5689 fillTexture(blue_texture, blue_color); 5690 fillTexture(color_texture, clean_color); 5691 fillTexture(red_texture, red_color); 5692 5693 m_source_textures[0] = blue_texture.m_id; 5694 m_source_textures[1] = red_texture.m_id; 5695 5696 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 5697 5698 /* Test */ 5699 bool result = true; 5700 for (GLuint i = 0; i < n_test_cases; ++i) 5701 { 5702 /* Clean output texture */ 5703 framebuffer.clear(GL_COLOR_BUFFER_BIT); 5704 5705 /* Execute test */ 5706 if (false == testDraw(test_configurations[i].m_routines, test_configurations[i].m_samplers, 5707 test_configurations[i].m_expected_color, color_texture)) 5708 { 5709 m_context.getTestContext().getLog() 5710 << tcu::TestLog::Message << "Error. Failure for configuration: " << test_configurations[i].m_description 5711 << tcu::TestLog::EndMessage; 5712 5713 result = false; 5714 } 5715 } 5716 5717 /* Set result */ 5718 if (true == result) 5719 { 5720 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5721 } 5722 else 5723 { 5724 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5725 } 5726 5727 /* Done */ 5728 return tcu::TestNode::STOP; 5729 } 5730 5731 /** Fill texture with specified color 5732 * 5733 * @param texture Texture instance 5734 * @param color Color 5735 **/ 5736 void FunctionalTest11::fillTexture(Utils::texture& texture, const glw::GLubyte color[4]) const 5737 { 5738 std::vector<GLubyte> texture_data; 5739 5740 /* Prepare texture data */ 5741 texture_data.resize(m_texture_width * m_texture_height * 4); 5742 5743 for (GLuint y = 0; y < m_texture_height; ++y) 5744 { 5745 const GLuint line_offset = y * m_texture_width * 4; 5746 5747 for (GLuint x = 0; x < m_texture_width; ++x) 5748 { 5749 const GLuint point_offset = x * 4 + line_offset; 5750 5751 texture_data[point_offset + 0] = color[0]; /* red */ 5752 texture_data[point_offset + 1] = color[1]; /* green */ 5753 texture_data[point_offset + 2] = color[2]; /* blue */ 5754 texture_data[point_offset + 3] = color[3]; /* alpha */ 5755 } 5756 } 5757 5758 texture.update(m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); 5759 } 5760 5761 /** Execute draw call and verify results 5762 * 5763 * @param routine_configuration Configurations of routines to be used 5764 * @param sampler_configuration Configuration of textures to be bound to samplers 5765 * @param expected_color Expected color of result image 5766 * 5767 * @return true if result image is filled with expected color, false otherwise 5768 **/ 5769 bool FunctionalTest11::testDraw(const glw::GLuint routine_configuration[5], const glw::GLuint sampler_configuration[2], 5770 const glw::GLubyte expected_color[4], Utils::texture& color_texture) const 5771 { 5772 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5773 static const GLint n_samplers = 2; 5774 static const GLint n_subroutine_uniforms = 5; 5775 GLuint subroutine_indices[5]; 5776 5777 /* Set samplers */ 5778 for (GLuint i = 0; i < n_samplers; ++i) 5779 { 5780 const GLuint location = m_uniform_locations[i]; 5781 const GLuint texture = m_source_textures[sampler_configuration[i]]; 5782 5783 gl.activeTexture(GL_TEXTURE0 + i); 5784 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); 5785 5786 gl.bindTexture(GL_TEXTURE_2D, texture); 5787 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 5788 5789 gl.uniform1i(location, i); 5790 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 5791 } 5792 5793 gl.activeTexture(GL_TEXTURE0 + 0); 5794 5795 /* Set subroutine uniforms */ 5796 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 5797 { 5798 const GLuint location = m_subroutine_uniform_locations[i]; 5799 const GLuint routine = routine_configuration[i]; 5800 5801 subroutine_indices[location] = m_subroutine_indices[i][routine]; 5802 } 5803 5804 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 5, subroutine_indices); 5805 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 5806 5807 /* Draw */ 5808 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 5809 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 5810 5811 /* Capture result */ 5812 std::vector<GLubyte> captured_data; 5813 captured_data.resize(m_texture_width * m_texture_height * 4); 5814 5815 color_texture.get(GL_RGBA, GL_UNSIGNED_BYTE, &captured_data[0]); 5816 5817 /* Verify result */ 5818 for (GLuint y = 0; y < m_texture_height; ++y) 5819 { 5820 const GLuint line_offset = y * m_texture_width * 4; 5821 5822 for (GLuint x = 0; x < m_texture_width; ++x) 5823 { 5824 const GLuint point_offset = x * 4 + line_offset; 5825 bool is_as_expected = true; 5826 5827 is_as_expected = is_as_expected && (expected_color[0] == captured_data[point_offset + 0]); /* red */ 5828 is_as_expected = is_as_expected && (expected_color[1] == captured_data[point_offset + 1]); /* green */ 5829 is_as_expected = is_as_expected && (expected_color[2] == captured_data[point_offset + 2]); /* blue */ 5830 is_as_expected = is_as_expected && (expected_color[3] == captured_data[point_offset + 3]); /* alpha */ 5831 5832 if (false == is_as_expected) 5833 { 5834 return false; 5835 } 5836 } 5837 } 5838 5839 /* Done */ 5840 return true; 5841 } 5842 5843 /* Constatns used by FunctionalTest12 */ 5844 const glw::GLuint FunctionalTest12::m_texture_height = 16; 5845 const glw::GLuint FunctionalTest12::m_texture_width = 16; 5846 5847 /** Constructor 5848 * 5849 * @param context CTS context 5850 **/ 5851 FunctionalTest12::FunctionalTest12(deqp::Context& context) 5852 : TestCase(context, "ssbo_atomic_image_load_store", 5853 "Verify that SSBO, atomic counters and image load store work as expected") 5854 , m_left_image(0) 5855 , m_right_image(0) 5856 { 5857 } 5858 5859 /** Execute test 5860 * 5861 * @return tcu::TestNode::STOP 5862 **/ 5863 tcu::TestNode::IterateResult FunctionalTest12::iterate() 5864 { 5865 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 5866 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 5867 { 5868 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 5869 } 5870 5871 bool result = true; 5872 5873 /* Test atomic counters */ 5874 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters")) 5875 { 5876 if (false == testAtomic()) 5877 { 5878 result = false; 5879 } 5880 } 5881 5882 /* Test shader storage buffer */ 5883 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_storage_buffer_object")) 5884 { 5885 if (false == testSSBO()) 5886 { 5887 result = false; 5888 } 5889 } 5890 5891 /* Test image load store */ 5892 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_image_load_store")) 5893 { 5894 if (false == testImage()) 5895 { 5896 result = false; 5897 } 5898 } 5899 5900 /* Set result */ 5901 if (true == result) 5902 { 5903 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5904 } 5905 else 5906 { 5907 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5908 } 5909 5910 /* Done */ 5911 return tcu::TestNode::STOP; 5912 } 5913 5914 /** Fill texture with specified color 5915 * 5916 * @param texture Texture instance 5917 * @param color Color 5918 **/ 5919 void FunctionalTest12::fillTexture(Utils::texture& texture, const glw::GLuint color[4]) const 5920 { 5921 std::vector<GLuint> texture_data; 5922 5923 /* Prepare texture data */ 5924 texture_data.resize(m_texture_width * m_texture_height * 4); 5925 5926 for (GLuint y = 0; y < m_texture_height; ++y) 5927 { 5928 const GLuint line_offset = y * m_texture_width * 4; 5929 5930 for (GLuint x = 0; x < m_texture_width; ++x) 5931 { 5932 const GLuint point_offset = x * 4 + line_offset; 5933 5934 texture_data[point_offset + 0] = color[0]; /* red */ 5935 texture_data[point_offset + 1] = color[1]; /* green */ 5936 texture_data[point_offset + 2] = color[2]; /* blue */ 5937 texture_data[point_offset + 3] = color[3]; /* alpha */ 5938 } 5939 } 5940 5941 texture.update(m_texture_width, m_texture_height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &texture_data[0]); 5942 } 5943 5944 /** Test atomic counters 5945 * 5946 * @return true if test pass, false otherwise 5947 **/ 5948 bool FunctionalTest12::testAtomic() 5949 { 5950 static const GLchar* fragment_shader_code = "#version 400 core\n" 5951 "#extension GL_ARB_shader_atomic_counters : require\n" 5952 "#extension GL_ARB_shader_subroutine : require\n" 5953 "\n" 5954 "precision highp float;\n" 5955 "\n" 5956 "layout(location = 0) out uint out_color;\n" 5957 "\n" 5958 "layout(binding = 0, offset = 8) uniform atomic_uint one;\n" 5959 "layout(binding = 0, offset = 4) uniform atomic_uint two;\n" 5960 "layout(binding = 0, offset = 0) uniform atomic_uint three;\n" 5961 "\n" 5962 "subroutine void atomic_routine(void)\n;" 5963 "\n" 5964 "subroutine(atomic_routine) void increment_two(void)\n" 5965 "{\n" 5966 " out_color = atomicCounterIncrement(two);\n" 5967 "}\n" 5968 "\n" 5969 "subroutine(atomic_routine) void decrement_three(void)\n" 5970 "{\n" 5971 " out_color = atomicCounterDecrement(three);\n" 5972 "}\n" 5973 "\n" 5974 "subroutine(atomic_routine) void read_one(void)\n" 5975 "{\n" 5976 " out_color = atomicCounter(one);\n" 5977 "}\n" 5978 "\n" 5979 "subroutine uniform atomic_routine routine;\n" 5980 "\n" 5981 "void main()\n" 5982 "{\n" 5983 " routine();\n" 5984 "}\n" 5985 "\n"; 5986 5987 static const GLchar* geometry_shader_code = "#version 400 core\n" 5988 "#extension GL_ARB_shader_subroutine : require\n" 5989 "\n" 5990 "precision highp float;\n" 5991 "\n" 5992 "layout(points) in;\n" 5993 "layout(triangle_strip, max_vertices = 4) out;\n" 5994 "\n" 5995 "void main()\n" 5996 "{\n" 5997 " gl_Position = vec4(-1, -1, 0, 1);\n" 5998 " EmitVertex();\n" 5999 " \n" 6000 " gl_Position = vec4(-1, 1, 0, 1);\n" 6001 " EmitVertex();\n" 6002 " \n" 6003 " gl_Position = vec4( 1, -1, 0, 1);\n" 6004 " EmitVertex();\n" 6005 " \n" 6006 " gl_Position = vec4( 1, 1, 0, 1);\n" 6007 " EmitVertex();\n" 6008 " \n" 6009 " EndPrimitive();\n" 6010 "}\n" 6011 "\n"; 6012 6013 static const GLchar* vertex_shader_code = "#version 400 core\n" 6014 "#extension GL_ARB_shader_subroutine : require\n" 6015 "\n" 6016 "precision highp float;\n" 6017 "\n" 6018 "void main()\n" 6019 "{\n" 6020 "}\n" 6021 "\n"; 6022 6023 static const GLchar* subroutine_names[] = { "increment_two", "decrement_three", "read_one" }; 6024 6025 /* Test data */ 6026 static const glw::GLuint atomic_buffer_data[] = { m_texture_width * m_texture_height, 6027 m_texture_width * m_texture_height, 6028 m_texture_width * m_texture_height }; 6029 6030 static const glw::GLuint expected_incremented_two[] = { atomic_buffer_data[0], 2 * atomic_buffer_data[1], 6031 atomic_buffer_data[2] }; 6032 6033 static const glw::GLuint expected_decremented_three[] = { 0, expected_incremented_two[1], 6034 expected_incremented_two[2] }; 6035 6036 static const glw::GLuint expected_read_one[] = { expected_decremented_three[0], expected_decremented_three[1], 6037 expected_decremented_three[2] }; 6038 6039 /* GL objects */ 6040 Utils::buffer atomic_buffer(m_context); 6041 Utils::texture color_texture(m_context); 6042 Utils::framebuffer framebuffer(m_context); 6043 Utils::program program(m_context); 6044 Utils::vertexArray vao(m_context); 6045 6046 /* Init GL objects */ 6047 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */, 6048 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */); 6049 6050 program.use(); 6051 6052 vao.generate(); 6053 vao.bind(); 6054 6055 color_texture.create(m_texture_width, m_texture_height, GL_R32UI); 6056 6057 atomic_buffer.generate(); 6058 atomic_buffer.update(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomic_buffer_data), (GLvoid*)atomic_buffer_data, 6059 GL_STATIC_DRAW); 6060 atomic_buffer.bindRange(GL_ATOMIC_COUNTER_BUFFER, 0 /* index */, 0 /* offset */, sizeof(atomic_buffer_data)); 6061 6062 framebuffer.generate(); 6063 framebuffer.bind(); 6064 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height); 6065 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 6066 framebuffer.clear(GL_COLOR_BUFFER_BIT); 6067 6068 /* Subroutine indices */ 6069 GLuint increment_two = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER); 6070 GLuint decrement_three = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER); 6071 GLuint read_one = program.getSubroutineIndex(subroutine_names[2], GL_FRAGMENT_SHADER); 6072 6073 /* Test */ 6074 bool result = true; 6075 6076 if (false == testAtomicDraw(increment_two, expected_incremented_two)) 6077 { 6078 result = false; 6079 } 6080 6081 if (false == testAtomicDraw(decrement_three, expected_decremented_three)) 6082 { 6083 result = false; 6084 } 6085 6086 if (false == testAtomicDraw(read_one, expected_read_one)) 6087 { 6088 result = false; 6089 } 6090 6091 /* Done */ 6092 return result; 6093 } 6094 6095 /** Execture draw call and verify results 6096 * 6097 * @param subroutine_index Index of subroutine that shall be used during draw call 6098 * @param expected_results Expected results 6099 * 6100 * @return true if results are as expected, false otherwise 6101 **/ 6102 bool FunctionalTest12::testAtomicDraw(GLuint subroutine_index, const GLuint expected_results[3]) const 6103 { 6104 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6105 6106 /* Set subroutine uniforms */ 6107 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index); 6108 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 6109 6110 /* Draw */ 6111 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 6112 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 6113 6114 /* Capture results */ 6115 GLuint* atomic_results = (GLuint*)gl.mapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY); 6116 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 6117 6118 /* Verify */ 6119 bool result = (0 == memcmp(expected_results, atomic_results, 3 * sizeof(GLuint))); 6120 6121 if (false == result) 6122 { 6123 m_context.getTestContext().getLog() 6124 << tcu::TestLog::Message << "Error. Invalid result. " 6125 << "Result: [ " << atomic_results[0] << ", " << atomic_results[1] << ", " << atomic_results[2] << " ] " 6126 << "Expected: [ " << expected_results[0] << ", " << expected_results[1] << ", " << expected_results[2] 6127 << " ]" << tcu::TestLog::EndMessage; 6128 } 6129 6130 /* Unmap buffer */ 6131 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 6132 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 6133 6134 /* Done */ 6135 return result; 6136 } 6137 6138 /** Test image load store 6139 * 6140 * @return true if test pass, false otherwise 6141 **/ 6142 bool FunctionalTest12::testImage() 6143 { 6144 static const GLchar* fragment_shader_code = 6145 "#version 400 core\n" 6146 "#extension GL_ARB_shader_image_load_store : require\n" 6147 "#extension GL_ARB_shader_subroutine : require\n" 6148 "\n" 6149 "precision highp float;\n" 6150 "\n" 6151 "layout(location = 0) out uvec4 out_color;\n" 6152 "\n" 6153 "layout(rgba32ui) uniform uimage2D left_image;\n" 6154 "layout(rgba32ui) uniform uimage2D right_image;\n" 6155 "\n" 6156 "subroutine void image_routine(void);\n" 6157 "\n" 6158 "subroutine(image_routine) void left_to_right(void)\n" 6159 "{\n" 6160 " out_color = imageLoad (left_image, ivec2(gl_FragCoord.xy));\n" 6161 " imageStore(right_image, ivec2(gl_FragCoord.xy), out_color);\n" 6162 "}\n" 6163 "\n" 6164 "subroutine(image_routine) void right_to_left(void)\n" 6165 "{\n" 6166 " out_color = imageLoad (right_image, ivec2(gl_FragCoord.xy));\n" 6167 " imageStore(left_image, ivec2(gl_FragCoord.xy), out_color);\n" 6168 "}\n" 6169 "\n" 6170 "subroutine uniform image_routine routine;\n" 6171 "\n" 6172 "void main()\n" 6173 "{\n" 6174 " routine();\n" 6175 "}\n" 6176 "\n"; 6177 6178 static const GLchar* geometry_shader_code = "#version 400 core\n" 6179 "#extension GL_ARB_shader_subroutine : require\n" 6180 "\n" 6181 "precision highp float;\n" 6182 "\n" 6183 "layout(points) in;\n" 6184 "layout(triangle_strip, max_vertices = 4) out;\n" 6185 "\n" 6186 "void main()\n" 6187 "{\n" 6188 " gl_Position = vec4(-1, -1, 0, 1);\n" 6189 " EmitVertex();\n" 6190 " \n" 6191 " gl_Position = vec4(-1, 1, 0, 1);\n" 6192 " EmitVertex();\n" 6193 " \n" 6194 " gl_Position = vec4( 1, -1, 0, 1);\n" 6195 " EmitVertex();\n" 6196 " \n" 6197 " gl_Position = vec4( 1, 1, 0, 1);\n" 6198 " EmitVertex();\n" 6199 " \n" 6200 " EndPrimitive();\n" 6201 "}\n" 6202 "\n"; 6203 6204 static const GLchar* vertex_shader_code = "#version 400 core\n" 6205 "#extension GL_ARB_shader_subroutine : require\n" 6206 "\n" 6207 "precision highp float;\n" 6208 "\n" 6209 "void main()\n" 6210 "{\n" 6211 "}\n" 6212 "\n"; 6213 6214 static const GLchar* subroutine_names[] = { "left_to_right", "right_to_left" }; 6215 6216 static const GLchar* uniform_names[] = { "left_image", "right_image" }; 6217 6218 /* Test data */ 6219 static const GLuint blue_color[4] = { 0, 0, 255, 255 }; 6220 static const GLuint clean_color[4] = { 16, 32, 64, 128 }; 6221 static const GLuint red_color[4] = { 255, 0, 0, 255 }; 6222 6223 /* GL objects */ 6224 Utils::texture blue_texture(m_context); 6225 Utils::texture destination_texture(m_context); 6226 Utils::texture color_texture(m_context); 6227 Utils::framebuffer framebuffer(m_context); 6228 Utils::program program(m_context); 6229 Utils::texture red_texture(m_context); 6230 Utils::vertexArray vao(m_context); 6231 6232 /* Init GL objects */ 6233 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */, 6234 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */); 6235 6236 program.use(); 6237 6238 vao.generate(); 6239 vao.bind(); 6240 6241 blue_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6242 destination_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6243 color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6244 red_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6245 6246 fillTexture(blue_texture, blue_color); 6247 fillTexture(destination_texture, clean_color); 6248 fillTexture(red_texture, red_color); 6249 6250 framebuffer.generate(); 6251 framebuffer.bind(); 6252 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height); 6253 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 6254 framebuffer.clear(GL_COLOR_BUFFER_BIT); 6255 6256 /* Subroutine indices */ 6257 GLuint left_to_right = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER); 6258 GLuint right_to_left = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER); 6259 6260 /* Uniform locations */ 6261 m_left_image = program.getUniformLocation(uniform_names[0]); 6262 m_right_image = program.getUniformLocation(uniform_names[1]); 6263 6264 /* Test */ 6265 bool result = true; 6266 6267 if (false == testImageDraw(left_to_right, blue_texture, destination_texture, blue_color, blue_color)) 6268 { 6269 result = false; 6270 } 6271 6272 if (false == testImageDraw(left_to_right, red_texture, destination_texture, red_color, red_color)) 6273 { 6274 result = false; 6275 } 6276 6277 if (false == testImageDraw(right_to_left, destination_texture, blue_texture, blue_color, blue_color)) 6278 { 6279 result = false; 6280 } 6281 6282 if (false == testImageDraw(right_to_left, destination_texture, red_texture, red_color, red_color)) 6283 { 6284 result = false; 6285 } 6286 6287 if (false == testImageDraw(left_to_right, blue_texture, red_texture, blue_color, blue_color)) 6288 { 6289 result = false; 6290 } 6291 6292 /* Done */ 6293 return result; 6294 } 6295 6296 /** Execute draw call and verifies results 6297 * 6298 * @param subroutine_index Index of subroutine that shall be used during draw call 6299 * @param left "Left" texture 6300 * @param right "Right" texture 6301 * @param expected_left_color Expected color of "left" texture 6302 * @param expected_right_color Expected color of "right" texture 6303 * 6304 * @return true if verification result is positive, false otherwise 6305 **/ 6306 bool FunctionalTest12::testImageDraw(GLuint subroutine_index, Utils::texture& left, Utils::texture& right, 6307 const GLuint expected_left_color[4], const GLuint expected_right_color[4]) const 6308 { 6309 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6310 6311 /* Set subroutine uniforms */ 6312 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index); 6313 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 6314 6315 /* Set up image units */ 6316 gl.uniform1i(m_left_image, 0); 6317 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 6318 6319 gl.uniform1i(m_right_image, 1); 6320 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 6321 6322 gl.bindImageTexture(0, left.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); 6323 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture"); 6324 6325 gl.bindImageTexture(1, right.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); 6326 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture"); 6327 6328 /* Draw */ 6329 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 6330 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 6331 6332 /* Verify results */ 6333 bool result = true; 6334 6335 if (false == verifyTexture(left, expected_left_color)) 6336 { 6337 m_context.getTestContext().getLog() << tcu::TestLog::Message 6338 << "Error. Invalid result. Left texture is filled with wrong color." 6339 << tcu::TestLog::EndMessage; 6340 result = false; 6341 } 6342 6343 if (false == verifyTexture(right, expected_right_color)) 6344 { 6345 m_context.getTestContext().getLog() << tcu::TestLog::Message 6346 << "Error. Invalid result. Right texture is filled with wrong color." 6347 << tcu::TestLog::EndMessage; 6348 result = false; 6349 } 6350 6351 /* Done */ 6352 return result; 6353 } 6354 6355 /** Test shader storage buffer 6356 * 6357 * @return true if test pass, false otherwise 6358 **/ 6359 bool FunctionalTest12::testSSBO() 6360 { 6361 static const GLchar* fragment_shader_code = "#version 400 core\n" 6362 "#extension GL_ARB_shader_storage_buffer_object : require\n" 6363 "#extension GL_ARB_shader_subroutine : require\n" 6364 "\n" 6365 "precision highp float;\n" 6366 "\n" 6367 "layout(location = 0) out uvec4 out_color;\n" 6368 "\n" 6369 "layout(std140, binding = 0) buffer Buffer\n" 6370 "{\n" 6371 " uvec4 entry;\n" 6372 "};\n" 6373 "\n" 6374 "subroutine void ssbo_routine(void)\n;" 6375 "\n" 6376 "subroutine(ssbo_routine) void increment(void)\n" 6377 "{\n" 6378 " out_color.x = atomicAdd(entry.x, 1);\n" 6379 " out_color.y = atomicAdd(entry.y, 1);\n" 6380 " out_color.z = atomicAdd(entry.z, 1);\n" 6381 " out_color.w = atomicAdd(entry.w, 1);\n" 6382 "}\n" 6383 "\n" 6384 "subroutine(ssbo_routine) void decrement(void)\n" 6385 "{\n" 6386 " out_color.x = atomicAdd(entry.x, -1);\n" 6387 " out_color.y = atomicAdd(entry.y, -1);\n" 6388 " out_color.z = atomicAdd(entry.z, -1);\n" 6389 " out_color.w = atomicAdd(entry.w, -1);\n" 6390 "}\n" 6391 "\n" 6392 "subroutine uniform ssbo_routine routine;\n" 6393 "\n" 6394 "void main()\n" 6395 "{\n" 6396 " routine();\n" 6397 "}\n" 6398 "\n"; 6399 6400 static const GLchar* geometry_shader_code = "#version 400 core\n" 6401 "#extension GL_ARB_shader_subroutine : require\n" 6402 "\n" 6403 "precision highp float;\n" 6404 "\n" 6405 "layout(points) in;\n" 6406 "layout(triangle_strip, max_vertices = 4) out;\n" 6407 "\n" 6408 "void main()\n" 6409 "{\n" 6410 " gl_Position = vec4(-1, -1, 0, 1);\n" 6411 " EmitVertex();\n" 6412 " \n" 6413 " gl_Position = vec4(-1, 1, 0, 1);\n" 6414 " EmitVertex();\n" 6415 " \n" 6416 " gl_Position = vec4( 1, -1, 0, 1);\n" 6417 " EmitVertex();\n" 6418 " \n" 6419 " gl_Position = vec4( 1, 1, 0, 1);\n" 6420 " EmitVertex();\n" 6421 " \n" 6422 " EndPrimitive();\n" 6423 "}\n" 6424 "\n"; 6425 6426 static const GLchar* vertex_shader_code = "#version 400 core\n" 6427 "#extension GL_ARB_shader_subroutine : require\n" 6428 "\n" 6429 "precision highp float;\n" 6430 "\n" 6431 "void main()\n" 6432 "{\n" 6433 "}\n" 6434 "\n"; 6435 6436 static const GLchar* subroutine_names[] = { "increment", "decrement" }; 6437 6438 /* Test data */ 6439 static const glw::GLuint buffer_data[] = { m_texture_width * m_texture_height + 1, 6440 m_texture_width * m_texture_height + 2, 6441 m_texture_width * m_texture_height + 3, 6442 m_texture_width * m_texture_height + 4 }; 6443 6444 static const glw::GLuint expected_incremented[] = { m_texture_width * m_texture_height + buffer_data[0], 6445 m_texture_width * m_texture_height + buffer_data[1], 6446 m_texture_width * m_texture_height + buffer_data[2], 6447 m_texture_width * m_texture_height + buffer_data[3] }; 6448 6449 static const glw::GLuint expected_decremented[] = { buffer_data[0], buffer_data[1], buffer_data[2], 6450 buffer_data[3] }; 6451 6452 /* GL objects */ 6453 Utils::buffer buffer(m_context); 6454 Utils::texture color_texture(m_context); 6455 Utils::framebuffer framebuffer(m_context); 6456 Utils::program program(m_context); 6457 Utils::vertexArray vao(m_context); 6458 6459 /* Init GL objects */ 6460 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */, 6461 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */); 6462 6463 program.use(); 6464 6465 vao.generate(); 6466 vao.bind(); 6467 6468 color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6469 6470 buffer.generate(); 6471 buffer.update(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), (GLvoid*)buffer_data, GL_STATIC_DRAW); 6472 buffer.bindRange(GL_SHADER_STORAGE_BUFFER, 0 /* index */, 0 /* offset */, sizeof(buffer_data)); 6473 6474 framebuffer.generate(); 6475 framebuffer.bind(); 6476 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height); 6477 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 6478 framebuffer.clear(GL_COLOR_BUFFER_BIT); 6479 6480 /* Subroutine indices */ 6481 GLuint increment = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER); 6482 GLuint decrement = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER); 6483 6484 /* Test */ 6485 bool result = true; 6486 6487 if (false == testSSBODraw(increment, expected_incremented)) 6488 { 6489 result = false; 6490 } 6491 6492 if (false == testSSBODraw(decrement, expected_decremented)) 6493 { 6494 result = false; 6495 } 6496 6497 /* Done */ 6498 return result; 6499 } 6500 6501 /** Execute draw call and verify results 6502 * 6503 * @param subroutine_index Index of subroutine that shall be used by draw call 6504 * @param expected_results Expected results 6505 * 6506 * 6507 **/ 6508 bool FunctionalTest12::testSSBODraw(GLuint subroutine_index, const GLuint expected_results[4]) const 6509 { 6510 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6511 6512 /* Set subroutine uniforms */ 6513 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index); 6514 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 6515 6516 /* Draw */ 6517 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 6518 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 6519 6520 /* Capture results */ 6521 GLuint* ssbo_results = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY); 6522 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 6523 6524 /* Verify */ 6525 bool result = (0 == memcmp(expected_results, ssbo_results, 4 * sizeof(GLuint))); 6526 6527 if (false == result) 6528 { 6529 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result. " 6530 << "Result: [ " << ssbo_results[0] << ", " << ssbo_results[1] << ", " 6531 << ssbo_results[2] << ", " << ssbo_results[3] << " ] " 6532 << "Expected: [ " << expected_results[0] << ", " << expected_results[1] 6533 << ", " << expected_results[2] << ", " << expected_results[3] << " ]" 6534 << tcu::TestLog::EndMessage; 6535 } 6536 6537 /* Unmap buffer */ 6538 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 6539 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 6540 6541 /* Done */ 6542 return result; 6543 } 6544 6545 /** Check if texture is filled with expected color 6546 * 6547 * @param texture Texture instance 6548 * @param expected_color Expected color 6549 * 6550 * @return true if texture is filled with specified color, false otherwise 6551 **/ 6552 bool FunctionalTest12::verifyTexture(Utils::texture& texture, const GLuint expected_color[4]) const 6553 { 6554 std::vector<GLuint> results; 6555 results.resize(m_texture_width * m_texture_height * 4); 6556 6557 texture.get(GL_RGBA_INTEGER, GL_UNSIGNED_INT, &results[0]); 6558 6559 for (GLuint y = 0; y < m_texture_height; ++y) 6560 { 6561 const GLuint line_offset = y * m_texture_width * 4; 6562 6563 for (GLuint x = 0; x < m_texture_width; ++x) 6564 { 6565 const GLuint point_offset = line_offset + x * 4; 6566 bool result = true; 6567 6568 result = result && (results[point_offset + 0] == expected_color[0]); 6569 result = result && (results[point_offset + 1] == expected_color[1]); 6570 result = result && (results[point_offset + 2] == expected_color[2]); 6571 result = result && (results[point_offset + 3] == expected_color[3]); 6572 6573 if (false == result) 6574 { 6575 return false; 6576 } 6577 } 6578 } 6579 6580 return true; 6581 } 6582 6583 /** Constructor. 6584 * 6585 * @param context Rendering context. 6586 * 6587 **/ 6588 FunctionalTest13::FunctionalTest13(deqp::Context& context) 6589 : TestCase(context, "subroutines_with_separate_shader_objects", 6590 "Verifies that subroutines work correctly when used in separate " 6591 "shader objects") 6592 , m_fbo_id(0) 6593 , m_pipeline_id(0) 6594 , m_read_buffer(DE_NULL) 6595 , m_to_height(4) 6596 , m_to_id(0) 6597 , m_to_width(4) 6598 , m_vao_id(0) 6599 , m_has_test_passed(true) 6600 { 6601 memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids)); 6602 memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids)); 6603 memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids)); 6604 memset(m_te_po_ids, 0, sizeof(m_te_po_ids)); 6605 memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids)); 6606 } 6607 6608 /** Deinitializes all GL objects that may have been created during test 6609 * execution, as well as releases all process-side buffers that may have 6610 * been allocated during the process. 6611 * The function also restores default GL state configuration. 6612 **/ 6613 void FunctionalTest13::deinit() 6614 { 6615 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6616 6617 if (m_fbo_id != 0) 6618 { 6619 gl.deleteFramebuffers(1, &m_fbo_id); 6620 6621 m_fbo_id = 0; 6622 } 6623 6624 if (m_pipeline_id != 0) 6625 { 6626 gl.deleteProgramPipelines(1, &m_pipeline_id); 6627 6628 m_pipeline_id = 0; 6629 } 6630 6631 if (m_read_buffer != DE_NULL) 6632 { 6633 delete[] m_read_buffer; 6634 6635 m_read_buffer = DE_NULL; 6636 } 6637 6638 for (unsigned int n_id = 0; n_id < 2 /* po id variants */; ++n_id) 6639 { 6640 if (m_fs_po_ids[n_id] != 0) 6641 { 6642 gl.deleteProgram(m_fs_po_ids[n_id]); 6643 6644 m_fs_po_ids[n_id] = 0; 6645 } 6646 6647 if (m_gs_po_ids[n_id] != 0) 6648 { 6649 gl.deleteProgram(m_gs_po_ids[n_id]); 6650 6651 m_gs_po_ids[n_id] = 0; 6652 } 6653 6654 if (m_tc_po_ids[n_id] != 0) 6655 { 6656 gl.deleteProgram(m_tc_po_ids[n_id]); 6657 6658 m_tc_po_ids[n_id] = 0; 6659 } 6660 6661 if (m_te_po_ids[n_id] != 0) 6662 { 6663 gl.deleteProgram(m_te_po_ids[n_id]); 6664 6665 m_te_po_ids[n_id] = 0; 6666 } 6667 6668 if (m_vs_po_ids[n_id] != 0) 6669 { 6670 gl.deleteProgram(m_vs_po_ids[n_id]); 6671 6672 m_vs_po_ids[n_id] = 0; 6673 } 6674 } /* for (both shader program object variants) */ 6675 6676 if (m_to_id != 0) 6677 { 6678 gl.deleteTextures(1, &m_to_id); 6679 6680 m_to_id = 0; 6681 } 6682 6683 if (m_vao_id != 0) 6684 { 6685 gl.deleteVertexArrays(1, &m_vao_id); 6686 6687 m_vao_id = 0; 6688 } 6689 6690 /* Restore default GL_PATCH_VERTICES setting value */ 6691 gl.patchParameteri(GL_PATCH_VERTICES, 3); 6692 6693 /* Restore default GL_PACK_ALIGNMENT setting value */ 6694 gl.pixelStorei(GL_PACK_ALIGNMENT, 4); 6695 } 6696 6697 /** Retrieves body of a fragment shader that should be used for the test. 6698 * The subroutine implementations are slightly changed, depending on the 6699 * index of the shader, as specified by the caller. 6700 * 6701 * @param n_id Index of the shader. 6702 * 6703 * @return Requested string. 6704 **/ 6705 std::string FunctionalTest13::getFragmentShaderBody(unsigned int n_id) 6706 { 6707 std::stringstream result_sstream; 6708 6709 /* Pre-amble */ 6710 result_sstream << "#version 400\n" 6711 "\n" 6712 "#extension GL_ARB_shader_subroutine : require\n" 6713 "\n" 6714 /* Sub-routine */ 6715 "subroutine void SubroutineFSType(inout vec4 result);\n" 6716 "\n" 6717 "subroutine(SubroutineFSType) void SubroutineFS1(inout vec4 result)\n" 6718 "{\n" 6719 " result += vec4(" 6720 << float(n_id + 1) / 10.0f << ", " << float(n_id + 2) / 10.0f << ", " << float(n_id + 3) / 10.0f 6721 << ", " << float(n_id + 4) / 10.0f 6722 << ");\n" 6723 "}\n" 6724 "subroutine(SubroutineFSType) void SubroutineFS2(inout vec4 result)\n" 6725 "{\n" 6726 " result += vec4(" 6727 << float(n_id + 1) / 20.0f << ", " << float(n_id + 2) / 20.0f << ", " << float(n_id + 3) / 20.0f 6728 << ", " << float(n_id + 4) / 20.0f << ");\n" 6729 "}\n" 6730 "\n" 6731 "subroutine uniform SubroutineFSType function;\n" 6732 "\n" 6733 /* Input block */ 6734 "in GS_DATA\n" 6735 "{\n" 6736 " vec4 data;\n" 6737 "} in_gs;\n" 6738 "\n" 6739 "out vec4 result;\n" 6740 /* main() declaration */ 6741 "void main()\n" 6742 "{\n" 6743 " vec4 data = in_gs.data;\n" 6744 " function(data);\n" 6745 "\n" 6746 " result = data;\n" 6747 "}\n"; 6748 6749 return result_sstream.str(); 6750 } 6751 6752 /** Retrieves body of a geometry shader that should be used for the test. 6753 * The subroutine implementations are slightly changed, depending on the 6754 * index of the shader, as specified by the caller. 6755 * 6756 * @param n_id Index of the shader. 6757 * 6758 * @return Requested string. 6759 **/ 6760 std::string FunctionalTest13::getGeometryShaderBody(unsigned int n_id) 6761 { 6762 std::stringstream result_sstream; 6763 6764 /* Pre-amble */ 6765 result_sstream << "#version 400\n" 6766 "\n" 6767 "#extension GL_ARB_shader_subroutine : require\n" 6768 "\n" 6769 "layout(points) in;\n" 6770 "layout(triangle_strip, max_vertices = 4) out;\n" 6771 /* Sub-routine */ 6772 "subroutine void SubroutineGSType(inout vec4 result);\n" 6773 "\n" 6774 "subroutine(SubroutineGSType) void SubroutineGS1(inout vec4 result)\n" 6775 "{\n" 6776 " result += vec4(0, 0, 0, " 6777 << float(n_id + 1) * 0.425f << ");\n" 6778 "}\n" 6779 "subroutine(SubroutineGSType) void SubroutineGS2(inout vec4 result)\n" 6780 "{\n" 6781 " result += vec4(0, 0, 0, " 6782 << float(n_id + 1) * 0.0425f << ");\n" 6783 "}\n" 6784 "\n" 6785 "subroutine uniform SubroutineGSType function;\n" 6786 "\n" 6787 /* Input block */ 6788 "in TE_DATA\n" 6789 "{\n" 6790 " vec4 data;\n" 6791 "} in_te[];\n" 6792 "\n" 6793 /* Output block */ 6794 "out GS_DATA\n" 6795 "{\n" 6796 " vec4 data;\n" 6797 "} out_gs;\n" 6798 "\n" 6799 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 6800 "out gl_PerVertex { vec4 gl_Position; };\n" 6801 /* main() declaration */ 6802 "void main()\n" 6803 "{\n" 6804 " vec4 data = in_te[0].data;\n" 6805 "\n" 6806 " function(data);\n" 6807 "\n" 6808 " gl_Position = vec4(1, -1, 0, 1);\n" 6809 " out_gs.data = data;\n" 6810 " EmitVertex();\n" 6811 "\n" 6812 " gl_Position = vec4(-1, -1, 0, 1);\n" 6813 " out_gs.data = data;\n" 6814 " EmitVertex();\n" 6815 "\n" 6816 " gl_Position = vec4(1, 1, 0, 1);\n" 6817 " out_gs.data = data;\n" 6818 " EmitVertex();\n" 6819 "\n" 6820 " gl_Position = vec4(-1, 1, 0, 1);\n" 6821 " out_gs.data = data;\n" 6822 " EmitVertex();\n" 6823 " EndPrimitive();\n" 6824 "}\n"; 6825 6826 return result_sstream.str(); 6827 } 6828 6829 /** Retrieves body of a tessellation control shader that should be used for the test. 6830 * The subroutine implementations are slightly changed, depending on the 6831 * index of the shader, as specified by the caller. 6832 * 6833 * @param n_id Index of the shader. 6834 * 6835 * @return Requested string. 6836 **/ 6837 std::string FunctionalTest13::getTessellationControlShaderBody(unsigned int n_id) 6838 { 6839 std::stringstream result_sstream; 6840 6841 /* Pre-amble */ 6842 result_sstream << "#version 400\n" 6843 "\n" 6844 "#extension GL_ARB_shader_subroutine : require\n" 6845 "\n" 6846 "layout(vertices = 4) out;\n" 6847 /* Sub-routine */ 6848 "subroutine void SubroutineTCType(inout vec4 result);\n" 6849 "\n" 6850 "subroutine(SubroutineTCType) void SubroutineTC1(inout vec4 result)\n" 6851 "{\n" 6852 " result += vec4(0, " 6853 << float(n_id + 1) * 0.25f << ", 0, 0);\n" 6854 "}\n" 6855 "subroutine(SubroutineTCType) void SubroutineTC2(inout vec4 result)\n" 6856 "{\n" 6857 " result += vec4(0, " 6858 << float(n_id + 1) * 0.025f 6859 << ", 0, 0);\n" 6860 "}\n" 6861 "\n" 6862 "subroutine uniform SubroutineTCType function;\n" 6863 "\n" 6864 /* Input block */ 6865 "in VS_DATA\n" 6866 "{\n" 6867 " vec4 data;\n" 6868 "} in_vs[];\n" 6869 "\n" 6870 /* Output block */ 6871 "out TC_DATA\n" 6872 "{\n" 6873 " vec4 data;\n" 6874 "} out_tc[];\n" 6875 "\n" 6876 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 6877 "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n" 6878 /* main() declaration */ 6879 "void main()\n" 6880 "{\n" 6881 " gl_TessLevelOuter[0] = 1.0;\n" 6882 " gl_TessLevelOuter[1] = 1.0;\n" 6883 " gl_TessLevelOuter[2] = 1.0;\n" 6884 " gl_TessLevelOuter[3] = 1.0;\n" 6885 " gl_TessLevelInner[0] = 1.0;\n" 6886 " gl_TessLevelInner[1] = 1.0;\n" 6887 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n" 6888 " out_tc[gl_InvocationID].data = in_vs[0].data;\n" 6889 "\n" 6890 " function(out_tc[gl_InvocationID].data);\n" 6891 "}\n"; 6892 6893 return result_sstream.str(); 6894 } 6895 6896 /** Retrieves body of a tessellation evaluation shader that should be used for the test. 6897 * The subroutine implementations are slightly changed, depending on the 6898 * index of the shader, as specified by the caller. 6899 * 6900 * @param n_id Index of the shader. 6901 * 6902 * @return Requested string. 6903 **/ 6904 std::string FunctionalTest13::getTessellationEvaluationShaderBody(unsigned int n_id) 6905 { 6906 std::stringstream result_sstream; 6907 6908 /* Pre-amble */ 6909 result_sstream << "#version 400\n" 6910 "\n" 6911 "#extension GL_ARB_shader_subroutine : require\n" 6912 "\n" 6913 "layout(quads, point_mode) in;\n" 6914 /* Sub-routine */ 6915 "subroutine void SubroutineTEType(inout vec4 result);\n" 6916 "\n" 6917 "subroutine(SubroutineTEType) void SubroutineTE1(inout vec4 result)\n" 6918 "{\n" 6919 " result += vec4(0, 0, " 6920 << float(n_id + 1) * 0.325f << ", 0);\n" 6921 "}\n" 6922 "subroutine(SubroutineTEType) void SubroutineTE2(inout vec4 result)\n" 6923 "{\n" 6924 " result += vec4(0, 0, " 6925 << float(n_id + 1) * 0.0325f << ", 0);\n" 6926 "}\n" 6927 "\n" 6928 "subroutine uniform SubroutineTEType function;\n" 6929 "\n" 6930 /* Input block */ 6931 "in TC_DATA\n" 6932 "{\n" 6933 " vec4 data;\n" 6934 "} in_tc[];\n" 6935 "\n" 6936 /* Output block */ 6937 "out TE_DATA\n" 6938 "{\n" 6939 " vec4 data;\n" 6940 "} out_te;\n" 6941 "\n" 6942 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 6943 "out gl_PerVertex { vec4 gl_Position; };\n" 6944 /* main() declaration */ 6945 "void main()\n" 6946 "{\n" 6947 " gl_Position = gl_in[0].gl_Position;\n" 6948 " out_te.data = in_tc[0].data;\n" 6949 "\n" 6950 " function(out_te.data);\n" 6951 "}\n"; 6952 6953 return result_sstream.str(); 6954 } 6955 6956 /** Retrieves body of a vertex shader that should be used for the test. 6957 * The subroutine implementations are slightly changed, depending on the 6958 * index of the shader, as specified by the caller. 6959 * 6960 * @param n_id Index of the shader. 6961 * 6962 * @return Requested string. 6963 **/ 6964 std::string FunctionalTest13::getVertexShaderBody(unsigned int n_id) 6965 { 6966 std::stringstream result_sstream; 6967 6968 /* Pre-amble */ 6969 result_sstream << "#version 400\n" 6970 "\n" 6971 "#extension GL_ARB_shader_subroutine : require\n" 6972 "\n" 6973 /* Sub-routine */ 6974 "subroutine void SubroutineVSType(inout vec4 result);\n" 6975 "\n" 6976 "subroutine(SubroutineVSType) void SubroutineVS1(inout vec4 result)\n" 6977 "{\n" 6978 " result += vec4(" 6979 << float(n_id + 1) * 0.125f << ", 0, 0, 0);\n" 6980 "}\n" 6981 "subroutine(SubroutineVSType) void SubroutineVS2(inout vec4 result)\n" 6982 "{\n" 6983 " result += vec4(" 6984 << float(n_id + 1) * 0.0125f << ", 0, 0, 0);\n" 6985 "}\n" 6986 "\n" 6987 "subroutine uniform SubroutineVSType function;\n" 6988 "\n" 6989 /* Output block */ 6990 "out VS_DATA\n" 6991 "{\n" 6992 " vec4 data;\n" 6993 "} out_vs;\n" 6994 "\n" 6995 "out gl_PerVertex { vec4 gl_Position; };\n" 6996 /* main() declaration */ 6997 "void main()\n" 6998 "{\n" 6999 " gl_Position = vec4(0, 0, 0, 1);\n" 7000 " out_vs.data = vec4(0);\n" 7001 "\n" 7002 " function(out_vs.data);\n" 7003 "\n" 7004 "}\n"; 7005 7006 return result_sstream.str(); 7007 } 7008 7009 /** Initializes all GL objects required to run the test. Also modifies a few 7010 * GL states in order for the test to run correctly. 7011 **/ 7012 void FunctionalTest13::initTest() 7013 { 7014 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7015 7016 /* Set up viewport */ 7017 gl.viewport(0 /* x */, 0 /* y */, m_to_width, m_to_height); 7018 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed."); 7019 7020 /* Make sure no program is used */ 7021 gl.useProgram(0); 7022 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 7023 7024 /* Generate a pipeline object */ 7025 gl.genProgramPipelines(1, &m_pipeline_id); 7026 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); 7027 7028 gl.bindProgramPipeline(m_pipeline_id); 7029 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 7030 7031 /* Initialize all shader programs */ 7032 for (unsigned int n_id = 0; n_id < 2 /* variants for each shader type */; ++n_id) 7033 { 7034 std::string fs_body = getFragmentShaderBody(n_id); 7035 const char* fs_body_raw_ptr = fs_body.c_str(); 7036 std::string gs_body = getGeometryShaderBody(n_id); 7037 const char* gs_body_raw_ptr = gs_body.c_str(); 7038 std::string tc_body = getTessellationControlShaderBody(n_id); 7039 const char* tc_body_raw_ptr = tc_body.c_str(); 7040 std::string te_body = getTessellationEvaluationShaderBody(n_id); 7041 const char* te_body_raw_ptr = te_body.c_str(); 7042 std::string vs_body = getVertexShaderBody(n_id); 7043 const char* vs_body_raw_ptr = vs_body.c_str(); 7044 7045 m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr); 7046 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7047 7048 m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr); 7049 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7050 7051 m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr); 7052 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7053 7054 m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr); 7055 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7056 7057 m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr); 7058 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7059 7060 /* Verify that all shader program objects have been linked successfully */ 7061 const glw::GLuint po_ids[] = { 7062 m_fs_po_ids[n_id], m_gs_po_ids[n_id], m_tc_po_ids[n_id], m_te_po_ids[n_id], m_vs_po_ids[n_id], 7063 }; 7064 const unsigned int n_po_ids = sizeof(po_ids) / sizeof(po_ids[0]); 7065 7066 for (unsigned int n_po_id = 0; n_po_id < n_po_ids; ++n_po_id) 7067 { 7068 glw::GLint link_status = GL_FALSE; 7069 glw::GLuint po_id = po_ids[n_po_id]; 7070 7071 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 7072 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 7073 7074 if (link_status != GL_TRUE) 7075 { 7076 TCU_FAIL("Shader program object linking failed."); 7077 } 7078 } /* for (all shader program objects) */ 7079 } /* for (both shader program object variants) */ 7080 7081 /* Generate a texture object. We will use the base mip-map as a render-target */ 7082 gl.genTextures(1, &m_to_id); 7083 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 7084 7085 gl.bindTexture(GL_TEXTURE_2D, m_to_id); 7086 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 7087 7088 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA32F, m_to_width, m_to_height); 7089 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed"); 7090 7091 /* Generate and configure a FBO we will use for the draw call */ 7092 gl.genFramebuffers(1, &m_fbo_id); 7093 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed."); 7094 7095 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 7096 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 7097 7098 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */); 7099 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 7100 7101 /* Generate & bind a VAO */ 7102 gl.genVertexArrays(1, &m_vao_id); 7103 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 7104 7105 gl.bindVertexArray(m_vao_id); 7106 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 7107 7108 /* Set up tessellation */ 7109 gl.patchParameteri(GL_PATCH_VERTICES, 1); 7110 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed."); 7111 7112 /* Set up pixel storage alignment */ 7113 gl.pixelStorei(GL_PACK_ALIGNMENT, 1); 7114 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed."); 7115 7116 /* Allocate enough space to hold color attachment data */ 7117 m_read_buffer = (unsigned char*)new float[m_to_width * m_to_height * 4 /* rgba */]; 7118 } 7119 7120 /** Executes test iteration. 7121 * 7122 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 7123 */ 7124 tcu::TestNode::IterateResult FunctionalTest13::iterate() 7125 { 7126 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7127 7128 /* Do not execute the test if GL_ARB_shader_subroutine and GL_ARB_separate_shader_objects 7129 * are not supported */ 7130 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 7131 { 7132 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 7133 } 7134 7135 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects")) 7136 { 7137 throw tcu::NotSupportedError("GL_ARB_separate_shader_objects is not supported"); 7138 } 7139 7140 /* Initialize all GL objects before we continue */ 7141 initTest(); 7142 7143 /* Iterate over all possible FS/GS/TC/TE/VS permutations */ 7144 for (int n_shader_permutation = 0; n_shader_permutation < 32 /* 2^5 */; ++n_shader_permutation) 7145 { 7146 const unsigned int n_fs_idx = ((n_shader_permutation & (1 << 0)) != 0) ? 1 : 0; 7147 const unsigned int n_gs_idx = ((n_shader_permutation & (1 << 1)) != 0) ? 1 : 0; 7148 const unsigned int n_tc_idx = ((n_shader_permutation & (1 << 2)) != 0) ? 1 : 0; 7149 const unsigned int n_te_idx = ((n_shader_permutation & (1 << 3)) != 0) ? 1 : 0; 7150 const unsigned int n_vs_idx = ((n_shader_permutation & (1 << 4)) != 0) ? 1 : 0; 7151 const unsigned int fs_po_id = m_fs_po_ids[n_fs_idx]; 7152 const unsigned int gs_po_id = m_gs_po_ids[n_gs_idx]; 7153 const unsigned int tc_po_id = m_tc_po_ids[n_tc_idx]; 7154 const unsigned int te_po_id = m_te_po_ids[n_te_idx]; 7155 const unsigned int vs_po_id = m_vs_po_ids[n_vs_idx]; 7156 7157 /* Configure fragment shader stage */ 7158 gl.useProgramStages(m_pipeline_id, GL_FRAGMENT_SHADER_BIT, fs_po_id); 7159 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_FRAGMENT_SHADER_BIT bit"); 7160 7161 /* Configure geometry shader stage */ 7162 gl.useProgramStages(m_pipeline_id, GL_GEOMETRY_SHADER_BIT, gs_po_id); 7163 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_GEOMETRY_SHADER_BIT bit"); 7164 7165 /* Configure tessellation control shader stage */ 7166 gl.useProgramStages(m_pipeline_id, GL_TESS_CONTROL_SHADER_BIT, tc_po_id); 7167 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_CONTROL_SHADER_BIT bit"); 7168 7169 /* Configure tessellation evaluation shader stage */ 7170 gl.useProgramStages(m_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT, te_po_id); 7171 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_EVALUATION_SHADER_BIT bit"); 7172 7173 /* Configure vertex shader stage */ 7174 gl.useProgramStages(m_pipeline_id, GL_VERTEX_SHADER_BIT, vs_po_id); 7175 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_VERTEX_SHADER_BIT bit"); 7176 7177 /* Validate the pipeline */ 7178 glw::GLint validate_status = GL_FALSE; 7179 7180 gl.validateProgramPipeline(m_pipeline_id); 7181 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed."); 7182 7183 gl.getProgramPipelineiv(m_pipeline_id, GL_VALIDATE_STATUS, &validate_status); 7184 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed."); 7185 7186 if (validate_status != GL_TRUE) 7187 { 7188 TCU_FAIL("Program pipeline has not been validated successfully."); 7189 } 7190 7191 /* Retrieve subroutine indices */ 7192 GLuint fs_subroutine_indices[2] = { (GLuint)-1 }; 7193 GLint fs_subroutine_uniform_index = 0; 7194 GLuint gs_subroutine_indices[2] = { (GLuint)-1 }; 7195 GLint gs_subroutine_uniform_index = 0; 7196 GLuint tc_subroutine_indices[2] = { (GLuint)-1 }; 7197 GLint tc_subroutine_uniform_index = 0; 7198 GLuint te_subroutine_indices[2] = { (GLuint)-1 }; 7199 GLint te_subroutine_uniform_index = 0; 7200 GLuint vs_subroutine_indices[2] = { (GLuint)-1 }; 7201 GLint vs_subroutine_uniform_index = 0; 7202 7203 for (unsigned int n_subroutine = 0; n_subroutine < 2; ++n_subroutine) 7204 { 7205 std::stringstream fs_subroutine_name_sstream; 7206 std::stringstream gs_subroutine_name_sstream; 7207 std::stringstream tc_subroutine_name_sstream; 7208 std::stringstream te_subroutine_name_sstream; 7209 std::stringstream vs_subroutine_name_sstream; 7210 7211 fs_subroutine_name_sstream << "SubroutineFS" << (n_subroutine + 1); 7212 gs_subroutine_name_sstream << "SubroutineGS" << (n_subroutine + 1); 7213 tc_subroutine_name_sstream << "SubroutineTC" << (n_subroutine + 1); 7214 te_subroutine_name_sstream << "SubroutineTE" << (n_subroutine + 1); 7215 vs_subroutine_name_sstream << "SubroutineVS" << (n_subroutine + 1); 7216 7217 fs_subroutine_indices[n_subroutine] = 7218 gl.getSubroutineIndex(fs_po_id, GL_FRAGMENT_SHADER, fs_subroutine_name_sstream.str().c_str()); 7219 gs_subroutine_indices[n_subroutine] = 7220 gl.getSubroutineIndex(gs_po_id, GL_GEOMETRY_SHADER, gs_subroutine_name_sstream.str().c_str()); 7221 tc_subroutine_indices[n_subroutine] = 7222 gl.getSubroutineIndex(tc_po_id, GL_TESS_CONTROL_SHADER, tc_subroutine_name_sstream.str().c_str()); 7223 te_subroutine_indices[n_subroutine] = 7224 gl.getSubroutineIndex(te_po_id, GL_TESS_EVALUATION_SHADER, te_subroutine_name_sstream.str().c_str()); 7225 vs_subroutine_indices[n_subroutine] = 7226 gl.getSubroutineIndex(vs_po_id, GL_VERTEX_SHADER, vs_subroutine_name_sstream.str().c_str()); 7227 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 7228 7229 if (fs_subroutine_indices[n_subroutine] == (GLuint)-1 || 7230 gs_subroutine_indices[n_subroutine] == (GLuint)-1 || 7231 tc_subroutine_indices[n_subroutine] == (GLuint)-1 || 7232 te_subroutine_indices[n_subroutine] == (GLuint)-1 || vs_subroutine_indices[n_subroutine] == (GLuint)-1) 7233 { 7234 m_testCtx.getLog() << tcu::TestLog::Message 7235 << "At least one subroutine was not recognized by glGetSubroutineIndex() call. " 7236 "(fs:" 7237 << fs_subroutine_indices[n_subroutine] 7238 << ", gs:" << gs_subroutine_indices[n_subroutine] 7239 << ", tc:" << tc_subroutine_indices[n_subroutine] 7240 << ", te:" << te_subroutine_indices[n_subroutine] 7241 << ", vs:" << vs_subroutine_indices[n_subroutine] << ")." 7242 << tcu::TestLog::EndMessage; 7243 7244 TCU_FAIL("At least one subroutine was not recognized"); 7245 } 7246 } /* for (both subroutines) */ 7247 7248 /* Retrieve subroutine uniform indices */ 7249 fs_subroutine_uniform_index = gl.getSubroutineUniformLocation(fs_po_id, GL_FRAGMENT_SHADER, "function"); 7250 gs_subroutine_uniform_index = gl.getSubroutineUniformLocation(gs_po_id, GL_GEOMETRY_SHADER, "function"); 7251 tc_subroutine_uniform_index = gl.getSubroutineUniformLocation(tc_po_id, GL_TESS_CONTROL_SHADER, "function"); 7252 te_subroutine_uniform_index = gl.getSubroutineUniformLocation(te_po_id, GL_TESS_EVALUATION_SHADER, "function"); 7253 vs_subroutine_uniform_index = gl.getSubroutineUniformLocation(vs_po_id, GL_VERTEX_SHADER, "function"); 7254 7255 if (fs_subroutine_uniform_index == -1 || gs_subroutine_uniform_index == -1 || 7256 tc_subroutine_uniform_index == -1 || te_subroutine_uniform_index == -1 || vs_subroutine_uniform_index == -1) 7257 { 7258 m_testCtx.getLog() << tcu::TestLog::Message << "At least one subroutine uniform is considered inactive by " 7259 "glGetSubroutineUniformLocation (" 7260 "fs:" 7261 << fs_subroutine_uniform_index << ", gs:" << gs_subroutine_uniform_index 7262 << ", tc:" << tc_subroutine_uniform_index << ", te:" << te_subroutine_uniform_index 7263 << ", vs:" << vs_subroutine_uniform_index << ")." << tcu::TestLog::EndMessage; 7264 7265 TCU_FAIL("At least one subroutine uniform is considered inactive"); 7266 } 7267 7268 /* Check if both subroutines work correctly in each stage */ 7269 for (int n_subroutine_permutation = 0; n_subroutine_permutation < 32; /* 2^5 */ 7270 ++n_subroutine_permutation) 7271 { 7272 unsigned int n_fs_subroutine = ((n_subroutine_permutation & (1 << 0)) != 0) ? 1 : 0; 7273 unsigned int n_gs_subroutine = ((n_subroutine_permutation & (1 << 1)) != 0) ? 1 : 0; 7274 unsigned int n_tc_subroutine = ((n_subroutine_permutation & (1 << 2)) != 0) ? 1 : 0; 7275 unsigned int n_te_subroutine = ((n_subroutine_permutation & (1 << 3)) != 0) ? 1 : 0; 7276 unsigned int n_vs_subroutine = ((n_subroutine_permutation & (1 << 4)) != 0) ? 1 : 0; 7277 7278 /* Configure subroutine uniforms */ 7279 struct 7280 { 7281 glw::GLenum stage; 7282 glw::GLuint po_id; 7283 glw::GLuint* indices; 7284 } configurations[] = { 7285 { GL_FRAGMENT_SHADER, fs_po_id, fs_subroutine_indices + n_fs_subroutine }, 7286 { GL_GEOMETRY_SHADER, gs_po_id, gs_subroutine_indices + n_gs_subroutine }, 7287 { GL_TESS_CONTROL_SHADER, tc_po_id, tc_subroutine_indices + n_tc_subroutine }, 7288 { GL_TESS_EVALUATION_SHADER, te_po_id, te_subroutine_indices + n_te_subroutine }, 7289 { GL_VERTEX_SHADER, vs_po_id, vs_subroutine_indices + n_vs_subroutine }, 7290 }; 7291 7292 for (int i = 0; i < 5; ++i) 7293 { 7294 gl.activeShaderProgram(m_pipeline_id, configurations[i].po_id); 7295 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveShaderProgram() call failed."); 7296 7297 gl.uniformSubroutinesuiv(configurations[i].stage, 1 /* count */, configurations[i].indices); 7298 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed."); 7299 } 7300 7301 /* Render a full-screen quad with the pipeline */ 7302 gl.clear(GL_COLOR_BUFFER_BIT); 7303 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed."); 7304 7305 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */); 7306 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 7307 7308 /* Read color attachment's contents */ 7309 gl.readPixels(0, /* x */ 7310 0, /* y */ 7311 m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_read_buffer); 7312 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 7313 7314 /* Verify the contents */ 7315 verifyReadBuffer(n_fs_idx, n_fs_subroutine, n_gs_idx, n_gs_subroutine, n_tc_idx, n_tc_subroutine, n_te_idx, 7316 n_te_subroutine, n_vs_idx, n_vs_subroutine); 7317 } /* for (all subroutine permutations) */ 7318 } /* for (all program shader object permutations) */ 7319 7320 /** All done */ 7321 if (m_has_test_passed) 7322 { 7323 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 7324 } 7325 else 7326 { 7327 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 7328 } 7329 7330 return STOP; 7331 } 7332 7333 /** Verifies the data that have been rendered using a pipeline object. 7334 * Contents of the data depends on indices of the shaders, as well as 7335 * on the subroutines that have been activated for particular iteration. 7336 * 7337 * @param n_fs_id Index of the fragment shader used for the iteration; 7338 * @param n_fs_subroutine Index of the subroutine used in the fragment shader 7339 * for the iteration; 7340 * @param n_gs_id Index of the geometry shader used for the iteration; 7341 * @param n_gs_subroutine Index of the subroutine used in the geometry shader 7342 * for the iteration; 7343 * @param n_tc_id Index of the tessellation control shader used for the iteration; 7344 * @param n_tc_subroutine Index of the subroutine used in the tessellation control 7345 * shader for the iteration; 7346 * @param n_te_id Index of the tessellation evaluation shader used for the iteration; 7347 * @param n_te_subroutine Index of the subroutine used in the tessellation evaluation 7348 * shader for the iteration; 7349 * @param n_vs_id Index of the vertex shader used for the iteration; 7350 * @param n_vs_subroutine Index of the subroutine used in the vertex shader for 7351 * the iteration. 7352 */ 7353 void FunctionalTest13::verifyReadBuffer(unsigned int n_fs_id, unsigned int n_fs_subroutine, unsigned int n_gs_id, 7354 unsigned int n_gs_subroutine, unsigned int n_tc_id, 7355 unsigned int n_tc_subroutine, unsigned int n_te_id, 7356 unsigned int n_te_subroutine, unsigned int n_vs_id, 7357 unsigned int n_vs_subroutine) 7358 { 7359 float expected_color[4] = { 0 }; 7360 float fs_modifier[4] = { 0 }; 7361 float gs_modifier[4] = { 0 }; 7362 float tc_modifier[4] = { 0 }; 7363 float te_modifier[4] = { 0 }; 7364 float vs_modifier[4] = { 0 }; 7365 7366 if (n_fs_subroutine == 0) 7367 { 7368 for (unsigned int n_component = 0; n_component < 4; ++n_component) 7369 { 7370 fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 10.0f; 7371 } 7372 } 7373 else 7374 { 7375 for (unsigned int n_component = 0; n_component < 4; ++n_component) 7376 { 7377 fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 20.0f; 7378 } 7379 } 7380 7381 if (n_gs_subroutine == 0) 7382 { 7383 gs_modifier[3] = float(n_gs_id + 1) * 0.425f; 7384 } 7385 else 7386 { 7387 gs_modifier[3] = float(n_gs_id + 1) * 0.0425f; 7388 } 7389 7390 if (n_tc_subroutine == 0) 7391 { 7392 tc_modifier[1] = float(n_tc_id + 1) * 0.25f; 7393 } 7394 else 7395 { 7396 tc_modifier[1] = float(n_tc_id + 1) * 0.025f; 7397 } 7398 7399 if (n_te_subroutine == 0) 7400 { 7401 te_modifier[2] = float(n_te_id + 1) * 0.325f; 7402 } 7403 else 7404 { 7405 te_modifier[2] = float(n_te_id + 1) * 0.0325f; 7406 } 7407 7408 if (n_vs_subroutine == 0) 7409 { 7410 vs_modifier[0] = float(n_vs_id + 1) * 0.125f; 7411 } 7412 else 7413 { 7414 vs_modifier[0] = float(n_vs_id + 1) * 0.0125f; 7415 } 7416 7417 /* Determine the expected color */ 7418 for (unsigned int n_component = 0; n_component < 4 /* rgba */; ++n_component) 7419 { 7420 expected_color[n_component] = fs_modifier[n_component] + gs_modifier[n_component] + tc_modifier[n_component] + 7421 te_modifier[n_component] + vs_modifier[n_component]; 7422 } 7423 7424 /* Verify all read texels are valid */ 7425 const float epsilon = 1e-5f; 7426 bool should_continue = true; 7427 7428 for (unsigned int y = 0; y < m_to_height && should_continue; ++y) 7429 { 7430 const float* row_ptr = (const float*)m_read_buffer + y * m_to_width * 4; /* rgba */ 7431 7432 for (unsigned int x = 0; x < m_to_width && should_continue; ++x) 7433 { 7434 const float* texel_ptr = row_ptr + x * 4; /* rgba */ 7435 7436 if (de::abs(texel_ptr[0] - expected_color[0]) > epsilon || 7437 de::abs(texel_ptr[1] - expected_color[1]) > epsilon || 7438 de::abs(texel_ptr[2] - expected_color[2]) > epsilon || 7439 de::abs(texel_ptr[3] - expected_color[3]) > epsilon) 7440 { 7441 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel rendered at (" << x << ", " << y 7442 << ") for " 7443 "the following configuration: " 7444 "n_fs_id:" 7445 << n_fs_id << " n_fs_subroutine:" << n_fs_subroutine << " n_gs_id:" << n_gs_id 7446 << " n_gs_subroutine:" << n_gs_subroutine << " n_tc_id:" << n_tc_id 7447 << " n_tc_subroutine:" << n_tc_subroutine << " n_te_id:" << n_te_id 7448 << " n_te_subroutine:" << n_te_subroutine << " n_vs_id:" << n_vs_id 7449 << " n_vs_subroutine:" << n_vs_subroutine << "; expected:" 7450 "(" 7451 << expected_color[0] << ", " << expected_color[1] << ", " << expected_color[2] 7452 << ", " << expected_color[3] << "), found:" 7453 "(" 7454 << texel_ptr[0] << ", " << texel_ptr[1] << ", " << texel_ptr[2] << ", " 7455 << texel_ptr[3] << ")." << tcu::TestLog::EndMessage; 7456 7457 m_has_test_passed = false; 7458 should_continue = false; 7459 } 7460 } /* for (all columns) */ 7461 } /* for (all rows) */ 7462 } 7463 7464 /** Constructor 7465 * 7466 * @param context CTS context 7467 **/ 7468 FunctionalTest14_15::FunctionalTest14_15(deqp::Context& context) 7469 : TestCase(context, "structure_parameters_program_binary", "Verify structures can be used as parameters") 7470 , m_uniform_location(0) 7471 { 7472 } 7473 7474 /** Execute test 7475 * 7476 * @return tcu::TestNode::STOP 7477 **/ 7478 tcu::TestNode::IterateResult FunctionalTest14_15::iterate() 7479 { 7480 static const GLchar* vertex_shader_code = 7481 "#version 400 core\n" 7482 "#extension GL_ARB_shader_subroutine : require\n" 7483 "\n" 7484 "precision highp float;\n" 7485 "\n" 7486 "struct data\n" 7487 "{\n" 7488 " uint r;\n" 7489 " uint g;\n" 7490 " uint b;\n" 7491 " uint a;\n" 7492 "};\n" 7493 "\n" 7494 "subroutine void routine_type_1(in data iparam, out data oparam);\n" 7495 "subroutine void routine_type_2(inout data arg);\n" 7496 "\n" 7497 "subroutine (routine_type_1) void invert(in data iparam, out data oparam)\n" 7498 "{\n" 7499 " oparam.r = iparam.a;\n" 7500 " oparam.g = iparam.b;\n" 7501 " oparam.b = iparam.g;\n" 7502 " oparam.a = iparam.r;\n" 7503 "}\n" 7504 "\n" 7505 "subroutine (routine_type_1) void increment(in data iparam, out data oparam)\n" 7506 "{\n" 7507 " oparam.r = 1 + iparam.r;\n" 7508 " oparam.g = 1 + iparam.g;\n" 7509 " oparam.b = 1 + iparam.b;\n" 7510 " oparam.a = 1 + iparam.a;\n" 7511 "}\n" 7512 "\n" 7513 "subroutine (routine_type_2) void div_by_2(inout data arg)\n" 7514 "{\n" 7515 " arg.r = arg.r / 2;\n" 7516 " arg.g = arg.g / 2;\n" 7517 " arg.b = arg.b / 2;\n" 7518 " arg.a = arg.a / 2;\n" 7519 "}\n" 7520 "\n" 7521 "subroutine (routine_type_2) void decrement(inout data arg)\n" 7522 "{\n" 7523 " arg.r = arg.r - 1;\n" 7524 " arg.g = arg.g - 1;\n" 7525 " arg.b = arg.b - 1;\n" 7526 " arg.a = arg.a - 1;\n" 7527 "}\n" 7528 "\n" 7529 "subroutine uniform routine_type_1 routine_1;\n" 7530 "subroutine uniform routine_type_2 routine_2;\n" 7531 "\n" 7532 "uniform uvec4 uni_input;\n" 7533 "\n" 7534 "out uvec4 out_routine_1;\n" 7535 "out uvec4 out_routine_2;\n" 7536 "\n" 7537 "\n" 7538 "void main()\n" 7539 "{\n" 7540 " data routine_1_input;\n" 7541 " data routine_1_output;\n" 7542 " data routine_2_arg;\n" 7543 "\n" 7544 " routine_1_input.r = uni_input.r;\n" 7545 " routine_1_input.g = uni_input.g;\n" 7546 " routine_1_input.b = uni_input.b;\n" 7547 " routine_1_input.a = uni_input.a;\n" 7548 "\n" 7549 " routine_2_arg.r = uni_input.r;\n" 7550 " routine_2_arg.g = uni_input.g;\n" 7551 " routine_2_arg.b = uni_input.b;\n" 7552 " routine_2_arg.a = uni_input.a;\n" 7553 "\n" 7554 " routine_1(routine_1_input, routine_1_output);\n" 7555 " routine_2(routine_2_arg);\n" 7556 "\n" 7557 " out_routine_1.r = routine_1_output.r;\n" 7558 " out_routine_1.g = routine_1_output.g;\n" 7559 " out_routine_1.b = routine_1_output.b;\n" 7560 " out_routine_1.a = routine_1_output.a;\n" 7561 "\n" 7562 " out_routine_2.r = routine_2_arg.r;\n" 7563 " out_routine_2.g = routine_2_arg.g;\n" 7564 " out_routine_2.b = routine_2_arg.b;\n" 7565 " out_routine_2.a = routine_2_arg.a;\n" 7566 "}\n" 7567 "\n"; 7568 7569 static const GLchar* subroutine_names[][2] = { { "invert", "increment" }, { "div_by_2", "decrement" } }; 7570 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 7571 7572 static const GLchar* subroutine_uniform_names[] = { "routine_1", "routine_2" }; 7573 static const GLuint n_subroutine_uniform_names = 7574 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]); 7575 7576 static const GLchar* uniform_name = "uni_input"; 7577 static const GLchar* varying_names[] = { "out_routine_1", "out_routine_2" }; 7578 7579 static const GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]); 7580 static const GLuint transform_feedback_buffer_size = n_varying_names * 4 * sizeof(GLuint); 7581 7582 /* Test data */ 7583 static const Utils::vec4<GLuint> uni_input[] = { Utils::vec4<GLuint>(8, 64, 4096, 16777216), 7584 Utils::vec4<GLuint>(8, 64, 4096, 16777216) }; 7585 7586 static const Utils::vec4<GLuint> out_routine_1[] = { Utils::vec4<GLuint>(16777216, 4096, 64, 8), 7587 Utils::vec4<GLuint>(9, 65, 4097, 16777217) }; 7588 7589 static const Utils::vec4<GLuint> out_routine_2[] = { Utils::vec4<GLuint>(4, 32, 2048, 8388608), 7590 Utils::vec4<GLuint>(7, 63, 4095, 16777215) }; 7591 7592 static const GLuint n_test_cases = 2; 7593 7594 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 7595 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 7596 { 7597 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 7598 } 7599 7600 /* GL objects */ 7601 Utils::program program(m_context); 7602 Utils::buffer transform_feedback_buffer(m_context); 7603 Utils::vertexArray vao(m_context); 7604 7605 bool is_program_binary_supported = program.isProgramBinarySupported(); 7606 7607 /* Init GL objects */ 7608 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, 7609 varying_names /* varying_names */, n_varying_names /* n_varyings */); 7610 7611 /* Do not execute the test if GL_ARB_get_program_binary is not supported */ 7612 if (true == is_program_binary_supported) 7613 { 7614 /* Get subroutine indices */ 7615 for (GLuint type = 0; type < n_subroutine_types; ++type) 7616 { 7617 m_initial_subroutine_indices[type][0] = 7618 program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER); 7619 7620 m_initial_subroutine_indices[type][1] = 7621 program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER); 7622 } 7623 7624 /* Get subroutine uniform locations */ 7625 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 7626 { 7627 m_initial_subroutine_uniform_locations[uniform] = 7628 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER); 7629 } 7630 7631 /* Delete program and recreate it from binary */ 7632 std::vector<GLubyte> program_binary; 7633 GLenum binary_format; 7634 7635 program.getBinary(program_binary, binary_format); 7636 program.remove(); 7637 program.createFromBinary(program_binary, binary_format); 7638 } 7639 7640 program.use(); 7641 7642 vao.generate(); 7643 vao.bind(); 7644 7645 transform_feedback_buffer.generate(); 7646 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 7647 GL_DYNAMIC_COPY); 7648 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 7649 7650 /* Get subroutine indices */ 7651 for (GLuint type = 0; type < n_subroutine_types; ++type) 7652 { 7653 m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER); 7654 m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER); 7655 } 7656 7657 /* Get subroutine uniform locations */ 7658 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 7659 { 7660 m_subroutine_uniform_locations[uniform] = 7661 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER); 7662 } 7663 7664 /* Get uniform locations */ 7665 m_uniform_location = program.getUniformLocation(uniform_name); 7666 7667 /* Test */ 7668 bool result = true; 7669 7670 /* Test program binary */ 7671 if (true == is_program_binary_supported) 7672 { 7673 /* Test indices and locations */ 7674 if (false == testIndicesAndLocations()) 7675 { 7676 static const GLuint n_subroutines_per_type = 2; 7677 7678 m_context.getTestContext().getLog() << tcu::TestLog::Message 7679 << "Error. Subroutine indices or subroutine uniform location changed." 7680 << tcu::TestLog::EndMessage; 7681 7682 for (GLuint type = 0; type < n_subroutine_types; ++type) 7683 { 7684 for (GLuint i = 0; i < n_subroutines_per_type; ++i) 7685 { 7686 m_context.getTestContext().getLog() 7687 << tcu::TestLog::Message << "Subroutine: " << subroutine_names[type][i] 7688 << " index: " << m_subroutine_indices[type][i] 7689 << " initial index: " << m_initial_subroutine_indices[type][i] << tcu::TestLog::EndMessage; 7690 } 7691 } 7692 7693 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 7694 { 7695 m_context.getTestContext().getLog() 7696 << tcu::TestLog::Message << "Subroutine uniform: " << subroutine_uniform_names[uniform] 7697 << " location: " << m_subroutine_uniform_locations[uniform] 7698 << " initial location: " << m_initial_subroutine_uniform_locations[uniform] 7699 << tcu::TestLog::EndMessage; 7700 } 7701 7702 result = false; 7703 } 7704 7705 /* Test draw with deafult set of subroutines */ 7706 if (false == testDefaultSubroutineSet(uni_input[0], out_routine_1, out_routine_2)) 7707 { 7708 result = false; 7709 } 7710 } 7711 7712 for (GLuint i = 0; i < n_test_cases; ++i) 7713 { 7714 if (false == testDraw(i, uni_input[i], out_routine_1[i], out_routine_2[i])) 7715 { 7716 result = false; 7717 } 7718 } 7719 7720 /* Set result */ 7721 if (true == result) 7722 { 7723 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 7724 } 7725 else 7726 { 7727 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 7728 } 7729 7730 /* Done */ 7731 return tcu::TestNode::STOP; 7732 } 7733 7734 /** Execute draw call and verify results 7735 * 7736 * @param uni_input Input data 7737 * @param expected_routine_1_result Set of expected results of "routine_1" 7738 * @param expected_routine_2_result Set of expected results of "routine_2" 7739 * 7740 * @return true if test pass, false otherwise 7741 **/ 7742 bool FunctionalTest14_15::testDefaultSubroutineSet(const Utils::vec4<glw::GLuint>& uni_input, 7743 const Utils::vec4<glw::GLuint> expected_routine_1_result[2], 7744 const Utils::vec4<glw::GLuint> expected_routine_2_result[2]) const 7745 { 7746 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7747 bool result = true; 7748 7749 /* Set up input data uniforms */ 7750 gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w); 7751 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 7752 7753 /* Execute draw call with transform feedback */ 7754 gl.beginTransformFeedback(GL_POINTS); 7755 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 7756 7757 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 7758 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 7759 7760 gl.endTransformFeedback(); 7761 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 7762 7763 /* Capture results */ 7764 GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 7765 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 7766 7767 Utils::vec4<GLuint> routine_1_result; 7768 Utils::vec4<GLuint> routine_2_result; 7769 7770 routine_1_result.m_x = feedback_data[0 + 0]; 7771 routine_1_result.m_y = feedback_data[0 + 1]; 7772 routine_1_result.m_z = feedback_data[0 + 2]; 7773 routine_1_result.m_w = feedback_data[0 + 3]; 7774 7775 routine_2_result.m_x = feedback_data[4 + 0]; 7776 routine_2_result.m_y = feedback_data[4 + 1]; 7777 routine_2_result.m_z = feedback_data[4 + 2]; 7778 routine_2_result.m_w = feedback_data[4 + 3]; 7779 7780 /* Unmap buffer */ 7781 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 7782 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 7783 7784 /* Verifiy */ 7785 result = result && 7786 ((routine_1_result == expected_routine_1_result[0]) || (routine_1_result == expected_routine_1_result[1])); 7787 7788 result = result && 7789 ((routine_2_result == expected_routine_2_result[0]) || (routine_2_result == expected_routine_2_result[1])); 7790 7791 /* Log error if any */ 7792 if (false == result) 7793 { 7794 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 7795 << tcu::TestLog::EndMessage; 7796 7797 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 7798 7799 message << "Routine_1, result: "; 7800 7801 routine_1_result.log(message); 7802 7803 message << "Routine_2, result: "; 7804 7805 routine_2_result.log(message); 7806 7807 message << tcu::TestLog::EndMessage; 7808 } 7809 7810 /* Done */ 7811 return result; 7812 } 7813 7814 /** Execute draw call and verify results 7815 * 7816 * @param routine_configuration Subroutine "type" ordinal 7817 * @param uni_input Input data 7818 * @param expected_routine_1_result Expected results of "routine_1" 7819 * @param expected_routine_2_result Expected results of "routine_2" 7820 * 7821 * @return true if test pass, false otherwise 7822 **/ 7823 bool FunctionalTest14_15::testDraw(glw::GLuint routine_configuration, const Utils::vec4<glw::GLuint>& uni_input, 7824 const Utils::vec4<glw::GLuint>& expected_routine_1_result, 7825 const Utils::vec4<glw::GLuint>& expected_routine_2_result) const 7826 { 7827 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7828 bool result = true; 7829 GLuint subroutine_indices[2]; 7830 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 7831 7832 /* Set up input data uniforms */ 7833 gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w); 7834 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 7835 7836 /* Prepare subroutine uniform data */ 7837 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 7838 { 7839 const GLuint location = m_subroutine_uniform_locations[i]; 7840 7841 subroutine_indices[location] = m_subroutine_indices[i][routine_configuration]; 7842 } 7843 7844 /* Set up subroutine uniforms */ 7845 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]); 7846 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 7847 7848 /* Execute draw call with transform feedback */ 7849 gl.beginTransformFeedback(GL_POINTS); 7850 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 7851 7852 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 7853 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 7854 7855 gl.endTransformFeedback(); 7856 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 7857 7858 /* Capture results */ 7859 GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 7860 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 7861 7862 Utils::vec4<GLuint> routine_1_result; 7863 Utils::vec4<GLuint> routine_2_result; 7864 7865 routine_1_result.m_x = feedback_data[0 + 0]; 7866 routine_1_result.m_y = feedback_data[0 + 1]; 7867 routine_1_result.m_z = feedback_data[0 + 2]; 7868 routine_1_result.m_w = feedback_data[0 + 3]; 7869 7870 routine_2_result.m_x = feedback_data[4 + 0]; 7871 routine_2_result.m_y = feedback_data[4 + 1]; 7872 routine_2_result.m_z = feedback_data[4 + 2]; 7873 routine_2_result.m_w = feedback_data[4 + 3]; 7874 7875 /* Unmap buffer */ 7876 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 7877 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 7878 7879 /* Verifiy */ 7880 result = result && (routine_1_result == expected_routine_1_result); 7881 result = result && (routine_2_result == expected_routine_2_result); 7882 7883 /* Log error if any */ 7884 if (false == result) 7885 { 7886 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 7887 << tcu::TestLog::EndMessage; 7888 7889 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 7890 7891 message << "Routine_1, result: "; 7892 7893 routine_1_result.log(message); 7894 7895 message << ", expected: "; 7896 7897 expected_routine_1_result.log(message); 7898 7899 message << "Routine_2, result: "; 7900 7901 routine_2_result.log(message); 7902 7903 message << ", expected: "; 7904 7905 expected_routine_2_result.log(message); 7906 7907 message << tcu::TestLog::EndMessage; 7908 } 7909 7910 /* Done */ 7911 return result; 7912 } 7913 7914 /** Verify initial and current values of subroutine indices and subroutines uniform locations 7915 * 7916 * @return true if test pass, false otherwise 7917 **/ 7918 bool FunctionalTest14_15::testIndicesAndLocations() const 7919 { 7920 static const GLuint n_subroutine_types = 2; 7921 bool result = true; 7922 7923 /* Verify subroutine indices */ 7924 for (GLuint type = 0; type < n_subroutine_types; ++type) 7925 { 7926 result = result && (m_subroutine_indices[type][0] == m_initial_subroutine_indices[type][0]); 7927 result = result && (m_subroutine_indices[type][1] == m_initial_subroutine_indices[type][1]); 7928 } 7929 7930 /* Verify subroutine uniform locations */ 7931 for (GLuint uniform = 0; uniform < n_subroutine_types; ++uniform) 7932 { 7933 result = result && (m_subroutine_uniform_locations[uniform] == m_initial_subroutine_uniform_locations[uniform]); 7934 } 7935 7936 return result; 7937 } 7938 7939 /** Constructor. 7940 * 7941 * @param context Rendering context. 7942 * 7943 **/ 7944 FunctionalTest16::FunctionalTest16(deqp::Context& context) 7945 : TestCase(context, "subroutine_uniform_reset", 7946 "Checks that when the active program for a shader stage is re-linke or " 7947 "changed by a call to UseProgram, BindProgramPipeline, or UseProgramStages," 7948 " subroutine uniforms for that stage are reset to arbitrarily chosen default " 7949 "functions with compatible subroutine types.") 7950 , m_are_pipeline_objects_supported(false) 7951 , m_has_test_passed(true) 7952 { 7953 memset(m_fs_ids, 0, sizeof(m_fs_ids)); 7954 memset(m_gs_ids, 0, sizeof(m_gs_ids)); 7955 memset(m_po_ids, 0, sizeof(m_po_ids)); 7956 memset(m_tc_ids, 0, sizeof(m_tc_ids)); 7957 memset(m_te_ids, 0, sizeof(m_te_ids)); 7958 memset(m_vs_ids, 0, sizeof(m_vs_ids)); 7959 7960 memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids)); 7961 memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids)); 7962 memset(m_pipeline_object_ids, 0, sizeof(m_pipeline_object_ids)); 7963 memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids)); 7964 memset(m_te_po_ids, 0, sizeof(m_te_po_ids)); 7965 memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids)); 7966 } 7967 7968 /** Deinitializes all GL objects that may have been created during test execution. */ 7969 void FunctionalTest16::deinit() 7970 { 7971 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7972 7973 for (unsigned int n_id = 0; n_id < 2; ++n_id) 7974 { 7975 if (m_fs_ids[n_id] != 0) 7976 { 7977 gl.deleteShader(m_fs_ids[n_id]); 7978 7979 m_fs_ids[n_id] = 0; 7980 } 7981 7982 if (m_fs_po_ids[n_id] != 0) 7983 { 7984 gl.deleteProgram(m_fs_po_ids[n_id]); 7985 7986 m_fs_po_ids[n_id] = 0; 7987 } 7988 7989 if (m_gs_ids[n_id] != 0) 7990 { 7991 gl.deleteShader(m_gs_ids[n_id]); 7992 7993 m_gs_ids[n_id] = 0; 7994 } 7995 7996 if (m_gs_po_ids[n_id] != 0) 7997 { 7998 gl.deleteProgram(m_gs_po_ids[n_id]); 7999 8000 m_gs_po_ids[n_id] = 0; 8001 } 8002 8003 if (m_pipeline_object_ids[n_id] != 0) 8004 { 8005 gl.deleteProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id); 8006 } 8007 8008 if (m_po_ids[n_id] != 0) 8009 { 8010 gl.deleteProgram(m_po_ids[n_id]); 8011 8012 m_po_ids[n_id] = 0; 8013 } 8014 8015 if (m_tc_ids[n_id] != 0) 8016 { 8017 gl.deleteShader(m_tc_ids[n_id]); 8018 8019 m_tc_ids[n_id] = 0; 8020 } 8021 8022 if (m_tc_po_ids[n_id] != 0) 8023 { 8024 gl.deleteProgram(m_tc_po_ids[n_id]); 8025 8026 m_tc_po_ids[n_id] = 0; 8027 } 8028 8029 if (m_te_ids[n_id] != 0) 8030 { 8031 gl.deleteShader(m_te_ids[n_id]); 8032 8033 m_te_ids[n_id] = 0; 8034 } 8035 8036 if (m_te_po_ids[n_id] != 0) 8037 { 8038 gl.deleteProgram(m_te_po_ids[n_id]); 8039 8040 m_te_po_ids[n_id] = 0; 8041 } 8042 8043 if (m_vs_ids[n_id] != 0) 8044 { 8045 gl.deleteShader(m_vs_ids[n_id]); 8046 8047 m_vs_ids[n_id] = 0; 8048 } 8049 8050 if (m_vs_po_ids[n_id] != 0) 8051 { 8052 gl.deleteProgram(m_vs_po_ids[n_id]); 8053 8054 m_vs_po_ids[n_id] = 0; 8055 } 8056 } /* for (both IDs) */ 8057 } 8058 8059 /** Retrieves body of a shader that should be used for user-specified shader stage. 8060 * This function returns slightly different implementations, depending on index of 8061 * the program/pipeline object the shader will be used for. 8062 * 8063 * @param shader_stage Stage the shader body is to be returned for. 8064 * @param n_id Index of the shader (as per description). 8065 * 8066 * @return Requested string. 8067 **/ 8068 std::string FunctionalTest16::getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_id) const 8069 { 8070 std::stringstream result_sstream; 8071 8072 result_sstream << "#version 400\n" 8073 "\n" 8074 "#extension GL_ARB_shader_subroutine : require\n" 8075 "\n"; 8076 8077 switch (shader_stage) 8078 { 8079 case Utils::SHADER_STAGE_VERTEX: 8080 { 8081 result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n"; 8082 break; 8083 } 8084 case Utils::SHADER_STAGE_GEOMETRY: 8085 { 8086 result_sstream << "layout(points) in;\n" 8087 "layout(points, max_vertices = 1) out;\n"; 8088 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"; 8089 result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n"; 8090 break; 8091 } 8092 8093 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 8094 { 8095 result_sstream << "layout(vertices = 4) out;\n"; 8096 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"; 8097 result_sstream << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"; 8098 break; 8099 } 8100 8101 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 8102 { 8103 result_sstream << "layout(quads) in;\n"; 8104 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"; 8105 result_sstream << "out gl_PerVertex { vec4 gl_Position; };\n"; 8106 break; 8107 } 8108 8109 default: 8110 break; 8111 } /* switch (shader_stage) */ 8112 8113 result_sstream << "\n" 8114 "subroutine void subroutineType (inout vec4 result);\n" 8115 "subroutine vec4 subroutineType2(in vec4 data);\n" 8116 "\n" 8117 "subroutine(subroutineType) void function1(inout vec4 result)\n" 8118 "{\n" 8119 " result += vec4(" 8120 << (n_id + 1) << ", " << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4) 8121 << ");\n" 8122 "}\n" 8123 "subroutine(subroutineType) void function2(inout vec4 result)\n" 8124 "{\n" 8125 " result += vec4(" 8126 << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4) << ", " << (n_id + 5) 8127 << ");\n" 8128 "}\n" 8129 "\n" 8130 "subroutine(subroutineType2) vec4 function3(in vec4 data)\n" 8131 "{\n" 8132 " return data * data;\n" 8133 "}\n" 8134 "subroutine(subroutineType2) vec4 function4(in vec4 data)\n" 8135 "{\n" 8136 " return data + data;\n" 8137 "}\n" 8138 "\n" 8139 "subroutine uniform subroutineType subroutine1;\n" 8140 "subroutine uniform subroutineType subroutine2;\n" 8141 "subroutine uniform subroutineType2 subroutine3;\n" 8142 "subroutine uniform subroutineType2 subroutine4;\n" 8143 "\n"; 8144 8145 if (shader_stage == Utils::SHADER_STAGE_FRAGMENT) 8146 { 8147 result_sstream << "out vec4 result;\n"; 8148 } 8149 8150 result_sstream << "void main()\n" 8151 "{\n"; 8152 8153 switch (shader_stage) 8154 { 8155 case Utils::SHADER_STAGE_FRAGMENT: 8156 { 8157 result_sstream << " result = vec4(0);\n" 8158 << " subroutine1(result);\n" 8159 " subroutine2(result);\n" 8160 " result = subroutine3(result) + subroutine4(result);\n"; 8161 8162 break; 8163 } 8164 8165 case Utils::SHADER_STAGE_GEOMETRY: 8166 { 8167 result_sstream << " gl_Position = vec4(0);\n" 8168 " subroutine1(gl_Position);\n" 8169 " subroutine2(gl_Position);\n" 8170 " gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n" 8171 " EmitVertex();\n"; 8172 8173 break; 8174 } 8175 8176 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 8177 { 8178 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0);\n" 8179 " subroutine1(gl_out[gl_InvocationID].gl_Position);\n" 8180 " subroutine2(gl_out[gl_InvocationID].gl_Position);\n" 8181 " gl_out[gl_InvocationID].gl_Position = subroutine3(gl_in[0].gl_Position) + " 8182 "subroutine4(gl_in[0].gl_Position);\n"; 8183 8184 break; 8185 } 8186 8187 case Utils::SHADER_STAGE_VERTEX: 8188 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 8189 { 8190 result_sstream << " gl_Position = vec4(0);\n" 8191 " subroutine1(gl_Position);\n" 8192 " subroutine2(gl_Position);\n" 8193 " gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n"; 8194 8195 break; 8196 } 8197 8198 default: 8199 break; 8200 } /* switch (shader_stage) */ 8201 8202 result_sstream << "}\n"; 8203 8204 return result_sstream.str(); 8205 } 8206 8207 /** Initializes all objects required to run the test. */ 8208 void FunctionalTest16::initTest() 8209 { 8210 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8211 8212 for (unsigned int n_id = 0; n_id < 2 /* test program/shader objects */; ++n_id) 8213 { 8214 const std::string fs_body = getShaderBody(Utils::SHADER_STAGE_FRAGMENT, n_id); 8215 const std::string gs_body = getShaderBody(Utils::SHADER_STAGE_GEOMETRY, n_id); 8216 const std::string tc_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_CONTROL, n_id); 8217 const std::string te_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_EVALUATION, n_id); 8218 const std::string vs_body = getShaderBody(Utils::SHADER_STAGE_VERTEX, n_id); 8219 8220 if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */ 8221 DE_NULL, /* n_xfb_varyings */ 8222 m_vs_ids + n_id, m_tc_ids + n_id, m_te_ids + n_id, m_gs_ids + n_id, m_fs_ids + n_id, 8223 m_po_ids + n_id)) 8224 { 8225 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build test program object, index:" 8226 "[" 8227 << n_id << "]" << tcu::TestLog::EndMessage; 8228 8229 TCU_FAIL("Failed to build a test program"); 8230 } 8231 8232 if (m_are_pipeline_objects_supported) 8233 { 8234 /* Initialize shader program objects */ 8235 const char* fs_body_raw_ptr = fs_body.c_str(); 8236 const char* gs_body_raw_ptr = gs_body.c_str(); 8237 glw::GLint link_status[5] = { GL_FALSE }; 8238 const char* tc_body_raw_ptr = tc_body.c_str(); 8239 const char* te_body_raw_ptr = te_body.c_str(); 8240 const char* vs_body_raw_ptr = vs_body.c_str(); 8241 8242 m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr); 8243 m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr); 8244 m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr); 8245 m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr); 8246 m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr); 8247 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 8248 8249 gl.getProgramiv(m_fs_po_ids[n_id], GL_LINK_STATUS, link_status + 0); 8250 gl.getProgramiv(m_gs_po_ids[n_id], GL_LINK_STATUS, link_status + 1); 8251 gl.getProgramiv(m_tc_po_ids[n_id], GL_LINK_STATUS, link_status + 2); 8252 gl.getProgramiv(m_te_po_ids[n_id], GL_LINK_STATUS, link_status + 3); 8253 gl.getProgramiv(m_vs_po_ids[n_id], GL_LINK_STATUS, link_status + 4); 8254 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 8255 8256 if (link_status[0] == GL_FALSE) 8257 TCU_FAIL("Fragment shader program failed to link"); 8258 if (link_status[1] == GL_FALSE) 8259 TCU_FAIL("Geometry shader program failed to link"); 8260 if (link_status[2] == GL_FALSE) 8261 TCU_FAIL("Tessellation control shader program failed to link"); 8262 if (link_status[3] == GL_FALSE) 8263 TCU_FAIL("Tessellation evaluation shader program failed to link"); 8264 if (link_status[4] == GL_FALSE) 8265 TCU_FAIL("Vertex shader program failed to link"); 8266 8267 /* Initialize pipeline program object */ 8268 gl.genProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id); 8269 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); 8270 8271 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_FRAGMENT_SHADER_BIT, m_fs_po_ids[n_id]); 8272 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_GEOMETRY_SHADER_BIT, m_gs_po_ids[n_id]); 8273 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_CONTROL_SHADER_BIT, m_tc_po_ids[n_id]); 8274 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_EVALUATION_SHADER_BIT, m_te_po_ids[n_id]); 8275 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_id]); 8276 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8277 } 8278 8279 /* Retrieve subroutine locations */ 8280 struct _item 8281 { 8282 glw::GLuint po_id; 8283 _shader_stage& stage; 8284 glw::GLuint so_id; 8285 glw::GLenum so_type; 8286 } items[] = { 8287 { m_po_ids[n_id], m_po_descriptors[n_id].fragment, m_fs_ids[n_id], GL_FRAGMENT_SHADER }, 8288 { m_po_ids[n_id], m_po_descriptors[n_id].geometry, m_gs_ids[n_id], GL_GEOMETRY_SHADER }, 8289 { m_po_ids[n_id], m_po_descriptors[n_id].tess_control, m_tc_ids[n_id], GL_TESS_CONTROL_SHADER }, 8290 { m_po_ids[n_id], m_po_descriptors[n_id].tess_evaluation, m_te_ids[n_id], GL_TESS_EVALUATION_SHADER }, 8291 { m_po_ids[n_id], m_po_descriptors[n_id].vertex, m_vs_ids[n_id], GL_VERTEX_SHADER }, 8292 8293 { m_fs_po_ids[n_id], m_fs_po_descriptors[n_id], m_fs_po_ids[n_id], GL_FRAGMENT_SHADER }, 8294 { m_gs_po_ids[n_id], m_gs_po_descriptors[n_id], m_gs_po_ids[n_id], GL_GEOMETRY_SHADER }, 8295 { m_tc_po_ids[n_id], m_tc_po_descriptors[n_id], m_tc_po_ids[n_id], GL_TESS_CONTROL_SHADER }, 8296 { m_te_po_ids[n_id], m_te_po_descriptors[n_id], m_te_po_ids[n_id], GL_TESS_EVALUATION_SHADER }, 8297 { m_vs_po_ids[n_id], m_vs_po_descriptors[n_id], m_vs_po_ids[n_id], GL_VERTEX_SHADER }, 8298 }; 8299 const unsigned int n_items = sizeof(items) / sizeof(items[0]); 8300 8301 for (unsigned int n_item = 0; n_item < n_items; ++n_item) 8302 { 8303 _item& current_item = items[n_item]; 8304 8305 current_item.stage.function1_index = 8306 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function1"); 8307 current_item.stage.function2_index = 8308 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function2"); 8309 current_item.stage.function3_index = 8310 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function3"); 8311 current_item.stage.function4_index = 8312 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function4"); 8313 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 8314 8315 if (current_item.stage.function1_index == GL_INVALID_INDEX || 8316 current_item.stage.function2_index == GL_INVALID_INDEX || 8317 current_item.stage.function3_index == GL_INVALID_INDEX || 8318 current_item.stage.function4_index == GL_INVALID_INDEX) 8319 { 8320 TCU_FAIL("Subroutine name was not recognized."); 8321 } 8322 8323 current_item.stage.subroutine1_uniform_location = 8324 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine1"); 8325 current_item.stage.subroutine2_uniform_location = 8326 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine2"); 8327 current_item.stage.subroutine3_uniform_location = 8328 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine3"); 8329 current_item.stage.subroutine4_uniform_location = 8330 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine4"); 8331 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed."); 8332 8333 if (current_item.stage.subroutine1_uniform_location == -1 || 8334 current_item.stage.subroutine2_uniform_location == -1 || 8335 current_item.stage.subroutine3_uniform_location == -1 || 8336 current_item.stage.subroutine4_uniform_location == -1) 8337 { 8338 TCU_FAIL("Subroutine uniform name was not recognized."); 8339 } 8340 8341 if (m_po_ids[n_id] == current_item.po_id) 8342 { 8343 gl.useProgram(current_item.po_id); 8344 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 8345 } 8346 else 8347 { 8348 /* Temporarily bind the program pipeline. */ 8349 gl.bindProgramPipeline(m_pipeline_object_ids[n_id]); 8350 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 8351 } 8352 8353 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine1_uniform_location, 8354 ¤t_item.stage.default_subroutine1_value); 8355 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine2_uniform_location, 8356 ¤t_item.stage.default_subroutine2_value); 8357 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine3_uniform_location, 8358 ¤t_item.stage.default_subroutine3_value); 8359 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine4_uniform_location, 8360 ¤t_item.stage.default_subroutine4_value); 8361 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed."); 8362 8363 current_item.stage.gl_stage = current_item.so_type; 8364 8365 if (m_po_ids[n_id] != current_item.po_id) 8366 { 8367 /* Unbind the program pipeline object */ 8368 gl.bindProgramPipeline(0); 8369 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 8370 } 8371 } /* for (all items) */ 8372 8373 /* Make sure the default subroutine choices are valid. */ 8374 verifySubroutineUniformValues( 8375 TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, /* makes the verification routine use program object descriptor */ 8376 n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES); 8377 8378 if (m_are_pipeline_objects_supported) 8379 { 8380 gl.useProgram(0); 8381 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 8382 8383 gl.bindProgramPipeline(m_pipeline_object_ids[n_id]); 8384 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 8385 { 8386 verifySubroutineUniformValues( 8387 TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT, /* makes the verification routine use pipeline object descriptor */ 8388 n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES); 8389 } 8390 gl.bindProgramPipeline(0); 8391 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 8392 } 8393 } /* for (both program descriptors) */ 8394 } 8395 8396 /** Retrieves IDs of shaders OR shader program objects, depending on which of the two 8397 * the caller requests for. 8398 * 8399 * @param retrieve_program_object_shader_ids true if the caller wishes to retrieve shader object IDs, 8400 * false to return shader program IDs. 8401 * @param n_id Index of the program/pipeline object the shaders 8402 * are a part of. 8403 * @param out_shader_stages Deref will be used to store exactly five IDs. Must not 8404 * be NULL. 8405 **/ 8406 void FunctionalTest16::getShaderStages(bool retrieve_program_object_shader_ids, const unsigned int& n_id, 8407 const _shader_stage** out_shader_stages) const 8408 { 8409 if (retrieve_program_object_shader_ids) 8410 { 8411 out_shader_stages[0] = &m_po_descriptors[n_id].vertex; 8412 out_shader_stages[1] = &m_po_descriptors[n_id].tess_control; 8413 out_shader_stages[2] = &m_po_descriptors[n_id].tess_evaluation; 8414 out_shader_stages[3] = &m_po_descriptors[n_id].geometry; 8415 out_shader_stages[4] = &m_po_descriptors[n_id].fragment; 8416 } 8417 else 8418 { 8419 out_shader_stages[0] = m_vs_po_descriptors + n_id; 8420 out_shader_stages[1] = m_tc_po_descriptors + n_id; 8421 out_shader_stages[2] = m_te_po_descriptors + n_id; 8422 out_shader_stages[3] = m_gs_po_descriptors + n_id; 8423 out_shader_stages[4] = m_fs_po_descriptors + n_id; 8424 } 8425 } 8426 8427 /** Executes test iteration. 8428 * 8429 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 8430 */ 8431 tcu::TestNode::IterateResult FunctionalTest16::iterate() 8432 { 8433 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8434 8435 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 8436 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 8437 { 8438 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 8439 } 8440 8441 m_are_pipeline_objects_supported = 8442 m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"); 8443 8444 /* Initialize GL objects required to run the test */ 8445 initTest(); 8446 8447 /* Iterate over both pipelines/programs and verify that calling glUseProgram() / 8448 * glBindProgramPipeline() / glUseProgramStages() resets subroutine uniform configuration. 8449 */ 8450 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 8451 { 8452 if (static_cast<_test_case>(test_case) != TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT && 8453 !m_are_pipeline_objects_supported) 8454 { 8455 /* Current test case requires GL_ARB_separate_shader_objects support which is 8456 * unavaiable on the platform that we're testing 8457 */ 8458 continue; 8459 } 8460 8461 for (unsigned int n_object_id = 0; n_object_id < 2; /* pipeline/program objects allocated for the test */ 8462 ++n_object_id) 8463 { 8464 /* Verify that currently reported subroutine uniform values are equal to default values */ 8465 if (test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT) 8466 { 8467 gl.useProgram(m_po_ids[n_object_id]); 8468 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 8469 } 8470 else 8471 { 8472 gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]); 8473 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed"); 8474 } 8475 8476 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id, 8477 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES); 8478 8479 /* Re-configure subroutine uniforms so that they point to different subroutines than 8480 * the default ones. 8481 */ 8482 const _shader_stage* stages[5 /* fs+gs+tc+te+vs */] = { DE_NULL }; 8483 8484 getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, 8485 n_object_id, stages); 8486 8487 for (unsigned int n_stage = 0; n_stage < 5 /* fs+gs+tc+te+vs stages */; ++n_stage) 8488 { 8489 const _shader_stage& current_stage = *(stages[n_stage]); 8490 glw::GLuint subroutine_configuration[4] = { GL_INVALID_INDEX }; 8491 8492 subroutine_configuration[0] = 8493 (current_stage.default_subroutine1_value == current_stage.function1_index) ? 8494 current_stage.function2_index : 8495 current_stage.function1_index; 8496 subroutine_configuration[1] = 8497 (current_stage.default_subroutine2_value == current_stage.function1_index) ? 8498 current_stage.function2_index : 8499 current_stage.function1_index; 8500 subroutine_configuration[2] = 8501 (current_stage.default_subroutine3_value == current_stage.function3_index) ? 8502 current_stage.function4_index : 8503 current_stage.function3_index; 8504 subroutine_configuration[3] = 8505 (current_stage.default_subroutine4_value == current_stage.function3_index) ? 8506 current_stage.function4_index : 8507 current_stage.function3_index; 8508 8509 gl.uniformSubroutinesuiv(current_stage.gl_stage, 4 /* count */, subroutine_configuration); 8510 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed."); 8511 } /* for (all stages) */ 8512 8513 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id, 8514 SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES); 8515 8516 /* Execute test case-specific code */ 8517 _shader_stage cached_shader_stage_data; 8518 bool stage_reset_status[Utils::SHADER_STAGE_COUNT] = { false, false, false, false, false }; 8519 bool uses_stage_reset_status = false; 8520 8521 switch (test_case) 8522 { 8523 case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT: 8524 { 8525 /* Switch to a different program object and then back to current PO. 8526 * Subroutine uniforms should be back at their default settings, instead of 8527 * the ones we've just set. 8528 */ 8529 gl.useProgram(m_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8530 gl.useProgram(m_po_ids[n_object_id]); 8531 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed."); 8532 8533 break; 8534 } 8535 8536 case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT: 8537 { 8538 /* Switch to a different pipeline object and then back to the current one. 8539 * Subroutine uniforms should be back at their default settings, instead of 8540 * the ones we've just set. 8541 */ 8542 gl.bindProgramPipeline( 8543 m_pipeline_object_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8544 gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]); 8545 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed."); 8546 8547 break; 8548 } 8549 8550 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE: 8551 { 8552 /* Change the fragment shader stage to a different one. 8553 * 8554 * Note: We also need to update internal descriptor since the subroutine/uniform 8555 * locations may be different between the two programs. 8556 */ 8557 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT, 8558 m_fs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8559 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8560 8561 cached_shader_stage_data = m_fs_po_descriptors[n_object_id]; 8562 m_fs_po_descriptors[n_object_id] = m_fs_po_descriptors[(n_object_id + 1) % 2]; 8563 8564 stage_reset_status[Utils::SHADER_STAGE_FRAGMENT] = true; 8565 uses_stage_reset_status = true; 8566 8567 break; 8568 } 8569 8570 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE: 8571 { 8572 /* Change the geometry shader stage to a different one. 8573 * 8574 * Note: We also need to update internal descriptor since the subroutine/uniform 8575 * locations may be different between the two programs. 8576 */ 8577 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT, 8578 m_gs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8579 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8580 8581 cached_shader_stage_data = m_gs_po_descriptors[n_object_id]; 8582 m_gs_po_descriptors[n_object_id] = m_gs_po_descriptors[(n_object_id + 1) % 2]; 8583 8584 stage_reset_status[Utils::SHADER_STAGE_GEOMETRY] = true; 8585 uses_stage_reset_status = true; 8586 8587 break; 8588 } 8589 8590 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE: 8591 { 8592 /* Change the tessellation control shader stage to a different one. 8593 * 8594 * Note: We also need to update internal descriptor since the subroutine/uniform 8595 * locations may be different between the two programs. 8596 */ 8597 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT, 8598 m_tc_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8599 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8600 8601 cached_shader_stage_data = m_tc_po_descriptors[n_object_id]; 8602 m_tc_po_descriptors[n_object_id] = m_tc_po_descriptors[(n_object_id + 1) % 2]; 8603 8604 stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_CONTROL] = true; 8605 uses_stage_reset_status = true; 8606 8607 break; 8608 } 8609 8610 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE: 8611 { 8612 /* Change the tessellation evaluation shader stage to a different one. 8613 * 8614 * Note: We also need to update internal descriptor since the subroutine/uniform 8615 * locations may be different between the two programs. 8616 */ 8617 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT, 8618 m_te_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8619 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8620 8621 cached_shader_stage_data = m_te_po_descriptors[n_object_id]; 8622 m_te_po_descriptors[n_object_id] = m_te_po_descriptors[(n_object_id + 1) % 2]; 8623 8624 stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_EVALUATION] = true; 8625 uses_stage_reset_status = true; 8626 8627 break; 8628 } 8629 8630 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE: 8631 { 8632 /* Change the vertex shader stage to a different one. 8633 * 8634 * Note: We also need to update internal descriptor since the subroutine/uniform 8635 * locations may be different between the two programs. 8636 */ 8637 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT, 8638 m_vs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8639 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8640 8641 cached_shader_stage_data = m_vs_po_descriptors[n_object_id]; 8642 m_vs_po_descriptors[n_object_id] = m_vs_po_descriptors[(n_object_id + 1) % 2]; 8643 8644 stage_reset_status[Utils::SHADER_STAGE_VERTEX] = true; 8645 uses_stage_reset_status = true; 8646 8647 break; 8648 } 8649 8650 default: 8651 { 8652 TCU_FAIL("Unrecognized test case"); 8653 } 8654 } /* switch (test_case) */ 8655 8656 /* Verify the subroutine uniform values are valid */ 8657 if (!uses_stage_reset_status) 8658 { 8659 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id, 8660 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES); 8661 } 8662 else 8663 { 8664 const _shader_stage* shader_stages[Utils::SHADER_STAGE_COUNT] = { DE_NULL }; 8665 8666 getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, 8667 n_object_id, shader_stages); 8668 8669 for (unsigned int n_shader_stage = 0; n_shader_stage < Utils::SHADER_STAGE_COUNT; ++n_shader_stage) 8670 { 8671 const _shader_stage& current_shader_stage = *(shader_stages[n_shader_stage]); 8672 8673 if (stage_reset_status[n_shader_stage]) 8674 { 8675 verifySubroutineUniformValuesForShaderStage(current_shader_stage, 8676 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES); 8677 } 8678 else 8679 { 8680 verifySubroutineUniformValuesForShaderStage(current_shader_stage, 8681 SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES); 8682 } 8683 } /* for (all shader stages) */ 8684 } 8685 8686 /* Revert the changes some of the test cases appied */ 8687 switch (test_case) 8688 { 8689 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE: 8690 { 8691 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT, 8692 m_fs_po_ids[n_object_id]); 8693 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8694 8695 m_fs_po_descriptors[n_object_id] = cached_shader_stage_data; 8696 8697 break; 8698 } 8699 8700 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE: 8701 { 8702 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT, 8703 m_gs_po_ids[n_object_id]); 8704 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8705 8706 m_gs_po_descriptors[n_object_id] = cached_shader_stage_data; 8707 8708 break; 8709 } 8710 8711 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE: 8712 { 8713 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT, 8714 m_tc_po_ids[n_object_id]); 8715 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8716 8717 m_tc_po_descriptors[n_object_id] = cached_shader_stage_data; 8718 8719 break; 8720 } 8721 8722 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE: 8723 { 8724 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT, 8725 m_te_po_ids[n_object_id]); 8726 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8727 8728 m_te_po_descriptors[n_object_id] = cached_shader_stage_data; 8729 8730 break; 8731 } 8732 8733 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE: 8734 { 8735 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_object_id]); 8736 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8737 8738 m_vs_po_descriptors[n_object_id] = cached_shader_stage_data; 8739 8740 break; 8741 } 8742 8743 default: 8744 break; 8745 } /* switch (test_case) */ 8746 8747 } /* for (all program object descriptors) */ 8748 8749 /* Unbind the program object */ 8750 gl.useProgram(0); 8751 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 8752 } /* for (all test cases) */ 8753 8754 if (m_has_test_passed) 8755 { 8756 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 8757 } 8758 else 8759 { 8760 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 8761 } 8762 8763 return STOP; 8764 } 8765 8766 /** Verifies the subroutine uniform values reported by GL implementation. Depending on the test case, 8767 * it will either query program object stages or separate shader objects. 8768 * 8769 * @param test_case Test case the verification is to be performed for. 8770 * @param n_id Index of the program/pipeline object to use for the verification 8771 * @param verification Verification method. 8772 */ 8773 void FunctionalTest16::verifySubroutineUniformValues(const _test_case& test_case, const unsigned int& n_id, 8774 const _subroutine_uniform_value_verification& verification) 8775 { 8776 const _shader_stage* stages[] = { 8777 DE_NULL, /* fragment shader stage slot */ 8778 DE_NULL, /* geometry shader stage slot */ 8779 DE_NULL, /* tess control shader stage slot */ 8780 DE_NULL, /* tess eval shader stage slot */ 8781 DE_NULL /* vertex shader stage slot */ 8782 }; 8783 const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]); 8784 8785 /* Verify that currently reported subroutine uniform values are equal to default values */ 8786 getShaderStages(test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, n_id, stages); 8787 8788 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage) 8789 { 8790 const _shader_stage& current_stage = *(stages[n_stage]); 8791 8792 verifySubroutineUniformValuesForShaderStage(current_stage, verification); 8793 } /* for (all items) */ 8794 } 8795 8796 /** Verifies the subroutine uniform values reported by GL implementation for user-specified 8797 * shader stage. If the verification fails, m_has_test_passed will be set to false. 8798 * 8799 * @param shader_stage Descriptor of a shader stage that should be used for the process. 8800 * @param verification Type of verification that should be performed. 8801 * 8802 **/ 8803 void FunctionalTest16::verifySubroutineUniformValuesForShaderStage( 8804 const _shader_stage& shader_stage, const _subroutine_uniform_value_verification& verification) 8805 { 8806 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8807 glw::GLuint result_values[4] = { 0 }; 8808 8809 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine1_uniform_location, result_values + 0); 8810 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine2_uniform_location, result_values + 1); 8811 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine3_uniform_location, result_values + 2); 8812 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine4_uniform_location, result_values + 3); 8813 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed."); 8814 8815 if (verification == SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES) 8816 { 8817 if (!((result_values[0] == (GLuint)shader_stage.subroutine1_uniform_location || 8818 result_values[0] == (GLuint)shader_stage.subroutine2_uniform_location) && 8819 (result_values[1] == (GLuint)shader_stage.subroutine1_uniform_location || 8820 result_values[1] == (GLuint)shader_stage.subroutine2_uniform_location) && 8821 (result_values[2] == (GLuint)shader_stage.subroutine3_uniform_location || 8822 result_values[2] == (GLuint)shader_stage.subroutine4_uniform_location) && 8823 (result_values[3] == (GLuint)shader_stage.subroutine3_uniform_location || 8824 result_values[3] == (GLuint)shader_stage.subroutine4_uniform_location))) 8825 { 8826 m_testCtx.getLog() << tcu::TestLog::Message << "SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES validation failed. " 8827 "Shader stage:[" 8828 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], " 8829 "expected data:[" 8830 << shader_stage.subroutine1_uniform_location << " OR " 8831 << shader_stage.subroutine2_uniform_location << " x 2, " 8832 << shader_stage.subroutine3_uniform_location << " OR " 8833 << shader_stage.subroutine4_uniform_location << " x 2], " 8834 "found data:[" 8835 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", " 8836 << result_values[3] << "]." << tcu::TestLog::EndMessage; 8837 8838 m_has_test_passed = false; 8839 } 8840 } 8841 else if (verification == SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES) 8842 { 8843 if (result_values[0] != shader_stage.default_subroutine1_value || 8844 result_values[1] != shader_stage.default_subroutine2_value || 8845 result_values[2] != shader_stage.default_subroutine3_value || 8846 result_values[3] != shader_stage.default_subroutine4_value) 8847 { 8848 m_testCtx.getLog() << tcu::TestLog::Message 8849 << "SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES validation failed. " 8850 "Shader stage:[" 8851 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], " 8852 "expected data:[" 8853 << shader_stage.default_subroutine1_value << ", " 8854 << shader_stage.default_subroutine2_value << ", " 8855 << shader_stage.default_subroutine3_value << ", " 8856 << shader_stage.default_subroutine4_value << "], " 8857 "found data:[" 8858 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", " 8859 << result_values[3] << "]." << tcu::TestLog::EndMessage; 8860 8861 m_has_test_passed = false; 8862 } 8863 } 8864 else 8865 { 8866 DE_ASSERT(verification == SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES); 8867 8868 if (result_values[0] == shader_stage.default_subroutine1_value || 8869 result_values[1] == shader_stage.default_subroutine2_value || 8870 result_values[2] == shader_stage.default_subroutine3_value || 8871 result_values[3] == shader_stage.default_subroutine4_value) 8872 { 8873 m_testCtx.getLog() << tcu::TestLog::Message 8874 << "SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES validation failed. " 8875 "Shader stage:[" 8876 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], " 8877 "expected data:![" 8878 << shader_stage.default_subroutine1_value << ", " 8879 << shader_stage.default_subroutine2_value << ", " 8880 << shader_stage.default_subroutine3_value << ", " 8881 << shader_stage.default_subroutine4_value << "], " 8882 "found data:[" 8883 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", " 8884 << result_values[3] << "]." << tcu::TestLog::EndMessage; 8885 8886 m_has_test_passed = false; 8887 } 8888 } 8889 } 8890 8891 /** Constructor. 8892 * 8893 * @param context Rendering context. 8894 * 8895 **/ 8896 FunctionalTest17::FunctionalTest17(deqp::Context& context) 8897 : TestCase(context, "same_subroutine_and_subroutine_uniform_but_different_type_used_in_all_stages", 8898 "Creates a program which uses the same subroutine and subroutine uniform " 8899 "names for every stage (types of subroutines are different in each stage) " 8900 "and then makes sure that such program compiles and works as expected.") 8901 , m_fbo_id(0) 8902 , m_fs_id(0) 8903 , m_gs_id(0) 8904 , m_has_test_passed(true) 8905 , m_po_id(0) 8906 , m_tc_id(0) 8907 , m_te_id(0) 8908 , m_to_data(DE_NULL) 8909 , m_to_height(4) /* arbitrary value */ 8910 , m_to_id(0) 8911 , m_to_width(4) /* arbitrary value */ 8912 , m_vao_id(0) 8913 , m_vs_id(0) 8914 { 8915 /* Left blank intentionally */ 8916 } 8917 8918 /** Deinitializes all GL objects that may have been created during test execution. */ 8919 void FunctionalTest17::deinit() 8920 { 8921 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8922 8923 if (m_fbo_id != 0) 8924 { 8925 gl.deleteFramebuffers(1, &m_fbo_id); 8926 8927 m_fbo_id = 0; 8928 } 8929 8930 if (m_fs_id != 0) 8931 { 8932 gl.deleteShader(m_fs_id); 8933 8934 m_fs_id = 0; 8935 } 8936 8937 if (m_gs_id != 0) 8938 { 8939 gl.deleteShader(m_gs_id); 8940 8941 m_gs_id = 0; 8942 } 8943 8944 if (m_po_id != 0) 8945 { 8946 gl.deleteProgram(m_po_id); 8947 8948 m_po_id = 0; 8949 } 8950 8951 if (m_tc_id != 0) 8952 { 8953 gl.deleteShader(m_tc_id); 8954 8955 m_tc_id = 0; 8956 } 8957 8958 if (m_te_id != 0) 8959 { 8960 gl.deleteShader(m_te_id); 8961 8962 m_te_id = 0; 8963 } 8964 8965 if (m_to_data != DE_NULL) 8966 { 8967 delete[] m_to_data; 8968 8969 m_to_data = DE_NULL; 8970 } 8971 8972 if (m_to_id != 0) 8973 { 8974 gl.deleteTextures(1, &m_to_id); 8975 8976 m_to_id = 0; 8977 } 8978 8979 if (m_vao_id != 0) 8980 { 8981 gl.deleteVertexArrays(1, &m_vao_id); 8982 8983 m_vao_id = 0; 8984 } 8985 8986 if (m_vs_id != 0) 8987 { 8988 gl.deleteShader(m_vs_id); 8989 8990 m_vs_id = 0; 8991 } 8992 8993 /* Restore original GL configuration */ 8994 gl.patchParameteri(GL_PATCH_VERTICES, 3); 8995 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed."); 8996 8997 gl.pixelStorei(GL_PACK_ALIGNMENT, 4); 8998 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed."); 8999 } 9000 9001 /** Retrieves body of a fragment shader that should be used by the test program. 9002 * 9003 * @return Requested string. 9004 **/ 9005 std::string FunctionalTest17::getFragmentShaderBody() const 9006 { 9007 return "#version 400\n" 9008 "\n" 9009 "#extension GL_ARB_shader_subroutine : require\n" 9010 "\n" 9011 "in GS_DATA\n" 9012 "{\n" 9013 " vec4 gs_data;\n" 9014 " vec4 tc_data;\n" 9015 " vec4 te_data;\n" 9016 " vec4 vs_data;\n" 9017 "} gs;\n" 9018 "\n" 9019 "out vec4 result;\n" 9020 "\n" 9021 "subroutine void subroutineTypeFS(out vec4 result);\n" 9022 "\n" 9023 "subroutine(subroutineTypeFS) void subroutine1(out vec4 result)\n" 9024 "{\n" 9025 " result = vec4(5, 6, 7, 8);\n" 9026 "}\n" 9027 "\n" 9028 "subroutine uniform subroutineTypeFS function;\n" 9029 "\n" 9030 "void main()\n" 9031 "{\n" 9032 " vec4 fs_data;\n" 9033 "\n" 9034 " function(fs_data);\n" 9035 " result = gs.gs_data + gs.tc_data + gs.te_data + gs.vs_data + fs_data;\n" 9036 "}\n"; 9037 } 9038 9039 /** Retrieves body of a geometry shader that should be used by the test program. 9040 * 9041 * @return Requested string. 9042 **/ 9043 std::string FunctionalTest17::getGeometryShaderBody() const 9044 { 9045 return "#version 400\n" 9046 "\n" 9047 "#extension GL_ARB_shader_subroutine : require\n" 9048 "\n" 9049 "layout(points) in;\n" 9050 "layout(triangle_strip, max_vertices = 4) out;\n" 9051 "\n" 9052 "subroutine void subroutineTypeGS(out vec4 result);\n" 9053 "\n" 9054 "subroutine(subroutineTypeGS) void subroutine1(out vec4 result)\n" 9055 "{\n" 9056 " result = vec4(4, 5, 6, 7);\n" 9057 "}\n" 9058 "\n" 9059 "subroutine uniform subroutineTypeGS function;\n" 9060 "\n" 9061 "in TE_DATA\n" 9062 "{\n" 9063 " vec4 tc_data;\n" 9064 " vec4 te_data;\n" 9065 " vec4 vs_data;\n" 9066 "} te[];\n" 9067 "\n" 9068 "out GS_DATA\n" 9069 "{\n" 9070 " vec4 gs_data;\n" 9071 " vec4 tc_data;\n" 9072 " vec4 te_data;\n" 9073 " vec4 vs_data;\n" 9074 "} result;\n" 9075 "\n" 9076 "void main()\n" 9077 "{\n" 9078 " function(result.gs_data);\n" 9079 " gl_Position = vec4(1, -1, 0, 1);\n" 9080 " result.tc_data = te[0].tc_data;\n" 9081 " result.te_data = te[0].te_data;\n" 9082 " result.vs_data = te[0].vs_data;\n" 9083 " EmitVertex();\n" 9084 "\n" 9085 " function(result.gs_data);\n" 9086 " gl_Position = vec4(-1, -1, 0, 1);\n" 9087 " result.tc_data = te[0].tc_data;\n" 9088 " result.te_data = te[0].te_data;\n" 9089 " result.vs_data = te[0].vs_data;\n" 9090 " EmitVertex();\n" 9091 "\n" 9092 " function(result.gs_data);\n" 9093 " gl_Position = vec4(1, 1, 0, 1);\n" 9094 " result.tc_data = te[0].tc_data;\n" 9095 " result.te_data = te[0].te_data;\n" 9096 " result.vs_data = te[0].vs_data;\n" 9097 " EmitVertex();\n" 9098 "\n" 9099 " function(result.gs_data);\n" 9100 " gl_Position = vec4(-1, 1, 0, 1);\n" 9101 " result.tc_data = te[0].tc_data;\n" 9102 " result.te_data = te[0].te_data;\n" 9103 " result.vs_data = te[0].vs_data;\n" 9104 " EmitVertex();\n" 9105 " EndPrimitive();\n" 9106 "}\n"; 9107 } 9108 9109 /** Retrieves body of a tessellation control shader that should be used by the test program. 9110 * 9111 * @return Requested string. 9112 **/ 9113 std::string FunctionalTest17::getTessellationControlShaderBody() const 9114 { 9115 return "#version 400\n" 9116 "\n" 9117 "#extension GL_ARB_shader_subroutine : require\n" 9118 "\n" 9119 "layout (vertices = 4) out;\n" 9120 "\n" 9121 "subroutine void subroutineTypeTC(out vec4 result);\n" 9122 "\n" 9123 "subroutine(subroutineTypeTC) void subroutine1(out vec4 result)\n" 9124 "{\n" 9125 " result = vec4(2, 3, 4, 5);\n" 9126 "}\n" 9127 "\n" 9128 "subroutine uniform subroutineTypeTC function;\n" 9129 "\n" 9130 "in VS_DATA\n" 9131 "{\n" 9132 " vec4 vs_data;\n" 9133 "} vs[];\n" 9134 "\n" 9135 "out TC_DATA\n" 9136 "{\n" 9137 " vec4 tc_data;\n" 9138 " vec4 vs_data;\n" 9139 "} result[];\n" 9140 "\n" 9141 "void main()\n" 9142 "{\n" 9143 " gl_TessLevelInner[0] = 1.0;\n" 9144 " gl_TessLevelInner[1] = 1.0;\n" 9145 " gl_TessLevelOuter[0] = 1.0;\n" 9146 " gl_TessLevelOuter[1] = 1.0;\n" 9147 " gl_TessLevelOuter[2] = 1.0;\n" 9148 " gl_TessLevelOuter[3] = 1.0;\n" 9149 "\n" 9150 " function(result[gl_InvocationID].tc_data);\n" 9151 " result[gl_InvocationID].vs_data = vs[gl_InvocationID].vs_data;\n" 9152 "}\n"; 9153 } 9154 9155 /** Retrieves body of a tessellation evaluation shader that should be used 9156 * by the test program. 9157 * 9158 * @return Requested string. 9159 **/ 9160 std::string FunctionalTest17::getTessellationEvaluationShaderBody() const 9161 { 9162 return "#version 400\n" 9163 "\n" 9164 "#extension GL_ARB_shader_subroutine : require\n" 9165 "\n" 9166 "layout (quads, point_mode) in;\n" 9167 "\n" 9168 "subroutine void subroutineTypeTE(out vec4 result);\n" 9169 "\n" 9170 "subroutine(subroutineTypeTE) void subroutine1(out vec4 result)\n" 9171 "{\n" 9172 " result = vec4(3, 4, 5, 6);\n" 9173 "}\n" 9174 "\n" 9175 "subroutine uniform subroutineTypeTE function;\n" 9176 "\n" 9177 "in TC_DATA\n" 9178 "{\n" 9179 " vec4 tc_data;\n" 9180 " vec4 vs_data;\n" 9181 "} tc[];\n" 9182 "\n" 9183 "out TE_DATA\n" 9184 "{\n" 9185 " vec4 tc_data;\n" 9186 " vec4 te_data;\n" 9187 " vec4 vs_data;\n" 9188 "} result;\n" 9189 "\n" 9190 "void main()\n" 9191 "{\n" 9192 " result.vs_data = tc[0].vs_data;\n" 9193 " result.tc_data = tc[0].tc_data;\n" 9194 " function(result.te_data);\n" 9195 "}\n"; 9196 } 9197 9198 /** Retrieves body of a vertex shader that should be used by the test program. 9199 * 9200 * @return Requested string. 9201 **/ 9202 std::string FunctionalTest17::getVertexShaderBody() const 9203 { 9204 return "#version 400\n" 9205 "\n" 9206 "#extension GL_ARB_shader_subroutine : require\n" 9207 "\n" 9208 "out VS_DATA\n" 9209 "{\n" 9210 " vec4 vs_data;\n" 9211 "} result;\n" 9212 "\n" 9213 "subroutine void subroutineTypeVS(out vec4 result);\n" 9214 "\n" 9215 "subroutine(subroutineTypeVS) void subroutine1(out vec4 result)\n" 9216 "{\n" 9217 " result = vec4(1, 2, 3, 4);\n" 9218 "}\n" 9219 "\n" 9220 "subroutine uniform subroutineTypeVS function;\n" 9221 "\n" 9222 "void main()\n" 9223 "{\n" 9224 " function(result.vs_data);\n" 9225 "}\n"; 9226 } 9227 9228 /** Initializes all buffers and GL objects required to run the test. */ 9229 void FunctionalTest17::initTest() 9230 { 9231 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9232 9233 /* Configure GL_PATCH_VERTICES so that TC only takes a single patch vertex */ 9234 gl.patchParameteri(GL_PATCH_VERTICES, 1); 9235 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed."); 9236 9237 /* Generate & bind a VAO */ 9238 gl.genVertexArrays(1, &m_vao_id); 9239 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 9240 9241 gl.bindVertexArray(m_vao_id); 9242 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 9243 9244 /* Set up test program object */ 9245 std::string fs_body = getFragmentShaderBody(); 9246 std::string gs_body = getGeometryShaderBody(); 9247 std::string tc_body = getTessellationControlShaderBody(); 9248 std::string te_body = getTessellationEvaluationShaderBody(); 9249 std::string vs_body = getVertexShaderBody(); 9250 9251 if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */ 9252 DE_NULL, /* n_xfb_varyings */ 9253 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 9254 { 9255 TCU_FAIL("Failed to link test program object"); 9256 } 9257 9258 /* Set up a texture object that will be used as a color attachment */ 9259 gl.genTextures(1, &m_to_id); 9260 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 9261 9262 gl.bindTexture(GL_TEXTURE_2D, m_to_id); 9263 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 9264 9265 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 9266 GL_RGBA32F, m_to_width, m_to_height); 9267 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed."); 9268 9269 /* Set up FBO */ 9270 gl.genFramebuffers(1, &m_fbo_id); 9271 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed."); 9272 9273 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 9274 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 9275 9276 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */); 9277 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 9278 9279 /* Make sure glReadPixels() does not return misaligned data */ 9280 gl.pixelStorei(GL_PACK_ALIGNMENT, 1); 9281 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed."); 9282 9283 /* Initialize a buffer that will be used to store rendered data */ 9284 m_to_data = new float[m_to_width * m_to_height * 4 /* rgba */]; 9285 } 9286 9287 /** Executes test iteration. 9288 * 9289 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 9290 */ 9291 tcu::TestNode::IterateResult FunctionalTest17::iterate() 9292 { 9293 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9294 9295 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 9296 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 9297 { 9298 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 9299 } 9300 9301 initTest(); 9302 9303 /* Use the test program to render a full-screen test quad */ 9304 gl.useProgram(m_po_id); 9305 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 9306 9307 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */); 9308 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 9309 9310 /* Read back the data that was rendered */ 9311 gl.readPixels(0, /* x */ 9312 0, /* y */ 9313 m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_to_data); 9314 GLU_EXPECT_NO_ERROR(gl.getError(), "glReaDPixels() call failed."); 9315 9316 /* Verify the data */ 9317 verifyRenderedData(); 9318 9319 /** All done */ 9320 if (m_has_test_passed) 9321 { 9322 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 9323 } 9324 else 9325 { 9326 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 9327 } 9328 9329 return STOP; 9330 } 9331 9332 /** Verifies the data that have been rendered by the test program. 9333 * 9334 * It is assumed the rendered data have already been copied to 9335 * m_to_data. 9336 * 9337 * If the rendered data is found to be invalid, m_has_test_passed 9338 * will be set to false. 9339 **/ 9340 void FunctionalTest17::verifyRenderedData() 9341 { 9342 const float epsilon = 1e-5f; 9343 const float expected_data[4] = { 15.0f, 20.0f, 25.0f, 30.0f }; 9344 9345 for (unsigned int y = 0; y < m_to_height && m_has_test_passed; ++y) 9346 { 9347 const float* row_ptr = m_to_data + y * 4 /* rgba */ * m_to_width; 9348 9349 for (unsigned int x = 0; x < m_to_width && m_has_test_passed; ++x) 9350 { 9351 const float* pixel_ptr = row_ptr + 4 /* rgba */ * x; 9352 9353 if (de::abs(pixel_ptr[0] - expected_data[0]) > epsilon || 9354 de::abs(pixel_ptr[1] - expected_data[1]) > epsilon || 9355 de::abs(pixel_ptr[2] - expected_data[2]) > epsilon || 9356 de::abs(pixel_ptr[3] - expected_data[3]) > epsilon) 9357 { 9358 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel found at (" << x << ", " << y 9359 << "): " 9360 "expected:(" 9361 << expected_data[0] << ", " << expected_data[1] << ", " << expected_data[2] << ", " 9362 << expected_data[3] << "), found:(" << pixel_ptr[0] << ", " << pixel_ptr[1] << ", " 9363 << pixel_ptr[2] << ", " << pixel_ptr[3] << ")." << tcu::TestLog::EndMessage; 9364 9365 m_has_test_passed = false; 9366 } 9367 } /* for (all columns) */ 9368 } /* for (all rows) */ 9369 } 9370 9371 /** Constructor. 9372 * 9373 * @param context Rendering context. 9374 * 9375 **/ 9376 FunctionalTest18_19::FunctionalTest18_19(deqp::Context& context) 9377 : TestCase(context, "control_flow_and_returned_subroutine_values_used_as_subroutine_input", 9378 "Makes sure that calling a subroutine with argument value returned by " 9379 "another subroutine works correctly. Also checks that subroutine and " 9380 "subroutine uniforms work as expected when used in connection with control " 9381 "flow functions.") 9382 , m_has_test_passed(true) 9383 , m_n_points_to_draw(16) /* arbitrary value */ 9384 , m_po_id(0) 9385 , m_po_subroutine_divide_by_two_location(GL_INVALID_INDEX) 9386 , m_po_subroutine_multiply_by_four_location(GL_INVALID_INDEX) 9387 , m_po_subroutine_returns_false_location(GL_INVALID_INDEX) 9388 , m_po_subroutine_returns_true_location(GL_INVALID_INDEX) 9389 , m_po_subroutine_uniform_bool_operator1(-1) 9390 , m_po_subroutine_uniform_bool_operator2(-1) 9391 , m_po_subroutine_uniform_vec4_processor1(-1) 9392 , m_po_subroutine_uniform_vec4_processor2(-1) 9393 , m_xfb_bo_id(0) 9394 , m_vao_id(0) 9395 , m_vs_id(0) 9396 { 9397 /* Left blank intentionally */ 9398 } 9399 9400 /** De-initializes all GL objects that may have been created during test execution */ 9401 void FunctionalTest18_19::deinit() 9402 { 9403 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9404 9405 if (m_po_id != 0) 9406 { 9407 gl.deleteProgram(m_po_id); 9408 9409 m_po_id = 0; 9410 } 9411 9412 if (m_vao_id != 0) 9413 { 9414 gl.deleteVertexArrays(1, &m_vao_id); 9415 9416 m_vao_id = 0; 9417 } 9418 9419 if (m_vs_id != 0) 9420 { 9421 gl.deleteShader(m_vs_id); 9422 9423 m_vs_id = 0; 9424 } 9425 9426 if (m_xfb_bo_id != 0) 9427 { 9428 gl.deleteBuffers(1, &m_xfb_bo_id); 9429 9430 m_xfb_bo_id = 0; 9431 } 9432 } 9433 9434 /** Executes a single test iteration using user-specified properties. If the 9435 * iterations fails, m_has_test_passed is set to false. 9436 * 9437 * @param bool_operator1_subroutine_location Location of a subroutine to be assigned to 9438 * bool_operator1 subroutine uniform. 9439 * @param bool_operator2_subroutine_location Location of a subroutine to be assigned to 9440 * bool_operator2 subroutine uniform. 9441 * @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to 9442 * vec4_operator1 subroutine uniform. 9443 * @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to 9444 * vec4_operator2 subroutine uniform. 9445 &**/ 9446 void FunctionalTest18_19::executeTest(glw::GLuint bool_operator1_subroutine_location, 9447 glw::GLuint bool_operator2_subroutine_location, 9448 glw::GLuint vec4_operator1_subroutine_location, 9449 glw::GLuint vec4_operator2_subroutine_location) 9450 { 9451 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9452 9453 /* Set up subroutines */ 9454 glw::GLuint subroutine_configuration[4 /* total number of subroutines */] = { 0 }; 9455 9456 subroutine_configuration[m_po_subroutine_uniform_bool_operator1] = bool_operator1_subroutine_location; 9457 subroutine_configuration[m_po_subroutine_uniform_bool_operator2] = bool_operator2_subroutine_location; 9458 subroutine_configuration[m_po_subroutine_uniform_vec4_processor1] = vec4_operator1_subroutine_location; 9459 subroutine_configuration[m_po_subroutine_uniform_vec4_processor2] = vec4_operator2_subroutine_location; 9460 9461 gl.useProgram(m_po_id); 9462 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 9463 9464 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 4 /* count */, subroutine_configuration); 9465 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed"); 9466 9467 /* Draw test-specific number of points */ 9468 gl.beginTransformFeedback(GL_POINTS); 9469 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed"); 9470 { 9471 gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw); 9472 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed"); 9473 } 9474 gl.endTransformFeedback(); 9475 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed"); 9476 9477 /* Map the BO storage into process space */ 9478 const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 9479 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 9480 9481 verifyXFBData(xfb_data_ptr, bool_operator1_subroutine_location, bool_operator2_subroutine_location, 9482 vec4_operator1_subroutine_location, vec4_operator2_subroutine_location); 9483 9484 /* Unmap BO storage */ 9485 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 9486 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 9487 } 9488 9489 /** Retrieves body of a vertex shader to be used by the test. */ 9490 std::string FunctionalTest18_19::getVertexShaderBody() const 9491 { 9492 return "#version 400\n" 9493 "\n" 9494 "subroutine bool bool_processor();\n" 9495 "subroutine vec4 vec4_processor(in vec4 iparam);\n" 9496 "\n" 9497 "subroutine(bool_processor) bool returnsFalse()\n" 9498 "{\n" 9499 " return false;\n" 9500 "}\n" 9501 "\n" 9502 "subroutine(bool_processor) bool returnsTrue()\n" 9503 "{\n" 9504 " return true;\n" 9505 "}\n" 9506 "\n" 9507 "subroutine(vec4_processor) vec4 divideByTwo(in vec4 iparam)\n" 9508 "{\n" 9509 " return iparam * vec4(0.5);\n" 9510 "}\n" 9511 "\n" 9512 "subroutine(vec4_processor) vec4 multiplyByFour(in vec4 iparam)\n" 9513 "{\n" 9514 " return iparam * vec4(4.0);\n" 9515 "}\n" 9516 "\n" 9517 "subroutine uniform bool_processor bool_operator1;\n" 9518 "subroutine uniform bool_processor bool_operator2;\n" 9519 "subroutine uniform vec4_processor vec4_operator1;\n" 9520 "subroutine uniform vec4_processor vec4_operator2;\n" 9521 "\n" 9522 "out float result;\n" 9523 "\n" 9524 "void main()\n" 9525 "{\n" 9526 " if (bool_operator1() )\n" 9527 " {\n" 9528 " float value = float( (3 * gl_VertexID + 1) * 2);\n" 9529 "\n" 9530 " while (bool_operator1() )\n" 9531 " {\n" 9532 " value /= float(gl_VertexID + 2);\n" 9533 "\n" 9534 " if (value <= 1.0f) break;\n" 9535 " }\n" 9536 "\n" 9537 " result = value;\n" 9538 " }\n" 9539 " else\n" 9540 " {\n" 9541 " vec4 value = vec4(gl_VertexID, gl_VertexID + 1,\n" 9542 " gl_VertexID + 2, gl_VertexID + 3);\n" 9543 "\n" 9544 " switch (gl_VertexID % 2)\n" 9545 " {\n" 9546 " case 0:\n" 9547 " {\n" 9548 " for (int iteration = 0; iteration < gl_VertexID && bool_operator2(); ++iteration)\n" 9549 " {\n" 9550 " value = vec4_operator2(vec4_operator1(value));\n" 9551 " }\n" 9552 "\n" 9553 " break;\n" 9554 " }\n" 9555 "\n" 9556 " case 1:\n" 9557 " {\n" 9558 " for (int iteration = 0; iteration < gl_VertexID * 2; ++iteration)\n" 9559 " {\n" 9560 " value = vec4_operator1(vec4_operator2(value));\n" 9561 " }\n" 9562 "\n" 9563 " break;\n" 9564 " }\n" 9565 " }\n" 9566 "\n" 9567 " result = value.x + value.y + value.z + value.w;\n" 9568 "\n" 9569 " }\n" 9570 "}\n"; 9571 } 9572 9573 /** Initializes all GL objects required to run the test. */ 9574 void FunctionalTest18_19::initTest() 9575 { 9576 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9577 const char* varyings[1] = { "result" }; 9578 std::string vs_body = getVertexShaderBody(); 9579 const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]); 9580 9581 if (!Utils::buildProgram(gl, vs_body, "", /* tc_body */ 9582 "", /* te_body */ 9583 "", /* gs_body */ 9584 "", /* fs_body */ 9585 varyings, n_varyings, &m_vs_id, DE_NULL, /* out_tc_id */ 9586 DE_NULL, /* out_te_id */ 9587 DE_NULL, /* out_gs_id */ 9588 DE_NULL, /* out_fs_id */ 9589 &m_po_id)) 9590 { 9591 TCU_FAIL("Failed to build test program object"); 9592 } 9593 9594 /* Retrieve subroutine & subroutine uniform locations */ 9595 m_po_subroutine_divide_by_two_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "divideByTwo"); 9596 m_po_subroutine_multiply_by_four_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "multiplyByFour"); 9597 m_po_subroutine_returns_false_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsFalse"); 9598 m_po_subroutine_returns_true_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsTrue"); 9599 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed"); 9600 9601 if (m_po_subroutine_divide_by_two_location == GL_INVALID_INDEX || 9602 m_po_subroutine_multiply_by_four_location == GL_INVALID_INDEX || 9603 m_po_subroutine_returns_false_location == GL_INVALID_INDEX || 9604 m_po_subroutine_returns_true_location == GL_INVALID_INDEX) 9605 { 9606 TCU_FAIL("glGetSubroutineIndex() returned GL_INVALID_INDEX for a valid subroutine"); 9607 } 9608 9609 m_po_subroutine_uniform_bool_operator1 = 9610 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator1"); 9611 m_po_subroutine_uniform_bool_operator2 = 9612 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator2"); 9613 m_po_subroutine_uniform_vec4_processor1 = 9614 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator1"); 9615 m_po_subroutine_uniform_vec4_processor2 = 9616 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator2"); 9617 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed"); 9618 9619 if (m_po_subroutine_uniform_bool_operator1 == -1 || m_po_subroutine_uniform_bool_operator2 == -1 || 9620 m_po_subroutine_uniform_vec4_processor1 == -1 || m_po_subroutine_uniform_vec4_processor2 == -1) 9621 { 9622 TCU_FAIL("glGetSubroutineUniformLocation() returned -1 for an active subroutine uniform"); 9623 } 9624 9625 /* Set up XFB BO */ 9626 const unsigned int bo_size = static_cast<unsigned int>(sizeof(float) * m_n_points_to_draw); 9627 9628 gl.genBuffers(1, &m_xfb_bo_id); 9629 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 9630 9631 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 9632 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 9633 9634 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 9635 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 9636 9637 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_COPY); 9638 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 9639 9640 /* Set up a VAO */ 9641 gl.genVertexArrays(1, &m_vao_id); 9642 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 9643 9644 gl.bindVertexArray(m_vao_id); 9645 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 9646 } 9647 9648 /** Executes test iteration. 9649 * 9650 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 9651 */ 9652 tcu::TestNode::IterateResult FunctionalTest18_19::iterate() 9653 { 9654 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 9655 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 9656 { 9657 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 9658 } 9659 9660 /* Initialize all GL objects required to run the test */ 9661 initTest(); 9662 9663 /* Iterate over all subroutine permutations */ 9664 const glw::GLuint subroutine_bool_operators[] = { m_po_subroutine_returns_false_location, 9665 m_po_subroutine_returns_true_location }; 9666 const unsigned int n_subroutine_bool_operators = 9667 sizeof(subroutine_bool_operators) / sizeof(subroutine_bool_operators[0]); 9668 9669 const glw::GLuint subroutine_vec4_operators[] = { m_po_subroutine_divide_by_two_location, 9670 m_po_subroutine_multiply_by_four_location }; 9671 const unsigned int n_subroutine_vec4_operators = 9672 sizeof(subroutine_vec4_operators) / sizeof(subroutine_vec4_operators[0]); 9673 9674 for (unsigned int n_subroutine_uniform_bool_operator1 = 0; 9675 n_subroutine_uniform_bool_operator1 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator1) 9676 { 9677 for (unsigned int n_subroutine_uniform_bool_operator2 = 0; 9678 n_subroutine_uniform_bool_operator2 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator2) 9679 { 9680 for (unsigned int n_subroutine_uniform_vec4_operator1 = 0; 9681 n_subroutine_uniform_vec4_operator1 < n_subroutine_vec4_operators; 9682 ++n_subroutine_uniform_vec4_operator1) 9683 { 9684 for (unsigned int n_subroutine_uniform_vec4_operator2 = 0; 9685 n_subroutine_uniform_vec4_operator2 < n_subroutine_vec4_operators; 9686 ++n_subroutine_uniform_vec4_operator2) 9687 { 9688 executeTest(subroutine_bool_operators[n_subroutine_uniform_bool_operator1], 9689 subroutine_bool_operators[n_subroutine_uniform_bool_operator2], 9690 subroutine_vec4_operators[n_subroutine_uniform_vec4_operator1], 9691 subroutine_vec4_operators[n_subroutine_uniform_vec4_operator2]); 9692 } /* for (all subroutine vec4 operator subroutines used for processor2) */ 9693 } /* for (all subroutine vec4 operator subroutines used for processor1) */ 9694 } /* for (all subroutine bool operator subroutines used for operator2) */ 9695 } /* for (all subroutine bool operator subroutines used for operator1) */ 9696 9697 /* All done */ 9698 if (m_has_test_passed) 9699 { 9700 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 9701 } 9702 else 9703 { 9704 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 9705 } 9706 9707 return STOP; 9708 } 9709 9710 /** Divides input argument by two. The result value is returned to the 9711 * caller. 9712 * 9713 * @param data Input value. 9714 * 9715 * @return As per description. 9716 **/ 9717 tcu::Vec4 FunctionalTest18_19::vec4operator_div2(tcu::Vec4 data) 9718 { 9719 return data * 0.5f; 9720 } 9721 9722 /** Multiplies input argument by four. The result value is returned to the 9723 * caller. 9724 * 9725 * @param data Input value. 9726 * 9727 * @return As per description. 9728 **/ 9729 tcu::Vec4 FunctionalTest18_19::vec4operator_mul4(tcu::Vec4 data) 9730 { 9731 return data * 4.0f; 9732 } 9733 9734 /** Verifies data XFBed out by the vertex shader. It is assumed the subroutines were configured 9735 * as per passed arguments, prior to the draw call. 9736 * 9737 * If the result data is found to be invalid, m_has_test_passed is set to false. 9738 * 9739 * @param data XFBed data. 9740 * @param bool_operator1_subroutine_location Location of a subroutine to be assigned to 9741 * bool_operator1 subroutine uniform. 9742 * @param bool_operator2_subroutine_location Location of a subroutine to be assigned to 9743 * bool_operator2 subroutine uniform. 9744 * @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to 9745 * vec4_operator1 subroutine uniform. 9746 * @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to 9747 * vec4_operator2 subroutine uniform. 9748 */ 9749 void FunctionalTest18_19::verifyXFBData(const glw::GLvoid* data, glw::GLuint bool_operator1_subroutine_location, 9750 glw::GLuint bool_operator2_subroutine_location, 9751 glw::GLuint vec4_operator1_subroutine_location, 9752 glw::GLuint vec4_operator2_subroutine_location) 9753 { 9754 bool bool_operator1_result = false; 9755 bool bool_operator2_result = false; 9756 const float epsilon = 1e-5f; 9757 PFNVEC4OPERATORPROC pVec4Operator1 = NULL; 9758 PFNVEC4OPERATORPROC pVec4Operator2 = NULL; 9759 const glw::GLfloat* traveller_ptr = (const glw::GLfloat*)data; 9760 9761 bool_operator1_result = (bool_operator1_subroutine_location == m_po_subroutine_returns_true_location); 9762 bool_operator2_result = (bool_operator2_subroutine_location == m_po_subroutine_returns_true_location); 9763 pVec4Operator1 = (vec4_operator1_subroutine_location == m_po_subroutine_divide_by_two_location) ? 9764 vec4operator_div2 : 9765 vec4operator_mul4; 9766 pVec4Operator2 = (vec4_operator2_subroutine_location == m_po_subroutine_divide_by_two_location) ? 9767 vec4operator_div2 : 9768 vec4operator_mul4; 9769 9770 for (unsigned int n_vertex = 0; n_vertex < m_n_points_to_draw; ++n_vertex) 9771 { 9772 float expected_value = 0.0f; 9773 9774 if (bool_operator1_result) 9775 { 9776 float value = float((3 * n_vertex + 1) * 2); 9777 9778 while (bool_operator1_result) 9779 { 9780 value /= float(n_vertex + 2); 9781 9782 if (value <= 1.0f) 9783 break; 9784 } 9785 9786 expected_value = value; 9787 } 9788 else 9789 { 9790 tcu::Vec4 value((float)n_vertex, (float)n_vertex + 1, (float)n_vertex + 2, (float)n_vertex + 3); 9791 9792 switch (n_vertex % 2) 9793 { 9794 case 0: 9795 { 9796 for (unsigned int iteration = 0; iteration < n_vertex && bool_operator2_result; ++iteration) 9797 { 9798 value = pVec4Operator2(pVec4Operator1(value)); 9799 } 9800 9801 break; 9802 } 9803 9804 case 1: 9805 { 9806 for (unsigned int iteration = 0; iteration < n_vertex * 2; ++iteration) 9807 { 9808 value = pVec4Operator1(pVec4Operator2(value)); 9809 } 9810 9811 break; 9812 } 9813 } /* switch (n_vertex % 2) */ 9814 9815 expected_value = value.x() + value.y() + value.z() + value.w(); 9816 } 9817 9818 if (de::abs(expected_value - *traveller_ptr) > epsilon) 9819 { 9820 m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data was found to be invalid at index [" << n_vertex 9821 << "]" 9822 "for the following subroutine location configuration:" 9823 " bool_operator1_subroutine_location:[" 9824 << bool_operator1_subroutine_location << "]" 9825 " bool_operator2_subroutine_location:[" 9826 << bool_operator2_subroutine_location << "]" 9827 " vec4_operator1_subroutine_location:[" 9828 << vec4_operator1_subroutine_location << "]" 9829 " vec4_operator2_subroutine_location:[" 9830 << vec4_operator2_subroutine_location << "];" 9831 " expected data:" 9832 << expected_value << ", found:" << *traveller_ptr << tcu::TestLog::EndMessage; 9833 9834 m_has_test_passed = false; 9835 } 9836 9837 ++traveller_ptr; 9838 } /* for (all drawn points) */ 9839 } 9840 9841 /* Constants used by FunctionalTest20_21 */ 9842 const GLuint FunctionalTest20_21::m_n_shared_contexts = 4; 9843 const GLuint FunctionalTest20_21::m_fragment_stage_index = 0; 9844 const GLuint FunctionalTest20_21::m_geometry_stage_index = 1; 9845 const GLuint FunctionalTest20_21::m_tesselation_control_stage_index = 2; 9846 const GLuint FunctionalTest20_21::m_tesselation_evaluation_stage_index = 3; 9847 const GLuint FunctionalTest20_21::m_vertex_stage_index = 4; 9848 9849 /** Set subroutine indices, indices are taken from one of two sets according to provided <bit_field> 9850 * 9851 * @param bit_field Selects source of of index for each stage 9852 * @param subroutine_indices Array of two indices sets 9853 **/ 9854 void FunctionalTest20_21::subroutineUniformSet::set(GLuint bit_field, const subroutineUniformSet subroutine_indices[2]) 9855 { 9856 GLuint vertex_stage = ((bit_field & (0x01 << 0)) >> 0); 9857 GLuint tesselation_control_stage = ((bit_field & (0x01 << 1)) >> 1); 9858 GLuint tesselation_evaluation_stage = ((bit_field & (0x01 << 2)) >> 2); 9859 GLuint geometry_stage = ((bit_field & (0x01 << 3)) >> 3); 9860 GLuint fragment_stage = ((bit_field & (0x01 << 4)) >> 4); 9861 9862 m_vertex_shader_stage = subroutine_indices[vertex_stage].m_vertex_shader_stage; 9863 m_tesselation_control_shader_stage = 9864 subroutine_indices[tesselation_control_stage].m_tesselation_control_shader_stage; 9865 m_tesselation_evaluation_shader_stage = 9866 subroutine_indices[tesselation_evaluation_stage].m_tesselation_evaluation_shader_stage; 9867 m_geometry_shader_stage = subroutine_indices[geometry_stage].m_geometry_shader_stage; 9868 m_fragment_shader_stage = subroutine_indices[fragment_stage].m_fragment_shader_stage; 9869 } 9870 9871 /** Negated comparison of two sets 9872 * 9873 * @param arg Instance that will be compared to this 9874 * 9875 * @return false when both objects are equal, true otherwise 9876 **/ 9877 bool FunctionalTest20_21::subroutineUniformSet::operator!=(const subroutineUniformSet& arg) const 9878 { 9879 if ((arg.m_vertex_shader_stage != m_vertex_shader_stage) || 9880 (arg.m_tesselation_control_shader_stage != m_tesselation_control_shader_stage) || 9881 (arg.m_tesselation_evaluation_shader_stage != m_tesselation_evaluation_shader_stage) || 9882 (arg.m_geometry_shader_stage != m_geometry_shader_stage) || 9883 (arg.m_fragment_shader_stage != m_fragment_shader_stage)) 9884 { 9885 return true; 9886 } 9887 9888 return false; 9889 } 9890 9891 /** Constructor. 9892 * 9893 * @param context Rendering context. 9894 * 9895 **/ 9896 FunctionalTest20_21::FunctionalTest20_21(deqp::Context& context) 9897 : TestCase(context, "multiple_contexts", 9898 "Verifies that shader uniforms are preserved when rendering context is switched.") 9899 { 9900 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i) 9901 { 9902 m_program_pipelines[i] = 0; 9903 } 9904 9905 for (GLuint i = 0; i < m_n_shared_contexts; ++i) 9906 { 9907 m_shared_contexts[i] = 0; 9908 } 9909 } 9910 9911 /** Deinitializes all GL objects that may have been created during 9912 * test execution. 9913 **/ 9914 void FunctionalTest20_21::deinit() 9915 { 9916 /* GL entry points */ 9917 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9918 9919 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i) 9920 { 9921 if (0 != m_program_pipelines[i]) 9922 { 9923 gl.deleteProgramPipelines(1, &m_program_pipelines[i]); 9924 m_program_pipelines[i] = 0; 9925 } 9926 } 9927 9928 for (GLuint i = 0; i < m_n_shared_contexts; ++i) 9929 { 9930 if (0 != m_shared_contexts[i]) 9931 { 9932 delete m_shared_contexts[i]; 9933 m_shared_contexts[i] = 0; 9934 } 9935 } 9936 9937 m_context.getRenderContext().makeCurrent(); 9938 } 9939 9940 /** Executes test iteration. 9941 * 9942 * @return Returns STOP 9943 */ 9944 tcu::TestNode::IterateResult FunctionalTest20_21::iterate() 9945 { 9946 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 9947 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 9948 { 9949 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 9950 } 9951 9952 /* Test cases, values stored here are used as bit fields */ 9953 static const GLuint test_cases[][m_n_shared_contexts + 1] = { 9954 { 0, 1, 2, 3, 4 }, { 1, 2, 3, 4, 0 }, { 2, 3, 4, 0, 1 }, { 3, 4, 0, 1, 2 }, 9955 { 4, 0, 1, 2, 3 }, { 27, 28, 29, 30, 31 }, { 28, 29, 30, 31, 27 }, { 29, 30, 31, 27, 28 }, 9956 { 30, 31, 27, 28, 29 }, { 31, 27, 28, 29, 30 }, 9957 }; 9958 static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]); 9959 9960 /* Prepare contexts */ 9961 initSharedContexts(); 9962 9963 /* Test result */ 9964 bool result = true; 9965 9966 /* Program pointers */ 9967 Utils::program* program_pointers[5]; 9968 9969 /* Test monolithic program */ 9970 { 9971 /* Prepare program */ 9972 Utils::program program(m_context); 9973 9974 program_pointers[m_fragment_stage_index] = &program; 9975 9976 prepareProgram(program_pointers, false); 9977 9978 /* Execute test */ 9979 if (false == testProgram(program_pointers, false, test_cases, n_test_cases)) 9980 { 9981 m_context.getTestContext().getLog() << tcu::TestLog::Message 9982 << "Last error message was caused by monolithic program." 9983 << tcu::TestLog::EndMessage; 9984 9985 result = false; 9986 } 9987 } 9988 9989 /* Test separable programs */ 9990 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects")) 9991 { 9992 /* Prepare programs */ 9993 Utils::program vertex_program(m_context); 9994 Utils::program tesselation_control_program(m_context); 9995 Utils::program tesselation_evaluation_program(m_context); 9996 Utils::program geometry_program(m_context); 9997 Utils::program fragment_program(m_context); 9998 9999 program_pointers[m_fragment_stage_index] = &fragment_program; 10000 program_pointers[m_geometry_stage_index] = &geometry_program; 10001 program_pointers[m_tesselation_control_stage_index] = &tesselation_control_program; 10002 program_pointers[m_tesselation_evaluation_stage_index] = &tesselation_evaluation_program; 10003 program_pointers[m_vertex_stage_index] = &vertex_program; 10004 10005 prepareProgram(program_pointers, true); 10006 10007 /* Execute test */ 10008 if (false == testProgram(program_pointers, true, test_cases, n_test_cases)) 10009 { 10010 m_context.getTestContext().getLog() << tcu::TestLog::Message 10011 << "Last error message was caused by separable program." 10012 << tcu::TestLog::EndMessage; 10013 result = false; 10014 } 10015 } 10016 10017 /* All done */ 10018 if (true == result) 10019 { 10020 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 10021 } 10022 else 10023 { 10024 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 10025 } 10026 10027 return tcu::TestNode::STOP; 10028 } 10029 10030 /** Query state of subroutine uniforms of current program/pipeline 10031 * 10032 * @param set Storage for results 10033 **/ 10034 void FunctionalTest20_21::captureCurrentSubroutineSet(subroutineUniformSet& set) 10035 { 10036 /* GL entry points */ 10037 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10038 10039 /* Fragment */ 10040 gl.getUniformSubroutineuiv(GL_FRAGMENT_SHADER, m_subroutine_uniform_locations.m_fragment_shader_stage, 10041 &set.m_fragment_shader_stage); 10042 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv"); 10043 10044 /* Geometry */ 10045 gl.getUniformSubroutineuiv(GL_GEOMETRY_SHADER, m_subroutine_uniform_locations.m_geometry_shader_stage, 10046 &set.m_geometry_shader_stage); 10047 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv"); 10048 10049 /* Tess ctrl */ 10050 gl.getUniformSubroutineuiv(GL_TESS_CONTROL_SHADER, 10051 m_subroutine_uniform_locations.m_tesselation_control_shader_stage, 10052 &set.m_tesselation_control_shader_stage); 10053 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv"); 10054 10055 /* Tess eval */ 10056 gl.getUniformSubroutineuiv(GL_TESS_EVALUATION_SHADER, 10057 m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage, 10058 &set.m_tesselation_evaluation_shader_stage); 10059 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv"); 10060 10061 /* Vertex */ 10062 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_subroutine_uniform_locations.m_vertex_shader_stage, 10063 &set.m_vertex_shader_stage); 10064 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv"); 10065 } 10066 10067 /** Get shaders' source code 10068 * 10069 * @param out_vertex_shader_code Vertex source code 10070 * @param out_tesselation_control_shader_code Tess ctrl source code 10071 * @param out_tesselation_evaluation_shader_code Tess eval source code 10072 * @param out_geometry_shader_code Geometry source code 10073 * @param out_fragment_shader_code Fragment source code 10074 **/ 10075 void FunctionalTest20_21::getShaders(const glw::GLchar*& out_vertex_shader_code, 10076 const glw::GLchar*& out_tesselation_control_shader_code, 10077 const glw::GLchar*& out_tesselation_evaluation_shader_code, 10078 const glw::GLchar*& out_geometry_shader_code, 10079 const glw::GLchar*& out_fragment_shader_code) 10080 { 10081 static const GLchar* vertex_shader_code = "#version 400 core\n" 10082 "#extension GL_ARB_shader_subroutine : require\n" 10083 "\n" 10084 "precision highp float;\n" 10085 "\n" 10086 "// Subroutine type\n" 10087 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n" 10088 "\n" 10089 "// Subroutine definition\n" 10090 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n" 10091 "{\n" 10092 " return left + right;\n" 10093 "}\n" 10094 "\n" 10095 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n" 10096 "{\n" 10097 " return left * right;\n" 10098 "}\n" 10099 "\n" 10100 "// Sub routine uniform\n" 10101 "subroutine uniform routine_type routine;\n" 10102 "\n" 10103 "// Input data\n" 10104 "uniform vec4 uni_vs_left;\n" 10105 "uniform vec4 uni_vs_right;\n" 10106 "\n" 10107 "// Output\n" 10108 "out vec4 vs_tcs_result;\n" 10109 "\n" 10110 "void main()\n" 10111 "{\n" 10112 " vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n" 10113 "}\n" 10114 "\n"; 10115 10116 static const GLchar* tesselation_control_shader_code = 10117 "#version 400 core\n" 10118 "#extension GL_ARB_shader_subroutine : require\n" 10119 "\n" 10120 "precision highp float;\n" 10121 "\n" 10122 "layout(vertices = 1) out;\n" 10123 "\n" 10124 "// Subroutine type\n" 10125 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n" 10126 "\n" 10127 "// Subroutine definition\n" 10128 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n" 10129 "{\n" 10130 " return left + right;\n" 10131 "}\n" 10132 "\n" 10133 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n" 10134 "{\n" 10135 " return left * right;\n" 10136 "}\n" 10137 "\n" 10138 "// Sub routine uniform\n" 10139 "subroutine uniform routine_type routine;\n" 10140 "\n" 10141 "// Input data\n" 10142 "uniform vec4 uni_tcs_left;\n" 10143 "uniform vec4 uni_tcs_right;\n" 10144 "\n" 10145 "in vec4 vs_tcs_result[];\n" 10146 "\n" 10147 "// Output\n" 10148 "out vec4 tcs_tes_result[];\n" 10149 "\n" 10150 "void main()\n" 10151 "{\n" 10152 " gl_TessLevelOuter[0] = 1.0;\n" 10153 " gl_TessLevelOuter[1] = 1.0;\n" 10154 " gl_TessLevelOuter[2] = 1.0;\n" 10155 " gl_TessLevelOuter[3] = 1.0;\n" 10156 " gl_TessLevelInner[0] = 1.0;\n" 10157 " gl_TessLevelInner[1] = 1.0;\n" 10158 "\n" 10159 " tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n" 10160 "}\n" 10161 "\n"; 10162 10163 static const GLchar* tesselation_evaluation_shader_code = 10164 "#version 400 core\n" 10165 "#extension GL_ARB_shader_subroutine : require\n" 10166 "\n" 10167 "precision highp float;\n" 10168 "\n" 10169 "layout(isolines, point_mode) in;\n" 10170 "\n" 10171 "// Subroutine type\n" 10172 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n" 10173 "\n" 10174 "// Subroutine definition\n" 10175 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n" 10176 "{\n" 10177 " return left + right;\n" 10178 "}\n" 10179 "\n" 10180 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n" 10181 "{\n" 10182 " return left * right;\n" 10183 "}\n" 10184 "\n" 10185 "// Sub routine uniform\n" 10186 "subroutine uniform routine_type routine;\n" 10187 "\n" 10188 "// Input data\n" 10189 "uniform vec4 uni_tes_left;\n" 10190 "uniform vec4 uni_tes_right;\n" 10191 "\n" 10192 "in vec4 tcs_tes_result[];\n" 10193 "\n" 10194 "// Output\n" 10195 "out vec4 tes_gs_result;\n" 10196 "\n" 10197 "void main()\n" 10198 "{\n" 10199 " tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n" 10200 "}\n" 10201 "\n"; 10202 10203 static const GLchar* geometry_shader_code = 10204 "#version 400 core\n" 10205 "#extension GL_ARB_shader_subroutine : require\n" 10206 "\n" 10207 "precision highp float;\n" 10208 "\n" 10209 "layout(points) in;\n" 10210 "layout(points, max_vertices = 1) out;\n" 10211 "\n" 10212 "// Subroutine type\n" 10213 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n" 10214 "\n" 10215 "// Subroutine definition\n" 10216 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n" 10217 "{\n" 10218 " return left + right;\n" 10219 "}\n" 10220 "\n" 10221 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n" 10222 "{\n" 10223 " return left * right;\n" 10224 "}\n" 10225 "\n" 10226 "// Sub routine uniform\n" 10227 "subroutine uniform routine_type routine;\n" 10228 "\n" 10229 "// Input data\n" 10230 "uniform vec4 uni_gs_left;\n" 10231 "uniform vec4 uni_gs_right;\n" 10232 "\n" 10233 "in vec4 tes_gs_result[];\n" 10234 "\n" 10235 "// Output\n" 10236 "out vec4 gs_fs_result;\n" 10237 "\n" 10238 "void main()\n" 10239 "{\n" 10240 " gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n" 10241 "}\n" 10242 "\n"; 10243 10244 static const GLchar* fragmenty_shader_code = 10245 "#version 400 core\n" 10246 "#extension GL_ARB_shader_subroutine : require\n" 10247 "\n" 10248 "precision highp float;\n" 10249 "\n" 10250 "// Subroutine type\n" 10251 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n" 10252 "\n" 10253 "// Subroutine definition\n" 10254 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n" 10255 "{\n" 10256 " return left + right;\n" 10257 "}\n" 10258 "\n" 10259 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n" 10260 "{\n" 10261 " return left * right;\n" 10262 "}\n" 10263 "\n" 10264 "// Sub routine uniform\n" 10265 "subroutine uniform routine_type routine;\n" 10266 "\n" 10267 "// Input data\n" 10268 "uniform vec4 uni_fs_left;\n" 10269 "uniform vec4 uni_fs_right;\n" 10270 "\n" 10271 "in vec4 gs_fs_result;\n" 10272 "\n" 10273 "// Output\n" 10274 "out vec4 fs_out_result;\n" 10275 "\n" 10276 "void main()\n" 10277 "{\n" 10278 " fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n" 10279 "}\n" 10280 "\n"; 10281 10282 out_vertex_shader_code = vertex_shader_code; 10283 out_tesselation_control_shader_code = tesselation_control_shader_code; 10284 out_tesselation_evaluation_shader_code = tesselation_evaluation_shader_code; 10285 out_geometry_shader_code = geometry_shader_code; 10286 out_fragment_shader_code = fragmenty_shader_code; 10287 } 10288 10289 /** Create <m_n_shared_contexts> shared contexts 10290 * 10291 **/ 10292 void FunctionalTest20_21::initSharedContexts() 10293 { 10294 for (GLuint i = 0; i < m_n_shared_contexts; ++i) 10295 { 10296 m_shared_contexts[i] = m_context.createSharedContext(); 10297 } 10298 } 10299 10300 /** Prepare program(s) 10301 * 10302 * @param programs An array of 5 programs' pointers. If monolithic program is prepared that only index m_fragment_stage_index should be initialized, otherwise all 5 10303 * @param is_separable Select if monolithic or separable programs should be prepared 10304 **/ 10305 void FunctionalTest20_21::prepareProgram(Utils::program** programs, bool is_separable) 10306 { 10307 /* Get shader sources */ 10308 const GLchar* vertex_shader_code; 10309 const GLchar* tesselation_control_shader_code; 10310 const GLchar* tesselation_evaluation_shader_code; 10311 const GLchar* geometry_shader_code; 10312 const GLchar* fragmenty_shader_code; 10313 10314 getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code, 10315 geometry_shader_code, fragmenty_shader_code); 10316 10317 /* Subroutines and uniform names */ 10318 static const GLchar* subroutine_names[] = { "add", "multiply" }; 10319 static const GLuint n_subroutines = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 10320 10321 static const GLchar* subroutine_uniform_name = "routine"; 10322 10323 /* Build program */ 10324 if (false == is_separable) 10325 { 10326 programs[0]->build(0 /* compute shader source */, fragmenty_shader_code, geometry_shader_code, 10327 tesselation_control_shader_code, tesselation_evaluation_shader_code, vertex_shader_code, 10328 0 /* varying_names */, 0 /* n_varying_names */); 10329 10330 programs[m_geometry_stage_index] = programs[m_fragment_stage_index]; 10331 programs[m_tesselation_control_stage_index] = programs[m_fragment_stage_index]; 10332 programs[m_tesselation_evaluation_stage_index] = programs[m_fragment_stage_index]; 10333 programs[m_vertex_stage_index] = programs[m_fragment_stage_index]; 10334 } 10335 else 10336 { 10337 programs[m_fragment_stage_index]->build(0, fragmenty_shader_code, 0, 0, 0, 0, 0, 0, true); 10338 programs[m_geometry_stage_index]->build(0, 0, geometry_shader_code, 0, 0, 0, 0, 0, true); 10339 programs[m_tesselation_control_stage_index]->build(0, 0, 0, tesselation_control_shader_code, 0, 0, 0, 0, true); 10340 programs[m_tesselation_evaluation_stage_index]->build(0, 0, 0, 0, tesselation_evaluation_shader_code, 0, 0, 0, 10341 true); 10342 programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true); 10343 } 10344 10345 /* Get subroutine indices */ 10346 for (GLuint i = 0; i < n_subroutines; ++i) 10347 { 10348 m_subroutine_indices[i].m_fragment_shader_stage = 10349 programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER); 10350 10351 m_subroutine_indices[i].m_geometry_shader_stage = 10352 programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER); 10353 10354 m_subroutine_indices[i].m_tesselation_control_shader_stage = 10355 programs[m_tesselation_control_stage_index]->getSubroutineIndex(subroutine_names[i], 10356 GL_TESS_CONTROL_SHADER); 10357 10358 m_subroutine_indices[i].m_tesselation_evaluation_shader_stage = 10359 programs[m_tesselation_evaluation_stage_index]->getSubroutineIndex(subroutine_names[i], 10360 GL_TESS_EVALUATION_SHADER); 10361 10362 m_subroutine_indices[i].m_vertex_shader_stage = 10363 programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER); 10364 } 10365 10366 /* Get subroutine uniform locations */ 10367 m_subroutine_uniform_locations.m_fragment_shader_stage = 10368 programs[m_fragment_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_FRAGMENT_SHADER); 10369 10370 m_subroutine_uniform_locations.m_geometry_shader_stage = 10371 programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER); 10372 10373 m_subroutine_uniform_locations.m_tesselation_control_shader_stage = 10374 programs[m_tesselation_control_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, 10375 GL_TESS_CONTROL_SHADER); 10376 10377 m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage = 10378 programs[m_tesselation_evaluation_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, 10379 GL_TESS_EVALUATION_SHADER); 10380 10381 m_subroutine_uniform_locations.m_vertex_shader_stage = 10382 programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER); 10383 } 10384 10385 /** Generate program pipeline for current context and attach separable programs 10386 * 10387 * @param out_pipeline_id Id of generated pipeline 10388 * @param programs Collection of separable programs 10389 **/ 10390 void FunctionalTest20_21::prepareProgramPipeline(glw::GLuint& out_pipeline_id, Utils::program** programs) 10391 { 10392 /* GL entry points */ 10393 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10394 10395 /* Generate */ 10396 gl.genProgramPipelines(1, &out_pipeline_id); 10397 GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines"); 10398 10399 /* Bind */ 10400 gl.bindProgramPipeline(out_pipeline_id); 10401 GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline"); 10402 10403 /* Set up programs */ 10404 gl.useProgramStages(out_pipeline_id, GL_FRAGMENT_SHADER_BIT, programs[m_fragment_stage_index]->m_program_object_id); 10405 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages"); 10406 10407 gl.useProgramStages(out_pipeline_id, GL_GEOMETRY_SHADER_BIT, programs[m_geometry_stage_index]->m_program_object_id); 10408 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages"); 10409 10410 gl.useProgramStages(out_pipeline_id, GL_TESS_CONTROL_SHADER_BIT, 10411 programs[m_tesselation_control_stage_index]->m_program_object_id); 10412 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages"); 10413 10414 gl.useProgramStages(out_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT, 10415 programs[m_tesselation_evaluation_stage_index]->m_program_object_id); 10416 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages"); 10417 10418 gl.useProgramStages(out_pipeline_id, GL_VERTEX_SHADER_BIT, programs[m_vertex_stage_index]->m_program_object_id); 10419 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages"); 10420 } 10421 10422 /** Test specific case 10423 * 10424 * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context 10425 * 10426 * @return True if test pass, false otherwise 10427 **/ 10428 bool FunctionalTest20_21::testCase(const glw::GLuint bit_field[5]) 10429 { 10430 /* Storage for subroutine indices */ 10431 subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1]; 10432 subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1]; 10433 10434 /* Prepare subroutine_indices with bit fields */ 10435 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i) 10436 { 10437 subroutine_indices[i].set(bit_field[i], m_subroutine_indices); 10438 }; 10439 10440 /* Update subroutine uniforms, each context gets different set */ 10441 for (GLuint i = 0; i < m_n_shared_contexts; ++i) 10442 { 10443 m_shared_contexts[i]->makeCurrent(); 10444 updateCurrentSubroutineSet(subroutine_indices[i]); 10445 } 10446 10447 m_context.getRenderContext().makeCurrent(); 10448 updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]); 10449 10450 /* Capture subroutine uniforms */ 10451 for (GLuint i = 0; i < m_n_shared_contexts; ++i) 10452 { 10453 m_shared_contexts[i]->makeCurrent(); 10454 captureCurrentSubroutineSet(captured_subroutine_indices[i]); 10455 } 10456 10457 m_context.getRenderContext().makeCurrent(); 10458 captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]); 10459 10460 /* Verify that captured uniforms match expected values */ 10461 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i) 10462 { 10463 if (subroutine_indices[i] != captured_subroutine_indices[i]) 10464 { 10465 m_context.getTestContext().getLog() 10466 << tcu::TestLog::Message << "Error." 10467 << " Context: " << i << " VS, expected: " << subroutine_indices[i].m_vertex_shader_stage 10468 << " captured: " << captured_subroutine_indices[i].m_vertex_shader_stage 10469 << " TCS, expected: " << subroutine_indices[i].m_tesselation_control_shader_stage 10470 << " captured: " << captured_subroutine_indices[i].m_tesselation_control_shader_stage 10471 << " TES, expected: " << subroutine_indices[i].m_tesselation_evaluation_shader_stage 10472 << " captured: " << captured_subroutine_indices[i].m_tesselation_evaluation_shader_stage 10473 << " GS, expected: " << subroutine_indices[i].m_geometry_shader_stage 10474 << " captured: " << captured_subroutine_indices[i].m_geometry_shader_stage 10475 << " FS, expected: " << subroutine_indices[i].m_fragment_shader_stage 10476 << " captured: " << captured_subroutine_indices[i].m_fragment_shader_stage << tcu::TestLog::EndMessage; 10477 10478 return false; 10479 } 10480 } 10481 10482 return true; 10483 } 10484 10485 /** Test a program or pipeline 10486 * 10487 * @param programs An array of 5 programs\ pointers, as in preparePrograms 10488 * @param is_separable Selects if monolithic or separable programs should be used 10489 * @param test_cases Collection of test cases 10490 * @param n_test_cases Number of test cases 10491 * 10492 * @return True if all cases pass, false otherwise 10493 **/ 10494 bool FunctionalTest20_21::testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5], 10495 glw::GLuint n_test_cases) 10496 { 10497 /* Set program/pipeline as current for all contexts */ 10498 if (false == is_separable) 10499 { 10500 programs[0]->use(); 10501 10502 for (GLuint i = 0; i < m_n_shared_contexts; ++i) 10503 { 10504 m_shared_contexts[i]->makeCurrent(); 10505 programs[0]->use(); 10506 } 10507 } 10508 else 10509 { 10510 /* GL entry points */ 10511 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10512 10513 /* Make sure that program pipeline will be used */ 10514 gl.useProgram(0); 10515 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 10516 10517 prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs); 10518 10519 for (GLuint i = 0; i < m_n_shared_contexts; ++i) 10520 { 10521 m_shared_contexts[i]->makeCurrent(); 10522 10523 /* Make sure that program pipeline will be used */ 10524 gl.useProgram(0); 10525 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 10526 10527 prepareProgramPipeline(m_program_pipelines[i], programs); 10528 } 10529 } 10530 10531 /* Execute test */ 10532 bool result = true; 10533 for (GLuint i = 0; i < n_test_cases; ++i) 10534 { 10535 if (false == testCase(test_cases[i])) 10536 { 10537 result = false; 10538 break; 10539 } 10540 } 10541 10542 return result; 10543 } 10544 10545 /** Set up subroutine uniforms for current program or pipeline 10546 * 10547 * @param set Set of subroutine indices 10548 **/ 10549 void FunctionalTest20_21::updateCurrentSubroutineSet(const subroutineUniformSet& set) 10550 { 10551 /* GL entry points */ 10552 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10553 10554 /* Fragment */ 10555 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage); 10556 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 10557 10558 /* Geometry */ 10559 gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage); 10560 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 10561 10562 /* Tess ctrl */ 10563 gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage); 10564 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 10565 10566 /* Tess eval */ 10567 gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage); 10568 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 10569 10570 /* Vertex */ 10571 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage); 10572 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 10573 } 10574 10575 /** Constructor. 10576 * 10577 * @param context Rendering context. 10578 * 10579 **/ 10580 NegativeTest1::NegativeTest1(deqp::Context& context) 10581 : TestCase(context, "subroutine_errors", "Verifies all GL_INVALID_OPERATION, GL_INVALID_VALUE, GL_INVALID ENUM " 10582 "errors related to subroutine usage are properly generated.") 10583 , m_has_test_passed(true) 10584 , m_po_active_subroutine_uniform_locations(0) 10585 , m_po_active_subroutine_uniforms(0) 10586 , m_po_active_subroutines(0) 10587 , m_po_subroutine_uniform_function_index(-1) 10588 , m_po_subroutine_uniform_function2_index(-1) 10589 , m_po_subroutine_test1_index(GL_INVALID_INDEX) 10590 , m_po_subroutine_test2_index(GL_INVALID_INDEX) 10591 , m_po_subroutine_test3_index(GL_INVALID_INDEX) 10592 , m_po_not_linked_id(0) 10593 , m_po_id(0) 10594 , m_vs_id(0) 10595 { 10596 /* Left blank intentionally */ 10597 } 10598 10599 /** Deinitializes all GL objects that may have been created during 10600 * test execution. 10601 **/ 10602 void NegativeTest1::deinit() 10603 { 10604 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10605 10606 if (m_po_id != 0) 10607 { 10608 gl.deleteProgram(m_po_id); 10609 10610 m_po_id = 0; 10611 } 10612 10613 if (m_po_not_linked_id != 0) 10614 { 10615 gl.deleteProgram(m_po_not_linked_id); 10616 10617 m_po_not_linked_id = 0; 10618 } 10619 10620 if (m_vs_id != 0) 10621 { 10622 gl.deleteShader(m_vs_id); 10623 10624 m_vs_id = 0; 10625 } 10626 } 10627 10628 /** Initializes all GL objects required to run the test. */ 10629 void NegativeTest1::initTest() 10630 { 10631 glw::GLint compile_status = GL_FALSE; 10632 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10633 10634 /* Create program objects */ 10635 m_po_not_linked_id = gl.createProgram(); 10636 m_po_id = gl.createProgram(); 10637 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed."); 10638 10639 /* Create vertex shader object */ 10640 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 10641 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 10642 10643 /* Set up vertex shader */ 10644 const char* vs_body = "#version 400\n" 10645 "\n" 10646 "#extension GL_ARB_shader_subroutine : require\n" 10647 "\n" 10648 "subroutine void subroutineType (out ivec2 arg);\n" 10649 "subroutine void subroutineType2(out ivec4 arg);\n" 10650 "\n" 10651 "subroutine(subroutineType) void test1(out ivec2 arg)\n" 10652 "{\n" 10653 " arg = ivec2(1, 2);\n" 10654 "}\n" 10655 "subroutine(subroutineType) void test2(out ivec2 arg)\n" 10656 "{\n" 10657 " arg = ivec2(3,4);\n" 10658 "}\n" 10659 "subroutine(subroutineType2) void test3(out ivec4 arg)\n" 10660 "{\n" 10661 " arg = ivec4(1, 2, 3, 4);\n" 10662 "}\n" 10663 "\n" 10664 "subroutine uniform subroutineType function;\n" 10665 "subroutine uniform subroutineType2 function2;\n" 10666 "\n" 10667 "void main()\n" 10668 "{\n" 10669 " ivec2 test;\n" 10670 " ivec4 test2;\n" 10671 "\n" 10672 " function(test);\n" 10673 "\n" 10674 " if (test.x > 2)\n" 10675 " {\n" 10676 " gl_Position = vec4(1);\n" 10677 " }\n" 10678 " else\n" 10679 " {\n" 10680 " function2(test2);\n" 10681 "\n" 10682 " gl_Position = vec4(float(test2.x) );\n" 10683 " }\n" 10684 "}\n"; 10685 10686 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */); 10687 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 10688 10689 gl.compileShader(m_vs_id); 10690 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 10691 10692 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); 10693 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 10694 10695 if (compile_status == GL_FALSE) 10696 { 10697 TCU_FAIL("Shader compilation failed"); 10698 } 10699 10700 /* Set up & link the test program object */ 10701 glw::GLint link_status = GL_FALSE; 10702 10703 gl.attachShader(m_po_id, m_vs_id); 10704 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 10705 10706 gl.linkProgram(m_po_id); 10707 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 10708 10709 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 10710 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 10711 10712 if (link_status == GL_FALSE) 10713 { 10714 TCU_FAIL("Program linking failed"); 10715 } 10716 10717 /* Query test program object's properties */ 10718 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, 10719 &m_po_active_subroutine_uniform_locations); 10720 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &m_po_active_subroutine_uniforms); 10721 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &m_po_active_subroutines); 10722 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call(s) failed."); 10723 10724 if (m_po_active_subroutine_uniform_locations != 2) 10725 { 10726 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS value returned"); 10727 } 10728 10729 m_po_subroutine_test1_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test1"); 10730 m_po_subroutine_test2_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test2"); 10731 m_po_subroutine_test3_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test3"); 10732 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 10733 10734 if (m_po_subroutine_test1_index == GL_INVALID_INDEX || m_po_subroutine_test2_index == GL_INVALID_INDEX || 10735 m_po_subroutine_test3_index == GL_INVALID_INDEX) 10736 { 10737 TCU_FAIL("Invalid subroutine index returned"); 10738 } 10739 10740 m_po_subroutine_uniform_function_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function"); 10741 m_po_subroutine_uniform_function2_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function2"); 10742 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed."); 10743 10744 if (m_po_subroutine_uniform_function_index == -1 || m_po_subroutine_uniform_function2_index == -1) 10745 { 10746 TCU_FAIL("Invalid subroutine uniform index returned"); 10747 } 10748 } 10749 10750 /** Executes test iteration. 10751 * 10752 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10753 */ 10754 tcu::TestNode::IterateResult NegativeTest1::iterate() 10755 { 10756 glw::GLenum error_code = GL_NO_ERROR; 10757 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10758 10759 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 10760 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 10761 { 10762 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 10763 } 10764 10765 /* Initialize GL objects required to run the test */ 10766 initTest(); 10767 10768 /* The error INVALID_OPERATION is generated by GetSubroutineUniformLocation 10769 * if the program object identified by <program> has not been successfully 10770 * linked. 10771 */ 10772 gl.getSubroutineUniformLocation(m_po_not_linked_id, GL_FRAGMENT_SHADER, "subroutine_uniform_name"); 10773 10774 error_code = gl.getError(); 10775 10776 if (error_code != GL_INVALID_OPERATION) 10777 { 10778 m_testCtx.getLog() << tcu::TestLog::Message 10779 << "glGetSubroutineUniformLocation() does not generate GL_INVALID_OPERATION " 10780 "error code when called for a non-linked program object." 10781 << tcu::TestLog::EndMessage; 10782 10783 m_has_test_passed = false; 10784 } 10785 10786 /* The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or 10787 * GetActiveSubroutineUniformName if <index> is greater than or equal to the 10788 * value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage. 10789 */ 10790 glw::GLint temp_length = 0; 10791 glw::GLint temp_values = 0; 10792 10793 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 10794 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values); 10795 error_code = gl.getError(); 10796 10797 if (error_code == GL_INVALID_VALUE) 10798 { 10799 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1, 10800 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values); 10801 10802 error_code = gl.getError(); 10803 } 10804 10805 if (error_code != GL_INVALID_VALUE) 10806 { 10807 m_testCtx.getLog() << tcu::TestLog::Message 10808 << "glGetActiveSubroutineUniformiv() does not generate GL_INVALID_VALUE " 10809 "when passed <index> argument that is greater than or equal to " 10810 "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS." 10811 << tcu::TestLog::EndMessage; 10812 10813 m_has_test_passed = false; 10814 } 10815 10816 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 0, /* bufsize */ 10817 &temp_length, DE_NULL); /* name */ 10818 error_code = gl.getError(); 10819 10820 if (error_code == GL_INVALID_VALUE) 10821 { 10822 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1, 10823 0, /* bufsize */ 10824 &temp_length, DE_NULL); /* name */ 10825 10826 error_code = gl.getError(); 10827 } 10828 10829 if (error_code != GL_INVALID_VALUE) 10830 { 10831 m_testCtx.getLog() << tcu::TestLog::Message 10832 << "glGetActiveSubroutineUniformName() does not generate GL_INVALID_VALUE " 10833 "when passed <index> argument that is greater than or equal to " 10834 "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS." 10835 << tcu::TestLog::EndMessage; 10836 10837 m_has_test_passed = false; 10838 } 10839 10840 /* The error INVALID_VALUE is generated by GetActiveSubroutineName if <index> 10841 * is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader 10842 * stage. 10843 */ 10844 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines, 0, /* bufsize */ 10845 &temp_length, DE_NULL); /* name */ 10846 error_code = gl.getError(); 10847 10848 if (error_code == GL_INVALID_VALUE) 10849 { 10850 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines + 1, 0, /* bufsize */ 10851 &temp_length, DE_NULL); /* name */ 10852 10853 error_code = gl.getError(); 10854 } 10855 10856 if (error_code != GL_INVALID_VALUE) 10857 { 10858 m_testCtx.getLog() << tcu::TestLog::Message << "glGetActiveSubroutineName() does not generate GL_INVALID_VALUE " 10859 "when passed <index> argument that is greater than or equal to " 10860 "the value of GL_ACTIVE_SUBROUTINES." 10861 << tcu::TestLog::EndMessage; 10862 10863 m_has_test_passed = false; 10864 } 10865 10866 /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count> 10867 * is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the 10868 * shader stage <shadertype>. 10869 */ 10870 glw::GLuint index = 0; 10871 10872 gl.useProgram(m_po_id); 10873 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10874 10875 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations - 1, &index); 10876 error_code = gl.getError(); 10877 10878 if (error_code == GL_INVALID_VALUE) 10879 { 10880 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &index); 10881 10882 error_code = gl.getError(); 10883 } 10884 10885 if (error_code != GL_INVALID_VALUE) 10886 { 10887 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesiv() does not generate GL_INVALID_VALUE " 10888 "when passed <count> argument that is not equal to the value of " 10889 "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS." 10890 << tcu::TestLog::EndMessage; 10891 10892 m_has_test_passed = false; 10893 } 10894 10895 /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value 10896 * in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES 10897 * for the shader stage. 10898 */ 10899 glw::GLuint invalid_subroutine_indices[4] = { (GLuint)m_po_active_subroutines, (GLuint)m_po_active_subroutines, 10900 (GLuint)m_po_active_subroutines + 1, 10901 (GLuint)m_po_active_subroutines + 1 }; 10902 10903 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, /* count */ 10904 invalid_subroutine_indices + 0); 10905 error_code = gl.getError(); 10906 10907 if (error_code == GL_INVALID_VALUE) 10908 { 10909 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, 10910 invalid_subroutine_indices + 2); 10911 10912 error_code = gl.getError(); 10913 } 10914 10915 if (error_code != GL_INVALID_VALUE) 10916 { 10917 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesuiv() does not generate GL_INVALID_VALUE " 10918 "when the value passed via <indices> argument is greater than " 10919 "or equal to the value of GL_ACTIVE_SUBROUTINES." 10920 << tcu::TestLog::EndMessage; 10921 10922 m_has_test_passed = false; 10923 } 10924 10925 /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv() if any 10926 * subroutine index in <indices> identifies a subroutine not associated with 10927 * the type of the subroutine uniform variable assigned to the corresponding 10928 * location. 10929 */ 10930 glw::GLuint invalid_subroutine_indices2[2] = { m_po_subroutine_test1_index, m_po_subroutine_test1_index }; 10931 10932 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, invalid_subroutine_indices2); 10933 error_code = gl.getError(); 10934 10935 if (error_code != GL_INVALID_OPERATION) 10936 { 10937 m_testCtx.getLog() << tcu::TestLog::Message 10938 << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION " 10939 "when the subroutine index passed via <indices> argument identifies" 10940 "a subroutine not associated with the type of the subroutine uniform " 10941 "assigned to the corresponding location." 10942 << tcu::TestLog::EndMessage; 10943 10944 m_has_test_passed = false; 10945 } 10946 10947 /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no 10948 * program is active. 10949 */ 10950 glw::GLuint valid_subroutine_locations[2] = { 0 }; 10951 10952 valid_subroutine_locations[m_po_subroutine_uniform_function_index] = m_po_subroutine_test1_index; 10953 valid_subroutine_locations[m_po_subroutine_uniform_function2_index] = m_po_subroutine_test3_index; 10954 10955 gl.useProgram(0); 10956 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10957 10958 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, valid_subroutine_locations); 10959 error_code = gl.getError(); 10960 10961 if (error_code != GL_INVALID_OPERATION) 10962 { 10963 m_testCtx.getLog() << tcu::TestLog::Message 10964 << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION " 10965 "when called without an active program object." 10966 << tcu::TestLog::EndMessage; 10967 10968 m_has_test_passed = false; 10969 } 10970 10971 /* The error INVALID_VALUE is generated by GetUniformSubroutineuiv if 10972 * <location> is greater than or equal to the value of 10973 * ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage. 10974 */ 10975 glw::GLuint temp_value = 0; 10976 10977 gl.useProgram(m_po_id); 10978 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10979 10980 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, &temp_value); 10981 error_code = gl.getError(); 10982 10983 if (error_code == GL_INVALID_VALUE) 10984 { 10985 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &temp_value); 10986 error_code = gl.getError(); 10987 } 10988 10989 if (error_code != GL_INVALID_VALUE) 10990 { 10991 m_testCtx.getLog() << tcu::TestLog::Message 10992 << "glGetUniformSubroutineuiv() does not generate GL_INVALID_VALUE " 10993 "when called for location that is greater than or equal to the value " 10994 "of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS." 10995 << tcu::TestLog::EndMessage; 10996 10997 m_has_test_passed = false; 10998 } 10999 11000 /* The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no 11001 * program is active for the shader stage identified by <shadertype>. 11002 */ 11003 const glw::GLenum undefined_shader_stages[] = { GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER, 11004 GL_TESS_EVALUATION_SHADER }; 11005 const unsigned int n_undefined_shader_stages = sizeof(undefined_shader_stages) / sizeof(undefined_shader_stages[0]); 11006 11007 for (unsigned int n_undefined_shader_stage = 0; n_undefined_shader_stage < n_undefined_shader_stages; 11008 ++n_undefined_shader_stage) 11009 { 11010 glw::GLenum shader_stage = undefined_shader_stages[n_undefined_shader_stage]; 11011 11012 gl.getUniformSubroutineuiv(shader_stage, 0, /* location */ 11013 &temp_value); 11014 error_code = gl.getError(); 11015 11016 if (error_code != GL_INVALID_OPERATION) 11017 { 11018 m_testCtx.getLog() << tcu::TestLog::Message 11019 << "glGetUniformSubroutineuiv() does not generate GL_INVALID_OPERATION " 11020 "when called for a shader stage that is not defined for active " 11021 "program object." 11022 << tcu::TestLog::EndMessage; 11023 11024 m_has_test_passed = false; 11025 } 11026 } /* for (all undefined shader stages) */ 11027 11028 /* All done */ 11029 if (m_has_test_passed) 11030 { 11031 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11032 } 11033 else 11034 { 11035 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11036 } 11037 11038 return STOP; 11039 } 11040 11041 /** Constructor 11042 * 11043 * @param context Rendering context. 11044 * 11045 **/ 11046 NegativeTest2::NegativeTest2(deqp::Context& context) 11047 : TestCase(context, "subroutine_uniform_scope", "Verifies subroutine uniforms declared in shader stage A" 11048 "cannot be accessed from a different stage.") 11049 , m_fs_id(0) 11050 , m_gs_id(0) 11051 , m_has_test_passed(true) 11052 , m_po_id(0) 11053 , m_tc_id(0) 11054 , m_te_id(0) 11055 , m_vs_id(0) 11056 { 11057 /* Left blank intentionally */ 11058 } 11059 11060 /** Deinitializes all GL objects that may have been created during test execution */ 11061 void NegativeTest2::deinit() 11062 { 11063 deinitGLObjects(); 11064 } 11065 11066 /** Deinitializes all GL objects that may have been created during test execution */ 11067 void NegativeTest2::deinitGLObjects() 11068 { 11069 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11070 11071 if (m_fs_id != 0) 11072 { 11073 gl.deleteShader(m_fs_id); 11074 11075 m_fs_id = 0; 11076 } 11077 11078 if (m_gs_id != 0) 11079 { 11080 gl.deleteShader(m_gs_id); 11081 11082 m_gs_id = 0; 11083 } 11084 11085 if (m_tc_id != 0) 11086 { 11087 gl.deleteShader(m_tc_id); 11088 11089 m_tc_id = 0; 11090 } 11091 11092 if (m_te_id != 0) 11093 { 11094 gl.deleteShader(m_te_id); 11095 11096 m_te_id = 0; 11097 } 11098 11099 if (m_vs_id != 0) 11100 { 11101 gl.deleteShader(m_vs_id); 11102 11103 m_vs_id = 0; 11104 } 11105 11106 if (m_po_id != 0) 11107 { 11108 gl.deleteProgram(m_po_id); 11109 11110 m_po_id = 0; 11111 } 11112 } 11113 11114 /** Builds an offending program object and tries to link it. We're either expecting 11115 * a compile-time or link-time error here. 11116 * 11117 * If the program object builds successfully, the test has failed. 11118 * 11119 * @param referencing_stage Shader stage which defines a subroutine uniform that 11120 * should be called from fragment/geometry/tess control/ 11121 * tess evaluation/vertex shader stages. 11122 * 11123 **/ 11124 void NegativeTest2::executeTestCase(const Utils::_shader_stage& referencing_stage) 11125 { 11126 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11127 11128 const std::string fs_body = getFragmentShaderBody(referencing_stage); 11129 const std::string gs_body = getGeometryShaderBody(referencing_stage); 11130 const std::string tc_body = getTessellationControlShaderBody(referencing_stage); 11131 const std::string te_body = getTessellationEvaluationShaderBody(referencing_stage); 11132 const std::string vs_body = getVertexShaderBody(referencing_stage); 11133 11134 if (Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, NULL, /* xfb_varyings */ 11135 0, /* n_xfb_varyings */ 11136 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 11137 { 11138 /* Test program should not have built correctly ! */ 11139 m_testCtx.getLog() << tcu::TestLog::Message << "In the following program, one of the stages references " 11140 "a subroutine that is defined in another stage. This " 11141 "is forbidden by the specification.\n" 11142 "\n" 11143 "Vertex shader:\n\n" 11144 << vs_body.c_str() << "\n\nTessellation control shader:\n\n" 11145 << tc_body.c_str() << "\n\nTessellation evaluation shader:\n\n" 11146 << te_body.c_str() << "\n\nGeometry shader:\n\n" 11147 << gs_body.c_str() << "\n\nFragment shader:\n\n" 11148 << fs_body.c_str() << tcu::TestLog::EndMessage; 11149 11150 m_has_test_passed = false; 11151 } /* if (test program was built successfully) */ 11152 11153 /* Release the shaders & the program object that buildProgram() created */ 11154 deinitGLObjects(); 11155 } 11156 11157 /** Retrieves an offending fragment shader body. 11158 * 11159 * @param referencing_stage Shader stage which defines the subroutine uniform that 11160 * will be called from fragment shader. 11161 * 11162 * @return Requested string. 11163 **/ 11164 std::string NegativeTest2::getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const 11165 { 11166 std::stringstream result; 11167 11168 /* Form the pre-amble */ 11169 result << "#version 400\n" 11170 "\n" 11171 "#extension GL_ARB_shader_subroutine : require\n" 11172 "\n" 11173 "subroutine void testSubroutineType(out vec4 test_argument);\n" 11174 "\n" 11175 /* Define a subroutine */ 11176 "subroutine(testSubroutineType) void fs_subroutine(out vec4 test_argument)\n" 11177 "{\n" 11178 " test_argument = vec4(1, 0, 0, 0);\n" 11179 "}\n" 11180 "\n" 11181 /* Define output variables */ 11182 "out vec4 result;\n" 11183 "\n" 11184 /* Define uniforms */ 11185 "subroutine uniform testSubroutineType test_fs_subroutine;\n" 11186 "\n" 11187 /* Define main() */ 11188 "void main()\n" 11189 "{\n" 11190 " " 11191 << getSubroutineUniformName(referencing_stage) << "(result);\n" 11192 "}\n"; 11193 11194 return result.str(); 11195 } 11196 11197 /** Retrieves an offending geometry shader body. 11198 * 11199 * @param referencing_stage Shader stage which defines the subroutine uniform that 11200 * will be called from geometry shader. 11201 * 11202 * @return Requested string. 11203 **/ 11204 std::string NegativeTest2::getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const 11205 { 11206 std::stringstream result; 11207 11208 /* Form the pre-amble */ 11209 result << "#version 400\n" 11210 "\n" 11211 "#extension GL_ARB_shader_subroutine : require\n" 11212 "\n" 11213 "subroutine void testSubroutineType(out vec4 test_argument);\n" 11214 "\n" 11215 "layout(points) in;\n" 11216 "layout(points, max_vertices = 1) out;\n" 11217 "\n" 11218 /* Define a subroutine */ 11219 "subroutine(testSubroutineType) void gs_subroutine(out vec4 test_argument)\n" 11220 "{\n" 11221 " test_argument = vec4(0, 1, 1, 1);\n" 11222 "}\n" 11223 "\n" 11224 /* Define output variables */ 11225 "out vec4 result;\n" 11226 "\n" 11227 /* Define uniforms */ 11228 "subroutine uniform testSubroutineType test_gs_subroutine;\n" 11229 "\n" 11230 /* Define main() */ 11231 "void main()\n" 11232 "{\n" 11233 " " 11234 << getSubroutineUniformName(referencing_stage) << "(result);\n" 11235 "}\n"; 11236 11237 return result.str(); 11238 } 11239 11240 /** Retrieves name of the subroutine uniform that is defined in user-specified 11241 * shader stage. 11242 * 11243 * @param stage Shader stage to retrieve the subroutine uniform name for. 11244 * 11245 * @return As per description. 11246 **/ 11247 std::string NegativeTest2::getSubroutineUniformName(const Utils::_shader_stage& stage) const 11248 { 11249 std::string result = "?"; 11250 11251 switch (stage) 11252 { 11253 case Utils::SHADER_STAGE_FRAGMENT: 11254 { 11255 result = "test_fs_subroutine"; 11256 11257 break; 11258 } 11259 11260 case Utils::SHADER_STAGE_GEOMETRY: 11261 { 11262 result = "test_gs_subroutine"; 11263 11264 break; 11265 } 11266 11267 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 11268 { 11269 result = "test_tc_subroutine"; 11270 11271 break; 11272 } 11273 11274 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 11275 { 11276 result = "test_te_subroutine"; 11277 11278 break; 11279 } 11280 11281 case Utils::SHADER_STAGE_VERTEX: 11282 { 11283 result = "test_vs_subroutine"; 11284 11285 break; 11286 } 11287 11288 default: 11289 { 11290 TCU_FAIL("Unrecognized shader stage requested"); 11291 } 11292 } /* switch (stage) */ 11293 11294 return result; 11295 } 11296 11297 /** Retrieves an offending tessellation control shader body. 11298 * 11299 * @param referencing_stage Shader stage which defines the subroutine uniform that 11300 * will be called from tessellation control shader. 11301 * 11302 * @return Requested string. 11303 **/ 11304 std::string NegativeTest2::getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const 11305 { 11306 std::stringstream result; 11307 11308 /* Form the pre-amble */ 11309 result << "#version 400\n" 11310 "\n" 11311 "#extension GL_ARB_shader_subroutine : require\n" 11312 "\n" 11313 "layout(vertices = 4) out;\n" 11314 "\n" 11315 "subroutine void testSubroutineType(out vec4 test_argument);\n" 11316 "\n" 11317 /* Define a subroutine */ 11318 "subroutine(testSubroutineType) void tc_subroutine(out vec4 test_argument)\n" 11319 "{\n" 11320 " test_argument = vec4(0, 0, 1, 0);\n" 11321 "}\n" 11322 "\n" 11323 /* Define uniforms */ 11324 "subroutine uniform testSubroutineType test_tc_subroutine;\n" 11325 "\n" 11326 /* Define main() */ 11327 "void main()\n" 11328 "{\n" 11329 " " 11330 << getSubroutineUniformName(referencing_stage) << "(gl_out[gl_InvocationID].gl_Position);\n" 11331 "}\n"; 11332 11333 return result.str(); 11334 } 11335 11336 /** Retrieves an offending tessellation evaluation shader body. 11337 * 11338 * @param referencing_stage Shader stage which defines the subroutine uniform that 11339 * will be called from tessellation evaluation shader. 11340 * 11341 * @return Requested string. 11342 **/ 11343 std::string NegativeTest2::getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const 11344 { 11345 std::stringstream result; 11346 11347 /* Form the pre-amble */ 11348 result << "#version 400\n" 11349 "\n" 11350 "#extension GL_ARB_shader_subroutine : require\n" 11351 "\n" 11352 "layout(quads) in;\n" 11353 "\n" 11354 "subroutine void testSubroutineType(out vec4 test_argument);\n" 11355 "\n" 11356 /* Define a subroutine */ 11357 "subroutine(testSubroutineType) void te_subroutine(out vec4 test_argument)\n" 11358 "{\n" 11359 " test_argument = vec4(1, 1, 1, 1);\n" 11360 "}\n" 11361 "\n" 11362 /* Define uniforms */ 11363 "subroutine uniform testSubroutineType test_te_subroutine;\n" 11364 "\n" 11365 /* Define main() */ 11366 "void main()\n" 11367 "{\n" 11368 " " 11369 << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n" 11370 "}\n"; 11371 11372 return result.str(); 11373 } 11374 11375 /** Retrieves an offending vertex shader body. 11376 * 11377 * @param referencing_stage Shader stage which defines the subroutine uniform that 11378 * will be called from vertex shader. 11379 * 11380 * @return Requested string. 11381 **/ 11382 std::string NegativeTest2::getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const 11383 { 11384 std::stringstream result; 11385 11386 /* Form the pre-amble */ 11387 result << "#version 400\n" 11388 "\n" 11389 "#extension GL_ARB_shader_subroutine : require\n" 11390 "\n" 11391 "subroutine void testSubroutineType(out vec4 test_argument);\n" 11392 "\n" 11393 /* Define a subroutine */ 11394 "subroutine(testSubroutineType) void vs_subroutine(out vec4 test_argument)\n" 11395 "{\n" 11396 " test_argument = vec4(0, 1, 0, 0);\n" 11397 "}\n" 11398 "\n" 11399 /* Define uniforms */ 11400 "subroutine uniform testSubroutineType test_vs_subroutine;\n" 11401 "\n" 11402 /* Define main() */ 11403 "void main()\n" 11404 "{\n" 11405 " " 11406 << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n" 11407 "}\n"; 11408 11409 return result.str(); 11410 } 11411 11412 /** Executes test iteration. 11413 * 11414 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 11415 */ 11416 tcu::TestNode::IterateResult NegativeTest2::iterate() 11417 { 11418 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 11419 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 11420 { 11421 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 11422 } 11423 11424 /* Iterate over all shader stages and execute the checks */ 11425 for (int referencing_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 11426 referencing_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++referencing_stage) 11427 { 11428 executeTestCase(static_cast<Utils::_shader_stage>(referencing_stage)); 11429 } /* for (all test cases) */ 11430 11431 /* All done */ 11432 if (m_has_test_passed) 11433 { 11434 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11435 } 11436 else 11437 { 11438 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11439 } 11440 11441 return STOP; 11442 } 11443 11444 /** Constructor. 11445 * 11446 * @param context Rendering context. 11447 * 11448 **/ 11449 NegativeTest3::NegativeTest3(deqp::Context& context) 11450 : TestCase(context, "missing_subroutine_keyword", "Verifies that subroutine keyword is necessary when declaring a " 11451 "subroutine uniforn and a compilation error occurs without it.") 11452 , m_has_test_passed(true) 11453 , m_so_id(0) 11454 { 11455 /* Left blank intentionally */ 11456 } 11457 11458 /** Deinitializes all GL objects that may have been created during test execution */ 11459 void NegativeTest3::deinit() 11460 { 11461 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11462 11463 if (m_so_id != 0) 11464 { 11465 gl.deleteShader(m_so_id); 11466 11467 m_so_id = 0; 11468 } 11469 } 11470 11471 /** Verifies that broken shader (for user-specified shader stage) does not compile. 11472 * 11473 * @param shader_stage Shader stage to use for the test. 11474 **/ 11475 void NegativeTest3::executeTest(const Utils::_shader_stage& shader_stage) 11476 { 11477 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11478 11479 /* Generate a new shader object */ 11480 m_so_id = gl.createShader(Utils::getGLenumForShaderStage(shader_stage)); 11481 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 11482 11483 /* Assign body to the shader */ 11484 std::string body; 11485 const char* body_raw_ptr = DE_NULL; 11486 11487 switch (shader_stage) 11488 { 11489 case Utils::SHADER_STAGE_VERTEX: 11490 body = getVertexShaderBody(); 11491 break; 11492 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 11493 body = getTessellationControlShaderBody(); 11494 break; 11495 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 11496 body = getTessellationEvaluationShaderBody(); 11497 break; 11498 case Utils::SHADER_STAGE_GEOMETRY: 11499 body = getGeometryShaderBody(); 11500 break; 11501 case Utils::SHADER_STAGE_FRAGMENT: 11502 body = getFragmentShaderBody(); 11503 break; 11504 11505 default: 11506 { 11507 TCU_FAIL("Unrecognized shader stage requested"); 11508 } 11509 } /* switch (shader_stage) */ 11510 11511 body_raw_ptr = body.c_str(); 11512 11513 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */); 11514 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 11515 11516 /* Try to compile the shader */ 11517 glw::GLint compile_status = 0; 11518 11519 gl.compileShader(m_so_id); 11520 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 11521 11522 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status); 11523 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 11524 11525 if (compile_status == GL_TRUE) 11526 { 11527 m_testCtx.getLog() << tcu::TestLog::Message << "The following shader was expected to fail to compile but was " 11528 "accepted by the compiler:\n" 11529 "\n" 11530 << body.c_str() << tcu::TestLog::EndMessage; 11531 11532 m_has_test_passed = false; 11533 } 11534 11535 /* Good to release the shader at this point */ 11536 gl.deleteShader(m_so_id); 11537 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed."); 11538 } 11539 11540 /** Retrieves body of a broken fragment shader. 11541 * 11542 * @return Requested string. 11543 **/ 11544 std::string NegativeTest3::getFragmentShaderBody() const 11545 { 11546 return "#version 400\n" 11547 "\n" 11548 "#extension GL_ARB_shader_subroutine : require\n" 11549 "\n" 11550 "subroutine void testSubroutineType(inout vec4 test);\n" 11551 "\n" 11552 "void testSubroutine1(inout vec4 test)\n" 11553 "{\n" 11554 " test += vec4(3, 4, 5, 6);\n" 11555 "}\n" 11556 "\n" 11557 "uniform testSubroutineType subroutineFunction;\n" 11558 "out vec4 result;\n" 11559 "\n" 11560 "void main()\n" 11561 "{\n" 11562 " vec4 test = vec4(2, 3, 4, 5);\n" 11563 "\n" 11564 " subroutineFunction(test);\n" 11565 "\n" 11566 " result = test;\n" 11567 "}\n"; 11568 } 11569 11570 /** Retrieves body of a broken geometry shader. 11571 * 11572 * @return Requested string. 11573 **/ 11574 std::string NegativeTest3::getGeometryShaderBody() const 11575 { 11576 return "#version 400\n" 11577 "\n" 11578 "#extension GL_ARB_shader_subroutine : require\n" 11579 "\n" 11580 "layout(points) in;\n" 11581 "layout(points, max_vertices = 1) out;\n" 11582 "\n" 11583 "subroutine void testSubroutineType(inout vec4 test);\n" 11584 "\n" 11585 "void testSubroutine1(inout vec4 test)\n" 11586 "{\n" 11587 " test += vec4(3, 4, 5, 6);\n" 11588 "}\n" 11589 "\n" 11590 "uniform testSubroutineType subroutineFunction;\n" 11591 "\n" 11592 "void main()\n" 11593 "{\n" 11594 " vec4 test = vec4(2, 3, 4, 5);\n" 11595 "\n" 11596 " subroutineFunction(test);\n" 11597 "\n" 11598 " gl_Position = test;\n" 11599 " EmitVertex();\n" 11600 "}\n"; 11601 } 11602 11603 /** Retrieves body of a broken tessellation control shader. 11604 * 11605 * @return Requested string. 11606 **/ 11607 std::string NegativeTest3::getTessellationControlShaderBody() const 11608 { 11609 return "#version 400\n" 11610 "\n" 11611 "#extension GL_ARB_shader_subroutine : require\n" 11612 "\n" 11613 "layout(vertices=4) out;\n" 11614 "\n" 11615 "subroutine void testSubroutineType(inout vec4 test);\n" 11616 "\n" 11617 "void testSubroutine1(inout vec4 test)\n" 11618 "{\n" 11619 " test += vec4(1, 2, 3, 4);\n" 11620 "}\n" 11621 "\n" 11622 "uniform testSubroutineType subroutineFunction;\n" 11623 "\n" 11624 "void main()\n" 11625 "{\n" 11626 " vec4 test = vec4(0, 1, 2, 3);\n" 11627 "\n" 11628 " subroutineFunction(test);\n" 11629 "\n" 11630 " gl_out[gl_InvocationID].gl_Position = test;\n" 11631 "}\n"; 11632 } 11633 11634 /** Retrieves body of a broken tessellation evaluation shader. 11635 * 11636 * @return Requested string. 11637 **/ 11638 std::string NegativeTest3::getTessellationEvaluationShaderBody() const 11639 { 11640 return "#version 400\n" 11641 "\n" 11642 "#extension GL_ARB_shader_subroutine : require\n" 11643 "\n" 11644 "layout(quads) in;\n" 11645 "\n" 11646 "subroutine void testSubroutineType(inout vec4 test);\n" 11647 "\n" 11648 "void testSubroutine1(inout vec4 test)\n" 11649 "{\n" 11650 " test += vec4(2, 3, 4, 5);\n" 11651 "}\n" 11652 "\n" 11653 "uniform testSubroutineType subroutineFunction;\n" 11654 "\n" 11655 "void main()\n" 11656 "{\n" 11657 " vec4 test = vec4(1, 2, 3, 4);\n" 11658 "\n" 11659 " subroutineFunction(test);\n" 11660 "\n" 11661 " gl_Position = test;\n" 11662 "}\n"; 11663 } 11664 11665 /** Retrieves body of a broken vertex shader. 11666 * 11667 * @return Requested string. 11668 **/ 11669 std::string NegativeTest3::getVertexShaderBody() const 11670 { 11671 return "#version 400\n" 11672 "\n" 11673 "#extension GL_ARB_shader_subroutine : require\n" 11674 "\n" 11675 "subroutine void testSubroutineType(inout vec4 test);\n" 11676 "\n" 11677 "void testSubroutine1(inout vec4 test)\n" 11678 "{\n" 11679 " test += vec4(0, 1, 2, 3);\n" 11680 "}\n" 11681 "\n" 11682 "uniform testSubroutineType subroutineFunction;\n" 11683 "\n" 11684 "void main()\n" 11685 "{\n" 11686 " subroutineFunction(gl_Position);\n" 11687 "}\n"; 11688 } 11689 11690 /** Executes test iteration. 11691 * 11692 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 11693 */ 11694 tcu::TestNode::IterateResult NegativeTest3::iterate() 11695 { 11696 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 11697 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 11698 { 11699 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 11700 } 11701 11702 /* Iterate over all shader stages */ 11703 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 11704 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 11705 { 11706 executeTest(static_cast<Utils::_shader_stage>(shader_stage)); 11707 } /* for (all shader stages) */ 11708 11709 /* Done */ 11710 if (m_has_test_passed) 11711 { 11712 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11713 } 11714 else 11715 { 11716 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11717 } 11718 11719 return STOP; 11720 } 11721 11722 /** Constructor. 11723 * 11724 * @param context Rendering context. 11725 * 11726 **/ 11727 NegativeTest4::NegativeTest4(deqp::Context& context) 11728 : TestCase(context, "subroutines_incompatible_with_subroutine_type", 11729 "Verifies that a compile-time error is generated when arguments and " 11730 "return type do not match beween the function and each associated " 11731 "subroutine type.") 11732 , m_has_test_passed(true) 11733 , m_so_id(0) 11734 { 11735 /* Left blank intentionally */ 11736 } 11737 11738 /** Deinitializes GL objects that may have been created during test 11739 * execution. 11740 **/ 11741 void NegativeTest4::deinit() 11742 { 11743 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11744 11745 if (m_so_id != 0) 11746 { 11747 gl.deleteShader(m_so_id); 11748 11749 m_so_id = 0; 11750 } 11751 } 11752 11753 /** Retrieves body of a shader of user-specified type that should be used 11754 * for a single test iteration. The shader will define user-specified number 11755 * of subroutine types, with the last type either defining an additional argument 11756 * or using a different return type. 11757 * A subroutine (claimed compatible with *all* subroutine types) will also be 11758 * defined in the shader. 11759 * 11760 * @param shader_stage Shader stage to use for the query. 11761 * @param n_subroutine_types Overall number of subroutine types that will be 11762 * declared & used in the shader. Please see description 11763 * for more details. 11764 * 11765 * @return Requested string. 11766 **/ 11767 std::string NegativeTest4::getShaderBody(const Utils::_shader_stage& shader_stage, 11768 const unsigned int& n_subroutine_types, const _test_case& test_case) const 11769 { 11770 std::stringstream result_sstream; 11771 11772 /* Form the pre-amble */ 11773 result_sstream << "#version 400\n" 11774 "\n" 11775 "#extension GL_ARB_shader_subroutine : require\n" 11776 "\n"; 11777 11778 /* Inject stage-specific code */ 11779 switch (shader_stage) 11780 { 11781 case Utils::SHADER_STAGE_GEOMETRY: 11782 { 11783 result_sstream << "layout (points) in;\n" 11784 "layout (points, max_vertices = 1) out;\n" 11785 "\n"; 11786 11787 break; 11788 } 11789 11790 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 11791 { 11792 result_sstream << "layout (vertices = 4) out;\n" 11793 "\n"; 11794 11795 break; 11796 } 11797 11798 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 11799 { 11800 result_sstream << "layout (quads) in;\n" 11801 "\n"; 11802 11803 break; 11804 } 11805 11806 default: 11807 break; 11808 } /* switch (shader_stage) */ 11809 11810 /* Insert subroutine type declarations */ 11811 for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types - 1; ++n_subroutine_type) 11812 { 11813 result_sstream << "subroutine void subroutineType" << n_subroutine_type << "(inout vec3 argument);\n"; 11814 } /* for (all subroutine types) */ 11815 11816 switch (test_case) 11817 { 11818 case TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST: 11819 { 11820 result_sstream << "subroutine void subroutineType" << (n_subroutine_types - 1) 11821 << "(inout vec3 argument, out vec4 argument2);\n"; 11822 11823 break; 11824 } 11825 11826 case TEST_CASE_INCOMPATIBLE_RETURN_TYPE: 11827 { 11828 result_sstream << "subroutine int subroutineType" << (n_subroutine_types - 1) << "(inout vec3 argument);\n"; 11829 11830 break; 11831 } 11832 11833 default: 11834 { 11835 TCU_FAIL("Unrecognized test case"); 11836 } 11837 } /* switch (test_case) */ 11838 11839 /* Insert subroutine declarations */ 11840 result_sstream << "subroutine("; 11841 11842 for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types; ++n_subroutine_type) 11843 { 11844 result_sstream << "subroutineType" << n_subroutine_type; 11845 11846 if (n_subroutine_type != (n_subroutine_types - 1)) 11847 { 11848 result_sstream << ", "; 11849 } 11850 } /* for (all subroutine types) */ 11851 11852 result_sstream << ") void function(inout vec3 argument)\n" 11853 "{\n" 11854 " argument = vec3(1, 2, 3);\n" 11855 "}\n" 11856 "\n"; 11857 11858 /* Insert remaining required stage-specific bits */ 11859 switch (shader_stage) 11860 { 11861 case Utils::SHADER_STAGE_FRAGMENT: 11862 { 11863 result_sstream << "out vec4 result;\n" 11864 "\n" 11865 "void main()\n" 11866 "{\n" 11867 " result = vec4(1, 2, 3, 4);\n" 11868 "}\n"; 11869 11870 break; 11871 } 11872 11873 case Utils::SHADER_STAGE_GEOMETRY: 11874 { 11875 result_sstream << "void main()\n" 11876 "{\n" 11877 " gl_Position = vec4(1, 2, 3, 4);\n" 11878 " EmitVertex();\n" 11879 "}\n"; 11880 11881 break; 11882 } 11883 11884 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 11885 { 11886 result_sstream << "void main()\n" 11887 "{\n" 11888 " gl_TessLevelInner[0] = 1;\n" 11889 " gl_TessLevelInner[1] = 1;\n" 11890 " gl_TessLevelOuter[0] = 1;\n" 11891 " gl_TessLevelOuter[1] = 1;\n" 11892 " gl_TessLevelOuter[2] = 1;\n" 11893 " gl_TessLevelOuter[3] = 1;\n" 11894 " gl_out[gl_InvocationID].gl_Position = vec4(2, 3, 4, 5);\n" 11895 "}\n"; 11896 11897 break; 11898 } 11899 11900 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 11901 case Utils::SHADER_STAGE_VERTEX: 11902 { 11903 result_sstream << "void main()\n" 11904 "{\n" 11905 " gl_Position = vec4(1, 2, 3, 4);\n" 11906 "}\n"; 11907 11908 break; 11909 } 11910 11911 default: 11912 { 11913 TCU_FAIL("Unrecognized shader stage"); 11914 } 11915 } /* switch (shader_stage) */ 11916 11917 return result_sstream.str(); 11918 } 11919 11920 /** Executes test iteration. 11921 * 11922 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 11923 */ 11924 tcu::TestNode::IterateResult NegativeTest4::iterate() 11925 { 11926 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11927 11928 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 11929 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 11930 { 11931 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 11932 } 11933 11934 /* Iterate over all shader stages.. */ 11935 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 11936 shader_stage != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 11937 { 11938 /* For each shader stage, we will be trying to compile a number of invalid shaders. 11939 * Each shader defines N different subroutine types. (N-1) of them are compatible 11940 * with a subroutine, but exactly 1 will be mismatched. The test passes if GLSL 11941 * compiler correctly detects that all shaders we will be trying to compile are 11942 * broken. 11943 */ 11944 const glw::GLenum shader_type = Utils::getGLenumForShaderStage(static_cast<Utils::_shader_stage>(shader_stage)); 11945 11946 for (unsigned int n_subroutine_types = 1; n_subroutine_types < 6; /* arbitrary number */ 11947 ++n_subroutine_types) 11948 { 11949 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); 11950 ++test_case) 11951 { 11952 std::string body; 11953 const char* body_raw_ptr = NULL; 11954 glw::GLint compile_status = GL_FALSE; 11955 11956 body = getShaderBody(static_cast<Utils::_shader_stage>(shader_stage), n_subroutine_types, 11957 static_cast<_test_case>(test_case)); 11958 body_raw_ptr = body.c_str(); 11959 11960 /* Try to compile the shader */ 11961 m_so_id = gl.createShader(shader_type); 11962 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed"); 11963 11964 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL); 11965 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 11966 11967 gl.compileShader(m_so_id); 11968 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 11969 11970 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status); 11971 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 11972 11973 if (compile_status == GL_TRUE) 11974 { 11975 m_testCtx.getLog() << tcu::TestLog::Message << "A malformed " 11976 << Utils::getShaderStageString(static_cast<Utils::_shader_stage>(shader_stage)) 11977 << " compiled successfully " 11978 "(" 11979 << n_subroutine_types << " subroutine types " 11980 "were defined)." 11981 << tcu::TestLog::EndMessage; 11982 11983 m_has_test_passed = false; 11984 } 11985 11986 /* Release the object */ 11987 gl.deleteShader(m_so_id); 11988 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed."); 11989 } /* for (all test cases) */ 11990 } /* for (a number of different subroutine type declarations) */ 11991 } /* for (all shader stages) */ 11992 11993 /* Done */ 11994 if (m_has_test_passed) 11995 { 11996 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11997 } 11998 else 11999 { 12000 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12001 } 12002 12003 return STOP; 12004 } 12005 12006 /** Constructor. 12007 * 12008 * @param context Rendering context. 12009 * 12010 **/ 12011 NegativeTest5::NegativeTest5(deqp::Context& context) 12012 : TestCase(context, "subroutine_uniform_wo_matching_subroutines", 12013 "Verifies that a link- or compile-time error occurs when " 12014 "trying to link a program with no subroutine for subroutine " 12015 "uniform variable.") 12016 , m_fs_id(0) 12017 , m_gs_id(0) 12018 , m_has_test_passed(true) 12019 , m_po_id(0) 12020 , m_tc_id(0) 12021 , m_te_id(0) 12022 , m_vs_id(0) 12023 { 12024 /* Left blank intentionally */ 12025 } 12026 12027 /** Deinitializes all GL objects that may have been created during test execution */ 12028 void NegativeTest5::deinit() 12029 { 12030 deinitIteration(); 12031 } 12032 12033 /** Deinitializes all GL objects that may have been created during a single test 12034 * iteration. 12035 ***/ 12036 void NegativeTest5::deinitIteration() 12037 { 12038 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12039 12040 if (m_fs_id != 0) 12041 { 12042 gl.deleteShader(m_fs_id); 12043 12044 m_fs_id = 0; 12045 } 12046 12047 if (m_gs_id != 0) 12048 { 12049 gl.deleteShader(m_gs_id); 12050 12051 m_gs_id = 0; 12052 } 12053 12054 if (m_po_id != 0) 12055 { 12056 gl.deleteProgram(m_po_id); 12057 12058 m_po_id = 0; 12059 } 12060 12061 if (m_tc_id != 0) 12062 { 12063 gl.deleteShader(m_tc_id); 12064 12065 m_tc_id = 0; 12066 } 12067 12068 if (m_te_id != 0) 12069 { 12070 gl.deleteShader(m_te_id); 12071 12072 m_te_id = 0; 12073 } 12074 12075 if (m_vs_id != 0) 12076 { 12077 gl.deleteShader(m_vs_id); 12078 12079 m_vs_id = 0; 12080 } 12081 } 12082 12083 /** Executes a single test iteration. 12084 * 12085 * If the iteration fails, m_has_test_passed will be set to false. 12086 * 12087 * @param shader_stage Shader stage, for which a subroutine uniform should be 12088 * declared in the shader without a matching subroutine. 12089 **/ 12090 void NegativeTest5::executeIteration(const Utils::_shader_stage& shader_stage) 12091 { 12092 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 12093 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 12094 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 12095 std::string te_body = 12096 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 12097 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 12098 12099 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 12100 DE_NULL, /* xfb_varyings */ 12101 DE_NULL, /* n_xfb_varyings */ 12102 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 12103 { 12104 /* None of the test programs should ever build successfully */ 12105 m_testCtx.getLog() << tcu::TestLog::Message 12106 << "A program object, consisting of the following shaders, has linked" 12107 " correctly. One of the shaders defines a subroutine uniform but does " 12108 "not implement any function that matches subroutine type of the uniform." 12109 " This should have resulted in a compilation/link-time error.\n" 12110 "\n" 12111 "Vertex shader:\n" 12112 "\n" 12113 << vs_body << "\n" 12114 "Tessellation control shader:\n" 12115 "\n" 12116 << tc_body << "\n" 12117 "Tessellation evaluation shader:\n" 12118 "\n" 12119 << te_body << "\n" 12120 "Geometry shader:\n" 12121 "\n" 12122 << gs_body << "\n" 12123 "Fragment shader:\n" 12124 "\n" 12125 << fs_body << tcu::TestLog::EndMessage; 12126 12127 m_has_test_passed = false; 12128 } 12129 } 12130 12131 /** Retrieves fragment shader body. 12132 * 12133 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 12134 * a subroutine uniform without 12135 * a matching subroutine, false otherwise. 12136 * 12137 * @return Requested string. 12138 **/ 12139 std::string NegativeTest5::getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const 12140 { 12141 std::stringstream result_sstream; 12142 12143 result_sstream << "#version 400\n" 12144 "\n" 12145 "#extension GL_ARB_shader_subroutine : require\n" 12146 "\n"; 12147 12148 if (include_invalid_subroutine_uniform_declaration) 12149 { 12150 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 12151 "\n" 12152 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 12153 }; 12154 12155 result_sstream << "\n" 12156 "out vec4 result;\n" 12157 "\n" 12158 "void main()\n" 12159 "{\n"; 12160 12161 if (include_invalid_subroutine_uniform_declaration) 12162 { 12163 result_sstream << " test_subroutineFS(result);\n"; 12164 } 12165 else 12166 { 12167 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 12168 } 12169 12170 result_sstream << "}\n"; 12171 12172 return result_sstream.str(); 12173 } 12174 12175 /** Retrieves geometry shader body. 12176 * 12177 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 12178 * a subroutine uniform without 12179 * a matching subroutine, false otherwise. 12180 * 12181 * @return Requested string. 12182 **/ 12183 std::string NegativeTest5::getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const 12184 { 12185 std::stringstream result_sstream; 12186 12187 result_sstream << "#version 400\n" 12188 "\n" 12189 "#extension GL_ARB_shader_subroutine : require\n" 12190 "\n" 12191 "layout (points) in;\n" 12192 "layout (points, max_vertices = 1) out;\n" 12193 "\n"; 12194 12195 if (include_invalid_subroutine_uniform_declaration) 12196 { 12197 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 12198 "\n" 12199 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 12200 }; 12201 12202 result_sstream << "\n" 12203 "void main()\n" 12204 "{\n"; 12205 12206 if (include_invalid_subroutine_uniform_declaration) 12207 { 12208 result_sstream << " test_subroutineGS(gl_Position);\n"; 12209 } 12210 else 12211 { 12212 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12213 } 12214 12215 result_sstream << "EmitVertex();\n" 12216 "}\n"; 12217 12218 return result_sstream.str(); 12219 } 12220 12221 /** Retrieves tessellation control shader body. 12222 * 12223 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 12224 * a subroutine uniform without 12225 * a matching subroutine, false otherwise. 12226 * 12227 * @return Requested string. 12228 **/ 12229 std::string NegativeTest5::getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const 12230 { 12231 std::stringstream result_sstream; 12232 12233 result_sstream << "#version 400\n" 12234 "\n" 12235 "#extension GL_ARB_shader_subroutine : require\n" 12236 "\n" 12237 "layout (vertices = 4) out;\n" 12238 "\n"; 12239 12240 if (include_invalid_subroutine_uniform_declaration) 12241 { 12242 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 12243 "\n" 12244 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 12245 }; 12246 12247 result_sstream << "\n" 12248 "void main()\n" 12249 "{\n"; 12250 12251 if (include_invalid_subroutine_uniform_declaration) 12252 { 12253 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 12254 } 12255 else 12256 { 12257 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 12258 } 12259 12260 result_sstream << "}\n"; 12261 12262 return result_sstream.str(); 12263 } 12264 12265 /** Retrieves tessellation evaluation body. 12266 * 12267 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 12268 * a subroutine uniform without 12269 * a matching subroutine, false otherwise. 12270 * 12271 * @return Requested string. 12272 **/ 12273 std::string NegativeTest5::getTessellationEvaluationShaderBody( 12274 bool include_invalid_subroutine_uniform_declaration) const 12275 { 12276 std::stringstream result_sstream; 12277 12278 result_sstream << "#version 400\n" 12279 "\n" 12280 "#extension GL_ARB_shader_subroutine : require\n" 12281 "\n" 12282 "layout (quads) in;\n" 12283 "\n"; 12284 12285 if (include_invalid_subroutine_uniform_declaration) 12286 { 12287 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 12288 "\n" 12289 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 12290 }; 12291 12292 result_sstream << "\n" 12293 "void main()\n" 12294 "{\n"; 12295 12296 if (include_invalid_subroutine_uniform_declaration) 12297 { 12298 result_sstream << " test_subroutineTE(gl_Position);\n"; 12299 } 12300 else 12301 { 12302 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12303 } 12304 12305 result_sstream << "}\n"; 12306 12307 return result_sstream.str(); 12308 } 12309 12310 /** Retrieves vertex shader body. 12311 * 12312 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 12313 * a subroutine uniform without 12314 * a matching subroutine, false otherwise. 12315 * 12316 * @return Requested string. 12317 **/ 12318 std::string NegativeTest5::getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const 12319 { 12320 std::stringstream result_sstream; 12321 12322 result_sstream << "#version 400\n" 12323 "\n" 12324 "#extension GL_ARB_shader_subroutine : require\n" 12325 "\n"; 12326 12327 if (include_invalid_subroutine_uniform_declaration) 12328 { 12329 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 12330 "\n" 12331 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 12332 }; 12333 12334 result_sstream << "\n" 12335 "void main()\n" 12336 "{\n"; 12337 12338 if (include_invalid_subroutine_uniform_declaration) 12339 { 12340 result_sstream << " test_subroutineVS(gl_Position);\n"; 12341 } 12342 else 12343 { 12344 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12345 } 12346 12347 result_sstream << "}\n"; 12348 12349 return result_sstream.str(); 12350 } 12351 12352 /** Executes test iteration. 12353 * 12354 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12355 */ 12356 tcu::TestNode::IterateResult NegativeTest5::iterate() 12357 { 12358 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 12359 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 12360 { 12361 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 12362 } 12363 12364 /* Iterate over all shader stages. Iteration-specific shader stage defines a subroutine type & 12365 * a corresponding subroutine uniform, for which no compatible subroutines are available. All 12366 * other shader stages are defined correctly. 12367 */ 12368 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 12369 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 12370 { 12371 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 12372 deinitIteration(); 12373 } /* for (all shader stages) */ 12374 12375 /* All done */ 12376 if (m_has_test_passed) 12377 { 12378 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12379 } 12380 else 12381 { 12382 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12383 } 12384 12385 return STOP; 12386 } 12387 12388 /** Constructor. 12389 * 12390 * @param context Rendering context. 12391 * 12392 **/ 12393 NegativeTest6::NegativeTest6(deqp::Context& context) 12394 : TestCase(context, "two_duplicate_functions_one_being_a_subroutine", 12395 "Verifies that a link- or compile-time error occurs if any shader in " 12396 "a program object includes two functions with the same name and one " 12397 "of which is associated with a subroutine type.") 12398 , m_fs_id(0) 12399 , m_gs_id(0) 12400 , m_has_test_passed(true) 12401 , m_po_id(0) 12402 , m_tc_id(0) 12403 , m_te_id(0) 12404 , m_vs_id(0) 12405 { 12406 /* Left blank intentionally */ 12407 } 12408 12409 /** Deinitializes all GL objects that may have been created during test execution */ 12410 void NegativeTest6::deinit() 12411 { 12412 deinitIteration(); 12413 } 12414 12415 /** Deinitializes all GL objects that may have been created during a single test 12416 * iteration. 12417 ***/ 12418 void NegativeTest6::deinitIteration() 12419 { 12420 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12421 12422 if (m_fs_id != 0) 12423 { 12424 gl.deleteShader(m_fs_id); 12425 12426 m_fs_id = 0; 12427 } 12428 12429 if (m_gs_id != 0) 12430 { 12431 gl.deleteShader(m_gs_id); 12432 12433 m_gs_id = 0; 12434 } 12435 12436 if (m_po_id != 0) 12437 { 12438 gl.deleteProgram(m_po_id); 12439 12440 m_po_id = 0; 12441 } 12442 12443 if (m_tc_id != 0) 12444 { 12445 gl.deleteShader(m_tc_id); 12446 12447 m_tc_id = 0; 12448 } 12449 12450 if (m_te_id != 0) 12451 { 12452 gl.deleteShader(m_te_id); 12453 12454 m_te_id = 0; 12455 } 12456 12457 if (m_vs_id != 0) 12458 { 12459 gl.deleteShader(m_vs_id); 12460 12461 m_vs_id = 0; 12462 } 12463 } 12464 12465 /** Executes a single test iteration. 12466 * 12467 * If the iteration fails, m_has_test_passed will be set to false. 12468 * 12469 * @param shader_stage Shader stage, for which two duplicate functions 12470 * (one additionally marked as subroutine) should 12471 * be defined. 12472 **/ 12473 void NegativeTest6::executeIteration(const Utils::_shader_stage& shader_stage) 12474 { 12475 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 12476 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 12477 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 12478 std::string te_body = 12479 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 12480 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 12481 12482 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 12483 DE_NULL, /* xfb_varyings */ 12484 DE_NULL, /* n_xfb_varyings */ 12485 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 12486 { 12487 /* None of the test programs should ever build successfully */ 12488 m_testCtx.getLog() << tcu::TestLog::Message 12489 << "A program object, consisting of the following shaders, has linked" 12490 " correctly. This is invalid, because one of the shaders defines two" 12491 " functions with the same name, with an exception that one of the" 12492 " functions is marked as a subroutine.\n" 12493 "\n" 12494 "Vertex shader:\n" 12495 "\n" 12496 << vs_body << "\n" 12497 "Tessellation control shader:\n" 12498 "\n" 12499 << tc_body << "\n" 12500 "Tessellation evaluation shader:\n" 12501 "\n" 12502 << te_body << "\n" 12503 "Geometry shader:\n" 12504 "\n" 12505 << gs_body << "\n" 12506 "Fragment shader:\n" 12507 "\n" 12508 << fs_body << tcu::TestLog::EndMessage; 12509 12510 m_has_test_passed = false; 12511 } 12512 } 12513 12514 /** Retrieves fragment shader body. 12515 * 12516 * @param include_invalid_declaration true if the shader should include duplicate function 12517 * declaration. 12518 * 12519 * @return Requested string. 12520 **/ 12521 std::string NegativeTest6::getFragmentShaderBody(bool include_invalid_declaration) const 12522 { 12523 std::stringstream result_sstream; 12524 12525 result_sstream << "#version 400\n" 12526 "\n" 12527 "#extension GL_ARB_shader_subroutine : require\n" 12528 "\n"; 12529 12530 if (include_invalid_declaration) 12531 { 12532 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 12533 "\n" 12534 "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test)\n" 12535 "{\n" 12536 " test = vec4(1, 2, 3, 4);\n" 12537 "}\n" 12538 "\n" 12539 "void test_impl1(out vec4 test)\n" 12540 "{\n" 12541 " test = vec4(2, 3, 4, 5);\n" 12542 "}\n" 12543 "\n" 12544 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 12545 }; 12546 12547 result_sstream << "\n" 12548 "out vec4 result;\n" 12549 "\n" 12550 "void main()\n" 12551 "{\n"; 12552 12553 if (include_invalid_declaration) 12554 { 12555 result_sstream << " test_subroutineFS(result);\n"; 12556 } 12557 else 12558 { 12559 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 12560 } 12561 12562 result_sstream << "}\n"; 12563 12564 return result_sstream.str(); 12565 } 12566 12567 /** Retrieves geometry shader body. 12568 * 12569 * @param include_invalid_declaration true if the shader should include duplicate function 12570 * declaration. 12571 * 12572 * @return Requested string. 12573 **/ 12574 std::string NegativeTest6::getGeometryShaderBody(bool include_invalid_declaration) const 12575 { 12576 std::stringstream result_sstream; 12577 12578 result_sstream << "#version 400\n" 12579 "\n" 12580 "#extension GL_ARB_shader_subroutine : require\n" 12581 "\n" 12582 "layout (points) in;\n" 12583 "layout (points, max_vertices = 1) out;\n" 12584 "\n"; 12585 12586 if (include_invalid_declaration) 12587 { 12588 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 12589 "\n" 12590 "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test)\n" 12591 "{\n" 12592 " test = vec4(1, 2, 3, 4);\n" 12593 "}\n" 12594 "\n" 12595 "void test_impl1(out vec4 test)\n" 12596 "{\n" 12597 " test = vec4(2, 3, 4, 5);\n" 12598 "}\n" 12599 "\n" 12600 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 12601 }; 12602 12603 result_sstream << "\n" 12604 "void main()\n" 12605 "{\n"; 12606 12607 if (include_invalid_declaration) 12608 { 12609 result_sstream << " test_subroutineGS(gl_Position);\n"; 12610 } 12611 else 12612 { 12613 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12614 } 12615 12616 result_sstream << "EmitVertex();\n" 12617 "}\n"; 12618 12619 return result_sstream.str(); 12620 } 12621 12622 /** Retrieves tessellation control shader body. 12623 * 12624 * @param include_invalid_declaration true if the shader should include duplicate function 12625 * declaration. 12626 * 12627 * @return Requested string. 12628 **/ 12629 std::string NegativeTest6::getTessellationControlShaderBody(bool include_invalid_declaration) const 12630 { 12631 std::stringstream result_sstream; 12632 12633 result_sstream << "#version 400\n" 12634 "\n" 12635 "#extension GL_ARB_shader_subroutine : require\n" 12636 "\n" 12637 "layout (vertices = 4) out;\n" 12638 "\n"; 12639 12640 if (include_invalid_declaration) 12641 { 12642 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 12643 "\n" 12644 "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test)\n" 12645 "{\n" 12646 " test = vec4(1, 2, 3, 4);\n" 12647 "}\n" 12648 "\n" 12649 "void test_impl1(out vec4 test)\n" 12650 "{\n" 12651 " test = vec4(2, 3, 4, 5);\n" 12652 "}\n" 12653 "\n" 12654 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 12655 }; 12656 12657 result_sstream << "\n" 12658 "void main()\n" 12659 "{\n"; 12660 12661 if (include_invalid_declaration) 12662 { 12663 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 12664 } 12665 else 12666 { 12667 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 12668 } 12669 12670 result_sstream << "}\n"; 12671 12672 return result_sstream.str(); 12673 } 12674 12675 /** Retrieves tessellation evaluation body. 12676 * 12677 * @param include_invalid_declaration true if the shader should include duplicate function 12678 * declaration. 12679 * 12680 * @return Requested string. 12681 **/ 12682 std::string NegativeTest6::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const 12683 { 12684 std::stringstream result_sstream; 12685 12686 result_sstream << "#version 400\n" 12687 "\n" 12688 "#extension GL_ARB_shader_subroutine : require\n" 12689 "\n" 12690 "layout (quads) in;\n" 12691 "\n"; 12692 12693 if (include_invalid_declaration) 12694 { 12695 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 12696 "\n" 12697 "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test)\n" 12698 "{\n" 12699 " test = vec4(1, 2, 3, 4);\n" 12700 "}\n" 12701 "\n" 12702 "void test_impl1(out vec4 test)\n" 12703 "{\n" 12704 " test = vec4(2, 3, 4, 5);\n" 12705 "}\n" 12706 "\n" 12707 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 12708 }; 12709 12710 result_sstream << "\n" 12711 "void main()\n" 12712 "{\n"; 12713 12714 if (include_invalid_declaration) 12715 { 12716 result_sstream << " test_subroutineTE(gl_Position);\n"; 12717 } 12718 else 12719 { 12720 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12721 } 12722 12723 result_sstream << "}\n"; 12724 12725 return result_sstream.str(); 12726 } 12727 12728 /** Retrieves vertex shader body. 12729 * 12730 * @param include_invalid_declaration true if the shader should include duplicate function 12731 * declaration. 12732 * 12733 * @return Requested string. 12734 **/ 12735 std::string NegativeTest6::getVertexShaderBody(bool include_invalid_declaration) const 12736 { 12737 std::stringstream result_sstream; 12738 12739 result_sstream << "#version 400\n" 12740 "\n" 12741 "#extension GL_ARB_shader_subroutine : require\n" 12742 "\n"; 12743 12744 if (include_invalid_declaration) 12745 { 12746 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 12747 "\n" 12748 "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test)\n" 12749 "{\n" 12750 " test = vec4(1, 2, 3, 4);\n" 12751 "}\n" 12752 "\n" 12753 "void test_impl1(out vec4 test)\n" 12754 "{\n" 12755 " test = vec4(2, 3, 4, 5);\n" 12756 "}\n" 12757 "\n" 12758 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 12759 }; 12760 12761 result_sstream << "\n" 12762 "void main()\n" 12763 "{\n"; 12764 12765 if (include_invalid_declaration) 12766 { 12767 result_sstream << " test_subroutineVS(gl_Position);\n"; 12768 } 12769 else 12770 { 12771 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12772 } 12773 12774 result_sstream << "}\n"; 12775 12776 return result_sstream.str(); 12777 } 12778 12779 /** Executes test iteration. 12780 * 12781 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12782 */ 12783 tcu::TestNode::IterateResult NegativeTest6::iterate() 12784 { 12785 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 12786 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 12787 { 12788 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 12789 } 12790 12791 /* Iterate over all shader stages. In each iteration, we will inject invalid 12792 * duplicate function declarations to iteration-specific shader stage. All other 12793 * shader stages will be assigned valid bodies. Test should fail if the program 12794 * links successfully. 12795 */ 12796 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 12797 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 12798 { 12799 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 12800 deinitIteration(); 12801 } /* for (all shader stages) */ 12802 12803 /* All done */ 12804 if (m_has_test_passed) 12805 { 12806 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12807 } 12808 else 12809 { 12810 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12811 } 12812 12813 return STOP; 12814 } 12815 12816 /** Constructor 12817 * 12818 * @param context CTS context 12819 **/ 12820 NegativeTest7::NegativeTest7(deqp::Context& context) 12821 : TestCase(context, "recursion", "Verify that it is not possible to build program with recursing subroutines") 12822 , m_program_id(0) 12823 , m_vertex_shader_id(0) 12824 { 12825 /* Nothing to be done here */ 12826 } 12827 12828 /** Deinitializes all GL objects that may have been created during test execution 12829 * 12830 **/ 12831 void NegativeTest7::deinit() 12832 { 12833 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12834 12835 if (m_program_id != 0) 12836 { 12837 gl.deleteProgram(m_program_id); 12838 12839 m_program_id = 0; 12840 } 12841 12842 if (m_vertex_shader_id != 0) 12843 { 12844 gl.deleteShader(m_vertex_shader_id); 12845 12846 m_vertex_shader_id = 0; 12847 } 12848 } 12849 12850 /** Executes test iteration. 12851 * 12852 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12853 **/ 12854 tcu::TestNode::IterateResult NegativeTest7::iterate() 12855 { 12856 static const GLchar* vertex_shader_with_static_recursion = 12857 "#version 400\n" 12858 "\n" 12859 "#extension GL_ARB_shader_subroutine : require\n" 12860 "\n" 12861 "precision highp float;\n" 12862 "\n" 12863 "subroutine vec4 routine_type(in vec4 data, in uint control);\n" 12864 "\n" 12865 "subroutine (routine_type) vec4 power_routine(in vec4 data, in uint control)\n" 12866 "{\n" 12867 " if (0 != control)\n" 12868 " {\n" 12869 " return data * power_routine(data, control - 1);\n" 12870 " }\n" 12871 " else\n" 12872 " {\n" 12873 " return vec4(1, 1, 1, 1);\n" 12874 " }\n" 12875 "}\n" 12876 "\n" 12877 "subroutine (routine_type) vec4 select_routine(in vec4 data, in uint control)\n" 12878 "{\n" 12879 " if (0 == control)\n" 12880 " {\n" 12881 " return data.rrrr;\n" 12882 " }\n" 12883 " else if (1 == control)\n" 12884 " {\n" 12885 " return data.gggg;\n" 12886 " }\n" 12887 " else if (2 == control)\n" 12888 " {\n" 12889 " return data.bbbb;\n" 12890 " }\n" 12891 " else\n" 12892 " {\n" 12893 " return data.aaaa;\n" 12894 " }\n" 12895 "}\n" 12896 "\n" 12897 "subroutine uniform routine_type routine;\n" 12898 "\n" 12899 "uniform vec4 uni_value;\n" 12900 "uniform uint uni_control;\n" 12901 "\n" 12902 "out vec4 out_result;\n" 12903 "\n" 12904 "void main()\n" 12905 "{\n" 12906 " out_result = routine(uni_value, uni_control);\n" 12907 "}\n" 12908 "\n"; 12909 12910 static const GLchar* vertex_shader_with_dynamic_recursion = 12911 "#version 400\n" 12912 "\n" 12913 "#extension GL_ARB_shader_subroutine : require\n" 12914 "\n" 12915 "precision highp float;\n" 12916 "\n" 12917 "subroutine vec4 routine_type(in vec4 data);\n" 12918 "\n" 12919 "subroutine uniform routine_type routine;\n" 12920 "\n" 12921 "subroutine (routine_type) vec4 div_by_2(in vec4 data)\n" 12922 "{\n" 12923 " return data / 2;\n" 12924 "}\n" 12925 "\n" 12926 "subroutine (routine_type) vec4 div_routine_result_by_2(in vec4 data)\n" 12927 "{\n" 12928 " return routine(data) / 2;\n" 12929 "}\n" 12930 "\n" 12931 "uniform vec4 uni_value;\n" 12932 "\n" 12933 "out vec4 out_result;\n" 12934 "\n" 12935 "void main()\n" 12936 "{\n" 12937 " out_result = routine(uni_value);\n" 12938 "}\n" 12939 "\n"; 12940 12941 static const GLchar* vertex_shader_with_subroutine_function_recursion = 12942 "#version 400\n" 12943 "\n" 12944 "#extension GL_ARB_shader_subroutine : require\n" 12945 "\n" 12946 "precision highp float;\n" 12947 "\n" 12948 "subroutine vec4 routine_type(in vec4 data);\n" 12949 "\n" 12950 "subroutine uniform routine_type routine;\n" 12951 "\n" 12952 "vec4 function(in vec4 data)\n" 12953 "{\n" 12954 " return routine(data) + vec4(0.5, 0.5, 0.5, 0.5);\n" 12955 "}\n" 12956 "\n" 12957 "subroutine (routine_type) vec4 routine_a(in vec4 data)\n" 12958 "{\n" 12959 " return function(data) / 2;\n" 12960 "}\n" 12961 "\n" 12962 "subroutine (routine_type) vec4 routine_b(in vec4 data)\n" 12963 "{\n" 12964 " return routine_a(data) * 2;\n" 12965 "}\n" 12966 "\n" 12967 "uniform vec4 uni_value;\n" 12968 "\n" 12969 "out vec4 out_result;\n" 12970 "\n" 12971 "void main()\n" 12972 "{\n" 12973 " out_result = routine(uni_value);\n" 12974 "}\n" 12975 "\n"; 12976 12977 bool result = true; 12978 12979 if (false == test(vertex_shader_with_subroutine_function_recursion, "routine_a")) 12980 { 12981 result = false; 12982 } 12983 12984 if (false == test(vertex_shader_with_dynamic_recursion, "div_routine_result_by_2")) 12985 { 12986 result = false; 12987 } 12988 12989 if (false == test(vertex_shader_with_static_recursion, "power_routine")) 12990 { 12991 result = false; 12992 } 12993 12994 /* Set result */ 12995 if (true == result) 12996 { 12997 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12998 } 12999 else 13000 { 13001 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13002 } 13003 13004 /* Done */ 13005 return tcu::TestNode::STOP; 13006 } 13007 13008 /** Try to build program from vertex shader code. 13009 * 13010 * @param vertex_shader_code Source code of vertex shader 13011 * @param name_of_recursive_routine Name of subroutine that should cause link failure due to recursion 13012 * 13013 * @return true build process failed, false otherwise 13014 **/ 13015 bool NegativeTest7::test(const GLchar* vertex_shader_code, const GLchar* name_of_recursive_routine) 13016 { 13017 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13018 bool result = true; 13019 static const GLchar* varying_name = "out_result"; 13020 13021 /* Try to build program */ 13022 if (true == Utils::buildProgram(gl, vertex_shader_code, "", "", "", "", &varying_name /* varying_names */, 13023 1 /* n_varyings */, &m_vertex_shader_id, 0, 0, 0, 0, &m_program_id)) 13024 { 13025 /* Success is considered an error */ 13026 13027 Utils::program program(m_context); 13028 GLuint index = 0; 13029 13030 program.build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0); 13031 13032 /* Verify that recursive subroutine is active */ 13033 try 13034 { 13035 index = program.getSubroutineIndex(name_of_recursive_routine, GL_VERTEX_SHADER); 13036 } 13037 catch (const std::exception& exc) 13038 { 13039 /* Something wrong with shader or compilation */ 13040 m_context.getTestContext().getLog() 13041 << tcu::TestLog::Message << "It is expected that subroutine: \n" 13042 << name_of_recursive_routine 13043 << " is considered active. This subroutine is potentially recursive and should cause link failure." 13044 << tcu::TestLog::EndMessage; 13045 13046 throw exc; 13047 } 13048 13049 /* Subsoutine is active, however linking should fail */ 13050 m_context.getTestContext().getLog() 13051 << tcu::TestLog::Message << "Error. Program with potentially recursive subroutine, " 13052 << name_of_recursive_routine << ", which is active, index: " << index << ", has been built successfully.\n" 13053 << vertex_shader_code << tcu::TestLog::EndMessage; 13054 13055 result = false; 13056 } 13057 13058 /* Delete program and shader */ 13059 deinit(); 13060 13061 /* Done */ 13062 return result; 13063 } 13064 13065 /** Constructor. 13066 * 13067 * @param context Rendering context. 13068 * 13069 **/ 13070 NegativeTest8::NegativeTest8(deqp::Context& context) 13071 : TestCase(context, "subroutine_wo_body", "Verifies that a compile- or link-time error occurs if a function " 13072 "declared as a subroutine does not include a body.") 13073 , m_fs_id(0) 13074 , m_gs_id(0) 13075 , m_has_test_passed(true) 13076 , m_po_id(0) 13077 , m_tc_id(0) 13078 , m_te_id(0) 13079 , m_vs_id(0) 13080 { 13081 /* Left blank intentionally */ 13082 } 13083 13084 /** Deinitializes all GL objects that may have been created during test execution */ 13085 void NegativeTest8::deinit() 13086 { 13087 deinitIteration(); 13088 } 13089 13090 /** Deinitializes all GL objects that may have been created during a single test 13091 * iteration. 13092 ***/ 13093 void NegativeTest8::deinitIteration() 13094 { 13095 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13096 13097 if (m_fs_id != 0) 13098 { 13099 gl.deleteShader(m_fs_id); 13100 13101 m_fs_id = 0; 13102 } 13103 13104 if (m_gs_id != 0) 13105 { 13106 gl.deleteShader(m_gs_id); 13107 13108 m_gs_id = 0; 13109 } 13110 13111 if (m_po_id != 0) 13112 { 13113 gl.deleteProgram(m_po_id); 13114 13115 m_po_id = 0; 13116 } 13117 13118 if (m_tc_id != 0) 13119 { 13120 gl.deleteShader(m_tc_id); 13121 13122 m_tc_id = 0; 13123 } 13124 13125 if (m_te_id != 0) 13126 { 13127 gl.deleteShader(m_te_id); 13128 13129 m_te_id = 0; 13130 } 13131 13132 if (m_vs_id != 0) 13133 { 13134 gl.deleteShader(m_vs_id); 13135 13136 m_vs_id = 0; 13137 } 13138 } 13139 13140 /** Executes a single test iteration. 13141 * 13142 * If the iteration fails, m_has_test_passed will be set to false. 13143 * 13144 * @param shader_stage Shader stage, for which two duplicate functions 13145 * (one additionally marked as subroutine) should 13146 * be defined. 13147 **/ 13148 void NegativeTest8::executeIteration(const Utils::_shader_stage& shader_stage) 13149 { 13150 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 13151 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 13152 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 13153 std::string te_body = 13154 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 13155 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 13156 13157 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 13158 DE_NULL, /* xfb_varyings */ 13159 DE_NULL, /* n_xfb_varyings */ 13160 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 13161 { 13162 /* None of the test programs should ever build successfully */ 13163 m_testCtx.getLog() << tcu::TestLog::Message 13164 << "A program object consisting of FS+GS+TC+TE+VS stages has linked successfully, " 13165 "even though one of the shaders only defines a subroutine that lacks any body." 13166 "\n" 13167 "Vertex shader:\n" 13168 "\n" 13169 << vs_body << "\n" 13170 "Tessellation control shader:\n" 13171 "\n" 13172 << tc_body << "\n" 13173 "Tessellation evaluation shader:\n" 13174 "\n" 13175 << te_body << "\n" 13176 "Geometry shader:\n" 13177 "\n" 13178 << gs_body << "\n" 13179 "Fragment shader:\n" 13180 "\n" 13181 << fs_body << tcu::TestLog::EndMessage; 13182 13183 m_has_test_passed = false; 13184 } 13185 } 13186 13187 /** Retrieves fragment shader body. 13188 * 13189 * @param include_invalid_declaration true if a subroutine prototype should be included in 13190 * the shader, false to skip it. 13191 * 13192 * @return Requested string. 13193 **/ 13194 std::string NegativeTest8::getFragmentShaderBody(bool include_invalid_declaration) const 13195 { 13196 std::stringstream result_sstream; 13197 13198 result_sstream << "#version 400\n" 13199 "\n" 13200 "#extension GL_ARB_shader_subroutine : require\n" 13201 "\n"; 13202 13203 if (include_invalid_declaration) 13204 { 13205 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 13206 "\n" 13207 "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test);\n" 13208 "\n" 13209 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 13210 }; 13211 13212 result_sstream << "\n" 13213 "out vec4 result;\n" 13214 "\n" 13215 "void main()\n" 13216 "{\n"; 13217 13218 if (include_invalid_declaration) 13219 { 13220 result_sstream << " test_subroutineFS(result);\n"; 13221 } 13222 else 13223 { 13224 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 13225 } 13226 13227 result_sstream << "}\n"; 13228 13229 return result_sstream.str(); 13230 } 13231 13232 /** Retrieves geometry shader body. 13233 * 13234 * @param include_invalid_declaration true if a subroutine prototype should be included in 13235 * the shader, false to skip it. 13236 * 13237 * @return Requested string. 13238 **/ 13239 std::string NegativeTest8::getGeometryShaderBody(bool include_invalid_declaration) const 13240 { 13241 std::stringstream result_sstream; 13242 13243 result_sstream << "#version 400\n" 13244 "\n" 13245 "#extension GL_ARB_shader_subroutine : require\n" 13246 "\n" 13247 "layout (points) in;\n" 13248 "layout (points, max_vertices = 1) out;\n" 13249 "\n"; 13250 13251 if (include_invalid_declaration) 13252 { 13253 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 13254 "\n" 13255 "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test);\n" 13256 "\n" 13257 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 13258 }; 13259 13260 result_sstream << "\n" 13261 "void main()\n" 13262 "{\n"; 13263 13264 if (include_invalid_declaration) 13265 { 13266 result_sstream << " test_subroutineGS(gl_Position);\n"; 13267 } 13268 else 13269 { 13270 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 13271 } 13272 13273 result_sstream << "EmitVertex();\n" 13274 "}\n"; 13275 13276 return result_sstream.str(); 13277 } 13278 13279 /** Retrieves tessellation control shader body. 13280 * 13281 * @param include_invalid_declaration true if a subroutine prototype should be included in 13282 * the shader, false to skip it. 13283 * 13284 * @return Requested string. 13285 **/ 13286 std::string NegativeTest8::getTessellationControlShaderBody(bool include_invalid_declaration) const 13287 { 13288 std::stringstream result_sstream; 13289 13290 result_sstream << "#version 400\n" 13291 "\n" 13292 "#extension GL_ARB_shader_subroutine : require\n" 13293 "\n" 13294 "layout (vertices = 4) out;\n" 13295 "\n"; 13296 13297 if (include_invalid_declaration) 13298 { 13299 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 13300 "\n" 13301 "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test);\n" 13302 "\n" 13303 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 13304 }; 13305 13306 result_sstream << "\n" 13307 "void main()\n" 13308 "{\n"; 13309 13310 if (include_invalid_declaration) 13311 { 13312 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 13313 } 13314 else 13315 { 13316 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 13317 } 13318 13319 result_sstream << "}\n"; 13320 13321 return result_sstream.str(); 13322 } 13323 13324 /** Retrieves tessellation evaluation body. 13325 * 13326 * @param include_invalid_declaration true if a subroutine prototype should be included in 13327 * the shader, false to skip it. 13328 * 13329 * @return Requested string. 13330 **/ 13331 std::string NegativeTest8::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const 13332 { 13333 std::stringstream result_sstream; 13334 13335 result_sstream << "#version 400\n" 13336 "\n" 13337 "#extension GL_ARB_shader_subroutine : require\n" 13338 "\n" 13339 "layout (quads) in;\n" 13340 "\n"; 13341 13342 if (include_invalid_declaration) 13343 { 13344 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 13345 "\n" 13346 "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test);\n" 13347 "\n" 13348 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 13349 }; 13350 13351 result_sstream << "\n" 13352 "void main()\n" 13353 "{\n"; 13354 13355 if (include_invalid_declaration) 13356 { 13357 result_sstream << " test_subroutineTE(gl_Position);\n"; 13358 } 13359 else 13360 { 13361 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 13362 } 13363 13364 result_sstream << "}\n"; 13365 13366 return result_sstream.str(); 13367 } 13368 13369 /** Retrieves vertex shader body. 13370 * 13371 * @param include_invalid_declaration true if a subroutine prototype should be included in 13372 * the shader, false to skip it. 13373 * 13374 * @return Requested string. 13375 **/ 13376 std::string NegativeTest8::getVertexShaderBody(bool include_invalid_declaration) const 13377 { 13378 std::stringstream result_sstream; 13379 13380 result_sstream << "#version 400\n" 13381 "\n" 13382 "#extension GL_ARB_shader_subroutine : require\n" 13383 "\n"; 13384 13385 if (include_invalid_declaration) 13386 { 13387 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 13388 "\n" 13389 "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test);\n" 13390 "\n" 13391 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 13392 }; 13393 13394 result_sstream << "\n" 13395 "void main()\n" 13396 "{\n"; 13397 13398 if (include_invalid_declaration) 13399 { 13400 result_sstream << " test_subroutineVS(gl_Position);\n"; 13401 } 13402 else 13403 { 13404 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 13405 } 13406 13407 result_sstream << "}\n"; 13408 13409 return result_sstream.str(); 13410 } 13411 13412 /** Executes test iteration. 13413 * 13414 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13415 */ 13416 tcu::TestNode::IterateResult NegativeTest8::iterate() 13417 { 13418 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13419 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13420 { 13421 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 13422 } 13423 13424 /* Iterate over all shader stages. For each iteration, iteration-specific shader stage 13425 * will feature an invalid subroutine definition. Other shader stages will be assigned 13426 * valid bodies. The test fails if a program built of such shaders links successfully. 13427 */ 13428 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 13429 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 13430 { 13431 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 13432 deinitIteration(); 13433 } /* for (all shader stages) */ 13434 13435 /* All done */ 13436 if (m_has_test_passed) 13437 { 13438 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13439 } 13440 else 13441 { 13442 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13443 } 13444 13445 return STOP; 13446 } 13447 13448 /** Constructor. 13449 * 13450 * @param context Rendering context. 13451 **/ 13452 NegativeTest9::NegativeTest9(deqp::Context& context) 13453 : TestCase(context, "subroutines_cannot_be_assigned_float_int_values_or_be_compared", 13454 "Make sure it is not possible to assign float/int to subroutine " 13455 "uniform and that subroutine uniform values cannot be compared.") 13456 , m_has_test_passed(true) 13457 , m_po_id(0) 13458 , m_vs_id(0) 13459 { 13460 /* Left blank intentionally */ 13461 } 13462 13463 /** Deinitializes any GL objects that may have been created during 13464 * test execution. 13465 **/ 13466 void NegativeTest9::deinit() 13467 { 13468 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13469 13470 if (m_po_id != 0) 13471 { 13472 gl.deleteProgram(m_po_id); 13473 13474 m_po_id = 0; 13475 } 13476 13477 if (m_vs_id != 0) 13478 { 13479 gl.deleteShader(m_vs_id); 13480 13481 m_vs_id = 0; 13482 } 13483 } 13484 13485 /** Returns a literal corresponding to user-specified test case enum. 13486 * 13487 * @param test_case As per description. 13488 * 13489 * @return Requested string. 13490 **/ 13491 std::string NegativeTest9::getTestCaseString(const _test_case& test_case) 13492 { 13493 std::string result = "?"; 13494 13495 switch (test_case) 13496 { 13497 case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 13498 result = "TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT"; 13499 break; 13500 case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 13501 result = "TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT"; 13502 break; 13503 case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON: 13504 result = "TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON"; 13505 break; 13506 default: 13507 break; 13508 } 13509 13510 return result; 13511 } 13512 13513 /** Retrieves vertex shader body for user-specified test case. 13514 * 13515 * @param test_case As per description. 13516 * 13517 * @return Requested string. 13518 **/ 13519 std::string NegativeTest9::getVertexShader(const _test_case& test_case) 13520 { 13521 std::stringstream result_sstream; 13522 13523 /* Form pre-amble */ 13524 result_sstream << "#version 400\n" 13525 "\n" 13526 "#extension GL_ARB_shader_subroutine : require\n" 13527 "\n" 13528 /* Define a subroutine */ 13529 "subroutine void subroutineType(inout vec4 test);\n" 13530 "\n" 13531 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13532 "{\n" 13533 " test += vec4(0, 1, 2, 3);\n" 13534 "}\n" 13535 "\n" 13536 "subroutine uniform subroutineType function;\n" 13537 "\n"; 13538 13539 /* Include case-specific implementation */ 13540 switch (test_case) 13541 { 13542 case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 13543 { 13544 result_sstream << "void main()\n" 13545 "{\n" 13546 " function = 1.0f;\n" 13547 "\n" 13548 " function(gl_Position);\n" 13549 "}\n"; 13550 13551 break; 13552 } 13553 13554 case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 13555 { 13556 result_sstream << "void main()\n" 13557 "{\n" 13558 " function = 1;\n" 13559 "\n" 13560 " function(gl_Position);\n" 13561 "}\n"; 13562 13563 break; 13564 } 13565 13566 case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON: 13567 { 13568 result_sstream << "subroutine uniform subroutineType function2;\n" 13569 "\n" 13570 "void main()\n" 13571 "{\n" 13572 " if (function == function2)\n" 13573 " {\n" 13574 " function(gl_Position);\n" 13575 " }\n" 13576 " else\n" 13577 " {\n" 13578 " function2(gl_Position);\n" 13579 " }\n" 13580 "}\n"; 13581 13582 break; 13583 } 13584 13585 default: 13586 break; 13587 } /* switch (test_case) */ 13588 13589 /* Done */ 13590 return result_sstream.str(); 13591 } 13592 13593 /** Executes test iteration. 13594 * 13595 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13596 */ 13597 tcu::TestNode::IterateResult NegativeTest9::iterate() 13598 { 13599 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13600 13601 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13602 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13603 { 13604 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 13605 } 13606 13607 /* Iterate over all test cases */ 13608 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 13609 { 13610 /* Try to build a program object using invalid vertex shader, specific to the 13611 * iteration we're currently in */ 13612 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 13613 13614 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 13615 "", /* te_body */ 13616 "", /* gs_body */ 13617 "", /* fs_body */ 13618 DE_NULL, /* xfb_varyings */ 13619 0, /* n_xfb_varyings */ 13620 &m_vs_id, DE_NULL, /* out_tc_id */ 13621 DE_NULL, /* out_te_id */ 13622 DE_NULL, /* out_gs_id */ 13623 DE_NULL, /* out_fs_id */ 13624 &m_po_id)) 13625 { 13626 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 13627 << getTestCaseString(static_cast<_test_case>(test_case)) 13628 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 13629 13630 m_has_test_passed = false; 13631 } 13632 13633 /* Delete any objects that may have been created */ 13634 deinit(); 13635 } /* for (all test cases) */ 13636 13637 /** All done */ 13638 if (m_has_test_passed) 13639 { 13640 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13641 } 13642 else 13643 { 13644 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13645 } 13646 13647 return STOP; 13648 } 13649 13650 /** Constructor. 13651 * 13652 * @param context Rendering context. 13653 **/ 13654 NegativeTest10::NegativeTest10(deqp::Context& context) 13655 : TestCase(context, "function_overloading_forbidden_for_subroutines", 13656 "Check that an overloaded function cannot be declared with subroutine and " 13657 "a program will fail to compile or link if any shader or stage contains" 13658 " two or more functions with the same name if the name is associated with" 13659 " a subroutine type.") 13660 , m_has_test_passed(true) 13661 , m_fs_id(0) 13662 , m_gs_id(0) 13663 , m_po_id(0) 13664 , m_tc_id(0) 13665 , m_te_id(0) 13666 , m_vs_id(0) 13667 { 13668 /* Left blank intentionally */ 13669 } 13670 13671 /** Deinitializes any GL objects that may have been created during 13672 * test execution. 13673 **/ 13674 void NegativeTest10::deinit() 13675 { 13676 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13677 13678 if (m_fs_id != 0) 13679 { 13680 gl.deleteShader(m_fs_id); 13681 13682 m_fs_id = 0; 13683 } 13684 13685 if (m_gs_id != 0) 13686 { 13687 gl.deleteShader(m_gs_id); 13688 13689 m_gs_id = 0; 13690 } 13691 13692 if (m_po_id != 0) 13693 { 13694 gl.deleteProgram(m_po_id); 13695 13696 m_po_id = 0; 13697 } 13698 13699 if (m_tc_id != 0) 13700 { 13701 gl.deleteShader(m_tc_id); 13702 13703 m_tc_id = 0; 13704 } 13705 13706 if (m_te_id != 0) 13707 { 13708 gl.deleteShader(m_te_id); 13709 13710 m_te_id = 0; 13711 } 13712 13713 if (m_vs_id != 0) 13714 { 13715 gl.deleteShader(m_vs_id); 13716 13717 m_vs_id = 0; 13718 } 13719 } 13720 13721 /** Retrieves fragment shader that should be used for the purpose of the test. 13722 * An overloaded version of a subroutine function is inserted if 13723 * @param include_duplicate_function flag is set to true. 13724 * 13725 * @param include_duplicate_function As per description. 13726 * 13727 * @return Requested string. 13728 **/ 13729 std::string NegativeTest10::getFragmentShader(bool include_duplicate_function) 13730 { 13731 std::stringstream result_sstream; 13732 13733 result_sstream << "#version 400\n" 13734 "\n" 13735 "#extension GL_ARB_shader_subroutine : require\n" 13736 "\n" 13737 "subroutine void subroutineType(inout vec4 test);\n" 13738 "\n" 13739 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13740 "{\n" 13741 " test = vec4(2, 3, 4, 5);\n" 13742 "}\n" 13743 "\n" 13744 "subroutine uniform subroutineType function;\n" 13745 "out vec4 result;\n" 13746 "\n"; 13747 13748 if (include_duplicate_function) 13749 { 13750 result_sstream << "void test_function(inout vec4 test)\n" 13751 "{\n" 13752 " test = vec4(3, 4, 5, 6);\n" 13753 "}\n" 13754 "\n"; 13755 } 13756 13757 result_sstream << "void main()\n" 13758 "{\n" 13759 " test_function(result);\n" 13760 "}\n"; 13761 13762 return result_sstream.str(); 13763 } 13764 13765 /** Retrieves geometry shader that should be used for the purpose of the test. 13766 * An overloaded version of a subroutine function is inserted if 13767 * @param include_duplicate_function flag is set to true. 13768 * 13769 * @param include_duplicate_function As per description. 13770 * 13771 * @return Requested string. 13772 **/ 13773 std::string NegativeTest10::getGeometryShader(bool include_duplicate_function) 13774 { 13775 std::stringstream result_sstream; 13776 13777 result_sstream << "#version 400\n" 13778 "\n" 13779 "#extension GL_ARB_shader_subroutine : require\n" 13780 "\n" 13781 "layout (triangles) in;\n" 13782 "layout (triangle_strip, max_vertices = 4) out;\n" 13783 "\n" 13784 "subroutine void subroutineType(inout vec4 test);\n" 13785 "\n" 13786 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13787 "{\n" 13788 " test = vec4(2, 3, 4, 5);\n" 13789 "}\n" 13790 "\n" 13791 "subroutine uniform subroutineType function;\n" 13792 "\n"; 13793 13794 if (include_duplicate_function) 13795 { 13796 result_sstream << "void test_function(inout vec4 test)\n" 13797 "{\n" 13798 " test = vec4(3, 4, 5, 6);\n" 13799 "}\n" 13800 "\n"; 13801 } 13802 13803 result_sstream << "void main()\n" 13804 "{\n" 13805 " function(gl_Position);\n" 13806 " EmitVertex();\n" 13807 " EndPrimitive();\n" 13808 "}\n"; 13809 13810 return result_sstream.str(); 13811 } 13812 13813 /** Retrieves tess control shader that should be used for the purpose of the test. 13814 * An overloaded version of a subroutine function is inserted if 13815 * @param include_duplicate_function flag is set to true. 13816 * 13817 * @param include_duplicate_function As per description. 13818 * 13819 * @return Requested string. 13820 **/ 13821 std::string NegativeTest10::getTessellationControlShader(bool include_duplicate_function) 13822 { 13823 std::stringstream result_sstream; 13824 13825 result_sstream << "#version 400\n" 13826 "\n" 13827 "#extension GL_ARB_shader_subroutine : require\n" 13828 "\n" 13829 "layout (vertices = 4) out;\n" 13830 "\n" 13831 "subroutine void subroutineType(inout vec4 test);\n" 13832 "\n" 13833 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13834 "{\n" 13835 " test = vec4(2, 3, 4, 5);\n" 13836 "}\n" 13837 "\n" 13838 "subroutine uniform subroutineType function;\n" 13839 "\n"; 13840 13841 if (include_duplicate_function) 13842 { 13843 result_sstream << "void test_function(inout vec4 test)\n" 13844 "{\n" 13845 " test = vec4(3, 4, 5, 6);\n" 13846 "}\n" 13847 "\n"; 13848 } 13849 13850 result_sstream << "void main()\n" 13851 "{\n" 13852 " vec4 temp;\n" 13853 "\n" 13854 " function(temp);\n" 13855 "\n" 13856 " gl_out[gl_InvocationID].gl_Position = temp;\n" 13857 " gl_TessLevelInner[0] = temp.x;\n" 13858 " gl_TessLevelInner[1] = temp.y;\n" 13859 " gl_TessLevelOuter[0] = temp.z;\n" 13860 " gl_TessLevelOuter[1] = temp.w;\n" 13861 " gl_TessLevelOuter[2] = temp.x;\n" 13862 " gl_TessLevelOuter[3] = temp.y;\n" 13863 "}\n"; 13864 13865 return result_sstream.str(); 13866 } 13867 13868 /** Retrieves tess evaluation shader that should be used for the purpose of the test. 13869 * An overloaded version of a subroutine function is inserted if 13870 * @param include_duplicate_function flag is set to true. 13871 * 13872 * @param include_duplicate_function As per description. 13873 * 13874 * @return Requested string. 13875 **/ 13876 std::string NegativeTest10::getTessellationEvaluationShader(bool include_duplicate_function) 13877 { 13878 std::stringstream result_sstream; 13879 13880 result_sstream << "#version 400\n" 13881 "\n" 13882 "#extension GL_ARB_shader_subroutine : require\n" 13883 "\n" 13884 "layout (quads) in;\n" 13885 "\n" 13886 "subroutine void subroutineType(inout vec4 test);\n" 13887 "\n" 13888 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13889 "{\n" 13890 " test = vec4(2, 3, 4, 5);\n" 13891 "}\n" 13892 "\n" 13893 "subroutine uniform subroutineType function;\n" 13894 "\n"; 13895 13896 if (include_duplicate_function) 13897 { 13898 result_sstream << "void test_function(inout vec4 test)\n" 13899 "{\n" 13900 " test = vec4(3, 4, 5, 6);\n" 13901 "}\n" 13902 "\n"; 13903 } 13904 13905 result_sstream << "void main()\n" 13906 "{\n" 13907 " vec4 temp;\n" 13908 "\n" 13909 " function(temp);\n" 13910 "\n" 13911 " gl_Position = temp;\n" 13912 "}\n"; 13913 13914 return result_sstream.str(); 13915 } 13916 13917 /** Retrieves vertex shader that should be used for the purpose of the test. 13918 * An overloaded version of a subroutine function is inserted if 13919 * @param include_duplicate_function flag is set to true. 13920 * 13921 * @param include_duplicate_function As per description. 13922 * 13923 * @return Requested string. 13924 **/ 13925 std::string NegativeTest10::getVertexShader(bool include_duplicate_function) 13926 { 13927 std::stringstream result_sstream; 13928 13929 result_sstream << "#version 400\n" 13930 "\n" 13931 "#extension GL_ARB_shader_subroutine : require\n" 13932 "\n" 13933 "subroutine void subroutineType(inout vec4 test);\n" 13934 "\n" 13935 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13936 "{\n" 13937 " test = vec4(2, 3, 4, 5);\n" 13938 "}\n" 13939 "\n" 13940 "subroutine uniform subroutineType function;\n" 13941 "\n"; 13942 13943 if (include_duplicate_function) 13944 { 13945 result_sstream << "void test_function(inout vec4 test)\n" 13946 "{\n" 13947 " test = vec4(3, 4, 5, 6);\n" 13948 "}\n" 13949 "\n"; 13950 } 13951 13952 result_sstream << "void main()\n" 13953 "{\n" 13954 " function(gl_Position);\n" 13955 "}\n"; 13956 13957 return result_sstream.str(); 13958 } 13959 13960 /** Fills m_test_cases field with test case descriptors */ 13961 void NegativeTest10::initTestCases() 13962 { 13963 /* For each test case, only one shader stage should define a function that 13964 * has already been defined as a subroutine. */ 13965 for (int offending_shader_stage_it = static_cast<int>(Utils::SHADER_STAGE_FIRST); 13966 offending_shader_stage_it != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++offending_shader_stage_it) 13967 { 13968 Utils::_shader_stage offending_shader_stage = static_cast<Utils::_shader_stage>(offending_shader_stage_it); 13969 /* Form the test case descriptor */ 13970 std::stringstream name_sstream; 13971 _test_case test_case; 13972 13973 name_sstream << "Broken shader stage:" << Utils::getShaderStageString(offending_shader_stage); 13974 13975 test_case.fs_body = getFragmentShader(offending_shader_stage == Utils::SHADER_STAGE_FRAGMENT); 13976 test_case.gs_body = getGeometryShader(offending_shader_stage == Utils::SHADER_STAGE_GEOMETRY); 13977 test_case.name = name_sstream.str(); 13978 test_case.tc_body = 13979 getTessellationControlShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 13980 test_case.te_body = 13981 getTessellationEvaluationShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 13982 test_case.vs_body = getVertexShader(offending_shader_stage == Utils::SHADER_STAGE_VERTEX); 13983 13984 m_test_cases.push_back(test_case); 13985 } 13986 } 13987 13988 /** Executes test iteration. 13989 * 13990 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13991 */ 13992 tcu::TestNode::IterateResult NegativeTest10::iterate() 13993 { 13994 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13995 13996 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13997 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13998 { 13999 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 14000 } 14001 14002 /* Form test cases */ 14003 initTestCases(); 14004 14005 /* Iterate over all test cases */ 14006 for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end(); 14007 ++test_case_iterator) 14008 { 14009 const _test_case& test_case = *test_case_iterator; 14010 14011 /* Try to build the program object */ 14012 if (ShaderSubroutine::Utils::buildProgram(gl, test_case.vs_body, test_case.tc_body, test_case.te_body, 14013 test_case.gs_body, test_case.fs_body, DE_NULL, /* xfb_varyings */ 14014 0, /* n_xfb_varyings */ 14015 &m_vs_id, (test_case.tc_body.length() > 0) ? &m_tc_id : DE_NULL, 14016 (test_case.te_body.length() > 0) ? &m_te_id : DE_NULL, 14017 (test_case.gs_body.length() > 0) ? &m_gs_id : DE_NULL, 14018 (test_case.fs_body.length() > 0) ? &m_fs_id : DE_NULL, &m_po_id)) 14019 { 14020 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 14021 << test_case.name << "] test case, even though it was invalid." 14022 << tcu::TestLog::EndMessage; 14023 14024 m_has_test_passed = false; 14025 } 14026 14027 /* Delete any objects that may have been created */ 14028 deinit(); 14029 } /* for (all test cases) */ 14030 14031 /** All done */ 14032 if (m_has_test_passed) 14033 { 14034 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 14035 } 14036 else 14037 { 14038 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 14039 } 14040 14041 return STOP; 14042 } 14043 14044 /** Constructor. 14045 * 14046 * @param context Rendering context. 14047 **/ 14048 NegativeTest11::NegativeTest11(deqp::Context& context) 14049 : TestCase(context, "subroutine_uniforms_used_for_sampling_atomic_image_functions", 14050 "Tries to use subroutine uniforms in invalid way in sampling, " 14051 "atomic and image functions. Verifies that compile- or link-time " 14052 "error occurs.") 14053 , m_has_test_passed(true) 14054 , m_po_id(0) 14055 , m_vs_id(0) 14056 { 14057 /* Left blank intentionally */ 14058 } 14059 14060 /** Deinitializes any GL objects that may have been created during 14061 * test execution. 14062 **/ 14063 void NegativeTest11::deinit() 14064 { 14065 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 14066 14067 if (m_po_id != 0) 14068 { 14069 gl.deleteProgram(m_po_id); 14070 14071 m_po_id = 0; 14072 } 14073 14074 if (m_vs_id != 0) 14075 { 14076 gl.deleteShader(m_vs_id); 14077 14078 m_vs_id = 0; 14079 } 14080 } 14081 14082 /** Returns a literal corresponding to user-specified test case enum. 14083 * 14084 * @param test_case As per description. 14085 * 14086 * @return Requested string. 14087 **/ 14088 std::string NegativeTest11::getTestCaseString(const _test_case& test_case) 14089 { 14090 std::string result = "?"; 14091 14092 switch (test_case) 14093 { 14094 case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT: 14095 result = "TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT"; 14096 break; 14097 case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT: 14098 result = "TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT"; 14099 break; 14100 case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT: 14101 result = "TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT"; 14102 break; 14103 default: 14104 break; 14105 } 14106 14107 return result; 14108 } 14109 14110 /** Retrieves vertex shader body for user-specified test case. 14111 * 14112 * @param test_case As per description. 14113 * 14114 * @return Requested string. 14115 **/ 14116 std::string NegativeTest11::getVertexShader(const _test_case& test_case) 14117 { 14118 std::stringstream result_sstream; 14119 14120 /* Form pre-amble */ 14121 result_sstream << "#version 400\n" 14122 "\n" 14123 "#extension GL_ARB_shader_subroutine : require\n"; 14124 14125 if (test_case == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT) 14126 { 14127 result_sstream << "#extension GL_ARB_shader_atomic_counters : require\n"; 14128 } 14129 14130 result_sstream << "\n" 14131 /* Define a subroutine */ 14132 "subroutine void subroutineType(inout vec4 test);\n" 14133 "\n" 14134 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 14135 "{\n" 14136 " test += vec4(0, 1, 2, 3);\n" 14137 "}\n" 14138 "\n" 14139 "subroutine uniform subroutineType function;\n" 14140 "\n" 14141 14142 /* Define main() body */ 14143 "void main()\n" 14144 "{\n"; 14145 14146 /* Implement case-specific behavior */ 14147 switch (test_case) 14148 { 14149 case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT: 14150 { 14151 result_sstream << "if (atomicCounter(function) > 2)\n" 14152 "{\n" 14153 " gl_Position = vec4(1);\n" 14154 "}\n"; 14155 14156 break; 14157 } 14158 14159 case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT: 14160 { 14161 result_sstream << "imageStore(function, vec2(0.0, 1.0), vec4(1.0) );\n"; 14162 14163 break; 14164 } 14165 14166 case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT: 14167 { 14168 result_sstream << "gl_Position = texture(function, vec2(1.0) );\n"; 14169 14170 break; 14171 } 14172 14173 default: 14174 break; 14175 } /* switch (test_case) */ 14176 14177 /* Close main() body */ 14178 result_sstream << "}\n"; 14179 14180 /* Done */ 14181 return result_sstream.str(); 14182 } 14183 14184 /** Executes test iteration. 14185 * 14186 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 14187 */ 14188 tcu::TestNode::IterateResult NegativeTest11::iterate() 14189 { 14190 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 14191 14192 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 14193 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 14194 { 14195 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 14196 } 14197 14198 /* Iterate over all test cases */ 14199 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 14200 { 14201 if (static_cast<_test_case>(test_case) == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT && 14202 !m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters")) 14203 { 14204 /* This iteration requires atomic counter support that this GL implementation 14205 * is not capable of. Skip the iteration 14206 */ 14207 continue; 14208 } 14209 14210 /* Try to build a program object using invalid vertex shader, specific to the 14211 * iteration we're currently in */ 14212 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 14213 14214 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 14215 "", /* te_body */ 14216 "", /* gs_body */ 14217 "", /* fs_body */ 14218 DE_NULL, /* xfb_varyings */ 14219 0, /* n_xfb_varyings */ 14220 &m_vs_id, DE_NULL, /* out_tc_id */ 14221 DE_NULL, /* out_te_id */ 14222 DE_NULL, /* out_gs_id */ 14223 DE_NULL, /* out_fs_id */ 14224 &m_po_id)) 14225 { 14226 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 14227 << getTestCaseString(static_cast<_test_case>(test_case)) 14228 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 14229 14230 m_has_test_passed = false; 14231 } 14232 14233 /* Delete any objects that may have been created */ 14234 deinit(); 14235 } /* for (all test cases) */ 14236 14237 /** All done */ 14238 if (m_has_test_passed) 14239 { 14240 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 14241 } 14242 else 14243 { 14244 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 14245 } 14246 14247 return STOP; 14248 } 14249 14250 /** Constructor. 14251 * 14252 * @param context Rendering context. 14253 **/ 14254 NegativeTest12::NegativeTest12(deqp::Context& context) 14255 : TestCase(context, "subroutines_not_allowed_as_variables_constructors_and_argument_or_return_types", 14256 "Verifies that it is not allowed to use subroutine type for " 14257 "local/global variables, constructors or argument/return type.") 14258 , m_has_test_passed(true) 14259 , m_po_id(0) 14260 , m_vs_id(0) 14261 { 14262 /* Left blank intentionally */ 14263 } 14264 14265 /** Deinitializes any GL objects that may have been created during 14266 * test execution. 14267 **/ 14268 void NegativeTest12::deinit() 14269 { 14270 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 14271 14272 if (m_po_id != 0) 14273 { 14274 gl.deleteProgram(m_po_id); 14275 14276 m_po_id = 0; 14277 } 14278 14279 if (m_vs_id != 0) 14280 { 14281 gl.deleteShader(m_vs_id); 14282 14283 m_vs_id = 0; 14284 } 14285 } 14286 14287 /** Returns a literal corresponding to user-specified test case enum. 14288 * 14289 * @param test_case As per description. 14290 * 14291 * @return Requested string. 14292 **/ 14293 std::string NegativeTest12::getTestCaseString(const _test_case& test_case) 14294 { 14295 std::string result = "?"; 14296 14297 switch (test_case) 14298 { 14299 case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE: 14300 result = "TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE"; 14301 break; 14302 case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE: 14303 result = "TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE"; 14304 break; 14305 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR: 14306 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR"; 14307 break; 14308 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT: 14309 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT"; 14310 break; 14311 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE: 14312 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE"; 14313 break; 14314 default: 14315 break; 14316 } 14317 14318 return result; 14319 } 14320 14321 /** Retrieves vertex shader body for user-specified test case. 14322 * 14323 * @param test_case As per description. 14324 * 14325 * @return Requested string. 14326 **/ 14327 std::string NegativeTest12::getVertexShader(const _test_case& test_case) 14328 { 14329 std::stringstream result_sstream; 14330 14331 /* Form pre-amble */ 14332 result_sstream << "#version 400\n" 14333 "\n" 14334 "#extension GL_ARB_shader_subroutine : require\n" 14335 "\n" 14336 /* Define a subroutine */ 14337 "subroutine void subroutineType(inout vec4 test);\n" 14338 "\n" 14339 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 14340 "{\n" 14341 " test += vec4(0, 1, 2, 3);\n" 14342 "}\n" 14343 "\n" 14344 "subroutine uniform subroutineType function;\n" 14345 "\n"; 14346 14347 /* Include case-specific implementation */ 14348 switch (test_case) 14349 { 14350 case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE: 14351 { 14352 result_sstream << "void main()\n" 14353 "{\n" 14354 " subroutine subroutineType function2;\n" 14355 " vec4 result;\n" 14356 "\n" 14357 " function2(result);\n" 14358 " gl_Position = result;\n" 14359 "}\n"; 14360 14361 break; 14362 } 14363 14364 case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE: 14365 { 14366 result_sstream << "subroutine subroutineType function2;\n" 14367 "\n" 14368 "void main()\n" 14369 "{\n" 14370 " vec4 result;\n" 14371 "\n" 14372 " function2(result);\n" 14373 " gl_Position = result;\n" 14374 "}\n"; 14375 14376 break; 14377 } 14378 14379 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR: 14380 { 14381 result_sstream << "void main()\n" 14382 "{\n" 14383 " subroutineType(function);\n" 14384 "}\n"; 14385 14386 break; 14387 } 14388 14389 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT: 14390 { 14391 result_sstream << "vec4 test_function(subroutineType argument)\n" 14392 "{\n" 14393 " vec4 result = vec4(1, 2, 3, 4);\n" 14394 "\n" 14395 " argument(result);\n" 14396 "\n" 14397 " return result;\n" 14398 "}\n" 14399 "\n" 14400 "void main()\n" 14401 "{\n" 14402 " test_function(function);\n" 14403 "}\n"; 14404 14405 break; 14406 } 14407 14408 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE: 14409 { 14410 result_sstream << "subroutineType test_function()\n" 14411 "{\n" 14412 " return function;\n" 14413 "}\n" 14414 "\n" 14415 "void main()\n" 14416 "{\n" 14417 " test_function()(gl_Position);\n" 14418 "}\n"; 14419 14420 break; 14421 } 14422 14423 default: 14424 break; 14425 } /* switch (test_case) */ 14426 14427 /* Done */ 14428 return result_sstream.str(); 14429 } 14430 14431 /** Executes test iteration. 14432 * 14433 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 14434 */ 14435 tcu::TestNode::IterateResult NegativeTest12::iterate() 14436 { 14437 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 14438 14439 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 14440 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 14441 { 14442 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 14443 } 14444 14445 /* Iterate over all test cases */ 14446 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 14447 { 14448 /* Try to build a program object using invalid vertex shader, specific to the 14449 * iteration we're currently in */ 14450 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 14451 14452 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 14453 "", /* te_body */ 14454 "", /* gs_body */ 14455 "", /* fs_body */ 14456 DE_NULL, /* xfb_varyings */ 14457 0, /* n_xfb_varyings */ 14458 &m_vs_id, DE_NULL, /* out_tc_id */ 14459 DE_NULL, /* out_te_id */ 14460 DE_NULL, /* out_gs_id */ 14461 DE_NULL, /* out_fs_id */ 14462 &m_po_id)) 14463 { 14464 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 14465 << getTestCaseString(static_cast<_test_case>(test_case)) 14466 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 14467 14468 m_has_test_passed = false; 14469 } 14470 14471 /* Delete any objects that may have been created */ 14472 deinit(); 14473 } /* for (all test cases) */ 14474 14475 /** All done */ 14476 if (m_has_test_passed) 14477 { 14478 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 14479 } 14480 else 14481 { 14482 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 14483 } 14484 14485 return STOP; 14486 } 14487 14488 } /* ShaderSubroutine */ 14489 14490 /** Constructor. 14491 * 14492 * @param context Rendering context. 14493 **/ 14494 ShaderSubroutineTests::ShaderSubroutineTests(deqp::Context& context) 14495 : TestCaseGroup(context, "shader_subroutine", "Verifies \"shader_subroutine\" functionality") 14496 { 14497 /* Left blank on purpose */ 14498 } 14499 14500 /** Initializes a texture_storage_multisample test group. 14501 * 14502 **/ 14503 void ShaderSubroutineTests::init(void) 14504 { 14505 addChild(new ShaderSubroutine::APITest1(m_context)); 14506 addChild(new ShaderSubroutine::APITest2(m_context)); 14507 addChild(new ShaderSubroutine::FunctionalTest1_2(m_context)); 14508 addChild(new ShaderSubroutine::FunctionalTest3_4(m_context)); 14509 addChild(new ShaderSubroutine::FunctionalTest5(m_context)); 14510 addChild(new ShaderSubroutine::FunctionalTest6(m_context)); 14511 addChild(new ShaderSubroutine::FunctionalTest7_8(m_context)); 14512 addChild(new ShaderSubroutine::FunctionalTest9(m_context)); 14513 addChild(new ShaderSubroutine::FunctionalTest10(m_context)); 14514 addChild(new ShaderSubroutine::FunctionalTest11(m_context)); 14515 addChild(new ShaderSubroutine::FunctionalTest12(m_context)); 14516 addChild(new ShaderSubroutine::FunctionalTest13(m_context)); 14517 addChild(new ShaderSubroutine::FunctionalTest14_15(m_context)); 14518 addChild(new ShaderSubroutine::FunctionalTest16(m_context)); 14519 addChild(new ShaderSubroutine::FunctionalTest17(m_context)); 14520 addChild(new ShaderSubroutine::FunctionalTest18_19(m_context)); 14521 addChild(new ShaderSubroutine::FunctionalTest20_21(m_context)); 14522 addChild(new ShaderSubroutine::NegativeTest1(m_context)); 14523 addChild(new ShaderSubroutine::NegativeTest2(m_context)); 14524 addChild(new ShaderSubroutine::NegativeTest3(m_context)); 14525 addChild(new ShaderSubroutine::NegativeTest4(m_context)); 14526 addChild(new ShaderSubroutine::NegativeTest5(m_context)); 14527 addChild(new ShaderSubroutine::NegativeTest6(m_context)); 14528 addChild(new ShaderSubroutine::NegativeTest7(m_context)); 14529 addChild(new ShaderSubroutine::NegativeTest8(m_context)); 14530 addChild(new ShaderSubroutine::NegativeTest9(m_context)); 14531 addChild(new ShaderSubroutine::NegativeTest10(m_context)); 14532 addChild(new ShaderSubroutine::NegativeTest11(m_context)); 14533 addChild(new ShaderSubroutine::NegativeTest12(m_context)); 14534 } 14535 14536 } /* glcts namespace */ 14537