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 38using namespace glw; 39 40namespace gl4cts 41{ 42namespace ShaderSubroutine 43{ 44/** Constructor. 45 * 46 * @param context CTS context. 47 **/ 48Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context) 49{ 50} 51 52/** Destructor 53 * 54 **/ 55Utils::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 **/ 73void 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 **/ 84void 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 **/ 99void 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 **/ 114Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context) 115{ 116 /* Nothing to be done here */ 117} 118 119/** Destructor 120 * 121 **/ 122Utils::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 **/ 140void 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 **/ 161void 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 **/ 173void 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 **/ 188void 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 **/ 199void 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 207const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9; 208 209/** Constructor. 210 * 211 * @param context CTS context. 212 **/ 213Utils::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 **/ 229Utils::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 **/ 246void 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 **/ 330void 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 **/ 380bool 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 **/ 400void 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 **/ 418void 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 **/ 442GLuint 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 **/ 467GLint 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 **/ 492GLint 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 **/ 514void 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 **/ 594void 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 **/ 650void 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 **/ 662Utils::texture::texture(deqp::Context& context) : m_id(0), m_context(context) 663{ 664 /* Nothing to done here */ 665} 666 667/** Destructor 668 * 669 **/ 670Utils::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 **/ 684void 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 **/ 698void 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 **/ 717void 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 **/ 735void 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 **/ 750Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context) 751{ 752} 753 754/** Destructor 755 * 756 **/ 757Utils::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 **/ 772void 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 **/ 783void 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 * */ 831bool 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 964end: 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 **/ 975Utils::_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 **/ 1056unsigned 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 **/ 1095glw::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 **/ 1132unsigned 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 **/ 1234std::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 **/ 1271std::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 **/ 1308const 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 } 1323 1324 return string; 1325} 1326 1327/** Returns string that represents pname's name 1328 * 1329 * @param pname pname 1330 * 1331 * @return String representation of known pnames 1332 **/ 1333const GLchar* Utils::pnameToStr(glw::GLenum pname) 1334{ 1335 const GLchar* string = "Unknown pname"; 1336 1337 switch (pname) 1338 { 1339 case GL_ACTIVE_SUBROUTINE_UNIFORMS: 1340 string = "GL_ACTIVE_SUBROUTINE_UNIFORMS"; 1341 break; 1342 case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS: 1343 string = "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"; 1344 break; 1345 case GL_ACTIVE_SUBROUTINES: 1346 string = "GL_ACTIVE_SUBROUTINES"; 1347 break; 1348 case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH: 1349 string = "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"; 1350 break; 1351 case GL_ACTIVE_SUBROUTINE_MAX_LENGTH: 1352 string = "GL_ACTIVE_SUBROUTINE_MAX_LENGTH"; 1353 break; 1354 case GL_NUM_COMPATIBLE_SUBROUTINES: 1355 string = "GL_NUM_COMPATIBLE_SUBROUTINES"; 1356 break; 1357 case GL_UNIFORM_SIZE: 1358 string = "GL_UNIFORM_SIZE"; 1359 break; 1360 case GL_COMPATIBLE_SUBROUTINES: 1361 string = "GL_COMPATIBLE_SUBROUTINES"; 1362 break; 1363 case GL_UNIFORM_NAME_LENGTH: 1364 string = "GL_UNIFORM_NAME_LENGTH"; 1365 break; 1366 case GL_ACTIVE_RESOURCES: 1367 string = "GL_ACTIVE_RESOURCES"; 1368 break; 1369 case GL_MAX_NAME_LENGTH: 1370 string = "GL_MAX_NAME_LENGTH"; 1371 break; 1372 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES: 1373 string = "GL_MAX_NUM_COMPATIBLE_SUBROUTINES"; 1374 break; 1375 case GL_NAME_LENGTH: 1376 string = "GL_NAME_LENGTH"; 1377 break; 1378 case GL_ARRAY_SIZE: 1379 string = "GL_ARRAY_SIZE"; 1380 break; 1381 case GL_LOCATION: 1382 string = "GL_LOCATION"; 1383 break; 1384 default: 1385 TCU_FAIL("Not implemented"); 1386 } 1387 1388 return string; 1389} 1390 1391bool Utils::compare(const glw::GLfloat& left, const glw::GLfloat& right) 1392{ 1393 static const glw::GLfloat m_epsilon = 0.00001f; 1394 1395 if (m_epsilon < std::abs(right - left)) 1396 { 1397 return false; 1398 } 1399 else 1400 { 1401 return true; 1402 } 1403} 1404 1405/** Returns a variable type enum corresponding to user-specified base variable type 1406 * and the number of components it should support. 1407 * 1408 * @param base_variable_type Base variable type to use for the query. 1409 * @param n_components Number of components to consider for the query. 1410 * 1411 * @return As per description. 1412 **/ 1413Utils::_variable_type Utils::getVariableTypeFromProperties(const _variable_type& base_variable_type, 1414 const unsigned int& n_components) 1415{ 1416 _variable_type result = VARIABLE_TYPE_UNKNOWN; 1417 1418 switch (base_variable_type) 1419 { 1420 case VARIABLE_TYPE_BOOL: 1421 { 1422 switch (n_components) 1423 { 1424 case 1: 1425 result = VARIABLE_TYPE_BOOL; 1426 break; 1427 case 2: 1428 result = VARIABLE_TYPE_BVEC2; 1429 break; 1430 case 3: 1431 result = VARIABLE_TYPE_BVEC3; 1432 break; 1433 case 4: 1434 result = VARIABLE_TYPE_BVEC4; 1435 break; 1436 1437 default: 1438 { 1439 TCU_FAIL("Unsupported number of components requested"); 1440 } 1441 } /* switch (n_components) */ 1442 1443 break; 1444 } 1445 1446 case VARIABLE_TYPE_DOUBLE: 1447 { 1448 switch (n_components) 1449 { 1450 case 1: 1451 result = VARIABLE_TYPE_DOUBLE; 1452 break; 1453 case 2: 1454 result = VARIABLE_TYPE_DVEC2; 1455 break; 1456 case 3: 1457 result = VARIABLE_TYPE_DVEC3; 1458 break; 1459 case 4: 1460 result = VARIABLE_TYPE_DVEC4; 1461 break; 1462 1463 default: 1464 { 1465 TCU_FAIL("Unsupported number of components requested"); 1466 } 1467 } /* switch (n_components) */ 1468 1469 break; 1470 } 1471 1472 case VARIABLE_TYPE_FLOAT: 1473 { 1474 switch (n_components) 1475 { 1476 case 1: 1477 result = VARIABLE_TYPE_FLOAT; 1478 break; 1479 case 2: 1480 result = VARIABLE_TYPE_VEC2; 1481 break; 1482 case 3: 1483 result = VARIABLE_TYPE_VEC3; 1484 break; 1485 case 4: 1486 result = VARIABLE_TYPE_VEC4; 1487 break; 1488 1489 default: 1490 { 1491 TCU_FAIL("Unsupported number of components requested"); 1492 } 1493 } /* switch (n_components) */ 1494 1495 break; 1496 } 1497 1498 case VARIABLE_TYPE_INT: 1499 { 1500 switch (n_components) 1501 { 1502 case 1: 1503 result = VARIABLE_TYPE_INT; 1504 break; 1505 case 2: 1506 result = VARIABLE_TYPE_IVEC2; 1507 break; 1508 case 3: 1509 result = VARIABLE_TYPE_IVEC3; 1510 break; 1511 case 4: 1512 result = VARIABLE_TYPE_IVEC4; 1513 break; 1514 1515 default: 1516 { 1517 TCU_FAIL("Unsupported number of components requested"); 1518 } 1519 } /* switch (n_components) */ 1520 1521 break; 1522 } 1523 1524 case VARIABLE_TYPE_UINT: 1525 { 1526 switch (n_components) 1527 { 1528 case 1: 1529 result = VARIABLE_TYPE_UINT; 1530 break; 1531 case 2: 1532 result = VARIABLE_TYPE_UVEC2; 1533 break; 1534 case 3: 1535 result = VARIABLE_TYPE_UVEC3; 1536 break; 1537 case 4: 1538 result = VARIABLE_TYPE_UVEC4; 1539 break; 1540 1541 default: 1542 { 1543 TCU_FAIL("Unsupported number of components requested"); 1544 } 1545 } /* switch (n_components) */ 1546 1547 break; 1548 } 1549 1550 default: 1551 { 1552 TCU_FAIL("Unrecognized base variable type"); 1553 } 1554 } /* switch (base_variable_type) */ 1555 1556 return result; 1557} 1558 1559/** Returns a GLSL literal corresponding to user-specified variable type. 1560 * 1561 * @param variable_type Variable type to use for the query. 1562 * 1563 * @return As per description or [?] if @param variable_type was not 1564 * recognized. 1565 **/ 1566std::string Utils::getVariableTypeGLSLString(const _variable_type& variable_type) 1567{ 1568 std::string result = "[?]"; 1569 1570 switch (variable_type) 1571 { 1572 case VARIABLE_TYPE_BOOL: 1573 result = "bool"; 1574 break; 1575 case VARIABLE_TYPE_BVEC2: 1576 result = "bvec2"; 1577 break; 1578 case VARIABLE_TYPE_BVEC3: 1579 result = "bvec3"; 1580 break; 1581 case VARIABLE_TYPE_BVEC4: 1582 result = "bvec4"; 1583 break; 1584 case VARIABLE_TYPE_DOUBLE: 1585 result = "double"; 1586 break; 1587 case VARIABLE_TYPE_DVEC2: 1588 result = "dvec2"; 1589 break; 1590 case VARIABLE_TYPE_DVEC3: 1591 result = "dvec3"; 1592 break; 1593 case VARIABLE_TYPE_DVEC4: 1594 result = "dvec4"; 1595 break; 1596 case VARIABLE_TYPE_FLOAT: 1597 result = "float"; 1598 break; 1599 case VARIABLE_TYPE_INT: 1600 result = "int"; 1601 break; 1602 case VARIABLE_TYPE_IVEC2: 1603 result = "ivec2"; 1604 break; 1605 case VARIABLE_TYPE_IVEC3: 1606 result = "ivec3"; 1607 break; 1608 case VARIABLE_TYPE_IVEC4: 1609 result = "ivec4"; 1610 break; 1611 case VARIABLE_TYPE_MAT2: 1612 result = "mat2"; 1613 break; 1614 case VARIABLE_TYPE_MAT2X3: 1615 result = "mat2x3"; 1616 break; 1617 case VARIABLE_TYPE_MAT2X4: 1618 result = "mat2x4"; 1619 break; 1620 case VARIABLE_TYPE_MAT3: 1621 result = "mat3"; 1622 break; 1623 case VARIABLE_TYPE_MAT3X2: 1624 result = "mat3x2"; 1625 break; 1626 case VARIABLE_TYPE_MAT3X4: 1627 result = "mat3x4"; 1628 break; 1629 case VARIABLE_TYPE_MAT4: 1630 result = "mat4"; 1631 break; 1632 case VARIABLE_TYPE_MAT4X2: 1633 result = "mat4x2"; 1634 break; 1635 case VARIABLE_TYPE_MAT4X3: 1636 result = "mat4x3"; 1637 break; 1638 case VARIABLE_TYPE_UINT: 1639 result = "uint"; 1640 break; 1641 case VARIABLE_TYPE_UVEC2: 1642 result = "uvec2"; 1643 break; 1644 case VARIABLE_TYPE_UVEC3: 1645 result = "uvec3"; 1646 break; 1647 case VARIABLE_TYPE_UVEC4: 1648 result = "uvec4"; 1649 break; 1650 case VARIABLE_TYPE_VEC2: 1651 result = "vec2"; 1652 break; 1653 case VARIABLE_TYPE_VEC3: 1654 result = "vec3"; 1655 break; 1656 case VARIABLE_TYPE_VEC4: 1657 result = "vec4"; 1658 break; 1659 1660 default: 1661 { 1662 TCU_FAIL("Unrecognized variable type"); 1663 } 1664 } /* switch (variable_type) */ 1665 1666 return result; 1667} 1668 1669/** Constructor. 1670 * 1671 * @param context Rendering context. 1672 * 1673 **/ 1674APITest1::APITest1(deqp::Context& context) 1675 : TestCase(context, "min_maxes", "Verifies the implementation returns valid GL_MAX_SUBROUTINE* pnames " 1676 "which meet the minimum maximum requirements enforced by the spec.") 1677 , m_has_test_passed(true) 1678{ 1679 /* Left blank intentionally */ 1680} 1681 1682/** Executes test iteration. 1683 * 1684 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 1685 */ 1686tcu::TestNode::IterateResult APITest1::iterate() 1687{ 1688 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1689 1690 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 1691 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 1692 { 1693 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 1694 } 1695 1696 /* Iterate over all pnames */ 1697 const struct 1698 { 1699 glw::GLenum pname; 1700 const char* pname_string; 1701 glw::GLint min_value; 1702 } pnames[] = { { GL_MAX_SUBROUTINES, "GL_MAX_SUBROUTINES", 256 }, 1703 { GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS", 1024 } }; 1704 const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]); 1705 1706 for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname) 1707 { 1708 glw::GLboolean bool_value = GL_FALSE; 1709 glw::GLdouble double_value = 0.0; 1710 glw::GLfloat float_value = 0.0f; 1711 glw::GLint int_value = 0; 1712 glw::GLint64 int64_value = 0; 1713 const glw::GLint min_value = pnames[n_pname].min_value; 1714 const glw::GLenum& pname = pnames[n_pname].pname; 1715 const char* pname_string = pnames[n_pname].pname_string; 1716 1717 /* Retrieve the pname values */ 1718 gl.getBooleanv(pname, &bool_value); 1719 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() call failed."); 1720 1721 gl.getDoublev(pname, &double_value); 1722 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetDoublev() call failed."); 1723 1724 gl.getFloatv(pname, &float_value); 1725 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed."); 1726 1727 gl.getIntegerv(pname, &int_value); 1728 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed."); 1729 1730 gl.getInteger64v(pname, &int64_value); 1731 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v() call failed."); 1732 1733 /* Make sure the value reported meets the min max requirement */ 1734 if (int_value < min_value) 1735 { 1736 m_testCtx.getLog() << tcu::TestLog::Message << "GL implementation reports a value of [" << int_value 1737 << "]" 1738 " for property [" 1739 << pname_string << "]" 1740 ", whereas the min max for the property is [" 1741 << min_value << "]." << tcu::TestLog::EndMessage; 1742 1743 m_has_test_passed = false; 1744 } 1745 1746 /* Verify the other getters reported valid values */ 1747 const float epsilon = 1e-5f; 1748 1749 if (((int_value == 0) && (bool_value == GL_TRUE)) || ((int_value != 0) && (bool_value != GL_TRUE))) 1750 { 1751 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid boolean value [" << bool_value 1752 << "]" 1753 " reported for property [" 1754 << pname_string << "]" 1755 " (int value:[" 1756 << int_value << "])" << tcu::TestLog::EndMessage; 1757 1758 m_has_test_passed = false; 1759 } 1760 1761 if (de::abs(double_value - (double)int_value) > epsilon) 1762 { 1763 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid double value [" << double_value 1764 << "]" 1765 " reported for property [" 1766 << pname_string << "]" 1767 " (int value:[" 1768 << int_value << "])" << tcu::TestLog::EndMessage; 1769 1770 m_has_test_passed = false; 1771 } 1772 1773 if (de::abs(float_value - (float)int_value) > epsilon) 1774 { 1775 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid float value [" << float_value 1776 << "]" 1777 " reported for property [" 1778 << pname_string << "]" 1779 " (int value:[" 1780 << int_value << "])" << tcu::TestLog::EndMessage; 1781 1782 m_has_test_passed = false; 1783 } 1784 1785 if (int64_value != int_value) 1786 { 1787 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid 64-bit integer value [" << float_value 1788 << "]" 1789 " reported for property [" 1790 << pname_string << "]" 1791 " (int value:[" 1792 << int_value << "])" << tcu::TestLog::EndMessage; 1793 1794 m_has_test_passed = false; 1795 } 1796 } /* for (all pnames) */ 1797 1798 if (m_has_test_passed) 1799 { 1800 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1801 } 1802 else 1803 { 1804 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1805 } 1806 1807 return STOP; 1808} 1809 1810/** Constructor. 1811 * 1812 * @param context Rendering context. 1813 * 1814 **/ 1815APITest2::APITest2(deqp::Context& context) 1816 : TestCase(context, "name_getters", "Verifies glGetActiveSubroutineName() and glGetActiveSubroutineUniformName() " 1817 "functions work correctly.") 1818 , m_buffer(DE_NULL) 1819 , m_has_test_passed(true) 1820 , m_po_id(0) 1821 , m_subroutine_name1("subroutine1") 1822 , m_subroutine_name2("subroutine2") 1823 , m_subroutine_uniform_name("data_provider") 1824 , m_vs_id(0) 1825{ 1826 /* Left blank intentionally */ 1827} 1828 1829/** Destroys all ES objects that may have been created during test initialization, 1830 * as well as releases any buffers that may have been allocated during the process. 1831 */ 1832void APITest2::deinit() 1833{ 1834 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1835 1836 if (m_buffer != DE_NULL) 1837 { 1838 delete[] m_buffer; 1839 1840 m_buffer = DE_NULL; 1841 } 1842 1843 if (m_po_id != 0) 1844 { 1845 gl.deleteProgram(m_po_id); 1846 1847 m_po_id = 0; 1848 } 1849 1850 if (m_vs_id != 0) 1851 { 1852 gl.deleteShader(m_vs_id); 1853 1854 m_vs_id = 0; 1855 } 1856} 1857 1858/** Returns body of a vertex shader that should be used for the test. 1859 * 1860 * @return As per description. 1861 **/ 1862std::string APITest2::getVertexShaderBody() 1863{ 1864 return "#version 400\n" 1865 "\n" 1866 "#extension GL_ARB_shader_subroutine : require\n" 1867 "\n" 1868 "subroutine int ExampleSubroutineType(int example_argument);\n" 1869 "\n" 1870 "subroutine(ExampleSubroutineType) int subroutine1(int example_argument)\n" 1871 "{\n" 1872 " return 1;\n" 1873 "}\n" 1874 "\n" 1875 "subroutine(ExampleSubroutineType) int subroutine2(int example_argument)\n" 1876 "{\n" 1877 " return 2;\n" 1878 "}\n" 1879 "\n" 1880 "subroutine uniform ExampleSubroutineType data_provider;\n" 1881 "\n" 1882 "void main()\n" 1883 "{\n" 1884 " gl_Position = vec4(float(data_provider(0)), vec3(1) );\n" 1885 "}\n"; 1886} 1887 1888/** Initializes all ES objects required to run the test. */ 1889void APITest2::initTest() 1890{ 1891 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1892 1893 /* Generate program & shader objects */ 1894 m_po_id = gl.createProgram(); 1895 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1896 1897 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call(s) failed."); 1898 1899 /* Attach the shader to the program object */ 1900 gl.attachShader(m_po_id, m_vs_id); 1901 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 1902 1903 /* Compile the shader */ 1904 glw::GLint compile_status = GL_FALSE; 1905 std::string vs_body = getVertexShaderBody(); 1906 const char* vs_body_raw_ptr = vs_body.c_str(); 1907 1908 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */); 1909 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 1910 1911 gl.compileShader(m_vs_id); 1912 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 1913 1914 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); 1915 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 1916 1917 if (compile_status != GL_TRUE) 1918 { 1919 TCU_FAIL("Shader compilation failed."); 1920 } 1921 1922 /* Try to link the program object */ 1923 glw::GLint link_status = GL_FALSE; 1924 1925 gl.linkProgram(m_po_id); 1926 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 1927 1928 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 1929 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 1930 1931 if (link_status != GL_TRUE) 1932 { 1933 TCU_FAIL("Program linking failed."); 1934 } 1935 1936 /* Perform a few quick checks */ 1937 glw::GLint n_active_subroutines = 0; 1938 glw::GLint n_active_subroutine_uniforms = 0; 1939 1940 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines); 1941 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms); 1942 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call failed."); 1943 1944 if (n_active_subroutines != 2 /* subroutines declared in vertex shader */) 1945 { 1946 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid amount of active subroutines reported; expected: 2," 1947 " reported:" 1948 << n_active_subroutines << tcu::TestLog::EndMessage; 1949 1950 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINES property value."); 1951 } 1952 1953 if (n_active_subroutine_uniforms != 1) 1954 { 1955 m_testCtx.getLog() << tcu::TestLog::Message 1956 << "Invalid amount of active subroutine uniforms reported: expected: 1," 1957 " reported: " 1958 << n_active_subroutine_uniforms << tcu::TestLog::EndMessage; 1959 1960 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORMS property value."); 1961 } 1962} 1963 1964/** Executes test iteration. 1965 * 1966 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 1967 */ 1968tcu::TestNode::IterateResult APITest2::iterate() 1969{ 1970 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 1971 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 1972 { 1973 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 1974 } 1975 1976 /* Initialize a test program object */ 1977 initTest(); 1978 1979 /* Verify glGetActiveSubroutineName() works correctly */ 1980 verifyGLGetActiveSubroutineNameFunctionality(); 1981 1982 /* Verify glGetActiveSubroutineUniformName() works correctly */ 1983 verifyGLGetActiveSubroutineUniformNameFunctionality(); 1984 1985 /* Done */ 1986 if (m_has_test_passed) 1987 { 1988 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1989 } 1990 else 1991 { 1992 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1993 } 1994 1995 return STOP; 1996} 1997 1998/** Verifies glGetActiveSubroutineName() behaves as per GL_ARB_shader_subroutine 1999 * specification. 2000 **/ 2001void APITest2::verifyGLGetActiveSubroutineNameFunctionality() 2002{ 2003 GLsizei expected_length1 = (GLsizei)strlen(m_subroutine_name1) + 1; 2004 GLsizei expected_length2 = (GLsizei)strlen(m_subroutine_name1) + 1; 2005 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2006 GLsizei reported_length = 0; 2007 2008 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, /* index */ 2009 0, /* bufsize */ 2010 DE_NULL, /* length */ 2011 DE_NULL); /* name */ 2012 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed."); 2013 2014 gl.getProgramInterfaceiv(m_po_id, GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, &reported_length); 2015 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed."); 2016 2017 if ((reported_length != expected_length1) && (reported_length != expected_length2)) 2018 { 2019 m_testCtx.getLog() << tcu::TestLog::Message 2020 << "Invalid active subroutine name length reported:" << reported_length 2021 << ", instead of: " << expected_length1 << " or " << expected_length2 2022 << tcu::TestLog::EndMessage; 2023 2024 TCU_FAIL("Incorrect length of active subroutine name"); 2025 } 2026 2027 m_buffer = new glw::GLchar[reported_length]; 2028 2029 memset(m_buffer, 0, reported_length); 2030 2031 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, reported_length, DE_NULL, /* length */ 2032 m_buffer); 2033 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed."); 2034 2035 if (strcmp(m_buffer, m_subroutine_name1) != 0 && strcmp(m_buffer, m_subroutine_name2) != 0) 2036 { 2037 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine name reported:[" << m_buffer 2038 << "]" 2039 " instead of:[" 2040 << m_subroutine_name1 << "]" 2041 " or:[" 2042 << m_subroutine_name2 << "]." << tcu::TestLog::EndMessage; 2043 2044 TCU_FAIL("Invalid active subroutine name reported."); 2045 } 2046 2047 delete[] m_buffer; 2048 m_buffer = DE_NULL; 2049} 2050 2051/** Verifies glGetActiveSubroutineUniformName() behaves as per GL_ARB_shader_subroutine 2052 * specification. 2053 **/ 2054void APITest2::verifyGLGetActiveSubroutineUniformNameFunctionality() 2055{ 2056 GLsizei expected_length = (GLsizei)strlen(m_subroutine_uniform_name); 2057 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2058 GLsizei reported_length = 0; 2059 2060 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */ 2061 0, /* bufsize */ 2062 DE_NULL, /* length */ 2063 DE_NULL); /* name */ 2064 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed."); 2065 2066 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */ 2067 0, /* bufsize */ 2068 &reported_length, DE_NULL); /* name */ 2069 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed."); 2070 2071 // reported_length is the actual number of characters written into <name> 2072 // If <bufSize> is 0, reported_length should be 0 2073 if (reported_length != 0) 2074 { 2075 m_testCtx.getLog() << tcu::TestLog::Message 2076 << "Invalid active subroutine uniform name length reported:" << reported_length 2077 << ", instead of: " << 0 << tcu::TestLog::EndMessage; 2078 2079 TCU_FAIL("Incorrect length of active subroutine uniform name"); 2080 } 2081 2082 m_buffer = new glw::GLchar[expected_length + 1]; 2083 2084 memset(m_buffer, 0, expected_length + 1); 2085 2086 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, expected_length + 1, &reported_length, m_buffer); 2087 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformName() call failed."); 2088 2089 if (reported_length != expected_length) 2090 { 2091 m_testCtx.getLog() << tcu::TestLog::Message 2092 << "Invalid active subroutine uniform name length reported:" << reported_length 2093 << ", instead of: " << expected_length << tcu::TestLog::EndMessage; 2094 2095 TCU_FAIL("Incorrect length of active subroutine uniform name"); 2096 } 2097 2098 if (strcmp(m_buffer, m_subroutine_uniform_name) != 0) 2099 { 2100 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine uniform name reported:[" << m_buffer 2101 << "]" 2102 " instead of:[" 2103 << m_subroutine_uniform_name << "]" << tcu::TestLog::EndMessage; 2104 2105 TCU_FAIL("Invalid active subroutine uniform name reported."); 2106 } 2107 2108 delete[] m_buffer; 2109 m_buffer = DE_NULL; 2110} 2111 2112/** Constructor. 2113 * 2114 * @param context Rendering context. 2115 * 2116 **/ 2117FunctionalTest1_2::FunctionalTest1_2(deqp::Context& context) 2118 : TestCase(context, "two_subroutines_single_subroutine_uniform", 2119 "Verifies the subroutines work correctly in a vertex shader for" 2120 " bool/float/int/uint/double/*vec*/*mat* argument and return types") 2121 , m_has_test_passed(true) 2122 , m_po_id(0) 2123 , m_po_getter0_subroutine_index(GL_INVALID_INDEX) 2124 , m_po_getter1_subroutine_index(GL_INVALID_INDEX) 2125 , m_po_subroutine_uniform_index(-1) 2126 , m_xfb_bo_id(0) 2127 , m_vao_id(0) 2128 , m_vs_id(0) 2129{ 2130 /* Left blank intentionally */ 2131} 2132 2133/** Destroys all ES objects that may have been created during test initialization, 2134 * as well as releases any buffers that may have been allocated during the process. 2135 */ 2136void FunctionalTest1_2::deinit() 2137{ 2138 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2139 2140 deinitTestIteration(); 2141 2142 if (m_xfb_bo_id != 0) 2143 { 2144 gl.deleteBuffers(1, &m_xfb_bo_id); 2145 2146 m_xfb_bo_id = 0; 2147 } 2148 2149 if (m_vao_id != 0) 2150 { 2151 gl.deleteVertexArrays(1, &m_vao_id); 2152 2153 m_vao_id = 0; 2154 } 2155} 2156 2157/** Deinitializes GL objects that are iteration-specific */ 2158void FunctionalTest1_2::deinitTestIteration() 2159{ 2160 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2161 2162 if (m_po_id != 0) 2163 { 2164 gl.deleteProgram(m_po_id); 2165 2166 m_po_id = 0; 2167 } 2168 2169 if (m_vs_id != 0) 2170 { 2171 gl.deleteShader(m_vs_id); 2172 2173 m_vs_id = 0; 2174 } 2175} 2176 2177/** Executes a single test iteration using user-specified test case propertiesz. 2178 * 2179 * @param test-case Test case descriptor. 2180 * 2181 * @return true if the test iteration passed, false otherwise. 2182 **/ 2183bool FunctionalTest1_2::executeTestIteration(const _test_case& test_case) 2184{ 2185 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2186 bool result = true; 2187 2188 /* Build the test program */ 2189 std::string empty_body; 2190 std::string vs_body = getVertexShaderBody(test_case.variable_type, test_case.array_size); 2191 const glw::GLchar* xfb_varyings[] = { "result" }; 2192 const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]); 2193 2194 if (!Utils::buildProgram(gl, vs_body, empty_body, empty_body, empty_body, empty_body, xfb_varyings, n_xfb_varyings, 2195 &m_vs_id, NULL, /* out_tc_id */ 2196 NULL, /* out_te_id */ 2197 NULL, /* out_gs_id */ 2198 NULL, &m_po_id)) 2199 { 2200 TCU_FAIL("Test program failed to build."); 2201 } 2202 2203 /* Retrieve subroutine locations */ 2204 m_po_getter0_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter0"); 2205 m_po_getter1_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter1"); 2206 2207 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 2208 2209 if (m_po_getter0_subroutine_index == GL_INVALID_INDEX || m_po_getter1_subroutine_index == GL_INVALID_INDEX) 2210 { 2211 TCU_FAIL("At least one subroutine is considered inactive which is invalid."); 2212 } 2213 2214 /* Retrieve subroutine uniform location */ 2215 m_po_subroutine_uniform_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "colorGetterUniform"); 2216 2217 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call failed."); 2218 2219 if (m_po_subroutine_uniform_index == -1) 2220 { 2221 TCU_FAIL("Subroutine uniform is considered inactive which is invalid."); 2222 } 2223 2224 /* Set up XFB BO storage */ 2225 const Utils::_variable_type base_variable_type = Utils::getBaseVariableType(test_case.variable_type); 2226 unsigned int iteration_xfb_bo_size = Utils::getComponentSizeForVariableType(base_variable_type) * 2227 Utils::getNumberOfComponentsForVariableType(test_case.variable_type); 2228 unsigned int total_xfb_bo_size = 0; 2229 2230 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2231 { 2232 /* Boolean varyings are not supported by OpenGL. Instead, we use ints to output 2233 * boolean values. */ 2234 iteration_xfb_bo_size = static_cast<unsigned int>(iteration_xfb_bo_size * sizeof(int)); 2235 } 2236 2237 total_xfb_bo_size = iteration_xfb_bo_size * 2 /* subroutines we will be testing */; 2238 2239 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, total_xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW); 2240 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 2241 2242 /* Activate test program object */ 2243 gl.useProgram(m_po_id); 2244 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2245 2246 /* Run two iterations. Each iteration should invoke different subroutine. */ 2247 const glw::GLuint subroutine_indices[] = { m_po_getter0_subroutine_index, m_po_getter1_subroutine_index }; 2248 const unsigned int n_subroutine_indices = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 2249 2250 for (unsigned int n_subroutine_index = 0; n_subroutine_index < n_subroutine_indices; ++n_subroutine_index) 2251 { 2252 /* Configure which subroutine should be used for the draw call */ 2253 glw::GLuint current_subroutine_index = subroutine_indices[n_subroutine_index]; 2254 2255 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, ¤t_subroutine_index); 2256 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed."); 2257 2258 /* Update XFB binding so that we do not overwrite data XFBed in previous iterations */ 2259 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 2260 m_xfb_bo_id, iteration_xfb_bo_size * n_subroutine_index, iteration_xfb_bo_size); 2261 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() call failed."); 2262 2263 /* Draw a single point */ 2264 gl.beginTransformFeedback(GL_POINTS); 2265 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 2266 { 2267 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 2268 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 2269 } 2270 gl.endTransformFeedback(); 2271 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 2272 } /* for (all subroutine indices) */ 2273 2274 /* Map the BO storage into process space */ 2275 const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 2276 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 2277 2278 result &= verifyXFBData(xfb_data_ptr, test_case.variable_type); 2279 2280 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 2281 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffeR() call failed."); 2282 2283 return result; 2284} 2285 2286/** Retrieves body of a vertex shader that should be used to verify 2287 * subroutine support, given user-specified test iteration properties. 2288 * 2289 * @param variable_type GLSL type that should be used for argument and 2290 * return type definition in a subroutine. This setting 2291 * also affects type of the only output variable in the shader. 2292 * @param array_size 1 if non-arrayed arguments/return types should be tested; 2293 * 2 if arrayed arguments/return types should be tested. 2294 * 2295 * @return Requested string. 2296 **/ 2297std::string FunctionalTest1_2::getVertexShaderBody(const Utils::_variable_type& variable_type, unsigned int array_size) 2298{ 2299 Utils::_variable_type base_variable_type = Utils::getBaseVariableType(variable_type); 2300 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 2301 std::stringstream result_sstream; 2302 std::string variable_type_glsl = Utils::getVariableTypeGLSLString(variable_type); 2303 std::stringstream variable_type_glsl_array_sstream; 2304 std::stringstream variable_type_glsl_arrayed_sstream; 2305 2306 variable_type_glsl_arrayed_sstream << variable_type_glsl; 2307 2308 if (array_size > 1) 2309 { 2310 variable_type_glsl_array_sstream << "[" << array_size << "]"; 2311 variable_type_glsl_arrayed_sstream << variable_type_glsl_array_sstream.str(); 2312 } 2313 2314 /* Form pre-amble */ 2315 result_sstream << "#version 400\n" 2316 "\n" 2317 "#extension GL_ARB_shader_subroutine : require\n"; 2318 2319 if (variable_type == Utils::VARIABLE_TYPE_DOUBLE) 2320 { 2321 result_sstream << "#extension GL_ARB_gpu_shader_fp64 : require\n"; 2322 } 2323 2324 /* Form subroutine type declaration */ 2325 result_sstream << "\n" 2326 "subroutine " 2327 << variable_type_glsl_arrayed_sstream.str() << " colorGetter(in " << variable_type_glsl 2328 << " in_value" << variable_type_glsl_array_sstream.str() << ");\n" 2329 "\n"; 2330 2331 /* Declare getter functions */ 2332 for (int n_getter = 0; n_getter < 2; ++n_getter) 2333 { 2334 result_sstream << "subroutine(colorGetter) " << variable_type_glsl_arrayed_sstream.str() << " getter" 2335 << n_getter << "(in " << variable_type_glsl << " in_value" 2336 << variable_type_glsl_array_sstream.str() << ")\n" 2337 "{\n"; 2338 2339 if (array_size > 1) 2340 { 2341 result_sstream << variable_type_glsl << " temp" << variable_type_glsl_array_sstream.str() << ";\n"; 2342 } 2343 2344 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2345 { 2346 if (array_size > 1) 2347 { 2348 for (unsigned int array_index = 0; array_index < array_size; ++array_index) 2349 { 2350 result_sstream << " temp[" << array_index << "]" 2351 " = " 2352 << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "") 2353 << "(in_value[" << array_index << "]);\n"; 2354 } 2355 2356 result_sstream << " return temp;\n"; 2357 } 2358 else 2359 { 2360 result_sstream << " return " 2361 << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "") 2362 << "(in_value);\n"; 2363 } 2364 } /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */ 2365 else 2366 { 2367 if (array_size > 1) 2368 { 2369 for (unsigned int array_index = 0; array_index < array_size; ++array_index) 2370 { 2371 result_sstream << " temp[" << array_index << "]" 2372 " = in_value[" 2373 << array_index << "] + " << (n_getter + 1) << ";\n"; 2374 } 2375 2376 result_sstream << " return temp;\n"; 2377 } 2378 else 2379 { 2380 result_sstream << " return (in_value + " << (n_getter + 1) << ");\n"; 2381 } 2382 } 2383 2384 result_sstream << "}\n"; 2385 } /* for (both getter functions) */ 2386 2387 /* Declare subroutine uniform */ 2388 result_sstream << "subroutine uniform colorGetter colorGetterUniform;\n" 2389 "\n"; 2390 2391 /* Declare output variable */ 2392 result_sstream << "out "; 2393 2394 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2395 { 2396 Utils::_variable_type result_as_int_variable_type = 2397 Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components); 2398 std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type); 2399 2400 result_sstream << variable_type_glsl_as_int; 2401 } 2402 else 2403 { 2404 result_sstream << variable_type_glsl; 2405 } 2406 2407 result_sstream << " result;\n" 2408 "\n"; 2409 2410 /* Declare main(): prepare input argument for the subroutine function */ 2411 result_sstream << "void main()\n" 2412 "{\n" 2413 " " 2414 << variable_type_glsl << " temp"; 2415 2416 if (array_size > 1) 2417 { 2418 result_sstream << "[" << array_size << "]"; 2419 } 2420 2421 result_sstream << ";\n"; 2422 2423 for (unsigned int array_index = 0; array_index < array_size; ++array_index) 2424 { 2425 result_sstream << " temp"; 2426 2427 if (array_size > 1) 2428 { 2429 result_sstream << "[" << array_index << "]"; 2430 } 2431 2432 result_sstream << " = " << variable_type_glsl << "("; 2433 2434 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2435 { 2436 result_sstream << "true"; 2437 } 2438 else 2439 { 2440 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 2441 { 2442 result_sstream << "3"; 2443 2444 if (n_component != (n_variable_type_components - 1)) 2445 { 2446 result_sstream << ", "; 2447 } 2448 } /* for (all components) */ 2449 } 2450 2451 result_sstream << ");\n"; 2452 } /* for (all array indices) */ 2453 2454 /* Declare main(): call the subroutine. Verify the input and write the result 2455 * to the output variable. 2456 **/ 2457 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2458 { 2459 Utils::_variable_type result_as_int_variable_type = 2460 Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components); 2461 std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type); 2462 2463 result_sstream << variable_type_glsl_arrayed_sstream.str() << " subroutine_result = colorGetterUniform(temp);\n" 2464 "result = "; 2465 2466 for (unsigned int array_index = 0; array_index < array_size; ++array_index) 2467 { 2468 if (variable_type_glsl == "bool") 2469 result_sstream << "bool(subroutine_result"; 2470 else 2471 result_sstream << "all(subroutine_result"; 2472 2473 if (array_size > 1) 2474 { 2475 result_sstream << "[" << array_index << "]"; 2476 } 2477 2478 result_sstream << ")"; 2479 2480 if (array_index != (array_size - 1)) 2481 { 2482 result_sstream << "&& "; 2483 } 2484 } 2485 2486 result_sstream << " == true ? " << variable_type_glsl_as_int << "(1) : " << variable_type_glsl_as_int << "(0);"; 2487 } 2488 else 2489 { 2490 if (array_size > 1) 2491 { 2492 DE_ASSERT(array_size == 2); 2493 2494 result_sstream << variable_type_glsl << " subroutine_result" << variable_type_glsl_array_sstream.str() 2495 << " = colorGetterUniform(temp);\n" 2496 "\n" 2497 "if (subroutine_result[0] == subroutine_result[1]) result = subroutine_result[0];\n" 2498 "else\n" 2499 "result = " 2500 << variable_type_glsl << "(-1);\n"; 2501 } 2502 else 2503 { 2504 result_sstream << "result = colorGetterUniform(temp);\n"; 2505 } 2506 } 2507 2508 /* All done */ 2509 result_sstream << "}\n"; 2510 2511 return result_sstream.str(); 2512} 2513 2514/** Initializes all GL objects required to run the test. */ 2515void FunctionalTest1_2::initTest() 2516{ 2517 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2518 2519 /* Generate buffer object to hold result XFB data */ 2520 gl.genBuffers(1, &m_xfb_bo_id); 2521 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 2522 2523 /* Set up XFB BO bindings */ 2524 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 2525 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 2526 2527 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 2528 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 2529 2530 /* Generate VAO to use for the draw calls */ 2531 gl.genVertexArrays(1, &m_vao_id); 2532 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 2533 2534 gl.bindVertexArray(m_vao_id); 2535 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 2536} 2537 2538/** Executes test iteration. 2539 * 2540 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 2541 */ 2542tcu::TestNode::IterateResult FunctionalTest1_2::iterate() 2543{ 2544 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 2545 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 2546 { 2547 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 2548 } 2549 2550 /* Initialize a test program object */ 2551 initTest(); 2552 2553 /* Construct test case descriptors: first, iIerate over all 2554 * variable types we want to cover */ 2555 const Utils::_variable_type variable_types[] = { 2556 Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_BVEC2, Utils::VARIABLE_TYPE_BVEC3, 2557 Utils::VARIABLE_TYPE_BVEC4, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, 2558 Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_IVEC3, 2559 Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_MAT2X3, 2560 Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_MAT3X2, 2561 Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_MAT4X2, 2562 Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_UVEC2, 2563 Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_VEC2, 2564 Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_VEC4 2565 }; 2566 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]); 2567 2568 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type) 2569 { 2570 Utils::_variable_type current_variable_type = variable_types[n_variable_type]; 2571 2572 /* We need to test both arrayed and non-arrayed arguments */ 2573 for (unsigned int array_size = 1; array_size < 3; ++array_size) 2574 { 2575 /* Exclude double variables if the relevant extension is unavailable */ 2576 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64") && 2577 current_variable_type == Utils::VARIABLE_TYPE_DOUBLE) 2578 { 2579 continue; 2580 } 2581 2582 /* Form the descriptor */ 2583 _test_case test_case; 2584 2585 test_case.array_size = array_size; 2586 test_case.variable_type = current_variable_type; 2587 2588 /* Store the test case descriptor */ 2589 m_test_cases.push_back(test_case); 2590 } /* for (both arrayed and non-arrayed arguments) */ 2591 } /* for (all variable types) */ 2592 2593 /* Iterate over all test cases and execute the test */ 2594 for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end(); 2595 ++test_case_iterator) 2596 { 2597 const _test_case& test_case = *test_case_iterator; 2598 2599 m_has_test_passed &= executeTestIteration(test_case); 2600 2601 /* Release GL objects that were created during the execution */ 2602 deinitTestIteration(); 2603 } /* for (all test cases) */ 2604 2605 /* Done */ 2606 if (m_has_test_passed) 2607 { 2608 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2609 } 2610 else 2611 { 2612 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2613 } 2614 2615 return STOP; 2616} 2617 2618/** Verifies data that has been XFBed out by the vertex shader. 2619 * 2620 * @param xfb_data Buffer holding the data. 2621 * @param variable_type GLSL type used for the test iteration 2622 * that generated the data at @param xfb_data. 2623 * 2624 * @return true if the data was found to be valid, false if it 2625 * was detected to be incorrect. 2626 **/ 2627bool FunctionalTest1_2::verifyXFBData(const void* xfb_data, const Utils::_variable_type& variable_type) 2628{ 2629 const Utils::_variable_type base_variable_type = Utils::getBaseVariableType(variable_type); 2630 const float epsilon = 1e-5f; 2631 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 2632 bool result = true; 2633 const unsigned char* traveller_ptr = (const unsigned char*)xfb_data; 2634 2635 /* Boolean arguments/return types are tested with a slightly different shader so we 2636 * need to test them in a separate code-path. 2637 */ 2638 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) 2639 { 2640 /* 0 should be returned when getter0 is used, 1 otherwise */ 2641 const unsigned int ref_values[] = { 0, 1 }; 2642 const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]); 2643 2644 for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value) 2645 { 2646 const unsigned int ref_value = ref_values[n_ref_value]; 2647 2648 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 2649 { 2650 int* result_value_ptr = (int*)(traveller_ptr); 2651 2652 if (*result_value_ptr != (int)ref_value) 2653 { 2654 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using " 2655 "[" 2656 << Utils::getVariableTypeGLSLString(variable_type) << "]" 2657 << " argument/return types (" 2658 "expected:[" 2659 << ref_value << "], found:[" << *result_value_ptr << "])" 2660 << tcu::TestLog::EndMessage; 2661 2662 result = false; 2663 break; 2664 } 2665 2666 traveller_ptr += sizeof(int); 2667 } /* for (all components) */ 2668 } /* for (all reference values) */ 2669 } /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */ 2670 else 2671 { 2672 /* 4 should be returned when getter0 is used, 5 otherwise */ 2673 const unsigned int ref_values[] = { 4, 5 }; 2674 const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]); 2675 2676 for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value) 2677 { 2678 const unsigned int ref_value = ref_values[n_ref_value]; 2679 2680 DE_ASSERT( 2681 base_variable_type == Utils::VARIABLE_TYPE_DOUBLE || base_variable_type == Utils::VARIABLE_TYPE_FLOAT || 2682 base_variable_type == Utils::VARIABLE_TYPE_INT || base_variable_type == Utils::VARIABLE_TYPE_UINT); 2683 2684 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 2685 { 2686 const double* double_value_ptr = (double*)traveller_ptr; 2687 const float* float_value_ptr = (float*)traveller_ptr; 2688 const int* int_value_ptr = (int*)traveller_ptr; 2689 2690 switch (base_variable_type) 2691 { 2692 case Utils::VARIABLE_TYPE_DOUBLE: 2693 { 2694 if (de::abs(*double_value_ptr - (double)ref_value) > epsilon) 2695 { 2696 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using " 2697 "[" 2698 << Utils::getVariableTypeGLSLString(variable_type) << "]" 2699 << " argument/return types (" 2700 "expected:[" 2701 << ref_value << "], found:[" << *double_value_ptr << "])" 2702 << tcu::TestLog::EndMessage; 2703 2704 result = false; 2705 } 2706 2707 traveller_ptr += sizeof(double); 2708 break; 2709 } 2710 2711 case Utils::VARIABLE_TYPE_FLOAT: 2712 { 2713 if (de::abs(*float_value_ptr - (float)ref_value) > epsilon) 2714 { 2715 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using " 2716 "[" 2717 << Utils::getVariableTypeGLSLString(variable_type) << "]" 2718 << " argument/return types (" 2719 "expected:[" 2720 << ref_value << "], found:[" << *float_value_ptr << "])" 2721 << tcu::TestLog::EndMessage; 2722 2723 result = false; 2724 } 2725 2726 traveller_ptr += sizeof(float); 2727 break; 2728 } 2729 2730 case Utils::VARIABLE_TYPE_INT: 2731 case Utils::VARIABLE_TYPE_UINT: 2732 { 2733 if (*int_value_ptr != (int)ref_value) 2734 { 2735 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using " 2736 "[" 2737 << Utils::getVariableTypeGLSLString(variable_type) << "]" 2738 << " argument/return types (" 2739 "expected:[" 2740 << ref_value << "], found:[" << *int_value_ptr << "])" 2741 << tcu::TestLog::EndMessage; 2742 2743 result = false; 2744 } 2745 2746 traveller_ptr += sizeof(int); 2747 break; 2748 } 2749 2750 default: 2751 break; 2752 } /* switch (base_variable_type) */ 2753 } /* for (all components) */ 2754 } /* for (all reference values) */ 2755 } 2756 2757 return result; 2758} 2759 2760/** Constructor 2761 * 2762 * @param context CTS context 2763 **/ 2764FunctionalTest3_4::FunctionalTest3_4(deqp::Context& context) 2765 : TestCase(context, "four_subroutines_with_two_uniforms", "Verify Get* API and draw calls") 2766 , m_n_active_subroutine_uniforms(0) 2767 , m_n_active_subroutine_uniform_locations(0) 2768 , m_n_active_subroutines(0) 2769 , m_n_active_subroutine_uniform_name_length(0) 2770 , m_n_active_subroutine_name_length(0) 2771 , m_n_active_subroutine_uniform_size(0) 2772{ 2773 /* Nothing to be done here */ 2774} 2775 2776/** Execute test 2777 * 2778 * @return tcu::TestNode::STOP 2779 **/ 2780tcu::TestNode::IterateResult FunctionalTest3_4::iterate() 2781{ 2782 static const glw::GLchar* vertex_shader_code = 2783 "#version 400 core\n" 2784 "#extension GL_ARB_shader_subroutine : require\n" 2785 "\n" 2786 "precision highp float;\n" 2787 "\n" 2788 "// Sub routine type declaration\n" 2789 "subroutine vec4 routine_type(in vec4 iparam);\n" 2790 "\n" 2791 "// Sub routine definitions\n" 2792 "subroutine(routine_type) vec4 inverse_order(in vec4 iparam)\n" 2793 "{\n" 2794 " return iparam.wzyx;\n" 2795 "}\n" 2796 "\n" 2797 "subroutine(routine_type) vec4 negate(in vec4 iparam)\n" 2798 "{\n" 2799 " return -iparam;\n" 2800 "}\n" 2801 "\n" 2802 "subroutine(routine_type) vec4 inverse(in vec4 iparam)\n" 2803 "{\n" 2804 " return 1 / iparam;\n" 2805 "}\n" 2806 "\n" 2807 "subroutine(routine_type) vec4 square(in vec4 iparam)\n" 2808 "{\n" 2809 " return iparam * iparam;\n" 2810 "}\n" 2811 "\n" 2812 "// Sub routine uniforms\n" 2813 "subroutine uniform routine_type first_routine;\n" 2814 "subroutine uniform routine_type second_routine;\n" 2815 "\n" 2816 "// Input data\n" 2817 "uniform vec4 input_data;\n" 2818 "\n" 2819 "// Output\n" 2820 "out vec4 out_input_data;\n" 2821 "out vec4 out_result_from_first_routine;\n" 2822 "out vec4 out_result_from_second_routine;\n" 2823 "out vec4 out_result_from_combined_routines;\n" 2824 "out vec4 out_result_from_routines_combined_in_reveresed_order;\n" 2825 "\n" 2826 "void main()\n" 2827 "{\n" 2828 " out_input_data = input_data;\n" 2829 " out_result_from_first_routine = first_routine(input_data);\n" 2830 " out_result_from_second_routine = second_routine(input_data);\n" 2831 " out_result_from_combined_routines = second_routine(first_routine(input_data));\n" 2832 " out_result_from_routines_combined_in_reveresed_order = first_routine(second_routine(input_data));\n" 2833 "}\n" 2834 "\n"; 2835 2836 static const GLchar* varying_names[] = { 2837 "out_input_data", 2838 "out_result_from_first_routine", 2839 "out_result_from_second_routine", 2840 "out_result_from_combined_routines", 2841 "out_result_from_routines_combined_in_reveresed_order", 2842 }; 2843 2844 static const GLchar* subroutine_uniform_names[] = { "first_routine", "second_routine" }; 2845 2846 static const GLchar* subroutine_names[] = { "inverse_order", "negate", "inverse", "square" }; 2847 2848 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]); 2849 static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */; 2850 2851 static const GLuint inverse_order_routine_index = 0; 2852 static const GLuint negate_routine_index = 1; 2853 static const GLuint inverse_routine_index = 2; 2854 static const GLuint square_routine_index = 3; 2855 2856 /* Test data */ 2857 static const Utils::vec4<GLfloat> inverse_order_negate_data[5] = { 2858 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2859 Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), 2860 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), 2861 }; 2862 2863 static const Utils::vec4<GLfloat> inverse_order_inverse_data[5] = { 2864 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2865 Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f), 2866 Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f), 2867 }; 2868 2869 static const Utils::vec4<GLfloat> inverse_order_square_data[5] = { 2870 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2871 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), 2872 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), 2873 }; 2874 2875 static const Utils::vec4<GLfloat> negate_inverse_data[5] = { 2876 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2877 Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f), 2878 Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f), 2879 }; 2880 2881 static const Utils::vec4<GLfloat> negate_square_data[5] = { 2882 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), 2883 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), 2884 Utils::vec4<GLfloat>(-4.0f, -1.0f, -1.0f, -4.0f), 2885 }; 2886 2887 static const Utils::vec4<GLfloat> inverse_square_data[5] = { 2888 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), 2889 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f), 2890 Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f), 2891 }; 2892 2893 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 2894 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 2895 { 2896 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 2897 } 2898 2899 m_n_active_subroutine_uniforms = 2; 2900 m_n_active_subroutine_uniform_locations = 2; 2901 m_n_active_subroutines = 4; 2902 m_n_active_subroutine_uniform_name_length = 0; 2903 m_n_active_subroutine_name_length = 0; 2904 m_n_active_subroutine_uniform_size = 1; 2905 2906 /* GL objects */ 2907 Utils::program program(m_context); 2908 Utils::buffer transform_feedback_buffer(m_context); 2909 Utils::vertexArray vao(m_context); 2910 2911 bool result = true; 2912 2913 /* Calculate max name lengths for subroutines and subroutine uniforms */ 2914 for (GLint i = 0; i < m_n_active_subroutine_uniforms; ++i) 2915 { 2916 const GLsizei length = (GLsizei)strlen(subroutine_uniform_names[i]); 2917 2918 if (length > m_n_active_subroutine_uniform_name_length) 2919 { 2920 m_n_active_subroutine_uniform_name_length = length; 2921 } 2922 } 2923 2924 for (GLint i = 0; i < m_n_active_subroutines; ++i) 2925 { 2926 const GLsizei length = (GLsizei)strlen(subroutine_names[i]); 2927 2928 if (length > m_n_active_subroutine_name_length) 2929 { 2930 m_n_active_subroutine_name_length = length; 2931 } 2932 } 2933 2934 /* Init */ 2935 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names, 2936 n_varyings); 2937 2938 vao.generate(); 2939 vao.bind(); 2940 2941 transform_feedback_buffer.generate(); 2942 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 2943 GL_DYNAMIC_COPY); 2944 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 2945 2946 program.use(); 2947 2948 /* Inspect Get* API */ 2949 if ((false == inspectProgramStageiv(program.m_program_object_id)) || 2950 (false == inspectActiveSubroutineUniformiv(program.m_program_object_id, subroutine_uniform_names)) || 2951 (false == inspectActiveSubroutineUniformName(program.m_program_object_id, subroutine_uniform_names)) || 2952 (false == inspectActiveSubroutineName(program.m_program_object_id, subroutine_names)) || 2953 (false == 2954 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, false))) 2955 { 2956 result = false; 2957 } 2958 2959 /* Inspect GetProgram* API */ 2960 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query")) 2961 { 2962 if ((false == inspectProgramInterfaceiv(program.m_program_object_id)) || 2963 (false == 2964 inspectProgramResourceiv(program.m_program_object_id, subroutine_names, subroutine_uniform_names)) || 2965 (false == 2966 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, true))) 2967 { 2968 result = false; 2969 } 2970 } 2971 2972 /* Test shader execution */ 2973 if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 2974 subroutine_names[negate_routine_index], subroutine_uniform_names, inverse_order_negate_data, 2975 false)) || 2976 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 2977 subroutine_names[inverse_routine_index], subroutine_uniform_names, 2978 inverse_order_inverse_data, false)) || 2979 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 2980 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_order_square_data, 2981 false)) || 2982 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index], 2983 subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data, 2984 false)) || 2985 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index], 2986 subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data, 2987 false)) || 2988 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index], 2989 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data, 2990 false))) 2991 { 2992 result = false; 2993 } 2994 2995 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query")) 2996 { 2997 if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 2998 subroutine_names[negate_routine_index], subroutine_uniform_names, 2999 inverse_order_negate_data, true)) || 3000 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 3001 subroutine_names[inverse_routine_index], subroutine_uniform_names, 3002 inverse_order_inverse_data, true)) || 3003 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index], 3004 subroutine_names[square_routine_index], subroutine_uniform_names, 3005 inverse_order_square_data, true)) || 3006 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index], 3007 subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data, 3008 true)) || 3009 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index], 3010 subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data, 3011 true)) || 3012 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index], 3013 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data, 3014 true))) 3015 { 3016 result = false; 3017 } 3018 } 3019 3020 /* Done */ 3021 if (true == result) 3022 { 3023 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3024 } 3025 else 3026 { 3027 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3028 } 3029 3030 return tcu::TestNode::STOP; 3031} 3032 3033/** Verify result of getProgramStageiv 3034 * 3035 * @param program_id Program object id 3036 * @param pname <pname> parameter for getProgramStageiv 3037 * @param expected Expected value 3038 * 3039 * @return true if result is equal to expected value, flase otherwise 3040 **/ 3041bool FunctionalTest3_4::checkProgramStageiv(glw::GLuint program_id, glw::GLenum pname, glw::GLint expected) const 3042{ 3043 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3044 GLint value = 0; 3045 3046 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, pname, &value); 3047 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3048 3049 if (expected != value) 3050 { 3051 m_context.getTestContext().getLog() << tcu::TestLog::Message 3052 << "Error. Invalid result. Function: getProgramStageiv. " 3053 << "pname: " << Utils::pnameToStr(pname) << ". " 3054 << "Result: " << value << ". " 3055 << "Expected: " << expected << "." << tcu::TestLog::EndMessage; 3056 3057 return false; 3058 } 3059 else 3060 { 3061 return true; 3062 } 3063} 3064 3065/** Verify result of getProgramResourceiv 3066 * 3067 * @param program_id Program object id 3068 * @param program_interface Program interface 3069 * @param pname <pname> parameter for getProgramStageiv 3070 * @param resource_name Resource name 3071 * @param expected Expected value 3072 * 3073 * @return true if result is equal to expected value, false otherwise 3074 **/ 3075bool FunctionalTest3_4::checkProgramResourceiv(GLuint program_id, GLenum program_interface, GLenum pname, 3076 const glw::GLchar* resource_name, GLint expected) const 3077{ 3078 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3079 GLuint index = gl.getProgramResourceIndex(program_id, program_interface, resource_name); 3080 GLint value = 0; 3081 3082 if (GL_INVALID_INDEX == index) 3083 { 3084 return false; 3085 } 3086 3087 gl.getProgramResourceiv(program_id, program_interface, index, 1, &pname, 1, 0, &value); 3088 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceiv"); 3089 3090 if (expected != value) 3091 { 3092 m_context.getTestContext().getLog() 3093 << tcu::TestLog::Message << "Error. Invalid result. Function: getProgramResourceiv. " 3094 << "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". " 3095 << "Resource name: " << resource_name << ". " 3096 << "Property: " << Utils::pnameToStr(pname) << ". " 3097 << "Result: " << value << ". " 3098 << "Expected: " << expected << "." << tcu::TestLog::EndMessage; 3099 3100 return false; 3101 } 3102 else 3103 { 3104 return true; 3105 } 3106} 3107 3108/** Verify result of getProgramInterfaceiv 3109 * 3110 * @param program_id Program object id 3111 * @param program_interface Program interface 3112 * @param pname <pname> parameter for getProgramStageiv 3113 * @param expected Expected value 3114 * 3115 * @return true if result is equal to expected value, flase otherwise 3116 **/ 3117bool FunctionalTest3_4::checkProgramInterfaceiv(GLuint program_id, GLenum program_interface, GLenum pname, 3118 GLint expected) const 3119{ 3120 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3121 GLint value = 0; 3122 3123 gl.getProgramInterfaceiv(program_id, program_interface, pname, &value); 3124 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInterfaceiv"); 3125 3126 if (expected != value) 3127 { 3128 m_context.getTestContext().getLog() 3129 << tcu::TestLog::Message << "Error. Invalid result. Function: getProgramInterfaceiv. " 3130 << "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". " 3131 << "pname: " << Utils::pnameToStr(pname) << ". " 3132 << "Result: " << value << ". " 3133 << "Expected: " << expected << "." << tcu::TestLog::EndMessage; 3134 3135 return false; 3136 } 3137 else 3138 { 3139 return true; 3140 } 3141} 3142 3143/** Verify result of getActiveSubroutineUniformiv 3144 * 3145 * @param program_id Program object id 3146 * @param index <index> parameter for getActiveSubroutineUniformiv 3147 * @param pname <pname> parameter for getActiveSubroutineUniformiv 3148 * @param expected Expected value 3149 * 3150 * @return true if result is equal to expected value, flase otherwise 3151 **/ 3152bool FunctionalTest3_4::checkActiveSubroutineUniformiv(GLuint program_id, GLuint index, GLenum pname, 3153 GLint expected) const 3154{ 3155 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3156 GLint value = 0; 3157 3158 gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, index, pname, &value); 3159 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv"); 3160 3161 if (expected != value) 3162 { 3163 m_context.getTestContext().getLog() << tcu::TestLog::Message 3164 << "Error. Invalid result. Function: getActiveSubroutineUniformiv. " 3165 << "idnex: " << index << ". " 3166 << "pname: " << Utils::pnameToStr(pname) << ". " 3167 << "Result: " << value << ". " 3168 << "Expected: " << expected << "." << tcu::TestLog::EndMessage; 3169 3170 return false; 3171 } 3172 else 3173 { 3174 return true; 3175 } 3176} 3177 3178/** Returns index of program resource 3179 * 3180 * @param program_id Program object id 3181 * @param program_interface Program interface 3182 * @param resource_name Name of resource 3183 * 3184 * @return Index of specified resource 3185 **/ 3186GLuint FunctionalTest3_4::getProgramResourceIndex(GLuint program_id, GLenum program_interface, 3187 const glw::GLchar* resource_name) const 3188{ 3189 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3190 GLuint index = gl.getProgramResourceIndex(program_id, program_interface, resource_name); 3191 3192 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceIndex"); 3193 3194 if (GL_INVALID_INDEX == index) 3195 { 3196 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Program resource is not available. " 3197 << "Program interface: " << Utils::programInterfaceToStr(program_interface) 3198 << ". " 3199 << "Resource name: " << resource_name << "." << tcu::TestLog::EndMessage; 3200 } 3201 3202 return index; 3203} 3204 3205/** Get subroutine index 3206 * 3207 * @param program_id Program object id 3208 * @param subroutine_name Subroutine name 3209 * @param use_program_query If true getProgramResourceIndex is used, otherwise getSubroutineIndex 3210 * 3211 * @return Index of subroutine 3212 **/ 3213GLuint FunctionalTest3_4::getSubroutineIndex(GLuint program_id, const glw::GLchar* subroutine_name, 3214 bool use_program_query) const 3215{ 3216 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3217 GLuint index = -1; 3218 3219 if (false == use_program_query) 3220 { 3221 index = gl.getSubroutineIndex(program_id, GL_VERTEX_SHADER, subroutine_name); 3222 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex"); 3223 } 3224 else 3225 { 3226 index = gl.getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE, subroutine_name); 3227 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex"); 3228 } 3229 3230 if (GL_INVALID_INDEX == index) 3231 { 3232 TCU_FAIL("Subroutine is not available"); 3233 } 3234 3235 return index; 3236} 3237 3238/** Get subroutine uniform location 3239 * 3240 * @param program_id Program object id 3241 * @param uniform_name Subroutine uniform name 3242 * @param use_program_query If true getProgramResourceLocation is used, otherwise getSubroutineUniformLocation 3243 * 3244 * @return Location of subroutine uniform 3245 **/ 3246GLint FunctionalTest3_4::getSubroutineUniformLocation(GLuint program_id, const glw::GLchar* uniform_name, 3247 bool use_program_query) const 3248{ 3249 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3250 GLint location = -1; 3251 3252 if (false == use_program_query) 3253 { 3254 location = gl.getSubroutineUniformLocation(program_id, GL_VERTEX_SHADER, uniform_name); 3255 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation"); 3256 } 3257 else 3258 { 3259 location = gl.getProgramResourceLocation(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name); 3260 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceLocation"); 3261 } 3262 3263 if (-1 == location) 3264 { 3265 TCU_FAIL("Subroutine uniform is not available"); 3266 } 3267 3268 return location; 3269} 3270 3271/** Test if getProgramStageiv results are as expected 3272 * 3273 * @param program_id Program object id 3274 * 3275 * @result false in case of invalid result for any pname, true otherwise 3276 **/ 3277bool FunctionalTest3_4::inspectProgramStageiv(glw::GLuint program_id) const 3278{ 3279 bool result = true; 3280 3281 const inspectionDetails details[] = { 3282 { GL_ACTIVE_SUBROUTINE_UNIFORMS, m_n_active_subroutine_uniforms }, 3283 { GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, m_n_active_subroutine_uniform_locations }, 3284 { GL_ACTIVE_SUBROUTINES, m_n_active_subroutines }, 3285 { GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH, m_n_active_subroutine_uniform_name_length + 1 }, 3286 { GL_ACTIVE_SUBROUTINE_MAX_LENGTH, m_n_active_subroutine_name_length + 1 } 3287 }; 3288 const GLuint n_details = sizeof(details) / sizeof(details[0]); 3289 3290 for (GLuint i = 0; i < n_details; ++i) 3291 { 3292 if (false == checkProgramStageiv(program_id, details[i].pname, details[i].expected_value)) 3293 { 3294 result = false; 3295 } 3296 } 3297 3298 return result; 3299} 3300 3301/** Test if checkProgramInterfaceiv results are as expected 3302 * 3303 * @param program_id Program object id 3304 * 3305 * @result false in case of invalid result for any pname, true otherwise 3306 **/ 3307bool FunctionalTest3_4::inspectProgramInterfaceiv(glw::GLuint program_id) const 3308{ 3309 bool result = true; 3310 3311 const inspectionDetailsForProgramInterface details[] = { 3312 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, m_n_active_subroutine_uniforms }, 3313 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, m_n_active_subroutine_uniform_name_length + 1 }, 3314 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines }, 3315 { GL_VERTEX_SUBROUTINE, GL_ACTIVE_RESOURCES, m_n_active_subroutines }, 3316 { GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, m_n_active_subroutine_name_length + 1 } 3317 }; 3318 const GLuint n_details = sizeof(details) / sizeof(details[0]); 3319 3320 for (GLuint i = 0; i < n_details; ++i) 3321 { 3322 if (false == checkProgramInterfaceiv(program_id, details[i].program_interface, details[i].pname, 3323 details[i].expected_value)) 3324 { 3325 result = false; 3326 } 3327 } 3328 3329 return result; 3330} 3331 3332/** Test if checkProgramResourceiv results are as expected 3333 * 3334 * @param program_id Program object id 3335 * @param subroutine_names Array of subroutine names 3336 * @param uniform_names Array of uniform names 3337 * 3338 * @result false in case of invalid result for any pname, true otherwise 3339 **/ 3340bool FunctionalTest3_4::inspectProgramResourceiv(GLuint program_id, const GLchar** subroutine_names, 3341 const GLchar** uniform_names) const 3342{ 3343 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3344 bool result = true; 3345 3346 for (GLint subroutine = 0; subroutine < m_n_active_subroutines; ++subroutine) 3347 { 3348 const GLchar* subroutine_name = subroutine_names[subroutine]; 3349 const GLint length = (GLint)strlen(subroutine_name) + 1; 3350 3351 if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE, GL_NAME_LENGTH, subroutine_name, length)) 3352 { 3353 result = false; 3354 } 3355 } 3356 3357 inspectionDetails details[] = { 3358 { GL_NAME_LENGTH, 0 }, 3359 { GL_ARRAY_SIZE, 1 }, 3360 { GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines }, 3361 { GL_LOCATION, 0 }, 3362 }; 3363 const GLuint n_details = sizeof(details) / sizeof(details[0]); 3364 3365 for (GLint uniform = 0; uniform < m_n_active_subroutine_uniforms; ++uniform) 3366 { 3367 const GLchar* uniform_name = uniform_names[uniform]; 3368 const GLint length = (GLint)strlen(uniform_name) + 1; 3369 const GLint location = getSubroutineUniformLocation(program_id, uniform_name, true); 3370 3371 details[0].expected_value = length; 3372 details[3].expected_value = location; 3373 3374 for (GLuint i = 0; i < n_details; ++i) 3375 { 3376 if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, details[i].pname, 3377 uniform_name, details[i].expected_value)) 3378 { 3379 result = false; 3380 } 3381 } 3382 3383 /* Check compatible subroutines */ 3384 GLuint index = getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name); 3385 3386 if (GL_INVALID_INDEX != index) 3387 { 3388 std::vector<GLint> compatible_subroutines; 3389 GLint index_sum = 0; 3390 GLenum prop = GL_COMPATIBLE_SUBROUTINES; 3391 3392 compatible_subroutines.resize(m_n_active_subroutines); 3393 3394 gl.getProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, index, 1, &prop, m_n_active_subroutines, 3395 0, &compatible_subroutines[0]); 3396 3397 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv"); 3398 3399 /* Expected indices are 0, 1, 2, ... N */ 3400 for (GLint i = 0; i < m_n_active_subroutines; ++i) 3401 { 3402 index_sum += compatible_subroutines[i]; 3403 } 3404 3405 /* Sum of E1, ..., EN = (E1 + EN) * N / 2 */ 3406 if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum) 3407 { 3408 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 3409 3410 message << "Error. Invalid result. Function: getProgramResourceiv. " 3411 << "Program interface: GL_VERTEX_SUBROUTINE_UNIFORM. " 3412 << "Resource name: " << uniform_name << ". " 3413 << "Property: GL_COMPATIBLE_SUBROUTINES. " 3414 << "Results: "; 3415 3416 for (GLint i = 1; i < m_n_active_subroutines; ++i) 3417 { 3418 message << compatible_subroutines[i]; 3419 } 3420 3421 message << tcu::TestLog::EndMessage; 3422 3423 result = false; 3424 } 3425 } 3426 } 3427 3428 return result; 3429} 3430 3431/** Test if getActiveSubroutineUniformiv results are as expected 3432 * 3433 * @param program_id Program object id 3434 * @param uniform_names Array of subroutine uniform names available in program 3435 * 3436 * @result false in case of invalid result for any pname, true otherwise 3437 **/ 3438bool FunctionalTest3_4::inspectActiveSubroutineUniformiv(GLuint program_id, const GLchar** uniform_names) const 3439{ 3440 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3441 bool result = true; 3442 GLint n_active_subroutine_uniforms = 0; 3443 3444 inspectionDetails details[] = { 3445 { GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines }, 3446 { GL_UNIFORM_SIZE, m_n_active_subroutine_uniform_size }, 3447 { GL_UNIFORM_NAME_LENGTH, 0 }, 3448 }; 3449 const GLuint n_details = sizeof(details) / sizeof(details[0]); 3450 3451 /* Get amount of active subroutine uniforms */ 3452 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms); 3453 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3454 3455 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform) 3456 { 3457 GLint name_length = (GLint)strlen(uniform_names[uniform]); 3458 3459 details[2].expected_value = name_length + 1; 3460 3461 /* Checks from "details" */ 3462 for (GLuint i = 0; i < n_details; ++i) 3463 { 3464 if (false == 3465 checkActiveSubroutineUniformiv(program_id, uniform, details[i].pname, details[i].expected_value)) 3466 { 3467 result = false; 3468 } 3469 } 3470 3471 /* Check compatible subroutines */ 3472 std::vector<GLint> compatible_subroutines; 3473 compatible_subroutines.resize(m_n_active_subroutines); 3474 GLint index_sum = 0; 3475 3476 gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, uniform, GL_COMPATIBLE_SUBROUTINES, 3477 &compatible_subroutines[0]); 3478 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv"); 3479 3480 /* Expected indices are 0, 1, 2, ... N */ 3481 for (GLint i = 0; i < m_n_active_subroutines; ++i) 3482 { 3483 index_sum += compatible_subroutines[i]; 3484 } 3485 3486 /* Sum of E1, ..., EN = (E1 + EN) * N / 2 */ 3487 if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum) 3488 { 3489 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 3490 3491 message << "Error. Invalid result. Function: getActiveSubroutineUniformiv. idnex: " << uniform 3492 << ". pname: " << Utils::pnameToStr(GL_COMPATIBLE_SUBROUTINES) << ". Results: "; 3493 3494 for (GLint i = 1; i < m_n_active_subroutines; ++i) 3495 { 3496 message << compatible_subroutines[i]; 3497 } 3498 3499 message << tcu::TestLog::EndMessage; 3500 3501 result = false; 3502 } 3503 } 3504 3505 return result; 3506} 3507 3508/** Test if getActiveSubroutineUniformName results are as expected 3509 * 3510 * @param program_id Program object id 3511 * @param uniform_names Array of subroutine uniform names available in program 3512 * 3513 * @result false in case of invalid result, true otherwise 3514 **/ 3515bool FunctionalTest3_4::inspectActiveSubroutineUniformName(GLuint program_id, const GLchar** uniform_names) const 3516{ 3517 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3518 bool result = true; 3519 GLint n_active_subroutine_uniforms = 0; 3520 std::vector<GLchar> active_uniform_name; 3521 3522 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms); 3523 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3524 3525 active_uniform_name.resize(m_n_active_subroutine_uniform_name_length + 1); 3526 3527 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform) 3528 { 3529 bool is_name_ok = false; 3530 3531 gl.getActiveSubroutineUniformName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_uniform_name.size(), 3532 0 /* length */, &active_uniform_name[0]); 3533 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveSubroutineUniformName"); 3534 3535 for (GLint name = 0; name < n_active_subroutine_uniforms; ++name) 3536 { 3537 if (0 == strcmp(uniform_names[name], &active_uniform_name[0])) 3538 { 3539 is_name_ok = true; 3540 break; 3541 } 3542 } 3543 3544 if (false == is_name_ok) 3545 { 3546 m_context.getTestContext().getLog() 3547 << tcu::TestLog::Message 3548 << "Error. Invalid result. Function: getActiveSubroutineUniformName. idnex: " << uniform 3549 << ". Result: " << &active_uniform_name[0] << tcu::TestLog::EndMessage; 3550 3551 result = false; 3552 break; 3553 } 3554 } 3555 3556 return result; 3557} 3558 3559/** Test if getActiveSubroutineUniformName results are as expected 3560 * 3561 * @param program_id Program object id 3562 * @param subroutine_names Array of subroutine names available in program 3563 * 3564 * @result false in case of invalid result, true otherwise 3565 **/ 3566bool FunctionalTest3_4::inspectActiveSubroutineName(GLuint program_id, const GLchar** subroutine_names) const 3567{ 3568 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3569 bool result = true; 3570 GLint n_active_subroutines = 0; 3571 std::vector<GLchar> active_subroutine_name; 3572 3573 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines); 3574 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3575 3576 active_subroutine_name.resize(m_n_active_subroutine_name_length + 1); 3577 3578 for (GLint uniform = 0; uniform < n_active_subroutines; ++uniform) 3579 { 3580 bool is_name_ok = false; 3581 3582 gl.getActiveSubroutineName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_subroutine_name.size(), 3583 0 /* length */, &active_subroutine_name[0]); 3584 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineName"); 3585 3586 for (GLint name = 0; name < n_active_subroutines; ++name) 3587 { 3588 if (0 == strcmp(subroutine_names[name], &active_subroutine_name[0])) 3589 { 3590 is_name_ok = true; 3591 break; 3592 } 3593 } 3594 3595 if (false == is_name_ok) 3596 { 3597 m_context.getTestContext().getLog() 3598 << tcu::TestLog::Message 3599 << "Error. Invalid result. Function: getActiveSubroutineName. idnex: " << uniform 3600 << ". Result: " << &active_subroutine_name[0] << tcu::TestLog::EndMessage; 3601 3602 result = false; 3603 break; 3604 } 3605 } 3606 3607 return result; 3608} 3609 3610/** Test if it is possible to "bind" all subroutines uniforms with all subroutines 3611 * 3612 * @param program_id Program object id 3613 * @param subroutine_names Array of subroutine names available in program 3614 * @param uniform_names Array of subroutine uniform names available in program 3615 * 3616 * @result false in case of invalid result, true otherwise 3617 **/ 3618bool FunctionalTest3_4::inspectSubroutineBinding(GLuint program_id, const GLchar** subroutine_names, 3619 const GLchar** uniform_names, bool use_program_query) const 3620{ 3621 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3622 bool result = true; 3623 GLint n_active_subroutines = 0; 3624 GLint n_active_subroutine_uniforms = 0; 3625 std::vector<GLuint> subroutine_uniforms; 3626 GLuint queried_subroutine_index = 0; 3627 3628 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines); 3629 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3630 3631 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms); 3632 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv"); 3633 3634 subroutine_uniforms.resize(n_active_subroutine_uniforms); 3635 3636 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform) 3637 { 3638 GLuint uniform_location = getSubroutineUniformLocation(program_id, uniform_names[uniform], use_program_query); 3639 3640 for (GLint routine = 0; routine < n_active_subroutines; ++routine) 3641 { 3642 GLuint routine_index = getSubroutineIndex(program_id, subroutine_names[routine], use_program_query); 3643 3644 subroutine_uniforms[uniform] = routine_index; 3645 3646 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_active_subroutine_uniforms, &subroutine_uniforms[0]); 3647 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 3648 3649 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, uniform_location, &queried_subroutine_index); 3650 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv"); 3651 3652 if (queried_subroutine_index != routine_index) 3653 { 3654 m_context.getTestContext().getLog() 3655 << tcu::TestLog::Message << "Error. Invalid result. Function: gl.getUniformSubroutineuiv." 3656 << " Subroutine uniform: " << uniform << ", name: " << uniform_names[uniform] 3657 << ", location: " << uniform_location << ". Subroutine: " << routine 3658 << ", name: " << subroutine_names[routine] << ", index: " << routine_index 3659 << ". Result: " << queried_subroutine_index << tcu::TestLog::EndMessage; 3660 3661 result = false; 3662 } 3663 } 3664 } 3665 3666 return result; 3667} 3668 3669/** Execute draw call and verify results 3670 * 3671 * @param program_id Program object id 3672 * @param first_routine_name Name of subroutine that shall be used aas first_routine 3673 * @param second_routine_name Name of subroutine that shall be used aas second_routine 3674 * @param uniform_names Name of uniforms 3675 * @param expected_results Test data. [0] is used as input data. All are used as expected_results 3676 * @param use_program_query If true GetProgram* API will be used 3677 * 3678 * @return false in case of invalid result, true otherwise 3679 **/ 3680bool FunctionalTest3_4::testDraw(GLuint program_id, const GLchar* first_routine_name, const GLchar* second_routine_name, 3681 const GLchar** uniform_names, const Utils::vec4<GLfloat> expected_results[5], 3682 bool use_program_query) const 3683{ 3684 static const GLuint n_varyings = 5; 3685 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3686 bool result = true; 3687 GLuint subroutine_uniforms[2] = { 0 }; 3688 3689 /* Get subroutine uniform locations */ 3690 GLint first_routine_location = getSubroutineUniformLocation(program_id, uniform_names[0], use_program_query); 3691 3692 GLint second_routine_location = getSubroutineUniformLocation(program_id, uniform_names[1], use_program_query); 3693 3694 /* Get subroutine indices */ 3695 GLuint first_routine_index = getSubroutineIndex(program_id, first_routine_name, use_program_query); 3696 3697 GLuint second_routine_index = getSubroutineIndex(program_id, second_routine_name, use_program_query); 3698 3699 /* Map uniforms with subroutines */ 3700 subroutine_uniforms[first_routine_location] = first_routine_index; 3701 subroutine_uniforms[second_routine_location] = second_routine_index; 3702 3703 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 2 /* number of uniforms */, &subroutine_uniforms[0]); 3704 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 3705 3706 /* Get location of input_data */ 3707 GLint input_data_location = gl.getUniformLocation(program_id, "input_data"); 3708 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation"); 3709 3710 if (-1 == input_data_location) 3711 { 3712 TCU_FAIL("Uniform is not available"); 3713 } 3714 3715 /* Set up input_data */ 3716 gl.uniform4f(input_data_location, expected_results[0].m_x, expected_results[0].m_y, expected_results[0].m_z, 3717 expected_results[0].m_w); 3718 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 3719 3720 /* Execute draw call with transform feedback */ 3721 gl.beginTransformFeedback(GL_POINTS); 3722 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 3723 3724 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 3725 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 3726 3727 gl.endTransformFeedback(); 3728 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 3729 3730 /* Verify results */ 3731 GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 3732 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 3733 3734 Utils::vec4<GLfloat> results[5]; 3735 3736 results[0].m_x = feedback_data[0]; 3737 results[0].m_y = feedback_data[1]; 3738 results[0].m_z = feedback_data[2]; 3739 results[0].m_w = feedback_data[3]; 3740 3741 results[1].m_x = feedback_data[4]; 3742 results[1].m_y = feedback_data[5]; 3743 results[1].m_z = feedback_data[6]; 3744 results[1].m_w = feedback_data[7]; 3745 3746 results[2].m_x = feedback_data[8]; 3747 results[2].m_y = feedback_data[9]; 3748 results[2].m_z = feedback_data[10]; 3749 results[2].m_w = feedback_data[11]; 3750 3751 results[3].m_x = feedback_data[12]; 3752 results[3].m_y = feedback_data[13]; 3753 results[3].m_z = feedback_data[14]; 3754 results[3].m_w = feedback_data[15]; 3755 3756 results[4].m_x = feedback_data[16]; 3757 results[4].m_y = feedback_data[17]; 3758 results[4].m_z = feedback_data[18]; 3759 results[4].m_w = feedback_data[19]; 3760 3761 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3762 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 3763 3764 for (GLuint i = 0; i < n_varyings; ++i) 3765 { 3766 result = result && (results[i] == expected_results[i]); 3767 } 3768 3769 if (false == result) 3770 { 3771 m_context.getTestContext().getLog() << tcu::TestLog::Message 3772 << "Error. Invalid result. First routine: " << first_routine_name 3773 << ". Second routine: " << second_routine_name << tcu::TestLog::EndMessage; 3774 3775 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 3776 3777 message << "Results:"; 3778 3779 for (GLuint i = 0; i < n_varyings; ++i) 3780 { 3781 results[i].log(message); 3782 } 3783 3784 message << tcu::TestLog::EndMessage; 3785 3786 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 3787 3788 message << "Expected:"; 3789 3790 for (GLuint i = 0; i < n_varyings; ++i) 3791 { 3792 expected_results[i].log(message); 3793 } 3794 3795 message << tcu::TestLog::EndMessage; 3796 } 3797 3798 return result; 3799} 3800 3801/** Constructor 3802 * 3803 * @param context CTS context 3804 **/ 3805FunctionalTest5::FunctionalTest5(deqp::Context& context) 3806 : TestCase(context, "eight_subroutines_four_uniforms", "Verify multiple subroutine sets") 3807{ 3808} 3809 3810/** Execute test 3811 * 3812 * @return tcu::TestNode::STOP 3813 **/ 3814tcu::TestNode::IterateResult FunctionalTest5::iterate() 3815{ 3816 static const GLchar* vertex_shader_code = 3817 "#version 400 core\n" 3818 "#extension GL_ARB_shader_subroutine : require\n" 3819 "\n" 3820 "precision highp float;\n" 3821 "\n" 3822 "// Subroutine types\n" 3823 "subroutine vec4 routine_type_1(in vec4 left, in vec4 right);\n" 3824 "subroutine vec4 routine_type_2(in vec4 iparam);\n" 3825 "subroutine vec4 routine_type_3(in vec4 a, in vec4 b, in vec4 c);\n" 3826 "subroutine bvec4 routine_type_4(in vec4 left, in vec4 right);\n" 3827 "\n" 3828 "// Subroutine definitions\n" 3829 "// 1st type\n" 3830 "subroutine(routine_type_1) vec4 add(in vec4 left, in vec4 right)\n" 3831 "{\n" 3832 " return left + right;\n" 3833 "}\n" 3834 "\n" 3835 "subroutine(routine_type_1) vec4 subtract(in vec4 left, in vec4 right)\n" 3836 "{\n" 3837 " return left - right;\n" 3838 "}\n" 3839 "\n" 3840 "// 2nd type\n" 3841 "subroutine(routine_type_2) vec4 square(in vec4 iparam)\n" 3842 "{\n" 3843 " return iparam * iparam;\n" 3844 "}\n" 3845 "\n" 3846 "subroutine(routine_type_2) vec4 square_root(in vec4 iparam)\n" 3847 "{\n" 3848 " return sqrt(iparam);\n" 3849 "}\n" 3850 "\n" 3851 "// 3rd type\n" 3852 "subroutine(routine_type_3) vec4 do_fma(in vec4 a, in vec4 b, in vec4 c)\n" 3853 "{\n" 3854 " return fma(a, b, c);\n" 3855 "}\n" 3856 "\n" 3857 "subroutine(routine_type_3) vec4 blend(in vec4 a, in vec4 b, in vec4 c)\n" 3858 "{\n" 3859 " return c * a + (vec4(1) - c) * b;\n" 3860 "}\n" 3861 "\n" 3862 "// 4th type\n" 3863 "subroutine(routine_type_4) bvec4 are_equal(in vec4 left, in vec4 right)\n" 3864 "{\n" 3865 " return equal(left, right);\n" 3866 "}\n" 3867 "\n" 3868 "subroutine(routine_type_4) bvec4 are_greater(in vec4 left, in vec4 right)\n" 3869 "{\n" 3870 " return greaterThan(left, right);\n" 3871 "}\n" 3872 "\n" 3873 "// Sub routine uniforms\n" 3874 "subroutine uniform routine_type_1 first_routine;\n" 3875 "subroutine uniform routine_type_2 second_routine;\n" 3876 "subroutine uniform routine_type_3 third_routine;\n" 3877 "subroutine uniform routine_type_4 fourth_routine;\n" 3878 "\n" 3879 "// Input data\n" 3880 "uniform vec4 first_input;\n" 3881 "uniform vec4 second_input;\n" 3882 "uniform vec4 third_input;\n" 3883 "\n" 3884 "// Output\n" 3885 "out vec4 out_result_from_first_routine;\n" 3886 "out vec4 out_result_from_second_routine;\n" 3887 "out vec4 out_result_from_third_routine;\n" 3888 "out uvec4 out_result_from_fourth_routine;\n" 3889 "\n" 3890 "void main()\n" 3891 "{\n" 3892 " out_result_from_first_routine = first_routine (first_input, second_input);\n" 3893 " out_result_from_second_routine = second_routine(first_input);\n" 3894 " out_result_from_third_routine = third_routine (first_input, second_input, third_input);\n" 3895 " out_result_from_fourth_routine = uvec4(fourth_routine(first_input, second_input));\n" 3896 "}\n" 3897 "\n"; 3898 3899 static const GLchar* subroutine_names[4][2] = { 3900 { "add", "subtract" }, { "square", "square_root" }, { "do_fma", "blend" }, { "are_equal", "are_greater" } 3901 }; 3902 3903 static const GLchar* subroutine_uniform_names[4][1] = { 3904 { "first_routine" }, { "second_routine" }, { "third_routine" }, { "fourth_routine" } 3905 }; 3906 3907 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 3908 static const GLuint n_subroutines_per_type = sizeof(subroutine_names[0]) / sizeof(subroutine_names[0][0]); 3909 static const GLuint n_subroutine_uniforms_per_type = 3910 sizeof(subroutine_uniform_names[0]) / sizeof(subroutine_uniform_names[0][0]); 3911 3912 static const GLchar* uniform_names[] = { "first_input", "second_input", "third_input" }; 3913 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]); 3914 3915 static const GLchar* varying_names[] = { "out_result_from_first_routine", "out_result_from_second_routine", 3916 "out_result_from_third_routine", "out_result_from_fourth_routine" }; 3917 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]); 3918 static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */; 3919 3920 /* Test data */ 3921 static const Utils::vec4<GLfloat> input_data[3] = { Utils::vec4<GLfloat>(1.0f, 4.0f, 9.0f, 16.0f), 3922 Utils::vec4<GLfloat>(16.0f, 9.0f, 4.0f, 1.0f), 3923 Utils::vec4<GLfloat>(0.25f, 0.5f, 0.75f, 1.0f) }; 3924 3925 static const Utils::vec4<GLfloat> expected_result_from_first_routine[2] = { 3926 Utils::vec4<GLfloat>(17.0f, 13.0f, 13.0f, 17.0f), Utils::vec4<GLfloat>(-15.0f, -5.0f, 5.0f, 15.0f) 3927 }; 3928 3929 static const Utils::vec4<GLfloat> expected_result_from_second_routine[2] = { 3930 Utils::vec4<GLfloat>(1.0f, 16.0f, 81.0f, 256.0f), Utils::vec4<GLfloat>(1.0f, 2.0f, 3.0f, 4.0f) 3931 }; 3932 3933 static const Utils::vec4<GLfloat> expected_result_from_third_routine[2] = { 3934 Utils::vec4<GLfloat>(16.25f, 36.5f, 36.75f, 17.0f), Utils::vec4<GLfloat>(12.25f, 6.5f, 7.75f, 16.0f) 3935 }; 3936 3937 static const Utils::vec4<GLuint> expected_result_from_fourth_routine[2] = { Utils::vec4<GLuint>(0, 0, 0, 0), 3938 Utils::vec4<GLuint>(0, 0, 1, 1) }; 3939 3940 /* All combinations of subroutines */ 3941 static const GLuint subroutine_combinations[][4] = { 3942 { 0, 0, 0, 0 }, { 0, 0, 0, 1 }, { 0, 0, 1, 0 }, { 0, 0, 1, 1 }, { 0, 1, 0, 0 }, { 0, 1, 0, 1 }, 3943 { 0, 1, 1, 0 }, { 0, 1, 1, 1 }, { 1, 0, 0, 0 }, { 1, 0, 0, 1 }, { 1, 0, 1, 0 }, { 1, 0, 1, 1 }, 3944 { 1, 1, 0, 0 }, { 1, 1, 0, 1 }, { 1, 1, 1, 0 }, { 1, 1, 1, 1 } 3945 }; 3946 static const GLuint n_subroutine_combinations = 3947 sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]); 3948 3949 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 3950 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 3951 { 3952 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 3953 } 3954 3955 /* Result */ 3956 bool result = true; 3957 3958 /* GL objects */ 3959 Utils::program program(m_context); 3960 Utils::buffer transform_feedback_buffer(m_context); 3961 Utils::vertexArray vao(m_context); 3962 3963 /* Init GL objects */ 3964 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names, 3965 n_varyings); 3966 3967 program.use(); 3968 3969 vao.generate(); 3970 vao.bind(); 3971 3972 transform_feedback_buffer.generate(); 3973 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 3974 GL_DYNAMIC_COPY); 3975 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 3976 3977 /* Get subroutine uniform locations and subroutine indices */ 3978 for (GLuint type = 0; type < n_subroutine_types; ++type) 3979 { 3980 for (GLuint uniform = 0; uniform < n_subroutine_uniforms_per_type; ++uniform) 3981 { 3982 m_subroutine_uniform_locations[type][uniform] = 3983 program.getSubroutineUniformLocation(subroutine_uniform_names[type][uniform], GL_VERTEX_SHADER); 3984 } 3985 3986 for (GLuint routine = 0; routine < n_subroutines_per_type; ++routine) 3987 { 3988 m_subroutine_indices[type][routine] = 3989 program.getSubroutineIndex(subroutine_names[type][routine], GL_VERTEX_SHADER); 3990 } 3991 } 3992 3993 /* Get uniform locations */ 3994 for (GLuint i = 0; i < n_uniform_names; ++i) 3995 { 3996 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]); 3997 } 3998 3999 /* Draw with each routine combination */ 4000 for (GLuint i = 0; i < n_subroutine_combinations; ++i) 4001 { 4002 Utils::vec4<GLfloat> first_routine_result; 4003 Utils::vec4<GLfloat> second_routine_result; 4004 Utils::vec4<GLfloat> third_routine_result; 4005 Utils::vec4<GLuint> fourth_routine_result; 4006 4007 testDraw(subroutine_combinations[i], input_data, first_routine_result, second_routine_result, 4008 third_routine_result, fourth_routine_result); 4009 4010 if (false == verify(first_routine_result, second_routine_result, third_routine_result, fourth_routine_result, 4011 expected_result_from_first_routine[subroutine_combinations[i][0]], 4012 expected_result_from_second_routine[subroutine_combinations[i][1]], 4013 expected_result_from_third_routine[subroutine_combinations[i][2]], 4014 expected_result_from_fourth_routine[subroutine_combinations[i][3]])) 4015 { 4016 logError(subroutine_names, subroutine_combinations[i], input_data, first_routine_result, 4017 second_routine_result, third_routine_result, fourth_routine_result, 4018 expected_result_from_first_routine[subroutine_combinations[i][0]], 4019 expected_result_from_second_routine[subroutine_combinations[i][1]], 4020 expected_result_from_third_routine[subroutine_combinations[i][2]], 4021 expected_result_from_fourth_routine[subroutine_combinations[i][3]]); 4022 4023 result = false; 4024 } 4025 } 4026 4027 /* Done */ 4028 if (true == result) 4029 { 4030 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4031 } 4032 else 4033 { 4034 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4035 } 4036 4037 return tcu::TestNode::STOP; 4038} 4039 4040/** Log error message 4041 * 4042 * @param subroutine_names Array of subroutine names 4043 * @param subroutine_combination Combination of subroutines 4044 * @param input_data Input data 4045 * @param first_routine_result Result of first routine 4046 * @param second_routine_result Result of second routine 4047 * @param third_routine_result Result of third routine 4048 * @param fourth_routine_result Result of fourth routine 4049 * @param first_routine_expected_result Expected result of first routine 4050 * @param second_routine_expected_result Expected result of second routine 4051 * @param third_routine_expected_result Expected result of third routine 4052 * @param fourth_routine_expected_result Expected result of fourth routine 4053 **/ 4054void FunctionalTest5::logError(const glw::GLchar* subroutine_names[4][2], const glw::GLuint subroutine_combination[4], 4055 const Utils::vec4<glw::GLfloat> input_data[3], 4056 const Utils::vec4<glw::GLfloat>& first_routine_result, 4057 const Utils::vec4<glw::GLfloat>& second_routine_result, 4058 const Utils::vec4<glw::GLfloat>& third_routine_result, 4059 const Utils::vec4<glw::GLuint>& fourth_routine_result, 4060 const Utils::vec4<glw::GLfloat>& first_routine_expected_result, 4061 const Utils::vec4<glw::GLfloat>& second_routine_expected_result, 4062 const Utils::vec4<glw::GLfloat>& third_routine_expected_result, 4063 const Utils::vec4<glw::GLuint>& fourth_routine_expected_result) const 4064{ 4065 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 4066 << tcu::TestLog::EndMessage; 4067 4068 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4069 4070 message << "Function: " << subroutine_names[0][subroutine_combination[0]] << "( "; 4071 input_data[0].log(message); 4072 message << ", "; 4073 input_data[1].log(message); 4074 message << " ). Result: "; 4075 first_routine_result.log(message); 4076 message << ". Expected: "; 4077 first_routine_expected_result.log(message); 4078 4079 message << tcu::TestLog::EndMessage; 4080 4081 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4082 4083 message << "Function: " << subroutine_names[1][subroutine_combination[1]] << "( "; 4084 input_data[0].log(message); 4085 message << " ). Result: "; 4086 second_routine_result.log(message); 4087 message << ". Expected: "; 4088 second_routine_expected_result.log(message); 4089 4090 message << tcu::TestLog::EndMessage; 4091 4092 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4093 4094 message << "Function: " << subroutine_names[2][subroutine_combination[2]] << "( "; 4095 input_data[0].log(message); 4096 message << ", "; 4097 input_data[1].log(message); 4098 message << ", "; 4099 input_data[2].log(message); 4100 message << "). Result: "; 4101 third_routine_result.log(message); 4102 message << ". Expected: "; 4103 third_routine_expected_result.log(message); 4104 4105 message << tcu::TestLog::EndMessage; 4106 4107 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4108 4109 message << "Function: " << subroutine_names[3][subroutine_combination[3]] << "( "; 4110 input_data[0].log(message); 4111 message << ", "; 4112 input_data[1].log(message); 4113 message << ", "; 4114 message << " ). Result: "; 4115 fourth_routine_result.log(message); 4116 message << ". Expected: "; 4117 fourth_routine_expected_result.log(message); 4118 4119 message << tcu::TestLog::EndMessage; 4120} 4121 4122/** Execute draw call and capture results 4123 * 4124 * @param subroutine_combination Combination of subroutines 4125 * @param input_data Input data 4126 * @param out_first_routine_result Result of first routine 4127 * @param out_second_routine_result Result of second routine 4128 * @param out_third_routine_result Result of third routine 4129 * @param out_fourth_routine_result Result of fourth routine 4130 **/ 4131void FunctionalTest5::testDraw(const glw::GLuint subroutine_combination[4], 4132 const Utils::vec4<glw::GLfloat> input_data[3], 4133 Utils::vec4<glw::GLfloat>& out_first_routine_result, 4134 Utils::vec4<glw::GLfloat>& out_second_routine_result, 4135 Utils::vec4<glw::GLfloat>& out_third_routine_result, 4136 Utils::vec4<glw::GLuint>& out_fourth_routine_result) const 4137{ 4138 static const GLuint n_uniforms = sizeof(m_uniform_locations) / sizeof(m_uniform_locations[0]); 4139 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4140 GLuint subroutine_indices[4]; 4141 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 4142 4143 /* Prepare subroutine uniform data */ 4144 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 4145 { 4146 const GLuint location = m_subroutine_uniform_locations[i][0]; 4147 4148 subroutine_indices[location] = m_subroutine_indices[i][subroutine_combination[i]]; 4149 } 4150 4151 /* Set up subroutine uniforms */ 4152 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]); 4153 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 4154 4155 /* Set up input data uniforms */ 4156 for (GLuint i = 0; i < n_uniforms; ++i) 4157 { 4158 gl.uniform4f(m_uniform_locations[i], input_data[i].m_x, input_data[i].m_y, input_data[i].m_z, 4159 input_data[i].m_w); 4160 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 4161 } 4162 4163 /* Execute draw call with transform feedback */ 4164 gl.beginTransformFeedback(GL_POINTS); 4165 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 4166 4167 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 4168 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 4169 4170 gl.endTransformFeedback(); 4171 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 4172 4173 /* Capture results */ 4174 GLvoid* feedback_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 4175 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4176 4177 GLfloat* float_ptr = (GLfloat*)feedback_data; 4178 4179 /* First result */ 4180 out_first_routine_result.m_x = float_ptr[0]; 4181 out_first_routine_result.m_y = float_ptr[1]; 4182 out_first_routine_result.m_z = float_ptr[2]; 4183 out_first_routine_result.m_w = float_ptr[3]; 4184 4185 /* Second result */ 4186 out_second_routine_result.m_x = float_ptr[4]; 4187 out_second_routine_result.m_y = float_ptr[5]; 4188 out_second_routine_result.m_z = float_ptr[6]; 4189 out_second_routine_result.m_w = float_ptr[7]; 4190 4191 /* Third result */ 4192 out_third_routine_result.m_x = float_ptr[8]; 4193 out_third_routine_result.m_y = float_ptr[9]; 4194 out_third_routine_result.m_z = float_ptr[10]; 4195 out_third_routine_result.m_w = float_ptr[11]; 4196 4197 /* Fourth result */ 4198 GLuint* uint_ptr = (GLuint*)(float_ptr + 12); 4199 out_fourth_routine_result.m_x = uint_ptr[0]; 4200 out_fourth_routine_result.m_y = uint_ptr[1]; 4201 out_fourth_routine_result.m_z = uint_ptr[2]; 4202 out_fourth_routine_result.m_w = uint_ptr[3]; 4203 4204 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4205 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 4206} 4207 4208/** Verify if results match expected results 4209 * 4210 * @param first_routine_result Result of first routine 4211 * @param second_routine_result Result of second routine 4212 * @param third_routine_result Result of third routine 4213 * @param fourth_routine_result Result of fourth routine 4214 * @param first_routine_expected_result Expected result of first routine 4215 * @param second_routine_expected_result Expected result of second routine 4216 * @param third_routine_expected_result Expected result of third routine 4217 * @param fourth_routine_expected_result Expected result of fourth routine 4218 **/ 4219bool FunctionalTest5::verify(const Utils::vec4<glw::GLfloat>& first_routine_result, 4220 const Utils::vec4<glw::GLfloat>& second_routine_result, 4221 const Utils::vec4<glw::GLfloat>& third_routine_result, 4222 const Utils::vec4<glw::GLuint>& fourth_routine_result, 4223 const Utils::vec4<glw::GLfloat>& first_routine_expected_result, 4224 const Utils::vec4<glw::GLfloat>& second_routine_expected_result, 4225 const Utils::vec4<glw::GLfloat>& third_routine_expected_result, 4226 const Utils::vec4<glw::GLuint>& fourth_routine_expected_result) const 4227{ 4228 bool result = true; 4229 4230 result = result && (first_routine_result == first_routine_expected_result); 4231 result = result && (second_routine_result == second_routine_expected_result); 4232 result = result && (third_routine_result == third_routine_expected_result); 4233 result = result && (fourth_routine_result == fourth_routine_expected_result); 4234 4235 return result; 4236} 4237 4238/** Constructor 4239 * 4240 * @param context CTS context 4241 **/ 4242FunctionalTest6::FunctionalTest6(deqp::Context& context) 4243 : TestCase(context, "static_subroutine_call", "Verify that subroutine can be called in a static manner") 4244{ 4245} 4246 4247/** Execute test 4248 * 4249 * @return tcu::TestNode::STOP 4250 **/ 4251tcu::TestNode::IterateResult FunctionalTest6::iterate() 4252{ 4253 static const GLchar* vertex_shader_code = "#version 400 core\n" 4254 "#extension GL_ARB_shader_subroutine : require\n" 4255 "\n" 4256 "precision highp float;\n" 4257 "\n" 4258 "// Subroutine type\n" 4259 "subroutine vec4 routine_type(in vec4 iparam);\n" 4260 "\n" 4261 "// Subroutine definition\n" 4262 "subroutine(routine_type) vec4 square(in vec4 iparam)\n" 4263 "{\n" 4264 " return iparam * iparam;\n" 4265 "}\n" 4266 "\n" 4267 "// Sub routine uniform\n" 4268 "subroutine uniform routine_type routine;\n" 4269 "\n" 4270 "// Input data\n" 4271 "uniform vec4 input_data;\n" 4272 "\n" 4273 "// Output\n" 4274 "out vec4 out_result;\n" 4275 "\n" 4276 "void main()\n" 4277 "{\n" 4278 " out_result = square(input_data);\n" 4279 "}\n" 4280 "\n"; 4281 4282 static const GLchar* varying_name = "out_result"; 4283 4284 /* Test data */ 4285 static const Utils::vec4<GLfloat> input_data(1.0f, 4.0f, 9.0f, 16.0f); 4286 4287 static const Utils::vec4<GLfloat> expected_result(1.0f, 16.0f, 81.0f, 256.0f); 4288 4289 static const GLuint transform_feedback_buffer_size = 4 * sizeof(GLfloat); 4290 4291 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 4292 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 4293 { 4294 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 4295 } 4296 4297 /* GL objects */ 4298 Utils::program program(m_context); 4299 Utils::buffer transform_feedback_buffer(m_context); 4300 Utils::vertexArray vao(m_context); 4301 4302 /* Init GL objects */ 4303 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name, 4304 1 /* n_varyings */); 4305 4306 program.use(); 4307 4308 vao.generate(); 4309 vao.bind(); 4310 4311 transform_feedback_buffer.generate(); 4312 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 4313 GL_DYNAMIC_COPY); 4314 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 4315 4316 /* Test */ 4317 { 4318 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4319 const GLint uniform_location = gl.getUniformLocation(program.m_program_object_id, "input_data"); 4320 4321 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation"); 4322 4323 if (-1 == uniform_location) 4324 { 4325 TCU_FAIL("Uniform is not available"); 4326 } 4327 4328 /* Set up input data uniforms */ 4329 gl.uniform4f(uniform_location, input_data.m_x, input_data.m_y, input_data.m_z, input_data.m_w); 4330 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 4331 4332 /* Execute draw call with transform feedback */ 4333 gl.beginTransformFeedback(GL_POINTS); 4334 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 4335 4336 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 4337 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 4338 4339 gl.endTransformFeedback(); 4340 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 4341 4342 /* Capture results */ 4343 GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 4344 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4345 4346 Utils::vec4<GLfloat> result(feedback_data[0], feedback_data[1], feedback_data[2], feedback_data[3]); 4347 4348 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4349 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 4350 4351 /* Verify */ 4352 if (expected_result == result) 4353 { 4354 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4355 } 4356 else 4357 { 4358 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 4359 << tcu::TestLog::EndMessage; 4360 4361 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4362 4363 message << "Function: square( "; 4364 input_data.log(message); 4365 message << " ). Result: "; 4366 result.log(message); 4367 message << ". Expected: "; 4368 expected_result.log(message); 4369 4370 message << tcu::TestLog::EndMessage; 4371 4372 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4373 } 4374 } 4375 4376 /* Done */ 4377 return tcu::TestNode::STOP; 4378} 4379 4380/** Constructor 4381 * 4382 * @param context CTS context 4383 **/ 4384FunctionalTest7_8::FunctionalTest7_8(deqp::Context& context) 4385 : TestCase(context, "arrayed_subroutine_uniforms", "Verify that subroutine can be called in a static manner") 4386{ 4387} 4388 4389/** Execute test 4390 * 4391 * @return tcu::TestNode::STOP 4392 **/ 4393tcu::TestNode::IterateResult FunctionalTest7_8::iterate() 4394{ 4395 static const GLchar* vertex_shader_code = 4396 "#version 400 core\n" 4397 "#extension GL_ARB_shader_subroutine : require\n" 4398 "\n" 4399 "precision highp float;\n" 4400 "\n" 4401 "// Subroutine type\n" 4402 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n" 4403 "\n" 4404 "// Subroutine definitions\n" 4405 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n" 4406 "{\n" 4407 " return left + right;\n" 4408 "}\n" 4409 "\n" 4410 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n" 4411 "{\n" 4412 " return left * right;\n" 4413 "}\n" 4414 "\n" 4415 "// Sub routine uniform\n" 4416 "subroutine uniform routine_type routine[4];\n" 4417 "\n" 4418 "// Input data\n" 4419 "uniform vec4 uni_left;\n" 4420 "uniform vec4 uni_right;\n" 4421 "uniform uvec4 uni_indices;\n" 4422 "\n" 4423 "// Output\n" 4424 "out vec4 out_combined;\n" 4425 "out vec4 out_combined_inverted;\n" 4426 "out vec4 out_constant;\n" 4427 "out vec4 out_constant_inverted;\n" 4428 "out vec4 out_dynamic;\n" 4429 "out vec4 out_dynamic_inverted;\n" 4430 "out vec4 out_loop;\n" 4431 "out uint out_array_length;\n" 4432 "\n" 4433 "void main()\n" 4434 "{\n" 4435 " out_combined = routine[3](routine[2](routine[1](routine[0](uni_left, uni_right), uni_right), " 4436 "uni_right), uni_right);\n" 4437 " out_combined_inverted = routine[0](routine[1](routine[2](routine[3](uni_left, uni_right), uni_right), " 4438 "uni_right), uni_right);\n" 4439 " \n" 4440 " out_constant = routine[3](routine[2](routine[1](routine[0](vec4(1, 2, 3, 4), vec4(-5, -6, -7, " 4441 "-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n" 4442 " out_constant_inverted = routine[0](routine[1](routine[2](routine[3](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 " \n" 4445 " out_dynamic = " 4446 "routine[uni_indices.w](routine[uni_indices.z](routine[uni_indices.y](routine[uni_indices.x](uni_left, " 4447 "uni_right), uni_right), uni_right), uni_right);\n" 4448 " out_dynamic_inverted = " 4449 "routine[uni_indices.x](routine[uni_indices.y](routine[uni_indices.z](routine[uni_indices.w](uni_left, " 4450 "uni_right), uni_right), uni_right), uni_right);\n" 4451 " \n" 4452 " out_loop = uni_left;\n" 4453 " for (uint i = 0u; i < routine.length(); ++i)\n" 4454 " {\n" 4455 " out_loop = routine[i](out_loop, uni_right);\n" 4456 " }\n" 4457 " \n" 4458 " out_array_length = routine.length() + 6 - (uni_indices.x + uni_indices.y + uni_indices.z + " 4459 "uni_indices.w);\n" 4460 "}\n" 4461 "\n"; 4462 4463 static const GLchar* subroutine_names[] = { 4464 "add", "multiply", 4465 }; 4466 static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 4467 4468 static const GLchar* subroutine_uniform_names[] = { "routine[0]", "routine[1]", "routine[2]", "routine[3]" }; 4469 static const GLuint n_subroutine_uniform_names = 4470 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]); 4471 4472 static const GLchar* uniform_names[] = { 4473 "uni_left", "uni_right", "uni_indices", 4474 }; 4475 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]); 4476 4477 static const GLchar* varying_names[] = { "out_combined", "out_combined_inverted", 4478 "out_constant", "out_constant_inverted", 4479 "out_dynamic", "out_dynamic_inverted", 4480 "out_loop", "out_array_length" }; 4481 4482 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]); 4483 static const GLuint transform_feedback_buffer_size = n_varyings * 4 * sizeof(GLfloat); 4484 4485 /* Test data */ 4486 static const Utils::vec4<GLfloat> uni_left(-1.0f, 0.75f, -0.5f, 0.25f); 4487 static const Utils::vec4<GLfloat> uni_right(1.0f, -0.75f, 0.5f, -0.25f); 4488 static const Utils::vec4<GLuint> uni_indices(1, 2, 0, 3); 4489 4490 static const GLuint subroutine_combinations[][4] = { 4491 { 0, 0, 0, 0 }, /* + + + + */ 4492 { 0, 0, 0, 1 }, /* + + + * */ 4493 { 0, 0, 1, 0 }, /* + + * + */ 4494 { 0, 0, 1, 1 }, /* + + * * */ 4495 { 0, 1, 0, 0 }, /* + * + + */ 4496 { 0, 1, 0, 1 }, /* + * + * */ 4497 { 0, 1, 1, 0 }, /* + * * + */ 4498 { 0, 1, 1, 1 }, /* + * * * */ 4499 { 1, 0, 0, 0 }, /* * + + + */ 4500 { 1, 0, 0, 1 }, /* * + + * */ 4501 { 1, 0, 1, 0 }, /* * + * + */ 4502 { 1, 0, 1, 1 }, /* * + * * */ 4503 { 1, 1, 0, 0 }, /* * * + + */ 4504 { 1, 1, 0, 1 }, /* * * + * */ 4505 { 1, 1, 1, 0 }, /* * * * + */ 4506 { 1, 1, 1, 1 } /* * * * * */ 4507 }; 4508 static const GLuint n_subroutine_combinations = 4509 sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]); 4510 4511 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 4512 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 4513 { 4514 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 4515 } 4516 4517 /* GL objects */ 4518 Utils::program program(m_context); 4519 Utils::buffer transform_feedback_buffer(m_context); 4520 Utils::vertexArray vao(m_context); 4521 4522 bool result = true; 4523 4524 /* Init GL objects */ 4525 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names, 4526 n_varyings); 4527 4528 program.use(); 4529 4530 vao.generate(); 4531 vao.bind(); 4532 4533 transform_feedback_buffer.generate(); 4534 4535 /* Get subroutine indices */ 4536 for (GLuint routine = 0; routine < n_subroutine_names; ++routine) 4537 { 4538 m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER); 4539 } 4540 4541 /* Get subroutine uniform locations */ 4542 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 4543 { 4544 m_subroutine_uniform_locations[uniform] = 4545 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER); 4546 } 4547 4548 /* Get uniform locations */ 4549 for (GLuint i = 0; i < n_uniform_names; ++i) 4550 { 4551 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]); 4552 } 4553 4554 /* Test */ 4555 for (GLuint i = 0; i < n_subroutine_combinations; ++i) 4556 { 4557 /* Clean */ 4558 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 4559 GL_DYNAMIC_COPY); 4560 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 4561 4562 /* Verify */ 4563 if (false == testDraw(subroutine_combinations[i], uni_left, uni_right, uni_indices)) 4564 { 4565 result = false; 4566 } 4567 } 4568 4569 if (true == result) 4570 { 4571 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4572 } 4573 else 4574 { 4575 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4576 } 4577 4578 /* Done */ 4579 return tcu::TestNode::STOP; 4580} 4581 4582/* Calculate result of function applied to operands 4583 * 4584 * @param function Function id, 0 is sum, 1 is multiplication 4585 * @param left Left operand 4586 * @param right Right operand 4587 * @param out Function result 4588 **/ 4589void FunctionalTest7_8::calculate(glw::GLuint function, const Utils::vec4<glw::GLfloat>& left, 4590 const Utils::vec4<glw::GLfloat>& right, Utils::vec4<glw::GLfloat>& out) const 4591{ 4592 if (0 == function) 4593 { 4594 out.m_x = left.m_x + right.m_x; 4595 out.m_y = left.m_y + right.m_y; 4596 out.m_z = left.m_z + right.m_z; 4597 out.m_w = left.m_w + right.m_w; 4598 } 4599 else 4600 { 4601 out.m_x = left.m_x * right.m_x; 4602 out.m_y = left.m_y * right.m_y; 4603 out.m_z = left.m_z * right.m_z; 4604 out.m_w = left.m_w * right.m_w; 4605 } 4606} 4607 4608/** Calculate expected values for all operations 4609 * 4610 * @param combination Function combination, first applied function is at index [0] 4611 * @param left Left operand 4612 * @param right Right operand 4613 * @param indices Indices used by dynamic calls 4614 * @param out_combined Expected result of "combined" operation 4615 * @param out_combined_inverted Expected result of "combined_inverted" operation 4616 * @param out_constant Expected result of "constant" operation 4617 * @param out_constant_inverted Expected result of "constant_inverted" operation 4618 * @param out_dynamic Expected result of "dynamic" operation 4619 * @param out_dynamic_inverted Expected result of "out_dynamic_inverted" operation 4620 * @param out_loop Expected result of "loop" operation 4621 **/ 4622void FunctionalTest7_8::calculate( 4623 const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, const Utils::vec4<glw::GLfloat>& right, 4624 const Utils::vec4<glw::GLuint>& indices, Utils::vec4<glw::GLfloat>& out_combined, 4625 Utils::vec4<glw::GLfloat>& out_combined_inverted, Utils::vec4<glw::GLfloat>& out_constant, 4626 Utils::vec4<glw::GLfloat>& out_constant_inverted, Utils::vec4<glw::GLfloat>& out_dynamic, 4627 Utils::vec4<glw::GLfloat>& out_dynamic_inverted, Utils::vec4<glw::GLfloat>& out_loop) const 4628{ 4629 /* Indices used by "dynamic" operations, range <0..4> */ 4630 const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y], 4631 combination[indices.m_z], combination[indices.m_w] }; 4632 4633 /* Values used by "constant" operations, come from shader code */ 4634 const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4), 4635 Utils::vec4<glw::GLfloat>(-5, -6, -7, -8), 4636 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 4640 /* Start values */ 4641 Utils::vec4<glw::GLfloat> combined = left; 4642 Utils::vec4<glw::GLfloat> combined_inverted = left; 4643 Utils::vec4<glw::GLfloat> constant = constant_values[0]; 4644 Utils::vec4<glw::GLfloat> constant_inverted = constant_values[0]; 4645 Utils::vec4<glw::GLfloat> dynamic = left; 4646 Utils::vec4<glw::GLfloat> dynamic_inverted = left; 4647 4648 /* Calculate expected results */ 4649 for (GLuint i = 0; i < 4; ++i) 4650 { 4651 GLuint function = combination[i]; 4652 GLuint function_inverted = combination[3 - i]; 4653 GLuint dynamic_function = dynamic_combination[i]; 4654 GLuint dynamic_function_inverted = dynamic_combination[3 - i]; 4655 4656 calculate(function, combined, right, combined); 4657 calculate(function_inverted, combined_inverted, right, combined_inverted); 4658 calculate(function, constant, constant_values[i + 1], constant); 4659 calculate(function_inverted, constant_inverted, constant_values[i + 1], constant_inverted); 4660 calculate(dynamic_function, dynamic, right, dynamic); 4661 calculate(dynamic_function_inverted, dynamic_inverted, right, dynamic_inverted); 4662 } 4663 4664 /* Store results */ 4665 out_combined = combined; 4666 out_combined_inverted = combined_inverted; 4667 out_constant = constant; 4668 out_constant_inverted = constant_inverted; 4669 out_dynamic = dynamic; 4670 out_dynamic_inverted = dynamic_inverted; 4671 out_loop = combined; 4672} 4673 4674/** Log error 4675 * 4676 * @param combination Operations combination 4677 * @param left Left operand 4678 * @param right Right operand 4679 * @param indices Inidices used by "dynamic" calls 4680 * @param vec4_expected Expected results 4681 * @param vec4_result Results 4682 * @param array_length Length of array 4683 * @param result Comparison results 4684 **/ 4685void FunctionalTest7_8::logError(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, 4686 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices, 4687 const Utils::vec4<glw::GLfloat> vec4_expected[7], 4688 const Utils::vec4<glw::GLfloat> vec4_result[7], glw::GLuint array_length, 4689 bool result[7]) const 4690{ 4691 static const GLuint n_functions = 4; 4692 static const GLuint n_operations = 7; 4693 4694 /* Indices used by "dynamic" operations, range <0..4> */ 4695 const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y], 4696 combination[indices.m_z], combination[indices.m_w] }; 4697 4698 /* Function symbols */ 4699 GLchar functions[4]; 4700 GLchar functions_inverted[4]; 4701 GLchar functions_dynamic[4]; 4702 GLchar functions_dynamic_inverted[4]; 4703 4704 for (GLuint i = 0; i < n_functions; ++i) 4705 { 4706 GLchar function = (0 == combination[i]) ? '+' : '*'; 4707 GLchar dynamic_function = (0 == dynamic_combination[i]) ? '+' : '*'; 4708 4709 functions[i] = function; 4710 functions_inverted[n_functions - i - 1] = function; 4711 functions_dynamic[i] = dynamic_function; 4712 functions_dynamic_inverted[n_functions - i - 1] = dynamic_function; 4713 } 4714 4715 /* Values used by "constant" operations, come from shader code */ 4716 const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4), 4717 Utils::vec4<glw::GLfloat>(-5, -6, -7, -8), 4718 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 4722 /* Values used by non-"constant" operations */ 4723 Utils::vec4<glw::GLfloat> dynamic_values[5]; 4724 dynamic_values[0] = left; 4725 dynamic_values[1] = right; 4726 dynamic_values[2] = right; 4727 dynamic_values[3] = right; 4728 dynamic_values[4] = right; 4729 4730 /* For each operation */ 4731 for (GLuint i = 0; i < n_operations; ++i) 4732 { 4733 /* If result is failure */ 4734 if (false == result[i]) 4735 { 4736 const GLchar* description = 0; 4737 const Utils::vec4<glw::GLfloat>* input = 0; 4738 const GLchar* operation = 0; 4739 4740 switch (i) 4741 { 4742 case 0: 4743 description = "Call made with predefined array indices"; 4744 input = dynamic_values; 4745 operation = functions; 4746 break; 4747 case 1: 4748 description = "Call made with predefined array indices in inverted order"; 4749 input = dynamic_values; 4750 operation = functions_inverted; 4751 break; 4752 case 2: 4753 description = "Call made with predefined array indices, for constant values"; 4754 input = constant_values; 4755 operation = functions; 4756 break; 4757 case 3: 4758 description = "Call made with predefined array indices in inverted order, for constant values"; 4759 input = constant_values; 4760 operation = functions_inverted; 4761 break; 4762 case 4: 4763 description = "Call made with dynamic array indices"; 4764 input = dynamic_values; 4765 operation = functions_dynamic; 4766 break; 4767 case 5: 4768 description = "Call made with dynamic array indices in inverted order"; 4769 input = dynamic_values; 4770 operation = functions_dynamic_inverted; 4771 break; 4772 case 6: 4773 description = "Call made with loop"; 4774 input = dynamic_values; 4775 operation = functions; 4776 break; 4777 } 4778 4779 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 4780 << tcu::TestLog::EndMessage; 4781 4782 m_context.getTestContext().getLog() << tcu::TestLog::Message << description << tcu::TestLog::EndMessage; 4783 4784 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4785 4786 message << "Operation: (((("; 4787 input[0].log(message); 4788 for (GLuint function = 0; function < n_functions; ++function) 4789 { 4790 message << " " << operation[function] << " "; 4791 4792 input[function + 1].log(message); 4793 4794 message << ")"; 4795 } 4796 4797 message << tcu::TestLog::EndMessage; 4798 4799 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4800 4801 message << "Result: "; 4802 vec4_result[i].log(message); 4803 4804 message << tcu::TestLog::EndMessage; 4805 4806 message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 4807 4808 message << "Expected: "; 4809 vec4_expected[i].log(message); 4810 4811 message << tcu::TestLog::EndMessage; 4812 } 4813 4814 /* Check array length, it should be 4 */ 4815 if (4 != array_length) 4816 { 4817 m_context.getTestContext().getLog() << tcu::TestLog::Message 4818 << "Error. Invalid array length: " << array_length << ". Expected 4." 4819 << tcu::TestLog::EndMessage; 4820 } 4821 } 4822} 4823 4824/** Execute draw call and verifies captrued varyings 4825 * 4826 * @param combination Function combination, first applied function is at index [0] 4827 * @param left Left operand 4828 * @param right Right operand 4829 * @param indices Indices used by dynamic calls 4830 * 4831 * @return true if all results match expected values, false otherwise 4832 **/ 4833bool FunctionalTest7_8::testDraw(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, 4834 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices) const 4835{ 4836 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4837 static const GLuint n_vec4_varyings = 7; 4838 bool result = true; 4839 GLuint subroutine_indices[4]; 4840 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 4841 4842 /* Prepare expected results */ 4843 Utils::vec4<glw::GLfloat> expected_results[7]; 4844 calculate(combination, left, right, indices, expected_results[0], expected_results[1], expected_results[2], 4845 expected_results[3], expected_results[4], expected_results[5], expected_results[6]); 4846 4847 /* Set up input data uniforms */ 4848 gl.uniform4f(m_uniform_locations[0], left.m_x, left.m_y, left.m_z, left.m_w); 4849 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 4850 4851 gl.uniform4f(m_uniform_locations[1], right.m_x, right.m_y, right.m_z, right.m_w); 4852 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 4853 4854 gl.uniform4ui(m_uniform_locations[2], indices.m_x, indices.m_y, indices.m_z, indices.m_w); 4855 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4ui"); 4856 4857 /* Prepare subroutine uniform data */ 4858 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 4859 { 4860 const GLuint location = m_subroutine_uniform_locations[i]; 4861 4862 subroutine_indices[location] = m_subroutine_indices[combination[i]]; 4863 } 4864 4865 /* Set up subroutine uniforms */ 4866 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]); 4867 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 4868 4869 /* Execute draw call with transform feedback */ 4870 gl.beginTransformFeedback(GL_POINTS); 4871 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 4872 4873 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 4874 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 4875 4876 gl.endTransformFeedback(); 4877 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 4878 4879 /* Capture results */ 4880 GLvoid* feedback_data = (GLvoid*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 4881 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4882 4883 Utils::vec4<GLfloat> vec4_results[7]; 4884 bool results[7]; 4885 GLfloat* float_data = (GLfloat*)feedback_data; 4886 for (GLuint i = 0; i < n_vec4_varyings; ++i) 4887 { 4888 vec4_results[i].m_x = float_data[i * 4 + 0]; 4889 vec4_results[i].m_y = float_data[i * 4 + 1]; 4890 vec4_results[i].m_z = float_data[i * 4 + 2]; 4891 vec4_results[i].m_w = float_data[i * 4 + 3]; 4892 } 4893 4894 GLuint* uint_data = (GLuint*)(float_data + (n_vec4_varyings)*4); 4895 GLuint array_length = uint_data[0]; 4896 4897 /* Unmap buffer */ 4898 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4899 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 4900 4901 /* Verification */ 4902 for (GLuint i = 0; i < n_vec4_varyings; ++i) 4903 { 4904 results[i] = (vec4_results[i] == expected_results[i]); 4905 result = result && results[i]; 4906 } 4907 4908 result = result && (4 == array_length); 4909 4910 /* Log error if any */ 4911 if (false == result) 4912 { 4913 logError(combination, left, right, indices, expected_results, vec4_results, array_length, results); 4914 } 4915 4916 /* Done */ 4917 return result; 4918} 4919 4920/** Constructor. 4921 * 4922 * @param context Rendering context. 4923 * 4924 **/ 4925FunctionalTest9::FunctionalTest9(deqp::Context& context) 4926 : TestCase(context, "subroutines_3_subroutine_types_and_subroutine_uniforms_one_function", 4927 "Makes sure that program with one function associated with 3 different " 4928 "subroutine types and 3 subroutine uniforms using that function compiles " 4929 "and works as expected") 4930 , m_has_test_passed(true) 4931 , m_n_points_to_draw(16) /* arbitrary value */ 4932 , m_po_id(0) 4933 , m_vao_id(0) 4934 , m_vs_id(0) 4935 , m_xfb_bo_id(0) 4936{ 4937 /* Left blank intentionally */ 4938} 4939 4940/** De-initializes GL objects that may have been created during test execution. */ 4941void FunctionalTest9::deinit() 4942{ 4943 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4944 4945 if (m_po_id != 0) 4946 { 4947 gl.deleteProgram(m_po_id); 4948 4949 m_po_id = 0; 4950 } 4951 4952 if (m_vao_id != 0) 4953 { 4954 gl.deleteVertexArrays(1, &m_vao_id); 4955 4956 m_vao_id = 0; 4957 } 4958 4959 if (m_vs_id != 0) 4960 { 4961 gl.deleteShader(m_vs_id); 4962 4963 m_vs_id = 0; 4964 } 4965 4966 if (m_xfb_bo_id != 0) 4967 { 4968 gl.deleteBuffers(1, &m_xfb_bo_id); 4969 4970 m_xfb_bo_id = 0; 4971 } 4972} 4973 4974/** Retrieves body of a vertex shader that should be used 4975 * for the testing purposes. 4976 **/ 4977std::string FunctionalTest9::getVertexShaderBody() const 4978{ 4979 return "#version 400\n" 4980 "\n" 4981 "#extension GL_ARB_shader_subroutine : require\n" 4982 "\n" 4983 "subroutine void subroutineType1(inout float);\n" 4984 "subroutine void subroutineType2(inout float);\n" 4985 "subroutine void subroutineType3(inout float);\n" 4986 "\n" 4987 "subroutine(subroutineType1, subroutineType2, subroutineType3) void function(inout float result)\n" 4988 "{\n" 4989 " result += float(0.123) + float(gl_VertexID);\n" 4990 "}\n" 4991 "\n" 4992 "subroutine uniform subroutineType1 subroutine_uniform1;\n" 4993 "subroutine uniform subroutineType2 subroutine_uniform2;\n" 4994 "subroutine uniform subroutineType3 subroutine_uniform3;\n" 4995 "\n" 4996 "out vec4 result;\n" 4997 "\n" 4998 "void main()\n" 4999 "{\n" 5000 " result = vec4(0, 1, 2, 3);\n" 5001 "\n" 5002 " subroutine_uniform1(result.x);\n" 5003 " subroutine_uniform2(result.y);\n" 5004 " subroutine_uniform3(result.z);\n" 5005 "\n" 5006 " result.w += result.x + result.y + result.z;\n" 5007 "}\n"; 5008} 5009 5010/** Initializes all GL objects required to run the test. */ 5011void FunctionalTest9::initTest() 5012{ 5013 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5014 5015 /* Set up program object */ 5016 const char* xfb_varyings[] = { "result" }; 5017 5018 const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]); 5019 if (!Utils::buildProgram(gl, getVertexShaderBody(), "", /* tc_body */ 5020 "", /* te_body */ 5021 "", /* gs_body */ 5022 "", /* fs_body */ 5023 xfb_varyings, n_xfb_varyings, &m_vs_id, DE_NULL, /* out_tc_id */ 5024 DE_NULL, /* out_te_id */ 5025 DE_NULL, /* out_gs_id */ 5026 DE_NULL, /* out_fs_id */ 5027 &m_po_id)) 5028 { 5029 TCU_FAIL("Program failed to link successfully"); 5030 } 5031 5032 /* Set up a buffer object we will use to hold XFB data */ 5033 const unsigned int xfb_bo_size = static_cast<unsigned int>(sizeof(float) * 4 /* components */ * m_n_points_to_draw); 5034 5035 gl.genBuffers(1, &m_xfb_bo_id); 5036 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 5037 5038 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 5039 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 5040 5041 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 5042 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 5043 5044 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL, /* data */ 5045 GL_STATIC_COPY); 5046 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 5047 5048 /* Generate & bind a VAO */ 5049 gl.genVertexArrays(1, &m_vao_id); 5050 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 5051 5052 gl.bindVertexArray(m_vao_id); 5053 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 5054} 5055 5056/** Executes test iteration. 5057 * 5058 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 5059 */ 5060tcu::TestNode::IterateResult FunctionalTest9::iterate() 5061{ 5062 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5063 5064 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 5065 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 5066 { 5067 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 5068 } 5069 initTest(); 5070 5071 /* Issue a draw call to make use of the three subroutine uniforms that we've defined */ 5072 gl.useProgram(m_po_id); 5073 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 5074 5075 gl.beginTransformFeedback(GL_POINTS); 5076 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 5077 { 5078 gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw); 5079 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 5080 } 5081 gl.endTransformFeedback(); 5082 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 5083 5084 /* Map the XFB BO storage into process space */ 5085 const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 5086 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 5087 5088 verifyXFBData(xfb_data_ptr); 5089 5090 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5091 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 5092 5093 /* All done */ 5094 if (m_has_test_passed) 5095 { 5096 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5097 } 5098 else 5099 { 5100 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5101 } 5102 5103 return STOP; 5104} 5105 5106/** Verifies the data XFBed out by the vertex shader. Should the data 5107 * be found invalid, m_has_test_passed will be set to false. 5108 * 5109 * @param data_ptr XFB data. 5110 **/ 5111void FunctionalTest9::verifyXFBData(const glw::GLvoid* data_ptr) 5112{ 5113 const float epsilon = 1e-5f; 5114 bool should_continue = true; 5115 const glw::GLfloat* traveller_ptr = (const glw::GLfloat*)data_ptr; 5116 5117 for (unsigned int n_point = 0; n_point < m_n_points_to_draw && should_continue; ++n_point) 5118 { 5119 tcu::Vec4 expected_result(0, 1, 2, 3); 5120 5121 for (unsigned int n_component = 0; n_component < 3 /* xyz */; ++n_component) 5122 { 5123 expected_result[n_component] += 0.123f + float(n_point); 5124 } 5125 5126 expected_result[3 /* w */] += expected_result[0] + expected_result[1] + expected_result[2]; 5127 5128 if (de::abs(expected_result[0] - traveller_ptr[0]) > epsilon || 5129 de::abs(expected_result[1] - traveller_ptr[1]) > epsilon || 5130 de::abs(expected_result[2] - traveller_ptr[2]) > epsilon || 5131 de::abs(expected_result[3] - traveller_ptr[3]) > epsilon) 5132 { 5133 m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data is invalid. Expected:" 5134 "(" 5135 << expected_result[0] << ", " << expected_result[1] << ", " << expected_result[2] << ", " 5136 << expected_result[3] << "), found:(" << traveller_ptr[0] << ", " << traveller_ptr[1] 5137 << ", " << traveller_ptr[2] << ", " << traveller_ptr[3] << ")." 5138 << tcu::TestLog::EndMessage; 5139 5140 m_has_test_passed = false; 5141 should_continue = false; 5142 } 5143 5144 traveller_ptr += 4; /* xyzw */ 5145 } /* for (all rendered points) */ 5146} 5147 5148/** Constructor 5149 * 5150 * @param context CTS context 5151 **/ 5152FunctionalTest10::FunctionalTest10(deqp::Context& context) 5153 : TestCase(context, "arrays_of_arrays_of_uniforms", "Verify that arrays of arrays of uniforms works as expected") 5154{ 5155} 5156 5157/** Execute test 5158 * 5159 * @return tcu::TestNode::STOP 5160 **/ 5161tcu::TestNode::IterateResult FunctionalTest10::iterate() 5162{ 5163 static const GLchar* vertex_shader_code = "#version 400 core\n" 5164 "#extension GL_ARB_arrays_of_arrays : require\n" 5165 "#extension GL_ARB_shader_subroutine : require\n" 5166 "\n" 5167 "precision highp float;\n" 5168 "\n" 5169 "// Subroutine type\n" 5170 "subroutine int routine_type(in int iparam);\n" 5171 "\n" 5172 "// Subroutine definitions\n" 5173 "subroutine(routine_type) int increment(in int iparam)\n" 5174 "{\n" 5175 " return iparam + 1;\n" 5176 "}\n" 5177 "\n" 5178 "subroutine(routine_type) int decrement(in int iparam)\n" 5179 "{\n" 5180 " return iparam - 1;\n" 5181 "}\n" 5182 "\n" 5183 "// Sub routine uniform\n" 5184 "subroutine uniform routine_type routine[4][4];\n" 5185 "\n" 5186 "// Output\n" 5187 "out int out_result;\n" 5188 "\n" 5189 "void main()\n" 5190 "{\n" 5191 " int result = 0;\n" 5192 " \n" 5193 " for (uint j = 0; j < routine.length(); ++j)\n" 5194 " {\n" 5195 " for (uint i = 0; i < routine[j].length(); ++i)\n" 5196 " {\n" 5197 " result = routine[j][i](result);\n" 5198 " }\n" 5199 " }\n" 5200 " \n" 5201 " out_result = result;\n" 5202 "}\n" 5203 "\n"; 5204 5205 static const GLchar* subroutine_names[] = { 5206 "increment", "decrement", 5207 }; 5208 static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 5209 5210 static const GLchar* subroutine_uniform_names[] = { 5211 "routine[0][0]", "routine[1][0]", "routine[2][0]", "routine[3][0]", "routine[0][1]", "routine[1][1]", 5212 "routine[2][1]", "routine[3][1]", "routine[0][2]", "routine[1][2]", "routine[2][2]", "routine[3][2]", 5213 "routine[0][3]", "routine[1][3]", "routine[2][3]", "routine[3][3]" 5214 }; 5215 static const GLuint n_subroutine_uniform_names = 5216 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]); 5217 5218 static const GLchar* varying_name = "out_result"; 5219 static const GLuint transform_feedback_buffer_size = sizeof(GLint); 5220 5221 static const GLuint configuration_increment[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 5222 5223 static const GLuint configuration_decrement[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 5224 5225 static const GLuint configuration_mix[16] = { 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1 }; 5226 5227 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 5228 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 5229 { 5230 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 5231 } 5232 5233 /* Do not execute the test if GL_ARB_arrays_of_arrays is not supported */ 5234 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_arrays_of_arrays")) 5235 { 5236 throw tcu::NotSupportedError("GL_ARB_arrays_of_arrays is not supported."); 5237 } 5238 5239 bool result = true; 5240 5241 /* GL objects */ 5242 Utils::program program(m_context); 5243 Utils::buffer transform_feedback_buffer(m_context); 5244 Utils::vertexArray vao(m_context); 5245 5246 /* Init GL objects */ 5247 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name, 5248 1 /* n_varyings */); 5249 5250 program.use(); 5251 5252 vao.generate(); 5253 vao.bind(); 5254 5255 transform_feedback_buffer.generate(); 5256 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 5257 GL_DYNAMIC_COPY); 5258 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 5259 5260 /* Get subroutine indices */ 5261 for (GLuint routine = 0; routine < n_subroutine_names; ++routine) 5262 { 5263 m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER); 5264 } 5265 5266 /* Get subroutine uniform locations */ 5267 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 5268 { 5269 m_subroutine_uniform_locations[uniform] = 5270 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER); 5271 } 5272 5273 /* Test */ 5274 GLint increment_result = testDraw(configuration_increment); 5275 GLint decrement_result = testDraw(configuration_decrement); 5276 GLint mix_result = testDraw(configuration_mix); 5277 5278 /* Verify */ 5279 if (16 != increment_result) 5280 { 5281 result = false; 5282 } 5283 5284 if (-16 != decrement_result) 5285 { 5286 result = false; 5287 } 5288 if (0 != mix_result) 5289 { 5290 result = false; 5291 } 5292 5293 /* Set test result */ 5294 if (true == result) 5295 { 5296 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5297 } 5298 else 5299 { 5300 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 5301 << " Incrementation applied 16 times: " << increment_result 5302 << ". Decrementation applied 16 times: " << decrement_result 5303 << ". Incrementation and decrementation applied 8 times: " << mix_result 5304 << tcu::TestLog::EndMessage; 5305 5306 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5307 } 5308 5309 /* Done */ 5310 return tcu::TestNode::STOP; 5311} 5312 5313/** Execute draw call and return captured varying 5314 * 5315 * @param routine_indices Configuration of subroutine uniforms 5316 * 5317 * @return Value of varying captured with transform feedback 5318 **/ 5319GLint FunctionalTest10::testDraw(const GLuint routine_indices[16]) const 5320{ 5321 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5322 GLuint subroutine_indices[16]; 5323 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 5324 5325 /* Prepare subroutine uniform data */ 5326 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 5327 { 5328 const GLuint location = m_subroutine_uniform_locations[i]; 5329 5330 subroutine_indices[location] = m_subroutine_indices[routine_indices[i]]; 5331 } 5332 5333 /* Set up subroutine uniforms */ 5334 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]); 5335 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 5336 5337 /* Execute draw call with transform feedback */ 5338 gl.beginTransformFeedback(GL_POINTS); 5339 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 5340 5341 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 5342 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 5343 5344 gl.endTransformFeedback(); 5345 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 5346 5347 /* Capture results */ 5348 GLint* feedback_data = (GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 5349 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 5350 5351 GLint result = feedback_data[0]; 5352 5353 /* Unmap buffer */ 5354 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5355 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 5356 5357 return result; 5358} 5359 5360/* Definitions of constants used by FunctionalTest11 */ 5361const GLuint FunctionalTest11::m_texture_height = 32; 5362const GLuint FunctionalTest11::m_texture_width = 32; 5363 5364/** Constructor 5365 * 5366 * @param context CTS context 5367 **/ 5368FunctionalTest11::FunctionalTest11(deqp::Context& context) 5369 : TestCase(context, "globals_sampling_output_discard_function_calls", "Verify that global variables, texture " 5370 "sampling, fragment output, fragment discard " 5371 "and function calls work as expected") 5372{ 5373} 5374 5375/** Execute test 5376 * 5377 * @return tcu::TestNode::STOP 5378 **/ 5379tcu::TestNode::IterateResult FunctionalTest11::iterate() 5380{ 5381 static const GLchar* fragment_shader_code = 5382 "#version 400 core\n" 5383 "#extension GL_ARB_shader_subroutine : require\n" 5384 "\n" 5385 "precision highp float;\n" 5386 "\n" 5387 "// Output\n" 5388 "layout(location = 0) out vec4 out_color;\n" 5389 "\n" 5390 "// Global variables\n" 5391 "vec4 success_color;\n" 5392 "vec4 failure_color;\n" 5393 "\n" 5394 "// Samplers\n" 5395 "uniform sampler2D sampler_1;\n" 5396 "uniform sampler2D sampler_2;\n" 5397 "\n" 5398 "// Functions\n" 5399 "bool are_same(in vec4 left, in vec4 right)\n" 5400 "{\n" 5401 " bvec4 result;\n" 5402 "\n" 5403 " result.x = (left.x == right.x);\n" 5404 " result.y = (left.y == right.y);\n" 5405 " result.z = (left.z == right.z);\n" 5406 " result.w = (left.w == right.w);\n" 5407 "\n" 5408 " return all(result);\n" 5409 "}\n" 5410 "\n" 5411 "bool are_different(in vec4 left, in vec4 right)\n" 5412 "{\n" 5413 " bvec4 result;\n" 5414 "\n" 5415 " result.x = (left.x != right.x);\n" 5416 " result.y = (left.y != right.y);\n" 5417 " result.z = (left.z != right.z);\n" 5418 " result.w = (left.w != right.w);\n" 5419 "\n" 5420 " return any(result);\n" 5421 "}\n" 5422 "\n" 5423 "// Subroutine types\n" 5424 "subroutine void discard_fragment_type(void);\n" 5425 "subroutine void set_global_colors_type(void);\n" 5426 "subroutine vec4 sample_texture_type(in vec2);\n" 5427 "subroutine bool comparison_type(in vec4 left, in vec4 right);\n" 5428 "subroutine void test_type(void);\n" 5429 "\n" 5430 "// Subroutine definitions\n" 5431 "// discard_fragment_type\n" 5432 "subroutine(discard_fragment_type) void discard_yes(void)\n" 5433 "{\n" 5434 " discard;\n" 5435 "}\n" 5436 "\n" 5437 "subroutine(discard_fragment_type) void discard_no(void)\n" 5438 "{\n" 5439 "}\n" 5440 "\n" 5441 "// set_global_colors_type\n" 5442 "subroutine(set_global_colors_type) void red_pass_blue_fail(void)\n" 5443 "{\n" 5444 " success_color = vec4(1, 0, 0, 1);\n" 5445 " failure_color = vec4(0, 0, 1, 1);\n" 5446 "}\n" 5447 "\n" 5448 "subroutine(set_global_colors_type) void blue_pass_red_fail(void)\n" 5449 "{\n" 5450 " success_color = vec4(0, 0, 1, 1);\n" 5451 " failure_color = vec4(1, 0, 0, 1);\n" 5452 "}\n" 5453 "\n" 5454 "// sample_texture_type\n" 5455 "subroutine(sample_texture_type) vec4 first_sampler(in vec2 coord)\n" 5456 "{\n" 5457 " return texture(sampler_1, coord);\n" 5458 "}\n" 5459 "\n" 5460 "subroutine(sample_texture_type) vec4 second_sampler(in vec2 coord)\n" 5461 "{\n" 5462 " return texture(sampler_2, coord);\n" 5463 "}\n" 5464 "\n" 5465 "// comparison_type\n" 5466 "subroutine(comparison_type) bool check_equal(in vec4 left, in vec4 right)\n" 5467 "{\n" 5468 " return are_same(left, right);\n" 5469 "}\n" 5470 "\n" 5471 "subroutine(comparison_type) bool check_not_equal(in vec4 left, in vec4 right)\n" 5472 "{\n" 5473 " return are_different(left, right);\n" 5474 "}\n" 5475 "\n" 5476 "// Subroutine uniforms\n" 5477 "subroutine uniform discard_fragment_type discard_fragment;\n" 5478 "subroutine uniform set_global_colors_type set_global_colors;\n" 5479 "subroutine uniform sample_texture_type sample_texture;\n" 5480 "subroutine uniform comparison_type compare;\n" 5481 "\n" 5482 "// Subroutine definitions\n" 5483 "// test_type\n" 5484 "subroutine(test_type) void test_with_discard(void)\n" 5485 "{\n" 5486 " discard_fragment();" 5487 "\n" 5488 " out_color = failure_color;\n" 5489 "\n" 5490 " set_global_colors();\n" 5491 "\n" 5492 " vec4 sampled_color = sample_texture(gl_PointCoord);\n" 5493 "\n" 5494 " bool comparison_result = compare(success_color, sampled_color);\n" 5495 "\n" 5496 " if (true == comparison_result)\n" 5497 " {\n" 5498 " out_color = success_color;\n" 5499 " }\n" 5500 " else\n" 5501 " {\n" 5502 " out_color = failure_color;\n" 5503 " }\n" 5504 "}\n" 5505 "\n" 5506 "subroutine(test_type) void test_without_discard(void)\n" 5507 "{\n" 5508 " set_global_colors();\n" 5509 "\n" 5510 " vec4 sampled_color = sample_texture(gl_PointCoord);\n" 5511 "\n" 5512 " bool comparison_result = compare(success_color, sampled_color);\n" 5513 "\n" 5514 " if (true == comparison_result)\n" 5515 " {\n" 5516 " out_color = success_color;\n" 5517 " }\n" 5518 " else\n" 5519 " {\n" 5520 " out_color = failure_color;\n" 5521 " }\n" 5522 "}\n" 5523 "\n" 5524 "// Subroutine uniforms\n" 5525 "subroutine uniform test_type test;\n" 5526 "\n" 5527 "void main()\n" 5528 "{\n" 5529 " // Set colors\n" 5530 " success_color = vec4(0.5, 0.5, 0.5, 0.5);\n" 5531 " failure_color = vec4(0.5, 0.5, 0.5, 0.5);\n" 5532 "\n" 5533 " test();\n" 5534 "}\n" 5535 "\n"; 5536 5537 static const GLchar* geometry_shader_code = "#version 400 core\n" 5538 "#extension GL_ARB_shader_subroutine : require\n" 5539 "\n" 5540 "precision highp float;\n" 5541 "\n" 5542 "layout(points) in;\n" 5543 "layout(triangle_strip, max_vertices = 4) out;\n" 5544 "\n" 5545 "void main()\n" 5546 "{\n" 5547 " gl_Position = vec4(-1, -1, 0, 1);\n" 5548 " EmitVertex();\n" 5549 " \n" 5550 " gl_Position = vec4(-1, 1, 0, 1);\n" 5551 " EmitVertex();\n" 5552 " \n" 5553 " gl_Position = vec4( 1, -1, 0, 1);\n" 5554 " EmitVertex();\n" 5555 " \n" 5556 " gl_Position = vec4( 1, 1, 0, 1);\n" 5557 " EmitVertex();\n" 5558 " \n" 5559 " EndPrimitive();\n" 5560 "}\n" 5561 "\n"; 5562 5563 static const GLchar* vertex_shader_code = "#version 400 core\n" 5564 "#extension GL_ARB_shader_subroutine : require\n" 5565 "\n" 5566 "precision highp float;\n" 5567 "\n" 5568 "void main()\n" 5569 "{\n" 5570 "}\n" 5571 "\n"; 5572 5573 static const GLchar* subroutine_names[][2] = { { "discard_yes", "discard_no" }, 5574 { "red_pass_blue_fail", "blue_pass_red_fail" }, 5575 { "first_sampler", "second_sampler" }, 5576 { "check_equal", "check_not_equal" }, 5577 { "test_with_discard", "test_without_discard" } }; 5578 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 5579 5580 static const GLchar* subroutine_uniform_names[] = { "discard_fragment", "set_global_colors", "sample_texture", 5581 "compare", "test" }; 5582 static const GLuint n_subroutine_uniform_names = 5583 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]); 5584 5585 static const GLchar* uniform_names[] = { 5586 "sampler_1", "sampler_2", 5587 }; 5588 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]); 5589 5590 /* Colors */ 5591 static const GLubyte blue_color[4] = { 0, 0, 255, 255 }; 5592 static const GLubyte clean_color[4] = { 0, 0, 0, 0 }; 5593 static const GLubyte red_color[4] = { 255, 0, 0, 255 }; 5594 5595 /* Configurations */ 5596 static const testConfiguration test_configurations[] = { 5597 testConfiguration( 5598 "Expect red color from 1st sampler", red_color, 1 /* discard_fragment : discard_no */, 5599 0 /* set_global_colors : red_pass_blue_fail */, 0 /* sample_texture : first_sampler */, 5600 0 /* compare : check_equal */, 0 /* test : test_with_discard */, 1 /* red */, 5601 0 /* blue */), 5602 5603 testConfiguration( 5604 "Test \"without discard\" option, expect no blue color from 2nd sampler", blue_color, 5605 0 /* discard_fragment : discard_yes */, 1 /* set_global_colors : blue_pass_red_fail */, 5606 1 /* sample_texture : second_sampler */, 1 /* compare : check_not_equal */, 5607 1 /* test : test_without_discard */, 0 /* blue */, 1 /* red */), 5608 5609 testConfiguration("Fragment shoud be discarded", clean_color, 0 /* discard_fragment : discard_yes */, 5610 0 /* set_global_colors : red_pass_blue_fail */, 5611 0 /* sample_texture : first_sampler */, 5612 0 /* compare : check_equal */, 5613 0 /* test : test_with_discard */, 1 /* red */, 0 /* blue */), 5614 5615 testConfiguration( 5616 "Expect blue color from 1st sampler", blue_color, 1 /* discard_fragment : discard_no */, 5617 1 /* set_global_colors : blue_pass_red_fail */, 0 /* sample_texture : first_sampler */, 5618 0 /* compare : check_equal */, 0 /* test : test_with_discard */, 5619 0 /* blue */, 1 /* red */), 5620 5621 testConfiguration( 5622 "Expect red color from 2nd sampler", red_color, 1 /* discard_fragment : discard_no */, 5623 0 /* set_global_colors : red_pass_blue_fail */, 1 /* sample_texture : second_sampler */, 5624 0 /* compare : check_equal */, 0 /* test : test_with_discard */, 5625 0 /* blue */, 1 /* red */), 5626 5627 testConfiguration( 5628 "Expect no blue color from 2nd sampler", blue_color, 1 /* discard_fragment : discard_no */, 5629 1 /* set_global_colors : blue_pass_red_fail */, 1 /* sample_texture : second_sampler */, 5630 1 /* compare : check_not_equal */, 0 /* test : test_with_discard */, 5631 0 /* blue */, 1 /* red */), 5632 }; 5633 static const GLuint n_test_cases = sizeof(test_configurations) / sizeof(test_configurations[0]); 5634 5635 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 5636 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 5637 { 5638 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 5639 } 5640 5641 /* GL objects */ 5642 Utils::texture blue_texture(m_context); 5643 Utils::texture color_texture(m_context); 5644 Utils::framebuffer framebuffer(m_context); 5645 Utils::program program(m_context); 5646 Utils::texture red_texture(m_context); 5647 Utils::vertexArray vao(m_context); 5648 5649 /* Init GL objects */ 5650 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */, 5651 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */); 5652 5653 program.use(); 5654 5655 vao.generate(); 5656 vao.bind(); 5657 5658 blue_texture.create(m_texture_width, m_texture_height, GL_RGBA8); 5659 color_texture.create(m_texture_width, m_texture_height, GL_RGBA8); 5660 red_texture.create(m_texture_width, m_texture_height, GL_RGBA8); 5661 5662 framebuffer.generate(); 5663 framebuffer.bind(); 5664 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height); 5665 5666 /* Get subroutine indices */ 5667 for (GLuint type = 0; type < n_subroutine_types; ++type) 5668 { 5669 m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_FRAGMENT_SHADER); 5670 m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_FRAGMENT_SHADER); 5671 } 5672 5673 /* Get subroutine uniform locations */ 5674 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 5675 { 5676 m_subroutine_uniform_locations[uniform] = 5677 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_FRAGMENT_SHADER); 5678 } 5679 5680 /* Get uniform locations */ 5681 for (GLuint i = 0; i < n_uniform_names; ++i) 5682 { 5683 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]); 5684 } 5685 5686 /* Prepare textures */ 5687 fillTexture(blue_texture, blue_color); 5688 fillTexture(color_texture, clean_color); 5689 fillTexture(red_texture, red_color); 5690 5691 m_source_textures[0] = blue_texture.m_id; 5692 m_source_textures[1] = red_texture.m_id; 5693 5694 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 5695 5696 /* Test */ 5697 bool result = true; 5698 for (GLuint i = 0; i < n_test_cases; ++i) 5699 { 5700 /* Clean output texture */ 5701 framebuffer.clear(GL_COLOR_BUFFER_BIT); 5702 5703 /* Execute test */ 5704 if (false == testDraw(test_configurations[i].m_routines, test_configurations[i].m_samplers, 5705 test_configurations[i].m_expected_color, color_texture)) 5706 { 5707 m_context.getTestContext().getLog() 5708 << tcu::TestLog::Message << "Error. Failure for configuration: " << test_configurations[i].m_description 5709 << tcu::TestLog::EndMessage; 5710 5711 result = false; 5712 } 5713 } 5714 5715 /* Set result */ 5716 if (true == result) 5717 { 5718 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5719 } 5720 else 5721 { 5722 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5723 } 5724 5725 /* Done */ 5726 return tcu::TestNode::STOP; 5727} 5728 5729/** Fill texture with specified color 5730 * 5731 * @param texture Texture instance 5732 * @param color Color 5733 **/ 5734void FunctionalTest11::fillTexture(Utils::texture& texture, const glw::GLubyte color[4]) const 5735{ 5736 std::vector<GLubyte> texture_data; 5737 5738 /* Prepare texture data */ 5739 texture_data.resize(m_texture_width * m_texture_height * 4); 5740 5741 for (GLuint y = 0; y < m_texture_height; ++y) 5742 { 5743 const GLuint line_offset = y * m_texture_width * 4; 5744 5745 for (GLuint x = 0; x < m_texture_width; ++x) 5746 { 5747 const GLuint point_offset = x * 4 + line_offset; 5748 5749 texture_data[point_offset + 0] = color[0]; /* red */ 5750 texture_data[point_offset + 1] = color[1]; /* green */ 5751 texture_data[point_offset + 2] = color[2]; /* blue */ 5752 texture_data[point_offset + 3] = color[3]; /* alpha */ 5753 } 5754 } 5755 5756 texture.update(m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); 5757} 5758 5759/** Execute draw call and verify results 5760 * 5761 * @param routine_configuration Configurations of routines to be used 5762 * @param sampler_configuration Configuration of textures to be bound to samplers 5763 * @param expected_color Expected color of result image 5764 * 5765 * @return true if result image is filled with expected color, false otherwise 5766 **/ 5767bool FunctionalTest11::testDraw(const glw::GLuint routine_configuration[5], const glw::GLuint sampler_configuration[2], 5768 const glw::GLubyte expected_color[4], Utils::texture& color_texture) const 5769{ 5770 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5771 static const GLint n_samplers = 2; 5772 static const GLint n_subroutine_uniforms = 5; 5773 GLuint subroutine_indices[5]; 5774 5775 /* Set samplers */ 5776 for (GLuint i = 0; i < n_samplers; ++i) 5777 { 5778 const GLuint location = m_uniform_locations[i]; 5779 const GLuint texture = m_source_textures[sampler_configuration[i]]; 5780 5781 gl.activeTexture(GL_TEXTURE0 + i); 5782 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); 5783 5784 gl.bindTexture(GL_TEXTURE_2D, texture); 5785 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 5786 5787 gl.uniform1i(location, i); 5788 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 5789 } 5790 5791 gl.activeTexture(GL_TEXTURE0 + 0); 5792 5793 /* Set subroutine uniforms */ 5794 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 5795 { 5796 const GLuint location = m_subroutine_uniform_locations[i]; 5797 const GLuint routine = routine_configuration[i]; 5798 5799 subroutine_indices[location] = m_subroutine_indices[i][routine]; 5800 } 5801 5802 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 5, subroutine_indices); 5803 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 5804 5805 /* Draw */ 5806 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 5807 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 5808 5809 /* Capture result */ 5810 std::vector<GLubyte> captured_data; 5811 captured_data.resize(m_texture_width * m_texture_height * 4); 5812 5813 color_texture.get(GL_RGBA, GL_UNSIGNED_BYTE, &captured_data[0]); 5814 5815 /* Verify result */ 5816 for (GLuint y = 0; y < m_texture_height; ++y) 5817 { 5818 const GLuint line_offset = y * m_texture_width * 4; 5819 5820 for (GLuint x = 0; x < m_texture_width; ++x) 5821 { 5822 const GLuint point_offset = x * 4 + line_offset; 5823 bool is_as_expected = true; 5824 5825 is_as_expected = is_as_expected && (expected_color[0] == captured_data[point_offset + 0]); /* red */ 5826 is_as_expected = is_as_expected && (expected_color[1] == captured_data[point_offset + 1]); /* green */ 5827 is_as_expected = is_as_expected && (expected_color[2] == captured_data[point_offset + 2]); /* blue */ 5828 is_as_expected = is_as_expected && (expected_color[3] == captured_data[point_offset + 3]); /* alpha */ 5829 5830 if (false == is_as_expected) 5831 { 5832 return false; 5833 } 5834 } 5835 } 5836 5837 /* Done */ 5838 return true; 5839} 5840 5841/* Constatns used by FunctionalTest12 */ 5842const glw::GLuint FunctionalTest12::m_texture_height = 16; 5843const glw::GLuint FunctionalTest12::m_texture_width = 16; 5844 5845/** Constructor 5846 * 5847 * @param context CTS context 5848 **/ 5849FunctionalTest12::FunctionalTest12(deqp::Context& context) 5850 : TestCase(context, "ssbo_atomic_image_load_store", 5851 "Verify that SSBO, atomic counters and image load store work as expected") 5852 , m_left_image(0) 5853 , m_right_image(0) 5854{ 5855} 5856 5857/** Execute test 5858 * 5859 * @return tcu::TestNode::STOP 5860 **/ 5861tcu::TestNode::IterateResult FunctionalTest12::iterate() 5862{ 5863 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 5864 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 5865 { 5866 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 5867 } 5868 5869 bool result = true; 5870 5871 /* Test atomic counters */ 5872 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters")) 5873 { 5874 if (false == testAtomic()) 5875 { 5876 result = false; 5877 } 5878 } 5879 5880 /* Test shader storage buffer */ 5881 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_storage_buffer_object")) 5882 { 5883 if (false == testSSBO()) 5884 { 5885 result = false; 5886 } 5887 } 5888 5889 /* Test image load store */ 5890 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_image_load_store")) 5891 { 5892 if (false == testImage()) 5893 { 5894 result = false; 5895 } 5896 } 5897 5898 /* Set result */ 5899 if (true == result) 5900 { 5901 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5902 } 5903 else 5904 { 5905 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5906 } 5907 5908 /* Done */ 5909 return tcu::TestNode::STOP; 5910} 5911 5912/** Fill texture with specified color 5913 * 5914 * @param texture Texture instance 5915 * @param color Color 5916 **/ 5917void FunctionalTest12::fillTexture(Utils::texture& texture, const glw::GLuint color[4]) const 5918{ 5919 std::vector<GLuint> texture_data; 5920 5921 /* Prepare texture data */ 5922 texture_data.resize(m_texture_width * m_texture_height * 4); 5923 5924 for (GLuint y = 0; y < m_texture_height; ++y) 5925 { 5926 const GLuint line_offset = y * m_texture_width * 4; 5927 5928 for (GLuint x = 0; x < m_texture_width; ++x) 5929 { 5930 const GLuint point_offset = x * 4 + line_offset; 5931 5932 texture_data[point_offset + 0] = color[0]; /* red */ 5933 texture_data[point_offset + 1] = color[1]; /* green */ 5934 texture_data[point_offset + 2] = color[2]; /* blue */ 5935 texture_data[point_offset + 3] = color[3]; /* alpha */ 5936 } 5937 } 5938 5939 texture.update(m_texture_width, m_texture_height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &texture_data[0]); 5940} 5941 5942/** Test atomic counters 5943 * 5944 * @return true if test pass, false otherwise 5945 **/ 5946bool FunctionalTest12::testAtomic() 5947{ 5948 static const GLchar* fragment_shader_code = "#version 410 core\n" 5949 "#extension GL_ARB_shader_atomic_counters : require\n" 5950 "#extension GL_ARB_shader_subroutine : require\n" 5951 "\n" 5952 "precision highp float;\n" 5953 "\n" 5954 "layout(location = 0) out uint out_color;\n" 5955 "\n" 5956 "layout(binding = 0, offset = 8) uniform atomic_uint one;\n" 5957 "layout(binding = 0, offset = 4) uniform atomic_uint two;\n" 5958 "layout(binding = 0, offset = 0) uniform atomic_uint three;\n" 5959 "\n" 5960 "subroutine void atomic_routine(void)\n;" 5961 "\n" 5962 "subroutine(atomic_routine) void increment_two(void)\n" 5963 "{\n" 5964 " out_color = atomicCounterIncrement(two);\n" 5965 "}\n" 5966 "\n" 5967 "subroutine(atomic_routine) void decrement_three(void)\n" 5968 "{\n" 5969 " out_color = atomicCounterDecrement(three);\n" 5970 "}\n" 5971 "\n" 5972 "subroutine(atomic_routine) void read_one(void)\n" 5973 "{\n" 5974 " out_color = atomicCounter(one);\n" 5975 "}\n" 5976 "\n" 5977 "subroutine uniform atomic_routine routine;\n" 5978 "\n" 5979 "void main()\n" 5980 "{\n" 5981 " routine();\n" 5982 "}\n" 5983 "\n"; 5984 5985 static const GLchar* geometry_shader_code = "#version 400 core\n" 5986 "#extension GL_ARB_shader_subroutine : require\n" 5987 "\n" 5988 "precision highp float;\n" 5989 "\n" 5990 "layout(points) in;\n" 5991 "layout(triangle_strip, max_vertices = 4) out;\n" 5992 "\n" 5993 "void main()\n" 5994 "{\n" 5995 " gl_Position = vec4(-1, -1, 0, 1);\n" 5996 " EmitVertex();\n" 5997 " \n" 5998 " gl_Position = vec4(-1, 1, 0, 1);\n" 5999 " EmitVertex();\n" 6000 " \n" 6001 " gl_Position = vec4( 1, -1, 0, 1);\n" 6002 " EmitVertex();\n" 6003 " \n" 6004 " gl_Position = vec4( 1, 1, 0, 1);\n" 6005 " EmitVertex();\n" 6006 " \n" 6007 " EndPrimitive();\n" 6008 "}\n" 6009 "\n"; 6010 6011 static const GLchar* vertex_shader_code = "#version 400 core\n" 6012 "#extension GL_ARB_shader_subroutine : require\n" 6013 "\n" 6014 "precision highp float;\n" 6015 "\n" 6016 "void main()\n" 6017 "{\n" 6018 "}\n" 6019 "\n"; 6020 6021 static const GLchar* subroutine_names[] = { "increment_two", "decrement_three", "read_one" }; 6022 6023 /* Test data */ 6024 static const glw::GLuint atomic_buffer_data[] = { m_texture_width * m_texture_height, 6025 m_texture_width * m_texture_height, 6026 m_texture_width * m_texture_height }; 6027 6028 static const glw::GLuint expected_incremented_two[] = { atomic_buffer_data[0], 2 * atomic_buffer_data[1], 6029 atomic_buffer_data[2] }; 6030 6031 static const glw::GLuint expected_decremented_three[] = { 0, expected_incremented_two[1], 6032 expected_incremented_two[2] }; 6033 6034 static const glw::GLuint expected_read_one[] = { expected_decremented_three[0], expected_decremented_three[1], 6035 expected_decremented_three[2] }; 6036 6037 /* GL objects */ 6038 Utils::buffer atomic_buffer(m_context); 6039 Utils::texture color_texture(m_context); 6040 Utils::framebuffer framebuffer(m_context); 6041 Utils::program program(m_context); 6042 Utils::vertexArray vao(m_context); 6043 6044 /* Init GL objects */ 6045 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */, 6046 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */); 6047 6048 program.use(); 6049 6050 vao.generate(); 6051 vao.bind(); 6052 6053 color_texture.create(m_texture_width, m_texture_height, GL_R32UI); 6054 6055 atomic_buffer.generate(); 6056 atomic_buffer.update(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomic_buffer_data), (GLvoid*)atomic_buffer_data, 6057 GL_STATIC_DRAW); 6058 atomic_buffer.bindRange(GL_ATOMIC_COUNTER_BUFFER, 0 /* index */, 0 /* offset */, sizeof(atomic_buffer_data)); 6059 6060 framebuffer.generate(); 6061 framebuffer.bind(); 6062 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height); 6063 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 6064 framebuffer.clear(GL_COLOR_BUFFER_BIT); 6065 6066 /* Subroutine indices */ 6067 GLuint increment_two = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER); 6068 GLuint decrement_three = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER); 6069 GLuint read_one = program.getSubroutineIndex(subroutine_names[2], GL_FRAGMENT_SHADER); 6070 6071 /* Test */ 6072 bool result = true; 6073 6074 if (false == testAtomicDraw(increment_two, expected_incremented_two)) 6075 { 6076 result = false; 6077 } 6078 6079 if (false == testAtomicDraw(decrement_three, expected_decremented_three)) 6080 { 6081 result = false; 6082 } 6083 6084 if (false == testAtomicDraw(read_one, expected_read_one)) 6085 { 6086 result = false; 6087 } 6088 6089 /* Done */ 6090 return result; 6091} 6092 6093/** Execture draw call and verify results 6094 * 6095 * @param subroutine_index Index of subroutine that shall be used during draw call 6096 * @param expected_results Expected results 6097 * 6098 * @return true if results are as expected, false otherwise 6099 **/ 6100bool FunctionalTest12::testAtomicDraw(GLuint subroutine_index, const GLuint expected_results[3]) const 6101{ 6102 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6103 6104 /* Set subroutine uniforms */ 6105 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index); 6106 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 6107 6108 /* Draw */ 6109 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 6110 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 6111 6112 /* Capture results */ 6113 GLuint* atomic_results = (GLuint*)gl.mapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY); 6114 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 6115 6116 /* Verify */ 6117 bool result = (0 == memcmp(expected_results, atomic_results, 3 * sizeof(GLuint))); 6118 6119 if (false == result) 6120 { 6121 m_context.getTestContext().getLog() 6122 << tcu::TestLog::Message << "Error. Invalid result. " 6123 << "Result: [ " << atomic_results[0] << ", " << atomic_results[1] << ", " << atomic_results[2] << " ] " 6124 << "Expected: [ " << expected_results[0] << ", " << expected_results[1] << ", " << expected_results[2] 6125 << " ]" << tcu::TestLog::EndMessage; 6126 } 6127 6128 /* Unmap buffer */ 6129 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 6130 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 6131 6132 /* Done */ 6133 return result; 6134} 6135 6136/** Test image load store 6137 * 6138 * @return true if test pass, false otherwise 6139 **/ 6140bool FunctionalTest12::testImage() 6141{ 6142 static const GLchar* fragment_shader_code = 6143 "#version 400 core\n" 6144 "#extension GL_ARB_shader_image_load_store : require\n" 6145 "#extension GL_ARB_shader_subroutine : require\n" 6146 "\n" 6147 "precision highp float;\n" 6148 "\n" 6149 "layout(location = 0) out uvec4 out_color;\n" 6150 "\n" 6151 "layout(rgba32ui) uniform uimage2D left_image;\n" 6152 "layout(rgba32ui) uniform uimage2D right_image;\n" 6153 "\n" 6154 "subroutine void image_routine(void);\n" 6155 "\n" 6156 "subroutine(image_routine) void left_to_right(void)\n" 6157 "{\n" 6158 " out_color = imageLoad (left_image, ivec2(gl_FragCoord.xy));\n" 6159 " imageStore(right_image, ivec2(gl_FragCoord.xy), out_color);\n" 6160 "}\n" 6161 "\n" 6162 "subroutine(image_routine) void right_to_left(void)\n" 6163 "{\n" 6164 " out_color = imageLoad (right_image, ivec2(gl_FragCoord.xy));\n" 6165 " imageStore(left_image, ivec2(gl_FragCoord.xy), out_color);\n" 6166 "}\n" 6167 "\n" 6168 "subroutine uniform image_routine routine;\n" 6169 "\n" 6170 "void main()\n" 6171 "{\n" 6172 " routine();\n" 6173 "}\n" 6174 "\n"; 6175 6176 static const GLchar* geometry_shader_code = "#version 400 core\n" 6177 "#extension GL_ARB_shader_subroutine : require\n" 6178 "\n" 6179 "precision highp float;\n" 6180 "\n" 6181 "layout(points) in;\n" 6182 "layout(triangle_strip, max_vertices = 4) out;\n" 6183 "\n" 6184 "void main()\n" 6185 "{\n" 6186 " gl_Position = vec4(-1, -1, 0, 1);\n" 6187 " EmitVertex();\n" 6188 " \n" 6189 " gl_Position = vec4(-1, 1, 0, 1);\n" 6190 " EmitVertex();\n" 6191 " \n" 6192 " gl_Position = vec4( 1, -1, 0, 1);\n" 6193 " EmitVertex();\n" 6194 " \n" 6195 " gl_Position = vec4( 1, 1, 0, 1);\n" 6196 " EmitVertex();\n" 6197 " \n" 6198 " EndPrimitive();\n" 6199 "}\n" 6200 "\n"; 6201 6202 static const GLchar* vertex_shader_code = "#version 400 core\n" 6203 "#extension GL_ARB_shader_subroutine : require\n" 6204 "\n" 6205 "precision highp float;\n" 6206 "\n" 6207 "void main()\n" 6208 "{\n" 6209 "}\n" 6210 "\n"; 6211 6212 static const GLchar* subroutine_names[] = { "left_to_right", "right_to_left" }; 6213 6214 static const GLchar* uniform_names[] = { "left_image", "right_image" }; 6215 6216 /* Test data */ 6217 static const GLuint blue_color[4] = { 0, 0, 255, 255 }; 6218 static const GLuint clean_color[4] = { 16, 32, 64, 128 }; 6219 static const GLuint red_color[4] = { 255, 0, 0, 255 }; 6220 6221 /* GL objects */ 6222 Utils::texture blue_texture(m_context); 6223 Utils::texture destination_texture(m_context); 6224 Utils::texture color_texture(m_context); 6225 Utils::framebuffer framebuffer(m_context); 6226 Utils::program program(m_context); 6227 Utils::texture red_texture(m_context); 6228 Utils::vertexArray vao(m_context); 6229 6230 /* Init GL objects */ 6231 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */, 6232 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */); 6233 6234 program.use(); 6235 6236 vao.generate(); 6237 vao.bind(); 6238 6239 blue_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6240 destination_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6241 color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6242 red_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6243 6244 fillTexture(blue_texture, blue_color); 6245 fillTexture(destination_texture, clean_color); 6246 fillTexture(red_texture, red_color); 6247 6248 framebuffer.generate(); 6249 framebuffer.bind(); 6250 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height); 6251 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 6252 framebuffer.clear(GL_COLOR_BUFFER_BIT); 6253 6254 /* Subroutine indices */ 6255 GLuint left_to_right = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER); 6256 GLuint right_to_left = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER); 6257 6258 /* Uniform locations */ 6259 m_left_image = program.getUniformLocation(uniform_names[0]); 6260 m_right_image = program.getUniformLocation(uniform_names[1]); 6261 6262 /* Test */ 6263 bool result = true; 6264 6265 if (false == testImageDraw(left_to_right, blue_texture, destination_texture, blue_color, blue_color)) 6266 { 6267 result = false; 6268 } 6269 6270 if (false == testImageDraw(left_to_right, red_texture, destination_texture, red_color, red_color)) 6271 { 6272 result = false; 6273 } 6274 6275 if (false == testImageDraw(right_to_left, destination_texture, blue_texture, blue_color, blue_color)) 6276 { 6277 result = false; 6278 } 6279 6280 if (false == testImageDraw(right_to_left, destination_texture, red_texture, red_color, red_color)) 6281 { 6282 result = false; 6283 } 6284 6285 if (false == testImageDraw(left_to_right, blue_texture, red_texture, blue_color, blue_color)) 6286 { 6287 result = false; 6288 } 6289 6290 /* Done */ 6291 return result; 6292} 6293 6294/** Execute draw call and verifies results 6295 * 6296 * @param subroutine_index Index of subroutine that shall be used during draw call 6297 * @param left "Left" texture 6298 * @param right "Right" texture 6299 * @param expected_left_color Expected color of "left" texture 6300 * @param expected_right_color Expected color of "right" texture 6301 * 6302 * @return true if verification result is positive, false otherwise 6303 **/ 6304bool FunctionalTest12::testImageDraw(GLuint subroutine_index, Utils::texture& left, Utils::texture& right, 6305 const GLuint expected_left_color[4], const GLuint expected_right_color[4]) const 6306{ 6307 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6308 6309 /* Set subroutine uniforms */ 6310 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index); 6311 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 6312 6313 /* Set up image units */ 6314 gl.uniform1i(m_left_image, 0); 6315 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 6316 6317 gl.uniform1i(m_right_image, 1); 6318 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); 6319 6320 gl.bindImageTexture(0, left.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); 6321 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture"); 6322 6323 gl.bindImageTexture(1, right.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); 6324 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture"); 6325 6326 /* Draw */ 6327 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 6328 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 6329 6330 /* Verify results */ 6331 bool result = true; 6332 6333 if (false == verifyTexture(left, expected_left_color)) 6334 { 6335 m_context.getTestContext().getLog() << tcu::TestLog::Message 6336 << "Error. Invalid result. Left texture is filled with wrong color." 6337 << tcu::TestLog::EndMessage; 6338 result = false; 6339 } 6340 6341 if (false == verifyTexture(right, expected_right_color)) 6342 { 6343 m_context.getTestContext().getLog() << tcu::TestLog::Message 6344 << "Error. Invalid result. Right texture is filled with wrong color." 6345 << tcu::TestLog::EndMessage; 6346 result = false; 6347 } 6348 6349 /* Done */ 6350 return result; 6351} 6352 6353/** Test shader storage buffer 6354 * 6355 * @return true if test pass, false otherwise 6356 **/ 6357bool FunctionalTest12::testSSBO() 6358{ 6359 static const GLchar* fragment_shader_code = "#version 400 core\n" 6360 "#extension GL_ARB_shader_storage_buffer_object : require\n" 6361 "#extension GL_ARB_shader_subroutine : require\n" 6362 "\n" 6363 "precision highp float;\n" 6364 "\n" 6365 "layout(location = 0) out uvec4 out_color;\n" 6366 "\n" 6367 "layout(std140, binding = 0) buffer Buffer\n" 6368 "{\n" 6369 " uvec4 entry;\n" 6370 "};\n" 6371 "\n" 6372 "subroutine void ssbo_routine(void)\n;" 6373 "\n" 6374 "subroutine(ssbo_routine) void increment(void)\n" 6375 "{\n" 6376 " out_color.x = atomicAdd(entry.x, 1);\n" 6377 " out_color.y = atomicAdd(entry.y, 1);\n" 6378 " out_color.z = atomicAdd(entry.z, 1);\n" 6379 " out_color.w = atomicAdd(entry.w, 1);\n" 6380 "}\n" 6381 "\n" 6382 "subroutine(ssbo_routine) void decrement(void)\n" 6383 "{\n" 6384 " out_color.x = atomicAdd(entry.x, -1);\n" 6385 " out_color.y = atomicAdd(entry.y, -1);\n" 6386 " out_color.z = atomicAdd(entry.z, -1);\n" 6387 " out_color.w = atomicAdd(entry.w, -1);\n" 6388 "}\n" 6389 "\n" 6390 "subroutine uniform ssbo_routine routine;\n" 6391 "\n" 6392 "void main()\n" 6393 "{\n" 6394 " routine();\n" 6395 "}\n" 6396 "\n"; 6397 6398 static const GLchar* geometry_shader_code = "#version 400 core\n" 6399 "#extension GL_ARB_shader_subroutine : require\n" 6400 "\n" 6401 "precision highp float;\n" 6402 "\n" 6403 "layout(points) in;\n" 6404 "layout(triangle_strip, max_vertices = 4) out;\n" 6405 "\n" 6406 "void main()\n" 6407 "{\n" 6408 " gl_Position = vec4(-1, -1, 0, 1);\n" 6409 " EmitVertex();\n" 6410 " \n" 6411 " gl_Position = vec4(-1, 1, 0, 1);\n" 6412 " EmitVertex();\n" 6413 " \n" 6414 " gl_Position = vec4( 1, -1, 0, 1);\n" 6415 " EmitVertex();\n" 6416 " \n" 6417 " gl_Position = vec4( 1, 1, 0, 1);\n" 6418 " EmitVertex();\n" 6419 " \n" 6420 " EndPrimitive();\n" 6421 "}\n" 6422 "\n"; 6423 6424 static const GLchar* vertex_shader_code = "#version 400 core\n" 6425 "#extension GL_ARB_shader_subroutine : require\n" 6426 "\n" 6427 "precision highp float;\n" 6428 "\n" 6429 "void main()\n" 6430 "{\n" 6431 "}\n" 6432 "\n"; 6433 6434 static const GLchar* subroutine_names[] = { "increment", "decrement" }; 6435 6436 /* Test data */ 6437 static const glw::GLuint buffer_data[] = { m_texture_width * m_texture_height + 1, 6438 m_texture_width * m_texture_height + 2, 6439 m_texture_width * m_texture_height + 3, 6440 m_texture_width * m_texture_height + 4 }; 6441 6442 static const glw::GLuint expected_incremented[] = { m_texture_width * m_texture_height + buffer_data[0], 6443 m_texture_width * m_texture_height + buffer_data[1], 6444 m_texture_width * m_texture_height + buffer_data[2], 6445 m_texture_width * m_texture_height + buffer_data[3] }; 6446 6447 static const glw::GLuint expected_decremented[] = { buffer_data[0], buffer_data[1], buffer_data[2], 6448 buffer_data[3] }; 6449 6450 /* GL objects */ 6451 Utils::buffer buffer(m_context); 6452 Utils::texture color_texture(m_context); 6453 Utils::framebuffer framebuffer(m_context); 6454 Utils::program program(m_context); 6455 Utils::vertexArray vao(m_context); 6456 6457 /* Init GL objects */ 6458 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */, 6459 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */); 6460 6461 program.use(); 6462 6463 vao.generate(); 6464 vao.bind(); 6465 6466 color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI); 6467 6468 buffer.generate(); 6469 buffer.update(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), (GLvoid*)buffer_data, GL_STATIC_DRAW); 6470 buffer.bindRange(GL_SHADER_STORAGE_BUFFER, 0 /* index */, 0 /* offset */, sizeof(buffer_data)); 6471 6472 framebuffer.generate(); 6473 framebuffer.bind(); 6474 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height); 6475 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 6476 framebuffer.clear(GL_COLOR_BUFFER_BIT); 6477 6478 /* Subroutine indices */ 6479 GLuint increment = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER); 6480 GLuint decrement = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER); 6481 6482 /* Test */ 6483 bool result = true; 6484 6485 if (false == testSSBODraw(increment, expected_incremented)) 6486 { 6487 result = false; 6488 } 6489 6490 if (false == testSSBODraw(decrement, expected_decremented)) 6491 { 6492 result = false; 6493 } 6494 6495 /* Done */ 6496 return result; 6497} 6498 6499/** Execute draw call and verify results 6500 * 6501 * @param subroutine_index Index of subroutine that shall be used by draw call 6502 * @param expected_results Expected results 6503 * 6504 * 6505 **/ 6506bool FunctionalTest12::testSSBODraw(GLuint subroutine_index, const GLuint expected_results[4]) const 6507{ 6508 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6509 6510 /* Set subroutine uniforms */ 6511 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index); 6512 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 6513 6514 /* Draw */ 6515 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 6516 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 6517 6518 /* Capture results */ 6519 GLuint* ssbo_results = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY); 6520 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 6521 6522 /* Verify */ 6523 bool result = (0 == memcmp(expected_results, ssbo_results, 4 * sizeof(GLuint))); 6524 6525 if (false == result) 6526 { 6527 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result. " 6528 << "Result: [ " << ssbo_results[0] << ", " << ssbo_results[1] << ", " 6529 << ssbo_results[2] << ", " << ssbo_results[3] << " ] " 6530 << "Expected: [ " << expected_results[0] << ", " << expected_results[1] 6531 << ", " << expected_results[2] << ", " << expected_results[3] << " ]" 6532 << tcu::TestLog::EndMessage; 6533 } 6534 6535 /* Unmap buffer */ 6536 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 6537 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 6538 6539 /* Done */ 6540 return result; 6541} 6542 6543/** Check if texture is filled with expected color 6544 * 6545 * @param texture Texture instance 6546 * @param expected_color Expected color 6547 * 6548 * @return true if texture is filled with specified color, false otherwise 6549 **/ 6550bool FunctionalTest12::verifyTexture(Utils::texture& texture, const GLuint expected_color[4]) const 6551{ 6552 std::vector<GLuint> results; 6553 results.resize(m_texture_width * m_texture_height * 4); 6554 6555 texture.get(GL_RGBA_INTEGER, GL_UNSIGNED_INT, &results[0]); 6556 6557 for (GLuint y = 0; y < m_texture_height; ++y) 6558 { 6559 const GLuint line_offset = y * m_texture_width * 4; 6560 6561 for (GLuint x = 0; x < m_texture_width; ++x) 6562 { 6563 const GLuint point_offset = line_offset + x * 4; 6564 bool result = true; 6565 6566 result = result && (results[point_offset + 0] == expected_color[0]); 6567 result = result && (results[point_offset + 1] == expected_color[1]); 6568 result = result && (results[point_offset + 2] == expected_color[2]); 6569 result = result && (results[point_offset + 3] == expected_color[3]); 6570 6571 if (false == result) 6572 { 6573 return false; 6574 } 6575 } 6576 } 6577 6578 return true; 6579} 6580 6581/** Constructor. 6582 * 6583 * @param context Rendering context. 6584 * 6585 **/ 6586FunctionalTest13::FunctionalTest13(deqp::Context& context) 6587 : TestCase(context, "subroutines_with_separate_shader_objects", 6588 "Verifies that subroutines work correctly when used in separate " 6589 "shader objects") 6590 , m_fbo_id(0) 6591 , m_pipeline_id(0) 6592 , m_read_buffer(DE_NULL) 6593 , m_to_height(4) 6594 , m_to_id(0) 6595 , m_to_width(4) 6596 , m_vao_id(0) 6597 , m_has_test_passed(true) 6598{ 6599 memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids)); 6600 memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids)); 6601 memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids)); 6602 memset(m_te_po_ids, 0, sizeof(m_te_po_ids)); 6603 memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids)); 6604} 6605 6606/** Deinitializes all GL objects that may have been created during test 6607 * execution, as well as releases all process-side buffers that may have 6608 * been allocated during the process. 6609 * The function also restores default GL state configuration. 6610 **/ 6611void FunctionalTest13::deinit() 6612{ 6613 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6614 6615 if (m_fbo_id != 0) 6616 { 6617 gl.deleteFramebuffers(1, &m_fbo_id); 6618 6619 m_fbo_id = 0; 6620 } 6621 6622 if (m_pipeline_id != 0) 6623 { 6624 gl.deleteProgramPipelines(1, &m_pipeline_id); 6625 6626 m_pipeline_id = 0; 6627 } 6628 6629 if (m_read_buffer != DE_NULL) 6630 { 6631 delete[] m_read_buffer; 6632 6633 m_read_buffer = DE_NULL; 6634 } 6635 6636 for (unsigned int n_id = 0; n_id < 2 /* po id variants */; ++n_id) 6637 { 6638 if (m_fs_po_ids[n_id] != 0) 6639 { 6640 gl.deleteProgram(m_fs_po_ids[n_id]); 6641 6642 m_fs_po_ids[n_id] = 0; 6643 } 6644 6645 if (m_gs_po_ids[n_id] != 0) 6646 { 6647 gl.deleteProgram(m_gs_po_ids[n_id]); 6648 6649 m_gs_po_ids[n_id] = 0; 6650 } 6651 6652 if (m_tc_po_ids[n_id] != 0) 6653 { 6654 gl.deleteProgram(m_tc_po_ids[n_id]); 6655 6656 m_tc_po_ids[n_id] = 0; 6657 } 6658 6659 if (m_te_po_ids[n_id] != 0) 6660 { 6661 gl.deleteProgram(m_te_po_ids[n_id]); 6662 6663 m_te_po_ids[n_id] = 0; 6664 } 6665 6666 if (m_vs_po_ids[n_id] != 0) 6667 { 6668 gl.deleteProgram(m_vs_po_ids[n_id]); 6669 6670 m_vs_po_ids[n_id] = 0; 6671 } 6672 } /* for (both shader program object variants) */ 6673 6674 if (m_to_id != 0) 6675 { 6676 gl.deleteTextures(1, &m_to_id); 6677 6678 m_to_id = 0; 6679 } 6680 6681 if (m_vao_id != 0) 6682 { 6683 gl.deleteVertexArrays(1, &m_vao_id); 6684 6685 m_vao_id = 0; 6686 } 6687 6688 /* Restore default GL_PATCH_VERTICES setting value */ 6689 gl.patchParameteri(GL_PATCH_VERTICES, 3); 6690 6691 /* Restore default GL_PACK_ALIGNMENT setting value */ 6692 gl.pixelStorei(GL_PACK_ALIGNMENT, 4); 6693} 6694 6695/** Retrieves body of a fragment shader that should be used for the test. 6696 * The subroutine implementations are slightly changed, depending on the 6697 * index of the shader, as specified by the caller. 6698 * 6699 * @param n_id Index of the shader. 6700 * 6701 * @return Requested string. 6702 **/ 6703std::string FunctionalTest13::getFragmentShaderBody(unsigned int n_id) 6704{ 6705 std::stringstream result_sstream; 6706 6707 /* Pre-amble */ 6708 result_sstream << "#version 400\n" 6709 "\n" 6710 "#extension GL_ARB_shader_subroutine : require\n" 6711 "\n" 6712 /* Sub-routine */ 6713 "subroutine void SubroutineFSType(inout vec4 result);\n" 6714 "\n" 6715 "subroutine(SubroutineFSType) void SubroutineFS1(inout vec4 result)\n" 6716 "{\n" 6717 " result += vec4(" 6718 << float(n_id + 1) / 10.0f << ", " << float(n_id + 2) / 10.0f << ", " << float(n_id + 3) / 10.0f 6719 << ", " << float(n_id + 4) / 10.0f 6720 << ");\n" 6721 "}\n" 6722 "subroutine(SubroutineFSType) void SubroutineFS2(inout vec4 result)\n" 6723 "{\n" 6724 " result += vec4(" 6725 << float(n_id + 1) / 20.0f << ", " << float(n_id + 2) / 20.0f << ", " << float(n_id + 3) / 20.0f 6726 << ", " << float(n_id + 4) / 20.0f << ");\n" 6727 "}\n" 6728 "\n" 6729 "subroutine uniform SubroutineFSType function;\n" 6730 "\n" 6731 /* Input block */ 6732 "in GS_DATA\n" 6733 "{\n" 6734 " vec4 data;\n" 6735 "} in_gs;\n" 6736 "\n" 6737 "out vec4 result;\n" 6738 /* main() declaration */ 6739 "void main()\n" 6740 "{\n" 6741 " vec4 data = in_gs.data;\n" 6742 " function(data);\n" 6743 "\n" 6744 " result = data;\n" 6745 "}\n"; 6746 6747 return result_sstream.str(); 6748} 6749 6750/** Retrieves body of a geometry shader that should be used for the test. 6751 * The subroutine implementations are slightly changed, depending on the 6752 * index of the shader, as specified by the caller. 6753 * 6754 * @param n_id Index of the shader. 6755 * 6756 * @return Requested string. 6757 **/ 6758std::string FunctionalTest13::getGeometryShaderBody(unsigned int n_id) 6759{ 6760 std::stringstream result_sstream; 6761 6762 /* Pre-amble */ 6763 result_sstream << "#version 400\n" 6764 "\n" 6765 "#extension GL_ARB_shader_subroutine : require\n" 6766 "\n" 6767 "layout(points) in;\n" 6768 "layout(triangle_strip, max_vertices = 4) out;\n" 6769 /* Sub-routine */ 6770 "subroutine void SubroutineGSType(inout vec4 result);\n" 6771 "\n" 6772 "subroutine(SubroutineGSType) void SubroutineGS1(inout vec4 result)\n" 6773 "{\n" 6774 " result += vec4(0, 0, 0, " 6775 << float(n_id + 1) * 0.425f << ");\n" 6776 "}\n" 6777 "subroutine(SubroutineGSType) void SubroutineGS2(inout vec4 result)\n" 6778 "{\n" 6779 " result += vec4(0, 0, 0, " 6780 << float(n_id + 1) * 0.0425f << ");\n" 6781 "}\n" 6782 "\n" 6783 "subroutine uniform SubroutineGSType function;\n" 6784 "\n" 6785 /* Input block */ 6786 "in TE_DATA\n" 6787 "{\n" 6788 " vec4 data;\n" 6789 "} in_te[];\n" 6790 "\n" 6791 /* Output block */ 6792 "out GS_DATA\n" 6793 "{\n" 6794 " vec4 data;\n" 6795 "} out_gs;\n" 6796 "\n" 6797 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 6798 "out gl_PerVertex { vec4 gl_Position; };\n" 6799 /* main() declaration */ 6800 "void main()\n" 6801 "{\n" 6802 " vec4 data = in_te[0].data;\n" 6803 "\n" 6804 " function(data);\n" 6805 "\n" 6806 " gl_Position = vec4(1, -1, 0, 1);\n" 6807 " out_gs.data = data;\n" 6808 " EmitVertex();\n" 6809 "\n" 6810 " gl_Position = vec4(-1, -1, 0, 1);\n" 6811 " out_gs.data = data;\n" 6812 " EmitVertex();\n" 6813 "\n" 6814 " gl_Position = vec4(1, 1, 0, 1);\n" 6815 " out_gs.data = data;\n" 6816 " EmitVertex();\n" 6817 "\n" 6818 " gl_Position = vec4(-1, 1, 0, 1);\n" 6819 " out_gs.data = data;\n" 6820 " EmitVertex();\n" 6821 " EndPrimitive();\n" 6822 "}\n"; 6823 6824 return result_sstream.str(); 6825} 6826 6827/** Retrieves body of a tessellation control shader that should be used for the test. 6828 * The subroutine implementations are slightly changed, depending on the 6829 * index of the shader, as specified by the caller. 6830 * 6831 * @param n_id Index of the shader. 6832 * 6833 * @return Requested string. 6834 **/ 6835std::string FunctionalTest13::getTessellationControlShaderBody(unsigned int n_id) 6836{ 6837 std::stringstream result_sstream; 6838 6839 /* Pre-amble */ 6840 result_sstream << "#version 400\n" 6841 "\n" 6842 "#extension GL_ARB_shader_subroutine : require\n" 6843 "\n" 6844 "layout(vertices = 4) out;\n" 6845 /* Sub-routine */ 6846 "subroutine void SubroutineTCType(inout vec4 result);\n" 6847 "\n" 6848 "subroutine(SubroutineTCType) void SubroutineTC1(inout vec4 result)\n" 6849 "{\n" 6850 " result += vec4(0, " 6851 << float(n_id + 1) * 0.25f << ", 0, 0);\n" 6852 "}\n" 6853 "subroutine(SubroutineTCType) void SubroutineTC2(inout vec4 result)\n" 6854 "{\n" 6855 " result += vec4(0, " 6856 << float(n_id + 1) * 0.025f 6857 << ", 0, 0);\n" 6858 "}\n" 6859 "\n" 6860 "subroutine uniform SubroutineTCType function;\n" 6861 "\n" 6862 /* Input block */ 6863 "in VS_DATA\n" 6864 "{\n" 6865 " vec4 data;\n" 6866 "} in_vs[];\n" 6867 "\n" 6868 /* Output block */ 6869 "out TC_DATA\n" 6870 "{\n" 6871 " vec4 data;\n" 6872 "} out_tc[];\n" 6873 "\n" 6874 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 6875 "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n" 6876 /* main() declaration */ 6877 "void main()\n" 6878 "{\n" 6879 " gl_TessLevelOuter[0] = 1.0;\n" 6880 " gl_TessLevelOuter[1] = 1.0;\n" 6881 " gl_TessLevelOuter[2] = 1.0;\n" 6882 " gl_TessLevelOuter[3] = 1.0;\n" 6883 " gl_TessLevelInner[0] = 1.0;\n" 6884 " gl_TessLevelInner[1] = 1.0;\n" 6885 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n" 6886 " out_tc[gl_InvocationID].data = in_vs[0].data;\n" 6887 "\n" 6888 " function(out_tc[gl_InvocationID].data);\n" 6889 "}\n"; 6890 6891 return result_sstream.str(); 6892} 6893 6894/** Retrieves body of a tessellation evaluation shader that should be used for the test. 6895 * The subroutine implementations are slightly changed, depending on the 6896 * index of the shader, as specified by the caller. 6897 * 6898 * @param n_id Index of the shader. 6899 * 6900 * @return Requested string. 6901 **/ 6902std::string FunctionalTest13::getTessellationEvaluationShaderBody(unsigned int n_id) 6903{ 6904 std::stringstream result_sstream; 6905 6906 /* Pre-amble */ 6907 result_sstream << "#version 400\n" 6908 "\n" 6909 "#extension GL_ARB_shader_subroutine : require\n" 6910 "\n" 6911 "layout(quads, point_mode) in;\n" 6912 /* Sub-routine */ 6913 "subroutine void SubroutineTEType(inout vec4 result);\n" 6914 "\n" 6915 "subroutine(SubroutineTEType) void SubroutineTE1(inout vec4 result)\n" 6916 "{\n" 6917 " result += vec4(0, 0, " 6918 << float(n_id + 1) * 0.325f << ", 0);\n" 6919 "}\n" 6920 "subroutine(SubroutineTEType) void SubroutineTE2(inout vec4 result)\n" 6921 "{\n" 6922 " result += vec4(0, 0, " 6923 << float(n_id + 1) * 0.0325f << ", 0);\n" 6924 "}\n" 6925 "\n" 6926 "subroutine uniform SubroutineTEType function;\n" 6927 "\n" 6928 /* Input block */ 6929 "in TC_DATA\n" 6930 "{\n" 6931 " vec4 data;\n" 6932 "} in_tc[];\n" 6933 "\n" 6934 /* Output block */ 6935 "out TE_DATA\n" 6936 "{\n" 6937 " vec4 data;\n" 6938 "} out_te;\n" 6939 "\n" 6940 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 6941 "out gl_PerVertex { vec4 gl_Position; };\n" 6942 /* main() declaration */ 6943 "void main()\n" 6944 "{\n" 6945 " gl_Position = gl_in[0].gl_Position;\n" 6946 " out_te.data = in_tc[0].data;\n" 6947 "\n" 6948 " function(out_te.data);\n" 6949 "}\n"; 6950 6951 return result_sstream.str(); 6952} 6953 6954/** Retrieves body of a vertex shader that should be used for the test. 6955 * The subroutine implementations are slightly changed, depending on the 6956 * index of the shader, as specified by the caller. 6957 * 6958 * @param n_id Index of the shader. 6959 * 6960 * @return Requested string. 6961 **/ 6962std::string FunctionalTest13::getVertexShaderBody(unsigned int n_id) 6963{ 6964 std::stringstream result_sstream; 6965 6966 /* Pre-amble */ 6967 result_sstream << "#version 400\n" 6968 "\n" 6969 "#extension GL_ARB_shader_subroutine : require\n" 6970 "#extension GL_ARB_separate_shader_objects: require\n" 6971 "\n" 6972 /* Sub-routine */ 6973 "subroutine void SubroutineVSType(inout vec4 result);\n" 6974 "\n" 6975 "subroutine(SubroutineVSType) void SubroutineVS1(inout vec4 result)\n" 6976 "{\n" 6977 " result += vec4(" 6978 << float(n_id + 1) * 0.125f << ", 0, 0, 0);\n" 6979 "}\n" 6980 "subroutine(SubroutineVSType) void SubroutineVS2(inout vec4 result)\n" 6981 "{\n" 6982 " result += vec4(" 6983 << float(n_id + 1) * 0.0125f << ", 0, 0, 0);\n" 6984 "}\n" 6985 "\n" 6986 "subroutine uniform SubroutineVSType function;\n" 6987 "\n" 6988 /* Output block */ 6989 "out VS_DATA\n" 6990 "{\n" 6991 " vec4 data;\n" 6992 "} out_vs;\n" 6993 "\n" 6994 "out gl_PerVertex { vec4 gl_Position; };\n" 6995 /* main() declaration */ 6996 "void main()\n" 6997 "{\n" 6998 " gl_Position = vec4(0, 0, 0, 1);\n" 6999 " out_vs.data = vec4(0);\n" 7000 "\n" 7001 " function(out_vs.data);\n" 7002 "\n" 7003 "}\n"; 7004 7005 return result_sstream.str(); 7006} 7007 7008/** Initializes all GL objects required to run the test. Also modifies a few 7009 * GL states in order for the test to run correctly. 7010 **/ 7011void FunctionalTest13::initTest() 7012{ 7013 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7014 7015 /* Set up viewport */ 7016 gl.viewport(0 /* x */, 0 /* y */, m_to_width, m_to_height); 7017 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed."); 7018 7019 /* Make sure no program is used */ 7020 gl.useProgram(0); 7021 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 7022 7023 /* Generate a pipeline object */ 7024 gl.genProgramPipelines(1, &m_pipeline_id); 7025 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); 7026 7027 gl.bindProgramPipeline(m_pipeline_id); 7028 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 7029 7030 /* Initialize all shader programs */ 7031 for (unsigned int n_id = 0; n_id < 2 /* variants for each shader type */; ++n_id) 7032 { 7033 std::string fs_body = getFragmentShaderBody(n_id); 7034 const char* fs_body_raw_ptr = fs_body.c_str(); 7035 std::string gs_body = getGeometryShaderBody(n_id); 7036 const char* gs_body_raw_ptr = gs_body.c_str(); 7037 std::string tc_body = getTessellationControlShaderBody(n_id); 7038 const char* tc_body_raw_ptr = tc_body.c_str(); 7039 std::string te_body = getTessellationEvaluationShaderBody(n_id); 7040 const char* te_body_raw_ptr = te_body.c_str(); 7041 std::string vs_body = getVertexShaderBody(n_id); 7042 const char* vs_body_raw_ptr = vs_body.c_str(); 7043 7044 m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr); 7045 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7046 7047 m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr); 7048 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7049 7050 m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr); 7051 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7052 7053 m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr); 7054 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7055 7056 m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr); 7057 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 7058 7059 /* Verify that all shader program objects have been linked successfully */ 7060 const glw::GLuint po_ids[] = { 7061 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], 7062 }; 7063 const unsigned int n_po_ids = sizeof(po_ids) / sizeof(po_ids[0]); 7064 7065 for (unsigned int n_po_id = 0; n_po_id < n_po_ids; ++n_po_id) 7066 { 7067 glw::GLint link_status = GL_FALSE; 7068 glw::GLuint po_id = po_ids[n_po_id]; 7069 7070 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 7071 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 7072 7073 if (link_status != GL_TRUE) 7074 { 7075 TCU_FAIL("Shader program object linking failed."); 7076 } 7077 } /* for (all shader program objects) */ 7078 } /* for (both shader program object variants) */ 7079 7080 /* Generate a texture object. We will use the base mip-map as a render-target */ 7081 gl.genTextures(1, &m_to_id); 7082 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 7083 7084 gl.bindTexture(GL_TEXTURE_2D, m_to_id); 7085 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 7086 7087 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA32F, m_to_width, m_to_height); 7088 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed"); 7089 7090 /* Generate and configure a FBO we will use for the draw call */ 7091 gl.genFramebuffers(1, &m_fbo_id); 7092 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed."); 7093 7094 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 7095 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 7096 7097 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */); 7098 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 7099 7100 /* Generate & bind a VAO */ 7101 gl.genVertexArrays(1, &m_vao_id); 7102 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 7103 7104 gl.bindVertexArray(m_vao_id); 7105 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 7106 7107 /* Set up tessellation */ 7108 gl.patchParameteri(GL_PATCH_VERTICES, 1); 7109 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed."); 7110 7111 /* Set up pixel storage alignment */ 7112 gl.pixelStorei(GL_PACK_ALIGNMENT, 1); 7113 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed."); 7114 7115 /* Allocate enough space to hold color attachment data */ 7116 m_read_buffer = (unsigned char*)new float[m_to_width * m_to_height * 4 /* rgba */]; 7117} 7118 7119/** Executes test iteration. 7120 * 7121 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 7122 */ 7123tcu::TestNode::IterateResult FunctionalTest13::iterate() 7124{ 7125 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7126 7127 /* Do not execute the test if GL_ARB_shader_subroutine and GL_ARB_separate_shader_objects 7128 * are not supported */ 7129 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 7130 { 7131 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 7132 } 7133 7134 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects")) 7135 { 7136 throw tcu::NotSupportedError("GL_ARB_separate_shader_objects is not supported"); 7137 } 7138 7139 /* Initialize all GL objects before we continue */ 7140 initTest(); 7141 7142 /* Iterate over all possible FS/GS/TC/TE/VS permutations */ 7143 for (int n_shader_permutation = 0; n_shader_permutation < 32 /* 2^5 */; ++n_shader_permutation) 7144 { 7145 const unsigned int n_fs_idx = ((n_shader_permutation & (1 << 0)) != 0) ? 1 : 0; 7146 const unsigned int n_gs_idx = ((n_shader_permutation & (1 << 1)) != 0) ? 1 : 0; 7147 const unsigned int n_tc_idx = ((n_shader_permutation & (1 << 2)) != 0) ? 1 : 0; 7148 const unsigned int n_te_idx = ((n_shader_permutation & (1 << 3)) != 0) ? 1 : 0; 7149 const unsigned int n_vs_idx = ((n_shader_permutation & (1 << 4)) != 0) ? 1 : 0; 7150 const unsigned int fs_po_id = m_fs_po_ids[n_fs_idx]; 7151 const unsigned int gs_po_id = m_gs_po_ids[n_gs_idx]; 7152 const unsigned int tc_po_id = m_tc_po_ids[n_tc_idx]; 7153 const unsigned int te_po_id = m_te_po_ids[n_te_idx]; 7154 const unsigned int vs_po_id = m_vs_po_ids[n_vs_idx]; 7155 7156 /* Configure fragment shader stage */ 7157 gl.useProgramStages(m_pipeline_id, GL_FRAGMENT_SHADER_BIT, fs_po_id); 7158 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_FRAGMENT_SHADER_BIT bit"); 7159 7160 /* Configure geometry shader stage */ 7161 gl.useProgramStages(m_pipeline_id, GL_GEOMETRY_SHADER_BIT, gs_po_id); 7162 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_GEOMETRY_SHADER_BIT bit"); 7163 7164 /* Configure tessellation control shader stage */ 7165 gl.useProgramStages(m_pipeline_id, GL_TESS_CONTROL_SHADER_BIT, tc_po_id); 7166 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_CONTROL_SHADER_BIT bit"); 7167 7168 /* Configure tessellation evaluation shader stage */ 7169 gl.useProgramStages(m_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT, te_po_id); 7170 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_EVALUATION_SHADER_BIT bit"); 7171 7172 /* Configure vertex shader stage */ 7173 gl.useProgramStages(m_pipeline_id, GL_VERTEX_SHADER_BIT, vs_po_id); 7174 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_VERTEX_SHADER_BIT bit"); 7175 7176 /* Validate the pipeline */ 7177 glw::GLint validate_status = GL_FALSE; 7178 7179 gl.validateProgramPipeline(m_pipeline_id); 7180 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed."); 7181 7182 gl.getProgramPipelineiv(m_pipeline_id, GL_VALIDATE_STATUS, &validate_status); 7183 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed."); 7184 7185 if (validate_status != GL_TRUE) 7186 { 7187 TCU_FAIL("Program pipeline has not been validated successfully."); 7188 } 7189 7190 /* Retrieve subroutine indices */ 7191 GLuint fs_subroutine_indices[2] = { (GLuint)-1 }; 7192 GLint fs_subroutine_uniform_index = 0; 7193 GLuint gs_subroutine_indices[2] = { (GLuint)-1 }; 7194 GLint gs_subroutine_uniform_index = 0; 7195 GLuint tc_subroutine_indices[2] = { (GLuint)-1 }; 7196 GLint tc_subroutine_uniform_index = 0; 7197 GLuint te_subroutine_indices[2] = { (GLuint)-1 }; 7198 GLint te_subroutine_uniform_index = 0; 7199 GLuint vs_subroutine_indices[2] = { (GLuint)-1 }; 7200 GLint vs_subroutine_uniform_index = 0; 7201 7202 for (unsigned int n_subroutine = 0; n_subroutine < 2; ++n_subroutine) 7203 { 7204 std::stringstream fs_subroutine_name_sstream; 7205 std::stringstream gs_subroutine_name_sstream; 7206 std::stringstream tc_subroutine_name_sstream; 7207 std::stringstream te_subroutine_name_sstream; 7208 std::stringstream vs_subroutine_name_sstream; 7209 7210 fs_subroutine_name_sstream << "SubroutineFS" << (n_subroutine + 1); 7211 gs_subroutine_name_sstream << "SubroutineGS" << (n_subroutine + 1); 7212 tc_subroutine_name_sstream << "SubroutineTC" << (n_subroutine + 1); 7213 te_subroutine_name_sstream << "SubroutineTE" << (n_subroutine + 1); 7214 vs_subroutine_name_sstream << "SubroutineVS" << (n_subroutine + 1); 7215 7216 fs_subroutine_indices[n_subroutine] = 7217 gl.getSubroutineIndex(fs_po_id, GL_FRAGMENT_SHADER, fs_subroutine_name_sstream.str().c_str()); 7218 gs_subroutine_indices[n_subroutine] = 7219 gl.getSubroutineIndex(gs_po_id, GL_GEOMETRY_SHADER, gs_subroutine_name_sstream.str().c_str()); 7220 tc_subroutine_indices[n_subroutine] = 7221 gl.getSubroutineIndex(tc_po_id, GL_TESS_CONTROL_SHADER, tc_subroutine_name_sstream.str().c_str()); 7222 te_subroutine_indices[n_subroutine] = 7223 gl.getSubroutineIndex(te_po_id, GL_TESS_EVALUATION_SHADER, te_subroutine_name_sstream.str().c_str()); 7224 vs_subroutine_indices[n_subroutine] = 7225 gl.getSubroutineIndex(vs_po_id, GL_VERTEX_SHADER, vs_subroutine_name_sstream.str().c_str()); 7226 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 7227 7228 if (fs_subroutine_indices[n_subroutine] == (GLuint)-1 || 7229 gs_subroutine_indices[n_subroutine] == (GLuint)-1 || 7230 tc_subroutine_indices[n_subroutine] == (GLuint)-1 || 7231 te_subroutine_indices[n_subroutine] == (GLuint)-1 || vs_subroutine_indices[n_subroutine] == (GLuint)-1) 7232 { 7233 m_testCtx.getLog() << tcu::TestLog::Message 7234 << "At least one subroutine was not recognized by glGetSubroutineIndex() call. " 7235 "(fs:" 7236 << fs_subroutine_indices[n_subroutine] 7237 << ", gs:" << gs_subroutine_indices[n_subroutine] 7238 << ", tc:" << tc_subroutine_indices[n_subroutine] 7239 << ", te:" << te_subroutine_indices[n_subroutine] 7240 << ", vs:" << vs_subroutine_indices[n_subroutine] << ")." 7241 << tcu::TestLog::EndMessage; 7242 7243 TCU_FAIL("At least one subroutine was not recognized"); 7244 } 7245 } /* for (both subroutines) */ 7246 7247 /* Retrieve subroutine uniform indices */ 7248 fs_subroutine_uniform_index = gl.getSubroutineUniformLocation(fs_po_id, GL_FRAGMENT_SHADER, "function"); 7249 gs_subroutine_uniform_index = gl.getSubroutineUniformLocation(gs_po_id, GL_GEOMETRY_SHADER, "function"); 7250 tc_subroutine_uniform_index = gl.getSubroutineUniformLocation(tc_po_id, GL_TESS_CONTROL_SHADER, "function"); 7251 te_subroutine_uniform_index = gl.getSubroutineUniformLocation(te_po_id, GL_TESS_EVALUATION_SHADER, "function"); 7252 vs_subroutine_uniform_index = gl.getSubroutineUniformLocation(vs_po_id, GL_VERTEX_SHADER, "function"); 7253 7254 if (fs_subroutine_uniform_index == -1 || gs_subroutine_uniform_index == -1 || 7255 tc_subroutine_uniform_index == -1 || te_subroutine_uniform_index == -1 || vs_subroutine_uniform_index == -1) 7256 { 7257 m_testCtx.getLog() << tcu::TestLog::Message << "At least one subroutine uniform is considered inactive by " 7258 "glGetSubroutineUniformLocation (" 7259 "fs:" 7260 << fs_subroutine_uniform_index << ", gs:" << gs_subroutine_uniform_index 7261 << ", tc:" << tc_subroutine_uniform_index << ", te:" << te_subroutine_uniform_index 7262 << ", vs:" << vs_subroutine_uniform_index << ")." << tcu::TestLog::EndMessage; 7263 7264 TCU_FAIL("At least one subroutine uniform is considered inactive"); 7265 } 7266 7267 /* Check if both subroutines work correctly in each stage */ 7268 for (int n_subroutine_permutation = 0; n_subroutine_permutation < 32; /* 2^5 */ 7269 ++n_subroutine_permutation) 7270 { 7271 unsigned int n_fs_subroutine = ((n_subroutine_permutation & (1 << 0)) != 0) ? 1 : 0; 7272 unsigned int n_gs_subroutine = ((n_subroutine_permutation & (1 << 1)) != 0) ? 1 : 0; 7273 unsigned int n_tc_subroutine = ((n_subroutine_permutation & (1 << 2)) != 0) ? 1 : 0; 7274 unsigned int n_te_subroutine = ((n_subroutine_permutation & (1 << 3)) != 0) ? 1 : 0; 7275 unsigned int n_vs_subroutine = ((n_subroutine_permutation & (1 << 4)) != 0) ? 1 : 0; 7276 7277 /* Configure subroutine uniforms */ 7278 struct 7279 { 7280 glw::GLenum stage; 7281 glw::GLuint po_id; 7282 glw::GLuint* indices; 7283 } configurations[] = { 7284 { GL_FRAGMENT_SHADER, fs_po_id, fs_subroutine_indices + n_fs_subroutine }, 7285 { GL_GEOMETRY_SHADER, gs_po_id, gs_subroutine_indices + n_gs_subroutine }, 7286 { GL_TESS_CONTROL_SHADER, tc_po_id, tc_subroutine_indices + n_tc_subroutine }, 7287 { GL_TESS_EVALUATION_SHADER, te_po_id, te_subroutine_indices + n_te_subroutine }, 7288 { GL_VERTEX_SHADER, vs_po_id, vs_subroutine_indices + n_vs_subroutine }, 7289 }; 7290 7291 for (int i = 0; i < 5; ++i) 7292 { 7293 gl.activeShaderProgram(m_pipeline_id, configurations[i].po_id); 7294 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveShaderProgram() call failed."); 7295 7296 gl.uniformSubroutinesuiv(configurations[i].stage, 1 /* count */, configurations[i].indices); 7297 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed."); 7298 } 7299 7300 /* Render a full-screen quad with the pipeline */ 7301 gl.clear(GL_COLOR_BUFFER_BIT); 7302 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed."); 7303 7304 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */); 7305 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 7306 7307 /* Read color attachment's contents */ 7308 gl.readPixels(0, /* x */ 7309 0, /* y */ 7310 m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_read_buffer); 7311 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 7312 7313 /* Verify the contents */ 7314 verifyReadBuffer(n_fs_idx, n_fs_subroutine, n_gs_idx, n_gs_subroutine, n_tc_idx, n_tc_subroutine, n_te_idx, 7315 n_te_subroutine, n_vs_idx, n_vs_subroutine); 7316 } /* for (all subroutine permutations) */ 7317 } /* for (all program shader object permutations) */ 7318 7319 /** All done */ 7320 if (m_has_test_passed) 7321 { 7322 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 7323 } 7324 else 7325 { 7326 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 7327 } 7328 7329 return STOP; 7330} 7331 7332/** Verifies the data that have been rendered using a pipeline object. 7333 * Contents of the data depends on indices of the shaders, as well as 7334 * on the subroutines that have been activated for particular iteration. 7335 * 7336 * @param n_fs_id Index of the fragment shader used for the iteration; 7337 * @param n_fs_subroutine Index of the subroutine used in the fragment shader 7338 * for the iteration; 7339 * @param n_gs_id Index of the geometry shader used for the iteration; 7340 * @param n_gs_subroutine Index of the subroutine used in the geometry shader 7341 * for the iteration; 7342 * @param n_tc_id Index of the tessellation control shader used for the iteration; 7343 * @param n_tc_subroutine Index of the subroutine used in the tessellation control 7344 * shader for the iteration; 7345 * @param n_te_id Index of the tessellation evaluation shader used for the iteration; 7346 * @param n_te_subroutine Index of the subroutine used in the tessellation evaluation 7347 * shader for the iteration; 7348 * @param n_vs_id Index of the vertex shader used for the iteration; 7349 * @param n_vs_subroutine Index of the subroutine used in the vertex shader for 7350 * the iteration. 7351 */ 7352void FunctionalTest13::verifyReadBuffer(unsigned int n_fs_id, unsigned int n_fs_subroutine, unsigned int n_gs_id, 7353 unsigned int n_gs_subroutine, unsigned int n_tc_id, 7354 unsigned int n_tc_subroutine, unsigned int n_te_id, 7355 unsigned int n_te_subroutine, unsigned int n_vs_id, 7356 unsigned int n_vs_subroutine) 7357{ 7358 float expected_color[4] = { 0 }; 7359 float fs_modifier[4] = { 0 }; 7360 float gs_modifier[4] = { 0 }; 7361 float tc_modifier[4] = { 0 }; 7362 float te_modifier[4] = { 0 }; 7363 float vs_modifier[4] = { 0 }; 7364 7365 if (n_fs_subroutine == 0) 7366 { 7367 for (unsigned int n_component = 0; n_component < 4; ++n_component) 7368 { 7369 fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 10.0f; 7370 } 7371 } 7372 else 7373 { 7374 for (unsigned int n_component = 0; n_component < 4; ++n_component) 7375 { 7376 fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 20.0f; 7377 } 7378 } 7379 7380 if (n_gs_subroutine == 0) 7381 { 7382 gs_modifier[3] = float(n_gs_id + 1) * 0.425f; 7383 } 7384 else 7385 { 7386 gs_modifier[3] = float(n_gs_id + 1) * 0.0425f; 7387 } 7388 7389 if (n_tc_subroutine == 0) 7390 { 7391 tc_modifier[1] = float(n_tc_id + 1) * 0.25f; 7392 } 7393 else 7394 { 7395 tc_modifier[1] = float(n_tc_id + 1) * 0.025f; 7396 } 7397 7398 if (n_te_subroutine == 0) 7399 { 7400 te_modifier[2] = float(n_te_id + 1) * 0.325f; 7401 } 7402 else 7403 { 7404 te_modifier[2] = float(n_te_id + 1) * 0.0325f; 7405 } 7406 7407 if (n_vs_subroutine == 0) 7408 { 7409 vs_modifier[0] = float(n_vs_id + 1) * 0.125f; 7410 } 7411 else 7412 { 7413 vs_modifier[0] = float(n_vs_id + 1) * 0.0125f; 7414 } 7415 7416 /* Determine the expected color */ 7417 for (unsigned int n_component = 0; n_component < 4 /* rgba */; ++n_component) 7418 { 7419 expected_color[n_component] = fs_modifier[n_component] + gs_modifier[n_component] + tc_modifier[n_component] + 7420 te_modifier[n_component] + vs_modifier[n_component]; 7421 } 7422 7423 /* Verify all read texels are valid */ 7424 const float epsilon = 1e-5f; 7425 bool should_continue = true; 7426 7427 for (unsigned int y = 0; y < m_to_height && should_continue; ++y) 7428 { 7429 const float* row_ptr = (const float*)m_read_buffer + y * m_to_width * 4; /* rgba */ 7430 7431 for (unsigned int x = 0; x < m_to_width && should_continue; ++x) 7432 { 7433 const float* texel_ptr = row_ptr + x * 4; /* rgba */ 7434 7435 if (de::abs(texel_ptr[0] - expected_color[0]) > epsilon || 7436 de::abs(texel_ptr[1] - expected_color[1]) > epsilon || 7437 de::abs(texel_ptr[2] - expected_color[2]) > epsilon || 7438 de::abs(texel_ptr[3] - expected_color[3]) > epsilon) 7439 { 7440 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel rendered at (" << x << ", " << y 7441 << ") for " 7442 "the following configuration: " 7443 "n_fs_id:" 7444 << n_fs_id << " n_fs_subroutine:" << n_fs_subroutine << " n_gs_id:" << n_gs_id 7445 << " n_gs_subroutine:" << n_gs_subroutine << " n_tc_id:" << n_tc_id 7446 << " n_tc_subroutine:" << n_tc_subroutine << " n_te_id:" << n_te_id 7447 << " n_te_subroutine:" << n_te_subroutine << " n_vs_id:" << n_vs_id 7448 << " n_vs_subroutine:" << n_vs_subroutine << "; expected:" 7449 "(" 7450 << expected_color[0] << ", " << expected_color[1] << ", " << expected_color[2] 7451 << ", " << expected_color[3] << "), found:" 7452 "(" 7453 << texel_ptr[0] << ", " << texel_ptr[1] << ", " << texel_ptr[2] << ", " 7454 << texel_ptr[3] << ")." << tcu::TestLog::EndMessage; 7455 7456 m_has_test_passed = false; 7457 should_continue = false; 7458 } 7459 } /* for (all columns) */ 7460 } /* for (all rows) */ 7461} 7462 7463/** Constructor 7464 * 7465 * @param context CTS context 7466 **/ 7467FunctionalTest14_15::FunctionalTest14_15(deqp::Context& context) 7468 : TestCase(context, "structure_parameters_program_binary", "Verify structures can be used as parameters") 7469 , m_uniform_location(0) 7470{ 7471} 7472 7473/** Execute test 7474 * 7475 * @return tcu::TestNode::STOP 7476 **/ 7477tcu::TestNode::IterateResult FunctionalTest14_15::iterate() 7478{ 7479 static const GLchar* vertex_shader_code = 7480 "#version 400 core\n" 7481 "#extension GL_ARB_shader_subroutine : require\n" 7482 "\n" 7483 "precision highp float;\n" 7484 "\n" 7485 "struct data\n" 7486 "{\n" 7487 " uint r;\n" 7488 " uint g;\n" 7489 " uint b;\n" 7490 " uint a;\n" 7491 "};\n" 7492 "\n" 7493 "subroutine void routine_type_1(in data iparam, out data oparam);\n" 7494 "subroutine void routine_type_2(inout data arg);\n" 7495 "\n" 7496 "subroutine (routine_type_1) void invert(in data iparam, out data oparam)\n" 7497 "{\n" 7498 " oparam.r = iparam.a;\n" 7499 " oparam.g = iparam.b;\n" 7500 " oparam.b = iparam.g;\n" 7501 " oparam.a = iparam.r;\n" 7502 "}\n" 7503 "\n" 7504 "subroutine (routine_type_1) void increment(in data iparam, out data oparam)\n" 7505 "{\n" 7506 " oparam.r = 1 + iparam.r;\n" 7507 " oparam.g = 1 + iparam.g;\n" 7508 " oparam.b = 1 + iparam.b;\n" 7509 " oparam.a = 1 + iparam.a;\n" 7510 "}\n" 7511 "\n" 7512 "subroutine (routine_type_2) void div_by_2(inout data arg)\n" 7513 "{\n" 7514 " arg.r = arg.r / 2;\n" 7515 " arg.g = arg.g / 2;\n" 7516 " arg.b = arg.b / 2;\n" 7517 " arg.a = arg.a / 2;\n" 7518 "}\n" 7519 "\n" 7520 "subroutine (routine_type_2) void decrement(inout data arg)\n" 7521 "{\n" 7522 " arg.r = arg.r - 1;\n" 7523 " arg.g = arg.g - 1;\n" 7524 " arg.b = arg.b - 1;\n" 7525 " arg.a = arg.a - 1;\n" 7526 "}\n" 7527 "\n" 7528 "subroutine uniform routine_type_1 routine_1;\n" 7529 "subroutine uniform routine_type_2 routine_2;\n" 7530 "\n" 7531 "uniform uvec4 uni_input;\n" 7532 "\n" 7533 "out uvec4 out_routine_1;\n" 7534 "out uvec4 out_routine_2;\n" 7535 "\n" 7536 "\n" 7537 "void main()\n" 7538 "{\n" 7539 " data routine_1_input;\n" 7540 " data routine_1_output;\n" 7541 " data routine_2_arg;\n" 7542 "\n" 7543 " routine_1_input.r = uni_input.r;\n" 7544 " routine_1_input.g = uni_input.g;\n" 7545 " routine_1_input.b = uni_input.b;\n" 7546 " routine_1_input.a = uni_input.a;\n" 7547 "\n" 7548 " routine_2_arg.r = uni_input.r;\n" 7549 " routine_2_arg.g = uni_input.g;\n" 7550 " routine_2_arg.b = uni_input.b;\n" 7551 " routine_2_arg.a = uni_input.a;\n" 7552 "\n" 7553 " routine_1(routine_1_input, routine_1_output);\n" 7554 " routine_2(routine_2_arg);\n" 7555 "\n" 7556 " out_routine_1.r = routine_1_output.r;\n" 7557 " out_routine_1.g = routine_1_output.g;\n" 7558 " out_routine_1.b = routine_1_output.b;\n" 7559 " out_routine_1.a = routine_1_output.a;\n" 7560 "\n" 7561 " out_routine_2.r = routine_2_arg.r;\n" 7562 " out_routine_2.g = routine_2_arg.g;\n" 7563 " out_routine_2.b = routine_2_arg.b;\n" 7564 " out_routine_2.a = routine_2_arg.a;\n" 7565 "}\n" 7566 "\n"; 7567 7568 static const GLchar* subroutine_names[][2] = { { "invert", "increment" }, { "div_by_2", "decrement" } }; 7569 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]); 7570 7571 static const GLchar* subroutine_uniform_names[] = { "routine_1", "routine_2" }; 7572 static const GLuint n_subroutine_uniform_names = 7573 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]); 7574 7575 static const GLchar* uniform_name = "uni_input"; 7576 static const GLchar* varying_names[] = { "out_routine_1", "out_routine_2" }; 7577 7578 static const GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]); 7579 static const GLuint transform_feedback_buffer_size = n_varying_names * 4 * sizeof(GLuint); 7580 7581 /* Test data */ 7582 static const Utils::vec4<GLuint> uni_input[] = { Utils::vec4<GLuint>(8, 64, 4096, 16777216), 7583 Utils::vec4<GLuint>(8, 64, 4096, 16777216) }; 7584 7585 static const Utils::vec4<GLuint> out_routine_1[] = { Utils::vec4<GLuint>(16777216, 4096, 64, 8), 7586 Utils::vec4<GLuint>(9, 65, 4097, 16777217) }; 7587 7588 static const Utils::vec4<GLuint> out_routine_2[] = { Utils::vec4<GLuint>(4, 32, 2048, 8388608), 7589 Utils::vec4<GLuint>(7, 63, 4095, 16777215) }; 7590 7591 static const GLuint n_test_cases = 2; 7592 7593 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 7594 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 7595 { 7596 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 7597 } 7598 7599 /* GL objects */ 7600 Utils::program program(m_context); 7601 Utils::buffer transform_feedback_buffer(m_context); 7602 Utils::vertexArray vao(m_context); 7603 7604 bool is_program_binary_supported = program.isProgramBinarySupported(); 7605 7606 /* Init GL objects */ 7607 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, 7608 varying_names /* varying_names */, n_varying_names /* n_varyings */); 7609 7610 /* Do not execute the test if GL_ARB_get_program_binary is not supported */ 7611 if (true == is_program_binary_supported) 7612 { 7613 /* Get subroutine indices */ 7614 for (GLuint type = 0; type < n_subroutine_types; ++type) 7615 { 7616 m_initial_subroutine_indices[type][0] = 7617 program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER); 7618 7619 m_initial_subroutine_indices[type][1] = 7620 program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER); 7621 } 7622 7623 /* Get subroutine uniform locations */ 7624 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 7625 { 7626 m_initial_subroutine_uniform_locations[uniform] = 7627 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER); 7628 } 7629 7630 /* Delete program and recreate it from binary */ 7631 std::vector<GLubyte> program_binary; 7632 GLenum binary_format; 7633 7634 program.getBinary(program_binary, binary_format); 7635 program.remove(); 7636 program.createFromBinary(program_binary, binary_format); 7637 } 7638 7639 program.use(); 7640 7641 vao.generate(); 7642 vao.bind(); 7643 7644 transform_feedback_buffer.generate(); 7645 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */, 7646 GL_DYNAMIC_COPY); 7647 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size); 7648 7649 /* Get subroutine indices */ 7650 for (GLuint type = 0; type < n_subroutine_types; ++type) 7651 { 7652 m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER); 7653 m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER); 7654 } 7655 7656 /* Get subroutine uniform locations */ 7657 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 7658 { 7659 m_subroutine_uniform_locations[uniform] = 7660 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER); 7661 } 7662 7663 /* Get uniform locations */ 7664 m_uniform_location = program.getUniformLocation(uniform_name); 7665 7666 /* Test */ 7667 bool result = true; 7668 7669 /* Test program binary */ 7670 if (true == is_program_binary_supported) 7671 { 7672 /* Test indices and locations */ 7673 if (false == testIndicesAndLocations()) 7674 { 7675 static const GLuint n_subroutines_per_type = 2; 7676 7677 m_context.getTestContext().getLog() << tcu::TestLog::Message 7678 << "Error. Subroutine indices or subroutine uniform location changed." 7679 << tcu::TestLog::EndMessage; 7680 7681 for (GLuint type = 0; type < n_subroutine_types; ++type) 7682 { 7683 for (GLuint i = 0; i < n_subroutines_per_type; ++i) 7684 { 7685 m_context.getTestContext().getLog() 7686 << tcu::TestLog::Message << "Subroutine: " << subroutine_names[type][i] 7687 << " index: " << m_subroutine_indices[type][i] 7688 << " initial index: " << m_initial_subroutine_indices[type][i] << tcu::TestLog::EndMessage; 7689 } 7690 } 7691 7692 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform) 7693 { 7694 m_context.getTestContext().getLog() 7695 << tcu::TestLog::Message << "Subroutine uniform: " << subroutine_uniform_names[uniform] 7696 << " location: " << m_subroutine_uniform_locations[uniform] 7697 << " initial location: " << m_initial_subroutine_uniform_locations[uniform] 7698 << tcu::TestLog::EndMessage; 7699 } 7700 7701 result = false; 7702 } 7703 7704 /* Test draw with deafult set of subroutines */ 7705 if (false == testDefaultSubroutineSet(uni_input[0], out_routine_1, out_routine_2)) 7706 { 7707 result = false; 7708 } 7709 } 7710 7711 for (GLuint i = 0; i < n_test_cases; ++i) 7712 { 7713 if (false == testDraw(i, uni_input[i], out_routine_1[i], out_routine_2[i])) 7714 { 7715 result = false; 7716 } 7717 } 7718 7719 /* Set result */ 7720 if (true == result) 7721 { 7722 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 7723 } 7724 else 7725 { 7726 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 7727 } 7728 7729 /* Done */ 7730 return tcu::TestNode::STOP; 7731} 7732 7733/** Execute draw call and verify results 7734 * 7735 * @param uni_input Input data 7736 * @param expected_routine_1_result Set of expected results of "routine_1" 7737 * @param expected_routine_2_result Set of expected results of "routine_2" 7738 * 7739 * @return true if test pass, false otherwise 7740 **/ 7741bool FunctionalTest14_15::testDefaultSubroutineSet(const Utils::vec4<glw::GLuint>& uni_input, 7742 const Utils::vec4<glw::GLuint> expected_routine_1_result[2], 7743 const Utils::vec4<glw::GLuint> expected_routine_2_result[2]) const 7744{ 7745 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7746 bool result = true; 7747 7748 /* Set up input data uniforms */ 7749 gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w); 7750 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 7751 7752 /* Execute draw call with transform feedback */ 7753 gl.beginTransformFeedback(GL_POINTS); 7754 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 7755 7756 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 7757 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 7758 7759 gl.endTransformFeedback(); 7760 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 7761 7762 /* Capture results */ 7763 GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 7764 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 7765 7766 Utils::vec4<GLuint> routine_1_result; 7767 Utils::vec4<GLuint> routine_2_result; 7768 7769 routine_1_result.m_x = feedback_data[0 + 0]; 7770 routine_1_result.m_y = feedback_data[0 + 1]; 7771 routine_1_result.m_z = feedback_data[0 + 2]; 7772 routine_1_result.m_w = feedback_data[0 + 3]; 7773 7774 routine_2_result.m_x = feedback_data[4 + 0]; 7775 routine_2_result.m_y = feedback_data[4 + 1]; 7776 routine_2_result.m_z = feedback_data[4 + 2]; 7777 routine_2_result.m_w = feedback_data[4 + 3]; 7778 7779 /* Unmap buffer */ 7780 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 7781 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 7782 7783 /* Verifiy */ 7784 result = result && 7785 ((routine_1_result == expected_routine_1_result[0]) || (routine_1_result == expected_routine_1_result[1])); 7786 7787 result = result && 7788 ((routine_2_result == expected_routine_2_result[0]) || (routine_2_result == expected_routine_2_result[1])); 7789 7790 /* Log error if any */ 7791 if (false == result) 7792 { 7793 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 7794 << tcu::TestLog::EndMessage; 7795 7796 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 7797 7798 message << "Routine_1, result: "; 7799 7800 routine_1_result.log(message); 7801 7802 message << "Routine_2, result: "; 7803 7804 routine_2_result.log(message); 7805 7806 message << tcu::TestLog::EndMessage; 7807 } 7808 7809 /* Done */ 7810 return result; 7811} 7812 7813/** Execute draw call and verify results 7814 * 7815 * @param routine_configuration Subroutine "type" ordinal 7816 * @param uni_input Input data 7817 * @param expected_routine_1_result Expected results of "routine_1" 7818 * @param expected_routine_2_result Expected results of "routine_2" 7819 * 7820 * @return true if test pass, false otherwise 7821 **/ 7822bool FunctionalTest14_15::testDraw(glw::GLuint routine_configuration, const Utils::vec4<glw::GLuint>& uni_input, 7823 const Utils::vec4<glw::GLuint>& expected_routine_1_result, 7824 const Utils::vec4<glw::GLuint>& expected_routine_2_result) const 7825{ 7826 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7827 bool result = true; 7828 GLuint subroutine_indices[2]; 7829 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]); 7830 7831 /* Set up input data uniforms */ 7832 gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w); 7833 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f"); 7834 7835 /* Prepare subroutine uniform data */ 7836 for (GLuint i = 0; i < n_subroutine_uniforms; ++i) 7837 { 7838 const GLuint location = m_subroutine_uniform_locations[i]; 7839 7840 subroutine_indices[location] = m_subroutine_indices[i][routine_configuration]; 7841 } 7842 7843 /* Set up subroutine uniforms */ 7844 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]); 7845 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv"); 7846 7847 /* Execute draw call with transform feedback */ 7848 gl.beginTransformFeedback(GL_POINTS); 7849 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 7850 7851 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 7852 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 7853 7854 gl.endTransformFeedback(); 7855 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 7856 7857 /* Capture results */ 7858 GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 7859 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 7860 7861 Utils::vec4<GLuint> routine_1_result; 7862 Utils::vec4<GLuint> routine_2_result; 7863 7864 routine_1_result.m_x = feedback_data[0 + 0]; 7865 routine_1_result.m_y = feedback_data[0 + 1]; 7866 routine_1_result.m_z = feedback_data[0 + 2]; 7867 routine_1_result.m_w = feedback_data[0 + 3]; 7868 7869 routine_2_result.m_x = feedback_data[4 + 0]; 7870 routine_2_result.m_y = feedback_data[4 + 1]; 7871 routine_2_result.m_z = feedback_data[4 + 2]; 7872 routine_2_result.m_w = feedback_data[4 + 3]; 7873 7874 /* Unmap buffer */ 7875 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 7876 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 7877 7878 /* Verifiy */ 7879 result = result && (routine_1_result == expected_routine_1_result); 7880 result = result && (routine_2_result == expected_routine_2_result); 7881 7882 /* Log error if any */ 7883 if (false == result) 7884 { 7885 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 7886 << tcu::TestLog::EndMessage; 7887 7888 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 7889 7890 message << "Routine_1, result: "; 7891 7892 routine_1_result.log(message); 7893 7894 message << ", expected: "; 7895 7896 expected_routine_1_result.log(message); 7897 7898 message << "Routine_2, result: "; 7899 7900 routine_2_result.log(message); 7901 7902 message << ", expected: "; 7903 7904 expected_routine_2_result.log(message); 7905 7906 message << tcu::TestLog::EndMessage; 7907 } 7908 7909 /* Done */ 7910 return result; 7911} 7912 7913/** Verify initial and current values of subroutine indices and subroutines uniform locations 7914 * 7915 * @return true if test pass, false otherwise 7916 **/ 7917bool FunctionalTest14_15::testIndicesAndLocations() const 7918{ 7919 static const GLuint n_subroutine_types = 2; 7920 bool result = true; 7921 7922 /* Verify subroutine indices */ 7923 for (GLuint type = 0; type < n_subroutine_types; ++type) 7924 { 7925 result = result && (m_subroutine_indices[type][0] == m_initial_subroutine_indices[type][0]); 7926 result = result && (m_subroutine_indices[type][1] == m_initial_subroutine_indices[type][1]); 7927 } 7928 7929 /* Verify subroutine uniform locations */ 7930 for (GLuint uniform = 0; uniform < n_subroutine_types; ++uniform) 7931 { 7932 result = result && (m_subroutine_uniform_locations[uniform] == m_initial_subroutine_uniform_locations[uniform]); 7933 } 7934 7935 return result; 7936} 7937 7938/** Constructor. 7939 * 7940 * @param context Rendering context. 7941 * 7942 **/ 7943FunctionalTest16::FunctionalTest16(deqp::Context& context) 7944 : TestCase(context, "subroutine_uniform_reset", 7945 "Checks that when the active program for a shader stage is re-linke or " 7946 "changed by a call to UseProgram, BindProgramPipeline, or UseProgramStages," 7947 " subroutine uniforms for that stage are reset to arbitrarily chosen default " 7948 "functions with compatible subroutine types.") 7949 , m_are_pipeline_objects_supported(false) 7950 , m_has_test_passed(true) 7951{ 7952 memset(m_fs_ids, 0, sizeof(m_fs_ids)); 7953 memset(m_gs_ids, 0, sizeof(m_gs_ids)); 7954 memset(m_po_ids, 0, sizeof(m_po_ids)); 7955 memset(m_tc_ids, 0, sizeof(m_tc_ids)); 7956 memset(m_te_ids, 0, sizeof(m_te_ids)); 7957 memset(m_vs_ids, 0, sizeof(m_vs_ids)); 7958 7959 memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids)); 7960 memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids)); 7961 memset(m_pipeline_object_ids, 0, sizeof(m_pipeline_object_ids)); 7962 memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids)); 7963 memset(m_te_po_ids, 0, sizeof(m_te_po_ids)); 7964 memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids)); 7965} 7966 7967/** Deinitializes all GL objects that may have been created during test execution. */ 7968void FunctionalTest16::deinit() 7969{ 7970 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7971 7972 for (unsigned int n_id = 0; n_id < 2; ++n_id) 7973 { 7974 if (m_fs_ids[n_id] != 0) 7975 { 7976 gl.deleteShader(m_fs_ids[n_id]); 7977 7978 m_fs_ids[n_id] = 0; 7979 } 7980 7981 if (m_fs_po_ids[n_id] != 0) 7982 { 7983 gl.deleteProgram(m_fs_po_ids[n_id]); 7984 7985 m_fs_po_ids[n_id] = 0; 7986 } 7987 7988 if (m_gs_ids[n_id] != 0) 7989 { 7990 gl.deleteShader(m_gs_ids[n_id]); 7991 7992 m_gs_ids[n_id] = 0; 7993 } 7994 7995 if (m_gs_po_ids[n_id] != 0) 7996 { 7997 gl.deleteProgram(m_gs_po_ids[n_id]); 7998 7999 m_gs_po_ids[n_id] = 0; 8000 } 8001 8002 if (m_pipeline_object_ids[n_id] != 0) 8003 { 8004 gl.deleteProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id); 8005 } 8006 8007 if (m_po_ids[n_id] != 0) 8008 { 8009 gl.deleteProgram(m_po_ids[n_id]); 8010 8011 m_po_ids[n_id] = 0; 8012 } 8013 8014 if (m_tc_ids[n_id] != 0) 8015 { 8016 gl.deleteShader(m_tc_ids[n_id]); 8017 8018 m_tc_ids[n_id] = 0; 8019 } 8020 8021 if (m_tc_po_ids[n_id] != 0) 8022 { 8023 gl.deleteProgram(m_tc_po_ids[n_id]); 8024 8025 m_tc_po_ids[n_id] = 0; 8026 } 8027 8028 if (m_te_ids[n_id] != 0) 8029 { 8030 gl.deleteShader(m_te_ids[n_id]); 8031 8032 m_te_ids[n_id] = 0; 8033 } 8034 8035 if (m_te_po_ids[n_id] != 0) 8036 { 8037 gl.deleteProgram(m_te_po_ids[n_id]); 8038 8039 m_te_po_ids[n_id] = 0; 8040 } 8041 8042 if (m_vs_ids[n_id] != 0) 8043 { 8044 gl.deleteShader(m_vs_ids[n_id]); 8045 8046 m_vs_ids[n_id] = 0; 8047 } 8048 8049 if (m_vs_po_ids[n_id] != 0) 8050 { 8051 gl.deleteProgram(m_vs_po_ids[n_id]); 8052 8053 m_vs_po_ids[n_id] = 0; 8054 } 8055 } /* for (both IDs) */ 8056} 8057 8058/** Retrieves body of a shader that should be used for user-specified shader stage. 8059 * This function returns slightly different implementations, depending on index of 8060 * the program/pipeline object the shader will be used for. 8061 * 8062 * @param shader_stage Stage the shader body is to be returned for. 8063 * @param n_id Index of the shader (as per description). 8064 * 8065 * @return Requested string. 8066 **/ 8067std::string FunctionalTest16::getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_id) const 8068{ 8069 std::stringstream result_sstream; 8070 8071 result_sstream << "#version 400\n" 8072 "\n" 8073 "#extension GL_ARB_shader_subroutine : require\n" 8074 "\n"; 8075 8076 switch (shader_stage) 8077 { 8078 case Utils::SHADER_STAGE_VERTEX: 8079 { 8080 result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n"; 8081 break; 8082 } 8083 case Utils::SHADER_STAGE_GEOMETRY: 8084 { 8085 result_sstream << "layout(points) in;\n" 8086 "layout(points, max_vertices = 1) out;\n"; 8087 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"; 8088 result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n"; 8089 break; 8090 } 8091 8092 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 8093 { 8094 result_sstream << "layout(vertices = 4) out;\n"; 8095 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"; 8096 result_sstream << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"; 8097 break; 8098 } 8099 8100 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 8101 { 8102 result_sstream << "layout(quads) in;\n"; 8103 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"; 8104 result_sstream << "out gl_PerVertex { vec4 gl_Position; };\n"; 8105 break; 8106 } 8107 8108 default: 8109 break; 8110 } /* switch (shader_stage) */ 8111 8112 result_sstream << "\n" 8113 "subroutine void subroutineType (inout vec4 result);\n" 8114 "subroutine vec4 subroutineType2(in vec4 data);\n" 8115 "\n" 8116 "subroutine(subroutineType) void function1(inout vec4 result)\n" 8117 "{\n" 8118 " result += vec4(" 8119 << (n_id + 1) << ", " << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4) 8120 << ");\n" 8121 "}\n" 8122 "subroutine(subroutineType) void function2(inout vec4 result)\n" 8123 "{\n" 8124 " result += vec4(" 8125 << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4) << ", " << (n_id + 5) 8126 << ");\n" 8127 "}\n" 8128 "\n" 8129 "subroutine(subroutineType2) vec4 function3(in vec4 data)\n" 8130 "{\n" 8131 " return data * data;\n" 8132 "}\n" 8133 "subroutine(subroutineType2) vec4 function4(in vec4 data)\n" 8134 "{\n" 8135 " return data + data;\n" 8136 "}\n" 8137 "\n" 8138 "subroutine uniform subroutineType subroutine1;\n" 8139 "subroutine uniform subroutineType subroutine2;\n" 8140 "subroutine uniform subroutineType2 subroutine3;\n" 8141 "subroutine uniform subroutineType2 subroutine4;\n" 8142 "\n"; 8143 8144 if (shader_stage == Utils::SHADER_STAGE_FRAGMENT) 8145 { 8146 result_sstream << "out vec4 result;\n"; 8147 } 8148 8149 result_sstream << "void main()\n" 8150 "{\n"; 8151 8152 switch (shader_stage) 8153 { 8154 case Utils::SHADER_STAGE_FRAGMENT: 8155 { 8156 result_sstream << " result = vec4(0);\n" 8157 << " subroutine1(result);\n" 8158 " subroutine2(result);\n" 8159 " result = subroutine3(result) + subroutine4(result);\n"; 8160 8161 break; 8162 } 8163 8164 case Utils::SHADER_STAGE_GEOMETRY: 8165 { 8166 result_sstream << " gl_Position = vec4(0);\n" 8167 " subroutine1(gl_Position);\n" 8168 " subroutine2(gl_Position);\n" 8169 " gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n" 8170 " EmitVertex();\n"; 8171 8172 break; 8173 } 8174 8175 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 8176 { 8177 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0);\n" 8178 " subroutine1(gl_out[gl_InvocationID].gl_Position);\n" 8179 " subroutine2(gl_out[gl_InvocationID].gl_Position);\n" 8180 " gl_out[gl_InvocationID].gl_Position = subroutine3(gl_in[0].gl_Position) + " 8181 "subroutine4(gl_in[0].gl_Position);\n"; 8182 8183 break; 8184 } 8185 8186 case Utils::SHADER_STAGE_VERTEX: 8187 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 8188 { 8189 result_sstream << " gl_Position = vec4(0);\n" 8190 " subroutine1(gl_Position);\n" 8191 " subroutine2(gl_Position);\n" 8192 " gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n"; 8193 8194 break; 8195 } 8196 8197 default: 8198 break; 8199 } /* switch (shader_stage) */ 8200 8201 result_sstream << "}\n"; 8202 8203 return result_sstream.str(); 8204} 8205 8206/** Initializes all objects required to run the test. */ 8207void FunctionalTest16::initTest() 8208{ 8209 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8210 8211 for (unsigned int n_id = 0; n_id < 2 /* test program/shader objects */; ++n_id) 8212 { 8213 const std::string fs_body = getShaderBody(Utils::SHADER_STAGE_FRAGMENT, n_id); 8214 const std::string gs_body = getShaderBody(Utils::SHADER_STAGE_GEOMETRY, n_id); 8215 const std::string tc_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_CONTROL, n_id); 8216 const std::string te_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_EVALUATION, n_id); 8217 const std::string vs_body = getShaderBody(Utils::SHADER_STAGE_VERTEX, n_id); 8218 8219 if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */ 8220 DE_NULL, /* n_xfb_varyings */ 8221 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, 8222 m_po_ids + n_id)) 8223 { 8224 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build test program object, index:" 8225 "[" 8226 << n_id << "]" << tcu::TestLog::EndMessage; 8227 8228 TCU_FAIL("Failed to build a test program"); 8229 } 8230 8231 if (m_are_pipeline_objects_supported) 8232 { 8233 /* Initialize shader program objects */ 8234 const char* fs_body_raw_ptr = fs_body.c_str(); 8235 const char* gs_body_raw_ptr = gs_body.c_str(); 8236 glw::GLint link_status[5] = { GL_FALSE }; 8237 const char* tc_body_raw_ptr = tc_body.c_str(); 8238 const char* te_body_raw_ptr = te_body.c_str(); 8239 const char* vs_body_raw_ptr = vs_body.c_str(); 8240 8241 m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr); 8242 m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr); 8243 m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr); 8244 m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr); 8245 m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr); 8246 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 8247 8248 gl.getProgramiv(m_fs_po_ids[n_id], GL_LINK_STATUS, link_status + 0); 8249 gl.getProgramiv(m_gs_po_ids[n_id], GL_LINK_STATUS, link_status + 1); 8250 gl.getProgramiv(m_tc_po_ids[n_id], GL_LINK_STATUS, link_status + 2); 8251 gl.getProgramiv(m_te_po_ids[n_id], GL_LINK_STATUS, link_status + 3); 8252 gl.getProgramiv(m_vs_po_ids[n_id], GL_LINK_STATUS, link_status + 4); 8253 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 8254 8255 if (link_status[0] == GL_FALSE) 8256 TCU_FAIL("Fragment shader program failed to link"); 8257 if (link_status[1] == GL_FALSE) 8258 TCU_FAIL("Geometry shader program failed to link"); 8259 if (link_status[2] == GL_FALSE) 8260 TCU_FAIL("Tessellation control shader program failed to link"); 8261 if (link_status[3] == GL_FALSE) 8262 TCU_FAIL("Tessellation evaluation shader program failed to link"); 8263 if (link_status[4] == GL_FALSE) 8264 TCU_FAIL("Vertex shader program failed to link"); 8265 8266 /* Initialize pipeline program object */ 8267 gl.genProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id); 8268 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); 8269 8270 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_FRAGMENT_SHADER_BIT, m_fs_po_ids[n_id]); 8271 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_GEOMETRY_SHADER_BIT, m_gs_po_ids[n_id]); 8272 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_CONTROL_SHADER_BIT, m_tc_po_ids[n_id]); 8273 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_EVALUATION_SHADER_BIT, m_te_po_ids[n_id]); 8274 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_id]); 8275 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8276 } 8277 8278 /* Retrieve subroutine locations */ 8279 struct _item 8280 { 8281 glw::GLuint po_id; 8282 _shader_stage& stage; 8283 glw::GLuint so_id; 8284 glw::GLenum so_type; 8285 } items[] = { 8286 { m_po_ids[n_id], m_po_descriptors[n_id].fragment, m_fs_ids[n_id], GL_FRAGMENT_SHADER }, 8287 { m_po_ids[n_id], m_po_descriptors[n_id].geometry, m_gs_ids[n_id], GL_GEOMETRY_SHADER }, 8288 { m_po_ids[n_id], m_po_descriptors[n_id].tess_control, m_tc_ids[n_id], GL_TESS_CONTROL_SHADER }, 8289 { m_po_ids[n_id], m_po_descriptors[n_id].tess_evaluation, m_te_ids[n_id], GL_TESS_EVALUATION_SHADER }, 8290 { m_po_ids[n_id], m_po_descriptors[n_id].vertex, m_vs_ids[n_id], GL_VERTEX_SHADER }, 8291 8292 { m_fs_po_ids[n_id], m_fs_po_descriptors[n_id], m_fs_po_ids[n_id], GL_FRAGMENT_SHADER }, 8293 { m_gs_po_ids[n_id], m_gs_po_descriptors[n_id], m_gs_po_ids[n_id], GL_GEOMETRY_SHADER }, 8294 { m_tc_po_ids[n_id], m_tc_po_descriptors[n_id], m_tc_po_ids[n_id], GL_TESS_CONTROL_SHADER }, 8295 { m_te_po_ids[n_id], m_te_po_descriptors[n_id], m_te_po_ids[n_id], GL_TESS_EVALUATION_SHADER }, 8296 { m_vs_po_ids[n_id], m_vs_po_descriptors[n_id], m_vs_po_ids[n_id], GL_VERTEX_SHADER }, 8297 }; 8298 const unsigned int n_items = sizeof(items) / sizeof(items[0]); 8299 8300 for (unsigned int n_item = 0; n_item < n_items; ++n_item) 8301 { 8302 _item& current_item = items[n_item]; 8303 8304 current_item.stage.function1_index = 8305 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function1"); 8306 current_item.stage.function2_index = 8307 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function2"); 8308 current_item.stage.function3_index = 8309 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function3"); 8310 current_item.stage.function4_index = 8311 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function4"); 8312 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 8313 8314 if (current_item.stage.function1_index == GL_INVALID_INDEX || 8315 current_item.stage.function2_index == GL_INVALID_INDEX || 8316 current_item.stage.function3_index == GL_INVALID_INDEX || 8317 current_item.stage.function4_index == GL_INVALID_INDEX) 8318 { 8319 TCU_FAIL("Subroutine name was not recognized."); 8320 } 8321 8322 current_item.stage.subroutine1_uniform_location = 8323 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine1"); 8324 current_item.stage.subroutine2_uniform_location = 8325 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine2"); 8326 current_item.stage.subroutine3_uniform_location = 8327 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine3"); 8328 current_item.stage.subroutine4_uniform_location = 8329 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine4"); 8330 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed."); 8331 8332 if (current_item.stage.subroutine1_uniform_location == -1 || 8333 current_item.stage.subroutine2_uniform_location == -1 || 8334 current_item.stage.subroutine3_uniform_location == -1 || 8335 current_item.stage.subroutine4_uniform_location == -1) 8336 { 8337 TCU_FAIL("Subroutine uniform name was not recognized."); 8338 } 8339 8340 if (m_po_ids[n_id] == current_item.po_id) 8341 { 8342 gl.useProgram(current_item.po_id); 8343 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 8344 } 8345 else 8346 { 8347 /* Temporarily bind the program pipeline. */ 8348 gl.bindProgramPipeline(m_pipeline_object_ids[n_id]); 8349 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 8350 } 8351 8352 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine1_uniform_location, 8353 ¤t_item.stage.default_subroutine1_value); 8354 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine2_uniform_location, 8355 ¤t_item.stage.default_subroutine2_value); 8356 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine3_uniform_location, 8357 ¤t_item.stage.default_subroutine3_value); 8358 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine4_uniform_location, 8359 ¤t_item.stage.default_subroutine4_value); 8360 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed."); 8361 8362 current_item.stage.gl_stage = current_item.so_type; 8363 8364 if (m_po_ids[n_id] != current_item.po_id) 8365 { 8366 /* Unbind the program pipeline object */ 8367 gl.bindProgramPipeline(0); 8368 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 8369 } 8370 } /* for (all items) */ 8371 8372 /* Make sure the default subroutine choices are valid. */ 8373 verifySubroutineUniformValues( 8374 TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, /* makes the verification routine use program object descriptor */ 8375 n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES); 8376 8377 if (m_are_pipeline_objects_supported) 8378 { 8379 gl.useProgram(0); 8380 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 8381 8382 gl.bindProgramPipeline(m_pipeline_object_ids[n_id]); 8383 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 8384 { 8385 verifySubroutineUniformValues( 8386 TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT, /* makes the verification routine use pipeline object descriptor */ 8387 n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES); 8388 } 8389 gl.bindProgramPipeline(0); 8390 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 8391 } 8392 } /* for (both program descriptors) */ 8393} 8394 8395/** Retrieves IDs of shaders OR shader program objects, depending on which of the two 8396 * the caller requests for. 8397 * 8398 * @param retrieve_program_object_shader_ids true if the caller wishes to retrieve shader object IDs, 8399 * false to return shader program IDs. 8400 * @param n_id Index of the program/pipeline object the shaders 8401 * are a part of. 8402 * @param out_shader_stages Deref will be used to store exactly five IDs. Must not 8403 * be NULL. 8404 **/ 8405void FunctionalTest16::getShaderStages(bool retrieve_program_object_shader_ids, const unsigned int& n_id, 8406 const _shader_stage** out_shader_stages) const 8407{ 8408 if (retrieve_program_object_shader_ids) 8409 { 8410 out_shader_stages[0] = &m_po_descriptors[n_id].vertex; 8411 out_shader_stages[1] = &m_po_descriptors[n_id].tess_control; 8412 out_shader_stages[2] = &m_po_descriptors[n_id].tess_evaluation; 8413 out_shader_stages[3] = &m_po_descriptors[n_id].geometry; 8414 out_shader_stages[4] = &m_po_descriptors[n_id].fragment; 8415 } 8416 else 8417 { 8418 out_shader_stages[0] = m_vs_po_descriptors + n_id; 8419 out_shader_stages[1] = m_tc_po_descriptors + n_id; 8420 out_shader_stages[2] = m_te_po_descriptors + n_id; 8421 out_shader_stages[3] = m_gs_po_descriptors + n_id; 8422 out_shader_stages[4] = m_fs_po_descriptors + n_id; 8423 } 8424} 8425 8426/** Executes test iteration. 8427 * 8428 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 8429 */ 8430tcu::TestNode::IterateResult FunctionalTest16::iterate() 8431{ 8432 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8433 8434 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 8435 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 8436 { 8437 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 8438 } 8439 8440 m_are_pipeline_objects_supported = 8441 m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"); 8442 8443 /* Initialize GL objects required to run the test */ 8444 initTest(); 8445 8446 /* Iterate over both pipelines/programs and verify that calling glUseProgram() / 8447 * glBindProgramPipeline() / glUseProgramStages() resets subroutine uniform configuration. 8448 */ 8449 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 8450 { 8451 if (static_cast<_test_case>(test_case) != TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT && 8452 !m_are_pipeline_objects_supported) 8453 { 8454 /* Current test case requires GL_ARB_separate_shader_objects support which is 8455 * unavaiable on the platform that we're testing 8456 */ 8457 continue; 8458 } 8459 8460 for (unsigned int n_object_id = 0; n_object_id < 2; /* pipeline/program objects allocated for the test */ 8461 ++n_object_id) 8462 { 8463 /* Verify that currently reported subroutine uniform values are equal to default values */ 8464 if (test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT) 8465 { 8466 gl.useProgram(m_po_ids[n_object_id]); 8467 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 8468 } 8469 else 8470 { 8471 gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]); 8472 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed"); 8473 } 8474 8475 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id, 8476 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES); 8477 8478 /* Re-configure subroutine uniforms so that they point to different subroutines than 8479 * the default ones. 8480 */ 8481 const _shader_stage* stages[5 /* fs+gs+tc+te+vs */] = { DE_NULL }; 8482 8483 getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, 8484 n_object_id, stages); 8485 8486 for (unsigned int n_stage = 0; n_stage < 5 /* fs+gs+tc+te+vs stages */; ++n_stage) 8487 { 8488 const _shader_stage& current_stage = *(stages[n_stage]); 8489 glw::GLuint subroutine_configuration[4] = { GL_INVALID_INDEX }; 8490 8491 subroutine_configuration[0] = 8492 (current_stage.default_subroutine1_value == current_stage.function1_index) ? 8493 current_stage.function2_index : 8494 current_stage.function1_index; 8495 subroutine_configuration[1] = 8496 (current_stage.default_subroutine2_value == current_stage.function1_index) ? 8497 current_stage.function2_index : 8498 current_stage.function1_index; 8499 subroutine_configuration[2] = 8500 (current_stage.default_subroutine3_value == current_stage.function3_index) ? 8501 current_stage.function4_index : 8502 current_stage.function3_index; 8503 subroutine_configuration[3] = 8504 (current_stage.default_subroutine4_value == current_stage.function3_index) ? 8505 current_stage.function4_index : 8506 current_stage.function3_index; 8507 8508 gl.uniformSubroutinesuiv(current_stage.gl_stage, 4 /* count */, subroutine_configuration); 8509 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed."); 8510 } /* for (all stages) */ 8511 8512 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id, 8513 SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES); 8514 8515 /* Execute test case-specific code */ 8516 _shader_stage cached_shader_stage_data; 8517 bool stage_reset_status[Utils::SHADER_STAGE_COUNT] = { false, false, false, false, false }; 8518 bool uses_stage_reset_status = false; 8519 8520 switch (test_case) 8521 { 8522 case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT: 8523 { 8524 /* Switch to a different program object and then back to current PO. 8525 * Subroutine uniforms should be back at their default settings, instead of 8526 * the ones we've just set. 8527 */ 8528 gl.useProgram(m_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8529 gl.useProgram(m_po_ids[n_object_id]); 8530 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed."); 8531 8532 break; 8533 } 8534 8535 case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT: 8536 { 8537 /* Switch to a different pipeline object and then back to the current one. 8538 * Subroutine uniforms should be back at their default settings, instead of 8539 * the ones we've just set. 8540 */ 8541 gl.bindProgramPipeline( 8542 m_pipeline_object_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8543 gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]); 8544 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed."); 8545 8546 break; 8547 } 8548 8549 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE: 8550 { 8551 /* Change the fragment shader stage to a different one. 8552 * 8553 * Note: We also need to update internal descriptor since the subroutine/uniform 8554 * locations may be different between the two programs. 8555 */ 8556 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT, 8557 m_fs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8558 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8559 8560 cached_shader_stage_data = m_fs_po_descriptors[n_object_id]; 8561 m_fs_po_descriptors[n_object_id] = m_fs_po_descriptors[(n_object_id + 1) % 2]; 8562 8563 stage_reset_status[Utils::SHADER_STAGE_FRAGMENT] = true; 8564 uses_stage_reset_status = true; 8565 8566 break; 8567 } 8568 8569 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE: 8570 { 8571 /* Change the geometry shader stage to a different one. 8572 * 8573 * Note: We also need to update internal descriptor since the subroutine/uniform 8574 * locations may be different between the two programs. 8575 */ 8576 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT, 8577 m_gs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8578 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8579 8580 cached_shader_stage_data = m_gs_po_descriptors[n_object_id]; 8581 m_gs_po_descriptors[n_object_id] = m_gs_po_descriptors[(n_object_id + 1) % 2]; 8582 8583 stage_reset_status[Utils::SHADER_STAGE_GEOMETRY] = true; 8584 uses_stage_reset_status = true; 8585 8586 break; 8587 } 8588 8589 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE: 8590 { 8591 /* Change the tessellation control shader stage to a different one. 8592 * 8593 * Note: We also need to update internal descriptor since the subroutine/uniform 8594 * locations may be different between the two programs. 8595 */ 8596 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT, 8597 m_tc_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8598 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8599 8600 cached_shader_stage_data = m_tc_po_descriptors[n_object_id]; 8601 m_tc_po_descriptors[n_object_id] = m_tc_po_descriptors[(n_object_id + 1) % 2]; 8602 8603 stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_CONTROL] = true; 8604 uses_stage_reset_status = true; 8605 8606 break; 8607 } 8608 8609 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE: 8610 { 8611 /* Change the tessellation evaluation shader stage to a different one. 8612 * 8613 * Note: We also need to update internal descriptor since the subroutine/uniform 8614 * locations may be different between the two programs. 8615 */ 8616 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT, 8617 m_te_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8618 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8619 8620 cached_shader_stage_data = m_te_po_descriptors[n_object_id]; 8621 m_te_po_descriptors[n_object_id] = m_te_po_descriptors[(n_object_id + 1) % 2]; 8622 8623 stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_EVALUATION] = true; 8624 uses_stage_reset_status = true; 8625 8626 break; 8627 } 8628 8629 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE: 8630 { 8631 /* Change the vertex shader stage to a different one. 8632 * 8633 * Note: We also need to update internal descriptor since the subroutine/uniform 8634 * locations may be different between the two programs. 8635 */ 8636 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT, 8637 m_vs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]); 8638 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8639 8640 cached_shader_stage_data = m_vs_po_descriptors[n_object_id]; 8641 m_vs_po_descriptors[n_object_id] = m_vs_po_descriptors[(n_object_id + 1) % 2]; 8642 8643 stage_reset_status[Utils::SHADER_STAGE_VERTEX] = true; 8644 uses_stage_reset_status = true; 8645 8646 break; 8647 } 8648 8649 default: 8650 { 8651 TCU_FAIL("Unrecognized test case"); 8652 } 8653 } /* switch (test_case) */ 8654 8655 /* Verify the subroutine uniform values are valid */ 8656 if (!uses_stage_reset_status) 8657 { 8658 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id, 8659 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES); 8660 } 8661 else 8662 { 8663 const _shader_stage* shader_stages[Utils::SHADER_STAGE_COUNT] = { DE_NULL }; 8664 8665 getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, 8666 n_object_id, shader_stages); 8667 8668 for (unsigned int n_shader_stage = 0; n_shader_stage < Utils::SHADER_STAGE_COUNT; ++n_shader_stage) 8669 { 8670 const _shader_stage& current_shader_stage = *(shader_stages[n_shader_stage]); 8671 8672 if (stage_reset_status[n_shader_stage]) 8673 { 8674 verifySubroutineUniformValuesForShaderStage(current_shader_stage, 8675 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES); 8676 } 8677 else 8678 { 8679 verifySubroutineUniformValuesForShaderStage(current_shader_stage, 8680 SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES); 8681 } 8682 } /* for (all shader stages) */ 8683 } 8684 8685 /* Revert the changes some of the test cases appied */ 8686 switch (test_case) 8687 { 8688 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE: 8689 { 8690 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT, 8691 m_fs_po_ids[n_object_id]); 8692 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8693 8694 m_fs_po_descriptors[n_object_id] = cached_shader_stage_data; 8695 8696 break; 8697 } 8698 8699 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE: 8700 { 8701 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT, 8702 m_gs_po_ids[n_object_id]); 8703 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8704 8705 m_gs_po_descriptors[n_object_id] = cached_shader_stage_data; 8706 8707 break; 8708 } 8709 8710 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE: 8711 { 8712 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT, 8713 m_tc_po_ids[n_object_id]); 8714 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8715 8716 m_tc_po_descriptors[n_object_id] = cached_shader_stage_data; 8717 8718 break; 8719 } 8720 8721 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE: 8722 { 8723 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT, 8724 m_te_po_ids[n_object_id]); 8725 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8726 8727 m_te_po_descriptors[n_object_id] = cached_shader_stage_data; 8728 8729 break; 8730 } 8731 8732 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE: 8733 { 8734 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_object_id]); 8735 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 8736 8737 m_vs_po_descriptors[n_object_id] = cached_shader_stage_data; 8738 8739 break; 8740 } 8741 8742 default: 8743 break; 8744 } /* switch (test_case) */ 8745 8746 } /* for (all program object descriptors) */ 8747 8748 /* Unbind the program object */ 8749 gl.useProgram(0); 8750 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 8751 } /* for (all test cases) */ 8752 8753 if (m_has_test_passed) 8754 { 8755 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 8756 } 8757 else 8758 { 8759 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 8760 } 8761 8762 return STOP; 8763} 8764 8765/** Verifies the subroutine uniform values reported by GL implementation. Depending on the test case, 8766 * it will either query program object stages or separate shader objects. 8767 * 8768 * @param test_case Test case the verification is to be performed for. 8769 * @param n_id Index of the program/pipeline object to use for the verification 8770 * @param verification Verification method. 8771 */ 8772void FunctionalTest16::verifySubroutineUniformValues(const _test_case& test_case, const unsigned int& n_id, 8773 const _subroutine_uniform_value_verification& verification) 8774{ 8775 const _shader_stage* stages[] = { 8776 DE_NULL, /* fragment shader stage slot */ 8777 DE_NULL, /* geometry shader stage slot */ 8778 DE_NULL, /* tess control shader stage slot */ 8779 DE_NULL, /* tess eval shader stage slot */ 8780 DE_NULL /* vertex shader stage slot */ 8781 }; 8782 const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]); 8783 8784 /* Verify that currently reported subroutine uniform values are equal to default values */ 8785 getShaderStages(test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, n_id, stages); 8786 8787 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage) 8788 { 8789 const _shader_stage& current_stage = *(stages[n_stage]); 8790 8791 verifySubroutineUniformValuesForShaderStage(current_stage, verification); 8792 } /* for (all items) */ 8793} 8794 8795/** Verifies the subroutine uniform values reported by GL implementation for user-specified 8796 * shader stage. If the verification fails, m_has_test_passed will be set to false. 8797 * 8798 * @param shader_stage Descriptor of a shader stage that should be used for the process. 8799 * @param verification Type of verification that should be performed. 8800 * 8801 **/ 8802void FunctionalTest16::verifySubroutineUniformValuesForShaderStage( 8803 const _shader_stage& shader_stage, const _subroutine_uniform_value_verification& verification) 8804{ 8805 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8806 glw::GLuint result_values[4] = { 0 }; 8807 8808 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine1_uniform_location, result_values + 0); 8809 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine2_uniform_location, result_values + 1); 8810 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine3_uniform_location, result_values + 2); 8811 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine4_uniform_location, result_values + 3); 8812 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed."); 8813 8814 if (verification == SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES) 8815 { 8816 if (!((result_values[0] == (GLuint)shader_stage.subroutine1_uniform_location || 8817 result_values[0] == (GLuint)shader_stage.subroutine2_uniform_location) && 8818 (result_values[1] == (GLuint)shader_stage.subroutine1_uniform_location || 8819 result_values[1] == (GLuint)shader_stage.subroutine2_uniform_location) && 8820 (result_values[2] == (GLuint)shader_stage.subroutine3_uniform_location || 8821 result_values[2] == (GLuint)shader_stage.subroutine4_uniform_location) && 8822 (result_values[3] == (GLuint)shader_stage.subroutine3_uniform_location || 8823 result_values[3] == (GLuint)shader_stage.subroutine4_uniform_location))) 8824 { 8825 m_testCtx.getLog() << tcu::TestLog::Message << "SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES validation failed. " 8826 "Shader stage:[" 8827 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], " 8828 "expected data:[" 8829 << shader_stage.subroutine1_uniform_location << " OR " 8830 << shader_stage.subroutine2_uniform_location << " x 2, " 8831 << shader_stage.subroutine3_uniform_location << " OR " 8832 << shader_stage.subroutine4_uniform_location << " x 2], " 8833 "found data:[" 8834 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", " 8835 << result_values[3] << "]." << tcu::TestLog::EndMessage; 8836 8837 m_has_test_passed = false; 8838 } 8839 } 8840 else if (verification == SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES) 8841 { 8842 if (result_values[0] != shader_stage.default_subroutine1_value || 8843 result_values[1] != shader_stage.default_subroutine2_value || 8844 result_values[2] != shader_stage.default_subroutine3_value || 8845 result_values[3] != shader_stage.default_subroutine4_value) 8846 { 8847 m_testCtx.getLog() << tcu::TestLog::Message 8848 << "SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES validation failed. " 8849 "Shader stage:[" 8850 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], " 8851 "expected data:[" 8852 << shader_stage.default_subroutine1_value << ", " 8853 << shader_stage.default_subroutine2_value << ", " 8854 << shader_stage.default_subroutine3_value << ", " 8855 << shader_stage.default_subroutine4_value << "], " 8856 "found data:[" 8857 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", " 8858 << result_values[3] << "]." << tcu::TestLog::EndMessage; 8859 8860 m_has_test_passed = false; 8861 } 8862 } 8863 else 8864 { 8865 DE_ASSERT(verification == SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES); 8866 8867 if (result_values[0] == shader_stage.default_subroutine1_value || 8868 result_values[1] == shader_stage.default_subroutine2_value || 8869 result_values[2] == shader_stage.default_subroutine3_value || 8870 result_values[3] == shader_stage.default_subroutine4_value) 8871 { 8872 m_testCtx.getLog() << tcu::TestLog::Message 8873 << "SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES validation failed. " 8874 "Shader stage:[" 8875 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], " 8876 "expected data:![" 8877 << shader_stage.default_subroutine1_value << ", " 8878 << shader_stage.default_subroutine2_value << ", " 8879 << shader_stage.default_subroutine3_value << ", " 8880 << shader_stage.default_subroutine4_value << "], " 8881 "found data:[" 8882 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", " 8883 << result_values[3] << "]." << tcu::TestLog::EndMessage; 8884 8885 m_has_test_passed = false; 8886 } 8887 } 8888} 8889 8890/** Constructor. 8891 * 8892 * @param context Rendering context. 8893 * 8894 **/ 8895FunctionalTest17::FunctionalTest17(deqp::Context& context) 8896 : TestCase(context, "same_subroutine_and_subroutine_uniform_but_different_type_used_in_all_stages", 8897 "Creates a program which uses the same subroutine and subroutine uniform " 8898 "names for every stage (types of subroutines are different in each stage) " 8899 "and then makes sure that such program compiles and works as expected.") 8900 , m_fbo_id(0) 8901 , m_fs_id(0) 8902 , m_gs_id(0) 8903 , m_has_test_passed(true) 8904 , m_po_id(0) 8905 , m_tc_id(0) 8906 , m_te_id(0) 8907 , m_to_data(DE_NULL) 8908 , m_to_height(4) /* arbitrary value */ 8909 , m_to_id(0) 8910 , m_to_width(4) /* arbitrary value */ 8911 , m_vao_id(0) 8912 , m_vs_id(0) 8913{ 8914 /* Left blank intentionally */ 8915} 8916 8917/** Deinitializes all GL objects that may have been created during test execution. */ 8918void FunctionalTest17::deinit() 8919{ 8920 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8921 8922 if (m_fbo_id != 0) 8923 { 8924 gl.deleteFramebuffers(1, &m_fbo_id); 8925 8926 m_fbo_id = 0; 8927 } 8928 8929 if (m_fs_id != 0) 8930 { 8931 gl.deleteShader(m_fs_id); 8932 8933 m_fs_id = 0; 8934 } 8935 8936 if (m_gs_id != 0) 8937 { 8938 gl.deleteShader(m_gs_id); 8939 8940 m_gs_id = 0; 8941 } 8942 8943 if (m_po_id != 0) 8944 { 8945 gl.deleteProgram(m_po_id); 8946 8947 m_po_id = 0; 8948 } 8949 8950 if (m_tc_id != 0) 8951 { 8952 gl.deleteShader(m_tc_id); 8953 8954 m_tc_id = 0; 8955 } 8956 8957 if (m_te_id != 0) 8958 { 8959 gl.deleteShader(m_te_id); 8960 8961 m_te_id = 0; 8962 } 8963 8964 if (m_to_data != DE_NULL) 8965 { 8966 delete[] m_to_data; 8967 8968 m_to_data = DE_NULL; 8969 } 8970 8971 if (m_to_id != 0) 8972 { 8973 gl.deleteTextures(1, &m_to_id); 8974 8975 m_to_id = 0; 8976 } 8977 8978 if (m_vao_id != 0) 8979 { 8980 gl.deleteVertexArrays(1, &m_vao_id); 8981 8982 m_vao_id = 0; 8983 } 8984 8985 if (m_vs_id != 0) 8986 { 8987 gl.deleteShader(m_vs_id); 8988 8989 m_vs_id = 0; 8990 } 8991 8992 /* Restore original GL configuration */ 8993 gl.patchParameteri(GL_PATCH_VERTICES, 3); 8994 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed."); 8995 8996 gl.pixelStorei(GL_PACK_ALIGNMENT, 4); 8997 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed."); 8998} 8999 9000/** Retrieves body of a fragment shader that should be used by the test program. 9001 * 9002 * @return Requested string. 9003 **/ 9004std::string FunctionalTest17::getFragmentShaderBody() const 9005{ 9006 return "#version 400\n" 9007 "\n" 9008 "#extension GL_ARB_shader_subroutine : require\n" 9009 "\n" 9010 "in GS_DATA\n" 9011 "{\n" 9012 " vec4 gs_data;\n" 9013 " vec4 tc_data;\n" 9014 " vec4 te_data;\n" 9015 " vec4 vs_data;\n" 9016 "} gs;\n" 9017 "\n" 9018 "out vec4 result;\n" 9019 "\n" 9020 "subroutine void subroutineTypeFS(out vec4 result);\n" 9021 "\n" 9022 "subroutine(subroutineTypeFS) void subroutine1(out vec4 result)\n" 9023 "{\n" 9024 " result = vec4(5, 6, 7, 8);\n" 9025 "}\n" 9026 "\n" 9027 "subroutine uniform subroutineTypeFS function;\n" 9028 "\n" 9029 "void main()\n" 9030 "{\n" 9031 " vec4 fs_data;\n" 9032 "\n" 9033 " function(fs_data);\n" 9034 " result = gs.gs_data + gs.tc_data + gs.te_data + gs.vs_data + fs_data;\n" 9035 "}\n"; 9036} 9037 9038/** Retrieves body of a geometry shader that should be used by the test program. 9039 * 9040 * @return Requested string. 9041 **/ 9042std::string FunctionalTest17::getGeometryShaderBody() const 9043{ 9044 return "#version 400\n" 9045 "\n" 9046 "#extension GL_ARB_shader_subroutine : require\n" 9047 "\n" 9048 "layout(points) in;\n" 9049 "layout(triangle_strip, max_vertices = 4) out;\n" 9050 "\n" 9051 "subroutine void subroutineTypeGS(out vec4 result);\n" 9052 "\n" 9053 "subroutine(subroutineTypeGS) void subroutine1(out vec4 result)\n" 9054 "{\n" 9055 " result = vec4(4, 5, 6, 7);\n" 9056 "}\n" 9057 "\n" 9058 "subroutine uniform subroutineTypeGS function;\n" 9059 "\n" 9060 "in TE_DATA\n" 9061 "{\n" 9062 " vec4 tc_data;\n" 9063 " vec4 te_data;\n" 9064 " vec4 vs_data;\n" 9065 "} te[];\n" 9066 "\n" 9067 "out GS_DATA\n" 9068 "{\n" 9069 " vec4 gs_data;\n" 9070 " vec4 tc_data;\n" 9071 " vec4 te_data;\n" 9072 " vec4 vs_data;\n" 9073 "} result;\n" 9074 "\n" 9075 "void main()\n" 9076 "{\n" 9077 " function(result.gs_data);\n" 9078 " gl_Position = vec4(1, -1, 0, 1);\n" 9079 " result.tc_data = te[0].tc_data;\n" 9080 " result.te_data = te[0].te_data;\n" 9081 " result.vs_data = te[0].vs_data;\n" 9082 " EmitVertex();\n" 9083 "\n" 9084 " function(result.gs_data);\n" 9085 " gl_Position = vec4(-1, -1, 0, 1);\n" 9086 " result.tc_data = te[0].tc_data;\n" 9087 " result.te_data = te[0].te_data;\n" 9088 " result.vs_data = te[0].vs_data;\n" 9089 " EmitVertex();\n" 9090 "\n" 9091 " function(result.gs_data);\n" 9092 " gl_Position = vec4(1, 1, 0, 1);\n" 9093 " result.tc_data = te[0].tc_data;\n" 9094 " result.te_data = te[0].te_data;\n" 9095 " result.vs_data = te[0].vs_data;\n" 9096 " EmitVertex();\n" 9097 "\n" 9098 " function(result.gs_data);\n" 9099 " gl_Position = vec4(-1, 1, 0, 1);\n" 9100 " result.tc_data = te[0].tc_data;\n" 9101 " result.te_data = te[0].te_data;\n" 9102 " result.vs_data = te[0].vs_data;\n" 9103 " EmitVertex();\n" 9104 " EndPrimitive();\n" 9105 "}\n"; 9106} 9107 9108/** Retrieves body of a tessellation control shader that should be used by the test program. 9109 * 9110 * @return Requested string. 9111 **/ 9112std::string FunctionalTest17::getTessellationControlShaderBody() const 9113{ 9114 return "#version 400\n" 9115 "\n" 9116 "#extension GL_ARB_shader_subroutine : require\n" 9117 "\n" 9118 "layout (vertices = 4) out;\n" 9119 "\n" 9120 "subroutine void subroutineTypeTC(out vec4 result);\n" 9121 "\n" 9122 "subroutine(subroutineTypeTC) void subroutine1(out vec4 result)\n" 9123 "{\n" 9124 " result = vec4(2, 3, 4, 5);\n" 9125 "}\n" 9126 "\n" 9127 "subroutine uniform subroutineTypeTC function;\n" 9128 "\n" 9129 "in VS_DATA\n" 9130 "{\n" 9131 " vec4 vs_data;\n" 9132 "} vs[];\n" 9133 "\n" 9134 "out TC_DATA\n" 9135 "{\n" 9136 " vec4 tc_data;\n" 9137 " vec4 vs_data;\n" 9138 "} result[];\n" 9139 "\n" 9140 "void main()\n" 9141 "{\n" 9142 " gl_TessLevelInner[0] = 1.0;\n" 9143 " gl_TessLevelInner[1] = 1.0;\n" 9144 " gl_TessLevelOuter[0] = 1.0;\n" 9145 " gl_TessLevelOuter[1] = 1.0;\n" 9146 " gl_TessLevelOuter[2] = 1.0;\n" 9147 " gl_TessLevelOuter[3] = 1.0;\n" 9148 "\n" 9149 " function(result[gl_InvocationID].tc_data);\n" 9150 " result[gl_InvocationID].vs_data = vs[gl_InvocationID].vs_data;\n" 9151 "}\n"; 9152} 9153 9154/** Retrieves body of a tessellation evaluation shader that should be used 9155 * by the test program. 9156 * 9157 * @return Requested string. 9158 **/ 9159std::string FunctionalTest17::getTessellationEvaluationShaderBody() const 9160{ 9161 return "#version 400\n" 9162 "\n" 9163 "#extension GL_ARB_shader_subroutine : require\n" 9164 "\n" 9165 "layout (quads, point_mode) in;\n" 9166 "\n" 9167 "subroutine void subroutineTypeTE(out vec4 result);\n" 9168 "\n" 9169 "subroutine(subroutineTypeTE) void subroutine1(out vec4 result)\n" 9170 "{\n" 9171 " result = vec4(3, 4, 5, 6);\n" 9172 "}\n" 9173 "\n" 9174 "subroutine uniform subroutineTypeTE function;\n" 9175 "\n" 9176 "in TC_DATA\n" 9177 "{\n" 9178 " vec4 tc_data;\n" 9179 " vec4 vs_data;\n" 9180 "} tc[];\n" 9181 "\n" 9182 "out TE_DATA\n" 9183 "{\n" 9184 " vec4 tc_data;\n" 9185 " vec4 te_data;\n" 9186 " vec4 vs_data;\n" 9187 "} result;\n" 9188 "\n" 9189 "void main()\n" 9190 "{\n" 9191 " result.vs_data = tc[0].vs_data;\n" 9192 " result.tc_data = tc[0].tc_data;\n" 9193 " function(result.te_data);\n" 9194 "}\n"; 9195} 9196 9197/** Retrieves body of a vertex shader that should be used by the test program. 9198 * 9199 * @return Requested string. 9200 **/ 9201std::string FunctionalTest17::getVertexShaderBody() const 9202{ 9203 return "#version 400\n" 9204 "\n" 9205 "#extension GL_ARB_shader_subroutine : require\n" 9206 "\n" 9207 "out VS_DATA\n" 9208 "{\n" 9209 " vec4 vs_data;\n" 9210 "} result;\n" 9211 "\n" 9212 "subroutine void subroutineTypeVS(out vec4 result);\n" 9213 "\n" 9214 "subroutine(subroutineTypeVS) void subroutine1(out vec4 result)\n" 9215 "{\n" 9216 " result = vec4(1, 2, 3, 4);\n" 9217 "}\n" 9218 "\n" 9219 "subroutine uniform subroutineTypeVS function;\n" 9220 "\n" 9221 "void main()\n" 9222 "{\n" 9223 " function(result.vs_data);\n" 9224 "}\n"; 9225} 9226 9227/** Initializes all buffers and GL objects required to run the test. */ 9228void FunctionalTest17::initTest() 9229{ 9230 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9231 9232 /* Configure GL_PATCH_VERTICES so that TC only takes a single patch vertex */ 9233 gl.patchParameteri(GL_PATCH_VERTICES, 1); 9234 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed."); 9235 9236 /* Generate & bind a VAO */ 9237 gl.genVertexArrays(1, &m_vao_id); 9238 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 9239 9240 gl.bindVertexArray(m_vao_id); 9241 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 9242 9243 /* Set up test program object */ 9244 std::string fs_body = getFragmentShaderBody(); 9245 std::string gs_body = getGeometryShaderBody(); 9246 std::string tc_body = getTessellationControlShaderBody(); 9247 std::string te_body = getTessellationEvaluationShaderBody(); 9248 std::string vs_body = getVertexShaderBody(); 9249 9250 if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */ 9251 DE_NULL, /* n_xfb_varyings */ 9252 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 9253 { 9254 TCU_FAIL("Failed to link test program object"); 9255 } 9256 9257 /* Set up a texture object that will be used as a color attachment */ 9258 gl.genTextures(1, &m_to_id); 9259 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 9260 9261 gl.bindTexture(GL_TEXTURE_2D, m_to_id); 9262 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 9263 9264 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 9265 GL_RGBA32F, m_to_width, m_to_height); 9266 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed."); 9267 9268 /* Set up FBO */ 9269 gl.genFramebuffers(1, &m_fbo_id); 9270 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed."); 9271 9272 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 9273 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 9274 9275 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */); 9276 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 9277 9278 /* Make sure glReadPixels() does not return misaligned data */ 9279 gl.pixelStorei(GL_PACK_ALIGNMENT, 1); 9280 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed."); 9281 9282 /* Initialize a buffer that will be used to store rendered data */ 9283 m_to_data = new float[m_to_width * m_to_height * 4 /* rgba */]; 9284} 9285 9286/** Executes test iteration. 9287 * 9288 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 9289 */ 9290tcu::TestNode::IterateResult FunctionalTest17::iterate() 9291{ 9292 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9293 9294 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 9295 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 9296 { 9297 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 9298 } 9299 9300 initTest(); 9301 9302 /* Use the test program to render a full-screen test quad */ 9303 gl.useProgram(m_po_id); 9304 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 9305 9306 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */); 9307 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 9308 9309 /* Read back the data that was rendered */ 9310 gl.readPixels(0, /* x */ 9311 0, /* y */ 9312 m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_to_data); 9313 GLU_EXPECT_NO_ERROR(gl.getError(), "glReaDPixels() call failed."); 9314 9315 /* Verify the data */ 9316 verifyRenderedData(); 9317 9318 /** All done */ 9319 if (m_has_test_passed) 9320 { 9321 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 9322 } 9323 else 9324 { 9325 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 9326 } 9327 9328 return STOP; 9329} 9330 9331/** Verifies the data that have been rendered by the test program. 9332 * 9333 * It is assumed the rendered data have already been copied to 9334 * m_to_data. 9335 * 9336 * If the rendered data is found to be invalid, m_has_test_passed 9337 * will be set to false. 9338 **/ 9339void FunctionalTest17::verifyRenderedData() 9340{ 9341 const float epsilon = 1e-5f; 9342 const float expected_data[4] = { 15.0f, 20.0f, 25.0f, 30.0f }; 9343 9344 for (unsigned int y = 0; y < m_to_height && m_has_test_passed; ++y) 9345 { 9346 const float* row_ptr = m_to_data + y * 4 /* rgba */ * m_to_width; 9347 9348 for (unsigned int x = 0; x < m_to_width && m_has_test_passed; ++x) 9349 { 9350 const float* pixel_ptr = row_ptr + 4 /* rgba */ * x; 9351 9352 if (de::abs(pixel_ptr[0] - expected_data[0]) > epsilon || 9353 de::abs(pixel_ptr[1] - expected_data[1]) > epsilon || 9354 de::abs(pixel_ptr[2] - expected_data[2]) > epsilon || 9355 de::abs(pixel_ptr[3] - expected_data[3]) > epsilon) 9356 { 9357 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel found at (" << x << ", " << y 9358 << "): " 9359 "expected:(" 9360 << expected_data[0] << ", " << expected_data[1] << ", " << expected_data[2] << ", " 9361 << expected_data[3] << "), found:(" << pixel_ptr[0] << ", " << pixel_ptr[1] << ", " 9362 << pixel_ptr[2] << ", " << pixel_ptr[3] << ")." << tcu::TestLog::EndMessage; 9363 9364 m_has_test_passed = false; 9365 } 9366 } /* for (all columns) */ 9367 } /* for (all rows) */ 9368} 9369 9370/** Constructor. 9371 * 9372 * @param context Rendering context. 9373 * 9374 **/ 9375FunctionalTest18_19::FunctionalTest18_19(deqp::Context& context) 9376 : TestCase(context, "control_flow_and_returned_subroutine_values_used_as_subroutine_input", 9377 "Makes sure that calling a subroutine with argument value returned by " 9378 "another subroutine works correctly. Also checks that subroutine and " 9379 "subroutine uniforms work as expected when used in connection with control " 9380 "flow functions.") 9381 , m_has_test_passed(true) 9382 , m_n_points_to_draw(16) /* arbitrary value */ 9383 , m_po_id(0) 9384 , m_po_subroutine_divide_by_two_location(GL_INVALID_INDEX) 9385 , m_po_subroutine_multiply_by_four_location(GL_INVALID_INDEX) 9386 , m_po_subroutine_returns_false_location(GL_INVALID_INDEX) 9387 , m_po_subroutine_returns_true_location(GL_INVALID_INDEX) 9388 , m_po_subroutine_uniform_bool_operator1(-1) 9389 , m_po_subroutine_uniform_bool_operator2(-1) 9390 , m_po_subroutine_uniform_vec4_processor1(-1) 9391 , m_po_subroutine_uniform_vec4_processor2(-1) 9392 , m_xfb_bo_id(0) 9393 , m_vao_id(0) 9394 , m_vs_id(0) 9395{ 9396 /* Left blank intentionally */ 9397} 9398 9399/** De-initializes all GL objects that may have been created during test execution */ 9400void FunctionalTest18_19::deinit() 9401{ 9402 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9403 9404 if (m_po_id != 0) 9405 { 9406 gl.deleteProgram(m_po_id); 9407 9408 m_po_id = 0; 9409 } 9410 9411 if (m_vao_id != 0) 9412 { 9413 gl.deleteVertexArrays(1, &m_vao_id); 9414 9415 m_vao_id = 0; 9416 } 9417 9418 if (m_vs_id != 0) 9419 { 9420 gl.deleteShader(m_vs_id); 9421 9422 m_vs_id = 0; 9423 } 9424 9425 if (m_xfb_bo_id != 0) 9426 { 9427 gl.deleteBuffers(1, &m_xfb_bo_id); 9428 9429 m_xfb_bo_id = 0; 9430 } 9431} 9432 9433/** Executes a single test iteration using user-specified properties. If the 9434 * iterations fails, m_has_test_passed is set to false. 9435 * 9436 * @param bool_operator1_subroutine_location Location of a subroutine to be assigned to 9437 * bool_operator1 subroutine uniform. 9438 * @param bool_operator2_subroutine_location Location of a subroutine to be assigned to 9439 * bool_operator2 subroutine uniform. 9440 * @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to 9441 * vec4_operator1 subroutine uniform. 9442 * @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to 9443 * vec4_operator2 subroutine uniform. 9444 &**/ 9445void FunctionalTest18_19::executeTest(glw::GLuint bool_operator1_subroutine_location, 9446 glw::GLuint bool_operator2_subroutine_location, 9447 glw::GLuint vec4_operator1_subroutine_location, 9448 glw::GLuint vec4_operator2_subroutine_location) 9449{ 9450 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9451 9452 /* Set up subroutines */ 9453 glw::GLuint subroutine_configuration[4 /* total number of subroutines */] = { 0 }; 9454 9455 subroutine_configuration[m_po_subroutine_uniform_bool_operator1] = bool_operator1_subroutine_location; 9456 subroutine_configuration[m_po_subroutine_uniform_bool_operator2] = bool_operator2_subroutine_location; 9457 subroutine_configuration[m_po_subroutine_uniform_vec4_processor1] = vec4_operator1_subroutine_location; 9458 subroutine_configuration[m_po_subroutine_uniform_vec4_processor2] = vec4_operator2_subroutine_location; 9459 9460 gl.useProgram(m_po_id); 9461 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 9462 9463 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 4 /* count */, subroutine_configuration); 9464 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed"); 9465 9466 /* Draw test-specific number of points */ 9467 gl.beginTransformFeedback(GL_POINTS); 9468 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed"); 9469 { 9470 gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw); 9471 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed"); 9472 } 9473 gl.endTransformFeedback(); 9474 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed"); 9475 9476 /* Map the BO storage into process space */ 9477 const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 9478 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 9479 9480 verifyXFBData(xfb_data_ptr, bool_operator1_subroutine_location, bool_operator2_subroutine_location, 9481 vec4_operator1_subroutine_location, vec4_operator2_subroutine_location); 9482 9483 /* Unmap BO storage */ 9484 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 9485 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 9486} 9487 9488/** Retrieves body of a vertex shader to be used by the test. */ 9489std::string FunctionalTest18_19::getVertexShaderBody() const 9490{ 9491 return "#version 400\n" 9492 "\n" 9493 "subroutine bool bool_processor();\n" 9494 "subroutine vec4 vec4_processor(in vec4 iparam);\n" 9495 "\n" 9496 "subroutine(bool_processor) bool returnsFalse()\n" 9497 "{\n" 9498 " return false;\n" 9499 "}\n" 9500 "\n" 9501 "subroutine(bool_processor) bool returnsTrue()\n" 9502 "{\n" 9503 " return true;\n" 9504 "}\n" 9505 "\n" 9506 "subroutine(vec4_processor) vec4 divideByTwo(in vec4 iparam)\n" 9507 "{\n" 9508 " return iparam * vec4(0.5);\n" 9509 "}\n" 9510 "\n" 9511 "subroutine(vec4_processor) vec4 multiplyByFour(in vec4 iparam)\n" 9512 "{\n" 9513 " return iparam * vec4(4.0);\n" 9514 "}\n" 9515 "\n" 9516 "subroutine uniform bool_processor bool_operator1;\n" 9517 "subroutine uniform bool_processor bool_operator2;\n" 9518 "subroutine uniform vec4_processor vec4_operator1;\n" 9519 "subroutine uniform vec4_processor vec4_operator2;\n" 9520 "\n" 9521 "out float result;\n" 9522 "\n" 9523 "void main()\n" 9524 "{\n" 9525 " if (bool_operator1() )\n" 9526 " {\n" 9527 " float value = float( (3 * gl_VertexID + 1) * 2);\n" 9528 "\n" 9529 " while (bool_operator1() )\n" 9530 " {\n" 9531 " value /= float(gl_VertexID + 2);\n" 9532 "\n" 9533 " if (value <= 1.0f) break;\n" 9534 " }\n" 9535 "\n" 9536 " result = value;\n" 9537 " }\n" 9538 " else\n" 9539 " {\n" 9540 " vec4 value = vec4(gl_VertexID, gl_VertexID + 1,\n" 9541 " gl_VertexID + 2, gl_VertexID + 3);\n" 9542 "\n" 9543 " switch (gl_VertexID % 2)\n" 9544 " {\n" 9545 " case 0:\n" 9546 " {\n" 9547 " for (int iteration = 0; iteration < gl_VertexID && bool_operator2(); ++iteration)\n" 9548 " {\n" 9549 " value = vec4_operator2(vec4_operator1(value));\n" 9550 " }\n" 9551 "\n" 9552 " break;\n" 9553 " }\n" 9554 "\n" 9555 " case 1:\n" 9556 " {\n" 9557 " for (int iteration = 0; iteration < gl_VertexID * 2; ++iteration)\n" 9558 " {\n" 9559 " value = vec4_operator1(vec4_operator2(value));\n" 9560 " }\n" 9561 "\n" 9562 " break;\n" 9563 " }\n" 9564 " }\n" 9565 "\n" 9566 " result = value.x + value.y + value.z + value.w;\n" 9567 "\n" 9568 " }\n" 9569 "}\n"; 9570} 9571 9572/** Initializes all GL objects required to run the test. */ 9573void FunctionalTest18_19::initTest() 9574{ 9575 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9576 const char* varyings[1] = { "result" }; 9577 std::string vs_body = getVertexShaderBody(); 9578 const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]); 9579 9580 if (!Utils::buildProgram(gl, vs_body, "", /* tc_body */ 9581 "", /* te_body */ 9582 "", /* gs_body */ 9583 "", /* fs_body */ 9584 varyings, n_varyings, &m_vs_id, DE_NULL, /* out_tc_id */ 9585 DE_NULL, /* out_te_id */ 9586 DE_NULL, /* out_gs_id */ 9587 DE_NULL, /* out_fs_id */ 9588 &m_po_id)) 9589 { 9590 TCU_FAIL("Failed to build test program object"); 9591 } 9592 9593 /* Retrieve subroutine & subroutine uniform locations */ 9594 m_po_subroutine_divide_by_two_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "divideByTwo"); 9595 m_po_subroutine_multiply_by_four_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "multiplyByFour"); 9596 m_po_subroutine_returns_false_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsFalse"); 9597 m_po_subroutine_returns_true_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsTrue"); 9598 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed"); 9599 9600 if (m_po_subroutine_divide_by_two_location == GL_INVALID_INDEX || 9601 m_po_subroutine_multiply_by_four_location == GL_INVALID_INDEX || 9602 m_po_subroutine_returns_false_location == GL_INVALID_INDEX || 9603 m_po_subroutine_returns_true_location == GL_INVALID_INDEX) 9604 { 9605 TCU_FAIL("glGetSubroutineIndex() returned GL_INVALID_INDEX for a valid subroutine"); 9606 } 9607 9608 m_po_subroutine_uniform_bool_operator1 = 9609 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator1"); 9610 m_po_subroutine_uniform_bool_operator2 = 9611 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator2"); 9612 m_po_subroutine_uniform_vec4_processor1 = 9613 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator1"); 9614 m_po_subroutine_uniform_vec4_processor2 = 9615 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator2"); 9616 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed"); 9617 9618 if (m_po_subroutine_uniform_bool_operator1 == -1 || m_po_subroutine_uniform_bool_operator2 == -1 || 9619 m_po_subroutine_uniform_vec4_processor1 == -1 || m_po_subroutine_uniform_vec4_processor2 == -1) 9620 { 9621 TCU_FAIL("glGetSubroutineUniformLocation() returned -1 for an active subroutine uniform"); 9622 } 9623 9624 /* Set up XFB BO */ 9625 const unsigned int bo_size = static_cast<unsigned int>(sizeof(float) * m_n_points_to_draw); 9626 9627 gl.genBuffers(1, &m_xfb_bo_id); 9628 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 9629 9630 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 9631 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 9632 9633 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 9634 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 9635 9636 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_COPY); 9637 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 9638 9639 /* Set up a VAO */ 9640 gl.genVertexArrays(1, &m_vao_id); 9641 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 9642 9643 gl.bindVertexArray(m_vao_id); 9644 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 9645} 9646 9647/** Executes test iteration. 9648 * 9649 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 9650 */ 9651tcu::TestNode::IterateResult FunctionalTest18_19::iterate() 9652{ 9653 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 9654 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 9655 { 9656 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 9657 } 9658 9659 /* Initialize all GL objects required to run the test */ 9660 initTest(); 9661 9662 /* Iterate over all subroutine permutations */ 9663 const glw::GLuint subroutine_bool_operators[] = { m_po_subroutine_returns_false_location, 9664 m_po_subroutine_returns_true_location }; 9665 const unsigned int n_subroutine_bool_operators = 9666 sizeof(subroutine_bool_operators) / sizeof(subroutine_bool_operators[0]); 9667 9668 const glw::GLuint subroutine_vec4_operators[] = { m_po_subroutine_divide_by_two_location, 9669 m_po_subroutine_multiply_by_four_location }; 9670 const unsigned int n_subroutine_vec4_operators = 9671 sizeof(subroutine_vec4_operators) / sizeof(subroutine_vec4_operators[0]); 9672 9673 for (unsigned int n_subroutine_uniform_bool_operator1 = 0; 9674 n_subroutine_uniform_bool_operator1 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator1) 9675 { 9676 for (unsigned int n_subroutine_uniform_bool_operator2 = 0; 9677 n_subroutine_uniform_bool_operator2 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator2) 9678 { 9679 for (unsigned int n_subroutine_uniform_vec4_operator1 = 0; 9680 n_subroutine_uniform_vec4_operator1 < n_subroutine_vec4_operators; 9681 ++n_subroutine_uniform_vec4_operator1) 9682 { 9683 for (unsigned int n_subroutine_uniform_vec4_operator2 = 0; 9684 n_subroutine_uniform_vec4_operator2 < n_subroutine_vec4_operators; 9685 ++n_subroutine_uniform_vec4_operator2) 9686 { 9687 executeTest(subroutine_bool_operators[n_subroutine_uniform_bool_operator1], 9688 subroutine_bool_operators[n_subroutine_uniform_bool_operator2], 9689 subroutine_vec4_operators[n_subroutine_uniform_vec4_operator1], 9690 subroutine_vec4_operators[n_subroutine_uniform_vec4_operator2]); 9691 } /* for (all subroutine vec4 operator subroutines used for processor2) */ 9692 } /* for (all subroutine vec4 operator subroutines used for processor1) */ 9693 } /* for (all subroutine bool operator subroutines used for operator2) */ 9694 } /* for (all subroutine bool operator subroutines used for operator1) */ 9695 9696 /* All done */ 9697 if (m_has_test_passed) 9698 { 9699 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 9700 } 9701 else 9702 { 9703 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 9704 } 9705 9706 return STOP; 9707} 9708 9709/** Divides input argument by two. The result value is returned to the 9710 * caller. 9711 * 9712 * @param data Input value. 9713 * 9714 * @return As per description. 9715 **/ 9716tcu::Vec4 FunctionalTest18_19::vec4operator_div2(tcu::Vec4 data) 9717{ 9718 return data * 0.5f; 9719} 9720 9721/** Multiplies input argument by four. The result value is returned to the 9722 * caller. 9723 * 9724 * @param data Input value. 9725 * 9726 * @return As per description. 9727 **/ 9728tcu::Vec4 FunctionalTest18_19::vec4operator_mul4(tcu::Vec4 data) 9729{ 9730 return data * 4.0f; 9731} 9732 9733/** Verifies data XFBed out by the vertex shader. It is assumed the subroutines were configured 9734 * as per passed arguments, prior to the draw call. 9735 * 9736 * If the result data is found to be invalid, m_has_test_passed is set to false. 9737 * 9738 * @param data XFBed data. 9739 * @param bool_operator1_subroutine_location Location of a subroutine to be assigned to 9740 * bool_operator1 subroutine uniform. 9741 * @param bool_operator2_subroutine_location Location of a subroutine to be assigned to 9742 * bool_operator2 subroutine uniform. 9743 * @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to 9744 * vec4_operator1 subroutine uniform. 9745 * @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to 9746 * vec4_operator2 subroutine uniform. 9747 */ 9748void FunctionalTest18_19::verifyXFBData(const glw::GLvoid* data, glw::GLuint bool_operator1_subroutine_location, 9749 glw::GLuint bool_operator2_subroutine_location, 9750 glw::GLuint vec4_operator1_subroutine_location, 9751 glw::GLuint vec4_operator2_subroutine_location) 9752{ 9753 bool bool_operator1_result = false; 9754 bool bool_operator2_result = false; 9755 const float epsilon = 1e-5f; 9756 PFNVEC4OPERATORPROC pVec4Operator1 = NULL; 9757 PFNVEC4OPERATORPROC pVec4Operator2 = NULL; 9758 const glw::GLfloat* traveller_ptr = (const glw::GLfloat*)data; 9759 9760 bool_operator1_result = (bool_operator1_subroutine_location == m_po_subroutine_returns_true_location); 9761 bool_operator2_result = (bool_operator2_subroutine_location == m_po_subroutine_returns_true_location); 9762 pVec4Operator1 = (vec4_operator1_subroutine_location == m_po_subroutine_divide_by_two_location) ? 9763 vec4operator_div2 : 9764 vec4operator_mul4; 9765 pVec4Operator2 = (vec4_operator2_subroutine_location == m_po_subroutine_divide_by_two_location) ? 9766 vec4operator_div2 : 9767 vec4operator_mul4; 9768 9769 for (unsigned int n_vertex = 0; n_vertex < m_n_points_to_draw; ++n_vertex) 9770 { 9771 float expected_value = 0.0f; 9772 9773 if (bool_operator1_result) 9774 { 9775 float value = float((3 * n_vertex + 1) * 2); 9776 9777 while (bool_operator1_result) 9778 { 9779 value /= float(n_vertex + 2); 9780 9781 if (value <= 1.0f) 9782 break; 9783 } 9784 9785 expected_value = value; 9786 } 9787 else 9788 { 9789 tcu::Vec4 value((float)n_vertex, (float)n_vertex + 1, (float)n_vertex + 2, (float)n_vertex + 3); 9790 9791 switch (n_vertex % 2) 9792 { 9793 case 0: 9794 { 9795 for (unsigned int iteration = 0; iteration < n_vertex && bool_operator2_result; ++iteration) 9796 { 9797 value = pVec4Operator2(pVec4Operator1(value)); 9798 } 9799 9800 break; 9801 } 9802 9803 case 1: 9804 { 9805 for (unsigned int iteration = 0; iteration < n_vertex * 2; ++iteration) 9806 { 9807 value = pVec4Operator1(pVec4Operator2(value)); 9808 } 9809 9810 break; 9811 } 9812 } /* switch (n_vertex % 2) */ 9813 9814 expected_value = value.x() + value.y() + value.z() + value.w(); 9815 } 9816 9817 if (de::abs(expected_value - *traveller_ptr) > epsilon) 9818 { 9819 m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data was found to be invalid at index [" << n_vertex 9820 << "]" 9821 "for the following subroutine location configuration:" 9822 " bool_operator1_subroutine_location:[" 9823 << bool_operator1_subroutine_location << "]" 9824 " bool_operator2_subroutine_location:[" 9825 << bool_operator2_subroutine_location << "]" 9826 " vec4_operator1_subroutine_location:[" 9827 << vec4_operator1_subroutine_location << "]" 9828 " vec4_operator2_subroutine_location:[" 9829 << vec4_operator2_subroutine_location << "];" 9830 " expected data:" 9831 << expected_value << ", found:" << *traveller_ptr << tcu::TestLog::EndMessage; 9832 9833 m_has_test_passed = false; 9834 } 9835 9836 ++traveller_ptr; 9837 } /* for (all drawn points) */ 9838} 9839 9840/** Constructor. 9841 * 9842 * @param context Rendering context. 9843 * 9844 **/ 9845NegativeTest1::NegativeTest1(deqp::Context& context) 9846 : TestCase(context, "subroutine_errors", "Verifies all GL_INVALID_OPERATION, GL_INVALID_VALUE, GL_INVALID ENUM " 9847 "errors related to subroutine usage are properly generated.") 9848 , m_has_test_passed(true) 9849 , m_po_active_subroutine_uniform_locations(0) 9850 , m_po_active_subroutine_uniforms(0) 9851 , m_po_active_subroutines(0) 9852 , m_po_subroutine_uniform_function_index(-1) 9853 , m_po_subroutine_uniform_function2_index(-1) 9854 , m_po_subroutine_test1_index(GL_INVALID_INDEX) 9855 , m_po_subroutine_test2_index(GL_INVALID_INDEX) 9856 , m_po_subroutine_test3_index(GL_INVALID_INDEX) 9857 , m_po_not_linked_id(0) 9858 , m_po_id(0) 9859 , m_vs_id(0) 9860{ 9861 /* Left blank intentionally */ 9862} 9863 9864/** Deinitializes all GL objects that may have been created during 9865 * test execution. 9866 **/ 9867void NegativeTest1::deinit() 9868{ 9869 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9870 9871 if (m_po_id != 0) 9872 { 9873 gl.deleteProgram(m_po_id); 9874 9875 m_po_id = 0; 9876 } 9877 9878 if (m_po_not_linked_id != 0) 9879 { 9880 gl.deleteProgram(m_po_not_linked_id); 9881 9882 m_po_not_linked_id = 0; 9883 } 9884 9885 if (m_vs_id != 0) 9886 { 9887 gl.deleteShader(m_vs_id); 9888 9889 m_vs_id = 0; 9890 } 9891} 9892 9893/** Initializes all GL objects required to run the test. */ 9894void NegativeTest1::initTest() 9895{ 9896 glw::GLint compile_status = GL_FALSE; 9897 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9898 9899 /* Create program objects */ 9900 m_po_not_linked_id = gl.createProgram(); 9901 m_po_id = gl.createProgram(); 9902 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed."); 9903 9904 /* Create vertex shader object */ 9905 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 9906 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 9907 9908 /* Set up vertex shader */ 9909 const char* vs_body = "#version 400\n" 9910 "\n" 9911 "#extension GL_ARB_shader_subroutine : require\n" 9912 "\n" 9913 "subroutine void subroutineType (out ivec2 arg);\n" 9914 "subroutine void subroutineType2(out ivec4 arg);\n" 9915 "\n" 9916 "subroutine(subroutineType) void test1(out ivec2 arg)\n" 9917 "{\n" 9918 " arg = ivec2(1, 2);\n" 9919 "}\n" 9920 "subroutine(subroutineType) void test2(out ivec2 arg)\n" 9921 "{\n" 9922 " arg = ivec2(3,4);\n" 9923 "}\n" 9924 "subroutine(subroutineType2) void test3(out ivec4 arg)\n" 9925 "{\n" 9926 " arg = ivec4(1, 2, 3, 4);\n" 9927 "}\n" 9928 "\n" 9929 "subroutine uniform subroutineType function;\n" 9930 "subroutine uniform subroutineType2 function2;\n" 9931 "\n" 9932 "void main()\n" 9933 "{\n" 9934 " ivec2 test;\n" 9935 " ivec4 test2;\n" 9936 "\n" 9937 " function(test);\n" 9938 "\n" 9939 " if (test.x > 2)\n" 9940 " {\n" 9941 " gl_Position = vec4(1);\n" 9942 " }\n" 9943 " else\n" 9944 " {\n" 9945 " function2(test2);\n" 9946 "\n" 9947 " gl_Position = vec4(float(test2.x) );\n" 9948 " }\n" 9949 "}\n"; 9950 9951 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */); 9952 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 9953 9954 gl.compileShader(m_vs_id); 9955 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 9956 9957 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); 9958 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 9959 9960 if (compile_status == GL_FALSE) 9961 { 9962 TCU_FAIL("Shader compilation failed"); 9963 } 9964 9965 /* Set up & link the test program object */ 9966 glw::GLint link_status = GL_FALSE; 9967 9968 gl.attachShader(m_po_id, m_vs_id); 9969 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 9970 9971 gl.linkProgram(m_po_id); 9972 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 9973 9974 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 9975 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 9976 9977 if (link_status == GL_FALSE) 9978 { 9979 TCU_FAIL("Program linking failed"); 9980 } 9981 9982 /* Query test program object's properties */ 9983 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, 9984 &m_po_active_subroutine_uniform_locations); 9985 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &m_po_active_subroutine_uniforms); 9986 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &m_po_active_subroutines); 9987 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call(s) failed."); 9988 9989 if (m_po_active_subroutine_uniform_locations != 2) 9990 { 9991 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS value returned"); 9992 } 9993 9994 m_po_subroutine_test1_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test1"); 9995 m_po_subroutine_test2_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test2"); 9996 m_po_subroutine_test3_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test3"); 9997 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed."); 9998 9999 if (m_po_subroutine_test1_index == GL_INVALID_INDEX || m_po_subroutine_test2_index == GL_INVALID_INDEX || 10000 m_po_subroutine_test3_index == GL_INVALID_INDEX) 10001 { 10002 TCU_FAIL("Invalid subroutine index returned"); 10003 } 10004 10005 m_po_subroutine_uniform_function_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function"); 10006 m_po_subroutine_uniform_function2_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function2"); 10007 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed."); 10008 10009 if (m_po_subroutine_uniform_function_index == -1 || m_po_subroutine_uniform_function2_index == -1) 10010 { 10011 TCU_FAIL("Invalid subroutine uniform index returned"); 10012 } 10013} 10014 10015/** Executes test iteration. 10016 * 10017 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10018 */ 10019tcu::TestNode::IterateResult NegativeTest1::iterate() 10020{ 10021 glw::GLenum error_code = GL_NO_ERROR; 10022 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10023 10024 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 10025 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 10026 { 10027 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 10028 } 10029 10030 /* Initialize GL objects required to run the test */ 10031 initTest(); 10032 10033 /* The error INVALID_OPERATION is generated by GetSubroutineUniformLocation 10034 * if the program object identified by <program> has not been successfully 10035 * linked. 10036 */ 10037 gl.getSubroutineUniformLocation(m_po_not_linked_id, GL_FRAGMENT_SHADER, "subroutine_uniform_name"); 10038 10039 error_code = gl.getError(); 10040 10041 if (error_code != GL_INVALID_OPERATION) 10042 { 10043 m_testCtx.getLog() << tcu::TestLog::Message 10044 << "glGetSubroutineUniformLocation() does not generate GL_INVALID_OPERATION " 10045 "error code when called for a non-linked program object." 10046 << tcu::TestLog::EndMessage; 10047 10048 m_has_test_passed = false; 10049 } 10050 10051 /* The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or 10052 * GetActiveSubroutineUniformName if <index> is greater than or equal to the 10053 * value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage. 10054 */ 10055 glw::GLint temp_length = 0; 10056 glw::GLint temp_values = 0; 10057 10058 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 10059 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values); 10060 error_code = gl.getError(); 10061 10062 if (error_code == GL_INVALID_VALUE) 10063 { 10064 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1, 10065 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values); 10066 10067 error_code = gl.getError(); 10068 } 10069 10070 if (error_code != GL_INVALID_VALUE) 10071 { 10072 m_testCtx.getLog() << tcu::TestLog::Message 10073 << "glGetActiveSubroutineUniformiv() does not generate GL_INVALID_VALUE " 10074 "when passed <index> argument that is greater than or equal to " 10075 "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS." 10076 << tcu::TestLog::EndMessage; 10077 10078 m_has_test_passed = false; 10079 } 10080 10081 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 0, /* bufsize */ 10082 &temp_length, DE_NULL); /* name */ 10083 error_code = gl.getError(); 10084 10085 if (error_code == GL_INVALID_VALUE) 10086 { 10087 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1, 10088 0, /* bufsize */ 10089 &temp_length, DE_NULL); /* name */ 10090 10091 error_code = gl.getError(); 10092 } 10093 10094 if (error_code != GL_INVALID_VALUE) 10095 { 10096 m_testCtx.getLog() << tcu::TestLog::Message 10097 << "glGetActiveSubroutineUniformName() does not generate GL_INVALID_VALUE " 10098 "when passed <index> argument that is greater than or equal to " 10099 "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS." 10100 << tcu::TestLog::EndMessage; 10101 10102 m_has_test_passed = false; 10103 } 10104 10105 /* The error INVALID_VALUE is generated by GetActiveSubroutineName if <index> 10106 * is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader 10107 * stage. 10108 */ 10109 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines, 0, /* bufsize */ 10110 &temp_length, DE_NULL); /* name */ 10111 error_code = gl.getError(); 10112 10113 if (error_code == GL_INVALID_VALUE) 10114 { 10115 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines + 1, 0, /* bufsize */ 10116 &temp_length, DE_NULL); /* name */ 10117 10118 error_code = gl.getError(); 10119 } 10120 10121 if (error_code != GL_INVALID_VALUE) 10122 { 10123 m_testCtx.getLog() << tcu::TestLog::Message << "glGetActiveSubroutineName() does not generate GL_INVALID_VALUE " 10124 "when passed <index> argument that is greater than or equal to " 10125 "the value of GL_ACTIVE_SUBROUTINES." 10126 << tcu::TestLog::EndMessage; 10127 10128 m_has_test_passed = false; 10129 } 10130 10131 /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count> 10132 * is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the 10133 * shader stage <shadertype>. 10134 */ 10135 glw::GLuint index = 0; 10136 10137 gl.useProgram(m_po_id); 10138 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10139 10140 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations - 1, &index); 10141 error_code = gl.getError(); 10142 10143 if (error_code == GL_INVALID_VALUE) 10144 { 10145 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &index); 10146 10147 error_code = gl.getError(); 10148 } 10149 10150 if (error_code != GL_INVALID_VALUE) 10151 { 10152 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesiv() does not generate GL_INVALID_VALUE " 10153 "when passed <count> argument that is not equal to the value of " 10154 "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS." 10155 << tcu::TestLog::EndMessage; 10156 10157 m_has_test_passed = false; 10158 } 10159 10160 /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value 10161 * in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES 10162 * for the shader stage. 10163 */ 10164 glw::GLuint invalid_subroutine_indices[4] = { (GLuint)m_po_active_subroutines, (GLuint)m_po_active_subroutines, 10165 (GLuint)m_po_active_subroutines + 1, 10166 (GLuint)m_po_active_subroutines + 1 }; 10167 10168 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, /* count */ 10169 invalid_subroutine_indices + 0); 10170 error_code = gl.getError(); 10171 10172 if (error_code == GL_INVALID_VALUE) 10173 { 10174 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, 10175 invalid_subroutine_indices + 2); 10176 10177 error_code = gl.getError(); 10178 } 10179 10180 if (error_code != GL_INVALID_VALUE) 10181 { 10182 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesuiv() does not generate GL_INVALID_VALUE " 10183 "when the value passed via <indices> argument is greater than " 10184 "or equal to the value of GL_ACTIVE_SUBROUTINES." 10185 << tcu::TestLog::EndMessage; 10186 10187 m_has_test_passed = false; 10188 } 10189 10190 /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv() if any 10191 * subroutine index in <indices> identifies a subroutine not associated with 10192 * the type of the subroutine uniform variable assigned to the corresponding 10193 * location. 10194 */ 10195 glw::GLuint invalid_subroutine_indices2[2] = { m_po_subroutine_test1_index, m_po_subroutine_test1_index }; 10196 10197 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, invalid_subroutine_indices2); 10198 error_code = gl.getError(); 10199 10200 if (error_code != GL_INVALID_OPERATION) 10201 { 10202 m_testCtx.getLog() << tcu::TestLog::Message 10203 << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION " 10204 "when the subroutine index passed via <indices> argument identifies" 10205 "a subroutine not associated with the type of the subroutine uniform " 10206 "assigned to the corresponding location." 10207 << tcu::TestLog::EndMessage; 10208 10209 m_has_test_passed = false; 10210 } 10211 10212 /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no 10213 * program is active. 10214 */ 10215 glw::GLuint valid_subroutine_locations[2] = { 0 }; 10216 10217 valid_subroutine_locations[m_po_subroutine_uniform_function_index] = m_po_subroutine_test1_index; 10218 valid_subroutine_locations[m_po_subroutine_uniform_function2_index] = m_po_subroutine_test3_index; 10219 10220 gl.useProgram(0); 10221 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10222 10223 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, valid_subroutine_locations); 10224 error_code = gl.getError(); 10225 10226 if (error_code != GL_INVALID_OPERATION) 10227 { 10228 m_testCtx.getLog() << tcu::TestLog::Message 10229 << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION " 10230 "when called without an active program object." 10231 << tcu::TestLog::EndMessage; 10232 10233 m_has_test_passed = false; 10234 } 10235 10236 /* The error INVALID_VALUE is generated by GetUniformSubroutineuiv if 10237 * <location> is greater than or equal to the value of 10238 * ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage. 10239 */ 10240 glw::GLuint temp_value = 0; 10241 10242 gl.useProgram(m_po_id); 10243 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 10244 10245 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, &temp_value); 10246 error_code = gl.getError(); 10247 10248 if (error_code == GL_INVALID_VALUE) 10249 { 10250 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &temp_value); 10251 error_code = gl.getError(); 10252 } 10253 10254 if (error_code != GL_INVALID_VALUE) 10255 { 10256 m_testCtx.getLog() << tcu::TestLog::Message 10257 << "glGetUniformSubroutineuiv() does not generate GL_INVALID_VALUE " 10258 "when called for location that is greater than or equal to the value " 10259 "of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS." 10260 << tcu::TestLog::EndMessage; 10261 10262 m_has_test_passed = false; 10263 } 10264 10265 /* The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no 10266 * program is active for the shader stage identified by <shadertype>. 10267 */ 10268 const glw::GLenum undefined_shader_stages[] = { GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER, 10269 GL_TESS_EVALUATION_SHADER }; 10270 const unsigned int n_undefined_shader_stages = sizeof(undefined_shader_stages) / sizeof(undefined_shader_stages[0]); 10271 10272 for (unsigned int n_undefined_shader_stage = 0; n_undefined_shader_stage < n_undefined_shader_stages; 10273 ++n_undefined_shader_stage) 10274 { 10275 glw::GLenum shader_stage = undefined_shader_stages[n_undefined_shader_stage]; 10276 10277 gl.getUniformSubroutineuiv(shader_stage, 0, /* location */ 10278 &temp_value); 10279 error_code = gl.getError(); 10280 10281 if (error_code != GL_INVALID_OPERATION) 10282 { 10283 m_testCtx.getLog() << tcu::TestLog::Message 10284 << "glGetUniformSubroutineuiv() does not generate GL_INVALID_OPERATION " 10285 "when called for a shader stage that is not defined for active " 10286 "program object." 10287 << tcu::TestLog::EndMessage; 10288 10289 m_has_test_passed = false; 10290 } 10291 } /* for (all undefined shader stages) */ 10292 10293 /* All done */ 10294 if (m_has_test_passed) 10295 { 10296 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 10297 } 10298 else 10299 { 10300 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 10301 } 10302 10303 return STOP; 10304} 10305 10306/** Constructor 10307 * 10308 * @param context Rendering context. 10309 * 10310 **/ 10311NegativeTest2::NegativeTest2(deqp::Context& context) 10312 : TestCase(context, "subroutine_uniform_scope", "Verifies subroutine uniforms declared in shader stage A" 10313 "cannot be accessed from a different stage.") 10314 , m_fs_id(0) 10315 , m_gs_id(0) 10316 , m_has_test_passed(true) 10317 , m_po_id(0) 10318 , m_tc_id(0) 10319 , m_te_id(0) 10320 , m_vs_id(0) 10321{ 10322 /* Left blank intentionally */ 10323} 10324 10325/** Deinitializes all GL objects that may have been created during test execution */ 10326void NegativeTest2::deinit() 10327{ 10328 deinitGLObjects(); 10329} 10330 10331/** Deinitializes all GL objects that may have been created during test execution */ 10332void NegativeTest2::deinitGLObjects() 10333{ 10334 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10335 10336 if (m_fs_id != 0) 10337 { 10338 gl.deleteShader(m_fs_id); 10339 10340 m_fs_id = 0; 10341 } 10342 10343 if (m_gs_id != 0) 10344 { 10345 gl.deleteShader(m_gs_id); 10346 10347 m_gs_id = 0; 10348 } 10349 10350 if (m_tc_id != 0) 10351 { 10352 gl.deleteShader(m_tc_id); 10353 10354 m_tc_id = 0; 10355 } 10356 10357 if (m_te_id != 0) 10358 { 10359 gl.deleteShader(m_te_id); 10360 10361 m_te_id = 0; 10362 } 10363 10364 if (m_vs_id != 0) 10365 { 10366 gl.deleteShader(m_vs_id); 10367 10368 m_vs_id = 0; 10369 } 10370 10371 if (m_po_id != 0) 10372 { 10373 gl.deleteProgram(m_po_id); 10374 10375 m_po_id = 0; 10376 } 10377} 10378 10379/** Builds an offending program object and tries to link it. We're either expecting 10380 * a compile-time or link-time error here. 10381 * 10382 * If the program object builds successfully, the test has failed. 10383 * 10384 * @param referencing_stage Shader stage which defines a subroutine uniform that 10385 * should be called from fragment/geometry/tess control/ 10386 * tess evaluation/vertex shader stages. 10387 * 10388 **/ 10389void NegativeTest2::executeTestCase(const Utils::_shader_stage& referencing_stage) 10390{ 10391 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10392 10393 const std::string fs_body = getFragmentShaderBody(referencing_stage); 10394 const std::string gs_body = getGeometryShaderBody(referencing_stage); 10395 const std::string tc_body = getTessellationControlShaderBody(referencing_stage); 10396 const std::string te_body = getTessellationEvaluationShaderBody(referencing_stage); 10397 const std::string vs_body = getVertexShaderBody(referencing_stage); 10398 10399 if (Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, NULL, /* xfb_varyings */ 10400 0, /* n_xfb_varyings */ 10401 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 10402 { 10403 /* Test program should not have built correctly ! */ 10404 m_testCtx.getLog() << tcu::TestLog::Message << "In the following program, one of the stages references " 10405 "a subroutine that is defined in another stage. This " 10406 "is forbidden by the specification.\n" 10407 "\n" 10408 "Vertex shader:\n\n" 10409 << vs_body.c_str() << "\n\nTessellation control shader:\n\n" 10410 << tc_body.c_str() << "\n\nTessellation evaluation shader:\n\n" 10411 << te_body.c_str() << "\n\nGeometry shader:\n\n" 10412 << gs_body.c_str() << "\n\nFragment shader:\n\n" 10413 << fs_body.c_str() << tcu::TestLog::EndMessage; 10414 10415 m_has_test_passed = false; 10416 } /* if (test program was built successfully) */ 10417 10418 /* Release the shaders & the program object that buildProgram() created */ 10419 deinitGLObjects(); 10420} 10421 10422/** Retrieves an offending fragment shader body. 10423 * 10424 * @param referencing_stage Shader stage which defines the subroutine uniform that 10425 * will be called from fragment shader. 10426 * 10427 * @return Requested string. 10428 **/ 10429std::string NegativeTest2::getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const 10430{ 10431 std::stringstream result; 10432 10433 /* Form the pre-amble */ 10434 result << "#version 400\n" 10435 "\n" 10436 "#extension GL_ARB_shader_subroutine : require\n" 10437 "\n" 10438 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10439 "\n" 10440 /* Define a subroutine */ 10441 "subroutine(testSubroutineType) void fs_subroutine(out vec4 test_argument)\n" 10442 "{\n" 10443 " test_argument = vec4(1, 0, 0, 0);\n" 10444 "}\n" 10445 "\n" 10446 /* Define output variables */ 10447 "out vec4 result;\n" 10448 "\n" 10449 /* Define uniforms */ 10450 "subroutine uniform testSubroutineType test_fs_subroutine;\n" 10451 "\n" 10452 /* Define main() */ 10453 "void main()\n" 10454 "{\n" 10455 " " 10456 << getSubroutineUniformName(referencing_stage) << "(result);\n" 10457 "}\n"; 10458 10459 return result.str(); 10460} 10461 10462/** Retrieves an offending geometry shader body. 10463 * 10464 * @param referencing_stage Shader stage which defines the subroutine uniform that 10465 * will be called from geometry shader. 10466 * 10467 * @return Requested string. 10468 **/ 10469std::string NegativeTest2::getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const 10470{ 10471 std::stringstream result; 10472 10473 /* Form the pre-amble */ 10474 result << "#version 400\n" 10475 "\n" 10476 "#extension GL_ARB_shader_subroutine : require\n" 10477 "\n" 10478 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10479 "\n" 10480 "layout(points) in;\n" 10481 "layout(points, max_vertices = 1) out;\n" 10482 "\n" 10483 /* Define a subroutine */ 10484 "subroutine(testSubroutineType) void gs_subroutine(out vec4 test_argument)\n" 10485 "{\n" 10486 " test_argument = vec4(0, 1, 1, 1);\n" 10487 "}\n" 10488 "\n" 10489 /* Define output variables */ 10490 "out vec4 result;\n" 10491 "\n" 10492 /* Define uniforms */ 10493 "subroutine uniform testSubroutineType test_gs_subroutine;\n" 10494 "\n" 10495 /* Define main() */ 10496 "void main()\n" 10497 "{\n" 10498 " " 10499 << getSubroutineUniformName(referencing_stage) << "(result);\n" 10500 "}\n"; 10501 10502 return result.str(); 10503} 10504 10505/** Retrieves name of the subroutine uniform that is defined in user-specified 10506 * shader stage. 10507 * 10508 * @param stage Shader stage to retrieve the subroutine uniform name for. 10509 * 10510 * @return As per description. 10511 **/ 10512std::string NegativeTest2::getSubroutineUniformName(const Utils::_shader_stage& stage) const 10513{ 10514 std::string result = "?"; 10515 10516 switch (stage) 10517 { 10518 case Utils::SHADER_STAGE_FRAGMENT: 10519 { 10520 result = "test_fs_subroutine"; 10521 10522 break; 10523 } 10524 10525 case Utils::SHADER_STAGE_GEOMETRY: 10526 { 10527 result = "test_gs_subroutine"; 10528 10529 break; 10530 } 10531 10532 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 10533 { 10534 result = "test_tc_subroutine"; 10535 10536 break; 10537 } 10538 10539 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 10540 { 10541 result = "test_te_subroutine"; 10542 10543 break; 10544 } 10545 10546 case Utils::SHADER_STAGE_VERTEX: 10547 { 10548 result = "test_vs_subroutine"; 10549 10550 break; 10551 } 10552 10553 default: 10554 { 10555 TCU_FAIL("Unrecognized shader stage requested"); 10556 } 10557 } /* switch (stage) */ 10558 10559 return result; 10560} 10561 10562/** Retrieves an offending tessellation control shader body. 10563 * 10564 * @param referencing_stage Shader stage which defines the subroutine uniform that 10565 * will be called from tessellation control shader. 10566 * 10567 * @return Requested string. 10568 **/ 10569std::string NegativeTest2::getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const 10570{ 10571 std::stringstream result; 10572 10573 /* Form the pre-amble */ 10574 result << "#version 400\n" 10575 "\n" 10576 "#extension GL_ARB_shader_subroutine : require\n" 10577 "\n" 10578 "layout(vertices = 4) out;\n" 10579 "\n" 10580 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10581 "\n" 10582 /* Define a subroutine */ 10583 "subroutine(testSubroutineType) void tc_subroutine(out vec4 test_argument)\n" 10584 "{\n" 10585 " test_argument = vec4(0, 0, 1, 0);\n" 10586 "}\n" 10587 "\n" 10588 /* Define uniforms */ 10589 "subroutine uniform testSubroutineType test_tc_subroutine;\n" 10590 "\n" 10591 /* Define main() */ 10592 "void main()\n" 10593 "{\n" 10594 " " 10595 << getSubroutineUniformName(referencing_stage) << "(gl_out[gl_InvocationID].gl_Position);\n" 10596 "}\n"; 10597 10598 return result.str(); 10599} 10600 10601/** Retrieves an offending tessellation evaluation shader body. 10602 * 10603 * @param referencing_stage Shader stage which defines the subroutine uniform that 10604 * will be called from tessellation evaluation shader. 10605 * 10606 * @return Requested string. 10607 **/ 10608std::string NegativeTest2::getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const 10609{ 10610 std::stringstream result; 10611 10612 /* Form the pre-amble */ 10613 result << "#version 400\n" 10614 "\n" 10615 "#extension GL_ARB_shader_subroutine : require\n" 10616 "\n" 10617 "layout(quads) in;\n" 10618 "\n" 10619 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10620 "\n" 10621 /* Define a subroutine */ 10622 "subroutine(testSubroutineType) void te_subroutine(out vec4 test_argument)\n" 10623 "{\n" 10624 " test_argument = vec4(1, 1, 1, 1);\n" 10625 "}\n" 10626 "\n" 10627 /* Define uniforms */ 10628 "subroutine uniform testSubroutineType test_te_subroutine;\n" 10629 "\n" 10630 /* Define main() */ 10631 "void main()\n" 10632 "{\n" 10633 " " 10634 << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n" 10635 "}\n"; 10636 10637 return result.str(); 10638} 10639 10640/** Retrieves an offending vertex shader body. 10641 * 10642 * @param referencing_stage Shader stage which defines the subroutine uniform that 10643 * will be called from vertex shader. 10644 * 10645 * @return Requested string. 10646 **/ 10647std::string NegativeTest2::getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const 10648{ 10649 std::stringstream result; 10650 10651 /* Form the pre-amble */ 10652 result << "#version 400\n" 10653 "\n" 10654 "#extension GL_ARB_shader_subroutine : require\n" 10655 "\n" 10656 "subroutine void testSubroutineType(out vec4 test_argument);\n" 10657 "\n" 10658 /* Define a subroutine */ 10659 "subroutine(testSubroutineType) void vs_subroutine(out vec4 test_argument)\n" 10660 "{\n" 10661 " test_argument = vec4(0, 1, 0, 0);\n" 10662 "}\n" 10663 "\n" 10664 /* Define uniforms */ 10665 "subroutine uniform testSubroutineType test_vs_subroutine;\n" 10666 "\n" 10667 /* Define main() */ 10668 "void main()\n" 10669 "{\n" 10670 " " 10671 << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n" 10672 "}\n"; 10673 10674 return result.str(); 10675} 10676 10677/** Executes test iteration. 10678 * 10679 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10680 */ 10681tcu::TestNode::IterateResult NegativeTest2::iterate() 10682{ 10683 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 10684 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 10685 { 10686 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 10687 } 10688 10689 /* Iterate over all shader stages and execute the checks */ 10690 for (int referencing_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 10691 referencing_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++referencing_stage) 10692 { 10693 executeTestCase(static_cast<Utils::_shader_stage>(referencing_stage)); 10694 } /* for (all test cases) */ 10695 10696 /* All done */ 10697 if (m_has_test_passed) 10698 { 10699 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 10700 } 10701 else 10702 { 10703 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 10704 } 10705 10706 return STOP; 10707} 10708 10709/** Constructor. 10710 * 10711 * @param context Rendering context. 10712 * 10713 **/ 10714NegativeTest3::NegativeTest3(deqp::Context& context) 10715 : TestCase(context, "missing_subroutine_keyword", "Verifies that subroutine keyword is necessary when declaring a " 10716 "subroutine uniforn and a compilation error occurs without it.") 10717 , m_has_test_passed(true) 10718 , m_so_id(0) 10719{ 10720 /* Left blank intentionally */ 10721} 10722 10723/** Deinitializes all GL objects that may have been created during test execution */ 10724void NegativeTest3::deinit() 10725{ 10726 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10727 10728 if (m_so_id != 0) 10729 { 10730 gl.deleteShader(m_so_id); 10731 10732 m_so_id = 0; 10733 } 10734} 10735 10736/** Verifies that broken shader (for user-specified shader stage) does not compile. 10737 * 10738 * @param shader_stage Shader stage to use for the test. 10739 **/ 10740void NegativeTest3::executeTest(const Utils::_shader_stage& shader_stage) 10741{ 10742 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10743 10744 /* Generate a new shader object */ 10745 m_so_id = gl.createShader(Utils::getGLenumForShaderStage(shader_stage)); 10746 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 10747 10748 /* Assign body to the shader */ 10749 std::string body; 10750 const char* body_raw_ptr = DE_NULL; 10751 10752 switch (shader_stage) 10753 { 10754 case Utils::SHADER_STAGE_VERTEX: 10755 body = getVertexShaderBody(); 10756 break; 10757 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 10758 body = getTessellationControlShaderBody(); 10759 break; 10760 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 10761 body = getTessellationEvaluationShaderBody(); 10762 break; 10763 case Utils::SHADER_STAGE_GEOMETRY: 10764 body = getGeometryShaderBody(); 10765 break; 10766 case Utils::SHADER_STAGE_FRAGMENT: 10767 body = getFragmentShaderBody(); 10768 break; 10769 10770 default: 10771 { 10772 TCU_FAIL("Unrecognized shader stage requested"); 10773 } 10774 } /* switch (shader_stage) */ 10775 10776 body_raw_ptr = body.c_str(); 10777 10778 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */); 10779 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 10780 10781 /* Try to compile the shader */ 10782 glw::GLint compile_status = 0; 10783 10784 gl.compileShader(m_so_id); 10785 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 10786 10787 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status); 10788 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 10789 10790 if (compile_status == GL_TRUE) 10791 { 10792 m_testCtx.getLog() << tcu::TestLog::Message << "The following shader was expected to fail to compile but was " 10793 "accepted by the compiler:\n" 10794 "\n" 10795 << body.c_str() << tcu::TestLog::EndMessage; 10796 10797 m_has_test_passed = false; 10798 } 10799 10800 /* Good to release the shader at this point */ 10801 gl.deleteShader(m_so_id); 10802 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed."); 10803} 10804 10805/** Retrieves body of a broken fragment shader. 10806 * 10807 * @return Requested string. 10808 **/ 10809std::string NegativeTest3::getFragmentShaderBody() const 10810{ 10811 return "#version 400\n" 10812 "\n" 10813 "#extension GL_ARB_shader_subroutine : require\n" 10814 "\n" 10815 "subroutine void testSubroutineType(inout vec4 test);\n" 10816 "\n" 10817 "void testSubroutine1(inout vec4 test)\n" 10818 "{\n" 10819 " test += vec4(3, 4, 5, 6);\n" 10820 "}\n" 10821 "\n" 10822 "uniform testSubroutineType subroutineFunction;\n" 10823 "out vec4 result;\n" 10824 "\n" 10825 "void main()\n" 10826 "{\n" 10827 " vec4 test = vec4(2, 3, 4, 5);\n" 10828 "\n" 10829 " subroutineFunction(test);\n" 10830 "\n" 10831 " result = test;\n" 10832 "}\n"; 10833} 10834 10835/** Retrieves body of a broken geometry shader. 10836 * 10837 * @return Requested string. 10838 **/ 10839std::string NegativeTest3::getGeometryShaderBody() const 10840{ 10841 return "#version 400\n" 10842 "\n" 10843 "#extension GL_ARB_shader_subroutine : require\n" 10844 "\n" 10845 "layout(points) in;\n" 10846 "layout(points, max_vertices = 1) out;\n" 10847 "\n" 10848 "subroutine void testSubroutineType(inout vec4 test);\n" 10849 "\n" 10850 "void testSubroutine1(inout vec4 test)\n" 10851 "{\n" 10852 " test += vec4(3, 4, 5, 6);\n" 10853 "}\n" 10854 "\n" 10855 "uniform testSubroutineType subroutineFunction;\n" 10856 "\n" 10857 "void main()\n" 10858 "{\n" 10859 " vec4 test = vec4(2, 3, 4, 5);\n" 10860 "\n" 10861 " subroutineFunction(test);\n" 10862 "\n" 10863 " gl_Position = test;\n" 10864 " EmitVertex();\n" 10865 "}\n"; 10866} 10867 10868/** Retrieves body of a broken tessellation control shader. 10869 * 10870 * @return Requested string. 10871 **/ 10872std::string NegativeTest3::getTessellationControlShaderBody() const 10873{ 10874 return "#version 400\n" 10875 "\n" 10876 "#extension GL_ARB_shader_subroutine : require\n" 10877 "\n" 10878 "layout(vertices=4) out;\n" 10879 "\n" 10880 "subroutine void testSubroutineType(inout vec4 test);\n" 10881 "\n" 10882 "void testSubroutine1(inout vec4 test)\n" 10883 "{\n" 10884 " test += vec4(1, 2, 3, 4);\n" 10885 "}\n" 10886 "\n" 10887 "uniform testSubroutineType subroutineFunction;\n" 10888 "\n" 10889 "void main()\n" 10890 "{\n" 10891 " vec4 test = vec4(0, 1, 2, 3);\n" 10892 "\n" 10893 " subroutineFunction(test);\n" 10894 "\n" 10895 " gl_out[gl_InvocationID].gl_Position = test;\n" 10896 "}\n"; 10897} 10898 10899/** Retrieves body of a broken tessellation evaluation shader. 10900 * 10901 * @return Requested string. 10902 **/ 10903std::string NegativeTest3::getTessellationEvaluationShaderBody() const 10904{ 10905 return "#version 400\n" 10906 "\n" 10907 "#extension GL_ARB_shader_subroutine : require\n" 10908 "\n" 10909 "layout(quads) in;\n" 10910 "\n" 10911 "subroutine void testSubroutineType(inout vec4 test);\n" 10912 "\n" 10913 "void testSubroutine1(inout vec4 test)\n" 10914 "{\n" 10915 " test += vec4(2, 3, 4, 5);\n" 10916 "}\n" 10917 "\n" 10918 "uniform testSubroutineType subroutineFunction;\n" 10919 "\n" 10920 "void main()\n" 10921 "{\n" 10922 " vec4 test = vec4(1, 2, 3, 4);\n" 10923 "\n" 10924 " subroutineFunction(test);\n" 10925 "\n" 10926 " gl_Position = test;\n" 10927 "}\n"; 10928} 10929 10930/** Retrieves body of a broken vertex shader. 10931 * 10932 * @return Requested string. 10933 **/ 10934std::string NegativeTest3::getVertexShaderBody() const 10935{ 10936 return "#version 400\n" 10937 "\n" 10938 "#extension GL_ARB_shader_subroutine : require\n" 10939 "\n" 10940 "subroutine void testSubroutineType(inout vec4 test);\n" 10941 "\n" 10942 "void testSubroutine1(inout vec4 test)\n" 10943 "{\n" 10944 " test += vec4(0, 1, 2, 3);\n" 10945 "}\n" 10946 "\n" 10947 "uniform testSubroutineType subroutineFunction;\n" 10948 "\n" 10949 "void main()\n" 10950 "{\n" 10951 " subroutineFunction(gl_Position);\n" 10952 "}\n"; 10953} 10954 10955/** Executes test iteration. 10956 * 10957 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10958 */ 10959tcu::TestNode::IterateResult NegativeTest3::iterate() 10960{ 10961 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 10962 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 10963 { 10964 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 10965 } 10966 10967 /* Iterate over all shader stages */ 10968 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 10969 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 10970 { 10971 executeTest(static_cast<Utils::_shader_stage>(shader_stage)); 10972 } /* for (all shader stages) */ 10973 10974 /* Done */ 10975 if (m_has_test_passed) 10976 { 10977 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 10978 } 10979 else 10980 { 10981 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 10982 } 10983 10984 return STOP; 10985} 10986 10987/** Constructor. 10988 * 10989 * @param context Rendering context. 10990 * 10991 **/ 10992NegativeTest4::NegativeTest4(deqp::Context& context) 10993 : TestCase(context, "subroutines_incompatible_with_subroutine_type", 10994 "Verifies that a compile-time error is generated when arguments and " 10995 "return type do not match beween the function and each associated " 10996 "subroutine type.") 10997 , m_has_test_passed(true) 10998 , m_so_id(0) 10999{ 11000 /* Left blank intentionally */ 11001} 11002 11003/** Deinitializes GL objects that may have been created during test 11004 * execution. 11005 **/ 11006void NegativeTest4::deinit() 11007{ 11008 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11009 11010 if (m_so_id != 0) 11011 { 11012 gl.deleteShader(m_so_id); 11013 11014 m_so_id = 0; 11015 } 11016} 11017 11018/** Retrieves body of a shader of user-specified type that should be used 11019 * for a single test iteration. The shader will define user-specified number 11020 * of subroutine types, with the last type either defining an additional argument 11021 * or using a different return type. 11022 * A subroutine (claimed compatible with *all* subroutine types) will also be 11023 * defined in the shader. 11024 * 11025 * @param shader_stage Shader stage to use for the query. 11026 * @param n_subroutine_types Overall number of subroutine types that will be 11027 * declared & used in the shader. Please see description 11028 * for more details. 11029 * 11030 * @return Requested string. 11031 **/ 11032std::string NegativeTest4::getShaderBody(const Utils::_shader_stage& shader_stage, 11033 const unsigned int& n_subroutine_types, const _test_case& test_case) const 11034{ 11035 std::stringstream result_sstream; 11036 11037 /* Form the pre-amble */ 11038 result_sstream << "#version 400\n" 11039 "\n" 11040 "#extension GL_ARB_shader_subroutine : require\n" 11041 "\n"; 11042 11043 /* Inject stage-specific code */ 11044 switch (shader_stage) 11045 { 11046 case Utils::SHADER_STAGE_GEOMETRY: 11047 { 11048 result_sstream << "layout (points) in;\n" 11049 "layout (points, max_vertices = 1) out;\n" 11050 "\n"; 11051 11052 break; 11053 } 11054 11055 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 11056 { 11057 result_sstream << "layout (vertices = 4) out;\n" 11058 "\n"; 11059 11060 break; 11061 } 11062 11063 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 11064 { 11065 result_sstream << "layout (quads) in;\n" 11066 "\n"; 11067 11068 break; 11069 } 11070 11071 default: 11072 break; 11073 } /* switch (shader_stage) */ 11074 11075 /* Insert subroutine type declarations */ 11076 for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types - 1; ++n_subroutine_type) 11077 { 11078 result_sstream << "subroutine void subroutineType" << n_subroutine_type << "(inout vec3 argument);\n"; 11079 } /* for (all subroutine types) */ 11080 11081 switch (test_case) 11082 { 11083 case TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST: 11084 { 11085 result_sstream << "subroutine void subroutineType" << (n_subroutine_types - 1) 11086 << "(inout vec3 argument, out vec4 argument2);\n"; 11087 11088 break; 11089 } 11090 11091 case TEST_CASE_INCOMPATIBLE_RETURN_TYPE: 11092 { 11093 result_sstream << "subroutine int subroutineType" << (n_subroutine_types - 1) << "(inout vec3 argument);\n"; 11094 11095 break; 11096 } 11097 11098 default: 11099 { 11100 TCU_FAIL("Unrecognized test case"); 11101 } 11102 } /* switch (test_case) */ 11103 11104 /* Insert subroutine declarations */ 11105 result_sstream << "subroutine("; 11106 11107 for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types; ++n_subroutine_type) 11108 { 11109 result_sstream << "subroutineType" << n_subroutine_type; 11110 11111 if (n_subroutine_type != (n_subroutine_types - 1)) 11112 { 11113 result_sstream << ", "; 11114 } 11115 } /* for (all subroutine types) */ 11116 11117 result_sstream << ") void function(inout vec3 argument)\n" 11118 "{\n" 11119 " argument = vec3(1, 2, 3);\n" 11120 "}\n" 11121 "\n"; 11122 11123 /* Insert remaining required stage-specific bits */ 11124 switch (shader_stage) 11125 { 11126 case Utils::SHADER_STAGE_FRAGMENT: 11127 { 11128 result_sstream << "out vec4 result;\n" 11129 "\n" 11130 "void main()\n" 11131 "{\n" 11132 " result = vec4(1, 2, 3, 4);\n" 11133 "}\n"; 11134 11135 break; 11136 } 11137 11138 case Utils::SHADER_STAGE_GEOMETRY: 11139 { 11140 result_sstream << "void main()\n" 11141 "{\n" 11142 " gl_Position = vec4(1, 2, 3, 4);\n" 11143 " EmitVertex();\n" 11144 "}\n"; 11145 11146 break; 11147 } 11148 11149 case Utils::SHADER_STAGE_TESSELLATION_CONTROL: 11150 { 11151 result_sstream << "void main()\n" 11152 "{\n" 11153 " gl_TessLevelInner[0] = 1;\n" 11154 " gl_TessLevelInner[1] = 1;\n" 11155 " gl_TessLevelOuter[0] = 1;\n" 11156 " gl_TessLevelOuter[1] = 1;\n" 11157 " gl_TessLevelOuter[2] = 1;\n" 11158 " gl_TessLevelOuter[3] = 1;\n" 11159 " gl_out[gl_InvocationID].gl_Position = vec4(2, 3, 4, 5);\n" 11160 "}\n"; 11161 11162 break; 11163 } 11164 11165 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION: 11166 case Utils::SHADER_STAGE_VERTEX: 11167 { 11168 result_sstream << "void main()\n" 11169 "{\n" 11170 " gl_Position = vec4(1, 2, 3, 4);\n" 11171 "}\n"; 11172 11173 break; 11174 } 11175 11176 default: 11177 { 11178 TCU_FAIL("Unrecognized shader stage"); 11179 } 11180 } /* switch (shader_stage) */ 11181 11182 return result_sstream.str(); 11183} 11184 11185/** Executes test iteration. 11186 * 11187 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 11188 */ 11189tcu::TestNode::IterateResult NegativeTest4::iterate() 11190{ 11191 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11192 11193 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 11194 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 11195 { 11196 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 11197 } 11198 11199 /* Iterate over all shader stages.. */ 11200 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 11201 shader_stage != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 11202 { 11203 /* For each shader stage, we will be trying to compile a number of invalid shaders. 11204 * Each shader defines N different subroutine types. (N-1) of them are compatible 11205 * with a subroutine, but exactly 1 will be mismatched. The test passes if GLSL 11206 * compiler correctly detects that all shaders we will be trying to compile are 11207 * broken. 11208 */ 11209 const glw::GLenum shader_type = Utils::getGLenumForShaderStage(static_cast<Utils::_shader_stage>(shader_stage)); 11210 11211 for (unsigned int n_subroutine_types = 1; n_subroutine_types < 6; /* arbitrary number */ 11212 ++n_subroutine_types) 11213 { 11214 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); 11215 ++test_case) 11216 { 11217 std::string body; 11218 const char* body_raw_ptr = NULL; 11219 glw::GLint compile_status = GL_FALSE; 11220 11221 body = getShaderBody(static_cast<Utils::_shader_stage>(shader_stage), n_subroutine_types, 11222 static_cast<_test_case>(test_case)); 11223 body_raw_ptr = body.c_str(); 11224 11225 /* Try to compile the shader */ 11226 m_so_id = gl.createShader(shader_type); 11227 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed"); 11228 11229 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL); 11230 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 11231 11232 gl.compileShader(m_so_id); 11233 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 11234 11235 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status); 11236 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 11237 11238 if (compile_status == GL_TRUE) 11239 { 11240 m_testCtx.getLog() << tcu::TestLog::Message << "A malformed " 11241 << Utils::getShaderStageString(static_cast<Utils::_shader_stage>(shader_stage)) 11242 << " compiled successfully " 11243 "(" 11244 << n_subroutine_types << " subroutine types " 11245 "were defined)." 11246 << tcu::TestLog::EndMessage; 11247 11248 m_has_test_passed = false; 11249 } 11250 11251 /* Release the object */ 11252 gl.deleteShader(m_so_id); 11253 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed."); 11254 } /* for (all test cases) */ 11255 } /* for (a number of different subroutine type declarations) */ 11256 } /* for (all shader stages) */ 11257 11258 /* Done */ 11259 if (m_has_test_passed) 11260 { 11261 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11262 } 11263 else 11264 { 11265 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11266 } 11267 11268 return STOP; 11269} 11270 11271/** Constructor. 11272 * 11273 * @param context Rendering context. 11274 * 11275 **/ 11276NegativeTest5::NegativeTest5(deqp::Context& context) 11277 : TestCase(context, "subroutine_uniform_wo_matching_subroutines", 11278 "Verifies that a link- or compile-time error occurs when " 11279 "trying to link a program with no subroutine for subroutine " 11280 "uniform variable.") 11281 , m_fs_id(0) 11282 , m_gs_id(0) 11283 , m_has_test_passed(true) 11284 , m_po_id(0) 11285 , m_tc_id(0) 11286 , m_te_id(0) 11287 , m_vs_id(0) 11288{ 11289 /* Left blank intentionally */ 11290} 11291 11292/** Deinitializes all GL objects that may have been created during test execution */ 11293void NegativeTest5::deinit() 11294{ 11295 deinitIteration(); 11296} 11297 11298/** Deinitializes all GL objects that may have been created during a single test 11299 * iteration. 11300 ***/ 11301void NegativeTest5::deinitIteration() 11302{ 11303 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11304 11305 if (m_fs_id != 0) 11306 { 11307 gl.deleteShader(m_fs_id); 11308 11309 m_fs_id = 0; 11310 } 11311 11312 if (m_gs_id != 0) 11313 { 11314 gl.deleteShader(m_gs_id); 11315 11316 m_gs_id = 0; 11317 } 11318 11319 if (m_po_id != 0) 11320 { 11321 gl.deleteProgram(m_po_id); 11322 11323 m_po_id = 0; 11324 } 11325 11326 if (m_tc_id != 0) 11327 { 11328 gl.deleteShader(m_tc_id); 11329 11330 m_tc_id = 0; 11331 } 11332 11333 if (m_te_id != 0) 11334 { 11335 gl.deleteShader(m_te_id); 11336 11337 m_te_id = 0; 11338 } 11339 11340 if (m_vs_id != 0) 11341 { 11342 gl.deleteShader(m_vs_id); 11343 11344 m_vs_id = 0; 11345 } 11346} 11347 11348/** Executes a single test iteration. 11349 * 11350 * If the iteration fails, m_has_test_passed will be set to false. 11351 * 11352 * @param shader_stage Shader stage, for which a subroutine uniform should be 11353 * declared in the shader without a matching subroutine. 11354 **/ 11355void NegativeTest5::executeIteration(const Utils::_shader_stage& shader_stage) 11356{ 11357 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 11358 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 11359 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 11360 std::string te_body = 11361 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 11362 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 11363 11364 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 11365 DE_NULL, /* xfb_varyings */ 11366 DE_NULL, /* n_xfb_varyings */ 11367 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 11368 { 11369 /* None of the test programs should ever build successfully */ 11370 m_testCtx.getLog() << tcu::TestLog::Message 11371 << "A program object, consisting of the following shaders, has linked" 11372 " correctly. One of the shaders defines a subroutine uniform but does " 11373 "not implement any function that matches subroutine type of the uniform." 11374 " This should have resulted in a compilation/link-time error.\n" 11375 "\n" 11376 "Vertex shader:\n" 11377 "\n" 11378 << vs_body << "\n" 11379 "Tessellation control shader:\n" 11380 "\n" 11381 << tc_body << "\n" 11382 "Tessellation evaluation shader:\n" 11383 "\n" 11384 << te_body << "\n" 11385 "Geometry shader:\n" 11386 "\n" 11387 << gs_body << "\n" 11388 "Fragment shader:\n" 11389 "\n" 11390 << fs_body << tcu::TestLog::EndMessage; 11391 11392 m_has_test_passed = false; 11393 } 11394} 11395 11396/** Retrieves fragment shader body. 11397 * 11398 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11399 * a subroutine uniform without 11400 * a matching subroutine, false otherwise. 11401 * 11402 * @return Requested string. 11403 **/ 11404std::string NegativeTest5::getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const 11405{ 11406 std::stringstream result_sstream; 11407 11408 result_sstream << "#version 400\n" 11409 "\n" 11410 "#extension GL_ARB_shader_subroutine : require\n" 11411 "\n"; 11412 11413 if (include_invalid_subroutine_uniform_declaration) 11414 { 11415 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 11416 "\n" 11417 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 11418 } 11419 11420 result_sstream << "\n" 11421 "out vec4 result;\n" 11422 "\n" 11423 "void main()\n" 11424 "{\n"; 11425 11426 if (include_invalid_subroutine_uniform_declaration) 11427 { 11428 result_sstream << " test_subroutineFS(result);\n"; 11429 } 11430 else 11431 { 11432 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 11433 } 11434 11435 result_sstream << "}\n"; 11436 11437 return result_sstream.str(); 11438} 11439 11440/** Retrieves geometry shader body. 11441 * 11442 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11443 * a subroutine uniform without 11444 * a matching subroutine, false otherwise. 11445 * 11446 * @return Requested string. 11447 **/ 11448std::string NegativeTest5::getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const 11449{ 11450 std::stringstream result_sstream; 11451 11452 result_sstream << "#version 400\n" 11453 "\n" 11454 "#extension GL_ARB_shader_subroutine : require\n" 11455 "\n" 11456 "layout (points) in;\n" 11457 "layout (points, max_vertices = 1) out;\n" 11458 "\n"; 11459 11460 if (include_invalid_subroutine_uniform_declaration) 11461 { 11462 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 11463 "\n" 11464 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 11465 } 11466 11467 result_sstream << "\n" 11468 "void main()\n" 11469 "{\n"; 11470 11471 if (include_invalid_subroutine_uniform_declaration) 11472 { 11473 result_sstream << " test_subroutineGS(gl_Position);\n"; 11474 } 11475 else 11476 { 11477 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11478 } 11479 11480 result_sstream << "EmitVertex();\n" 11481 "}\n"; 11482 11483 return result_sstream.str(); 11484} 11485 11486/** Retrieves tessellation control shader body. 11487 * 11488 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11489 * a subroutine uniform without 11490 * a matching subroutine, false otherwise. 11491 * 11492 * @return Requested string. 11493 **/ 11494std::string NegativeTest5::getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const 11495{ 11496 std::stringstream result_sstream; 11497 11498 result_sstream << "#version 400\n" 11499 "\n" 11500 "#extension GL_ARB_shader_subroutine : require\n" 11501 "\n" 11502 "layout (vertices = 4) out;\n" 11503 "\n"; 11504 11505 if (include_invalid_subroutine_uniform_declaration) 11506 { 11507 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 11508 "\n" 11509 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 11510 } 11511 11512 result_sstream << "\n" 11513 "void main()\n" 11514 "{\n"; 11515 11516 if (include_invalid_subroutine_uniform_declaration) 11517 { 11518 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 11519 } 11520 else 11521 { 11522 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 11523 } 11524 11525 result_sstream << "}\n"; 11526 11527 return result_sstream.str(); 11528} 11529 11530/** Retrieves tessellation evaluation body. 11531 * 11532 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11533 * a subroutine uniform without 11534 * a matching subroutine, false otherwise. 11535 * 11536 * @return Requested string. 11537 **/ 11538std::string NegativeTest5::getTessellationEvaluationShaderBody( 11539 bool include_invalid_subroutine_uniform_declaration) const 11540{ 11541 std::stringstream result_sstream; 11542 11543 result_sstream << "#version 400\n" 11544 "\n" 11545 "#extension GL_ARB_shader_subroutine : require\n" 11546 "\n" 11547 "layout (quads) in;\n" 11548 "\n"; 11549 11550 if (include_invalid_subroutine_uniform_declaration) 11551 { 11552 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 11553 "\n" 11554 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 11555 } 11556 11557 result_sstream << "\n" 11558 "void main()\n" 11559 "{\n"; 11560 11561 if (include_invalid_subroutine_uniform_declaration) 11562 { 11563 result_sstream << " test_subroutineTE(gl_Position);\n"; 11564 } 11565 else 11566 { 11567 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11568 } 11569 11570 result_sstream << "}\n"; 11571 11572 return result_sstream.str(); 11573} 11574 11575/** Retrieves vertex shader body. 11576 * 11577 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare 11578 * a subroutine uniform without 11579 * a matching subroutine, false otherwise. 11580 * 11581 * @return Requested string. 11582 **/ 11583std::string NegativeTest5::getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const 11584{ 11585 std::stringstream result_sstream; 11586 11587 result_sstream << "#version 400\n" 11588 "\n" 11589 "#extension GL_ARB_shader_subroutine : require\n" 11590 "\n"; 11591 11592 if (include_invalid_subroutine_uniform_declaration) 11593 { 11594 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 11595 "\n" 11596 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 11597 } 11598 11599 result_sstream << "\n" 11600 "void main()\n" 11601 "{\n"; 11602 11603 if (include_invalid_subroutine_uniform_declaration) 11604 { 11605 result_sstream << " test_subroutineVS(gl_Position);\n"; 11606 } 11607 else 11608 { 11609 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11610 } 11611 11612 result_sstream << "}\n"; 11613 11614 return result_sstream.str(); 11615} 11616 11617/** Executes test iteration. 11618 * 11619 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 11620 */ 11621tcu::TestNode::IterateResult NegativeTest5::iterate() 11622{ 11623 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 11624 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 11625 { 11626 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 11627 } 11628 11629 /* Iterate over all shader stages. Iteration-specific shader stage defines a subroutine type & 11630 * a corresponding subroutine uniform, for which no compatible subroutines are available. All 11631 * other shader stages are defined correctly. 11632 */ 11633 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 11634 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 11635 { 11636 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 11637 deinitIteration(); 11638 } /* for (all shader stages) */ 11639 11640 /* All done */ 11641 if (m_has_test_passed) 11642 { 11643 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11644 } 11645 else 11646 { 11647 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11648 } 11649 11650 return STOP; 11651} 11652 11653/** Constructor. 11654 * 11655 * @param context Rendering context. 11656 * 11657 **/ 11658NegativeTest6::NegativeTest6(deqp::Context& context) 11659 : TestCase(context, "two_duplicate_functions_one_being_a_subroutine", 11660 "Verifies that a link- or compile-time error occurs if any shader in " 11661 "a program object includes two functions with the same name and one " 11662 "of which is associated with a subroutine type.") 11663 , m_fs_id(0) 11664 , m_gs_id(0) 11665 , m_has_test_passed(true) 11666 , m_po_id(0) 11667 , m_tc_id(0) 11668 , m_te_id(0) 11669 , m_vs_id(0) 11670{ 11671 /* Left blank intentionally */ 11672} 11673 11674/** Deinitializes all GL objects that may have been created during test execution */ 11675void NegativeTest6::deinit() 11676{ 11677 deinitIteration(); 11678} 11679 11680/** Deinitializes all GL objects that may have been created during a single test 11681 * iteration. 11682 ***/ 11683void NegativeTest6::deinitIteration() 11684{ 11685 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11686 11687 if (m_fs_id != 0) 11688 { 11689 gl.deleteShader(m_fs_id); 11690 11691 m_fs_id = 0; 11692 } 11693 11694 if (m_gs_id != 0) 11695 { 11696 gl.deleteShader(m_gs_id); 11697 11698 m_gs_id = 0; 11699 } 11700 11701 if (m_po_id != 0) 11702 { 11703 gl.deleteProgram(m_po_id); 11704 11705 m_po_id = 0; 11706 } 11707 11708 if (m_tc_id != 0) 11709 { 11710 gl.deleteShader(m_tc_id); 11711 11712 m_tc_id = 0; 11713 } 11714 11715 if (m_te_id != 0) 11716 { 11717 gl.deleteShader(m_te_id); 11718 11719 m_te_id = 0; 11720 } 11721 11722 if (m_vs_id != 0) 11723 { 11724 gl.deleteShader(m_vs_id); 11725 11726 m_vs_id = 0; 11727 } 11728} 11729 11730/** Executes a single test iteration. 11731 * 11732 * If the iteration fails, m_has_test_passed will be set to false. 11733 * 11734 * @param shader_stage Shader stage, for which two duplicate functions 11735 * (one additionally marked as subroutine) should 11736 * be defined. 11737 **/ 11738void NegativeTest6::executeIteration(const Utils::_shader_stage& shader_stage) 11739{ 11740 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 11741 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 11742 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 11743 std::string te_body = 11744 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 11745 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 11746 11747 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 11748 DE_NULL, /* xfb_varyings */ 11749 DE_NULL, /* n_xfb_varyings */ 11750 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 11751 { 11752 /* None of the test programs should ever build successfully */ 11753 m_testCtx.getLog() << tcu::TestLog::Message 11754 << "A program object, consisting of the following shaders, has linked" 11755 " correctly. This is invalid, because one of the shaders defines two" 11756 " functions with the same name, with an exception that one of the" 11757 " functions is marked as a subroutine.\n" 11758 "\n" 11759 "Vertex shader:\n" 11760 "\n" 11761 << vs_body << "\n" 11762 "Tessellation control shader:\n" 11763 "\n" 11764 << tc_body << "\n" 11765 "Tessellation evaluation shader:\n" 11766 "\n" 11767 << te_body << "\n" 11768 "Geometry shader:\n" 11769 "\n" 11770 << gs_body << "\n" 11771 "Fragment shader:\n" 11772 "\n" 11773 << fs_body << tcu::TestLog::EndMessage; 11774 11775 m_has_test_passed = false; 11776 } 11777} 11778 11779/** Retrieves fragment shader body. 11780 * 11781 * @param include_invalid_declaration true if the shader should include duplicate function 11782 * declaration. 11783 * 11784 * @return Requested string. 11785 **/ 11786std::string NegativeTest6::getFragmentShaderBody(bool include_invalid_declaration) const 11787{ 11788 std::stringstream result_sstream; 11789 11790 result_sstream << "#version 400\n" 11791 "\n" 11792 "#extension GL_ARB_shader_subroutine : require\n" 11793 "\n"; 11794 11795 if (include_invalid_declaration) 11796 { 11797 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 11798 "\n" 11799 "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test)\n" 11800 "{\n" 11801 " test = vec4(1, 2, 3, 4);\n" 11802 "}\n" 11803 "\n" 11804 "void test_impl1(out vec4 test)\n" 11805 "{\n" 11806 " test = vec4(2, 3, 4, 5);\n" 11807 "}\n" 11808 "\n" 11809 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 11810 } 11811 11812 result_sstream << "\n" 11813 "out vec4 result;\n" 11814 "\n" 11815 "void main()\n" 11816 "{\n"; 11817 11818 if (include_invalid_declaration) 11819 { 11820 result_sstream << " test_subroutineFS(result);\n"; 11821 } 11822 else 11823 { 11824 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 11825 } 11826 11827 result_sstream << "}\n"; 11828 11829 return result_sstream.str(); 11830} 11831 11832/** Retrieves geometry shader body. 11833 * 11834 * @param include_invalid_declaration true if the shader should include duplicate function 11835 * declaration. 11836 * 11837 * @return Requested string. 11838 **/ 11839std::string NegativeTest6::getGeometryShaderBody(bool include_invalid_declaration) const 11840{ 11841 std::stringstream result_sstream; 11842 11843 result_sstream << "#version 400\n" 11844 "\n" 11845 "#extension GL_ARB_shader_subroutine : require\n" 11846 "\n" 11847 "layout (points) in;\n" 11848 "layout (points, max_vertices = 1) out;\n" 11849 "\n"; 11850 11851 if (include_invalid_declaration) 11852 { 11853 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 11854 "\n" 11855 "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test)\n" 11856 "{\n" 11857 " test = vec4(1, 2, 3, 4);\n" 11858 "}\n" 11859 "\n" 11860 "void test_impl1(out vec4 test)\n" 11861 "{\n" 11862 " test = vec4(2, 3, 4, 5);\n" 11863 "}\n" 11864 "\n" 11865 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 11866 } 11867 11868 result_sstream << "\n" 11869 "void main()\n" 11870 "{\n"; 11871 11872 if (include_invalid_declaration) 11873 { 11874 result_sstream << " test_subroutineGS(gl_Position);\n"; 11875 } 11876 else 11877 { 11878 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11879 } 11880 11881 result_sstream << "EmitVertex();\n" 11882 "}\n"; 11883 11884 return result_sstream.str(); 11885} 11886 11887/** Retrieves tessellation control shader body. 11888 * 11889 * @param include_invalid_declaration true if the shader should include duplicate function 11890 * declaration. 11891 * 11892 * @return Requested string. 11893 **/ 11894std::string NegativeTest6::getTessellationControlShaderBody(bool include_invalid_declaration) const 11895{ 11896 std::stringstream result_sstream; 11897 11898 result_sstream << "#version 400\n" 11899 "\n" 11900 "#extension GL_ARB_shader_subroutine : require\n" 11901 "\n" 11902 "layout (vertices = 4) out;\n" 11903 "\n"; 11904 11905 if (include_invalid_declaration) 11906 { 11907 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 11908 "\n" 11909 "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test)\n" 11910 "{\n" 11911 " test = vec4(1, 2, 3, 4);\n" 11912 "}\n" 11913 "\n" 11914 "void test_impl1(out vec4 test)\n" 11915 "{\n" 11916 " test = vec4(2, 3, 4, 5);\n" 11917 "}\n" 11918 "\n" 11919 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 11920 } 11921 11922 result_sstream << "\n" 11923 "void main()\n" 11924 "{\n"; 11925 11926 if (include_invalid_declaration) 11927 { 11928 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 11929 } 11930 else 11931 { 11932 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 11933 } 11934 11935 result_sstream << "}\n"; 11936 11937 return result_sstream.str(); 11938} 11939 11940/** Retrieves tessellation evaluation body. 11941 * 11942 * @param include_invalid_declaration true if the shader should include duplicate function 11943 * declaration. 11944 * 11945 * @return Requested string. 11946 **/ 11947std::string NegativeTest6::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const 11948{ 11949 std::stringstream result_sstream; 11950 11951 result_sstream << "#version 400\n" 11952 "\n" 11953 "#extension GL_ARB_shader_subroutine : require\n" 11954 "\n" 11955 "layout (quads) in;\n" 11956 "\n"; 11957 11958 if (include_invalid_declaration) 11959 { 11960 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 11961 "\n" 11962 "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test)\n" 11963 "{\n" 11964 " test = vec4(1, 2, 3, 4);\n" 11965 "}\n" 11966 "\n" 11967 "void test_impl1(out vec4 test)\n" 11968 "{\n" 11969 " test = vec4(2, 3, 4, 5);\n" 11970 "}\n" 11971 "\n" 11972 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 11973 } 11974 11975 result_sstream << "\n" 11976 "void main()\n" 11977 "{\n"; 11978 11979 if (include_invalid_declaration) 11980 { 11981 result_sstream << " test_subroutineTE(gl_Position);\n"; 11982 } 11983 else 11984 { 11985 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 11986 } 11987 11988 result_sstream << "}\n"; 11989 11990 return result_sstream.str(); 11991} 11992 11993/** Retrieves vertex shader body. 11994 * 11995 * @param include_invalid_declaration true if the shader should include duplicate function 11996 * declaration. 11997 * 11998 * @return Requested string. 11999 **/ 12000std::string NegativeTest6::getVertexShaderBody(bool include_invalid_declaration) const 12001{ 12002 std::stringstream result_sstream; 12003 12004 result_sstream << "#version 400\n" 12005 "\n" 12006 "#extension GL_ARB_shader_subroutine : require\n" 12007 "\n"; 12008 12009 if (include_invalid_declaration) 12010 { 12011 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 12012 "\n" 12013 "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test)\n" 12014 "{\n" 12015 " test = vec4(1, 2, 3, 4);\n" 12016 "}\n" 12017 "\n" 12018 "void test_impl1(out vec4 test)\n" 12019 "{\n" 12020 " test = vec4(2, 3, 4, 5);\n" 12021 "}\n" 12022 "\n" 12023 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 12024 } 12025 12026 result_sstream << "\n" 12027 "void main()\n" 12028 "{\n"; 12029 12030 if (include_invalid_declaration) 12031 { 12032 result_sstream << " test_subroutineVS(gl_Position);\n"; 12033 } 12034 else 12035 { 12036 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12037 } 12038 12039 result_sstream << "}\n"; 12040 12041 return result_sstream.str(); 12042} 12043 12044/** Executes test iteration. 12045 * 12046 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12047 */ 12048tcu::TestNode::IterateResult NegativeTest6::iterate() 12049{ 12050 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 12051 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 12052 { 12053 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 12054 } 12055 12056 /* Iterate over all shader stages. In each iteration, we will inject invalid 12057 * duplicate function declarations to iteration-specific shader stage. All other 12058 * shader stages will be assigned valid bodies. Test should fail if the program 12059 * links successfully. 12060 */ 12061 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 12062 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 12063 { 12064 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 12065 deinitIteration(); 12066 } /* for (all shader stages) */ 12067 12068 /* All done */ 12069 if (m_has_test_passed) 12070 { 12071 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12072 } 12073 else 12074 { 12075 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12076 } 12077 12078 return STOP; 12079} 12080 12081/** Constructor 12082 * 12083 * @param context CTS context 12084 **/ 12085NegativeTest7::NegativeTest7(deqp::Context& context) 12086 : TestCase(context, "recursion", "Verify that it is not possible to build program with recursing subroutines") 12087 , m_program_id(0) 12088 , m_vertex_shader_id(0) 12089{ 12090 /* Nothing to be done here */ 12091} 12092 12093/** Deinitializes all GL objects that may have been created during test execution 12094 * 12095 **/ 12096void NegativeTest7::deinit() 12097{ 12098 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12099 12100 if (m_program_id != 0) 12101 { 12102 gl.deleteProgram(m_program_id); 12103 12104 m_program_id = 0; 12105 } 12106 12107 if (m_vertex_shader_id != 0) 12108 { 12109 gl.deleteShader(m_vertex_shader_id); 12110 12111 m_vertex_shader_id = 0; 12112 } 12113} 12114 12115/** Executes test iteration. 12116 * 12117 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12118 **/ 12119tcu::TestNode::IterateResult NegativeTest7::iterate() 12120{ 12121 static const GLchar* vertex_shader_with_static_recursion = 12122 "#version 400\n" 12123 "\n" 12124 "#extension GL_ARB_shader_subroutine : require\n" 12125 "\n" 12126 "precision highp float;\n" 12127 "\n" 12128 "subroutine vec4 routine_type(in vec4 data, in uint control);\n" 12129 "\n" 12130 "subroutine (routine_type) vec4 power_routine(in vec4 data, in uint control)\n" 12131 "{\n" 12132 " if (0 != control)\n" 12133 " {\n" 12134 " return data * power_routine(data, control - 1);\n" 12135 " }\n" 12136 " else\n" 12137 " {\n" 12138 " return vec4(1, 1, 1, 1);\n" 12139 " }\n" 12140 "}\n" 12141 "\n" 12142 "subroutine (routine_type) vec4 select_routine(in vec4 data, in uint control)\n" 12143 "{\n" 12144 " if (0 == control)\n" 12145 " {\n" 12146 " return data.rrrr;\n" 12147 " }\n" 12148 " else if (1 == control)\n" 12149 " {\n" 12150 " return data.gggg;\n" 12151 " }\n" 12152 " else if (2 == control)\n" 12153 " {\n" 12154 " return data.bbbb;\n" 12155 " }\n" 12156 " else\n" 12157 " {\n" 12158 " return data.aaaa;\n" 12159 " }\n" 12160 "}\n" 12161 "\n" 12162 "subroutine uniform routine_type routine;\n" 12163 "\n" 12164 "uniform vec4 uni_value;\n" 12165 "uniform uint uni_control;\n" 12166 "\n" 12167 "out vec4 out_result;\n" 12168 "\n" 12169 "void main()\n" 12170 "{\n" 12171 " out_result = routine(uni_value, uni_control);\n" 12172 "}\n" 12173 "\n"; 12174 12175 static const GLchar* vertex_shader_with_dynamic_recursion = 12176 "#version 400\n" 12177 "\n" 12178 "#extension GL_ARB_shader_subroutine : require\n" 12179 "\n" 12180 "precision highp float;\n" 12181 "\n" 12182 "subroutine vec4 routine_type(in vec4 data);\n" 12183 "\n" 12184 "subroutine uniform routine_type routine;\n" 12185 "\n" 12186 "subroutine (routine_type) vec4 div_by_2(in vec4 data)\n" 12187 "{\n" 12188 " return data / 2;\n" 12189 "}\n" 12190 "\n" 12191 "subroutine (routine_type) vec4 div_routine_result_by_2(in vec4 data)\n" 12192 "{\n" 12193 " return routine(data) / 2;\n" 12194 "}\n" 12195 "\n" 12196 "uniform vec4 uni_value;\n" 12197 "\n" 12198 "out vec4 out_result;\n" 12199 "\n" 12200 "void main()\n" 12201 "{\n" 12202 " out_result = routine(uni_value);\n" 12203 "}\n" 12204 "\n"; 12205 12206 static const GLchar* vertex_shader_with_subroutine_function_recursion = 12207 "#version 400\n" 12208 "\n" 12209 "#extension GL_ARB_shader_subroutine : require\n" 12210 "\n" 12211 "precision highp float;\n" 12212 "\n" 12213 "subroutine vec4 routine_type(in vec4 data);\n" 12214 "\n" 12215 "subroutine uniform routine_type routine;\n" 12216 "\n" 12217 "vec4 function(in vec4 data)\n" 12218 "{\n" 12219 " return routine(data) + vec4(0.5, 0.5, 0.5, 0.5);\n" 12220 "}\n" 12221 "\n" 12222 "subroutine (routine_type) vec4 routine_a(in vec4 data)\n" 12223 "{\n" 12224 " return function(data) / 2;\n" 12225 "}\n" 12226 "\n" 12227 "subroutine (routine_type) vec4 routine_b(in vec4 data)\n" 12228 "{\n" 12229 " return routine_a(data) * 2;\n" 12230 "}\n" 12231 "\n" 12232 "uniform vec4 uni_value;\n" 12233 "\n" 12234 "out vec4 out_result;\n" 12235 "\n" 12236 "void main()\n" 12237 "{\n" 12238 " out_result = routine(uni_value);\n" 12239 "}\n" 12240 "\n"; 12241 12242 bool result = true; 12243 12244 if (false == test(vertex_shader_with_subroutine_function_recursion, "routine_a")) 12245 { 12246 result = false; 12247 } 12248 12249 if (false == test(vertex_shader_with_dynamic_recursion, "div_routine_result_by_2")) 12250 { 12251 result = false; 12252 } 12253 12254 if (false == test(vertex_shader_with_static_recursion, "power_routine")) 12255 { 12256 result = false; 12257 } 12258 12259 /* Set result */ 12260 if (true == result) 12261 { 12262 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12263 } 12264 else 12265 { 12266 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12267 } 12268 12269 /* Done */ 12270 return tcu::TestNode::STOP; 12271} 12272 12273/** Try to build program from vertex shader code. 12274 * 12275 * @param vertex_shader_code Source code of vertex shader 12276 * @param name_of_recursive_routine Name of subroutine that should cause link failure due to recursion 12277 * 12278 * @return true build process failed, false otherwise 12279 **/ 12280bool NegativeTest7::test(const GLchar* vertex_shader_code, const GLchar* name_of_recursive_routine) 12281{ 12282 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12283 bool result = true; 12284 static const GLchar* varying_name = "out_result"; 12285 12286 /* Try to build program */ 12287 if (true == Utils::buildProgram(gl, vertex_shader_code, "", "", "", "", &varying_name /* varying_names */, 12288 1 /* n_varyings */, &m_vertex_shader_id, 0, 0, 0, 0, &m_program_id)) 12289 { 12290 /* Success is considered an error */ 12291 12292 Utils::program program(m_context); 12293 GLuint index = 0; 12294 12295 program.build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0); 12296 12297 /* Verify that recursive subroutine is active */ 12298 try 12299 { 12300 index = program.getSubroutineIndex(name_of_recursive_routine, GL_VERTEX_SHADER); 12301 } 12302 catch (const std::exception& exc) 12303 { 12304 /* Something wrong with shader or compilation */ 12305 m_context.getTestContext().getLog() 12306 << tcu::TestLog::Message << "It is expected that subroutine: \n" 12307 << name_of_recursive_routine 12308 << " is considered active. This subroutine is potentially recursive and should cause link failure." 12309 << tcu::TestLog::EndMessage; 12310 12311 throw exc; 12312 } 12313 12314 /* Subsoutine is active, however linking should fail */ 12315 m_context.getTestContext().getLog() 12316 << tcu::TestLog::Message << "Error. Program with potentially recursive subroutine, " 12317 << name_of_recursive_routine << ", which is active, index: " << index << ", has been built successfully.\n" 12318 << vertex_shader_code << tcu::TestLog::EndMessage; 12319 12320 result = false; 12321 } 12322 12323 /* Delete program and shader */ 12324 deinit(); 12325 12326 /* Done */ 12327 return result; 12328} 12329 12330/** Constructor. 12331 * 12332 * @param context Rendering context. 12333 * 12334 **/ 12335NegativeTest8::NegativeTest8(deqp::Context& context) 12336 : TestCase(context, "subroutine_wo_body", "Verifies that a compile- or link-time error occurs if a function " 12337 "declared as a subroutine does not include a body.") 12338 , m_fs_id(0) 12339 , m_gs_id(0) 12340 , m_has_test_passed(true) 12341 , m_po_id(0) 12342 , m_tc_id(0) 12343 , m_te_id(0) 12344 , m_vs_id(0) 12345{ 12346 /* Left blank intentionally */ 12347} 12348 12349/** Deinitializes all GL objects that may have been created during test execution */ 12350void NegativeTest8::deinit() 12351{ 12352 deinitIteration(); 12353} 12354 12355/** Deinitializes all GL objects that may have been created during a single test 12356 * iteration. 12357 ***/ 12358void NegativeTest8::deinitIteration() 12359{ 12360 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12361 12362 if (m_fs_id != 0) 12363 { 12364 gl.deleteShader(m_fs_id); 12365 12366 m_fs_id = 0; 12367 } 12368 12369 if (m_gs_id != 0) 12370 { 12371 gl.deleteShader(m_gs_id); 12372 12373 m_gs_id = 0; 12374 } 12375 12376 if (m_po_id != 0) 12377 { 12378 gl.deleteProgram(m_po_id); 12379 12380 m_po_id = 0; 12381 } 12382 12383 if (m_tc_id != 0) 12384 { 12385 gl.deleteShader(m_tc_id); 12386 12387 m_tc_id = 0; 12388 } 12389 12390 if (m_te_id != 0) 12391 { 12392 gl.deleteShader(m_te_id); 12393 12394 m_te_id = 0; 12395 } 12396 12397 if (m_vs_id != 0) 12398 { 12399 gl.deleteShader(m_vs_id); 12400 12401 m_vs_id = 0; 12402 } 12403} 12404 12405/** Executes a single test iteration. 12406 * 12407 * If the iteration fails, m_has_test_passed will be set to false. 12408 * 12409 * @param shader_stage Shader stage, for which two duplicate functions 12410 * (one additionally marked as subroutine) should 12411 * be defined. 12412 **/ 12413void NegativeTest8::executeIteration(const Utils::_shader_stage& shader_stage) 12414{ 12415 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT); 12416 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY); 12417 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 12418 std::string te_body = 12419 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 12420 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX); 12421 12422 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body, 12423 DE_NULL, /* xfb_varyings */ 12424 DE_NULL, /* n_xfb_varyings */ 12425 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id)) 12426 { 12427 /* None of the test programs should ever build successfully */ 12428 m_testCtx.getLog() << tcu::TestLog::Message 12429 << "A program object consisting of FS+GS+TC+TE+VS stages has linked successfully, " 12430 "even though one of the shaders only defines a subroutine that lacks any body." 12431 "\n" 12432 "Vertex shader:\n" 12433 "\n" 12434 << vs_body << "\n" 12435 "Tessellation control shader:\n" 12436 "\n" 12437 << tc_body << "\n" 12438 "Tessellation evaluation shader:\n" 12439 "\n" 12440 << te_body << "\n" 12441 "Geometry shader:\n" 12442 "\n" 12443 << gs_body << "\n" 12444 "Fragment shader:\n" 12445 "\n" 12446 << fs_body << tcu::TestLog::EndMessage; 12447 12448 m_has_test_passed = false; 12449 } 12450} 12451 12452/** Retrieves fragment shader body. 12453 * 12454 * @param include_invalid_declaration true if a subroutine prototype should be included in 12455 * the shader, false to skip it. 12456 * 12457 * @return Requested string. 12458 **/ 12459std::string NegativeTest8::getFragmentShaderBody(bool include_invalid_declaration) const 12460{ 12461 std::stringstream result_sstream; 12462 12463 result_sstream << "#version 400\n" 12464 "\n" 12465 "#extension GL_ARB_shader_subroutine : require\n" 12466 "\n"; 12467 12468 if (include_invalid_declaration) 12469 { 12470 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n" 12471 "\n" 12472 "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test);\n" 12473 "\n" 12474 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n"; 12475 } 12476 12477 result_sstream << "\n" 12478 "out vec4 result;\n" 12479 "\n" 12480 "void main()\n" 12481 "{\n"; 12482 12483 if (include_invalid_declaration) 12484 { 12485 result_sstream << " test_subroutineFS(result);\n"; 12486 } 12487 else 12488 { 12489 result_sstream << " result = vec4(0, 1, 2, 3);\n"; 12490 } 12491 12492 result_sstream << "}\n"; 12493 12494 return result_sstream.str(); 12495} 12496 12497/** Retrieves geometry shader body. 12498 * 12499 * @param include_invalid_declaration true if a subroutine prototype should be included in 12500 * the shader, false to skip it. 12501 * 12502 * @return Requested string. 12503 **/ 12504std::string NegativeTest8::getGeometryShaderBody(bool include_invalid_declaration) const 12505{ 12506 std::stringstream result_sstream; 12507 12508 result_sstream << "#version 400\n" 12509 "\n" 12510 "#extension GL_ARB_shader_subroutine : require\n" 12511 "\n" 12512 "layout (points) in;\n" 12513 "layout (points, max_vertices = 1) out;\n" 12514 "\n"; 12515 12516 if (include_invalid_declaration) 12517 { 12518 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n" 12519 "\n" 12520 "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test);\n" 12521 "\n" 12522 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n"; 12523 } 12524 12525 result_sstream << "\n" 12526 "void main()\n" 12527 "{\n"; 12528 12529 if (include_invalid_declaration) 12530 { 12531 result_sstream << " test_subroutineGS(gl_Position);\n"; 12532 } 12533 else 12534 { 12535 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12536 } 12537 12538 result_sstream << "EmitVertex();\n" 12539 "}\n"; 12540 12541 return result_sstream.str(); 12542} 12543 12544/** Retrieves tessellation control shader body. 12545 * 12546 * @param include_invalid_declaration true if a subroutine prototype should be included in 12547 * the shader, false to skip it. 12548 * 12549 * @return Requested string. 12550 **/ 12551std::string NegativeTest8::getTessellationControlShaderBody(bool include_invalid_declaration) const 12552{ 12553 std::stringstream result_sstream; 12554 12555 result_sstream << "#version 400\n" 12556 "\n" 12557 "#extension GL_ARB_shader_subroutine : require\n" 12558 "\n" 12559 "layout (vertices = 4) out;\n" 12560 "\n"; 12561 12562 if (include_invalid_declaration) 12563 { 12564 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n" 12565 "\n" 12566 "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test);\n" 12567 "\n" 12568 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n"; 12569 } 12570 12571 result_sstream << "\n" 12572 "void main()\n" 12573 "{\n"; 12574 12575 if (include_invalid_declaration) 12576 { 12577 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n"; 12578 } 12579 else 12580 { 12581 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n"; 12582 } 12583 12584 result_sstream << "}\n"; 12585 12586 return result_sstream.str(); 12587} 12588 12589/** Retrieves tessellation evaluation body. 12590 * 12591 * @param include_invalid_declaration true if a subroutine prototype should be included in 12592 * the shader, false to skip it. 12593 * 12594 * @return Requested string. 12595 **/ 12596std::string NegativeTest8::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const 12597{ 12598 std::stringstream result_sstream; 12599 12600 result_sstream << "#version 400\n" 12601 "\n" 12602 "#extension GL_ARB_shader_subroutine : require\n" 12603 "\n" 12604 "layout (quads) in;\n" 12605 "\n"; 12606 12607 if (include_invalid_declaration) 12608 { 12609 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n" 12610 "\n" 12611 "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test);\n" 12612 "\n" 12613 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n"; 12614 } 12615 12616 result_sstream << "\n" 12617 "void main()\n" 12618 "{\n"; 12619 12620 if (include_invalid_declaration) 12621 { 12622 result_sstream << " test_subroutineTE(gl_Position);\n"; 12623 } 12624 else 12625 { 12626 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12627 } 12628 12629 result_sstream << "}\n"; 12630 12631 return result_sstream.str(); 12632} 12633 12634/** Retrieves vertex shader body. 12635 * 12636 * @param include_invalid_declaration true if a subroutine prototype should be included in 12637 * the shader, false to skip it. 12638 * 12639 * @return Requested string. 12640 **/ 12641std::string NegativeTest8::getVertexShaderBody(bool include_invalid_declaration) const 12642{ 12643 std::stringstream result_sstream; 12644 12645 result_sstream << "#version 400\n" 12646 "\n" 12647 "#extension GL_ARB_shader_subroutine : require\n" 12648 "\n"; 12649 12650 if (include_invalid_declaration) 12651 { 12652 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n" 12653 "\n" 12654 "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test);\n" 12655 "\n" 12656 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n"; 12657 } 12658 12659 result_sstream << "\n" 12660 "void main()\n" 12661 "{\n"; 12662 12663 if (include_invalid_declaration) 12664 { 12665 result_sstream << " test_subroutineVS(gl_Position);\n"; 12666 } 12667 else 12668 { 12669 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n"; 12670 } 12671 12672 result_sstream << "}\n"; 12673 12674 return result_sstream.str(); 12675} 12676 12677/** Executes test iteration. 12678 * 12679 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12680 */ 12681tcu::TestNode::IterateResult NegativeTest8::iterate() 12682{ 12683 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 12684 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 12685 { 12686 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 12687 } 12688 12689 /* Iterate over all shader stages. For each iteration, iteration-specific shader stage 12690 * will feature an invalid subroutine definition. Other shader stages will be assigned 12691 * valid bodies. The test fails if a program built of such shaders links successfully. 12692 */ 12693 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST); 12694 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage) 12695 { 12696 executeIteration(static_cast<Utils::_shader_stage>(shader_stage)); 12697 deinitIteration(); 12698 } /* for (all shader stages) */ 12699 12700 /* All done */ 12701 if (m_has_test_passed) 12702 { 12703 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12704 } 12705 else 12706 { 12707 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12708 } 12709 12710 return STOP; 12711} 12712 12713/** Constructor. 12714 * 12715 * @param context Rendering context. 12716 **/ 12717NegativeTest9::NegativeTest9(deqp::Context& context) 12718 : TestCase(context, "subroutines_cannot_be_assigned_float_int_values_or_be_compared", 12719 "Make sure it is not possible to assign float/int to subroutine " 12720 "uniform and that subroutine uniform values cannot be compared.") 12721 , m_has_test_passed(true) 12722 , m_po_id(0) 12723 , m_vs_id(0) 12724{ 12725 /* Left blank intentionally */ 12726} 12727 12728/** Deinitializes any GL objects that may have been created during 12729 * test execution. 12730 **/ 12731void NegativeTest9::deinit() 12732{ 12733 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12734 12735 if (m_po_id != 0) 12736 { 12737 gl.deleteProgram(m_po_id); 12738 12739 m_po_id = 0; 12740 } 12741 12742 if (m_vs_id != 0) 12743 { 12744 gl.deleteShader(m_vs_id); 12745 12746 m_vs_id = 0; 12747 } 12748} 12749 12750/** Returns a literal corresponding to user-specified test case enum. 12751 * 12752 * @param test_case As per description. 12753 * 12754 * @return Requested string. 12755 **/ 12756std::string NegativeTest9::getTestCaseString(const _test_case& test_case) 12757{ 12758 std::string result = "?"; 12759 12760 switch (test_case) 12761 { 12762 case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 12763 result = "TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT"; 12764 break; 12765 case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 12766 result = "TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT"; 12767 break; 12768 case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON: 12769 result = "TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON"; 12770 break; 12771 default: 12772 break; 12773 } 12774 12775 return result; 12776} 12777 12778/** Retrieves vertex shader body for user-specified test case. 12779 * 12780 * @param test_case As per description. 12781 * 12782 * @return Requested string. 12783 **/ 12784std::string NegativeTest9::getVertexShader(const _test_case& test_case) 12785{ 12786 std::stringstream result_sstream; 12787 12788 /* Form pre-amble */ 12789 result_sstream << "#version 400\n" 12790 "\n" 12791 "#extension GL_ARB_shader_subroutine : require\n" 12792 "\n" 12793 /* Define a subroutine */ 12794 "subroutine void subroutineType(inout vec4 test);\n" 12795 "\n" 12796 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 12797 "{\n" 12798 " test += vec4(0, 1, 2, 3);\n" 12799 "}\n" 12800 "\n" 12801 "subroutine uniform subroutineType function;\n" 12802 "\n"; 12803 12804 /* Include case-specific implementation */ 12805 switch (test_case) 12806 { 12807 case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 12808 { 12809 result_sstream << "void main()\n" 12810 "{\n" 12811 " function = 1.0f;\n" 12812 "\n" 12813 " function(gl_Position);\n" 12814 "}\n"; 12815 12816 break; 12817 } 12818 12819 case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT: 12820 { 12821 result_sstream << "void main()\n" 12822 "{\n" 12823 " function = 1;\n" 12824 "\n" 12825 " function(gl_Position);\n" 12826 "}\n"; 12827 12828 break; 12829 } 12830 12831 case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON: 12832 { 12833 result_sstream << "subroutine uniform subroutineType function2;\n" 12834 "\n" 12835 "void main()\n" 12836 "{\n" 12837 " if (function == function2)\n" 12838 " {\n" 12839 " function(gl_Position);\n" 12840 " }\n" 12841 " else\n" 12842 " {\n" 12843 " function2(gl_Position);\n" 12844 " }\n" 12845 "}\n"; 12846 12847 break; 12848 } 12849 12850 default: 12851 break; 12852 } /* switch (test_case) */ 12853 12854 /* Done */ 12855 return result_sstream.str(); 12856} 12857 12858/** Executes test iteration. 12859 * 12860 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 12861 */ 12862tcu::TestNode::IterateResult NegativeTest9::iterate() 12863{ 12864 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12865 12866 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 12867 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 12868 { 12869 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 12870 } 12871 12872 /* Iterate over all test cases */ 12873 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 12874 { 12875 /* Try to build a program object using invalid vertex shader, specific to the 12876 * iteration we're currently in */ 12877 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 12878 12879 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 12880 "", /* te_body */ 12881 "", /* gs_body */ 12882 "", /* fs_body */ 12883 DE_NULL, /* xfb_varyings */ 12884 0, /* n_xfb_varyings */ 12885 &m_vs_id, DE_NULL, /* out_tc_id */ 12886 DE_NULL, /* out_te_id */ 12887 DE_NULL, /* out_gs_id */ 12888 DE_NULL, /* out_fs_id */ 12889 &m_po_id)) 12890 { 12891 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 12892 << getTestCaseString(static_cast<_test_case>(test_case)) 12893 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 12894 12895 m_has_test_passed = false; 12896 } 12897 12898 /* Delete any objects that may have been created */ 12899 deinit(); 12900 } /* for (all test cases) */ 12901 12902 /** All done */ 12903 if (m_has_test_passed) 12904 { 12905 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 12906 } 12907 else 12908 { 12909 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 12910 } 12911 12912 return STOP; 12913} 12914 12915/** Constructor. 12916 * 12917 * @param context Rendering context. 12918 **/ 12919NegativeTest10::NegativeTest10(deqp::Context& context) 12920 : TestCase(context, "function_overloading_forbidden_for_subroutines", 12921 "Check that an overloaded function cannot be declared with subroutine and " 12922 "a program will fail to compile or link if any shader or stage contains" 12923 " two or more functions with the same name if the name is associated with" 12924 " a subroutine type.") 12925 , m_has_test_passed(true) 12926 , m_fs_id(0) 12927 , m_gs_id(0) 12928 , m_po_id(0) 12929 , m_tc_id(0) 12930 , m_te_id(0) 12931 , m_vs_id(0) 12932{ 12933 /* Left blank intentionally */ 12934} 12935 12936/** Deinitializes any GL objects that may have been created during 12937 * test execution. 12938 **/ 12939void NegativeTest10::deinit() 12940{ 12941 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 12942 12943 if (m_fs_id != 0) 12944 { 12945 gl.deleteShader(m_fs_id); 12946 12947 m_fs_id = 0; 12948 } 12949 12950 if (m_gs_id != 0) 12951 { 12952 gl.deleteShader(m_gs_id); 12953 12954 m_gs_id = 0; 12955 } 12956 12957 if (m_po_id != 0) 12958 { 12959 gl.deleteProgram(m_po_id); 12960 12961 m_po_id = 0; 12962 } 12963 12964 if (m_tc_id != 0) 12965 { 12966 gl.deleteShader(m_tc_id); 12967 12968 m_tc_id = 0; 12969 } 12970 12971 if (m_te_id != 0) 12972 { 12973 gl.deleteShader(m_te_id); 12974 12975 m_te_id = 0; 12976 } 12977 12978 if (m_vs_id != 0) 12979 { 12980 gl.deleteShader(m_vs_id); 12981 12982 m_vs_id = 0; 12983 } 12984} 12985 12986/** Retrieves fragment shader that should be used for the purpose of the test. 12987 * An overloaded version of a subroutine function is inserted if 12988 * @param include_duplicate_function flag is set to true. 12989 * 12990 * @param include_duplicate_function As per description. 12991 * 12992 * @return Requested string. 12993 **/ 12994std::string NegativeTest10::getFragmentShader(bool include_duplicate_function) 12995{ 12996 std::stringstream result_sstream; 12997 12998 result_sstream << "#version 400\n" 12999 "\n" 13000 "#extension GL_ARB_shader_subroutine : require\n" 13001 "\n" 13002 "subroutine void subroutineType(inout vec4 test);\n" 13003 "\n" 13004 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13005 "{\n" 13006 " test = vec4(2, 3, 4, 5);\n" 13007 "}\n" 13008 "\n" 13009 "subroutine uniform subroutineType function;\n" 13010 "out vec4 result;\n" 13011 "\n"; 13012 13013 if (include_duplicate_function) 13014 { 13015 result_sstream << "void test_function(inout vec4 test)\n" 13016 "{\n" 13017 " test = vec4(3, 4, 5, 6);\n" 13018 "}\n" 13019 "\n"; 13020 } 13021 13022 result_sstream << "void main()\n" 13023 "{\n" 13024 " test_function(result);\n" 13025 "}\n"; 13026 13027 return result_sstream.str(); 13028} 13029 13030/** Retrieves geometry shader that should be used for the purpose of the test. 13031 * An overloaded version of a subroutine function is inserted if 13032 * @param include_duplicate_function flag is set to true. 13033 * 13034 * @param include_duplicate_function As per description. 13035 * 13036 * @return Requested string. 13037 **/ 13038std::string NegativeTest10::getGeometryShader(bool include_duplicate_function) 13039{ 13040 std::stringstream result_sstream; 13041 13042 result_sstream << "#version 400\n" 13043 "\n" 13044 "#extension GL_ARB_shader_subroutine : require\n" 13045 "\n" 13046 "layout (triangles) in;\n" 13047 "layout (triangle_strip, max_vertices = 4) out;\n" 13048 "\n" 13049 "subroutine void subroutineType(inout vec4 test);\n" 13050 "\n" 13051 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13052 "{\n" 13053 " test = vec4(2, 3, 4, 5);\n" 13054 "}\n" 13055 "\n" 13056 "subroutine uniform subroutineType function;\n" 13057 "\n"; 13058 13059 if (include_duplicate_function) 13060 { 13061 result_sstream << "void test_function(inout vec4 test)\n" 13062 "{\n" 13063 " test = vec4(3, 4, 5, 6);\n" 13064 "}\n" 13065 "\n"; 13066 } 13067 13068 result_sstream << "void main()\n" 13069 "{\n" 13070 " function(gl_Position);\n" 13071 " EmitVertex();\n" 13072 " EndPrimitive();\n" 13073 "}\n"; 13074 13075 return result_sstream.str(); 13076} 13077 13078/** Retrieves tess control shader that should be used for the purpose of the test. 13079 * An overloaded version of a subroutine function is inserted if 13080 * @param include_duplicate_function flag is set to true. 13081 * 13082 * @param include_duplicate_function As per description. 13083 * 13084 * @return Requested string. 13085 **/ 13086std::string NegativeTest10::getTessellationControlShader(bool include_duplicate_function) 13087{ 13088 std::stringstream result_sstream; 13089 13090 result_sstream << "#version 400\n" 13091 "\n" 13092 "#extension GL_ARB_shader_subroutine : require\n" 13093 "\n" 13094 "layout (vertices = 4) out;\n" 13095 "\n" 13096 "subroutine void subroutineType(inout vec4 test);\n" 13097 "\n" 13098 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13099 "{\n" 13100 " test = vec4(2, 3, 4, 5);\n" 13101 "}\n" 13102 "\n" 13103 "subroutine uniform subroutineType function;\n" 13104 "\n"; 13105 13106 if (include_duplicate_function) 13107 { 13108 result_sstream << "void test_function(inout vec4 test)\n" 13109 "{\n" 13110 " test = vec4(3, 4, 5, 6);\n" 13111 "}\n" 13112 "\n"; 13113 } 13114 13115 result_sstream << "void main()\n" 13116 "{\n" 13117 " vec4 temp;\n" 13118 "\n" 13119 " function(temp);\n" 13120 "\n" 13121 " gl_out[gl_InvocationID].gl_Position = temp;\n" 13122 " gl_TessLevelInner[0] = temp.x;\n" 13123 " gl_TessLevelInner[1] = temp.y;\n" 13124 " gl_TessLevelOuter[0] = temp.z;\n" 13125 " gl_TessLevelOuter[1] = temp.w;\n" 13126 " gl_TessLevelOuter[2] = temp.x;\n" 13127 " gl_TessLevelOuter[3] = temp.y;\n" 13128 "}\n"; 13129 13130 return result_sstream.str(); 13131} 13132 13133/** Retrieves tess evaluation shader that should be used for the purpose of the test. 13134 * An overloaded version of a subroutine function is inserted if 13135 * @param include_duplicate_function flag is set to true. 13136 * 13137 * @param include_duplicate_function As per description. 13138 * 13139 * @return Requested string. 13140 **/ 13141std::string NegativeTest10::getTessellationEvaluationShader(bool include_duplicate_function) 13142{ 13143 std::stringstream result_sstream; 13144 13145 result_sstream << "#version 400\n" 13146 "\n" 13147 "#extension GL_ARB_shader_subroutine : require\n" 13148 "\n" 13149 "layout (quads) in;\n" 13150 "\n" 13151 "subroutine void subroutineType(inout vec4 test);\n" 13152 "\n" 13153 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13154 "{\n" 13155 " test = vec4(2, 3, 4, 5);\n" 13156 "}\n" 13157 "\n" 13158 "subroutine uniform subroutineType function;\n" 13159 "\n"; 13160 13161 if (include_duplicate_function) 13162 { 13163 result_sstream << "void test_function(inout vec4 test)\n" 13164 "{\n" 13165 " test = vec4(3, 4, 5, 6);\n" 13166 "}\n" 13167 "\n"; 13168 } 13169 13170 result_sstream << "void main()\n" 13171 "{\n" 13172 " vec4 temp;\n" 13173 "\n" 13174 " function(temp);\n" 13175 "\n" 13176 " gl_Position = temp;\n" 13177 "}\n"; 13178 13179 return result_sstream.str(); 13180} 13181 13182/** Retrieves vertex shader that should be used for the purpose of the test. 13183 * An overloaded version of a subroutine function is inserted if 13184 * @param include_duplicate_function flag is set to true. 13185 * 13186 * @param include_duplicate_function As per description. 13187 * 13188 * @return Requested string. 13189 **/ 13190std::string NegativeTest10::getVertexShader(bool include_duplicate_function) 13191{ 13192 std::stringstream result_sstream; 13193 13194 result_sstream << "#version 400\n" 13195 "\n" 13196 "#extension GL_ARB_shader_subroutine : require\n" 13197 "\n" 13198 "subroutine void subroutineType(inout vec4 test);\n" 13199 "\n" 13200 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13201 "{\n" 13202 " test = vec4(2, 3, 4, 5);\n" 13203 "}\n" 13204 "\n" 13205 "subroutine uniform subroutineType function;\n" 13206 "\n"; 13207 13208 if (include_duplicate_function) 13209 { 13210 result_sstream << "void test_function(inout vec4 test)\n" 13211 "{\n" 13212 " test = vec4(3, 4, 5, 6);\n" 13213 "}\n" 13214 "\n"; 13215 } 13216 13217 result_sstream << "void main()\n" 13218 "{\n" 13219 " function(gl_Position);\n" 13220 "}\n"; 13221 13222 return result_sstream.str(); 13223} 13224 13225/** Fills m_test_cases field with test case descriptors */ 13226void NegativeTest10::initTestCases() 13227{ 13228 /* For each test case, only one shader stage should define a function that 13229 * has already been defined as a subroutine. */ 13230 for (int offending_shader_stage_it = static_cast<int>(Utils::SHADER_STAGE_FIRST); 13231 offending_shader_stage_it != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++offending_shader_stage_it) 13232 { 13233 Utils::_shader_stage offending_shader_stage = static_cast<Utils::_shader_stage>(offending_shader_stage_it); 13234 /* Form the test case descriptor */ 13235 std::stringstream name_sstream; 13236 _test_case test_case; 13237 13238 name_sstream << "Broken shader stage:" << Utils::getShaderStageString(offending_shader_stage); 13239 13240 test_case.fs_body = getFragmentShader(offending_shader_stage == Utils::SHADER_STAGE_FRAGMENT); 13241 test_case.gs_body = getGeometryShader(offending_shader_stage == Utils::SHADER_STAGE_GEOMETRY); 13242 test_case.name = name_sstream.str(); 13243 test_case.tc_body = 13244 getTessellationControlShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL); 13245 test_case.te_body = 13246 getTessellationEvaluationShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION); 13247 test_case.vs_body = getVertexShader(offending_shader_stage == Utils::SHADER_STAGE_VERTEX); 13248 13249 m_test_cases.push_back(test_case); 13250 } 13251} 13252 13253/** Executes test iteration. 13254 * 13255 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13256 */ 13257tcu::TestNode::IterateResult NegativeTest10::iterate() 13258{ 13259 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13260 13261 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13262 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13263 { 13264 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 13265 } 13266 13267 /* Form test cases */ 13268 initTestCases(); 13269 13270 /* Iterate over all test cases */ 13271 for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end(); 13272 ++test_case_iterator) 13273 { 13274 const _test_case& test_case = *test_case_iterator; 13275 13276 /* Try to build the program object */ 13277 if (ShaderSubroutine::Utils::buildProgram(gl, test_case.vs_body, test_case.tc_body, test_case.te_body, 13278 test_case.gs_body, test_case.fs_body, DE_NULL, /* xfb_varyings */ 13279 0, /* n_xfb_varyings */ 13280 &m_vs_id, (test_case.tc_body.length() > 0) ? &m_tc_id : DE_NULL, 13281 (test_case.te_body.length() > 0) ? &m_te_id : DE_NULL, 13282 (test_case.gs_body.length() > 0) ? &m_gs_id : DE_NULL, 13283 (test_case.fs_body.length() > 0) ? &m_fs_id : DE_NULL, &m_po_id)) 13284 { 13285 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 13286 << test_case.name << "] test case, even though it was invalid." 13287 << tcu::TestLog::EndMessage; 13288 13289 m_has_test_passed = false; 13290 } 13291 13292 /* Delete any objects that may have been created */ 13293 deinit(); 13294 } /* for (all test cases) */ 13295 13296 /** All done */ 13297 if (m_has_test_passed) 13298 { 13299 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13300 } 13301 else 13302 { 13303 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13304 } 13305 13306 return STOP; 13307} 13308 13309/** Constructor. 13310 * 13311 * @param context Rendering context. 13312 **/ 13313NegativeTest11::NegativeTest11(deqp::Context& context) 13314 : TestCase(context, "subroutine_uniforms_used_for_sampling_atomic_image_functions", 13315 "Tries to use subroutine uniforms in invalid way in sampling, " 13316 "atomic and image functions. Verifies that compile- or link-time " 13317 "error occurs.") 13318 , m_has_test_passed(true) 13319 , m_po_id(0) 13320 , m_vs_id(0) 13321{ 13322 /* Left blank intentionally */ 13323} 13324 13325/** Deinitializes any GL objects that may have been created during 13326 * test execution. 13327 **/ 13328void NegativeTest11::deinit() 13329{ 13330 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13331 13332 if (m_po_id != 0) 13333 { 13334 gl.deleteProgram(m_po_id); 13335 13336 m_po_id = 0; 13337 } 13338 13339 if (m_vs_id != 0) 13340 { 13341 gl.deleteShader(m_vs_id); 13342 13343 m_vs_id = 0; 13344 } 13345} 13346 13347/** Returns a literal corresponding to user-specified test case enum. 13348 * 13349 * @param test_case As per description. 13350 * 13351 * @return Requested string. 13352 **/ 13353std::string NegativeTest11::getTestCaseString(const _test_case& test_case) 13354{ 13355 std::string result = "?"; 13356 13357 switch (test_case) 13358 { 13359 case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT: 13360 result = "TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT"; 13361 break; 13362 case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT: 13363 result = "TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT"; 13364 break; 13365 case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT: 13366 result = "TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT"; 13367 break; 13368 default: 13369 break; 13370 } 13371 13372 return result; 13373} 13374 13375/** Retrieves vertex shader body for user-specified test case. 13376 * 13377 * @param test_case As per description. 13378 * 13379 * @return Requested string. 13380 **/ 13381std::string NegativeTest11::getVertexShader(const _test_case& test_case) 13382{ 13383 std::stringstream result_sstream; 13384 13385 /* Form pre-amble */ 13386 result_sstream << "#version 400\n" 13387 "\n" 13388 "#extension GL_ARB_shader_subroutine : require\n"; 13389 13390 if (test_case == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT) 13391 { 13392 result_sstream << "#extension GL_ARB_shader_atomic_counters : require\n"; 13393 } 13394 13395 result_sstream << "\n" 13396 /* Define a subroutine */ 13397 "subroutine void subroutineType(inout vec4 test);\n" 13398 "\n" 13399 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13400 "{\n" 13401 " test += vec4(0, 1, 2, 3);\n" 13402 "}\n" 13403 "\n" 13404 "subroutine uniform subroutineType function;\n" 13405 "\n" 13406 13407 /* Define main() body */ 13408 "void main()\n" 13409 "{\n"; 13410 13411 /* Implement case-specific behavior */ 13412 switch (test_case) 13413 { 13414 case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT: 13415 { 13416 result_sstream << "if (atomicCounter(function) > 2)\n" 13417 "{\n" 13418 " gl_Position = vec4(1);\n" 13419 "}\n"; 13420 13421 break; 13422 } 13423 13424 case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT: 13425 { 13426 result_sstream << "imageStore(function, vec2(0.0, 1.0), vec4(1.0) );\n"; 13427 13428 break; 13429 } 13430 13431 case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT: 13432 { 13433 result_sstream << "gl_Position = texture(function, vec2(1.0) );\n"; 13434 13435 break; 13436 } 13437 13438 default: 13439 break; 13440 } /* switch (test_case) */ 13441 13442 /* Close main() body */ 13443 result_sstream << "}\n"; 13444 13445 /* Done */ 13446 return result_sstream.str(); 13447} 13448 13449/** Executes test iteration. 13450 * 13451 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13452 */ 13453tcu::TestNode::IterateResult NegativeTest11::iterate() 13454{ 13455 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13456 13457 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13458 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13459 { 13460 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 13461 } 13462 13463 /* Iterate over all test cases */ 13464 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 13465 { 13466 if (static_cast<_test_case>(test_case) == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT && 13467 !m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters")) 13468 { 13469 /* This iteration requires atomic counter support that this GL implementation 13470 * is not capable of. Skip the iteration 13471 */ 13472 continue; 13473 } 13474 13475 /* Try to build a program object using invalid vertex shader, specific to the 13476 * iteration we're currently in */ 13477 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 13478 13479 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 13480 "", /* te_body */ 13481 "", /* gs_body */ 13482 "", /* fs_body */ 13483 DE_NULL, /* xfb_varyings */ 13484 0, /* n_xfb_varyings */ 13485 &m_vs_id, DE_NULL, /* out_tc_id */ 13486 DE_NULL, /* out_te_id */ 13487 DE_NULL, /* out_gs_id */ 13488 DE_NULL, /* out_fs_id */ 13489 &m_po_id)) 13490 { 13491 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 13492 << getTestCaseString(static_cast<_test_case>(test_case)) 13493 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 13494 13495 m_has_test_passed = false; 13496 } 13497 13498 /* Delete any objects that may have been created */ 13499 deinit(); 13500 } /* for (all test cases) */ 13501 13502 /** All done */ 13503 if (m_has_test_passed) 13504 { 13505 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13506 } 13507 else 13508 { 13509 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13510 } 13511 13512 return STOP; 13513} 13514 13515/** Constructor. 13516 * 13517 * @param context Rendering context. 13518 **/ 13519NegativeTest12::NegativeTest12(deqp::Context& context) 13520 : TestCase(context, "subroutines_not_allowed_as_variables_constructors_and_argument_or_return_types", 13521 "Verifies that it is not allowed to use subroutine type for " 13522 "local/global variables, constructors or argument/return type.") 13523 , m_has_test_passed(true) 13524 , m_po_id(0) 13525 , m_vs_id(0) 13526{ 13527 /* Left blank intentionally */ 13528} 13529 13530/** Deinitializes any GL objects that may have been created during 13531 * test execution. 13532 **/ 13533void NegativeTest12::deinit() 13534{ 13535 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13536 13537 if (m_po_id != 0) 13538 { 13539 gl.deleteProgram(m_po_id); 13540 13541 m_po_id = 0; 13542 } 13543 13544 if (m_vs_id != 0) 13545 { 13546 gl.deleteShader(m_vs_id); 13547 13548 m_vs_id = 0; 13549 } 13550} 13551 13552/** Returns a literal corresponding to user-specified test case enum. 13553 * 13554 * @param test_case As per description. 13555 * 13556 * @return Requested string. 13557 **/ 13558std::string NegativeTest12::getTestCaseString(const _test_case& test_case) 13559{ 13560 std::string result = "?"; 13561 13562 switch (test_case) 13563 { 13564 case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE: 13565 result = "TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE"; 13566 break; 13567 case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE: 13568 result = "TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE"; 13569 break; 13570 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR: 13571 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR"; 13572 break; 13573 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT: 13574 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT"; 13575 break; 13576 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE: 13577 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE"; 13578 break; 13579 default: 13580 break; 13581 } 13582 13583 return result; 13584} 13585 13586/** Retrieves vertex shader body for user-specified test case. 13587 * 13588 * @param test_case As per description. 13589 * 13590 * @return Requested string. 13591 **/ 13592std::string NegativeTest12::getVertexShader(const _test_case& test_case) 13593{ 13594 std::stringstream result_sstream; 13595 13596 /* Form pre-amble */ 13597 result_sstream << "#version 400\n" 13598 "\n" 13599 "#extension GL_ARB_shader_subroutine : require\n" 13600 "\n" 13601 /* Define a subroutine */ 13602 "subroutine void subroutineType(inout vec4 test);\n" 13603 "\n" 13604 "subroutine(subroutineType) void test_function(inout vec4 test)\n" 13605 "{\n" 13606 " test += vec4(0, 1, 2, 3);\n" 13607 "}\n" 13608 "\n" 13609 "subroutine uniform subroutineType function;\n" 13610 "\n"; 13611 13612 /* Include case-specific implementation */ 13613 switch (test_case) 13614 { 13615 case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE: 13616 { 13617 result_sstream << "void main()\n" 13618 "{\n" 13619 " subroutine subroutineType function2;\n" 13620 " vec4 result;\n" 13621 "\n" 13622 " function2(result);\n" 13623 " gl_Position = result;\n" 13624 "}\n"; 13625 13626 break; 13627 } 13628 13629 case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE: 13630 { 13631 result_sstream << "subroutine subroutineType function2;\n" 13632 "\n" 13633 "void main()\n" 13634 "{\n" 13635 " vec4 result;\n" 13636 "\n" 13637 " function2(result);\n" 13638 " gl_Position = result;\n" 13639 "}\n"; 13640 13641 break; 13642 } 13643 13644 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR: 13645 { 13646 result_sstream << "void main()\n" 13647 "{\n" 13648 " subroutineType(function);\n" 13649 "}\n"; 13650 13651 break; 13652 } 13653 13654 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT: 13655 { 13656 result_sstream << "vec4 test_function(subroutineType argument)\n" 13657 "{\n" 13658 " vec4 result = vec4(1, 2, 3, 4);\n" 13659 "\n" 13660 " argument(result);\n" 13661 "\n" 13662 " return result;\n" 13663 "}\n" 13664 "\n" 13665 "void main()\n" 13666 "{\n" 13667 " test_function(function);\n" 13668 "}\n"; 13669 13670 break; 13671 } 13672 13673 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE: 13674 { 13675 result_sstream << "subroutineType test_function()\n" 13676 "{\n" 13677 " return function;\n" 13678 "}\n" 13679 "\n" 13680 "void main()\n" 13681 "{\n" 13682 " test_function()(gl_Position);\n" 13683 "}\n"; 13684 13685 break; 13686 } 13687 13688 default: 13689 break; 13690 } /* switch (test_case) */ 13691 13692 /* Done */ 13693 return result_sstream.str(); 13694} 13695 13696/** Executes test iteration. 13697 * 13698 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 13699 */ 13700tcu::TestNode::IterateResult NegativeTest12::iterate() 13701{ 13702 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13703 13704 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */ 13705 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine")) 13706 { 13707 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported."); 13708 } 13709 13710 /* Iterate over all test cases */ 13711 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case) 13712 { 13713 /* Try to build a program object using invalid vertex shader, specific to the 13714 * iteration we're currently in */ 13715 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case)); 13716 13717 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */ 13718 "", /* te_body */ 13719 "", /* gs_body */ 13720 "", /* fs_body */ 13721 DE_NULL, /* xfb_varyings */ 13722 0, /* n_xfb_varyings */ 13723 &m_vs_id, DE_NULL, /* out_tc_id */ 13724 DE_NULL, /* out_te_id */ 13725 DE_NULL, /* out_gs_id */ 13726 DE_NULL, /* out_fs_id */ 13727 &m_po_id)) 13728 { 13729 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for [" 13730 << getTestCaseString(static_cast<_test_case>(test_case)) 13731 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage; 13732 13733 m_has_test_passed = false; 13734 } 13735 13736 /* Delete any objects that may have been created */ 13737 deinit(); 13738 } /* for (all test cases) */ 13739 13740 /** All done */ 13741 if (m_has_test_passed) 13742 { 13743 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13744 } 13745 else 13746 { 13747 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13748 } 13749 13750 return STOP; 13751} 13752 13753} /* ShaderSubroutine */ 13754 13755/** Constructor. 13756 * 13757 * @param context Rendering context. 13758 **/ 13759ShaderSubroutineTests::ShaderSubroutineTests(deqp::Context& context) 13760 : TestCaseGroup(context, "shader_subroutine", "Verifies \"shader_subroutine\" functionality") 13761{ 13762 /* Left blank on purpose */ 13763} 13764 13765/** Initializes a texture_storage_multisample test group. 13766 * 13767 **/ 13768void ShaderSubroutineTests::init(void) 13769{ 13770 addChild(new ShaderSubroutine::APITest1(m_context)); 13771 addChild(new ShaderSubroutine::APITest2(m_context)); 13772 addChild(new ShaderSubroutine::FunctionalTest1_2(m_context)); 13773 addChild(new ShaderSubroutine::FunctionalTest3_4(m_context)); 13774 addChild(new ShaderSubroutine::FunctionalTest5(m_context)); 13775 addChild(new ShaderSubroutine::FunctionalTest6(m_context)); 13776 addChild(new ShaderSubroutine::FunctionalTest7_8(m_context)); 13777 addChild(new ShaderSubroutine::FunctionalTest9(m_context)); 13778 addChild(new ShaderSubroutine::FunctionalTest10(m_context)); 13779 addChild(new ShaderSubroutine::FunctionalTest11(m_context)); 13780 addChild(new ShaderSubroutine::FunctionalTest12(m_context)); 13781 addChild(new ShaderSubroutine::FunctionalTest13(m_context)); 13782 addChild(new ShaderSubroutine::FunctionalTest14_15(m_context)); 13783 addChild(new ShaderSubroutine::FunctionalTest16(m_context)); 13784 addChild(new ShaderSubroutine::FunctionalTest17(m_context)); 13785 addChild(new ShaderSubroutine::FunctionalTest18_19(m_context)); 13786 addChild(new ShaderSubroutine::NegativeTest1(m_context)); 13787 addChild(new ShaderSubroutine::NegativeTest2(m_context)); 13788 addChild(new ShaderSubroutine::NegativeTest3(m_context)); 13789 addChild(new ShaderSubroutine::NegativeTest4(m_context)); 13790 addChild(new ShaderSubroutine::NegativeTest5(m_context)); 13791 addChild(new ShaderSubroutine::NegativeTest6(m_context)); 13792 addChild(new ShaderSubroutine::NegativeTest7(m_context)); 13793 addChild(new ShaderSubroutine::NegativeTest8(m_context)); 13794 addChild(new ShaderSubroutine::NegativeTest9(m_context)); 13795 addChild(new ShaderSubroutine::NegativeTest10(m_context)); 13796 addChild(new ShaderSubroutine::NegativeTest11(m_context)); 13797 addChild(new ShaderSubroutine::NegativeTest12(m_context)); 13798} 13799 13800} /* glcts namespace */ 13801