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 /** Constructor. 9842 * 9843 * @param context Rendering context. 9844 * 9845 **/ 9846 NegativeTest1::NegativeTest1(deqp::Context& context) 9847 : TestCase(context, "subroutine_errors", "Verifies all GL_INVALID_OPERATION, GL_INVALID_VALUE, GL_INVALID ENUM " 9848 "errors related to subroutine usage are properly generated.") 9849 , m_has_test_passed(true) 9850 , m_po_active_subroutine_uniform_locations(0) 9851 , m_po_active_subroutine_uniforms(0) 9852 , m_po_active_subroutines(0) 9853 , m_po_subroutine_uniform_function_index(-1) 9854 , m_po_subroutine_uniform_function2_index(-1) 9855 , m_po_subroutine_test1_index(GL_INVALID_INDEX) 9856 , m_po_subroutine_test2_index(GL_INVALID_INDEX) 9857 , m_po_subroutine_test3_index(GL_INVALID_INDEX) 9858 , m_po_not_linked_id(0) 9859 , m_po_id(0) 9860 , m_vs_id(0) 9861 { 9862 /* Left blank intentionally */ 9863 } 9864 9865 /** Deinitializes all GL objects that may have been created during 9866 * test execution. 9867 **/ 9868 void NegativeTest1::deinit() 9869 { 9870 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9871 9872 if (m_po_id != 0) 9873 { 9874 gl.deleteProgram(m_po_id); 9875 9876 m_po_id = 0; 9877 } 9878 9879 if (m_po_not_linked_id != 0) 9880 { 9881 gl.deleteProgram(m_po_not_linked_id); 9882 9883 m_po_not_linked_id = 0; 9884 } 9885 9886 if (m_vs_id != 0) 9887 { 9888 gl.deleteShader(m_vs_id); 9889 9890 m_vs_id = 0; 9891 } 9892 } 9893 9894 /** Initializes all GL objects required to run the test. */ 9895 void NegativeTest1::initTest() 9896 { 9897 glw::GLint compile_status = GL_FALSE; 9898 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9899 9900 /* Create program objects */ 9901 m_po_not_linked_id = gl.createProgram(); 9902 m_po_id = gl.createProgram(); 9903 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed."); 9904 9905 /* Create vertex shader object */ 9906 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 9907 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 9908 9909 /* Set up vertex shader */ 9910 const char* vs_body = "#version 400\n" 9911 "\n" 9912 "#extension GL_ARB_shader_subroutine : require\n" 9913 "\n" 9914 "subroutine void subroutineType (out ivec2 arg);\n" 9915 "subroutine void subroutineType2(out ivec4 arg);\n" 9916 "\n" 9917 "subroutine(subroutineType) void test1(out ivec2 arg)\n" 9918 "{\n" 9919 " arg = ivec2(1, 2);\n" 9920 "}\n" 9921 "subroutine(subroutineType) void test2(out ivec2 arg)\n" 9922 "{\n" 9923 " arg = ivec2(3,4);\n" 9924 "}\n" 9925 "subroutine(subroutineType2) void test3(out ivec4 arg)\n" 9926 "{\n" 9927 " arg = ivec4(1, 2, 3, 4);\n" 9928 "}\n" 9929 "\n" 9930 "subroutine uniform subroutineType function;\n" 9931 "subroutine uniform subroutineType2 function2;\n" 9932 "\n" 9933 "void main()\n" 9934 "{\n" 9935 " ivec2 test;\n" 9936 " ivec4 test2;\n" 9937 "\n" 9938 " function(test);\n" 9939 "\n" 9940 " if (test.x > 2)\n" 9941 " {\n" 9942 " gl_Position = vec4(1);\n" 9943 " }\n" 9944 " else\n" 9945 " {\n" 9946 " function2(test2);\n" 9947 "\n" 9948 " gl_Position = vec4(float(test2.x) );\n" 9949 " }\n" 9950 "}\n"; 9951 9952 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */); 9953 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 9954 9955 gl.compileShader(m_vs_id); 9956 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 9957 9958 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); 9959 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 9960 9961 if (compile_status == GL_FALSE) 9962 { 9963 TCU_FAIL("Shader compilation failed"); 9964 } 9965 9966 /* Set up & link the test program object */ 9967 glw::GLint link_status = GL_FALSE; 9968 9969 gl.attachShader(m_po_id, m_vs_id); 9970 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 9971 9972 gl.linkProgram(m_po_id); 9973 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 9974 9975 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 9976 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 9977 9978 if (link_status == GL_FALSE) 9979 { 9980 TCU_FAIL("Program linking failed"); 9981 } 9982 9983 /* Query test program object's properties */ 9984 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, 9985 &m_po_active_subroutine_uniform_locations); 9986 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &m_po_active_subroutine_uniforms); 9987 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &m_po_active_subroutines); 9988 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call(s) failed."); 9989 9990 if (m_po_active_subroutine_uniform_locations != 2) 9991 { 9992 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS value returned"); 9993 } 9994 9995 m_po_subroutine_test1_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test1"); 9996 m_po_subroutine_test2_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test2"); 9997 m_po_subroutine_test3_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test3"); 9998 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 9999 10000 if (m_po_subroutine_test1_index == GL_INVALID_INDEX || m_po_subroutine_test2_index == GL_INVALID_INDEX || 10001 m_po_subroutine_test3_index == GL_INVALID_INDEX) 10002 { 10003 TCU_FAIL("Invalid subroutine index returned"); 10004 } 10005 10006 m_po_subroutine_uniform_function_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function"); 10007 m_po_subroutine_uniform_function2_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function2"); 10008 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed."); 10009 10010 if (m_po_subroutine_uniform_function_index == -1 || m_po_subroutine_uniform_function2_index == -1) 10011 { 10012 TCU_FAIL("Invalid subroutine uniform index returned"); 10013 } 10014 } 10015 10016 /** Executes test iteration. 10017 * 10018 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10019 */ 10020 tcu::TestNode::IterateResult NegativeTest1::iterate() 10021 { 10022 glw::GLenum error_code = GL_NO_ERROR; 10023 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10024 10025 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 10026 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 10027 { 10028 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 10029 } 10030 10031 /* Initialize GL objects required to run the test */ 10032 initTest(); 10033 10034 /* The error INVALID_OPERATION is generated by GetSubroutineUniformLocation 10035 * if the program object identified by <program> has not been successfully 10036 * linked. 10037 */ 10038 gl.getSubroutineUniformLocation(m_po_not_linked_id, GL_FRAGMENT_SHADER, "subroutine_uniform_name"); 10039 10040 error_code = gl.getError(); 10041 10042 if (error_code != GL_INVALID_OPERATION) 10043 { 10044 m_testCtx.getLog() << tcu::TestLog::Message 10045 << "glGetSubroutineUniformLocation() does not generate GL_INVALID_OPERATION " 10046 "error code when called for a non-linked program object." 10047 << tcu::TestLog::EndMessage; 10048 10049 m_has_test_passed = false; 10050 } 10051 10052 /* The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or 10053 * GetActiveSubroutineUniformName if <index> is greater than or equal to the 10054 * value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage. 10055 */ 10056 glw::GLint temp_length = 0; 10057 glw::GLint temp_values = 0; 10058 10059 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 10060 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values); 10061 error_code = gl.getError(); 10062 10063 if (error_code == GL_INVALID_VALUE) 10064 { 10065 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1, 10066 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values); 10067 10068 error_code = gl.getError(); 10069 } 10070 10071 if (error_code != GL_INVALID_VALUE) 10072 { 10073 m_testCtx.getLog() << tcu::TestLog::Message 10074 << "glGetActiveSubroutineUniformiv() does not generate GL_INVALID_VALUE " 10075 "when passed <index> argument that is greater than or equal to " 10076 "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS." 10077 << tcu::TestLog::EndMessage; 10078 10079 m_has_test_passed = false; 10080 } 10081 10082 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 0, /* bufsize */ 10083 &temp_length, DE_NULL); /* name */ 10084 error_code = gl.getError(); 10085 10086 if (error_code == GL_INVALID_VALUE) 10087 { 10088 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1, 10089 0, /* bufsize */ 10090 &temp_length, DE_NULL); /* name */ 10091 10092 error_code = gl.getError(); 10093 } 10094 10095 if (error_code != GL_INVALID_VALUE) 10096 { 10097 m_testCtx.getLog() << tcu::TestLog::Message 10098 << "glGetActiveSubroutineUniformName() does not generate GL_INVALID_VALUE " 10099 "when passed <index> argument that is greater than or equal to " 10100 "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS." 10101 << tcu::TestLog::EndMessage; 10102 10103 m_has_test_passed = false; 10104 } 10105 10106 /* The error INVALID_VALUE is generated by GetActiveSubroutineName if <index> 10107 * is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader 10108 * stage. 10109 */ 10110 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines, 0, /* bufsize */ 10111 &temp_length, DE_NULL); /* name */ 10112 error_code = gl.getError(); 10113 10114 if (error_code == GL_INVALID_VALUE) 10115 { 10116 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines + 1, 0, /* bufsize */ 10117 &temp_length, DE_NULL); /* name */ 10118 10119 error_code = gl.getError(); 10120 } 10121 10122 if (error_code != GL_INVALID_VALUE) 10123 { 10124 m_testCtx.getLog() << tcu::TestLog::Message << "glGetActiveSubroutineName() does not generate GL_INVALID_VALUE " 10125 "when passed <index> argument that is greater than or equal to " 10126 "the value of GL_ACTIVE_SUBROUTINES." 10127 << tcu::TestLog::EndMessage; 10128 10129 m_has_test_passed = false; 10130 } 10131 10132 /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count> 10133 * is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the 10134 * shader stage <shadertype>. 10135 */ 10136 glw::GLuint index = 0; 10137 10138 gl.useProgram(m_po_id); 10139 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10140 10141 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations - 1, &index); 10142 error_code = gl.getError(); 10143 10144 if (error_code == GL_INVALID_VALUE) 10145 { 10146 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &index); 10147 10148 error_code = gl.getError(); 10149 } 10150 10151 if (error_code != GL_INVALID_VALUE) 10152 { 10153 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesiv() does not generate GL_INVALID_VALUE " 10154 "when passed <count> argument that is not equal to the value of " 10155 "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS." 10156 << tcu::TestLog::EndMessage; 10157 10158 m_has_test_passed = false; 10159 } 10160 10161 /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value 10162 * in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES 10163 * for the shader stage. 10164 */ 10165 glw::GLuint invalid_subroutine_indices[4] = { (GLuint)m_po_active_subroutines, (GLuint)m_po_active_subroutines, 10166 (GLuint)m_po_active_subroutines + 1, 10167 (GLuint)m_po_active_subroutines + 1 }; 10168 10169 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, /* count */ 10170 invalid_subroutine_indices + 0); 10171 error_code = gl.getError(); 10172 10173 if (error_code == GL_INVALID_VALUE) 10174 { 10175 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, 10176 invalid_subroutine_indices + 2); 10177 10178 error_code = gl.getError(); 10179 } 10180 10181 if (error_code != GL_INVALID_VALUE) 10182 { 10183 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesuiv() does not generate GL_INVALID_VALUE " 10184 "when the value passed via <indices> argument is greater than " 10185 "or equal to the value of GL_ACTIVE_SUBROUTINES." 10186 << tcu::TestLog::EndMessage; 10187 10188 m_has_test_passed = false; 10189 } 10190 10191 /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv() if any 10192 * subroutine index in <indices> identifies a subroutine not associated with 10193 * the type of the subroutine uniform variable assigned to the corresponding 10194 * location. 10195 */ 10196 glw::GLuint invalid_subroutine_indices2[2] = { m_po_subroutine_test1_index, m_po_subroutine_test1_index }; 10197 10198 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, invalid_subroutine_indices2); 10199 error_code = gl.getError(); 10200 10201 if (error_code != GL_INVALID_OPERATION) 10202 { 10203 m_testCtx.getLog() << tcu::TestLog::Message 10204 << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION " 10205 "when the subroutine index passed via <indices> argument identifies" 10206 "a subroutine not associated with the type of the subroutine uniform " 10207 "assigned to the corresponding location." 10208 << tcu::TestLog::EndMessage; 10209 10210 m_has_test_passed = false; 10211 } 10212 10213 /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no 10214 * program is active. 10215 */ 10216 glw::GLuint valid_subroutine_locations[2] = { 0 }; 10217 10218 valid_subroutine_locations[m_po_subroutine_uniform_function_index] = m_po_subroutine_test1_index; 10219 valid_subroutine_locations[m_po_subroutine_uniform_function2_index] = m_po_subroutine_test3_index; 10220 10221 gl.useProgram(0); 10222 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10223 10224 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, valid_subroutine_locations); 10225 error_code = gl.getError(); 10226 10227 if (error_code != GL_INVALID_OPERATION) 10228 { 10229 m_testCtx.getLog() << tcu::TestLog::Message 10230 << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION " 10231 "when called without an active program object." 10232 << tcu::TestLog::EndMessage; 10233 10234 m_has_test_passed = false; 10235 } 10236 10237 /* The error INVALID_VALUE is generated by GetUniformSubroutineuiv if 10238 * <location> is greater than or equal to the value of 10239 * ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage. 10240 */ 10241 glw::GLuint temp_value = 0; 10242 10243 gl.useProgram(m_po_id); 10244 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10245 10246 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, &temp_value); 10247 error_code = gl.getError(); 10248 10249 if (error_code == GL_INVALID_VALUE) 10250 { 10251 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &temp_value); 10252 error_code = gl.getError(); 10253 } 10254 10255 if (error_code != GL_INVALID_VALUE) 10256 { 10257 m_testCtx.getLog() << tcu::TestLog::Message 10258 << "glGetUniformSubroutineuiv() does not generate GL_INVALID_VALUE " 10259 "when called for location that is greater than or equal to the value " 10260 "of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS." 10261 << tcu::TestLog::EndMessage; 10262 10263 m_has_test_passed = false; 10264 } 10265 10266 /* The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no 10267 * program is active for the shader stage identified by <shadertype>. 10268 */ 10269 const glw::GLenum undefined_shader_stages[] = { GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER, 10270 GL_TESS_EVALUATION_SHADER }; 10271 const unsigned int n_undefined_shader_stages = sizeof(undefined_shader_stages) / sizeof(undefined_shader_stages[0]); 10272 10273 for (unsigned int n_undefined_shader_stage = 0; n_undefined_shader_stage < n_undefined_shader_stages; 10274 ++n_undefined_shader_stage) 10275 { 10276 glw::GLenum shader_stage = undefined_shader_stages[n_undefined_shader_stage]; 10277 10278 gl.getUniformSubroutineuiv(shader_stage, 0, /* location */ 10279 &temp_value); 10280 error_code = gl.getError(); 10281 10282 if (error_code != GL_INVALID_OPERATION) 10283 { 10284 m_testCtx.getLog() << tcu::TestLog::Message 10285 << "glGetUniformSubroutineuiv() does not generate GL_INVALID_OPERATION " 10286 "when called for a shader stage that is not defined for active " 10287 "program object." 10288 << tcu::TestLog::EndMessage; 10289 10290 m_has_test_passed = false; 10291 } 10292 } /* for (all undefined shader stages) */ 10293 10294 /* All done */ 10295 if (m_has_test_passed) 10296 { 10297 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 10298 } 10299 else 10300 { 10301 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 10302 } 10303 10304 return STOP; 10305 } 10306 10307 /** Constructor 10308 * 10309 * @param context Rendering context. 10310 * 10311 **/ 10312 NegativeTest2::NegativeTest2(deqp::Context& context) 10313 : TestCase(context, "subroutine_uniform_scope", "Verifies subroutine uniforms declared in shader stage A" 10314 "cannot be accessed from a different stage.") 10315 , m_fs_id(0) 10316 , m_gs_id(0) 10317 , m_has_test_passed(true) 10318 , m_po_id(0) 10319 , m_tc_id(0) 10320 , m_te_id(0) 10321 , m_vs_id(0) 10322 { 10323 /* Left blank intentionally */ 10324 } 10325 10326 /** Deinitializes all GL objects that may have been created during test execution */ 10327 void NegativeTest2::deinit() 10328 { 10329 deinitGLObjects(); 10330 } 10331 10332 /** Deinitializes all GL objects that may have been created during test execution */ 10333 void NegativeTest2::deinitGLObjects() 10334 { 10335 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10336 10337 if (m_fs_id != 0) 10338 { 10339 gl.deleteShader(m_fs_id); 10340 10341 m_fs_id = 0; 10342 } 10343 10344 if (m_gs_id != 0) 10345 { 10346 gl.deleteShader(m_gs_id); 10347 10348 m_gs_id = 0; 10349 } 10350 10351 if (m_tc_id != 0) 10352 { 10353 gl.deleteShader(m_tc_id); 10354 10355 m_tc_id = 0; 10356 } 10357 10358 if (m_te_id != 0) 10359 { 10360 gl.deleteShader(m_te_id); 10361 10362 m_te_id = 0; 10363 } 10364 10365 if (m_vs_id != 0) 10366 { 10367 gl.deleteShader(m_vs_id); 10368 10369 m_vs_id = 0; 10370 } 10371 10372 if (m_po_id != 0) 10373 { 10374 gl.deleteProgram(m_po_id); 10375 10376 m_po_id = 0; 10377 } 10378 } 10379 10380 /** Builds an offending program object and tries to link it. We're either expecting 10381 * a compile-time or link-time error here. 10382 * 10383 * If the program object builds successfully, the test has failed. 10384 * 10385 * @param referencing_stage Shader stage which defines a subroutine uniform that 10386 * should be called from fragment/geometry/tess control/ 10387 * tess evaluation/vertex shader stages. 10388 * 10389 **/ 10390 void NegativeTest2::executeTestCase(const Utils::_shader_stage& referencing_stage) 10391 { 10392 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10393 10394 const std::string fs_body = getFragmentShaderBody(referencing_stage); 10395 const std::string gs_body = getGeometryShaderBody(referencing_stage); 10396 const std::string tc_body = getTessellationControlShaderBody(referencing_stage); 10397 const std::string te_body = getTessellationEvaluationShaderBody(referencing_stage); 10398 const std::string vs_body = getVertexShaderBody(referencing_stage); 10399 10400 if (Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, NULL, /* xfb_varyings */ 10401 0, /* n_xfb_varyings */ 10402 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 10403 { 10404 /* Test program should not have built correctly ! */ 10405 m_testCtx.getLog() << tcu::TestLog::Message << "In the following program, one of the stages references " 10406 "a subroutine that is defined in another stage. This " 10407 "is forbidden by the specification.\n" 10408 "\n" 10409 "Vertex shader:\n\n" 10410 << vs_body.c_str() << "\n\nTessellation control shader:\n\n" 10411 << tc_body.c_str() << "\n\nTessellation evaluation shader:\n\n" 10412 << te_body.c_str() << "\n\nGeometry shader:\n\n" 10413 << gs_body.c_str() << "\n\nFragment shader:\n\n" 10414 << fs_body.c_str() << tcu::TestLog::EndMessage; 10415 10416 m_has_test_passed = false; 10417 } /* if (test program was built successfully) */ 10418 10419 /* Release the shaders & the program object that buildProgram() created */ 10420 deinitGLObjects(); 10421 } 10422 10423 /** Retrieves an offending fragment shader body. 10424 * 10425 * @param referencing_stage Shader stage which defines the subroutine uniform that 10426 * will be called from fragment shader. 10427 * 10428 * @return Requested string. 10429 **/ 10430 std::string NegativeTest2::getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const 10431 { 10432 std::stringstream result; 10433 10434 /* Form the pre-amble */ 10435 result << "#version 400\n" 10436 "\n" 10437 "#extension GL_ARB_shader_subroutine : require\n" 10438 "\n" 10439 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10440 "\n" 10441 /* Define a subroutine */ 10442 "subroutine(testSubroutineType) void fs_subroutine(out vec4 test_argument)\n" 10443 "{\n" 10444 " test_argument = vec4(1, 0, 0, 0);\n" 10445 "}\n" 10446 "\n" 10447 /* Define output variables */ 10448 "out vec4 result;\n" 10449 "\n" 10450 /* Define uniforms */ 10451 "subroutine uniform testSubroutineType test_fs_subroutine;\n" 10452 "\n" 10453 /* Define main() */ 10454 "void main()\n" 10455 "{\n" 10456 " " 10457 << getSubroutineUniformName(referencing_stage) << "(result);\n" 10458 "}\n"; 10459 10460 return result.str(); 10461 } 10462 10463 /** Retrieves an offending geometry shader body. 10464 * 10465 * @param referencing_stage Shader stage which defines the subroutine uniform that 10466 * will be called from geometry shader. 10467 * 10468 * @return Requested string. 10469 **/ 10470 std::string NegativeTest2::getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const 10471 { 10472 std::stringstream result; 10473 10474 /* Form the pre-amble */ 10475 result << "#version 400\n" 10476 "\n" 10477 "#extension GL_ARB_shader_subroutine : require\n" 10478 "\n" 10479 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10480 "\n" 10481 "layout(points) in;\n" 10482 "layout(points, max_vertices = 1) out;\n" 10483 "\n" 10484 /* Define a subroutine */ 10485 "subroutine(testSubroutineType) void gs_subroutine(out vec4 test_argument)\n" 10486 "{\n" 10487 " test_argument = vec4(0, 1, 1, 1);\n" 10488 "}\n" 10489 "\n" 10490 /* Define output variables */ 10491 "out vec4 result;\n" 10492 "\n" 10493 /* Define uniforms */ 10494 "subroutine uniform testSubroutineType test_gs_subroutine;\n" 10495 "\n" 10496 /* Define main() */ 10497 "void main()\n" 10498 "{\n" 10499 " " 10500 << getSubroutineUniformName(referencing_stage) << "(result);\n" 10501 "}\n"; 10502 10503 return result.str(); 10504 } 10505 10506 /** Retrieves name of the subroutine uniform that is defined in user-specified 10507 * shader stage. 10508 * 10509 * @param stage Shader stage to retrieve the subroutine uniform name for. 10510 * 10511 * @return As per description. 10512 **/ 10513 std::string NegativeTest2::getSubroutineUniformName(const Utils::_shader_stage& stage) const 10514 { 10515 std::string result = "?"; 10516 10517 switch (stage) 10518 { 10519 case Utils::SHADER_STAGE_FRAGMENT: 10520 { 10521 result = "test_fs_subroutine"; 10522 10523 break; 10524 } 10525 10526 case Utils::SHADER_STAGE_GEOMETRY: 10527 { 10528 result = "test_gs_subroutine"; 10529 10530 break; 10531 } 10532 10533 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 10534 { 10535 result = "test_tc_subroutine"; 10536 10537 break; 10538 } 10539 10540 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 10541 { 10542 result = "test_te_subroutine"; 10543 10544 break; 10545 } 10546 10547 case Utils::SHADER_STAGE_VERTEX: 10548 { 10549 result = "test_vs_subroutine"; 10550 10551 break; 10552 } 10553 10554 default: 10555 { 10556 TCU_FAIL("Unrecognized shader stage requested"); 10557 } 10558 } /* switch (stage) */ 10559 10560 return result; 10561 } 10562 10563 /** Retrieves an offending tessellation control shader body. 10564 * 10565 * @param referencing_stage Shader stage which defines the subroutine uniform that 10566 * will be called from tessellation control shader. 10567 * 10568 * @return Requested string. 10569 **/ 10570 std::string NegativeTest2::getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const 10571 { 10572 std::stringstream result; 10573 10574 /* Form the pre-amble */ 10575 result << "#version 400\n" 10576 "\n" 10577 "#extension GL_ARB_shader_subroutine : require\n" 10578 "\n" 10579 "layout(vertices = 4) out;\n" 10580 "\n" 10581 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10582 "\n" 10583 /* Define a subroutine */ 10584 "subroutine(testSubroutineType) void tc_subroutine(out vec4 test_argument)\n" 10585 "{\n" 10586 " test_argument = vec4(0, 0, 1, 0);\n" 10587 "}\n" 10588 "\n" 10589 /* Define uniforms */ 10590 "subroutine uniform testSubroutineType test_tc_subroutine;\n" 10591 "\n" 10592 /* Define main() */ 10593 "void main()\n" 10594 "{\n" 10595 " " 10596 << getSubroutineUniformName(referencing_stage) << "(gl_out[gl_InvocationID].gl_Position);\n" 10597 "}\n"; 10598 10599 return result.str(); 10600 } 10601 10602 /** Retrieves an offending tessellation evaluation shader body. 10603 * 10604 * @param referencing_stage Shader stage which defines the subroutine uniform that 10605 * will be called from tessellation evaluation shader. 10606 * 10607 * @return Requested string. 10608 **/ 10609 std::string NegativeTest2::getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const 10610 { 10611 std::stringstream result; 10612 10613 /* Form the pre-amble */ 10614 result << "#version 400\n" 10615 "\n" 10616 "#extension GL_ARB_shader_subroutine : require\n" 10617 "\n" 10618 "layout(quads) in;\n" 10619 "\n" 10620 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10621 "\n" 10622 /* Define a subroutine */ 10623 "subroutine(testSubroutineType) void te_subroutine(out vec4 test_argument)\n" 10624 "{\n" 10625 " test_argument = vec4(1, 1, 1, 1);\n" 10626 "}\n" 10627 "\n" 10628 /* Define uniforms */ 10629 "subroutine uniform testSubroutineType test_te_subroutine;\n" 10630 "\n" 10631 /* Define main() */ 10632 "void main()\n" 10633 "{\n" 10634 " " 10635 << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n" 10636 "}\n"; 10637 10638 return result.str(); 10639 } 10640 10641 /** Retrieves an offending vertex shader body. 10642 * 10643 * @param referencing_stage Shader stage which defines the subroutine uniform that 10644 * will be called from vertex shader. 10645 * 10646 * @return Requested string. 10647 **/ 10648 std::string NegativeTest2::getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const 10649 { 10650 std::stringstream result; 10651 10652 /* Form the pre-amble */ 10653 result << "#version 400\n" 10654 "\n" 10655 "#extension GL_ARB_shader_subroutine : require\n" 10656 "\n" 10657 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10658 "\n" 10659 /* Define a subroutine */ 10660 "subroutine(testSubroutineType) void vs_subroutine(out vec4 test_argument)\n" 10661 "{\n" 10662 " test_argument = vec4(0, 1, 0, 0);\n" 10663 "}\n" 10664 "\n" 10665 /* Define uniforms */ 10666 "subroutine uniform testSubroutineType test_vs_subroutine;\n" 10667 "\n" 10668 /* Define main() */ 10669 "void main()\n" 10670 "{\n" 10671 " " 10672 << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n" 10673 "}\n"; 10674 10675 return result.str(); 10676 } 10677 10678 /** Executes test iteration. 10679 * 10680 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10681 */ 10682 tcu::TestNode::IterateResult NegativeTest2::iterate() 10683 { 10684 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 10685 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 10686 { 10687 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 10688 } 10689 10690 /* Iterate over all shader stages and execute the checks */ 10691 for (int referencing_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 10692 referencing_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++referencing_stage) 10693 { 10694 executeTestCase(static_cast<Utils::_shader_stage>(referencing_stage)); 10695 } /* for (all test cases) */ 10696 10697 /* All done */ 10698 if (m_has_test_passed) 10699 { 10700 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 10701 } 10702 else 10703 { 10704 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 10705 } 10706 10707 return STOP; 10708 } 10709 10710 /** Constructor. 10711 * 10712 * @param context Rendering context. 10713 * 10714 **/ 10715 NegativeTest3::NegativeTest3(deqp::Context& context) 10716 : TestCase(context, "missing_subroutine_keyword", "Verifies that subroutine keyword is necessary when declaring a " 10717 "subroutine uniforn and a compilation error occurs without it.") 10718 , m_has_test_passed(true) 10719 , m_so_id(0) 10720 { 10721 /* Left blank intentionally */ 10722 } 10723 10724 /** Deinitializes all GL objects that may have been created during test execution */ 10725 void NegativeTest3::deinit() 10726 { 10727 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10728 10729 if (m_so_id != 0) 10730 { 10731 gl.deleteShader(m_so_id); 10732 10733 m_so_id = 0; 10734 } 10735 } 10736 10737 /** Verifies that broken shader (for user-specified shader stage) does not compile. 10738 * 10739 * @param shader_stage Shader stage to use for the test. 10740 **/ 10741 void NegativeTest3::executeTest(const Utils::_shader_stage& shader_stage) 10742 { 10743 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10744 10745 /* Generate a new shader object */ 10746 m_so_id = gl.createShader(Utils::getGLenumForShaderStage(shader_stage)); 10747 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 10748 10749 /* Assign body to the shader */ 10750 std::string body; 10751 const char* body_raw_ptr = DE_NULL; 10752 10753 switch (shader_stage) 10754 { 10755 case Utils::SHADER_STAGE_VERTEX: 10756 body = getVertexShaderBody(); 10757 break; 10758 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 10759 body = getTessellationControlShaderBody(); 10760 break; 10761 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 10762 body = getTessellationEvaluationShaderBody(); 10763 break; 10764 case Utils::SHADER_STAGE_GEOMETRY: 10765 body = getGeometryShaderBody(); 10766 break; 10767 case Utils::SHADER_STAGE_FRAGMENT: 10768 body = getFragmentShaderBody(); 10769 break; 10770 10771 default: 10772 { 10773 TCU_FAIL("Unrecognized shader stage requested"); 10774 } 10775 } /* switch (shader_stage) */ 10776 10777 body_raw_ptr = body.c_str(); 10778 10779 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */); 10780 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 10781 10782 /* Try to compile the shader */ 10783 glw::GLint compile_status = 0; 10784 10785 gl.compileShader(m_so_id); 10786 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 10787 10788 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status); 10789 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 10790 10791 if (compile_status == GL_TRUE) 10792 { 10793 m_testCtx.getLog() << tcu::TestLog::Message << "The following shader was expected to fail to compile but was " 10794 "accepted by the compiler:\n" 10795 "\n" 10796 << body.c_str() << tcu::TestLog::EndMessage; 10797 10798 m_has_test_passed = false; 10799 } 10800 10801 /* Good to release the shader at this point */ 10802 gl.deleteShader(m_so_id); 10803 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed."); 10804 } 10805 10806 /** Retrieves body of a broken fragment shader. 10807 * 10808 * @return Requested string. 10809 **/ 10810 std::string NegativeTest3::getFragmentShaderBody() const 10811 { 10812 return "#version 400\n" 10813 "\n" 10814 "#extension GL_ARB_shader_subroutine : require\n" 10815 "\n" 10816 "subroutine void testSubroutineType(inout vec4 test);\n" 10817 "\n" 10818 "void testSubroutine1(inout vec4 test)\n" 10819 "{\n" 10820 " test += vec4(3, 4, 5, 6);\n" 10821 "}\n" 10822 "\n" 10823 "uniform testSubroutineType subroutineFunction;\n" 10824 "out vec4 result;\n" 10825 "\n" 10826 "void main()\n" 10827 "{\n" 10828 " vec4 test = vec4(2, 3, 4, 5);\n" 10829 "\n" 10830 " subroutineFunction(test);\n" 10831 "\n" 10832 " result = test;\n" 10833 "}\n"; 10834 } 10835 10836 /** Retrieves body of a broken geometry shader. 10837 * 10838 * @return Requested string. 10839 **/ 10840 std::string NegativeTest3::getGeometryShaderBody() const 10841 { 10842 return "#version 400\n" 10843 "\n" 10844 "#extension GL_ARB_shader_subroutine : require\n" 10845 "\n" 10846 "layout(points) in;\n" 10847 "layout(points, max_vertices = 1) out;\n" 10848 "\n" 10849 "subroutine void testSubroutineType(inout vec4 test);\n" 10850 "\n" 10851 "void testSubroutine1(inout vec4 test)\n" 10852 "{\n" 10853 " test += vec4(3, 4, 5, 6);\n" 10854 "}\n" 10855 "\n" 10856 "uniform testSubroutineType subroutineFunction;\n" 10857 "\n" 10858 "void main()\n" 10859 "{\n" 10860 " vec4 test = vec4(2, 3, 4, 5);\n" 10861 "\n" 10862 " subroutineFunction(test);\n" 10863 "\n" 10864 " gl_Position = test;\n" 10865 " EmitVertex();\n" 10866 "}\n"; 10867 } 10868 10869 /** Retrieves body of a broken tessellation control shader. 10870 * 10871 * @return Requested string. 10872 **/ 10873 std::string NegativeTest3::getTessellationControlShaderBody() const 10874 { 10875 return "#version 400\n" 10876 "\n" 10877 "#extension GL_ARB_shader_subroutine : require\n" 10878 "\n" 10879 "layout(vertices=4) out;\n" 10880 "\n" 10881 "subroutine void testSubroutineType(inout vec4 test);\n" 10882 "\n" 10883 "void testSubroutine1(inout vec4 test)\n" 10884 "{\n" 10885 " test += vec4(1, 2, 3, 4);\n" 10886 "}\n" 10887 "\n" 10888 "uniform testSubroutineType subroutineFunction;\n" 10889 "\n" 10890 "void main()\n" 10891 "{\n" 10892 " vec4 test = vec4(0, 1, 2, 3);\n" 10893 "\n" 10894 " subroutineFunction(test);\n" 10895 "\n" 10896 " gl_out[gl_InvocationID].gl_Position = test;\n" 10897 "}\n"; 10898 } 10899 10900 /** Retrieves body of a broken tessellation evaluation shader. 10901 * 10902 * @return Requested string. 10903 **/ 10904 std::string NegativeTest3::getTessellationEvaluationShaderBody() const 10905 { 10906 return "#version 400\n" 10907 "\n" 10908 "#extension GL_ARB_shader_subroutine : require\n" 10909 "\n" 10910 "layout(quads) in;\n" 10911 "\n" 10912 "subroutine void testSubroutineType(inout vec4 test);\n" 10913 "\n" 10914 "void testSubroutine1(inout vec4 test)\n" 10915 "{\n" 10916 " test += vec4(2, 3, 4, 5);\n" 10917 "}\n" 10918 "\n" 10919 "uniform testSubroutineType subroutineFunction;\n" 10920 "\n" 10921 "void main()\n" 10922 "{\n" 10923 " vec4 test = vec4(1, 2, 3, 4);\n" 10924 "\n" 10925 " subroutineFunction(test);\n" 10926 "\n" 10927 " gl_Position = test;\n" 10928 "}\n"; 10929 } 10930 10931 /** Retrieves body of a broken vertex shader. 10932 * 10933 * @return Requested string. 10934 **/ 10935 std::string NegativeTest3::getVertexShaderBody() const 10936 { 10937 return "#version 400\n" 10938 "\n" 10939 "#extension GL_ARB_shader_subroutine : require\n" 10940 "\n" 10941 "subroutine void testSubroutineType(inout vec4 test);\n" 10942 "\n" 10943 "void testSubroutine1(inout vec4 test)\n" 10944 "{\n" 10945 " test += vec4(0, 1, 2, 3);\n" 10946 "}\n" 10947 "\n" 10948 "uniform testSubroutineType subroutineFunction;\n" 10949 "\n" 10950 "void main()\n" 10951 "{\n" 10952 " subroutineFunction(gl_Position);\n" 10953 "}\n"; 10954 } 10955 10956 /** Executes test iteration. 10957 * 10958 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10959 */ 10960 tcu::TestNode::IterateResult NegativeTest3::iterate() 10961 { 10962 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 10963 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 10964 { 10965 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 10966 } 10967 10968 /* Iterate over all shader stages */ 10969 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 10970 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 10971 { 10972 executeTest(static_cast<Utils::_shader_stage>(shader_stage)); 10973 } /* for (all shader stages) */ 10974 10975 /* Done */ 10976 if (m_has_test_passed) 10977 { 10978 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 10979 } 10980 else 10981 { 10982 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 10983 } 10984 10985 return STOP; 10986 } 10987 10988 /** Constructor. 10989 * 10990 * @param context Rendering context. 10991 * 10992 **/ 10993 NegativeTest4::NegativeTest4(deqp::Context& context) 10994 : TestCase(context, "subroutines_incompatible_with_subroutine_type", 10995 "Verifies that a compile-time error is generated when arguments and " 10996 "return type do not match beween the function and each associated " 10997 "subroutine type.") 10998 , m_has_test_passed(true) 10999 , m_so_id(0) 11000 { 11001 /* Left blank intentionally */ 11002 } 11003 11004 /** Deinitializes GL objects that may have been created during test 11005 * execution. 11006 **/ 11007 void NegativeTest4::deinit() 11008 { 11009 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11010 11011 if (m_so_id != 0) 11012 { 11013 gl.deleteShader(m_so_id); 11014 11015 m_so_id = 0; 11016 } 11017 } 11018 11019 /** Retrieves body of a shader of user-specified type that should be used 11020 * for a single test iteration. The shader will define user-specified number 11021 * of subroutine types, with the last type either defining an additional argument 11022 * or using a different return type. 11023 * A subroutine (claimed compatible with *all* subroutine types) will also be 11024 * defined in the shader. 11025 * 11026 * @param shader_stage Shader stage to use for the query. 11027 * @param n_subroutine_types Overall number of subroutine types that will be 11028 * declared & used in the shader. Please see description 11029 * for more details. 11030 * 11031 * @return Requested string. 11032 **/ 11033 std::string NegativeTest4::getShaderBody(const Utils::_shader_stage& shader_stage, 11034 const unsigned int& n_subroutine_types, const _test_case& test_case) const 11035 { 11036 std::stringstream result_sstream; 11037 11038 /* Form the pre-amble */ 11039 result_sstream << "#version 400\n" 11040 "\n" 11041 "#extension GL_ARB_shader_subroutine : require\n" 11042 "\n"; 11043 11044 /* Inject stage-specific code */ 11045 switch (shader_stage) 11046 { 11047 case Utils::SHADER_STAGE_GEOMETRY: 11048 { 11049 result_sstream << "layout (points) in;\n" 11050 "layout (points, max_vertices = 1) out;\n" 11051 "\n"; 11052 11053 break; 11054 } 11055 11056 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 11057 { 11058 result_sstream << "layout (vertices = 4) out;\n" 11059 "\n"; 11060 11061 break; 11062 } 11063 11064 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 11065 { 11066 result_sstream << "layout (quads) in;\n" 11067 "\n"; 11068 11069 break; 11070 } 11071 11072 default: 11073 break; 11074 } /* switch (shader_stage) */ 11075 11076 /* Insert subroutine type declarations */ 11077 for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types - 1; ++n_subroutine_type) 11078 { 11079 result_sstream << "subroutine void subroutineType" << n_subroutine_type << "(inout vec3 argument);\n"; 11080 } /* for (all subroutine types) */ 11081 11082 switch (test_case) 11083 { 11084 case TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST: 11085 { 11086 result_sstream << "subroutine void subroutineType" << (n_subroutine_types - 1) 11087 << "(inout vec3 argument, out vec4 argument2);\n"; 11088 11089 break; 11090 } 11091 11092 case TEST_CASE_INCOMPATIBLE_RETURN_TYPE: 11093 { 11094 result_sstream << "subroutine int subroutineType" << (n_subroutine_types - 1) << "(inout vec3 argument);\n"; 11095 11096 break; 11097 } 11098 11099 default: 11100 { 11101 TCU_FAIL("Unrecognized test case"); 11102 } 11103 } /* switch (test_case) */ 11104 11105 /* Insert subroutine declarations */ 11106 result_sstream << "subroutine("; 11107 11108 for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types; ++n_subroutine_type) 11109 { 11110 result_sstream << "subroutineType" << n_subroutine_type; 11111 11112 if (n_subroutine_type != (n_subroutine_types - 1)) 11113 { 11114 result_sstream << ", "; 11115 } 11116 } /* for (all subroutine types) */ 11117 11118 result_sstream << ") void function(inout vec3 argument)\n" 11119 "{\n" 11120 " argument = vec3(1, 2, 3);\n" 11121 "}\n" 11122 "\n"; 11123 11124 /* Insert remaining required stage-specific bits */ 11125 switch (shader_stage) 11126 { 11127 case Utils::SHADER_STAGE_FRAGMENT: 11128 { 11129 result_sstream << "out vec4 result;\n" 11130 "\n" 11131 "void main()\n" 11132 "{\n" 11133 " result = vec4(1, 2, 3, 4);\n" 11134 "}\n"; 11135 11136 break; 11137 } 11138 11139 case Utils::SHADER_STAGE_GEOMETRY: 11140 { 11141 result_sstream << "void main()\n" 11142 "{\n" 11143 " gl_Position = vec4(1, 2, 3, 4);\n" 11144 " EmitVertex();\n" 11145 "}\n"; 11146 11147 break; 11148 } 11149 11150 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 11151 { 11152 result_sstream << "void main()\n" 11153 "{\n" 11154 " gl_TessLevelInner[0] = 1;\n" 11155 " gl_TessLevelInner[1] = 1;\n" 11156 " gl_TessLevelOuter[0] = 1;\n" 11157 " gl_TessLevelOuter[1] = 1;\n" 11158 " gl_TessLevelOuter[2] = 1;\n" 11159 " gl_TessLevelOuter[3] = 1;\n" 11160 " gl_out[gl_InvocationID].gl_Position = vec4(2, 3, 4, 5);\n" 11161 "}\n"; 11162 11163 break; 11164 } 11165 11166 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 11167 case Utils::SHADER_STAGE_VERTEX: 11168 { 11169 result_sstream << "void main()\n" 11170 "{\n" 11171 " gl_Position = vec4(1, 2, 3, 4);\n" 11172 "}\n"; 11173 11174 break; 11175 } 11176 11177 default: 11178 { 11179 TCU_FAIL("Unrecognized shader stage"); 11180 } 11181 } /* switch (shader_stage) */ 11182 11183 return result_sstream.str(); 11184 } 11185 11186 /** Executes test iteration. 11187 * 11188 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 11189 */ 11190 tcu::TestNode::IterateResult NegativeTest4::iterate() 11191 { 11192 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11193 11194 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 11195 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 11196 { 11197 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 11198 } 11199 11200 /* Iterate over all shader stages.. */ 11201 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 11202 shader_stage != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 11203 { 11204 /* For each shader stage, we will be trying to compile a number of invalid shaders. 11205 * Each shader defines N different subroutine types. (N-1) of them are compatible 11206 * with a subroutine, but exactly 1 will be mismatched. The test passes if GLSL 11207 * compiler correctly detects that all shaders we will be trying to compile are 11208 * broken. 11209 */ 11210 const glw::GLenum shader_type = Utils::getGLenumForShaderStage(static_cast<Utils::_shader_stage>(shader_stage)); 11211 11212 for (unsigned int n_subroutine_types = 1; n_subroutine_types < 6; /* arbitrary number */ 11213 ++n_subroutine_types) 11214 { 11215 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); 11216 ++test_case) 11217 { 11218 std::string body; 11219 const char* body_raw_ptr = NULL; 11220 glw::GLint compile_status = GL_FALSE; 11221 11222 body = getShaderBody(static_cast<Utils::_shader_stage>(shader_stage), n_subroutine_types, 11223 static_cast<_test_case>(test_case)); 11224 body_raw_ptr = body.c_str(); 11225 11226 /* Try to compile the shader */ 11227 m_so_id = gl.createShader(shader_type); 11228 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed"); 11229 11230 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL); 11231 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 11232 11233 gl.compileShader(m_so_id); 11234 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 11235 11236 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status); 11237 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 11238 11239 if (compile_status == GL_TRUE) 11240 { 11241 m_testCtx.getLog() << tcu::TestLog::Message << "A malformed " 11242 << Utils::getShaderStageString(static_cast<Utils::_shader_stage>(shader_stage)) 11243 << " compiled successfully " 11244 "(" 11245 << n_subroutine_types << " subroutine types " 11246 "were defined)." 11247 << tcu::TestLog::EndMessage; 11248 11249 m_has_test_passed = false; 11250 } 11251 11252 /* Release the object */ 11253 gl.deleteShader(m_so_id); 11254 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed."); 11255 } /* for (all test cases) */ 11256 } /* for (a number of different subroutine type declarations) */ 11257 } /* for (all shader stages) */ 11258 11259 /* Done */ 11260 if (m_has_test_passed) 11261 { 11262 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11263 } 11264 else 11265 { 11266 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11267 } 11268 11269 return STOP; 11270 } 11271 11272 /** Constructor. 11273 * 11274 * @param context Rendering context. 11275 * 11276 **/ 11277 NegativeTest5::NegativeTest5(deqp::Context& context) 11278 : TestCase(context, "subroutine_uniform_wo_matching_subroutines", 11279 "Verifies that a link- or compile-time error occurs when " 11280 "trying to link a program with no subroutine for subroutine " 11281 "uniform variable.") 11282 , m_fs_id(0) 11283 , m_gs_id(0) 11284 , m_has_test_passed(true) 11285 , m_po_id(0) 11286 , m_tc_id(0) 11287 , m_te_id(0) 11288 , m_vs_id(0) 11289 { 11290 /* Left blank intentionally */ 11291 } 11292 11293 /** Deinitializes all GL objects that may have been created during test execution */ 11294 void NegativeTest5::deinit() 11295 { 11296 deinitIteration(); 11297 } 11298 11299 /** Deinitializes all GL objects that may have been created during a single test 11300 * iteration. 11301 ***/ 11302 void NegativeTest5::deinitIteration() 11303 { 11304 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11305 11306 if (m_fs_id != 0) 11307 { 11308 gl.deleteShader(m_fs_id); 11309 11310 m_fs_id = 0; 11311 } 11312 11313 if (m_gs_id != 0) 11314 { 11315 gl.deleteShader(m_gs_id); 11316 11317 m_gs_id = 0; 11318 } 11319 11320 if (m_po_id != 0) 11321 { 11322 gl.deleteProgram(m_po_id); 11323 11324 m_po_id = 0; 11325 } 11326 11327 if (m_tc_id != 0) 11328 { 11329 gl.deleteShader(m_tc_id); 11330 11331 m_tc_id = 0; 11332 } 11333 11334 if (m_te_id != 0) 11335 { 11336 gl.deleteShader(m_te_id); 11337 11338 m_te_id = 0; 11339 } 11340 11341 if (m_vs_id != 0) 11342 { 11343 gl.deleteShader(m_vs_id); 11344 11345 m_vs_id = 0; 11346 } 11347 } 11348 11349 /** Executes a single test iteration. 11350 * 11351 * If the iteration fails, m_has_test_passed will be set to false. 11352 * 11353 * @param shader_stage Shader stage, for which a subroutine uniform should be 11354 * declared in the shader without a matching subroutine. 11355 **/ 11356 void NegativeTest5::executeIteration(const Utils::_shader_stage& shader_stage) 11357 { 11358 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 11359 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 11360 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 11361 std::string te_body = 11362 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 11363 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 11364 11365 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 11366 DE_NULL, /* xfb_varyings */ 11367 DE_NULL, /* n_xfb_varyings */ 11368 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 11369 { 11370 /* None of the test programs should ever build successfully */ 11371 m_testCtx.getLog() << tcu::TestLog::Message 11372 << "A program object, consisting of the following shaders, has linked" 11373 " correctly. One of the shaders defines a subroutine uniform but does " 11374 "not implement any function that matches subroutine type of the uniform." 11375 " This should have resulted in a compilation/link-time error.\n" 11376 "\n" 11377 "Vertex shader:\n" 11378 "\n" 11379 << vs_body << "\n" 11380 "Tessellation control shader:\n" 11381 "\n" 11382 << tc_body << "\n" 11383 "Tessellation evaluation shader:\n" 11384 "\n" 11385 << te_body << "\n" 11386 "Geometry shader:\n" 11387 "\n" 11388 << gs_body << "\n" 11389 "Fragment shader:\n" 11390 "\n" 11391 << fs_body << tcu::TestLog::EndMessage; 11392 11393 m_has_test_passed = false; 11394 } 11395 } 11396 11397 /** Retrieves fragment shader body. 11398 * 11399 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11400 * a subroutine uniform without 11401 * a matching subroutine, false otherwise. 11402 * 11403 * @return Requested string. 11404 **/ 11405 std::string NegativeTest5::getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const 11406 { 11407 std::stringstream result_sstream; 11408 11409 result_sstream << "#version 400\n" 11410 "\n" 11411 "#extension GL_ARB_shader_subroutine : require\n" 11412 "\n"; 11413 11414 if (include_invalid_subroutine_uniform_declaration) 11415 { 11416 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 11417 "\n" 11418 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 11419 }; 11420 11421 result_sstream << "\n" 11422 "out vec4 result;\n" 11423 "\n" 11424 "void main()\n" 11425 "{\n"; 11426 11427 if (include_invalid_subroutine_uniform_declaration) 11428 { 11429 result_sstream << " test_subroutineFS(result);\n"; 11430 } 11431 else 11432 { 11433 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 11434 } 11435 11436 result_sstream << "}\n"; 11437 11438 return result_sstream.str(); 11439 } 11440 11441 /** Retrieves geometry shader body. 11442 * 11443 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11444 * a subroutine uniform without 11445 * a matching subroutine, false otherwise. 11446 * 11447 * @return Requested string. 11448 **/ 11449 std::string NegativeTest5::getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const 11450 { 11451 std::stringstream result_sstream; 11452 11453 result_sstream << "#version 400\n" 11454 "\n" 11455 "#extension GL_ARB_shader_subroutine : require\n" 11456 "\n" 11457 "layout (points) in;\n" 11458 "layout (points, max_vertices = 1) out;\n" 11459 "\n"; 11460 11461 if (include_invalid_subroutine_uniform_declaration) 11462 { 11463 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 11464 "\n" 11465 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 11466 }; 11467 11468 result_sstream << "\n" 11469 "void main()\n" 11470 "{\n"; 11471 11472 if (include_invalid_subroutine_uniform_declaration) 11473 { 11474 result_sstream << " test_subroutineGS(gl_Position);\n"; 11475 } 11476 else 11477 { 11478 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11479 } 11480 11481 result_sstream << "EmitVertex();\n" 11482 "}\n"; 11483 11484 return result_sstream.str(); 11485 } 11486 11487 /** Retrieves tessellation control shader body. 11488 * 11489 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11490 * a subroutine uniform without 11491 * a matching subroutine, false otherwise. 11492 * 11493 * @return Requested string. 11494 **/ 11495 std::string NegativeTest5::getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const 11496 { 11497 std::stringstream result_sstream; 11498 11499 result_sstream << "#version 400\n" 11500 "\n" 11501 "#extension GL_ARB_shader_subroutine : require\n" 11502 "\n" 11503 "layout (vertices = 4) out;\n" 11504 "\n"; 11505 11506 if (include_invalid_subroutine_uniform_declaration) 11507 { 11508 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 11509 "\n" 11510 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 11511 }; 11512 11513 result_sstream << "\n" 11514 "void main()\n" 11515 "{\n"; 11516 11517 if (include_invalid_subroutine_uniform_declaration) 11518 { 11519 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 11520 } 11521 else 11522 { 11523 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 11524 } 11525 11526 result_sstream << "}\n"; 11527 11528 return result_sstream.str(); 11529 } 11530 11531 /** Retrieves tessellation evaluation body. 11532 * 11533 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11534 * a subroutine uniform without 11535 * a matching subroutine, false otherwise. 11536 * 11537 * @return Requested string. 11538 **/ 11539 std::string NegativeTest5::getTessellationEvaluationShaderBody( 11540 bool include_invalid_subroutine_uniform_declaration) const 11541 { 11542 std::stringstream result_sstream; 11543 11544 result_sstream << "#version 400\n" 11545 "\n" 11546 "#extension GL_ARB_shader_subroutine : require\n" 11547 "\n" 11548 "layout (quads) in;\n" 11549 "\n"; 11550 11551 if (include_invalid_subroutine_uniform_declaration) 11552 { 11553 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 11554 "\n" 11555 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 11556 }; 11557 11558 result_sstream << "\n" 11559 "void main()\n" 11560 "{\n"; 11561 11562 if (include_invalid_subroutine_uniform_declaration) 11563 { 11564 result_sstream << " test_subroutineTE(gl_Position);\n"; 11565 } 11566 else 11567 { 11568 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11569 } 11570 11571 result_sstream << "}\n"; 11572 11573 return result_sstream.str(); 11574 } 11575 11576 /** Retrieves vertex shader body. 11577 * 11578 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11579 * a subroutine uniform without 11580 * a matching subroutine, false otherwise. 11581 * 11582 * @return Requested string. 11583 **/ 11584 std::string NegativeTest5::getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const 11585 { 11586 std::stringstream result_sstream; 11587 11588 result_sstream << "#version 400\n" 11589 "\n" 11590 "#extension GL_ARB_shader_subroutine : require\n" 11591 "\n"; 11592 11593 if (include_invalid_subroutine_uniform_declaration) 11594 { 11595 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 11596 "\n" 11597 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 11598 }; 11599 11600 result_sstream << "\n" 11601 "void main()\n" 11602 "{\n"; 11603 11604 if (include_invalid_subroutine_uniform_declaration) 11605 { 11606 result_sstream << " test_subroutineVS(gl_Position);\n"; 11607 } 11608 else 11609 { 11610 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11611 } 11612 11613 result_sstream << "}\n"; 11614 11615 return result_sstream.str(); 11616 } 11617 11618 /** Executes test iteration. 11619 * 11620 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 11621 */ 11622 tcu::TestNode::IterateResult NegativeTest5::iterate() 11623 { 11624 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 11625 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 11626 { 11627 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 11628 } 11629 11630 /* Iterate over all shader stages. Iteration-specific shader stage defines a subroutine type & 11631 * a corresponding subroutine uniform, for which no compatible subroutines are available. All 11632 * other shader stages are defined correctly. 11633 */ 11634 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 11635 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 11636 { 11637 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 11638 deinitIteration(); 11639 } /* for (all shader stages) */ 11640 11641 /* All done */ 11642 if (m_has_test_passed) 11643 { 11644 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11645 } 11646 else 11647 { 11648 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11649 } 11650 11651 return STOP; 11652 } 11653 11654 /** Constructor. 11655 * 11656 * @param context Rendering context. 11657 * 11658 **/ 11659 NegativeTest6::NegativeTest6(deqp::Context& context) 11660 : TestCase(context, "two_duplicate_functions_one_being_a_subroutine", 11661 "Verifies that a link- or compile-time error occurs if any shader in " 11662 "a program object includes two functions with the same name and one " 11663 "of which is associated with a subroutine type.") 11664 , m_fs_id(0) 11665 , m_gs_id(0) 11666 , m_has_test_passed(true) 11667 , m_po_id(0) 11668 , m_tc_id(0) 11669 , m_te_id(0) 11670 , m_vs_id(0) 11671 { 11672 /* Left blank intentionally */ 11673 } 11674 11675 /** Deinitializes all GL objects that may have been created during test execution */ 11676 void NegativeTest6::deinit() 11677 { 11678 deinitIteration(); 11679 } 11680 11681 /** Deinitializes all GL objects that may have been created during a single test 11682 * iteration. 11683 ***/ 11684 void NegativeTest6::deinitIteration() 11685 { 11686 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11687 11688 if (m_fs_id != 0) 11689 { 11690 gl.deleteShader(m_fs_id); 11691 11692 m_fs_id = 0; 11693 } 11694 11695 if (m_gs_id != 0) 11696 { 11697 gl.deleteShader(m_gs_id); 11698 11699 m_gs_id = 0; 11700 } 11701 11702 if (m_po_id != 0) 11703 { 11704 gl.deleteProgram(m_po_id); 11705 11706 m_po_id = 0; 11707 } 11708 11709 if (m_tc_id != 0) 11710 { 11711 gl.deleteShader(m_tc_id); 11712 11713 m_tc_id = 0; 11714 } 11715 11716 if (m_te_id != 0) 11717 { 11718 gl.deleteShader(m_te_id); 11719 11720 m_te_id = 0; 11721 } 11722 11723 if (m_vs_id != 0) 11724 { 11725 gl.deleteShader(m_vs_id); 11726 11727 m_vs_id = 0; 11728 } 11729 } 11730 11731 /** Executes a single test iteration. 11732 * 11733 * If the iteration fails, m_has_test_passed will be set to false. 11734 * 11735 * @param shader_stage Shader stage, for which two duplicate functions 11736 * (one additionally marked as subroutine) should 11737 * be defined. 11738 **/ 11739 void NegativeTest6::executeIteration(const Utils::_shader_stage& shader_stage) 11740 { 11741 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 11742 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 11743 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 11744 std::string te_body = 11745 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 11746 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 11747 11748 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 11749 DE_NULL, /* xfb_varyings */ 11750 DE_NULL, /* n_xfb_varyings */ 11751 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 11752 { 11753 /* None of the test programs should ever build successfully */ 11754 m_testCtx.getLog() << tcu::TestLog::Message 11755 << "A program object, consisting of the following shaders, has linked" 11756 " correctly. This is invalid, because one of the shaders defines two" 11757 " functions with the same name, with an exception that one of the" 11758 " functions is marked as a subroutine.\n" 11759 "\n" 11760 "Vertex shader:\n" 11761 "\n" 11762 << vs_body << "\n" 11763 "Tessellation control shader:\n" 11764 "\n" 11765 << tc_body << "\n" 11766 "Tessellation evaluation shader:\n" 11767 "\n" 11768 << te_body << "\n" 11769 "Geometry shader:\n" 11770 "\n" 11771 << gs_body << "\n" 11772 "Fragment shader:\n" 11773 "\n" 11774 << fs_body << tcu::TestLog::EndMessage; 11775 11776 m_has_test_passed = false; 11777 } 11778 } 11779 11780 /** Retrieves fragment shader body. 11781 * 11782 * @param include_invalid_declaration true if the shader should include duplicate function 11783 * declaration. 11784 * 11785 * @return Requested string. 11786 **/ 11787 std::string NegativeTest6::getFragmentShaderBody(bool include_invalid_declaration) const 11788 { 11789 std::stringstream result_sstream; 11790 11791 result_sstream << "#version 400\n" 11792 "\n" 11793 "#extension GL_ARB_shader_subroutine : require\n" 11794 "\n"; 11795 11796 if (include_invalid_declaration) 11797 { 11798 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 11799 "\n" 11800 "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test)\n" 11801 "{\n" 11802 " test = vec4(1, 2, 3, 4);\n" 11803 "}\n" 11804 "\n" 11805 "void test_impl1(out vec4 test)\n" 11806 "{\n" 11807 " test = vec4(2, 3, 4, 5);\n" 11808 "}\n" 11809 "\n" 11810 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 11811 }; 11812 11813 result_sstream << "\n" 11814 "out vec4 result;\n" 11815 "\n" 11816 "void main()\n" 11817 "{\n"; 11818 11819 if (include_invalid_declaration) 11820 { 11821 result_sstream << " test_subroutineFS(result);\n"; 11822 } 11823 else 11824 { 11825 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 11826 } 11827 11828 result_sstream << "}\n"; 11829 11830 return result_sstream.str(); 11831 } 11832 11833 /** Retrieves geometry shader body. 11834 * 11835 * @param include_invalid_declaration true if the shader should include duplicate function 11836 * declaration. 11837 * 11838 * @return Requested string. 11839 **/ 11840 std::string NegativeTest6::getGeometryShaderBody(bool include_invalid_declaration) const 11841 { 11842 std::stringstream result_sstream; 11843 11844 result_sstream << "#version 400\n" 11845 "\n" 11846 "#extension GL_ARB_shader_subroutine : require\n" 11847 "\n" 11848 "layout (points) in;\n" 11849 "layout (points, max_vertices = 1) out;\n" 11850 "\n"; 11851 11852 if (include_invalid_declaration) 11853 { 11854 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 11855 "\n" 11856 "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test)\n" 11857 "{\n" 11858 " test = vec4(1, 2, 3, 4);\n" 11859 "}\n" 11860 "\n" 11861 "void test_impl1(out vec4 test)\n" 11862 "{\n" 11863 " test = vec4(2, 3, 4, 5);\n" 11864 "}\n" 11865 "\n" 11866 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 11867 }; 11868 11869 result_sstream << "\n" 11870 "void main()\n" 11871 "{\n"; 11872 11873 if (include_invalid_declaration) 11874 { 11875 result_sstream << " test_subroutineGS(gl_Position);\n"; 11876 } 11877 else 11878 { 11879 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11880 } 11881 11882 result_sstream << "EmitVertex();\n" 11883 "}\n"; 11884 11885 return result_sstream.str(); 11886 } 11887 11888 /** Retrieves tessellation control shader body. 11889 * 11890 * @param include_invalid_declaration true if the shader should include duplicate function 11891 * declaration. 11892 * 11893 * @return Requested string. 11894 **/ 11895 std::string NegativeTest6::getTessellationControlShaderBody(bool include_invalid_declaration) const 11896 { 11897 std::stringstream result_sstream; 11898 11899 result_sstream << "#version 400\n" 11900 "\n" 11901 "#extension GL_ARB_shader_subroutine : require\n" 11902 "\n" 11903 "layout (vertices = 4) out;\n" 11904 "\n"; 11905 11906 if (include_invalid_declaration) 11907 { 11908 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 11909 "\n" 11910 "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test)\n" 11911 "{\n" 11912 " test = vec4(1, 2, 3, 4);\n" 11913 "}\n" 11914 "\n" 11915 "void test_impl1(out vec4 test)\n" 11916 "{\n" 11917 " test = vec4(2, 3, 4, 5);\n" 11918 "}\n" 11919 "\n" 11920 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 11921 }; 11922 11923 result_sstream << "\n" 11924 "void main()\n" 11925 "{\n"; 11926 11927 if (include_invalid_declaration) 11928 { 11929 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 11930 } 11931 else 11932 { 11933 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 11934 } 11935 11936 result_sstream << "}\n"; 11937 11938 return result_sstream.str(); 11939 } 11940 11941 /** Retrieves tessellation evaluation body. 11942 * 11943 * @param include_invalid_declaration true if the shader should include duplicate function 11944 * declaration. 11945 * 11946 * @return Requested string. 11947 **/ 11948 std::string NegativeTest6::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const 11949 { 11950 std::stringstream result_sstream; 11951 11952 result_sstream << "#version 400\n" 11953 "\n" 11954 "#extension GL_ARB_shader_subroutine : require\n" 11955 "\n" 11956 "layout (quads) in;\n" 11957 "\n"; 11958 11959 if (include_invalid_declaration) 11960 { 11961 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 11962 "\n" 11963 "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test)\n" 11964 "{\n" 11965 " test = vec4(1, 2, 3, 4);\n" 11966 "}\n" 11967 "\n" 11968 "void test_impl1(out vec4 test)\n" 11969 "{\n" 11970 " test = vec4(2, 3, 4, 5);\n" 11971 "}\n" 11972 "\n" 11973 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 11974 }; 11975 11976 result_sstream << "\n" 11977 "void main()\n" 11978 "{\n"; 11979 11980 if (include_invalid_declaration) 11981 { 11982 result_sstream << " test_subroutineTE(gl_Position);\n"; 11983 } 11984 else 11985 { 11986 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11987 } 11988 11989 result_sstream << "}\n"; 11990 11991 return result_sstream.str(); 11992 } 11993 11994 /** Retrieves vertex shader body. 11995 * 11996 * @param include_invalid_declaration true if the shader should include duplicate function 11997 * declaration. 11998 * 11999 * @return Requested string. 12000 **/ 12001 std::string NegativeTest6::getVertexShaderBody(bool include_invalid_declaration) const 12002 { 12003 std::stringstream result_sstream; 12004 12005 result_sstream << "#version 400\n" 12006 "\n" 12007 "#extension GL_ARB_shader_subroutine : require\n" 12008 "\n"; 12009 12010 if (include_invalid_declaration) 12011 { 12012 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 12013 "\n" 12014 "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test)\n" 12015 "{\n" 12016 " test = vec4(1, 2, 3, 4);\n" 12017 "}\n" 12018 "\n" 12019 "void test_impl1(out vec4 test)\n" 12020 "{\n" 12021 " test = vec4(2, 3, 4, 5);\n" 12022 "}\n" 12023 "\n" 12024 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 12025 }; 12026 12027 result_sstream << "\n" 12028 "void main()\n" 12029 "{\n"; 12030 12031 if (include_invalid_declaration) 12032 { 12033 result_sstream << " test_subroutineVS(gl_Position);\n"; 12034 } 12035 else 12036 { 12037 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12038 } 12039 12040 result_sstream << "}\n"; 12041 12042 return result_sstream.str(); 12043 } 12044 12045 /** Executes test iteration. 12046 * 12047 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12048 */ 12049 tcu::TestNode::IterateResult NegativeTest6::iterate() 12050 { 12051 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 12052 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 12053 { 12054 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 12055 } 12056 12057 /* Iterate over all shader stages. In each iteration, we will inject invalid 12058 * duplicate function declarations to iteration-specific shader stage. All other 12059 * shader stages will be assigned valid bodies. Test should fail if the program 12060 * links successfully. 12061 */ 12062 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 12063 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 12064 { 12065 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 12066 deinitIteration(); 12067 } /* for (all shader stages) */ 12068 12069 /* All done */ 12070 if (m_has_test_passed) 12071 { 12072 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12073 } 12074 else 12075 { 12076 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12077 } 12078 12079 return STOP; 12080 } 12081 12082 /** Constructor 12083 * 12084 * @param context CTS context 12085 **/ 12086 NegativeTest7::NegativeTest7(deqp::Context& context) 12087 : TestCase(context, "recursion", "Verify that it is not possible to build program with recursing subroutines") 12088 , m_program_id(0) 12089 , m_vertex_shader_id(0) 12090 { 12091 /* Nothing to be done here */ 12092 } 12093 12094 /** Deinitializes all GL objects that may have been created during test execution 12095 * 12096 **/ 12097 void NegativeTest7::deinit() 12098 { 12099 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12100 12101 if (m_program_id != 0) 12102 { 12103 gl.deleteProgram(m_program_id); 12104 12105 m_program_id = 0; 12106 } 12107 12108 if (m_vertex_shader_id != 0) 12109 { 12110 gl.deleteShader(m_vertex_shader_id); 12111 12112 m_vertex_shader_id = 0; 12113 } 12114 } 12115 12116 /** Executes test iteration. 12117 * 12118 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12119 **/ 12120 tcu::TestNode::IterateResult NegativeTest7::iterate() 12121 { 12122 static const GLchar* vertex_shader_with_static_recursion = 12123 "#version 400\n" 12124 "\n" 12125 "#extension GL_ARB_shader_subroutine : require\n" 12126 "\n" 12127 "precision highp float;\n" 12128 "\n" 12129 "subroutine vec4 routine_type(in vec4 data, in uint control);\n" 12130 "\n" 12131 "subroutine (routine_type) vec4 power_routine(in vec4 data, in uint control)\n" 12132 "{\n" 12133 " if (0 != control)\n" 12134 " {\n" 12135 " return data * power_routine(data, control - 1);\n" 12136 " }\n" 12137 " else\n" 12138 " {\n" 12139 " return vec4(1, 1, 1, 1);\n" 12140 " }\n" 12141 "}\n" 12142 "\n" 12143 "subroutine (routine_type) vec4 select_routine(in vec4 data, in uint control)\n" 12144 "{\n" 12145 " if (0 == control)\n" 12146 " {\n" 12147 " return data.rrrr;\n" 12148 " }\n" 12149 " else if (1 == control)\n" 12150 " {\n" 12151 " return data.gggg;\n" 12152 " }\n" 12153 " else if (2 == control)\n" 12154 " {\n" 12155 " return data.bbbb;\n" 12156 " }\n" 12157 " else\n" 12158 " {\n" 12159 " return data.aaaa;\n" 12160 " }\n" 12161 "}\n" 12162 "\n" 12163 "subroutine uniform routine_type routine;\n" 12164 "\n" 12165 "uniform vec4 uni_value;\n" 12166 "uniform uint uni_control;\n" 12167 "\n" 12168 "out vec4 out_result;\n" 12169 "\n" 12170 "void main()\n" 12171 "{\n" 12172 " out_result = routine(uni_value, uni_control);\n" 12173 "}\n" 12174 "\n"; 12175 12176 static const GLchar* vertex_shader_with_dynamic_recursion = 12177 "#version 400\n" 12178 "\n" 12179 "#extension GL_ARB_shader_subroutine : require\n" 12180 "\n" 12181 "precision highp float;\n" 12182 "\n" 12183 "subroutine vec4 routine_type(in vec4 data);\n" 12184 "\n" 12185 "subroutine uniform routine_type routine;\n" 12186 "\n" 12187 "subroutine (routine_type) vec4 div_by_2(in vec4 data)\n" 12188 "{\n" 12189 " return data / 2;\n" 12190 "}\n" 12191 "\n" 12192 "subroutine (routine_type) vec4 div_routine_result_by_2(in vec4 data)\n" 12193 "{\n" 12194 " return routine(data) / 2;\n" 12195 "}\n" 12196 "\n" 12197 "uniform vec4 uni_value;\n" 12198 "\n" 12199 "out vec4 out_result;\n" 12200 "\n" 12201 "void main()\n" 12202 "{\n" 12203 " out_result = routine(uni_value);\n" 12204 "}\n" 12205 "\n"; 12206 12207 static const GLchar* vertex_shader_with_subroutine_function_recursion = 12208 "#version 400\n" 12209 "\n" 12210 "#extension GL_ARB_shader_subroutine : require\n" 12211 "\n" 12212 "precision highp float;\n" 12213 "\n" 12214 "subroutine vec4 routine_type(in vec4 data);\n" 12215 "\n" 12216 "subroutine uniform routine_type routine;\n" 12217 "\n" 12218 "vec4 function(in vec4 data)\n" 12219 "{\n" 12220 " return routine(data) + vec4(0.5, 0.5, 0.5, 0.5);\n" 12221 "}\n" 12222 "\n" 12223 "subroutine (routine_type) vec4 routine_a(in vec4 data)\n" 12224 "{\n" 12225 " return function(data) / 2;\n" 12226 "}\n" 12227 "\n" 12228 "subroutine (routine_type) vec4 routine_b(in vec4 data)\n" 12229 "{\n" 12230 " return routine_a(data) * 2;\n" 12231 "}\n" 12232 "\n" 12233 "uniform vec4 uni_value;\n" 12234 "\n" 12235 "out vec4 out_result;\n" 12236 "\n" 12237 "void main()\n" 12238 "{\n" 12239 " out_result = routine(uni_value);\n" 12240 "}\n" 12241 "\n"; 12242 12243 bool result = true; 12244 12245 if (false == test(vertex_shader_with_subroutine_function_recursion, "routine_a")) 12246 { 12247 result = false; 12248 } 12249 12250 if (false == test(vertex_shader_with_dynamic_recursion, "div_routine_result_by_2")) 12251 { 12252 result = false; 12253 } 12254 12255 if (false == test(vertex_shader_with_static_recursion, "power_routine")) 12256 { 12257 result = false; 12258 } 12259 12260 /* Set result */ 12261 if (true == result) 12262 { 12263 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12264 } 12265 else 12266 { 12267 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12268 } 12269 12270 /* Done */ 12271 return tcu::TestNode::STOP; 12272 } 12273 12274 /** Try to build program from vertex shader code. 12275 * 12276 * @param vertex_shader_code Source code of vertex shader 12277 * @param name_of_recursive_routine Name of subroutine that should cause link failure due to recursion 12278 * 12279 * @return true build process failed, false otherwise 12280 **/ 12281 bool NegativeTest7::test(const GLchar* vertex_shader_code, const GLchar* name_of_recursive_routine) 12282 { 12283 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12284 bool result = true; 12285 static const GLchar* varying_name = "out_result"; 12286 12287 /* Try to build program */ 12288 if (true == Utils::buildProgram(gl, vertex_shader_code, "", "", "", "", &varying_name /* varying_names */, 12289 1 /* n_varyings */, &m_vertex_shader_id, 0, 0, 0, 0, &m_program_id)) 12290 { 12291 /* Success is considered an error */ 12292 12293 Utils::program program(m_context); 12294 GLuint index = 0; 12295 12296 program.build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0); 12297 12298 /* Verify that recursive subroutine is active */ 12299 try 12300 { 12301 index = program.getSubroutineIndex(name_of_recursive_routine, GL_VERTEX_SHADER); 12302 } 12303 catch (const std::exception& exc) 12304 { 12305 /* Something wrong with shader or compilation */ 12306 m_context.getTestContext().getLog() 12307 << tcu::TestLog::Message << "It is expected that subroutine: \n" 12308 << name_of_recursive_routine 12309 << " is considered active. This subroutine is potentially recursive and should cause link failure." 12310 << tcu::TestLog::EndMessage; 12311 12312 throw exc; 12313 } 12314 12315 /* Subsoutine is active, however linking should fail */ 12316 m_context.getTestContext().getLog() 12317 << tcu::TestLog::Message << "Error. Program with potentially recursive subroutine, " 12318 << name_of_recursive_routine << ", which is active, index: " << index << ", has been built successfully.\n" 12319 << vertex_shader_code << tcu::TestLog::EndMessage; 12320 12321 result = false; 12322 } 12323 12324 /* Delete program and shader */ 12325 deinit(); 12326 12327 /* Done */ 12328 return result; 12329 } 12330 12331 /** Constructor. 12332 * 12333 * @param context Rendering context. 12334 * 12335 **/ 12336 NegativeTest8::NegativeTest8(deqp::Context& context) 12337 : TestCase(context, "subroutine_wo_body", "Verifies that a compile- or link-time error occurs if a function " 12338 "declared as a subroutine does not include a body.") 12339 , m_fs_id(0) 12340 , m_gs_id(0) 12341 , m_has_test_passed(true) 12342 , m_po_id(0) 12343 , m_tc_id(0) 12344 , m_te_id(0) 12345 , m_vs_id(0) 12346 { 12347 /* Left blank intentionally */ 12348 } 12349 12350 /** Deinitializes all GL objects that may have been created during test execution */ 12351 void NegativeTest8::deinit() 12352 { 12353 deinitIteration(); 12354 } 12355 12356 /** Deinitializes all GL objects that may have been created during a single test 12357 * iteration. 12358 ***/ 12359 void NegativeTest8::deinitIteration() 12360 { 12361 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12362 12363 if (m_fs_id != 0) 12364 { 12365 gl.deleteShader(m_fs_id); 12366 12367 m_fs_id = 0; 12368 } 12369 12370 if (m_gs_id != 0) 12371 { 12372 gl.deleteShader(m_gs_id); 12373 12374 m_gs_id = 0; 12375 } 12376 12377 if (m_po_id != 0) 12378 { 12379 gl.deleteProgram(m_po_id); 12380 12381 m_po_id = 0; 12382 } 12383 12384 if (m_tc_id != 0) 12385 { 12386 gl.deleteShader(m_tc_id); 12387 12388 m_tc_id = 0; 12389 } 12390 12391 if (m_te_id != 0) 12392 { 12393 gl.deleteShader(m_te_id); 12394 12395 m_te_id = 0; 12396 } 12397 12398 if (m_vs_id != 0) 12399 { 12400 gl.deleteShader(m_vs_id); 12401 12402 m_vs_id = 0; 12403 } 12404 } 12405 12406 /** Executes a single test iteration. 12407 * 12408 * If the iteration fails, m_has_test_passed will be set to false. 12409 * 12410 * @param shader_stage Shader stage, for which two duplicate functions 12411 * (one additionally marked as subroutine) should 12412 * be defined. 12413 **/ 12414 void NegativeTest8::executeIteration(const Utils::_shader_stage& shader_stage) 12415 { 12416 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 12417 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 12418 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 12419 std::string te_body = 12420 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 12421 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 12422 12423 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 12424 DE_NULL, /* xfb_varyings */ 12425 DE_NULL, /* n_xfb_varyings */ 12426 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 12427 { 12428 /* None of the test programs should ever build successfully */ 12429 m_testCtx.getLog() << tcu::TestLog::Message 12430 << "A program object consisting of FS+GS+TC+TE+VS stages has linked successfully, " 12431 "even though one of the shaders only defines a subroutine that lacks any body." 12432 "\n" 12433 "Vertex shader:\n" 12434 "\n" 12435 << vs_body << "\n" 12436 "Tessellation control shader:\n" 12437 "\n" 12438 << tc_body << "\n" 12439 "Tessellation evaluation shader:\n" 12440 "\n" 12441 << te_body << "\n" 12442 "Geometry shader:\n" 12443 "\n" 12444 << gs_body << "\n" 12445 "Fragment shader:\n" 12446 "\n" 12447 << fs_body << tcu::TestLog::EndMessage; 12448 12449 m_has_test_passed = false; 12450 } 12451 } 12452 12453 /** Retrieves fragment shader body. 12454 * 12455 * @param include_invalid_declaration true if a subroutine prototype should be included in 12456 * the shader, false to skip it. 12457 * 12458 * @return Requested string. 12459 **/ 12460 std::string NegativeTest8::getFragmentShaderBody(bool include_invalid_declaration) const 12461 { 12462 std::stringstream result_sstream; 12463 12464 result_sstream << "#version 400\n" 12465 "\n" 12466 "#extension GL_ARB_shader_subroutine : require\n" 12467 "\n"; 12468 12469 if (include_invalid_declaration) 12470 { 12471 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 12472 "\n" 12473 "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test);\n" 12474 "\n" 12475 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 12476 }; 12477 12478 result_sstream << "\n" 12479 "out vec4 result;\n" 12480 "\n" 12481 "void main()\n" 12482 "{\n"; 12483 12484 if (include_invalid_declaration) 12485 { 12486 result_sstream << " test_subroutineFS(result);\n"; 12487 } 12488 else 12489 { 12490 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 12491 } 12492 12493 result_sstream << "}\n"; 12494 12495 return result_sstream.str(); 12496 } 12497 12498 /** Retrieves geometry shader body. 12499 * 12500 * @param include_invalid_declaration true if a subroutine prototype should be included in 12501 * the shader, false to skip it. 12502 * 12503 * @return Requested string. 12504 **/ 12505 std::string NegativeTest8::getGeometryShaderBody(bool include_invalid_declaration) const 12506 { 12507 std::stringstream result_sstream; 12508 12509 result_sstream << "#version 400\n" 12510 "\n" 12511 "#extension GL_ARB_shader_subroutine : require\n" 12512 "\n" 12513 "layout (points) in;\n" 12514 "layout (points, max_vertices = 1) out;\n" 12515 "\n"; 12516 12517 if (include_invalid_declaration) 12518 { 12519 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 12520 "\n" 12521 "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test);\n" 12522 "\n" 12523 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 12524 }; 12525 12526 result_sstream << "\n" 12527 "void main()\n" 12528 "{\n"; 12529 12530 if (include_invalid_declaration) 12531 { 12532 result_sstream << " test_subroutineGS(gl_Position);\n"; 12533 } 12534 else 12535 { 12536 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12537 } 12538 12539 result_sstream << "EmitVertex();\n" 12540 "}\n"; 12541 12542 return result_sstream.str(); 12543 } 12544 12545 /** Retrieves tessellation control shader body. 12546 * 12547 * @param include_invalid_declaration true if a subroutine prototype should be included in 12548 * the shader, false to skip it. 12549 * 12550 * @return Requested string. 12551 **/ 12552 std::string NegativeTest8::getTessellationControlShaderBody(bool include_invalid_declaration) const 12553 { 12554 std::stringstream result_sstream; 12555 12556 result_sstream << "#version 400\n" 12557 "\n" 12558 "#extension GL_ARB_shader_subroutine : require\n" 12559 "\n" 12560 "layout (vertices = 4) out;\n" 12561 "\n"; 12562 12563 if (include_invalid_declaration) 12564 { 12565 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 12566 "\n" 12567 "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test);\n" 12568 "\n" 12569 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 12570 }; 12571 12572 result_sstream << "\n" 12573 "void main()\n" 12574 "{\n"; 12575 12576 if (include_invalid_declaration) 12577 { 12578 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 12579 } 12580 else 12581 { 12582 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 12583 } 12584 12585 result_sstream << "}\n"; 12586 12587 return result_sstream.str(); 12588 } 12589 12590 /** Retrieves tessellation evaluation body. 12591 * 12592 * @param include_invalid_declaration true if a subroutine prototype should be included in 12593 * the shader, false to skip it. 12594 * 12595 * @return Requested string. 12596 **/ 12597 std::string NegativeTest8::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const 12598 { 12599 std::stringstream result_sstream; 12600 12601 result_sstream << "#version 400\n" 12602 "\n" 12603 "#extension GL_ARB_shader_subroutine : require\n" 12604 "\n" 12605 "layout (quads) in;\n" 12606 "\n"; 12607 12608 if (include_invalid_declaration) 12609 { 12610 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 12611 "\n" 12612 "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test);\n" 12613 "\n" 12614 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 12615 }; 12616 12617 result_sstream << "\n" 12618 "void main()\n" 12619 "{\n"; 12620 12621 if (include_invalid_declaration) 12622 { 12623 result_sstream << " test_subroutineTE(gl_Position);\n"; 12624 } 12625 else 12626 { 12627 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12628 } 12629 12630 result_sstream << "}\n"; 12631 12632 return result_sstream.str(); 12633 } 12634 12635 /** Retrieves vertex shader body. 12636 * 12637 * @param include_invalid_declaration true if a subroutine prototype should be included in 12638 * the shader, false to skip it. 12639 * 12640 * @return Requested string. 12641 **/ 12642 std::string NegativeTest8::getVertexShaderBody(bool include_invalid_declaration) const 12643 { 12644 std::stringstream result_sstream; 12645 12646 result_sstream << "#version 400\n" 12647 "\n" 12648 "#extension GL_ARB_shader_subroutine : require\n" 12649 "\n"; 12650 12651 if (include_invalid_declaration) 12652 { 12653 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 12654 "\n" 12655 "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test);\n" 12656 "\n" 12657 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 12658 }; 12659 12660 result_sstream << "\n" 12661 "void main()\n" 12662 "{\n"; 12663 12664 if (include_invalid_declaration) 12665 { 12666 result_sstream << " test_subroutineVS(gl_Position);\n"; 12667 } 12668 else 12669 { 12670 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12671 } 12672 12673 result_sstream << "}\n"; 12674 12675 return result_sstream.str(); 12676 } 12677 12678 /** Executes test iteration. 12679 * 12680 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12681 */ 12682 tcu::TestNode::IterateResult NegativeTest8::iterate() 12683 { 12684 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 12685 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 12686 { 12687 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 12688 } 12689 12690 /* Iterate over all shader stages. For each iteration, iteration-specific shader stage 12691 * will feature an invalid subroutine definition. Other shader stages will be assigned 12692 * valid bodies. The test fails if a program built of such shaders links successfully. 12693 */ 12694 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 12695 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 12696 { 12697 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 12698 deinitIteration(); 12699 } /* for (all shader stages) */ 12700 12701 /* All done */ 12702 if (m_has_test_passed) 12703 { 12704 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12705 } 12706 else 12707 { 12708 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12709 } 12710 12711 return STOP; 12712 } 12713 12714 /** Constructor. 12715 * 12716 * @param context Rendering context. 12717 **/ 12718 NegativeTest9::NegativeTest9(deqp::Context& context) 12719 : TestCase(context, "subroutines_cannot_be_assigned_float_int_values_or_be_compared", 12720 "Make sure it is not possible to assign float/int to subroutine " 12721 "uniform and that subroutine uniform values cannot be compared.") 12722 , m_has_test_passed(true) 12723 , m_po_id(0) 12724 , m_vs_id(0) 12725 { 12726 /* Left blank intentionally */ 12727 } 12728 12729 /** Deinitializes any GL objects that may have been created during 12730 * test execution. 12731 **/ 12732 void NegativeTest9::deinit() 12733 { 12734 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12735 12736 if (m_po_id != 0) 12737 { 12738 gl.deleteProgram(m_po_id); 12739 12740 m_po_id = 0; 12741 } 12742 12743 if (m_vs_id != 0) 12744 { 12745 gl.deleteShader(m_vs_id); 12746 12747 m_vs_id = 0; 12748 } 12749 } 12750 12751 /** Returns a literal corresponding to user-specified test case enum. 12752 * 12753 * @param test_case As per description. 12754 * 12755 * @return Requested string. 12756 **/ 12757 std::string NegativeTest9::getTestCaseString(const _test_case& test_case) 12758 { 12759 std::string result = "?"; 12760 12761 switch (test_case) 12762 { 12763 case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 12764 result = "TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT"; 12765 break; 12766 case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 12767 result = "TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT"; 12768 break; 12769 case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON: 12770 result = "TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON"; 12771 break; 12772 default: 12773 break; 12774 } 12775 12776 return result; 12777 } 12778 12779 /** Retrieves vertex shader body for user-specified test case. 12780 * 12781 * @param test_case As per description. 12782 * 12783 * @return Requested string. 12784 **/ 12785 std::string NegativeTest9::getVertexShader(const _test_case& test_case) 12786 { 12787 std::stringstream result_sstream; 12788 12789 /* Form pre-amble */ 12790 result_sstream << "#version 400\n" 12791 "\n" 12792 "#extension GL_ARB_shader_subroutine : require\n" 12793 "\n" 12794 /* Define a subroutine */ 12795 "subroutine void subroutineType(inout vec4 test);\n" 12796 "\n" 12797 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 12798 "{\n" 12799 " test += vec4(0, 1, 2, 3);\n" 12800 "}\n" 12801 "\n" 12802 "subroutine uniform subroutineType function;\n" 12803 "\n"; 12804 12805 /* Include case-specific implementation */ 12806 switch (test_case) 12807 { 12808 case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 12809 { 12810 result_sstream << "void main()\n" 12811 "{\n" 12812 " function = 1.0f;\n" 12813 "\n" 12814 " function(gl_Position);\n" 12815 "}\n"; 12816 12817 break; 12818 } 12819 12820 case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 12821 { 12822 result_sstream << "void main()\n" 12823 "{\n" 12824 " function = 1;\n" 12825 "\n" 12826 " function(gl_Position);\n" 12827 "}\n"; 12828 12829 break; 12830 } 12831 12832 case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON: 12833 { 12834 result_sstream << "subroutine uniform subroutineType function2;\n" 12835 "\n" 12836 "void main()\n" 12837 "{\n" 12838 " if (function == function2)\n" 12839 " {\n" 12840 " function(gl_Position);\n" 12841 " }\n" 12842 " else\n" 12843 " {\n" 12844 " function2(gl_Position);\n" 12845 " }\n" 12846 "}\n"; 12847 12848 break; 12849 } 12850 12851 default: 12852 break; 12853 } /* switch (test_case) */ 12854 12855 /* Done */ 12856 return result_sstream.str(); 12857 } 12858 12859 /** Executes test iteration. 12860 * 12861 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12862 */ 12863 tcu::TestNode::IterateResult NegativeTest9::iterate() 12864 { 12865 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12866 12867 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 12868 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 12869 { 12870 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 12871 } 12872 12873 /* Iterate over all test cases */ 12874 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 12875 { 12876 /* Try to build a program object using invalid vertex shader, specific to the 12877 * iteration we're currently in */ 12878 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 12879 12880 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 12881 "", /* te_body */ 12882 "", /* gs_body */ 12883 "", /* fs_body */ 12884 DE_NULL, /* xfb_varyings */ 12885 0, /* n_xfb_varyings */ 12886 &m_vs_id, DE_NULL, /* out_tc_id */ 12887 DE_NULL, /* out_te_id */ 12888 DE_NULL, /* out_gs_id */ 12889 DE_NULL, /* out_fs_id */ 12890 &m_po_id)) 12891 { 12892 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 12893 << getTestCaseString(static_cast<_test_case>(test_case)) 12894 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 12895 12896 m_has_test_passed = false; 12897 } 12898 12899 /* Delete any objects that may have been created */ 12900 deinit(); 12901 } /* for (all test cases) */ 12902 12903 /** All done */ 12904 if (m_has_test_passed) 12905 { 12906 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12907 } 12908 else 12909 { 12910 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12911 } 12912 12913 return STOP; 12914 } 12915 12916 /** Constructor. 12917 * 12918 * @param context Rendering context. 12919 **/ 12920 NegativeTest10::NegativeTest10(deqp::Context& context) 12921 : TestCase(context, "function_overloading_forbidden_for_subroutines", 12922 "Check that an overloaded function cannot be declared with subroutine and " 12923 "a program will fail to compile or link if any shader or stage contains" 12924 " two or more functions with the same name if the name is associated with" 12925 " a subroutine type.") 12926 , m_has_test_passed(true) 12927 , m_fs_id(0) 12928 , m_gs_id(0) 12929 , m_po_id(0) 12930 , m_tc_id(0) 12931 , m_te_id(0) 12932 , m_vs_id(0) 12933 { 12934 /* Left blank intentionally */ 12935 } 12936 12937 /** Deinitializes any GL objects that may have been created during 12938 * test execution. 12939 **/ 12940 void NegativeTest10::deinit() 12941 { 12942 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12943 12944 if (m_fs_id != 0) 12945 { 12946 gl.deleteShader(m_fs_id); 12947 12948 m_fs_id = 0; 12949 } 12950 12951 if (m_gs_id != 0) 12952 { 12953 gl.deleteShader(m_gs_id); 12954 12955 m_gs_id = 0; 12956 } 12957 12958 if (m_po_id != 0) 12959 { 12960 gl.deleteProgram(m_po_id); 12961 12962 m_po_id = 0; 12963 } 12964 12965 if (m_tc_id != 0) 12966 { 12967 gl.deleteShader(m_tc_id); 12968 12969 m_tc_id = 0; 12970 } 12971 12972 if (m_te_id != 0) 12973 { 12974 gl.deleteShader(m_te_id); 12975 12976 m_te_id = 0; 12977 } 12978 12979 if (m_vs_id != 0) 12980 { 12981 gl.deleteShader(m_vs_id); 12982 12983 m_vs_id = 0; 12984 } 12985 } 12986 12987 /** Retrieves fragment shader that should be used for the purpose of the test. 12988 * An overloaded version of a subroutine function is inserted if 12989 * @param include_duplicate_function flag is set to true. 12990 * 12991 * @param include_duplicate_function As per description. 12992 * 12993 * @return Requested string. 12994 **/ 12995 std::string NegativeTest10::getFragmentShader(bool include_duplicate_function) 12996 { 12997 std::stringstream result_sstream; 12998 12999 result_sstream << "#version 400\n" 13000 "\n" 13001 "#extension GL_ARB_shader_subroutine : require\n" 13002 "\n" 13003 "subroutine void subroutineType(inout vec4 test);\n" 13004 "\n" 13005 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13006 "{\n" 13007 " test = vec4(2, 3, 4, 5);\n" 13008 "}\n" 13009 "\n" 13010 "subroutine uniform subroutineType function;\n" 13011 "out vec4 result;\n" 13012 "\n"; 13013 13014 if (include_duplicate_function) 13015 { 13016 result_sstream << "void test_function(inout vec4 test)\n" 13017 "{\n" 13018 " test = vec4(3, 4, 5, 6);\n" 13019 "}\n" 13020 "\n"; 13021 } 13022 13023 result_sstream << "void main()\n" 13024 "{\n" 13025 " test_function(result);\n" 13026 "}\n"; 13027 13028 return result_sstream.str(); 13029 } 13030 13031 /** Retrieves geometry shader that should be used for the purpose of the test. 13032 * An overloaded version of a subroutine function is inserted if 13033 * @param include_duplicate_function flag is set to true. 13034 * 13035 * @param include_duplicate_function As per description. 13036 * 13037 * @return Requested string. 13038 **/ 13039 std::string NegativeTest10::getGeometryShader(bool include_duplicate_function) 13040 { 13041 std::stringstream result_sstream; 13042 13043 result_sstream << "#version 400\n" 13044 "\n" 13045 "#extension GL_ARB_shader_subroutine : require\n" 13046 "\n" 13047 "layout (triangles) in;\n" 13048 "layout (triangle_strip, max_vertices = 4) out;\n" 13049 "\n" 13050 "subroutine void subroutineType(inout vec4 test);\n" 13051 "\n" 13052 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13053 "{\n" 13054 " test = vec4(2, 3, 4, 5);\n" 13055 "}\n" 13056 "\n" 13057 "subroutine uniform subroutineType function;\n" 13058 "\n"; 13059 13060 if (include_duplicate_function) 13061 { 13062 result_sstream << "void test_function(inout vec4 test)\n" 13063 "{\n" 13064 " test = vec4(3, 4, 5, 6);\n" 13065 "}\n" 13066 "\n"; 13067 } 13068 13069 result_sstream << "void main()\n" 13070 "{\n" 13071 " function(gl_Position);\n" 13072 " EmitVertex();\n" 13073 " EndPrimitive();\n" 13074 "}\n"; 13075 13076 return result_sstream.str(); 13077 } 13078 13079 /** Retrieves tess control shader that should be used for the purpose of the test. 13080 * An overloaded version of a subroutine function is inserted if 13081 * @param include_duplicate_function flag is set to true. 13082 * 13083 * @param include_duplicate_function As per description. 13084 * 13085 * @return Requested string. 13086 **/ 13087 std::string NegativeTest10::getTessellationControlShader(bool include_duplicate_function) 13088 { 13089 std::stringstream result_sstream; 13090 13091 result_sstream << "#version 400\n" 13092 "\n" 13093 "#extension GL_ARB_shader_subroutine : require\n" 13094 "\n" 13095 "layout (vertices = 4) out;\n" 13096 "\n" 13097 "subroutine void subroutineType(inout vec4 test);\n" 13098 "\n" 13099 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13100 "{\n" 13101 " test = vec4(2, 3, 4, 5);\n" 13102 "}\n" 13103 "\n" 13104 "subroutine uniform subroutineType function;\n" 13105 "\n"; 13106 13107 if (include_duplicate_function) 13108 { 13109 result_sstream << "void test_function(inout vec4 test)\n" 13110 "{\n" 13111 " test = vec4(3, 4, 5, 6);\n" 13112 "}\n" 13113 "\n"; 13114 } 13115 13116 result_sstream << "void main()\n" 13117 "{\n" 13118 " vec4 temp;\n" 13119 "\n" 13120 " function(temp);\n" 13121 "\n" 13122 " gl_out[gl_InvocationID].gl_Position = temp;\n" 13123 " gl_TessLevelInner[0] = temp.x;\n" 13124 " gl_TessLevelInner[1] = temp.y;\n" 13125 " gl_TessLevelOuter[0] = temp.z;\n" 13126 " gl_TessLevelOuter[1] = temp.w;\n" 13127 " gl_TessLevelOuter[2] = temp.x;\n" 13128 " gl_TessLevelOuter[3] = temp.y;\n" 13129 "}\n"; 13130 13131 return result_sstream.str(); 13132 } 13133 13134 /** Retrieves tess evaluation shader that should be used for the purpose of the test. 13135 * An overloaded version of a subroutine function is inserted if 13136 * @param include_duplicate_function flag is set to true. 13137 * 13138 * @param include_duplicate_function As per description. 13139 * 13140 * @return Requested string. 13141 **/ 13142 std::string NegativeTest10::getTessellationEvaluationShader(bool include_duplicate_function) 13143 { 13144 std::stringstream result_sstream; 13145 13146 result_sstream << "#version 400\n" 13147 "\n" 13148 "#extension GL_ARB_shader_subroutine : require\n" 13149 "\n" 13150 "layout (quads) in;\n" 13151 "\n" 13152 "subroutine void subroutineType(inout vec4 test);\n" 13153 "\n" 13154 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13155 "{\n" 13156 " test = vec4(2, 3, 4, 5);\n" 13157 "}\n" 13158 "\n" 13159 "subroutine uniform subroutineType function;\n" 13160 "\n"; 13161 13162 if (include_duplicate_function) 13163 { 13164 result_sstream << "void test_function(inout vec4 test)\n" 13165 "{\n" 13166 " test = vec4(3, 4, 5, 6);\n" 13167 "}\n" 13168 "\n"; 13169 } 13170 13171 result_sstream << "void main()\n" 13172 "{\n" 13173 " vec4 temp;\n" 13174 "\n" 13175 " function(temp);\n" 13176 "\n" 13177 " gl_Position = temp;\n" 13178 "}\n"; 13179 13180 return result_sstream.str(); 13181 } 13182 13183 /** Retrieves vertex shader that should be used for the purpose of the test. 13184 * An overloaded version of a subroutine function is inserted if 13185 * @param include_duplicate_function flag is set to true. 13186 * 13187 * @param include_duplicate_function As per description. 13188 * 13189 * @return Requested string. 13190 **/ 13191 std::string NegativeTest10::getVertexShader(bool include_duplicate_function) 13192 { 13193 std::stringstream result_sstream; 13194 13195 result_sstream << "#version 400\n" 13196 "\n" 13197 "#extension GL_ARB_shader_subroutine : require\n" 13198 "\n" 13199 "subroutine void subroutineType(inout vec4 test);\n" 13200 "\n" 13201 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13202 "{\n" 13203 " test = vec4(2, 3, 4, 5);\n" 13204 "}\n" 13205 "\n" 13206 "subroutine uniform subroutineType function;\n" 13207 "\n"; 13208 13209 if (include_duplicate_function) 13210 { 13211 result_sstream << "void test_function(inout vec4 test)\n" 13212 "{\n" 13213 " test = vec4(3, 4, 5, 6);\n" 13214 "}\n" 13215 "\n"; 13216 } 13217 13218 result_sstream << "void main()\n" 13219 "{\n" 13220 " function(gl_Position);\n" 13221 "}\n"; 13222 13223 return result_sstream.str(); 13224 } 13225 13226 /** Fills m_test_cases field with test case descriptors */ 13227 void NegativeTest10::initTestCases() 13228 { 13229 /* For each test case, only one shader stage should define a function that 13230 * has already been defined as a subroutine. */ 13231 for (int offending_shader_stage_it = static_cast<int>(Utils::SHADER_STAGE_FIRST); 13232 offending_shader_stage_it != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++offending_shader_stage_it) 13233 { 13234 Utils::_shader_stage offending_shader_stage = static_cast<Utils::_shader_stage>(offending_shader_stage_it); 13235 /* Form the test case descriptor */ 13236 std::stringstream name_sstream; 13237 _test_case test_case; 13238 13239 name_sstream << "Broken shader stage:" << Utils::getShaderStageString(offending_shader_stage); 13240 13241 test_case.fs_body = getFragmentShader(offending_shader_stage == Utils::SHADER_STAGE_FRAGMENT); 13242 test_case.gs_body = getGeometryShader(offending_shader_stage == Utils::SHADER_STAGE_GEOMETRY); 13243 test_case.name = name_sstream.str(); 13244 test_case.tc_body = 13245 getTessellationControlShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 13246 test_case.te_body = 13247 getTessellationEvaluationShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 13248 test_case.vs_body = getVertexShader(offending_shader_stage == Utils::SHADER_STAGE_VERTEX); 13249 13250 m_test_cases.push_back(test_case); 13251 } 13252 } 13253 13254 /** Executes test iteration. 13255 * 13256 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13257 */ 13258 tcu::TestNode::IterateResult NegativeTest10::iterate() 13259 { 13260 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13261 13262 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13263 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13264 { 13265 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 13266 } 13267 13268 /* Form test cases */ 13269 initTestCases(); 13270 13271 /* Iterate over all test cases */ 13272 for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end(); 13273 ++test_case_iterator) 13274 { 13275 const _test_case& test_case = *test_case_iterator; 13276 13277 /* Try to build the program object */ 13278 if (ShaderSubroutine::Utils::buildProgram(gl, test_case.vs_body, test_case.tc_body, test_case.te_body, 13279 test_case.gs_body, test_case.fs_body, DE_NULL, /* xfb_varyings */ 13280 0, /* n_xfb_varyings */ 13281 &m_vs_id, (test_case.tc_body.length() > 0) ? &m_tc_id : DE_NULL, 13282 (test_case.te_body.length() > 0) ? &m_te_id : DE_NULL, 13283 (test_case.gs_body.length() > 0) ? &m_gs_id : DE_NULL, 13284 (test_case.fs_body.length() > 0) ? &m_fs_id : DE_NULL, &m_po_id)) 13285 { 13286 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 13287 << test_case.name << "] test case, even though it was invalid." 13288 << tcu::TestLog::EndMessage; 13289 13290 m_has_test_passed = false; 13291 } 13292 13293 /* Delete any objects that may have been created */ 13294 deinit(); 13295 } /* for (all test cases) */ 13296 13297 /** All done */ 13298 if (m_has_test_passed) 13299 { 13300 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13301 } 13302 else 13303 { 13304 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13305 } 13306 13307 return STOP; 13308 } 13309 13310 /** Constructor. 13311 * 13312 * @param context Rendering context. 13313 **/ 13314 NegativeTest11::NegativeTest11(deqp::Context& context) 13315 : TestCase(context, "subroutine_uniforms_used_for_sampling_atomic_image_functions", 13316 "Tries to use subroutine uniforms in invalid way in sampling, " 13317 "atomic and image functions. Verifies that compile- or link-time " 13318 "error occurs.") 13319 , m_has_test_passed(true) 13320 , m_po_id(0) 13321 , m_vs_id(0) 13322 { 13323 /* Left blank intentionally */ 13324 } 13325 13326 /** Deinitializes any GL objects that may have been created during 13327 * test execution. 13328 **/ 13329 void NegativeTest11::deinit() 13330 { 13331 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13332 13333 if (m_po_id != 0) 13334 { 13335 gl.deleteProgram(m_po_id); 13336 13337 m_po_id = 0; 13338 } 13339 13340 if (m_vs_id != 0) 13341 { 13342 gl.deleteShader(m_vs_id); 13343 13344 m_vs_id = 0; 13345 } 13346 } 13347 13348 /** Returns a literal corresponding to user-specified test case enum. 13349 * 13350 * @param test_case As per description. 13351 * 13352 * @return Requested string. 13353 **/ 13354 std::string NegativeTest11::getTestCaseString(const _test_case& test_case) 13355 { 13356 std::string result = "?"; 13357 13358 switch (test_case) 13359 { 13360 case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT: 13361 result = "TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT"; 13362 break; 13363 case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT: 13364 result = "TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT"; 13365 break; 13366 case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT: 13367 result = "TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT"; 13368 break; 13369 default: 13370 break; 13371 } 13372 13373 return result; 13374 } 13375 13376 /** Retrieves vertex shader body for user-specified test case. 13377 * 13378 * @param test_case As per description. 13379 * 13380 * @return Requested string. 13381 **/ 13382 std::string NegativeTest11::getVertexShader(const _test_case& test_case) 13383 { 13384 std::stringstream result_sstream; 13385 13386 /* Form pre-amble */ 13387 result_sstream << "#version 400\n" 13388 "\n" 13389 "#extension GL_ARB_shader_subroutine : require\n"; 13390 13391 if (test_case == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT) 13392 { 13393 result_sstream << "#extension GL_ARB_shader_atomic_counters : require\n"; 13394 } 13395 13396 result_sstream << "\n" 13397 /* Define a subroutine */ 13398 "subroutine void subroutineType(inout vec4 test);\n" 13399 "\n" 13400 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13401 "{\n" 13402 " test += vec4(0, 1, 2, 3);\n" 13403 "}\n" 13404 "\n" 13405 "subroutine uniform subroutineType function;\n" 13406 "\n" 13407 13408 /* Define main() body */ 13409 "void main()\n" 13410 "{\n"; 13411 13412 /* Implement case-specific behavior */ 13413 switch (test_case) 13414 { 13415 case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT: 13416 { 13417 result_sstream << "if (atomicCounter(function) > 2)\n" 13418 "{\n" 13419 " gl_Position = vec4(1);\n" 13420 "}\n"; 13421 13422 break; 13423 } 13424 13425 case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT: 13426 { 13427 result_sstream << "imageStore(function, vec2(0.0, 1.0), vec4(1.0) );\n"; 13428 13429 break; 13430 } 13431 13432 case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT: 13433 { 13434 result_sstream << "gl_Position = texture(function, vec2(1.0) );\n"; 13435 13436 break; 13437 } 13438 13439 default: 13440 break; 13441 } /* switch (test_case) */ 13442 13443 /* Close main() body */ 13444 result_sstream << "}\n"; 13445 13446 /* Done */ 13447 return result_sstream.str(); 13448 } 13449 13450 /** Executes test iteration. 13451 * 13452 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13453 */ 13454 tcu::TestNode::IterateResult NegativeTest11::iterate() 13455 { 13456 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13457 13458 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13459 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13460 { 13461 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 13462 } 13463 13464 /* Iterate over all test cases */ 13465 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 13466 { 13467 if (static_cast<_test_case>(test_case) == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT && 13468 !m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters")) 13469 { 13470 /* This iteration requires atomic counter support that this GL implementation 13471 * is not capable of. Skip the iteration 13472 */ 13473 continue; 13474 } 13475 13476 /* Try to build a program object using invalid vertex shader, specific to the 13477 * iteration we're currently in */ 13478 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 13479 13480 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 13481 "", /* te_body */ 13482 "", /* gs_body */ 13483 "", /* fs_body */ 13484 DE_NULL, /* xfb_varyings */ 13485 0, /* n_xfb_varyings */ 13486 &m_vs_id, DE_NULL, /* out_tc_id */ 13487 DE_NULL, /* out_te_id */ 13488 DE_NULL, /* out_gs_id */ 13489 DE_NULL, /* out_fs_id */ 13490 &m_po_id)) 13491 { 13492 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 13493 << getTestCaseString(static_cast<_test_case>(test_case)) 13494 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 13495 13496 m_has_test_passed = false; 13497 } 13498 13499 /* Delete any objects that may have been created */ 13500 deinit(); 13501 } /* for (all test cases) */ 13502 13503 /** All done */ 13504 if (m_has_test_passed) 13505 { 13506 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13507 } 13508 else 13509 { 13510 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13511 } 13512 13513 return STOP; 13514 } 13515 13516 /** Constructor. 13517 * 13518 * @param context Rendering context. 13519 **/ 13520 NegativeTest12::NegativeTest12(deqp::Context& context) 13521 : TestCase(context, "subroutines_not_allowed_as_variables_constructors_and_argument_or_return_types", 13522 "Verifies that it is not allowed to use subroutine type for " 13523 "local/global variables, constructors or argument/return type.") 13524 , m_has_test_passed(true) 13525 , m_po_id(0) 13526 , m_vs_id(0) 13527 { 13528 /* Left blank intentionally */ 13529 } 13530 13531 /** Deinitializes any GL objects that may have been created during 13532 * test execution. 13533 **/ 13534 void NegativeTest12::deinit() 13535 { 13536 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13537 13538 if (m_po_id != 0) 13539 { 13540 gl.deleteProgram(m_po_id); 13541 13542 m_po_id = 0; 13543 } 13544 13545 if (m_vs_id != 0) 13546 { 13547 gl.deleteShader(m_vs_id); 13548 13549 m_vs_id = 0; 13550 } 13551 } 13552 13553 /** Returns a literal corresponding to user-specified test case enum. 13554 * 13555 * @param test_case As per description. 13556 * 13557 * @return Requested string. 13558 **/ 13559 std::string NegativeTest12::getTestCaseString(const _test_case& test_case) 13560 { 13561 std::string result = "?"; 13562 13563 switch (test_case) 13564 { 13565 case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE: 13566 result = "TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE"; 13567 break; 13568 case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE: 13569 result = "TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE"; 13570 break; 13571 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR: 13572 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR"; 13573 break; 13574 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT: 13575 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT"; 13576 break; 13577 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE: 13578 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE"; 13579 break; 13580 default: 13581 break; 13582 } 13583 13584 return result; 13585 } 13586 13587 /** Retrieves vertex shader body for user-specified test case. 13588 * 13589 * @param test_case As per description. 13590 * 13591 * @return Requested string. 13592 **/ 13593 std::string NegativeTest12::getVertexShader(const _test_case& test_case) 13594 { 13595 std::stringstream result_sstream; 13596 13597 /* Form pre-amble */ 13598 result_sstream << "#version 400\n" 13599 "\n" 13600 "#extension GL_ARB_shader_subroutine : require\n" 13601 "\n" 13602 /* Define a subroutine */ 13603 "subroutine void subroutineType(inout vec4 test);\n" 13604 "\n" 13605 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13606 "{\n" 13607 " test += vec4(0, 1, 2, 3);\n" 13608 "}\n" 13609 "\n" 13610 "subroutine uniform subroutineType function;\n" 13611 "\n"; 13612 13613 /* Include case-specific implementation */ 13614 switch (test_case) 13615 { 13616 case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE: 13617 { 13618 result_sstream << "void main()\n" 13619 "{\n" 13620 " subroutine subroutineType function2;\n" 13621 " vec4 result;\n" 13622 "\n" 13623 " function2(result);\n" 13624 " gl_Position = result;\n" 13625 "}\n"; 13626 13627 break; 13628 } 13629 13630 case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE: 13631 { 13632 result_sstream << "subroutine subroutineType function2;\n" 13633 "\n" 13634 "void main()\n" 13635 "{\n" 13636 " vec4 result;\n" 13637 "\n" 13638 " function2(result);\n" 13639 " gl_Position = result;\n" 13640 "}\n"; 13641 13642 break; 13643 } 13644 13645 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR: 13646 { 13647 result_sstream << "void main()\n" 13648 "{\n" 13649 " subroutineType(function);\n" 13650 "}\n"; 13651 13652 break; 13653 } 13654 13655 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT: 13656 { 13657 result_sstream << "vec4 test_function(subroutineType argument)\n" 13658 "{\n" 13659 " vec4 result = vec4(1, 2, 3, 4);\n" 13660 "\n" 13661 " argument(result);\n" 13662 "\n" 13663 " return result;\n" 13664 "}\n" 13665 "\n" 13666 "void main()\n" 13667 "{\n" 13668 " test_function(function);\n" 13669 "}\n"; 13670 13671 break; 13672 } 13673 13674 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE: 13675 { 13676 result_sstream << "subroutineType test_function()\n" 13677 "{\n" 13678 " return function;\n" 13679 "}\n" 13680 "\n" 13681 "void main()\n" 13682 "{\n" 13683 " test_function()(gl_Position);\n" 13684 "}\n"; 13685 13686 break; 13687 } 13688 13689 default: 13690 break; 13691 } /* switch (test_case) */ 13692 13693 /* Done */ 13694 return result_sstream.str(); 13695 } 13696 13697 /** Executes test iteration. 13698 * 13699 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13700 */ 13701 tcu::TestNode::IterateResult NegativeTest12::iterate() 13702 { 13703 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13704 13705 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13706 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13707 { 13708 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 13709 } 13710 13711 /* Iterate over all test cases */ 13712 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 13713 { 13714 /* Try to build a program object using invalid vertex shader, specific to the 13715 * iteration we're currently in */ 13716 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 13717 13718 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 13719 "", /* te_body */ 13720 "", /* gs_body */ 13721 "", /* fs_body */ 13722 DE_NULL, /* xfb_varyings */ 13723 0, /* n_xfb_varyings */ 13724 &m_vs_id, DE_NULL, /* out_tc_id */ 13725 DE_NULL, /* out_te_id */ 13726 DE_NULL, /* out_gs_id */ 13727 DE_NULL, /* out_fs_id */ 13728 &m_po_id)) 13729 { 13730 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 13731 << getTestCaseString(static_cast<_test_case>(test_case)) 13732 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 13733 13734 m_has_test_passed = false; 13735 } 13736 13737 /* Delete any objects that may have been created */ 13738 deinit(); 13739 } /* for (all test cases) */ 13740 13741 /** All done */ 13742 if (m_has_test_passed) 13743 { 13744 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13745 } 13746 else 13747 { 13748 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13749 } 13750 13751 return STOP; 13752 } 13753 13754 } /* ShaderSubroutine */ 13755 13756 /** Constructor. 13757 * 13758 * @param context Rendering context. 13759 **/ 13760 ShaderSubroutineTests::ShaderSubroutineTests(deqp::Context& context) 13761 : TestCaseGroup(context, "shader_subroutine", "Verifies \"shader_subroutine\" functionality") 13762 { 13763 /* Left blank on purpose */ 13764 } 13765 13766 /** Initializes a texture_storage_multisample test group. 13767 * 13768 **/ 13769 void ShaderSubroutineTests::init(void) 13770 { 13771 addChild(new ShaderSubroutine::APITest1(m_context)); 13772 addChild(new ShaderSubroutine::APITest2(m_context)); 13773 addChild(new ShaderSubroutine::FunctionalTest1_2(m_context)); 13774 addChild(new ShaderSubroutine::FunctionalTest3_4(m_context)); 13775 addChild(new ShaderSubroutine::FunctionalTest5(m_context)); 13776 addChild(new ShaderSubroutine::FunctionalTest6(m_context)); 13777 addChild(new ShaderSubroutine::FunctionalTest7_8(m_context)); 13778 addChild(new ShaderSubroutine::FunctionalTest9(m_context)); 13779 addChild(new ShaderSubroutine::FunctionalTest10(m_context)); 13780 addChild(new ShaderSubroutine::FunctionalTest11(m_context)); 13781 addChild(new ShaderSubroutine::FunctionalTest12(m_context)); 13782 addChild(new ShaderSubroutine::FunctionalTest13(m_context)); 13783 addChild(new ShaderSubroutine::FunctionalTest14_15(m_context)); 13784 addChild(new ShaderSubroutine::FunctionalTest16(m_context)); 13785 addChild(new ShaderSubroutine::FunctionalTest17(m_context)); 13786 addChild(new ShaderSubroutine::FunctionalTest18_19(m_context)); 13787 addChild(new ShaderSubroutine::NegativeTest1(m_context)); 13788 addChild(new ShaderSubroutine::NegativeTest2(m_context)); 13789 addChild(new ShaderSubroutine::NegativeTest3(m_context)); 13790 addChild(new ShaderSubroutine::NegativeTest4(m_context)); 13791 addChild(new ShaderSubroutine::NegativeTest5(m_context)); 13792 addChild(new ShaderSubroutine::NegativeTest6(m_context)); 13793 addChild(new ShaderSubroutine::NegativeTest7(m_context)); 13794 addChild(new ShaderSubroutine::NegativeTest8(m_context)); 13795 addChild(new ShaderSubroutine::NegativeTest9(m_context)); 13796 addChild(new ShaderSubroutine::NegativeTest10(m_context)); 13797 addChild(new ShaderSubroutine::NegativeTest11(m_context)); 13798 addChild(new ShaderSubroutine::NegativeTest12(m_context)); 13799 } 13800 13801 } /* glcts namespace */ 13802