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 gl4GPUShaderFP64Tests.cpp 26 * \brief Implements conformance tests for "GPU Shader FP64" functionality. 27 */ /*-------------------------------------------------------------------*/ 28 29 #include "gl4cGPUShaderFP64Tests.hpp" 30 #include "gluContextInfo.hpp" 31 #include "glwFunctions.hpp" 32 #include "tcuMatrix.hpp" 33 #include "tcuTestLog.hpp" 34 35 #include <iomanip> 36 37 #include "deMath.h" 38 #include "deUniquePtr.hpp" 39 #include "tcuMatrixUtil.hpp" 40 #include "tcuVectorUtil.hpp" 41 42 #include <cstdlib> 43 #include <cstring> 44 #include <limits> 45 #include <memory> 46 47 namespace gl4cts 48 { 49 50 const glw::GLenum Utils::programInfo::ARB_COMPUTE_SHADER = 0x91B9; 51 52 /** Constructor 53 * 54 * @param context Test context 55 **/ 56 Utils::programInfo::programInfo(deqp::Context& context) 57 : m_context(context) 58 , m_compute_shader_id(0) 59 , m_fragment_shader_id(0) 60 , m_geometry_shader_id(0) 61 , m_program_object_id(0) 62 , m_tesselation_control_shader_id(0) 63 , m_tesselation_evaluation_shader_id(0) 64 , m_vertex_shader_id(0) 65 { 66 /* Nothing to be done here */ 67 } 68 69 /** Destructor 70 * 71 **/ 72 Utils::programInfo::~programInfo() 73 { 74 /* GL entry points */ 75 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 76 77 /* Make sure program object is no longer used by GL */ 78 gl.useProgram(0); 79 80 /* Clean program object */ 81 if (0 != m_program_object_id) 82 { 83 gl.deleteProgram(m_program_object_id); 84 m_program_object_id = 0; 85 } 86 87 /* Clean shaders */ 88 if (0 != m_compute_shader_id) 89 { 90 gl.deleteShader(m_compute_shader_id); 91 m_compute_shader_id = 0; 92 } 93 94 if (0 != m_fragment_shader_id) 95 { 96 gl.deleteShader(m_fragment_shader_id); 97 m_fragment_shader_id = 0; 98 } 99 100 if (0 != m_geometry_shader_id) 101 { 102 gl.deleteShader(m_geometry_shader_id); 103 m_geometry_shader_id = 0; 104 } 105 106 if (0 != m_tesselation_control_shader_id) 107 { 108 gl.deleteShader(m_tesselation_control_shader_id); 109 m_tesselation_control_shader_id = 0; 110 } 111 112 if (0 != m_tesselation_evaluation_shader_id) 113 { 114 gl.deleteShader(m_tesselation_evaluation_shader_id); 115 m_tesselation_evaluation_shader_id = 0; 116 } 117 118 if (0 != m_vertex_shader_id) 119 { 120 gl.deleteShader(m_vertex_shader_id); 121 m_vertex_shader_id = 0; 122 } 123 } 124 125 /** Build program 126 * 127 * @param compute_shader_code Compute shader source code 128 * @param fragment_shader_code Fragment shader source code 129 * @param geometry_shader_code Geometry shader source code 130 * @param tesselation_control_shader_code Tesselation control shader source code 131 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code 132 * @param vertex_shader_code Vertex shader source code 133 * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback 134 * @param n_varying_names Number of varyings to be captured with transfrom feedback 135 **/ 136 void Utils::programInfo::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code, 137 const glw::GLchar* geometry_shader_code, 138 const glw::GLchar* tesselation_control_shader_code, 139 const glw::GLchar* tesselation_evaluation_shader_code, 140 const glw::GLchar* vertex_shader_code, const glw::GLchar* const* varying_names, 141 glw::GLuint n_varying_names) 142 { 143 /* GL entry points */ 144 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 145 146 /* Create shader objects and compile */ 147 if (0 != compute_shader_code) 148 { 149 m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER); 150 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 151 152 compile(m_compute_shader_id, compute_shader_code); 153 } 154 155 if (0 != fragment_shader_code) 156 { 157 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 158 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 159 160 compile(m_fragment_shader_id, fragment_shader_code); 161 } 162 163 if (0 != geometry_shader_code) 164 { 165 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER); 166 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 167 168 compile(m_geometry_shader_id, geometry_shader_code); 169 } 170 171 if (0 != tesselation_control_shader_code) 172 { 173 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER); 174 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 175 176 compile(m_tesselation_control_shader_id, tesselation_control_shader_code); 177 } 178 179 if (0 != tesselation_evaluation_shader_code) 180 { 181 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER); 182 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 183 184 compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code); 185 } 186 187 if (0 != vertex_shader_code) 188 { 189 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 190 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 191 192 compile(m_vertex_shader_id, vertex_shader_code); 193 } 194 195 /* Create program object */ 196 m_program_object_id = gl.createProgram(); 197 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram"); 198 199 /* Set up captyured varyings' names */ 200 if (0 != n_varying_names) 201 { 202 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS); 203 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings"); 204 } 205 206 /* Link program */ 207 link(); 208 } 209 210 /** Compile shader 211 * 212 * @param shader_id Shader object id 213 * @param shader_code Shader source code 214 **/ 215 void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const 216 { 217 /* GL entry points */ 218 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 219 220 /* Compilation status */ 221 glw::GLint status = GL_FALSE; 222 223 /* Set source code */ 224 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0); 225 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource"); 226 227 /* Compile */ 228 gl.compileShader(shader_id); 229 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader"); 230 231 /* Get compilation status */ 232 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status); 233 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 234 235 /* Log compilation error */ 236 if (GL_TRUE != status) 237 { 238 glw::GLint length = 0; 239 std::vector<glw::GLchar> message; 240 241 /* Error log length */ 242 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length); 243 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 244 245 /* Prepare storage */ 246 message.resize(length); 247 248 /* Get error log */ 249 gl.getShaderInfoLog(shader_id, length, 0, &message[0]); 250 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog"); 251 252 /* Log */ 253 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n" 254 << &message[0] << "\nShader source\n" 255 << shader_code << tcu::TestLog::EndMessage; 256 257 TCU_FAIL("Failed to compile shader"); 258 } 259 } 260 261 /** Attach shaders and link program 262 * 263 **/ 264 void Utils::programInfo::link() const 265 { 266 /* GL entry points */ 267 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 268 269 /* Link status */ 270 glw::GLint status = GL_FALSE; 271 272 /* Attach shaders */ 273 if (0 != m_compute_shader_id) 274 { 275 gl.attachShader(m_program_object_id, m_compute_shader_id); 276 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 277 } 278 279 if (0 != m_fragment_shader_id) 280 { 281 gl.attachShader(m_program_object_id, m_fragment_shader_id); 282 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 283 } 284 285 if (0 != m_geometry_shader_id) 286 { 287 gl.attachShader(m_program_object_id, m_geometry_shader_id); 288 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 289 } 290 291 if (0 != m_tesselation_control_shader_id) 292 { 293 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id); 294 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 295 } 296 297 if (0 != m_tesselation_evaluation_shader_id) 298 { 299 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id); 300 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 301 } 302 303 if (0 != m_vertex_shader_id) 304 { 305 gl.attachShader(m_program_object_id, m_vertex_shader_id); 306 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 307 } 308 309 /* Link */ 310 gl.linkProgram(m_program_object_id); 311 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram"); 312 313 /* Get link status */ 314 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status); 315 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 316 317 /* Log link error */ 318 if (GL_TRUE != status) 319 { 320 glw::GLint length = 0; 321 std::vector<glw::GLchar> message; 322 323 /* Get error log length */ 324 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length); 325 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 326 327 message.resize(length); 328 329 /* Get error log */ 330 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]); 331 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog"); 332 333 /* Log */ 334 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n" 335 << &message[0] << tcu::TestLog::EndMessage; 336 337 TCU_FAIL("Failed to link program"); 338 } 339 } 340 341 /** Retrieves base type of user-provided variable type. (eg. VARIABLE_TYPE_DOUBLE for double-precision 342 * matrix types. 343 * 344 * @param type Variable type to return base type for. 345 * 346 * @return Requested value or VARAIBLE_TYPE_UNKNOWN if @param type was not recognized. 347 **/ 348 Utils::_variable_type Utils::getBaseVariableType(_variable_type type) 349 { 350 _variable_type result = VARIABLE_TYPE_UNKNOWN; 351 352 switch (type) 353 { 354 case VARIABLE_TYPE_BOOL: 355 { 356 result = VARIABLE_TYPE_BOOL; 357 358 break; 359 } 360 361 case VARIABLE_TYPE_DOUBLE: 362 case VARIABLE_TYPE_DMAT2: 363 case VARIABLE_TYPE_DMAT2X3: 364 case VARIABLE_TYPE_DMAT2X4: 365 case VARIABLE_TYPE_DMAT3: 366 case VARIABLE_TYPE_DMAT3X2: 367 case VARIABLE_TYPE_DMAT3X4: 368 case VARIABLE_TYPE_DMAT4: 369 case VARIABLE_TYPE_DMAT4X2: 370 case VARIABLE_TYPE_DMAT4X3: 371 case VARIABLE_TYPE_DVEC2: 372 case VARIABLE_TYPE_DVEC3: 373 case VARIABLE_TYPE_DVEC4: 374 { 375 result = VARIABLE_TYPE_DOUBLE; 376 377 break; 378 } 379 380 case VARIABLE_TYPE_INT: 381 case VARIABLE_TYPE_IVEC2: 382 case VARIABLE_TYPE_IVEC3: 383 case VARIABLE_TYPE_IVEC4: 384 { 385 result = VARIABLE_TYPE_INT; 386 387 break; 388 } 389 390 case VARIABLE_TYPE_UINT: 391 case VARIABLE_TYPE_UVEC2: 392 case VARIABLE_TYPE_UVEC3: 393 case VARIABLE_TYPE_UVEC4: 394 { 395 result = VARIABLE_TYPE_UINT; 396 397 break; 398 } 399 400 case VARIABLE_TYPE_FLOAT: 401 case VARIABLE_TYPE_MAT2: 402 case VARIABLE_TYPE_MAT2X3: 403 case VARIABLE_TYPE_MAT2X4: 404 case VARIABLE_TYPE_MAT3: 405 case VARIABLE_TYPE_MAT3X2: 406 case VARIABLE_TYPE_MAT3X4: 407 case VARIABLE_TYPE_MAT4: 408 case VARIABLE_TYPE_MAT4X2: 409 case VARIABLE_TYPE_MAT4X3: 410 case VARIABLE_TYPE_VEC2: 411 case VARIABLE_TYPE_VEC3: 412 case VARIABLE_TYPE_VEC4: 413 { 414 result = VARIABLE_TYPE_FLOAT; 415 416 break; 417 } 418 419 default: 420 { 421 TCU_FAIL("Unrecognized variable type"); 422 } 423 } /* switch (type) */ 424 425 return result; 426 } 427 428 /** Returns size (in bytes) of a single component of a base variable type. 429 * 430 * @param type Base variable type to use for the query. 431 * 432 * @return Requested value or 0 if @param type was not recognized. 433 **/ 434 unsigned int Utils::getBaseVariableTypeComponentSize(_variable_type type) 435 { 436 unsigned int result = 0; 437 438 switch (type) 439 { 440 case VARIABLE_TYPE_BOOL: 441 result = sizeof(bool); 442 break; 443 case VARIABLE_TYPE_DOUBLE: 444 result = sizeof(double); 445 break; 446 case VARIABLE_TYPE_FLOAT: 447 result = sizeof(float); 448 break; 449 case VARIABLE_TYPE_INT: 450 result = sizeof(int); 451 break; 452 case VARIABLE_TYPE_UINT: 453 result = sizeof(unsigned int); 454 break; 455 456 default: 457 { 458 TCU_FAIL("Unrecognized variable type"); 459 } 460 } /* switch (type) */ 461 462 return result; 463 } 464 465 /** Returns component, corresponding to user-specified index 466 * (eg. index:0 corresponds to 'x', index:1 corresponds to 'y', 467 * and so on. 468 * 469 * @param index Component index. 470 * 471 * @return As per description. 472 **/ 473 unsigned char Utils::getComponentAtIndex(unsigned int index) 474 { 475 unsigned char result = '?'; 476 477 switch (index) 478 { 479 case 0: 480 result = 'x'; 481 break; 482 case 1: 483 result = 'y'; 484 break; 485 case 2: 486 result = 'z'; 487 break; 488 case 3: 489 result = 'w'; 490 break; 491 492 default: 493 { 494 TCU_FAIL("Unrecognized component index"); 495 } 496 } 497 498 return result; 499 } 500 501 /** Get _variable_type representing double-precision type with given dimmensions 502 * 503 * @param n_columns Number of columns 504 * @param n_row Number of rows 505 * 506 * @return Corresponding _variable_type 507 **/ 508 Utils::_variable_type Utils::getDoubleVariableType(glw::GLuint n_columns, glw::GLuint n_rows) 509 { 510 Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN; 511 512 static const _variable_type types[4][4] = { 513 { VARIABLE_TYPE_DOUBLE, VARIABLE_TYPE_DVEC2, VARIABLE_TYPE_DVEC3, VARIABLE_TYPE_DVEC4 }, 514 { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT2, VARIABLE_TYPE_DMAT2X3, VARIABLE_TYPE_DMAT2X4 }, 515 { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT3X2, VARIABLE_TYPE_DMAT3, VARIABLE_TYPE_DMAT3X4 }, 516 { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT4X2, VARIABLE_TYPE_DMAT4X3, VARIABLE_TYPE_DMAT4 } 517 }; 518 519 type = types[n_columns - 1][n_rows - 1]; 520 521 return type; 522 } 523 524 /** Returns a single-precision equivalent of a double-precision floating-point variable 525 * type. 526 * 527 * @param type Double-precision variable type. Only VARIABLE_TYPE_D* variable types 528 * are accepted. 529 * 530 * @return Requested GLSL type. 531 **/ 532 std::string Utils::getFPVariableTypeStringForVariableType(_variable_type type) 533 { 534 std::string result = "[?]"; 535 536 switch (type) 537 { 538 case VARIABLE_TYPE_DOUBLE: 539 result = "float"; 540 break; 541 case VARIABLE_TYPE_DMAT2: 542 result = "mat2"; 543 break; 544 case VARIABLE_TYPE_DMAT2X3: 545 result = "mat2x3"; 546 break; 547 case VARIABLE_TYPE_DMAT2X4: 548 result = "mat2x4"; 549 break; 550 case VARIABLE_TYPE_DMAT3: 551 result = "mat3"; 552 break; 553 case VARIABLE_TYPE_DMAT3X2: 554 result = "mat3x2"; 555 break; 556 case VARIABLE_TYPE_DMAT3X4: 557 result = "mat3x4"; 558 break; 559 case VARIABLE_TYPE_DMAT4: 560 result = "mat4"; 561 break; 562 case VARIABLE_TYPE_DMAT4X2: 563 result = "mat4x2"; 564 break; 565 case VARIABLE_TYPE_DMAT4X3: 566 result = "mat4x3"; 567 break; 568 case VARIABLE_TYPE_DVEC2: 569 result = "vec2"; 570 break; 571 case VARIABLE_TYPE_DVEC3: 572 result = "vec3"; 573 break; 574 case VARIABLE_TYPE_DVEC4: 575 result = "vec4"; 576 break; 577 578 default: 579 { 580 TCU_FAIL("Unrecognized variable type"); 581 } 582 }; /* switch (type) */ 583 584 return result; 585 } 586 587 /** Returns GL data type enum corresponding to user-provided base variable type. 588 * 589 * @param type Base variable type to return corresponding GLenum value for. 590 * 591 * @return Corresponding GLenum value or GL_NONE if the input value was not 592 * recognized. 593 **/ 594 glw::GLenum Utils::getGLDataTypeOfBaseVariableType(_variable_type type) 595 { 596 glw::GLenum result = GL_NONE; 597 598 switch (type) 599 { 600 case VARIABLE_TYPE_BOOL: 601 result = GL_BOOL; 602 break; 603 case VARIABLE_TYPE_DOUBLE: 604 result = GL_DOUBLE; 605 break; 606 case VARIABLE_TYPE_FLOAT: 607 result = GL_FLOAT; 608 break; 609 case VARIABLE_TYPE_INT: 610 result = GL_INT; 611 break; 612 case VARIABLE_TYPE_UINT: 613 result = GL_UNSIGNED_INT; 614 break; 615 616 default: 617 { 618 TCU_FAIL("Unrecognized variable type"); 619 } 620 } 621 622 return result; 623 } 624 625 /** Return GLenum representing given <type> 626 * 627 * @param type Type of variable 628 * 629 * @return GL enumeration 630 **/ 631 glw::GLenum Utils::getGLDataTypeOfVariableType(_variable_type type) 632 { 633 glw::GLenum result = GL_NONE; 634 635 switch (type) 636 { 637 case VARIABLE_TYPE_BOOL: 638 result = GL_BOOL; 639 break; 640 case VARIABLE_TYPE_DOUBLE: 641 result = GL_DOUBLE; 642 break; 643 case VARIABLE_TYPE_DMAT2: 644 result = GL_DOUBLE_MAT2; 645 break; 646 case VARIABLE_TYPE_DMAT2X3: 647 result = GL_DOUBLE_MAT2x3; 648 break; 649 case VARIABLE_TYPE_DMAT2X4: 650 result = GL_DOUBLE_MAT2x4; 651 break; 652 case VARIABLE_TYPE_DMAT3: 653 result = GL_DOUBLE_MAT3; 654 break; 655 case VARIABLE_TYPE_DMAT3X2: 656 result = GL_DOUBLE_MAT3x2; 657 break; 658 case VARIABLE_TYPE_DMAT3X4: 659 result = GL_DOUBLE_MAT3x4; 660 break; 661 case VARIABLE_TYPE_DMAT4: 662 result = GL_DOUBLE_MAT4; 663 break; 664 case VARIABLE_TYPE_DMAT4X2: 665 result = GL_DOUBLE_MAT4x2; 666 break; 667 case VARIABLE_TYPE_DMAT4X3: 668 result = GL_DOUBLE_MAT4x3; 669 break; 670 case VARIABLE_TYPE_DVEC2: 671 result = GL_DOUBLE_VEC2; 672 break; 673 case VARIABLE_TYPE_DVEC3: 674 result = GL_DOUBLE_VEC3; 675 break; 676 case VARIABLE_TYPE_DVEC4: 677 result = GL_DOUBLE_VEC4; 678 break; 679 case VARIABLE_TYPE_FLOAT: 680 result = GL_FLOAT; 681 break; 682 case VARIABLE_TYPE_INT: 683 result = GL_INT; 684 break; 685 case VARIABLE_TYPE_IVEC2: 686 result = GL_INT_VEC2; 687 break; 688 case VARIABLE_TYPE_IVEC3: 689 result = GL_INT_VEC3; 690 break; 691 case VARIABLE_TYPE_IVEC4: 692 result = GL_INT_VEC4; 693 break; 694 case VARIABLE_TYPE_MAT2: 695 result = GL_FLOAT_MAT2; 696 break; 697 case VARIABLE_TYPE_MAT2X3: 698 result = GL_FLOAT_MAT2x3; 699 break; 700 case VARIABLE_TYPE_MAT2X4: 701 result = GL_FLOAT_MAT2x4; 702 break; 703 case VARIABLE_TYPE_MAT3: 704 result = GL_FLOAT_MAT3; 705 break; 706 case VARIABLE_TYPE_MAT3X2: 707 result = GL_FLOAT_MAT3x2; 708 break; 709 case VARIABLE_TYPE_MAT3X4: 710 result = GL_FLOAT_MAT3x4; 711 break; 712 case VARIABLE_TYPE_MAT4: 713 result = GL_FLOAT_MAT4; 714 break; 715 case VARIABLE_TYPE_MAT4X2: 716 result = GL_FLOAT_MAT4x2; 717 break; 718 case VARIABLE_TYPE_MAT4X3: 719 result = GL_FLOAT_MAT4x3; 720 break; 721 case VARIABLE_TYPE_UINT: 722 result = GL_UNSIGNED_INT; 723 break; 724 case VARIABLE_TYPE_UVEC2: 725 result = GL_UNSIGNED_INT_VEC2; 726 break; 727 case VARIABLE_TYPE_UVEC3: 728 result = GL_UNSIGNED_INT_VEC3; 729 break; 730 case VARIABLE_TYPE_UVEC4: 731 result = GL_UNSIGNED_INT_VEC4; 732 break; 733 case VARIABLE_TYPE_VEC2: 734 result = GL_FLOAT_VEC2; 735 break; 736 case VARIABLE_TYPE_VEC3: 737 result = GL_FLOAT_VEC3; 738 break; 739 case VARIABLE_TYPE_VEC4: 740 result = GL_FLOAT_VEC4; 741 break; 742 743 default: 744 { 745 TCU_FAIL("Unrecognized variable type"); 746 } 747 } 748 749 return result; 750 } 751 752 /** Get _variable_type representing integer type with given dimmensions 753 * 754 * @param n_columns Number of columns 755 * @param n_row Number of rows 756 * 757 * @return Corresponding _variable_type 758 **/ 759 Utils::_variable_type Utils::getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows) 760 { 761 Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN; 762 763 static const _variable_type types[4] = { VARIABLE_TYPE_INT, VARIABLE_TYPE_IVEC2, VARIABLE_TYPE_IVEC3, 764 VARIABLE_TYPE_IVEC4 }; 765 766 if (1 != n_columns) 767 { 768 TCU_FAIL("Not implemented"); 769 } 770 else 771 { 772 type = types[n_rows - 1]; 773 } 774 775 return type; 776 } 777 778 /** Returns te number of components that variables defined with user-specified type 779 * support. For matrix types, total amount of values accessible for the type will be 780 * returned. 781 * 782 * @param type Variable type to return the described vale for. 783 * 784 * @return As per description or 0 if @param type was not recognized. 785 */ 786 unsigned int Utils::getNumberOfComponentsForVariableType(_variable_type type) 787 { 788 unsigned int result = 0; 789 790 switch (type) 791 { 792 case VARIABLE_TYPE_BOOL: 793 case VARIABLE_TYPE_DOUBLE: 794 case VARIABLE_TYPE_FLOAT: 795 case VARIABLE_TYPE_INT: 796 case VARIABLE_TYPE_UINT: 797 { 798 result = 1; 799 800 break; 801 } 802 803 case VARIABLE_TYPE_DVEC2: 804 case VARIABLE_TYPE_IVEC2: 805 case VARIABLE_TYPE_UVEC2: 806 case VARIABLE_TYPE_VEC2: 807 { 808 result = 2; 809 810 break; 811 } 812 813 case VARIABLE_TYPE_DVEC3: 814 case VARIABLE_TYPE_IVEC3: 815 case VARIABLE_TYPE_UVEC3: 816 case VARIABLE_TYPE_VEC3: 817 { 818 result = 3; 819 820 break; 821 } 822 823 case VARIABLE_TYPE_DVEC4: 824 case VARIABLE_TYPE_IVEC4: 825 case VARIABLE_TYPE_UVEC4: 826 case VARIABLE_TYPE_VEC4: 827 { 828 result = 4; 829 830 break; 831 } 832 833 case VARIABLE_TYPE_DMAT2: 834 case VARIABLE_TYPE_MAT2: 835 { 836 result = 2 * 2; 837 838 break; 839 } 840 841 case VARIABLE_TYPE_DMAT2X3: 842 case VARIABLE_TYPE_DMAT3X2: 843 case VARIABLE_TYPE_MAT2X3: 844 case VARIABLE_TYPE_MAT3X2: 845 { 846 result = 2 * 3; 847 848 break; 849 } 850 851 case VARIABLE_TYPE_DMAT2X4: 852 case VARIABLE_TYPE_DMAT4X2: 853 case VARIABLE_TYPE_MAT2X4: 854 case VARIABLE_TYPE_MAT4X2: 855 { 856 result = 2 * 4; 857 858 break; 859 } 860 861 case VARIABLE_TYPE_DMAT3: 862 case VARIABLE_TYPE_MAT3: 863 { 864 result = 3 * 3; 865 866 break; 867 } 868 869 case VARIABLE_TYPE_DMAT3X4: 870 case VARIABLE_TYPE_DMAT4X3: 871 case VARIABLE_TYPE_MAT3X4: 872 case VARIABLE_TYPE_MAT4X3: 873 { 874 result = 3 * 4; 875 876 break; 877 } 878 879 case VARIABLE_TYPE_DMAT4: 880 case VARIABLE_TYPE_MAT4: 881 { 882 result = 4 * 4; 883 884 break; 885 } 886 887 default: 888 { 889 TCU_FAIL("Unrecognized type"); 890 } 891 } /* switch (type) */ 892 893 return result; 894 } 895 896 /** Returns number of columns user-specified matrix variable type describes. 897 * 898 * @param type Variable type to use for the query. Only VARIABLE_TYPE_DMAT* 899 * values are valid. 900 * 901 * @return As per description. 902 **/ 903 unsigned int Utils::getNumberOfColumnsForVariableType(_variable_type type) 904 { 905 unsigned int result = 0; 906 907 switch (type) 908 { 909 case VARIABLE_TYPE_BOOL: 910 case VARIABLE_TYPE_DOUBLE: 911 case VARIABLE_TYPE_FLOAT: 912 case VARIABLE_TYPE_INT: 913 case VARIABLE_TYPE_UINT: 914 case VARIABLE_TYPE_DVEC2: 915 case VARIABLE_TYPE_IVEC2: 916 case VARIABLE_TYPE_UVEC2: 917 case VARIABLE_TYPE_VEC2: 918 case VARIABLE_TYPE_DVEC3: 919 case VARIABLE_TYPE_IVEC3: 920 case VARIABLE_TYPE_UVEC3: 921 case VARIABLE_TYPE_VEC3: 922 case VARIABLE_TYPE_DVEC4: 923 case VARIABLE_TYPE_IVEC4: 924 case VARIABLE_TYPE_UVEC4: 925 case VARIABLE_TYPE_VEC4: 926 { 927 result = 1; 928 929 break; 930 } 931 932 case VARIABLE_TYPE_DMAT2: 933 case VARIABLE_TYPE_DMAT2X3: 934 case VARIABLE_TYPE_DMAT2X4: 935 case VARIABLE_TYPE_MAT2: 936 case VARIABLE_TYPE_MAT2X3: 937 case VARIABLE_TYPE_MAT2X4: 938 { 939 result = 2; 940 941 break; 942 } 943 944 case VARIABLE_TYPE_DMAT3: 945 case VARIABLE_TYPE_DMAT3X2: 946 case VARIABLE_TYPE_DMAT3X4: 947 case VARIABLE_TYPE_MAT3: 948 case VARIABLE_TYPE_MAT3X2: 949 case VARIABLE_TYPE_MAT3X4: 950 { 951 result = 3; 952 953 break; 954 } 955 956 case VARIABLE_TYPE_DMAT4: 957 case VARIABLE_TYPE_DMAT4X2: 958 case VARIABLE_TYPE_DMAT4X3: 959 case VARIABLE_TYPE_MAT4: 960 case VARIABLE_TYPE_MAT4X2: 961 case VARIABLE_TYPE_MAT4X3: 962 { 963 result = 4; 964 965 break; 966 } 967 968 default: 969 { 970 TCU_FAIL("Unrecognized type"); 971 } 972 } /* switch (type) */ 973 974 return result; 975 } 976 977 /** Returns maximum number of uniform locations taken by user-specified double-precision 978 * variable type. 979 * 980 * @param type Variable type to use for the query. Only VARIABLE_TYPE_D* values are valid. 981 * 982 * @return As per description. 983 **/ 984 unsigned int Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type) 985 { 986 unsigned int result = 0; 987 988 switch (type) 989 { 990 case VARIABLE_TYPE_DOUBLE: 991 result = 1; 992 break; 993 case VARIABLE_TYPE_DVEC2: 994 result = 1; 995 break; 996 case VARIABLE_TYPE_DVEC3: 997 result = 2; 998 break; 999 case VARIABLE_TYPE_DVEC4: 1000 result = 2; 1001 break; 1002 case VARIABLE_TYPE_DMAT2: 1003 result = 2; 1004 break; 1005 case VARIABLE_TYPE_DMAT2X3: 1006 result = 6; 1007 break; 1008 case VARIABLE_TYPE_DMAT2X4: 1009 result = 8; 1010 break; 1011 case VARIABLE_TYPE_DMAT3: 1012 result = 6; 1013 break; 1014 case VARIABLE_TYPE_DMAT3X2: 1015 result = 4; 1016 break; 1017 case VARIABLE_TYPE_DMAT3X4: 1018 result = 8; 1019 break; 1020 case VARIABLE_TYPE_DMAT4: 1021 result = 8; 1022 break; 1023 case VARIABLE_TYPE_DMAT4X2: 1024 result = 4; 1025 break; 1026 case VARIABLE_TYPE_DMAT4X3: 1027 result = 6; 1028 break; 1029 1030 default: 1031 { 1032 TCU_FAIL("Unrecognized type"); 1033 } 1034 } /* switch (type) */ 1035 1036 return result; 1037 } 1038 1039 /** Get number of rows for given variable type 1040 * 1041 * @param type Type of variable 1042 * 1043 * @return Number of rows 1044 **/ 1045 unsigned int Utils::getNumberOfRowsForVariableType(_variable_type type) 1046 { 1047 unsigned int result = 0; 1048 1049 switch (type) 1050 { 1051 case VARIABLE_TYPE_BOOL: 1052 case VARIABLE_TYPE_DOUBLE: 1053 case VARIABLE_TYPE_FLOAT: 1054 case VARIABLE_TYPE_INT: 1055 case VARIABLE_TYPE_UINT: 1056 { 1057 result = 1; 1058 1059 break; 1060 } 1061 1062 case VARIABLE_TYPE_DVEC2: 1063 case VARIABLE_TYPE_IVEC2: 1064 case VARIABLE_TYPE_UVEC2: 1065 case VARIABLE_TYPE_VEC2: 1066 case VARIABLE_TYPE_DMAT2: 1067 case VARIABLE_TYPE_DMAT3X2: 1068 case VARIABLE_TYPE_DMAT4X2: 1069 case VARIABLE_TYPE_MAT2: 1070 case VARIABLE_TYPE_MAT3X2: 1071 case VARIABLE_TYPE_MAT4X2: 1072 { 1073 result = 2; 1074 1075 break; 1076 } 1077 1078 case VARIABLE_TYPE_DVEC3: 1079 case VARIABLE_TYPE_IVEC3: 1080 case VARIABLE_TYPE_UVEC3: 1081 case VARIABLE_TYPE_VEC3: 1082 case VARIABLE_TYPE_DMAT2X3: 1083 case VARIABLE_TYPE_DMAT3: 1084 case VARIABLE_TYPE_DMAT4X3: 1085 case VARIABLE_TYPE_MAT2X3: 1086 case VARIABLE_TYPE_MAT3: 1087 case VARIABLE_TYPE_MAT4X3: 1088 { 1089 result = 3; 1090 1091 break; 1092 } 1093 1094 case VARIABLE_TYPE_DVEC4: 1095 case VARIABLE_TYPE_IVEC4: 1096 case VARIABLE_TYPE_UVEC4: 1097 case VARIABLE_TYPE_VEC4: 1098 case VARIABLE_TYPE_DMAT2X4: 1099 case VARIABLE_TYPE_DMAT3X4: 1100 case VARIABLE_TYPE_DMAT4: 1101 case VARIABLE_TYPE_MAT2X4: 1102 case VARIABLE_TYPE_MAT3X4: 1103 case VARIABLE_TYPE_MAT4: 1104 { 1105 result = 4; 1106 1107 break; 1108 } 1109 1110 default: 1111 { 1112 TCU_FAIL("Unrecognized type"); 1113 } 1114 } /* switch (type) */ 1115 1116 return result; 1117 } 1118 1119 /** Returns variable type of a matrix constructed by multiplying two matrices. 1120 * 1121 * @param type_matrix_a L-side matrix type. 1122 * @param type_matrix_b R-side matrix type. 1123 * 1124 * @return As per description. 1125 **/ 1126 Utils::_variable_type Utils::getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a, 1127 _variable_type type_matrix_b) 1128 { 1129 const unsigned int n_a_columns = Utils::getNumberOfColumnsForVariableType(type_matrix_a); 1130 const unsigned int n_a_components = Utils::getNumberOfComponentsForVariableType(type_matrix_a); 1131 const unsigned int n_a_rows = n_a_components / n_a_columns; 1132 const unsigned int n_b_columns = Utils::getNumberOfColumnsForVariableType(type_matrix_b); 1133 const unsigned int n_result_columns = n_b_columns; 1134 const unsigned int n_result_rows = n_a_rows; 1135 Utils::_variable_type result; 1136 1137 switch (n_result_columns) 1138 { 1139 case 2: 1140 { 1141 switch (n_result_rows) 1142 { 1143 case 2: 1144 result = VARIABLE_TYPE_DMAT2; 1145 break; 1146 case 3: 1147 result = VARIABLE_TYPE_DMAT2X3; 1148 break; 1149 case 4: 1150 result = VARIABLE_TYPE_DMAT2X4; 1151 break; 1152 1153 default: 1154 { 1155 TCU_FAIL("Unrecognized amount of rows in result variable"); 1156 } 1157 } /* switch (n_result_rows) */ 1158 1159 break; 1160 } /* case 2: */ 1161 1162 case 3: 1163 { 1164 switch (n_result_rows) 1165 { 1166 case 2: 1167 result = VARIABLE_TYPE_DMAT3X2; 1168 break; 1169 case 3: 1170 result = VARIABLE_TYPE_DMAT3; 1171 break; 1172 case 4: 1173 result = VARIABLE_TYPE_DMAT3X4; 1174 break; 1175 1176 default: 1177 { 1178 TCU_FAIL("Unrecognized amount of rows in result variable"); 1179 } 1180 } /* switch (n_result_rows) */ 1181 1182 break; 1183 } /* case 3: */ 1184 1185 case 4: 1186 { 1187 switch (n_result_rows) 1188 { 1189 case 2: 1190 result = VARIABLE_TYPE_DMAT4X2; 1191 break; 1192 case 3: 1193 result = VARIABLE_TYPE_DMAT4X3; 1194 break; 1195 case 4: 1196 result = VARIABLE_TYPE_DMAT4; 1197 break; 1198 1199 default: 1200 { 1201 TCU_FAIL("Unrecognized amount of rows in result variable"); 1202 } 1203 } /* switch (n_result_rows) */ 1204 1205 break; 1206 } /* case 4: */ 1207 1208 default: 1209 { 1210 TCU_FAIL("Unrecognized amount of columns in result variable"); 1211 } 1212 } /* switch (n_result_columns) */ 1213 1214 /* Done */ 1215 return result; 1216 } 1217 1218 /** Returns a string holding the value represented by user-provided variable, for which 1219 * the data are represented in @param type variable type. 1220 * 1221 * @return As per description. 1222 **/ 1223 std::string Utils::getStringForVariableTypeValue(_variable_type type, const unsigned char* data_ptr) 1224 { 1225 std::stringstream result_sstream; 1226 1227 switch (type) 1228 { 1229 case VARIABLE_TYPE_BOOL: 1230 result_sstream << *((bool*)data_ptr); 1231 break; 1232 case VARIABLE_TYPE_DOUBLE: 1233 result_sstream << *((double*)data_ptr); 1234 break; 1235 case VARIABLE_TYPE_FLOAT: 1236 result_sstream << *((float*)data_ptr); 1237 break; 1238 case VARIABLE_TYPE_INT: 1239 result_sstream << *((int*)data_ptr); 1240 break; 1241 case VARIABLE_TYPE_UINT: 1242 result_sstream << *((unsigned int*)data_ptr); 1243 break; 1244 1245 default: 1246 { 1247 TCU_FAIL("Unrecognized variable type requested"); 1248 } 1249 } /* switch (type) */ 1250 1251 return result_sstream.str(); 1252 } 1253 1254 /** Returns variable type of a transposed matrix of user-specified variable type. 1255 * 1256 * @param type Variable type of the matrix to be transposed. 1257 * 1258 * @return Transposed matrix variable type. 1259 **/ 1260 Utils::_variable_type Utils::getTransposedMatrixVariableType(Utils::_variable_type type) 1261 { 1262 Utils::_variable_type result; 1263 1264 switch (type) 1265 { 1266 case VARIABLE_TYPE_DMAT2: 1267 result = VARIABLE_TYPE_DMAT2; 1268 break; 1269 case VARIABLE_TYPE_DMAT2X3: 1270 result = VARIABLE_TYPE_DMAT3X2; 1271 break; 1272 case VARIABLE_TYPE_DMAT2X4: 1273 result = VARIABLE_TYPE_DMAT4X2; 1274 break; 1275 case VARIABLE_TYPE_DMAT3: 1276 result = VARIABLE_TYPE_DMAT3; 1277 break; 1278 case VARIABLE_TYPE_DMAT3X2: 1279 result = VARIABLE_TYPE_DMAT2X3; 1280 break; 1281 case VARIABLE_TYPE_DMAT3X4: 1282 result = VARIABLE_TYPE_DMAT4X3; 1283 break; 1284 case VARIABLE_TYPE_DMAT4: 1285 result = VARIABLE_TYPE_DMAT4; 1286 break; 1287 case VARIABLE_TYPE_DMAT4X2: 1288 result = VARIABLE_TYPE_DMAT2X4; 1289 break; 1290 case VARIABLE_TYPE_DMAT4X3: 1291 result = VARIABLE_TYPE_DMAT3X4; 1292 break; 1293 1294 default: 1295 { 1296 TCU_FAIL("Unrecognized double-precision matrix variable type."); 1297 } 1298 } /* switch (type) */ 1299 1300 return result; 1301 } 1302 1303 /** Get _variable_type representing unsigned integer type with given dimmensions 1304 * 1305 * @param n_columns Number of columns 1306 * @param n_row Number of rows 1307 * 1308 * @return Corresponding _variable_type 1309 **/ 1310 Utils::_variable_type Utils::getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows) 1311 { 1312 Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN; 1313 1314 static const _variable_type types[4] = { VARIABLE_TYPE_UINT, VARIABLE_TYPE_UVEC2, VARIABLE_TYPE_UVEC3, 1315 VARIABLE_TYPE_UVEC4 }; 1316 1317 if (1 != n_columns) 1318 { 1319 TCU_FAIL("Not implemented"); 1320 } 1321 else 1322 { 1323 type = types[n_rows - 1]; 1324 } 1325 1326 return type; 1327 } 1328 1329 /** Returns a literal corresponding to a GLSL keyword describing user-specified 1330 * variable type. 1331 * 1332 * @param type Variable type to use for the query. 1333 * 1334 * @return Requested GLSL keyword or [?] if @param type was not recognized. 1335 **/ 1336 std::string Utils::getVariableTypeString(_variable_type type) 1337 { 1338 std::string result = "[?]"; 1339 1340 switch (type) 1341 { 1342 case VARIABLE_TYPE_BOOL: 1343 result = "bool"; 1344 break; 1345 case VARIABLE_TYPE_BVEC2: 1346 result = "bvec2"; 1347 break; 1348 case VARIABLE_TYPE_BVEC3: 1349 result = "bvec3"; 1350 break; 1351 case VARIABLE_TYPE_BVEC4: 1352 result = "bvec4"; 1353 break; 1354 case VARIABLE_TYPE_DOUBLE: 1355 result = "double"; 1356 break; 1357 case VARIABLE_TYPE_DMAT2: 1358 result = "dmat2"; 1359 break; 1360 case VARIABLE_TYPE_DMAT2X3: 1361 result = "dmat2x3"; 1362 break; 1363 case VARIABLE_TYPE_DMAT2X4: 1364 result = "dmat2x4"; 1365 break; 1366 case VARIABLE_TYPE_DMAT3: 1367 result = "dmat3"; 1368 break; 1369 case VARIABLE_TYPE_DMAT3X2: 1370 result = "dmat3x2"; 1371 break; 1372 case VARIABLE_TYPE_DMAT3X4: 1373 result = "dmat3x4"; 1374 break; 1375 case VARIABLE_TYPE_DMAT4: 1376 result = "dmat4"; 1377 break; 1378 case VARIABLE_TYPE_DMAT4X2: 1379 result = "dmat4x2"; 1380 break; 1381 case VARIABLE_TYPE_DMAT4X3: 1382 result = "dmat4x3"; 1383 break; 1384 case VARIABLE_TYPE_DVEC2: 1385 result = "dvec2"; 1386 break; 1387 case VARIABLE_TYPE_DVEC3: 1388 result = "dvec3"; 1389 break; 1390 case VARIABLE_TYPE_DVEC4: 1391 result = "dvec4"; 1392 break; 1393 case VARIABLE_TYPE_FLOAT: 1394 result = "float"; 1395 break; 1396 case VARIABLE_TYPE_INT: 1397 result = "int"; 1398 break; 1399 case VARIABLE_TYPE_IVEC2: 1400 result = "ivec2"; 1401 break; 1402 case VARIABLE_TYPE_IVEC3: 1403 result = "ivec3"; 1404 break; 1405 case VARIABLE_TYPE_IVEC4: 1406 result = "ivec4"; 1407 break; 1408 case VARIABLE_TYPE_MAT2: 1409 result = "mat2"; 1410 break; 1411 case VARIABLE_TYPE_MAT2X3: 1412 result = "mat2x3"; 1413 break; 1414 case VARIABLE_TYPE_MAT2X4: 1415 result = "mat2x4"; 1416 break; 1417 case VARIABLE_TYPE_MAT3: 1418 result = "mat3"; 1419 break; 1420 case VARIABLE_TYPE_MAT3X2: 1421 result = "mat3x2"; 1422 break; 1423 case VARIABLE_TYPE_MAT3X4: 1424 result = "mat3x4"; 1425 break; 1426 case VARIABLE_TYPE_MAT4: 1427 result = "mat4"; 1428 break; 1429 case VARIABLE_TYPE_MAT4X2: 1430 result = "mat4x2"; 1431 break; 1432 case VARIABLE_TYPE_MAT4X3: 1433 result = "mat4x3"; 1434 break; 1435 case VARIABLE_TYPE_UINT: 1436 result = "uint"; 1437 break; 1438 case VARIABLE_TYPE_UVEC2: 1439 result = "uvec2"; 1440 break; 1441 case VARIABLE_TYPE_UVEC3: 1442 result = "uvec3"; 1443 break; 1444 case VARIABLE_TYPE_UVEC4: 1445 result = "uvec4"; 1446 break; 1447 case VARIABLE_TYPE_VEC2: 1448 result = "vec2"; 1449 break; 1450 case VARIABLE_TYPE_VEC3: 1451 result = "vec3"; 1452 break; 1453 case VARIABLE_TYPE_VEC4: 1454 result = "vec4"; 1455 break; 1456 1457 default: 1458 { 1459 TCU_FAIL("Unrecognized variable type"); 1460 } 1461 }; /* switch (type) */ 1462 1463 return result; 1464 } 1465 1466 /** Check if GL context meets version requirements 1467 * 1468 * @param gl Functions 1469 * @param required_major Minimum required MAJOR_VERSION 1470 * @param required_minor Minimum required MINOR_VERSION 1471 * 1472 * @return true if GL context version is at least as requested, false otherwise 1473 **/ 1474 bool Utils::isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor) 1475 { 1476 glw::GLint major = 0; 1477 glw::GLint minor = 0; 1478 1479 gl.getIntegerv(GL_MAJOR_VERSION, &major); 1480 gl.getIntegerv(GL_MINOR_VERSION, &minor); 1481 1482 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 1483 1484 if (major > required_major) 1485 { 1486 /* Major is higher than required one */ 1487 return true; 1488 } 1489 else if (major == required_major) 1490 { 1491 if (minor >= required_minor) 1492 { 1493 /* Major is equal to required one */ 1494 /* Minor is higher than or equal to required one */ 1495 return true; 1496 } 1497 else 1498 { 1499 /* Major is equal to required one */ 1500 /* Minor is lower than required one */ 1501 return false; 1502 } 1503 } 1504 else 1505 { 1506 /* Major is lower than required one */ 1507 return false; 1508 } 1509 } 1510 1511 /** Tells whether user-specified variable type corresponds to a matrix type. 1512 * 1513 * @param type Variable type to use for the query. 1514 * 1515 * @return true if the variable type describes a matrix, false otherwise. 1516 **/ 1517 bool Utils::isMatrixVariableType(_variable_type type) 1518 { 1519 return (type == VARIABLE_TYPE_MAT2 || type == VARIABLE_TYPE_MAT3 || type == VARIABLE_TYPE_MAT4 || 1520 type == VARIABLE_TYPE_MAT2X3 || type == VARIABLE_TYPE_MAT2X4 || type == VARIABLE_TYPE_MAT3X2 || 1521 type == VARIABLE_TYPE_MAT3X4 || type == VARIABLE_TYPE_MAT4X2 || type == VARIABLE_TYPE_MAT4X3 || 1522 type == VARIABLE_TYPE_DMAT2 || type == VARIABLE_TYPE_DMAT3 || type == VARIABLE_TYPE_DMAT4 || 1523 type == VARIABLE_TYPE_DMAT2X3 || type == VARIABLE_TYPE_DMAT2X4 || type == VARIABLE_TYPE_DMAT3X2 || 1524 type == VARIABLE_TYPE_DMAT3X4 || type == VARIABLE_TYPE_DMAT4X2 || type == VARIABLE_TYPE_DMAT4X3); 1525 } 1526 1527 /** Tells whether user-specified variable type is scalar. 1528 * 1529 * @return true if @param type is a scalar variable type, false otherwise. 1530 **/ 1531 bool Utils::isScalarVariableType(_variable_type type) 1532 { 1533 bool result = false; 1534 1535 switch (type) 1536 { 1537 case VARIABLE_TYPE_BOOL: 1538 result = true; 1539 break; 1540 case VARIABLE_TYPE_DOUBLE: 1541 result = true; 1542 break; 1543 case VARIABLE_TYPE_FLOAT: 1544 result = true; 1545 break; 1546 case VARIABLE_TYPE_INT: 1547 result = true; 1548 break; 1549 case VARIABLE_TYPE_UINT: 1550 result = true; 1551 break; 1552 default: 1553 break; 1554 }; /* switch (type) */ 1555 1556 return result; 1557 } 1558 1559 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion> 1560 * 1561 * @param token Token string 1562 * @param search_position Position at which find will start, it is updated to position at which replaced text ends 1563 * @param text String that will be used as replacement for <token> 1564 * @param string String to work on 1565 **/ 1566 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text, 1567 std::string& string) 1568 { 1569 const size_t text_length = strlen(text); 1570 const size_t token_length = strlen(token); 1571 const size_t token_position = string.find(token, search_position); 1572 1573 string.replace(token_position, token_length, text, text_length); 1574 1575 search_position = token_position + text_length; 1576 } 1577 1578 /** Constructor. 1579 * 1580 * @param context Rendering context. 1581 * 1582 **/ 1583 GPUShaderFP64Test1::GPUShaderFP64Test1(deqp::Context& context) 1584 : TestCase(context, "errors", "Verifies that various erroneous conditions related to double-precision " 1585 "float uniform support & glUniform*() / glUniformMatrix*() API " 1586 " are reported correctly.") 1587 , m_has_test_passed(true) 1588 , m_po_bool_arr_uniform_location(0) 1589 , m_po_bool_uniform_location(0) 1590 , m_po_bvec2_arr_uniform_location(0) 1591 , m_po_bvec2_uniform_location(0) 1592 , m_po_bvec3_arr_uniform_location(0) 1593 , m_po_bvec3_uniform_location(0) 1594 , m_po_bvec4_arr_uniform_location(0) 1595 , m_po_bvec4_uniform_location(0) 1596 , m_po_dmat2_arr_uniform_location(0) 1597 , m_po_dmat2_uniform_location(0) 1598 , m_po_dmat2x3_arr_uniform_location(0) 1599 , m_po_dmat2x3_uniform_location(0) 1600 , m_po_dmat2x4_arr_uniform_location(0) 1601 , m_po_dmat2x4_uniform_location(0) 1602 , m_po_dmat3_arr_uniform_location(0) 1603 , m_po_dmat3_uniform_location(0) 1604 , m_po_dmat3x2_arr_uniform_location(0) 1605 , m_po_dmat3x2_uniform_location(0) 1606 , m_po_dmat3x4_arr_uniform_location(0) 1607 , m_po_dmat3x4_uniform_location(0) 1608 , m_po_dmat4_arr_uniform_location(0) 1609 , m_po_dmat4_uniform_location(0) 1610 , m_po_dmat4x2_arr_uniform_location(0) 1611 , m_po_dmat4x2_uniform_location(0) 1612 , m_po_dmat4x3_arr_uniform_location(0) 1613 , m_po_dmat4x3_uniform_location(0) 1614 , m_po_double_arr_uniform_location(0) 1615 , m_po_double_uniform_location(0) 1616 , m_po_dvec2_arr_uniform_location(0) 1617 , m_po_dvec2_uniform_location(0) 1618 , m_po_dvec3_arr_uniform_location(0) 1619 , m_po_dvec3_uniform_location(0) 1620 , m_po_dvec4_arr_uniform_location(0) 1621 , m_po_dvec4_uniform_location(0) 1622 , m_po_float_arr_uniform_location(0) 1623 , m_po_float_uniform_location(0) 1624 , m_po_int_arr_uniform_location(0) 1625 , m_po_int_uniform_location(0) 1626 , m_po_ivec2_arr_uniform_location(0) 1627 , m_po_ivec2_uniform_location(0) 1628 , m_po_ivec3_arr_uniform_location(0) 1629 , m_po_ivec3_uniform_location(0) 1630 , m_po_ivec4_arr_uniform_location(0) 1631 , m_po_ivec4_uniform_location(0) 1632 , m_po_sampler_uniform_location(0) 1633 , m_po_uint_arr_uniform_location(0) 1634 , m_po_uint_uniform_location(0) 1635 , m_po_uvec2_arr_uniform_location(0) 1636 , m_po_uvec2_uniform_location(0) 1637 , m_po_uvec3_arr_uniform_location(0) 1638 , m_po_uvec3_uniform_location(0) 1639 , m_po_uvec4_arr_uniform_location(0) 1640 , m_po_uvec4_uniform_location(0) 1641 , m_po_vec2_arr_uniform_location(0) 1642 , m_po_vec2_uniform_location(0) 1643 , m_po_vec3_arr_uniform_location(0) 1644 , m_po_vec3_uniform_location(0) 1645 , m_po_vec4_arr_uniform_location(0) 1646 , m_po_vec4_uniform_location(0) 1647 , m_po_id(0) 1648 , m_vs_id(0) 1649 { 1650 /* Left blank intentionally */ 1651 } 1652 1653 /** Deinitializes all GL objects that may have been created during 1654 * test execution. 1655 **/ 1656 void GPUShaderFP64Test1::deinit() 1657 { 1658 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1659 1660 if (m_po_id != 0) 1661 { 1662 gl.deleteProgram(m_po_id); 1663 1664 m_po_id = 0; 1665 } 1666 1667 if (m_vs_id != 0) 1668 { 1669 gl.deleteShader(m_vs_id); 1670 1671 m_vs_id = 0; 1672 } 1673 } 1674 1675 /** Returns a string describing GL API function represented by user-provided enum. 1676 * 1677 * @param func Uniform function to return the string for. 1678 * 1679 * @return As per description. [?] will be returned if the function was not recognized. 1680 **/ 1681 const char* GPUShaderFP64Test1::getUniformFunctionString(_uniform_function func) 1682 { 1683 const char* result = "[?]"; 1684 1685 switch (func) 1686 { 1687 case UNIFORM_FUNCTION_1D: 1688 result = "glUniform1d"; 1689 break; 1690 case UNIFORM_FUNCTION_1DV: 1691 result = "glUniform1dv"; 1692 break; 1693 case UNIFORM_FUNCTION_2D: 1694 result = "glUniform2d"; 1695 break; 1696 case UNIFORM_FUNCTION_2DV: 1697 result = "glUniform2dv"; 1698 break; 1699 case UNIFORM_FUNCTION_3D: 1700 result = "glUniform3d"; 1701 break; 1702 case UNIFORM_FUNCTION_3DV: 1703 result = "glUniform3dv"; 1704 break; 1705 case UNIFORM_FUNCTION_4D: 1706 result = "glUniform4d"; 1707 break; 1708 case UNIFORM_FUNCTION_4DV: 1709 result = "glUniform4dv"; 1710 break; 1711 case UNIFORM_FUNCTION_MATRIX2DV: 1712 result = "glUniformMatrix2dv"; 1713 break; 1714 case UNIFORM_FUNCTION_MATRIX2X3DV: 1715 result = "glUniformMatrix2x3dv"; 1716 break; 1717 case UNIFORM_FUNCTION_MATRIX2X4DV: 1718 result = "glUniformMatrix2x4dv"; 1719 break; 1720 case UNIFORM_FUNCTION_MATRIX3DV: 1721 result = "glUniformMatrix3dv"; 1722 break; 1723 case UNIFORM_FUNCTION_MATRIX3X2DV: 1724 result = "glUniformMatrix3x2dv"; 1725 break; 1726 case UNIFORM_FUNCTION_MATRIX3X4DV: 1727 result = "glUniformMatrix3x4dv"; 1728 break; 1729 case UNIFORM_FUNCTION_MATRIX4DV: 1730 result = "glUniformMatrix4dv"; 1731 break; 1732 case UNIFORM_FUNCTION_MATRIX4X2DV: 1733 result = "glUniformMatrix4x2dv"; 1734 break; 1735 case UNIFORM_FUNCTION_MATRIX4X3DV: 1736 result = "glUniformMatrix4x3dv"; 1737 break; 1738 default: 1739 break; 1740 } 1741 1742 return result; 1743 } 1744 1745 /** Returns name of an uniform bound to user-provided location. 1746 * 1747 * @param location Location of the uniform to return the name for. 1748 * 1749 * @return As per description. [?] will be returned if the location was not 1750 * recognized. 1751 **/ 1752 const char* GPUShaderFP64Test1::getUniformNameForLocation(glw::GLint location) 1753 { 1754 const char* result = "[?]"; 1755 1756 if (location == m_po_bool_arr_uniform_location) 1757 result = "uniform_bool_arr"; 1758 else if (location == m_po_bool_uniform_location) 1759 result = "uniform_bool"; 1760 else if (location == m_po_bvec2_arr_uniform_location) 1761 result = "uniform_bvec2_arr"; 1762 else if (location == m_po_bvec2_uniform_location) 1763 result = "uniform_bvec2"; 1764 else if (location == m_po_bvec3_arr_uniform_location) 1765 result = "uniform_bvec3_arr"; 1766 else if (location == m_po_bvec3_uniform_location) 1767 result = "uniform_bvec3"; 1768 else if (location == m_po_bvec4_arr_uniform_location) 1769 result = "uniform_bvec4_arr"; 1770 else if (location == m_po_bvec4_uniform_location) 1771 result = "uniform_bvec4"; 1772 else if (location == m_po_dmat2_arr_uniform_location) 1773 result = "uniform_dmat2_arr"; 1774 else if (location == m_po_dmat2_uniform_location) 1775 result = "uniform_dmat2"; 1776 else if (location == m_po_dmat2x3_arr_uniform_location) 1777 result = "uniform_dmat2x3_arr"; 1778 else if (location == m_po_dmat2x3_uniform_location) 1779 result = "uniform_dmat2x3"; 1780 else if (location == m_po_dmat2x4_arr_uniform_location) 1781 result = "uniform_dmat2x4_arr"; 1782 else if (location == m_po_dmat2x4_uniform_location) 1783 result = "uniform_dmat2x4"; 1784 else if (location == m_po_dmat3_arr_uniform_location) 1785 result = "uniform_dmat3_arr"; 1786 else if (location == m_po_dmat3_uniform_location) 1787 result = "uniform_dmat3"; 1788 else if (location == m_po_dmat3x2_arr_uniform_location) 1789 result = "uniform_dmat3x2_arr"; 1790 else if (location == m_po_dmat3x2_uniform_location) 1791 result = "uniform_dmat3x2"; 1792 else if (location == m_po_dmat3x4_arr_uniform_location) 1793 result = "uniform_dmat3x4_arr"; 1794 else if (location == m_po_dmat3x4_uniform_location) 1795 result = "uniform_dmat3x4"; 1796 else if (location == m_po_dmat4_arr_uniform_location) 1797 result = "uniform_dmat4_arr"; 1798 else if (location == m_po_dmat4_uniform_location) 1799 result = "uniform_dmat4"; 1800 else if (location == m_po_dmat4x2_arr_uniform_location) 1801 result = "uniform_dmat4x2_arr"; 1802 else if (location == m_po_dmat4x2_uniform_location) 1803 result = "uniform_dmat4x2"; 1804 else if (location == m_po_dmat4x3_arr_uniform_location) 1805 result = "uniform_dmat4x3_arr"; 1806 else if (location == m_po_dmat4x3_uniform_location) 1807 result = "uniform_dmat4x3"; 1808 else if (location == m_po_double_arr_uniform_location) 1809 result = "uniform_double_arr"; 1810 else if (location == m_po_double_uniform_location) 1811 result = "uniform_double"; 1812 else if (location == m_po_dvec2_arr_uniform_location) 1813 result = "uniform_dvec2_arr"; 1814 else if (location == m_po_dvec2_uniform_location) 1815 result = "uniform_dvec2"; 1816 else if (location == m_po_dvec3_arr_uniform_location) 1817 result = "uniform_dvec3_arr"; 1818 else if (location == m_po_dvec3_uniform_location) 1819 result = "uniform_dvec3"; 1820 else if (location == m_po_dvec4_arr_uniform_location) 1821 result = "uniform_dvec4_arr"; 1822 else if (location == m_po_dvec4_uniform_location) 1823 result = "uniform_dvec4"; 1824 else if (location == m_po_float_arr_uniform_location) 1825 result = "uniform_float_arr"; 1826 else if (location == m_po_float_uniform_location) 1827 result = "uniform_float"; 1828 else if (location == m_po_int_arr_uniform_location) 1829 result = "uniform_int_arr"; 1830 else if (location == m_po_int_uniform_location) 1831 result = "uniform_int"; 1832 else if (location == m_po_ivec2_arr_uniform_location) 1833 result = "uniform_ivec2_arr"; 1834 else if (location == m_po_ivec2_uniform_location) 1835 result = "uniform_ivec2"; 1836 else if (location == m_po_ivec3_arr_uniform_location) 1837 result = "uniform_ivec3_arr"; 1838 else if (location == m_po_ivec3_uniform_location) 1839 result = "uniform_ivec3"; 1840 else if (location == m_po_ivec4_arr_uniform_location) 1841 result = "uniform_ivec4_arr"; 1842 else if (location == m_po_ivec4_uniform_location) 1843 result = "uniform_ivec4"; 1844 else if (location == m_po_uint_arr_uniform_location) 1845 result = "uniform_uint_arr"; 1846 else if (location == m_po_uint_uniform_location) 1847 result = "uniform_uint"; 1848 else if (location == m_po_uvec2_arr_uniform_location) 1849 result = "uniform_uvec2_arr"; 1850 else if (location == m_po_uvec2_uniform_location) 1851 result = "uniform_uvec2"; 1852 else if (location == m_po_uvec3_arr_uniform_location) 1853 result = "uniform_uvec3_arr"; 1854 else if (location == m_po_uvec3_uniform_location) 1855 result = "uniform_uvec3"; 1856 else if (location == m_po_uvec4_arr_uniform_location) 1857 result = "uniform_uvec4_arr"; 1858 else if (location == m_po_uvec4_uniform_location) 1859 result = "uniform_uvec4"; 1860 else if (location == m_po_vec2_arr_uniform_location) 1861 result = "uniform_vec2_arr"; 1862 else if (location == m_po_vec2_uniform_location) 1863 result = "uniform_vec2"; 1864 else if (location == m_po_vec3_arr_uniform_location) 1865 result = "uniform_vec3_arr"; 1866 else if (location == m_po_vec3_uniform_location) 1867 result = "uniform_vec3"; 1868 else if (location == m_po_vec4_arr_uniform_location) 1869 result = "uniform_vec4_arr"; 1870 else if (location == m_po_vec4_uniform_location) 1871 result = "uniform_vec4"; 1872 1873 return result; 1874 } 1875 1876 /** Initializes all GL objects required to run the test. Also extracts locations of all 1877 * uniforms used by the test. 1878 * 1879 * This function can throw a TestError exception if the implementation misbehaves. 1880 */ 1881 void GPUShaderFP64Test1::initTest() 1882 { 1883 glw::GLint compile_status = GL_FALSE; 1884 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1885 glw::GLint link_status = GL_FALSE; 1886 1887 /* Set up a program object using all new double-precision types */ 1888 const char* vs_body = 1889 "#version 400\n" 1890 "\n" 1891 "uniform bool uniform_bool;\n" 1892 "uniform bvec2 uniform_bvec2;\n" 1893 "uniform bvec3 uniform_bvec3;\n" 1894 "uniform bvec4 uniform_bvec4;\n" 1895 "uniform dmat2 uniform_dmat2;\n" 1896 "uniform dmat2x3 uniform_dmat2x3;\n" 1897 "uniform dmat2x4 uniform_dmat2x4;\n" 1898 "uniform dmat3 uniform_dmat3;\n" 1899 "uniform dmat3x2 uniform_dmat3x2;\n" 1900 "uniform dmat3x4 uniform_dmat3x4;\n" 1901 "uniform dmat4 uniform_dmat4;\n" 1902 "uniform dmat4x2 uniform_dmat4x2;\n" 1903 "uniform dmat4x3 uniform_dmat4x3;\n" 1904 "uniform double uniform_double;\n" 1905 "uniform dvec2 uniform_dvec2;\n" 1906 "uniform dvec3 uniform_dvec3;\n" 1907 "uniform dvec4 uniform_dvec4;\n" 1908 "uniform float uniform_float;\n" 1909 "uniform int uniform_int;\n" 1910 "uniform ivec2 uniform_ivec2;\n" 1911 "uniform ivec3 uniform_ivec3;\n" 1912 "uniform ivec4 uniform_ivec4;\n" 1913 "uniform sampler2D uniform_sampler;\n" 1914 "uniform uint uniform_uint;\n" 1915 "uniform uvec2 uniform_uvec2;\n" 1916 "uniform uvec3 uniform_uvec3;\n" 1917 "uniform uvec4 uniform_uvec4;\n" 1918 "uniform vec2 uniform_vec2;\n" 1919 "uniform vec3 uniform_vec3;\n" 1920 "uniform vec4 uniform_vec4;\n" 1921 "uniform bool uniform_bool_arr [2];\n" 1922 "uniform bvec2 uniform_bvec2_arr [2];\n" 1923 "uniform bvec3 uniform_bvec3_arr [2];\n" 1924 "uniform bvec4 uniform_bvec4_arr [2];\n" 1925 "uniform dmat2 uniform_dmat2_arr [2];\n" 1926 "uniform dmat2x3 uniform_dmat2x3_arr[2];\n" 1927 "uniform dmat2x4 uniform_dmat2x4_arr[2];\n" 1928 "uniform dmat3 uniform_dmat3_arr [2];\n" 1929 "uniform dmat3x2 uniform_dmat3x2_arr[2];\n" 1930 "uniform dmat3x4 uniform_dmat3x4_arr[2];\n" 1931 "uniform dmat4 uniform_dmat4_arr [2];\n" 1932 "uniform dmat4x2 uniform_dmat4x2_arr[2];\n" 1933 "uniform dmat4x3 uniform_dmat4x3_arr[2];\n" 1934 "uniform double uniform_double_arr [2];\n" 1935 "uniform dvec2 uniform_dvec2_arr [2];\n" 1936 "uniform dvec3 uniform_dvec3_arr [2];\n" 1937 "uniform dvec4 uniform_dvec4_arr [2];\n" 1938 "uniform float uniform_float_arr [2];\n" 1939 "uniform int uniform_int_arr [2];\n" 1940 "uniform ivec2 uniform_ivec2_arr [2];\n" 1941 "uniform ivec3 uniform_ivec3_arr [2];\n" 1942 "uniform ivec4 uniform_ivec4_arr [2];\n" 1943 "uniform uint uniform_uint_arr [2];\n" 1944 "uniform uvec2 uniform_uvec2_arr [2];\n" 1945 "uniform uvec3 uniform_uvec3_arr [2];\n" 1946 "uniform uvec4 uniform_uvec4_arr [2];\n" 1947 "uniform vec2 uniform_vec2_arr [2];\n" 1948 "uniform vec3 uniform_vec3_arr [2];\n" 1949 "uniform vec4 uniform_vec4_arr [2];\n" 1950 "\n" 1951 "void main()\n" 1952 "{\n" 1953 " gl_Position = vec4(0) + texture(uniform_sampler, vec2(0) );\n" 1954 "\n" 1955 " if (uniform_bool && uniform_bvec2.y && uniform_bvec3.z && uniform_bvec4.w &&\n" 1956 " uniform_bool_arr[1] && uniform_bvec2_arr[1].y && uniform_bvec3_arr[1].z && uniform_bvec4_arr[1].w)\n" 1957 " {\n" 1958 " double sum = uniform_dmat2 [0].x + uniform_dmat2x3 [0].x + uniform_dmat2x4 [0].x +\n" 1959 " uniform_dmat3 [0].x + uniform_dmat3x2 [0].x + uniform_dmat3x4 [0].x +\n" 1960 " uniform_dmat4 [0].x + uniform_dmat4x2 [0].x + uniform_dmat4x3 [0].x +\n" 1961 " uniform_dmat2_arr[0][0].x + uniform_dmat2x3_arr[0][0].x + uniform_dmat2x4_arr[0][0].x +\n" 1962 " uniform_dmat3_arr[0][0].x + uniform_dmat3x2_arr[0][0].x + uniform_dmat3x4_arr[0][0].x +\n" 1963 " uniform_dmat4_arr[0][0].x + uniform_dmat4x2_arr[0][0].x + uniform_dmat4x3_arr[0][0].x +\n" 1964 " uniform_double + uniform_double_arr [0] +\n" 1965 " uniform_dvec2.x + uniform_dvec3.x + uniform_dvec4.x +\n" 1966 " uniform_dvec2_arr[0].x + uniform_dvec3_arr[0].x + uniform_dvec4_arr[0].x;\n" 1967 " int sum2 = uniform_int + uniform_ivec2.x + uniform_ivec3.x +\n" 1968 " uniform_ivec4.x + uniform_ivec2_arr[0].x + uniform_ivec3_arr[0].x +\n" 1969 " uniform_ivec4_arr[0].x + uniform_int_arr[0];\n" 1970 " uint sum3 = uniform_uint + uniform_uvec2.x + uniform_uvec3.x +\n" 1971 " uniform_uvec4.x + uniform_uint_arr[0] + uniform_uvec2_arr[0].x +\n" 1972 " uniform_uvec3_arr[0].x + uniform_uvec4_arr[0].x;\n" 1973 " float sum4 = uniform_float + uniform_float_arr[0] + \n" 1974 " uniform_vec2.x + uniform_vec2_arr[0].x + \n" 1975 " uniform_vec3.x + uniform_vec3_arr[0].x + \n" 1976 " uniform_vec4.x + uniform_vec4_arr[0].x;\n" 1977 "\n" 1978 " if (sum * sum4 > intBitsToFloat(sum2) * uintBitsToFloat(sum3) )\n" 1979 " {\n" 1980 " gl_Position = vec4(1);\n" 1981 " }\n" 1982 " }\n" 1983 "}\n"; 1984 1985 m_po_id = gl.createProgram(); 1986 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 1987 1988 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1989 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 1990 1991 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */); 1992 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 1993 1994 gl.compileShader(m_vs_id); 1995 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 1996 1997 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); 1998 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 1999 2000 if (compile_status != GL_TRUE) 2001 { 2002 TCU_FAIL("Shader compilation failed."); 2003 } 2004 2005 gl.attachShader(m_po_id, m_vs_id); 2006 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 2007 2008 gl.linkProgram(m_po_id); 2009 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 2010 2011 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 2012 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 2013 2014 if (link_status != GL_TRUE) 2015 { 2016 TCU_FAIL("Program linking failed."); 2017 } 2018 2019 m_po_bool_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bool_arr[0]"); 2020 m_po_bool_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bool"); 2021 m_po_bvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec2_arr[0]"); 2022 m_po_bvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec2"); 2023 m_po_bvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec3_arr[0]"); 2024 m_po_bvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec3"); 2025 m_po_bvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec4_arr[0]"); 2026 m_po_bvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec4"); 2027 m_po_dmat2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2_arr[0]"); 2028 m_po_dmat2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2"); 2029 m_po_dmat2x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3_arr[0]"); 2030 m_po_dmat2x3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3"); 2031 m_po_dmat2x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4_arr[0]"); 2032 m_po_dmat2x4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4"); 2033 m_po_dmat3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3_arr[0]"); 2034 m_po_dmat3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3"); 2035 m_po_dmat3x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2_arr[0]"); 2036 m_po_dmat3x2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2"); 2037 m_po_dmat3x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4_arr[0]"); 2038 m_po_dmat3x4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4"); 2039 m_po_dmat4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4_arr[0]"); 2040 m_po_dmat4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4"); 2041 m_po_dmat4x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2_arr[0]"); 2042 m_po_dmat4x2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2"); 2043 m_po_dmat4x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3_arr[0]"); 2044 m_po_dmat4x3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3"); 2045 m_po_double_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_double_arr[0]"); 2046 m_po_double_uniform_location = gl.getUniformLocation(m_po_id, "uniform_double"); 2047 m_po_dvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec2_arr[0]"); 2048 m_po_dvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec2"); 2049 m_po_dvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec3_arr[0]"); 2050 m_po_dvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec3"); 2051 m_po_dvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec4_arr[0]"); 2052 m_po_dvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec4"); 2053 m_po_float_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_float_arr[0]"); 2054 m_po_float_uniform_location = gl.getUniformLocation(m_po_id, "uniform_float"); 2055 m_po_int_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_int_arr[0]"); 2056 m_po_int_uniform_location = gl.getUniformLocation(m_po_id, "uniform_int"); 2057 m_po_ivec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec2_arr[0]"); 2058 m_po_ivec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec2"); 2059 m_po_ivec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec3_arr[0]"); 2060 m_po_ivec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec3"); 2061 m_po_ivec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec4_arr[0]"); 2062 m_po_ivec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec4"); 2063 m_po_sampler_uniform_location = gl.getUniformLocation(m_po_id, "uniform_sampler"); 2064 m_po_uint_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uint_arr[0]"); 2065 m_po_uint_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uint"); 2066 m_po_uvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec2_arr[0]"); 2067 m_po_uvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec2"); 2068 m_po_uvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec3_arr[0]"); 2069 m_po_uvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec3"); 2070 m_po_uvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec4_arr[0]"); 2071 m_po_uvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec4"); 2072 m_po_vec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec2_arr[0]"); 2073 m_po_vec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec2"); 2074 m_po_vec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec3_arr[0]"); 2075 m_po_vec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec3"); 2076 m_po_vec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec4_arr[0]"); 2077 m_po_vec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec4"); 2078 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed."); 2079 2080 if (m_po_bool_arr_uniform_location == -1 || m_po_bool_uniform_location == -1 || 2081 m_po_bvec2_arr_uniform_location == -1 || m_po_bvec2_uniform_location == -1 || 2082 m_po_bvec3_arr_uniform_location == -1 || m_po_bvec3_uniform_location == -1 || 2083 m_po_bvec4_arr_uniform_location == -1 || m_po_bvec4_uniform_location == -1 || 2084 m_po_dmat2_arr_uniform_location == -1 || m_po_dmat2_uniform_location == -1 || 2085 m_po_dmat2x3_arr_uniform_location == -1 || m_po_dmat2x3_uniform_location == -1 || 2086 m_po_dmat2x4_arr_uniform_location == -1 || m_po_dmat2x4_uniform_location == -1 || 2087 m_po_dmat3_arr_uniform_location == -1 || m_po_dmat3_uniform_location == -1 || 2088 m_po_dmat3x2_arr_uniform_location == -1 || m_po_dmat3x2_uniform_location == -1 || 2089 m_po_dmat3x4_arr_uniform_location == -1 || m_po_dmat3x4_uniform_location == -1 || 2090 m_po_dmat4_arr_uniform_location == -1 || m_po_dmat4_uniform_location == -1 || 2091 m_po_dmat4x2_arr_uniform_location == -1 || m_po_dmat4x2_uniform_location == -1 || 2092 m_po_dmat4x3_arr_uniform_location == -1 || m_po_dmat4x3_uniform_location == -1 || 2093 m_po_double_arr_uniform_location == -1 || m_po_double_uniform_location == -1 || 2094 m_po_dvec2_arr_uniform_location == -1 || m_po_dvec2_uniform_location == -1 || 2095 m_po_dvec3_arr_uniform_location == -1 || m_po_dvec3_uniform_location == -1 || 2096 m_po_dvec4_arr_uniform_location == -1 || m_po_dvec4_uniform_location == -1 || 2097 m_po_float_arr_uniform_location == -1 || m_po_float_uniform_location == -1 || 2098 m_po_int_arr_uniform_location == -1 || m_po_int_uniform_location == -1 || 2099 m_po_ivec2_arr_uniform_location == -1 || m_po_ivec2_uniform_location == -1 || 2100 m_po_ivec3_arr_uniform_location == -1 || m_po_ivec3_uniform_location == -1 || 2101 m_po_ivec4_arr_uniform_location == -1 || m_po_ivec4_uniform_location == -1 || 2102 m_po_sampler_uniform_location == -1 || m_po_uint_arr_uniform_location == -1 || 2103 m_po_uint_uniform_location == -1 || m_po_uvec2_arr_uniform_location == -1 || 2104 m_po_uvec2_uniform_location == -1 || m_po_uvec3_arr_uniform_location == -1 || 2105 m_po_uvec3_uniform_location == -1 || m_po_uvec4_arr_uniform_location == -1 || 2106 m_po_uvec4_uniform_location == -1 || m_po_vec2_arr_uniform_location == -1 || m_po_vec2_uniform_location == -1 || 2107 m_po_vec3_arr_uniform_location == -1 || m_po_vec3_uniform_location == -1 || 2108 m_po_vec4_arr_uniform_location == -1 || m_po_vec4_uniform_location == -1) 2109 { 2110 TCU_FAIL("At last one of the required uniforms is considered inactive."); 2111 } 2112 } 2113 2114 /** Tells wheter uniform at user-specified location represents a double-precision 2115 * matrix uniform. 2116 * 2117 * @param uniform_location Location of the uniform to use for the query. 2118 * 2119 * @return Requested information. 2120 **/ 2121 bool GPUShaderFP64Test1::isMatrixUniform(glw::GLint uniform_location) 2122 { 2123 return (uniform_location == m_po_dmat2_uniform_location || uniform_location == m_po_dmat2x3_uniform_location || 2124 uniform_location == m_po_dmat2x4_uniform_location || uniform_location == m_po_dmat3_uniform_location || 2125 uniform_location == m_po_dmat3x2_uniform_location || uniform_location == m_po_dmat3x4_uniform_location || 2126 uniform_location == m_po_dmat4_uniform_location || uniform_location == m_po_dmat4x2_uniform_location || 2127 uniform_location == m_po_dmat4x3_uniform_location); 2128 } 2129 2130 /** Tells whether user-specified uniform function corresponds to one of the 2131 * functions in glUniformMatrix*() class. 2132 * 2133 * @param func Uniform function enum to use for the query. 2134 * 2135 * @return true if the specified enum represents one of the glUniformMatrix*() functions, 2136 * false otherwise. 2137 **/ 2138 bool GPUShaderFP64Test1::isMatrixUniformFunction(_uniform_function func) 2139 { 2140 return (func == UNIFORM_FUNCTION_MATRIX2DV || func == UNIFORM_FUNCTION_MATRIX2X3DV || 2141 func == UNIFORM_FUNCTION_MATRIX2X4DV || func == UNIFORM_FUNCTION_MATRIX3DV || 2142 func == UNIFORM_FUNCTION_MATRIX3X2DV || func == UNIFORM_FUNCTION_MATRIX3X4DV || 2143 func == UNIFORM_FUNCTION_MATRIX4DV || func == UNIFORM_FUNCTION_MATRIX4X2DV || 2144 func == UNIFORM_FUNCTION_MATRIX4X3DV); 2145 } 2146 2147 /** Executes test iteration. 2148 * 2149 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 2150 */ 2151 tcu::TestNode::IterateResult GPUShaderFP64Test1::iterate() 2152 { 2153 /* Do not execute the test if GL_ARB_texture_view is not supported */ 2154 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 2155 { 2156 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported."); 2157 } 2158 2159 /* Initialize all ES objects required to run all the checks */ 2160 initTest(); 2161 2162 /* Make sure GL_INVALID_OPERATION is generated by glUniform*() and 2163 * glUniformMatrix*() functions if there is no current program object. 2164 */ 2165 m_has_test_passed &= verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO(); 2166 2167 /* Make sure GL_INVALID_OPERATION is generated by glUniform*() if 2168 * the size of the uniform variable declared in the shader does not 2169 * match the size indicated by the command. 2170 */ 2171 m_has_test_passed &= verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions(); 2172 2173 /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and 2174 * glUniformMatrix*() are used to load a uniform variable of type 2175 * bool, bvec2, bvec3, bvec4, float, int, ivec2, ivec3, ivec4, 2176 * unsigned int, uvec2, uvec3, uvec4, vec2, vec3, vec4 or an array 2177 * of these. 2178 */ 2179 m_has_test_passed &= verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions(); 2180 2181 /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and 2182 * glUniformMatrix*() are used to load incompatible double-typed 2183 * uniforms, as presented below: 2184 * 2185 * I. double-typed uniform configured by glUniform2d(); 2186 * II. double-typed uniform configured by glUniform3d(); 2187 * III. double-typed uniform configured by glUniform4d(); 2188 * IV. double-typed uniform configured by glUniformMatrix*(); 2189 * V. dvec2-typed uniform configured by glUniform1d(); 2190 * VI. dvec2-typed uniform configured by glUniform3d(); 2191 * VII. dvec2-typed uniform configured by glUniform4d(); 2192 * VIII. dvec2-typed uniform configured by glUniformMatrix*(); 2193 * 2194 * (etc.) 2195 * 2196 */ 2197 m_has_test_passed &= verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions(); 2198 2199 /* Make sure GL_INVALID_OPERATION is generated if <location> of 2200 * glUniform*() and glUniformMatrix*() is an invalid uniform 2201 * location for the current program object and location is not 2202 * equal to -1. 2203 */ 2204 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation(); 2205 2206 /* Make sure GL_INVALID_VALUE is generated if <count> of 2207 * glUniform*() (*dv() functions only) and glUniformMatrix*() is 2208 * negative. 2209 */ 2210 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount(); 2211 2212 /* Make sure GL_INVALID_OPERATION is generated if <count> of 2213 * glUniform*() (*dv() functions only) and glUniformMatrix*() is 2214 * greater than 1 and the indicated uniform variable is not an 2215 * array variable. 2216 */ 2217 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount(); 2218 2219 /* Make sure GL_INVALID_OPERATION is generated if a sampler is 2220 * loaded by glUniform*() and glUniformMatrix*(). 2221 */ 2222 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers(); 2223 2224 /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and 2225 * glUniformMatrix*() is used to load values for uniforms of 2226 * boolean types. 2227 */ 2228 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans(); 2229 2230 if (m_has_test_passed) 2231 { 2232 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2233 } 2234 else 2235 { 2236 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2237 } 2238 2239 return STOP; 2240 } 2241 2242 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or 2243 * glUniformMatrix*dv() functions is used to load a boolean uniform. 2244 * 2245 * @return true if the implementation was found to behave as expected, false otherwise. 2246 **/ 2247 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans() 2248 { 2249 const double double_data[] = { 2250 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 2251 }; 2252 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2253 bool result = true; 2254 glw::GLint uniform_locations[] = { m_po_bool_arr_uniform_location, m_po_bool_uniform_location, 2255 m_po_bvec2_arr_uniform_location, m_po_bvec2_uniform_location, 2256 m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location, 2257 m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location }; 2258 const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]); 2259 2260 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT; 2261 ++n_uniform_function) 2262 { 2263 const _uniform_function uniform_function = (_uniform_function)n_uniform_function; 2264 2265 for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location) 2266 { 2267 const glw::GLint uniform_location = uniform_locations[n_uniform_location]; 2268 2269 switch (uniform_function) 2270 { 2271 case UNIFORM_FUNCTION_1D: 2272 gl.uniform1d(uniform_location, 0.0); 2273 break; 2274 case UNIFORM_FUNCTION_2D: 2275 gl.uniform2d(uniform_location, 0.0, 1.0); 2276 break; 2277 case UNIFORM_FUNCTION_3D: 2278 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0); 2279 break; 2280 case UNIFORM_FUNCTION_4D: 2281 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0); 2282 break; 2283 2284 case UNIFORM_FUNCTION_1DV: 2285 gl.uniform1dv(uniform_location, 1 /* count */, double_data); 2286 break; 2287 case UNIFORM_FUNCTION_2DV: 2288 gl.uniform2dv(uniform_location, 1 /* count */, double_data); 2289 break; 2290 case UNIFORM_FUNCTION_3DV: 2291 gl.uniform3dv(uniform_location, 1 /* count */, double_data); 2292 break; 2293 case UNIFORM_FUNCTION_4DV: 2294 gl.uniform4dv(uniform_location, 1 /* count */, double_data); 2295 break; 2296 2297 case UNIFORM_FUNCTION_MATRIX2DV: 2298 gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2299 break; 2300 case UNIFORM_FUNCTION_MATRIX2X3DV: 2301 gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2302 break; 2303 case UNIFORM_FUNCTION_MATRIX2X4DV: 2304 gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2305 break; 2306 case UNIFORM_FUNCTION_MATRIX3DV: 2307 gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2308 break; 2309 case UNIFORM_FUNCTION_MATRIX3X2DV: 2310 gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2311 break; 2312 case UNIFORM_FUNCTION_MATRIX3X4DV: 2313 gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2314 break; 2315 case UNIFORM_FUNCTION_MATRIX4DV: 2316 gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2317 break; 2318 case UNIFORM_FUNCTION_MATRIX4X2DV: 2319 gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2320 break; 2321 case UNIFORM_FUNCTION_MATRIX4X3DV: 2322 gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2323 break; 2324 2325 default: 2326 { 2327 TCU_FAIL("Unrecognized uniform function"); 2328 } 2329 } 2330 2331 /* Make sure GL_INVALID_OPERATION was generated by the call */ 2332 const glw::GLenum error_code = gl.getError(); 2333 2334 if (error_code != GL_INVALID_OPERATION) 2335 { 2336 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) 2337 << "() did not generate an error" 2338 " when applied against a boolean uniform." 2339 << tcu::TestLog::EndMessage; 2340 2341 result = false; 2342 } 2343 } /* for (all bool uniforms) */ 2344 } /* for (all uniform functions) */ 2345 2346 return result; 2347 } 2348 2349 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or 2350 * glUniformMatrix*dv() functions is used to load a sampler2D uniform. 2351 * 2352 * @return true if the implementation was found to behave as expected, false otherwise. 2353 **/ 2354 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers() 2355 { 2356 const double double_data[] = { 2357 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 2358 }; 2359 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2360 bool result = true; 2361 2362 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT; 2363 ++n_uniform_function) 2364 { 2365 _uniform_function uniform_function = (_uniform_function)n_uniform_function; 2366 2367 switch (uniform_function) 2368 { 2369 case UNIFORM_FUNCTION_1D: 2370 gl.uniform1d(m_po_sampler_uniform_location, 0.0); 2371 break; 2372 case UNIFORM_FUNCTION_2D: 2373 gl.uniform2d(m_po_sampler_uniform_location, 0.0, 1.0); 2374 break; 2375 case UNIFORM_FUNCTION_3D: 2376 gl.uniform3d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0); 2377 break; 2378 case UNIFORM_FUNCTION_4D: 2379 gl.uniform4d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0, 3.0); 2380 break; 2381 2382 case UNIFORM_FUNCTION_1DV: 2383 gl.uniform1dv(m_po_sampler_uniform_location, 1 /* count */, double_data); 2384 break; 2385 case UNIFORM_FUNCTION_2DV: 2386 gl.uniform2dv(m_po_sampler_uniform_location, 1 /* count */, double_data); 2387 break; 2388 case UNIFORM_FUNCTION_3DV: 2389 gl.uniform3dv(m_po_sampler_uniform_location, 1 /* count */, double_data); 2390 break; 2391 case UNIFORM_FUNCTION_4DV: 2392 gl.uniform4dv(m_po_sampler_uniform_location, 1 /* count */, double_data); 2393 break; 2394 2395 case UNIFORM_FUNCTION_MATRIX2DV: 2396 gl.uniformMatrix2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2397 break; 2398 case UNIFORM_FUNCTION_MATRIX2X3DV: 2399 gl.uniformMatrix2x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2400 break; 2401 case UNIFORM_FUNCTION_MATRIX2X4DV: 2402 gl.uniformMatrix2x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2403 break; 2404 case UNIFORM_FUNCTION_MATRIX3DV: 2405 gl.uniformMatrix3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2406 break; 2407 case UNIFORM_FUNCTION_MATRIX3X2DV: 2408 gl.uniformMatrix3x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2409 break; 2410 case UNIFORM_FUNCTION_MATRIX3X4DV: 2411 gl.uniformMatrix3x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2412 break; 2413 case UNIFORM_FUNCTION_MATRIX4DV: 2414 gl.uniformMatrix4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2415 break; 2416 case UNIFORM_FUNCTION_MATRIX4X2DV: 2417 gl.uniformMatrix4x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2418 break; 2419 case UNIFORM_FUNCTION_MATRIX4X3DV: 2420 gl.uniformMatrix4x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2421 break; 2422 2423 default: 2424 { 2425 TCU_FAIL("Unrecognized uniform function"); 2426 } 2427 } 2428 2429 /* Make sure GL_INVALID_OPERATION was generated by the call */ 2430 const glw::GLenum error_code = gl.getError(); 2431 2432 if (error_code != GL_INVALID_OPERATION) 2433 { 2434 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) 2435 << "() did not generate an error" 2436 " when applied against a sampler uniform." 2437 << tcu::TestLog::EndMessage; 2438 2439 result = false; 2440 } 2441 } /* for (all uniform functions) */ 2442 2443 return result; 2444 } 2445 2446 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*dv() or 2447 * glUniformMatrix*dv() functions is used to load a compatible uniform using an 2448 * invalid <count> argument. 2449 * 2450 * @return true if the implementation was found to behave as expected, false otherwise. 2451 **/ 2452 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount() 2453 { 2454 const glw::GLdouble double_values[16] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 2455 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 }; 2456 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2457 bool result = true; 2458 const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV, UNIFORM_FUNCTION_2DV, 2459 UNIFORM_FUNCTION_3DV, UNIFORM_FUNCTION_4DV, 2460 UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV, 2461 UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV, 2462 UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV, 2463 UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV, 2464 UNIFORM_FUNCTION_MATRIX4X3DV }; 2465 const glw::GLint uniforms[] = { 2466 m_po_bool_uniform_location, m_po_bvec2_uniform_location, m_po_bvec3_uniform_location, 2467 m_po_bvec4_uniform_location, m_po_dmat2_uniform_location, m_po_dmat2x3_uniform_location, 2468 m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location, m_po_dmat3x2_uniform_location, 2469 m_po_dmat3x4_uniform_location, m_po_dmat4_uniform_location, m_po_dmat4x2_uniform_location, 2470 m_po_dmat4x3_uniform_location, m_po_double_uniform_location, m_po_dvec2_uniform_location, 2471 m_po_dvec3_uniform_location, m_po_dvec4_uniform_location, m_po_float_uniform_location, 2472 m_po_int_uniform_location, m_po_ivec2_uniform_location, m_po_ivec3_uniform_location, 2473 m_po_ivec4_uniform_location, m_po_uint_uniform_location, m_po_uvec2_uniform_location, 2474 m_po_uvec3_uniform_location, m_po_uvec4_uniform_location, m_po_vec2_uniform_location, 2475 m_po_vec3_uniform_location, m_po_vec4_uniform_location 2476 }; 2477 2478 const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]); 2479 const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]); 2480 2481 for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function) 2482 { 2483 _uniform_function uniform_function = uniform_functions[n_uniform_function]; 2484 2485 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform) 2486 { 2487 glw::GLint uniform_location = uniforms[n_uniform]; 2488 2489 /* Make sure we only use glUniformMatrix*() functions with matrix uniforms, 2490 * and glUniform*() functions with vector uniforms. 2491 */ 2492 bool is_matrix_uniform = isMatrixUniform(uniform_location); 2493 2494 if (((false == is_matrix_uniform) && (true == isMatrixUniformFunction(uniform_function))) || 2495 ((true == is_matrix_uniform) && (false == isMatrixUniformFunction(uniform_function)))) 2496 { 2497 continue; 2498 } 2499 2500 /* Issue the call with an invalid <count> argument */ 2501 switch (uniform_function) 2502 { 2503 case UNIFORM_FUNCTION_1DV: 2504 gl.uniform1dv(uniform_location, 2, double_values); 2505 break; 2506 case UNIFORM_FUNCTION_2DV: 2507 gl.uniform2dv(uniform_location, 2, double_values); 2508 break; 2509 case UNIFORM_FUNCTION_3DV: 2510 gl.uniform3dv(uniform_location, 2, double_values); 2511 break; 2512 case UNIFORM_FUNCTION_4DV: 2513 gl.uniform4dv(uniform_location, 2, double_values); 2514 break; 2515 case UNIFORM_FUNCTION_MATRIX2DV: 2516 gl.uniformMatrix2dv(uniform_location, 2, GL_FALSE, double_values); 2517 break; 2518 case UNIFORM_FUNCTION_MATRIX2X3DV: 2519 gl.uniformMatrix2x3dv(uniform_location, 2, GL_FALSE, double_values); 2520 break; 2521 case UNIFORM_FUNCTION_MATRIX2X4DV: 2522 gl.uniformMatrix2x4dv(uniform_location, 2, GL_FALSE, double_values); 2523 break; 2524 case UNIFORM_FUNCTION_MATRIX3DV: 2525 gl.uniformMatrix3dv(uniform_location, 2, GL_FALSE, double_values); 2526 break; 2527 case UNIFORM_FUNCTION_MATRIX3X2DV: 2528 gl.uniformMatrix3x2dv(uniform_location, 2, GL_FALSE, double_values); 2529 break; 2530 case UNIFORM_FUNCTION_MATRIX3X4DV: 2531 gl.uniformMatrix3x4dv(uniform_location, 2, GL_FALSE, double_values); 2532 break; 2533 case UNIFORM_FUNCTION_MATRIX4DV: 2534 gl.uniformMatrix4dv(uniform_location, 2, GL_FALSE, double_values); 2535 break; 2536 case UNIFORM_FUNCTION_MATRIX4X2DV: 2537 gl.uniformMatrix4x2dv(uniform_location, 2, GL_FALSE, double_values); 2538 break; 2539 case UNIFORM_FUNCTION_MATRIX4X3DV: 2540 gl.uniformMatrix4x3dv(uniform_location, 2, GL_FALSE, double_values); 2541 break; 2542 2543 default: 2544 { 2545 TCU_FAIL("Unrecognized uniform function"); 2546 } 2547 } /* switch (uniform_function) */ 2548 2549 /* Make sure GL_INVALID_VALUE was generated */ 2550 glw::GLenum error_code = gl.getError(); 2551 2552 if (error_code != GL_INVALID_OPERATION) 2553 { 2554 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) 2555 << "() " 2556 "was called with an invalid count argument but did not generate a " 2557 "GL_INVALID_OPERATION error" 2558 << tcu::TestLog::EndMessage; 2559 2560 result = false; 2561 } 2562 } /* for (all non-arrayed uniforms) */ 2563 } /* for (all uniform functions) */ 2564 2565 return result; 2566 } 2567 2568 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or 2569 * glUniformMatrix*dv() functions is used to load an uniform at an invalid location. 2570 * 2571 * @return true if the implementation was found to behave as expected, false otherwise. 2572 **/ 2573 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation() 2574 { 2575 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2576 bool result = true; 2577 2578 /* Find the largest valid uniform location */ 2579 const glw::GLint uniform_locations[] = { 2580 m_po_bool_arr_uniform_location, m_po_bool_uniform_location, m_po_bvec2_arr_uniform_location, 2581 m_po_bvec2_uniform_location, m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location, 2582 m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location, m_po_dmat2_arr_uniform_location, 2583 m_po_dmat2_uniform_location, m_po_dmat2x3_arr_uniform_location, m_po_dmat2x3_uniform_location, 2584 m_po_dmat2x4_arr_uniform_location, m_po_dmat2x4_uniform_location, m_po_dmat3_arr_uniform_location, 2585 m_po_dmat3_uniform_location, m_po_dmat3x2_arr_uniform_location, m_po_dmat3x2_uniform_location, 2586 m_po_dmat3x4_arr_uniform_location, m_po_dmat3x4_uniform_location, m_po_dmat4_arr_uniform_location, 2587 m_po_dmat4_uniform_location, m_po_dmat4x2_arr_uniform_location, m_po_dmat4x2_uniform_location, 2588 m_po_dmat4x3_arr_uniform_location, m_po_dmat4x3_uniform_location, m_po_double_arr_uniform_location, 2589 m_po_double_uniform_location, m_po_dvec2_arr_uniform_location, m_po_dvec2_uniform_location, 2590 m_po_dvec3_arr_uniform_location, m_po_dvec3_uniform_location, m_po_dvec4_arr_uniform_location, 2591 m_po_dvec4_uniform_location, m_po_float_arr_uniform_location, m_po_float_uniform_location, 2592 m_po_int_arr_uniform_location, m_po_int_uniform_location, m_po_ivec2_arr_uniform_location, 2593 m_po_ivec2_uniform_location, m_po_ivec3_arr_uniform_location, m_po_ivec3_uniform_location, 2594 m_po_ivec4_arr_uniform_location, m_po_ivec4_uniform_location, m_po_uint_arr_uniform_location, 2595 m_po_uint_uniform_location, m_po_uvec2_arr_uniform_location, m_po_uvec2_uniform_location, 2596 m_po_uvec3_arr_uniform_location, m_po_uvec3_uniform_location, m_po_uvec4_arr_uniform_location, 2597 m_po_uvec4_uniform_location, m_po_vec2_arr_uniform_location, m_po_vec2_uniform_location, 2598 m_po_vec3_arr_uniform_location, m_po_vec3_uniform_location, m_po_vec4_arr_uniform_location, 2599 m_po_vec4_uniform_location 2600 }; 2601 const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]); 2602 glw::GLint valid_uniform_location = -1; 2603 2604 for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location) 2605 { 2606 glw::GLint uniform_location = uniform_locations[n_uniform_location]; 2607 2608 if (uniform_location > valid_uniform_location) 2609 { 2610 valid_uniform_location = uniform_location; 2611 } 2612 } /* for (all uniform locations) */ 2613 2614 /* Iterate through all uniform functions and make sure GL_INVALID_OPERATION error is always generated 2615 * for invalid uniform location that is != -1 2616 */ 2617 const double double_data[] = { 2618 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 2619 }; 2620 const glw::GLint invalid_uniform_location = valid_uniform_location + 1; 2621 2622 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT; 2623 ++n_uniform_function) 2624 { 2625 _uniform_function uniform_function = (_uniform_function)n_uniform_function; 2626 2627 switch (uniform_function) 2628 { 2629 case UNIFORM_FUNCTION_1D: 2630 gl.uniform1d(invalid_uniform_location, 0.0); 2631 break; 2632 case UNIFORM_FUNCTION_2D: 2633 gl.uniform2d(invalid_uniform_location, 0.0, 1.0); 2634 break; 2635 case UNIFORM_FUNCTION_3D: 2636 gl.uniform3d(invalid_uniform_location, 0.0, 1.0, 2.0); 2637 break; 2638 case UNIFORM_FUNCTION_4D: 2639 gl.uniform4d(invalid_uniform_location, 0.0, 1.0, 2.0, 3.0); 2640 break; 2641 2642 case UNIFORM_FUNCTION_1DV: 2643 gl.uniform1dv(invalid_uniform_location, 1 /* count */, double_data); 2644 break; 2645 case UNIFORM_FUNCTION_2DV: 2646 gl.uniform2dv(invalid_uniform_location, 1 /* count */, double_data); 2647 break; 2648 case UNIFORM_FUNCTION_3DV: 2649 gl.uniform3dv(invalid_uniform_location, 1 /* count */, double_data); 2650 break; 2651 case UNIFORM_FUNCTION_4DV: 2652 gl.uniform4dv(invalid_uniform_location, 1 /* count */, double_data); 2653 break; 2654 2655 case UNIFORM_FUNCTION_MATRIX2DV: 2656 gl.uniformMatrix2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2657 break; 2658 case UNIFORM_FUNCTION_MATRIX2X3DV: 2659 gl.uniformMatrix2x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2660 break; 2661 case UNIFORM_FUNCTION_MATRIX2X4DV: 2662 gl.uniformMatrix2x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2663 break; 2664 case UNIFORM_FUNCTION_MATRIX3DV: 2665 gl.uniformMatrix3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2666 break; 2667 case UNIFORM_FUNCTION_MATRIX3X2DV: 2668 gl.uniformMatrix3x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2669 break; 2670 case UNIFORM_FUNCTION_MATRIX3X4DV: 2671 gl.uniformMatrix3x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2672 break; 2673 case UNIFORM_FUNCTION_MATRIX4DV: 2674 gl.uniformMatrix4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2675 break; 2676 case UNIFORM_FUNCTION_MATRIX4X2DV: 2677 gl.uniformMatrix4x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2678 break; 2679 case UNIFORM_FUNCTION_MATRIX4X3DV: 2680 gl.uniformMatrix4x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); 2681 break; 2682 2683 default: 2684 { 2685 TCU_FAIL("Unrecognized uniform function"); 2686 } 2687 } 2688 2689 const glw::GLenum error_code = gl.getError(); 2690 2691 if (error_code != GL_INVALID_OPERATION) 2692 { 2693 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) 2694 << "() did not generate an error" 2695 " when passed an invalid uniform location different from -1." 2696 << tcu::TestLog::EndMessage; 2697 2698 result = false; 2699 } 2700 } /* for (all uniform functions) */ 2701 2702 return result; 2703 } 2704 2705 /** Verifies GL_INVALID_VALUE is generated if any of the glUniform*dv() or 2706 * glUniformMatrix*dv() functions is used to load a compatible uniform using an 2707 * invalid <count> argument of -1. 2708 * 2709 * @return true if the implementation was found to behave as expected, false otherwise. 2710 **/ 2711 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount() 2712 { 2713 const glw::GLdouble double_values[16] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 2714 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 }; 2715 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2716 bool result = true; 2717 const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV, UNIFORM_FUNCTION_2DV, 2718 UNIFORM_FUNCTION_3DV, UNIFORM_FUNCTION_4DV, 2719 UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV, 2720 UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV, 2721 UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV, 2722 UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV, 2723 UNIFORM_FUNCTION_MATRIX4X3DV }; 2724 const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]); 2725 2726 for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function) 2727 { 2728 _uniform_function uniform_function = uniform_functions[n_uniform_function]; 2729 2730 switch (uniform_function) 2731 { 2732 case UNIFORM_FUNCTION_1DV: 2733 gl.uniform1dv(m_po_double_arr_uniform_location, -1, double_values); 2734 break; 2735 case UNIFORM_FUNCTION_2DV: 2736 gl.uniform2dv(m_po_dvec2_arr_uniform_location, -1, double_values); 2737 break; 2738 case UNIFORM_FUNCTION_3DV: 2739 gl.uniform3dv(m_po_dvec3_arr_uniform_location, -1, double_values); 2740 break; 2741 case UNIFORM_FUNCTION_4DV: 2742 gl.uniform4dv(m_po_dvec4_arr_uniform_location, -1, double_values); 2743 break; 2744 case UNIFORM_FUNCTION_MATRIX2DV: 2745 gl.uniformMatrix2dv(m_po_dmat2_arr_uniform_location, -1, GL_FALSE, double_values); 2746 break; 2747 case UNIFORM_FUNCTION_MATRIX2X3DV: 2748 gl.uniformMatrix2x3dv(m_po_dmat2x3_arr_uniform_location, -1, GL_FALSE, double_values); 2749 break; 2750 case UNIFORM_FUNCTION_MATRIX2X4DV: 2751 gl.uniformMatrix2x4dv(m_po_dmat2x4_arr_uniform_location, -1, GL_FALSE, double_values); 2752 break; 2753 case UNIFORM_FUNCTION_MATRIX3DV: 2754 gl.uniformMatrix3dv(m_po_dmat3_arr_uniform_location, -1, GL_FALSE, double_values); 2755 break; 2756 case UNIFORM_FUNCTION_MATRIX3X2DV: 2757 gl.uniformMatrix3x2dv(m_po_dmat3x2_arr_uniform_location, -1, GL_FALSE, double_values); 2758 break; 2759 case UNIFORM_FUNCTION_MATRIX3X4DV: 2760 gl.uniformMatrix3x4dv(m_po_dmat3x4_arr_uniform_location, -1, GL_FALSE, double_values); 2761 break; 2762 case UNIFORM_FUNCTION_MATRIX4DV: 2763 gl.uniformMatrix4dv(m_po_dmat4_arr_uniform_location, -1, GL_FALSE, double_values); 2764 break; 2765 case UNIFORM_FUNCTION_MATRIX4X2DV: 2766 gl.uniformMatrix4x2dv(m_po_dmat4x2_arr_uniform_location, -1, GL_FALSE, double_values); 2767 break; 2768 case UNIFORM_FUNCTION_MATRIX4X3DV: 2769 gl.uniformMatrix4x3dv(m_po_dmat4x3_arr_uniform_location, -1, GL_FALSE, double_values); 2770 break; 2771 2772 default: 2773 { 2774 TCU_FAIL("Unrecognized uniform function"); 2775 } 2776 } /* switch (uniform_function) */ 2777 2778 /* Make sure GL_INVALID_VALUE was generated */ 2779 glw::GLenum error_code = gl.getError(); 2780 2781 if (error_code != GL_INVALID_VALUE) 2782 { 2783 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) 2784 << "() " 2785 "was called with a negative count argument but did not generate a " 2786 "GL_INVALID_VALUE error" 2787 << tcu::TestLog::EndMessage; 2788 2789 result = false; 2790 } 2791 } /* for (all uniform functions) */ 2792 2793 return result; 2794 } 2795 2796 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or 2797 * glUniformMatrix*dv() functions is used to load an uniform that's incompatible with the 2798 * function (as per spec). 2799 * 2800 * @return true if the implementation was found to behave as expected, false otherwise. 2801 **/ 2802 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions() 2803 { 2804 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 2805 glw::GLenum error_code = GL_NO_ERROR; 2806 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2807 bool result = true; 2808 2809 const glw::GLint double_uniform_locations[] = { m_po_dmat2_uniform_location, m_po_dmat2x3_uniform_location, 2810 m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location, 2811 m_po_dmat3x2_uniform_location, m_po_dmat3x4_uniform_location, 2812 m_po_dmat4_uniform_location, m_po_dmat4x2_uniform_location, 2813 m_po_dmat4x3_uniform_location, m_po_double_uniform_location, 2814 m_po_dvec2_uniform_location, m_po_dvec3_uniform_location, 2815 m_po_dvec4_uniform_location }; 2816 const unsigned int n_double_uniform_locations = 2817 sizeof(double_uniform_locations) / sizeof(double_uniform_locations[0]); 2818 2819 gl.useProgram(m_po_id); 2820 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2821 2822 for (unsigned int n_uniform_location = 0; n_uniform_location < n_double_uniform_locations; ++n_uniform_location) 2823 { 2824 glw::GLint uniform_location = double_uniform_locations[n_uniform_location]; 2825 2826 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); 2827 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); function++) 2828 { 2829 _uniform_function e_function = static_cast<_uniform_function>(function); 2830 /* Exclude valid combinations */ 2831 if (((uniform_location == m_po_dmat2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2DV)) || 2832 ((uniform_location == m_po_dmat2x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X3DV)) || 2833 ((uniform_location == m_po_dmat2x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X4DV)) || 2834 ((uniform_location == m_po_dmat3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3DV)) || 2835 ((uniform_location == m_po_dmat3x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X2DV)) || 2836 ((uniform_location == m_po_dmat3x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X4DV)) || 2837 ((uniform_location == m_po_dmat4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4DV)) || 2838 ((uniform_location == m_po_dmat4x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X2DV)) || 2839 ((uniform_location == m_po_dmat4x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X3DV)) || 2840 ((uniform_location == m_po_double_uniform_location) && 2841 ((e_function == UNIFORM_FUNCTION_1D) || (e_function == UNIFORM_FUNCTION_1DV))) || 2842 ((uniform_location == m_po_dvec2_uniform_location) && 2843 ((e_function == UNIFORM_FUNCTION_2D) || (e_function == UNIFORM_FUNCTION_2DV))) || 2844 ((uniform_location == m_po_dvec3_uniform_location) && 2845 ((e_function == UNIFORM_FUNCTION_3D) || (e_function == UNIFORM_FUNCTION_3DV))) || 2846 ((uniform_location == m_po_dvec4_uniform_location) && 2847 ((e_function == UNIFORM_FUNCTION_4D) || (e_function == UNIFORM_FUNCTION_4DV)))) 2848 { 2849 continue; 2850 } 2851 2852 switch (e_function) 2853 { 2854 case UNIFORM_FUNCTION_1D: 2855 { 2856 gl.uniform1d(uniform_location, double_data[0]); 2857 2858 break; 2859 } 2860 2861 case UNIFORM_FUNCTION_2D: 2862 { 2863 gl.uniform2d(uniform_location, double_data[0], double_data[1]); 2864 2865 break; 2866 } 2867 2868 case UNIFORM_FUNCTION_3D: 2869 { 2870 gl.uniform3d(uniform_location, double_data[0], double_data[1], double_data[2]); 2871 2872 break; 2873 } 2874 2875 case UNIFORM_FUNCTION_4D: 2876 { 2877 gl.uniform4d(uniform_location, double_data[0], double_data[1], double_data[2], double_data[3]); 2878 2879 break; 2880 } 2881 2882 case UNIFORM_FUNCTION_1DV: 2883 gl.uniform1dv(uniform_location, 1 /* count */, double_data); 2884 break; 2885 case UNIFORM_FUNCTION_2DV: 2886 gl.uniform2dv(uniform_location, 1 /* count */, double_data); 2887 break; 2888 case UNIFORM_FUNCTION_3DV: 2889 gl.uniform3dv(uniform_location, 1 /* count */, double_data); 2890 break; 2891 case UNIFORM_FUNCTION_4DV: 2892 gl.uniform4dv(uniform_location, 1 /* count */, double_data); 2893 break; 2894 case UNIFORM_FUNCTION_MATRIX2DV: 2895 gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2896 break; 2897 case UNIFORM_FUNCTION_MATRIX2X3DV: 2898 gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2899 break; 2900 case UNIFORM_FUNCTION_MATRIX2X4DV: 2901 gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2902 break; 2903 case UNIFORM_FUNCTION_MATRIX3DV: 2904 gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2905 break; 2906 case UNIFORM_FUNCTION_MATRIX3X2DV: 2907 gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2908 break; 2909 case UNIFORM_FUNCTION_MATRIX3X4DV: 2910 gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2911 break; 2912 case UNIFORM_FUNCTION_MATRIX4DV: 2913 gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2914 break; 2915 case UNIFORM_FUNCTION_MATRIX4X2DV: 2916 gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2917 break; 2918 case UNIFORM_FUNCTION_MATRIX4X3DV: 2919 gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data); 2920 break; 2921 2922 default: 2923 { 2924 TCU_FAIL("Unrecognized function"); 2925 } 2926 } /* switch (function) */ 2927 2928 /* Make sure GL_INVALID_OPERATION error was generated */ 2929 error_code = gl.getError(); 2930 2931 if (error_code != GL_INVALID_OPERATION) 2932 { 2933 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error [" << error_code 2934 << "] was generated when a mismatched " 2935 "double-precision uniform function " 2936 << getUniformFunctionString(e_function) << "() was used to configure uniform " 2937 << getUniformNameForLocation(uniform_location) << "." << tcu::TestLog::EndMessage; 2938 2939 result = false; 2940 } 2941 } /* for (all uniform functions) */ 2942 } /* for (all uniform locations) */ 2943 2944 return result; 2945 } 2946 2947 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or 2948 * glUniform*dv() functions is used to load an uniform, size of which is incompatible 2949 * with the function. 2950 * 2951 * @return true if the implementation was found to behave as expected, false otherwise. 2952 **/ 2953 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions() 2954 { 2955 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 2956 glw::GLenum error_code = GL_NO_ERROR; 2957 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2958 bool result = true; 2959 2960 const int data[] = { 2961 /* API function */ /* Uniform location */ /* Count (dv functions only) */ 2962 (int)UNIFORM_FUNCTION_2D, m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_2DV, 2963 m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_double_uniform_location, 0, 2964 (int)UNIFORM_FUNCTION_3DV, m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_4D, 2965 m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_double_uniform_location, 2, 2966 (int)UNIFORM_FUNCTION_1D, m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV, 2967 m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_dvec2_uniform_location, 0, 2968 (int)UNIFORM_FUNCTION_3DV, m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_4D, 2969 m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec2_uniform_location, 2, 2970 (int)UNIFORM_FUNCTION_1D, m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV, 2971 m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec3_uniform_location, 0, 2972 (int)UNIFORM_FUNCTION_2DV, m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_4D, 2973 m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec3_uniform_location, 2, 2974 (int)UNIFORM_FUNCTION_1D, m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV, 2975 m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec4_uniform_location, 0, 2976 (int)UNIFORM_FUNCTION_2DV, m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, 2977 m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_3DV, m_po_dvec4_uniform_location, 2, 2978 }; 2979 const unsigned int n_checks = sizeof(data) / sizeof(data[0]) / 3 /* entries per row */; 2980 2981 gl.useProgram(m_po_id); 2982 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2983 2984 for (unsigned int n_check = 0; n_check < n_checks; ++n_check) 2985 { 2986 _uniform_function function = (_uniform_function)data[n_check * 3 + 0]; 2987 int uniform_location = data[n_check * 3 + 1]; 2988 int uniform_count = data[n_check * 3 + 2]; 2989 2990 switch (function) 2991 { 2992 case UNIFORM_FUNCTION_1D: 2993 gl.uniform1d(uniform_location, 0.0); 2994 break; 2995 case UNIFORM_FUNCTION_1DV: 2996 gl.uniform1dv(uniform_location, uniform_count, double_data); 2997 break; 2998 case UNIFORM_FUNCTION_2D: 2999 gl.uniform2d(uniform_location, 0.0, 1.0); 3000 break; 3001 case UNIFORM_FUNCTION_2DV: 3002 gl.uniform2dv(uniform_location, uniform_count, double_data); 3003 break; 3004 case UNIFORM_FUNCTION_3D: 3005 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0); 3006 break; 3007 case UNIFORM_FUNCTION_3DV: 3008 gl.uniform3dv(uniform_location, uniform_count, double_data); 3009 break; 3010 case UNIFORM_FUNCTION_4D: 3011 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0); 3012 break; 3013 case UNIFORM_FUNCTION_4DV: 3014 gl.uniform4dv(uniform_location, uniform_count, double_data); 3015 break; 3016 3017 default: 3018 { 3019 DE_ASSERT(false); 3020 } 3021 } /* switch (function) */ 3022 3023 error_code = gl.getError(); 3024 if (error_code != GL_INVALID_OPERATION) 3025 { 3026 m_testCtx.getLog() << tcu::TestLog::Message << getUniformFunctionString(function) 3027 << "() function did not generate GL_INVALID_OPERATION error when called for" 3028 " a uniform of incompatible size. (check index: " 3029 << n_check << ")" << tcu::TestLog::EndMessage; 3030 3031 result = false; 3032 } 3033 } /* for (all checks) */ 3034 3035 return result; 3036 } 3037 3038 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or 3039 * glUniform*dv() functions is used to load an uniform, type of which is incompatible 3040 * with the function. 3041 * 3042 * @return true if the implementation was found to behave as expected, false otherwise. 3043 **/ 3044 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions() 3045 { 3046 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 3047 glw::GLenum error_code = GL_NO_ERROR; 3048 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3049 bool result = true; 3050 3051 const glw::GLint nondouble_uniform_locations[] = { m_po_bool_uniform_location, m_po_bvec2_uniform_location, 3052 m_po_bvec3_uniform_location, m_po_bvec4_uniform_location, 3053 m_po_float_uniform_location, m_po_int_uniform_location, 3054 m_po_ivec2_uniform_location, m_po_ivec3_uniform_location, 3055 m_po_ivec4_uniform_location, m_po_uint_uniform_location, 3056 m_po_uvec2_uniform_location, m_po_uvec3_uniform_location, 3057 m_po_uvec4_uniform_location, m_po_vec2_uniform_location, 3058 m_po_vec3_uniform_location, m_po_vec4_uniform_location }; 3059 const unsigned int n_nondouble_uniform_locations = 3060 sizeof(nondouble_uniform_locations) / sizeof(nondouble_uniform_locations[0]); 3061 3062 gl.useProgram(m_po_id); 3063 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 3064 3065 for (unsigned int n_uniform_location = 0; n_uniform_location < n_nondouble_uniform_locations; ++n_uniform_location) 3066 { 3067 glw::GLint uniform_location = nondouble_uniform_locations[n_uniform_location]; 3068 3069 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); 3070 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); ++function) 3071 { 3072 switch (static_cast<_uniform_function>(function)) 3073 { 3074 case UNIFORM_FUNCTION_1D: 3075 gl.uniform1d(uniform_location, 0.0); 3076 break; 3077 case UNIFORM_FUNCTION_1DV: 3078 gl.uniform1dv(uniform_location, 1, double_data); 3079 break; 3080 case UNIFORM_FUNCTION_2D: 3081 gl.uniform2d(uniform_location, 0.0, 1.0); 3082 break; 3083 case UNIFORM_FUNCTION_2DV: 3084 gl.uniform2dv(uniform_location, 1, double_data); 3085 break; 3086 case UNIFORM_FUNCTION_3D: 3087 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0); 3088 break; 3089 case UNIFORM_FUNCTION_3DV: 3090 gl.uniform3dv(uniform_location, 1, double_data); 3091 break; 3092 case UNIFORM_FUNCTION_4D: 3093 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0); 3094 break; 3095 case UNIFORM_FUNCTION_4DV: 3096 gl.uniform4dv(uniform_location, 1, double_data); 3097 break; 3098 3099 case UNIFORM_FUNCTION_MATRIX2DV: 3100 gl.uniformMatrix2dv(uniform_location, 1, GL_FALSE, double_data); 3101 break; 3102 case UNIFORM_FUNCTION_MATRIX2X3DV: 3103 gl.uniformMatrix2x3dv(uniform_location, 1, GL_FALSE, double_data); 3104 break; 3105 case UNIFORM_FUNCTION_MATRIX2X4DV: 3106 gl.uniformMatrix2x4dv(uniform_location, 1, GL_FALSE, double_data); 3107 break; 3108 case UNIFORM_FUNCTION_MATRIX3DV: 3109 gl.uniformMatrix3dv(uniform_location, 1, GL_FALSE, double_data); 3110 break; 3111 case UNIFORM_FUNCTION_MATRIX3X2DV: 3112 gl.uniformMatrix3x2dv(uniform_location, 1, GL_FALSE, double_data); 3113 break; 3114 case UNIFORM_FUNCTION_MATRIX3X4DV: 3115 gl.uniformMatrix3x4dv(uniform_location, 1, GL_FALSE, double_data); 3116 break; 3117 case UNIFORM_FUNCTION_MATRIX4DV: 3118 gl.uniformMatrix4dv(uniform_location, 1, GL_FALSE, double_data); 3119 break; 3120 case UNIFORM_FUNCTION_MATRIX4X2DV: 3121 gl.uniformMatrix4x2dv(uniform_location, 1, GL_FALSE, double_data); 3122 break; 3123 case UNIFORM_FUNCTION_MATRIX4X3DV: 3124 gl.uniformMatrix4x3dv(uniform_location, 1, GL_FALSE, double_data); 3125 break; 3126 3127 default: 3128 { 3129 DE_ASSERT(false); 3130 } 3131 } /* switch (function) */ 3132 3133 error_code = gl.getError(); 3134 if (error_code != GL_INVALID_OPERATION) 3135 { 3136 m_testCtx.getLog() << tcu::TestLog::Message 3137 << getUniformFunctionString(static_cast<_uniform_function>(function)) 3138 << "() function did not generate GL_INVALID_OPERATION error when called for" 3139 " a uniform of incompatible type." 3140 << tcu::TestLog::EndMessage; 3141 3142 result = false; 3143 } 3144 } 3145 } /* for (all checks) */ 3146 3147 return result; 3148 } 3149 3150 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or 3151 * glUniform*dv() functions are called without a bound program object. 3152 * 3153 * @return true if the implementation was found to behave as expected, false otherwise. 3154 **/ 3155 bool GPUShaderFP64Test1::verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO() 3156 { 3157 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3158 bool result = true; 3159 3160 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); function < static_cast<int>(UNIFORM_FUNCTION_COUNT); 3161 function++) 3162 { 3163 const double data[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 }; 3164 3165 switch (static_cast<_uniform_function>(function)) 3166 { 3167 case UNIFORM_FUNCTION_1D: 3168 gl.uniform1d(m_po_double_uniform_location, 0.0); 3169 break; 3170 case UNIFORM_FUNCTION_1DV: 3171 gl.uniform1dv(m_po_double_uniform_location, 1, data); 3172 break; 3173 case UNIFORM_FUNCTION_2D: 3174 gl.uniform2d(m_po_dvec2_uniform_location, 0.0, 1.0); 3175 break; 3176 case UNIFORM_FUNCTION_2DV: 3177 gl.uniform2dv(m_po_dvec2_uniform_location, 1, data); 3178 break; 3179 case UNIFORM_FUNCTION_3D: 3180 gl.uniform3d(m_po_dvec3_uniform_location, 0.0, 1.0, 2.0); 3181 break; 3182 case UNIFORM_FUNCTION_3DV: 3183 gl.uniform3dv(m_po_dvec3_uniform_location, 1, data); 3184 break; 3185 case UNIFORM_FUNCTION_4D: 3186 gl.uniform4d(m_po_dvec4_uniform_location, 0.0, 1.0, 2.0, 3.0); 3187 break; 3188 case UNIFORM_FUNCTION_4DV: 3189 gl.uniform4dv(m_po_dvec4_uniform_location, 1, data); 3190 break; 3191 3192 case UNIFORM_FUNCTION_MATRIX2DV: 3193 gl.uniformMatrix2dv(m_po_dmat2_uniform_location, 1, GL_FALSE /* transpose */, data); 3194 break; 3195 case UNIFORM_FUNCTION_MATRIX2X3DV: 3196 gl.uniformMatrix2x3dv(m_po_dmat2x3_uniform_location, 1, GL_FALSE /* transpose */, data); 3197 break; 3198 case UNIFORM_FUNCTION_MATRIX2X4DV: 3199 gl.uniformMatrix2x4dv(m_po_dmat2x4_uniform_location, 1, GL_FALSE /* transpose */, data); 3200 break; 3201 case UNIFORM_FUNCTION_MATRIX3DV: 3202 gl.uniformMatrix3dv(m_po_dmat3_uniform_location, 1, GL_FALSE /* transpose */, data); 3203 break; 3204 case UNIFORM_FUNCTION_MATRIX3X2DV: 3205 gl.uniformMatrix3x2dv(m_po_dmat3x2_uniform_location, 1, GL_FALSE /* transpose */, data); 3206 break; 3207 case UNIFORM_FUNCTION_MATRIX3X4DV: 3208 gl.uniformMatrix3x4dv(m_po_dmat3x4_uniform_location, 1, GL_FALSE /* transpose */, data); 3209 break; 3210 case UNIFORM_FUNCTION_MATRIX4DV: 3211 gl.uniformMatrix4dv(m_po_dmat4_uniform_location, 1, GL_FALSE /* transpose */, data); 3212 break; 3213 case UNIFORM_FUNCTION_MATRIX4X2DV: 3214 gl.uniformMatrix4x2dv(m_po_dmat4x2_uniform_location, 1, GL_FALSE /* transpose */, data); 3215 break; 3216 case UNIFORM_FUNCTION_MATRIX4X3DV: 3217 gl.uniformMatrix4x3dv(m_po_dmat4x3_uniform_location, 1, GL_FALSE /* transpose */, data); 3218 break; 3219 3220 default: 3221 { 3222 TCU_FAIL("Unrecognized uniform function"); 3223 } 3224 } /* switch (func) */ 3225 3226 /* Query the error code */ 3227 glw::GLenum error_code = gl.getError(); 3228 3229 if (error_code != GL_INVALID_OPERATION) 3230 { 3231 m_testCtx.getLog() << tcu::TestLog::Message << "Implementation did not return GL_INVALID_OPERATION when " 3232 << getUniformFunctionString(static_cast<_uniform_function>(function)) 3233 << "() was called without an active program object" << tcu::TestLog::EndMessage; 3234 3235 result = false; 3236 } 3237 } /* for (all uniform functions) */ 3238 3239 return result; 3240 } 3241 3242 /* Defeinitions of static const symbols declared in GPUShaderFP64Test2 */ 3243 const glw::GLuint GPUShaderFP64Test2::m_n_captured_results = 1024; 3244 const glw::GLint GPUShaderFP64Test2::m_result_failure = 2; 3245 const glw::GLint GPUShaderFP64Test2::m_result_success = 1; 3246 const glw::GLuint GPUShaderFP64Test2::m_texture_width = 32; 3247 const glw::GLuint GPUShaderFP64Test2::m_texture_height = m_n_captured_results / m_texture_width; 3248 const glw::GLuint GPUShaderFP64Test2::m_transform_feedback_buffer_size = 3249 m_n_captured_results * sizeof(captured_varying_type); 3250 const glw::GLchar* GPUShaderFP64Test2::m_uniform_block_name = "UniformBlock"; 3251 const glw::GLenum GPUShaderFP64Test2::ARB_MAX_COMPUTE_UNIFORM_COMPONENTS = 0x8263; 3252 3253 /** Constructor 3254 * 3255 * @param context Test context 3256 **/ 3257 GPUShaderFP64Test2::GPUShaderFP64Test2(deqp::Context& context) 3258 : TestCase(context, "max_uniform_components", 3259 "Verifies that maximum allowed uniform components can be used as double-precision float types") 3260 , m_pDispatchCompute(0) 3261 , m_framebuffer_id(0) 3262 , m_texture_id(0) 3263 , m_transform_feedback_buffer_id(0) 3264 , m_uniform_buffer_id(0) 3265 , m_vertex_array_object_id(0) 3266 { 3267 /* Nothing to be done */ 3268 } 3269 3270 /** Deinitialize test 3271 * 3272 **/ 3273 void GPUShaderFP64Test2::deinit() 3274 { 3275 /* GL entry points */ 3276 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3277 3278 /* Clean frambuffer */ 3279 if (0 != m_framebuffer_id) 3280 { 3281 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 3282 gl.deleteFramebuffers(1, &m_framebuffer_id); 3283 m_framebuffer_id = 0; 3284 } 3285 3286 /* Clean texture */ 3287 if (0 != m_texture_id) 3288 { 3289 gl.bindTexture(GL_TEXTURE_2D, 0); 3290 gl.bindImageTexture(0 /* unit */, 0 /* texture */, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, 3291 GL_READ_ONLY, GL_RGBA8); 3292 gl.deleteTextures(1, &m_texture_id); 3293 m_texture_id = 0; 3294 } 3295 3296 /* Clean buffers */ 3297 if (0 != m_transform_feedback_buffer_id) 3298 { 3299 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 3300 gl.deleteBuffers(1, &m_transform_feedback_buffer_id); 3301 m_transform_feedback_buffer_id = 0; 3302 } 3303 3304 if (0 != m_uniform_buffer_id) 3305 { 3306 gl.bindBuffer(GL_UNIFORM_BUFFER, 0); 3307 gl.deleteBuffers(1, &m_uniform_buffer_id); 3308 m_uniform_buffer_id = 0; 3309 } 3310 3311 /* Clean VAO */ 3312 if (0 != m_vertex_array_object_id) 3313 { 3314 gl.bindVertexArray(0); 3315 gl.deleteVertexArrays(1, &m_vertex_array_object_id); 3316 m_vertex_array_object_id = 0; 3317 } 3318 } 3319 3320 /** Execute test 3321 * 3322 * @return tcu::TestNode::STOP 3323 **/ 3324 tcu::TestNode::IterateResult GPUShaderFP64Test2::iterate() 3325 { 3326 bool result = true; 3327 3328 /* Check if extension is supported */ 3329 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 3330 { 3331 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported"); 3332 } 3333 3334 /* Initialize test */ 3335 testInit(); 3336 3337 prepareShaderStages(); 3338 prepareUniformTypes(); 3339 3340 /* For all shaders and uniform type combinations */ 3341 for (std::vector<shaderStage>::const_iterator shader_stage = m_shader_stages.begin(); 3342 m_shader_stages.end() != shader_stage; ++shader_stage) 3343 { 3344 for (std::vector<uniformTypeDetails>::const_iterator uniform_type = m_uniform_types.begin(); 3345 m_uniform_types.end() != uniform_type; ++uniform_type) 3346 { 3347 /* Execute test */ 3348 if (false == test(*shader_stage, *uniform_type)) 3349 { 3350 result = false; 3351 } 3352 } 3353 } 3354 3355 /* Set result */ 3356 if (true == result) 3357 { 3358 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3359 } 3360 else 3361 { 3362 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3363 } 3364 3365 /* Done */ 3366 return tcu::TestNode::STOP; 3367 } 3368 3369 /** Constructor 3370 * 3371 * @param n_columns Number of columns 3372 * @param n_rows Number of rows 3373 **/ 3374 GPUShaderFP64Test2::uniformTypeDetails::uniformTypeDetails(glw::GLuint n_columns, glw::GLuint n_rows) 3375 : m_n_columns(n_columns), m_n_rows(n_rows) 3376 { 3377 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows); 3378 3379 m_type_name = Utils::getVariableTypeString(type); 3380 m_type = Utils::getGLDataTypeOfVariableType(type); 3381 } 3382 3383 /** Get primitive type captured with transform feedback 3384 * 3385 * @param shader_stage Tested shader stage id 3386 * 3387 * @return Primitive type 3388 **/ 3389 glw::GLenum GPUShaderFP64Test2::getCapturedPrimitiveType(shaderStage shader_stage) const 3390 { 3391 switch (shader_stage) 3392 { 3393 case GEOMETRY_SHADER: 3394 case TESS_CTRL_SHADER: 3395 case TESS_EVAL_SHADER: 3396 case VERTEX_SHADER: 3397 return GL_POINTS; 3398 break; 3399 3400 default: 3401 return GL_NONE; 3402 break; 3403 } 3404 } 3405 3406 /** Get primitive type drawn with DrawArrays 3407 * 3408 * @param shader_stage Tested shader stage id 3409 * 3410 * @return Primitive type 3411 **/ 3412 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const 3413 { 3414 switch (shader_stage) 3415 { 3416 case FRAGMENT_SHADER: 3417 return GL_TRIANGLE_FAN; 3418 break; 3419 3420 case GEOMETRY_SHADER: 3421 case VERTEX_SHADER: 3422 return GL_POINTS; 3423 break; 3424 3425 case TESS_CTRL_SHADER: 3426 case TESS_EVAL_SHADER: 3427 return GL_PATCHES; 3428 break; 3429 3430 default: 3431 return GL_NONE; 3432 break; 3433 } 3434 } 3435 3436 /** Get maximum allowed number of uniform components 3437 * 3438 * @param shader_stage Tested shader stage id 3439 * 3440 * @return Maxmimum uniform components 3441 **/ 3442 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const 3443 { 3444 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3445 glw::GLint max_uniform_components = 0; 3446 glw::GLenum pname = 0; 3447 3448 switch (shader_stage) 3449 { 3450 case COMPUTE_SHADER: 3451 pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS; 3452 break; 3453 case FRAGMENT_SHADER: 3454 pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS; 3455 break; 3456 case GEOMETRY_SHADER: 3457 pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS; 3458 break; 3459 case TESS_CTRL_SHADER: 3460 pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS; 3461 break; 3462 case TESS_EVAL_SHADER: 3463 pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS; 3464 break; 3465 case VERTEX_SHADER: 3466 pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS; 3467 break; 3468 } 3469 3470 gl.getIntegerv(pname, &max_uniform_components); 3471 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3472 3473 return max_uniform_components; 3474 } 3475 3476 /** Get maximum size allowed for an uniform block 3477 * 3478 * @return Maxmimum uniform block size 3479 **/ 3480 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const 3481 { 3482 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3483 glw::GLint max_uniform_block_size = 0; 3484 3485 gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size); 3486 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); 3487 3488 return max_uniform_block_size; 3489 } 3490 3491 /** Get number of components required to store single uniform of given type 3492 * 3493 * @param uniform_type Tested uniform type 3494 * 3495 * @return Number of components 3496 **/ 3497 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const 3498 { 3499 static const glw::GLuint type_size = 2; /* double takes 2 N */ 3500 const glw::GLuint column_length = uniform_type.m_n_rows; 3501 3502 if (1 == uniform_type.m_n_columns) 3503 { 3504 return type_size * column_length; 3505 } 3506 else 3507 { 3508 const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length); 3509 3510 return alignment * uniform_type.m_n_columns; 3511 } 3512 } 3513 3514 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout 3515 * 3516 * @param uniform_type Tested uniform type 3517 * 3518 * @return Size of a single member 3519 **/ 3520 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const 3521 { 3522 static const glw::GLuint vec4_size = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT); 3523 const glw::GLuint column_length = uniform_type.m_n_rows; 3524 3525 /** Size for a layout(std140, column_major) uniform_type uniform[] **/ 3526 return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns; 3527 } 3528 3529 /** Get the maximum amount of uniforms to be used in a shader stage for a given type 3530 * 3531 * @param shader_stage Tested shader stage id 3532 * @param uniform_type Tested uniform type 3533 * 3534 * @return Number of components 3535 **/ 3536 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage shader_stage, 3537 const uniformTypeDetails& uniform_type) const 3538 { 3539 const glw::GLuint max_uniform_components = getMaxUniformComponents(shader_stage); 3540 const glw::GLuint required_components = getRequiredComponentsNumber(uniform_type); 3541 const glw::GLuint n_uniforms = max_uniform_components / required_components; 3542 const glw::GLuint max_uniform_block_size = getMaxUniformBlockSize(); 3543 const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type); 3544 const glw::GLuint max_uniforms = max_uniform_block_size / uniform_type_member_size; 3545 3546 return max_uniforms < n_uniforms ? max_uniforms : n_uniforms; 3547 } 3548 3549 /** Get name of shader stage 3550 * 3551 * @param shader_stage Tested shader stage id 3552 * 3553 * @return Name 3554 **/ 3555 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const 3556 { 3557 switch (shader_stage) 3558 { 3559 case COMPUTE_SHADER: 3560 return "compute shader"; 3561 break; 3562 case FRAGMENT_SHADER: 3563 return "fragment shader"; 3564 break; 3565 case GEOMETRY_SHADER: 3566 return "geometry shader"; 3567 break; 3568 case TESS_CTRL_SHADER: 3569 return "tesselation control shader"; 3570 break; 3571 case TESS_EVAL_SHADER: 3572 return "tesselation evaluation shader"; 3573 break; 3574 case VERTEX_SHADER: 3575 return "vertex shader"; 3576 break; 3577 } 3578 3579 return 0; 3580 } 3581 3582 /** Inspect program to get: buffer_size, offset, strides and block index 3583 * 3584 * @param program_id Program id 3585 * @param out_buffer_size Size of uniform buffer 3586 * @param out_uniform_details Uniform offset and strides 3587 * @param uniform_block_index Uniform block index 3588 **/ 3589 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms, 3590 const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size, 3591 uniformDetails& out_uniform_details, glw::GLuint uniform_block_index) const 3592 { 3593 glw::GLint array_stride = 0; 3594 std::vector<glw::GLchar> extracted_uniform_name; 3595 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3596 glw::GLuint index = 0; 3597 glw::GLint matrix_stride = 0; 3598 glw::GLint offset = 0; 3599 glw::GLsizei size = 0; 3600 glw::GLenum type = 0; 3601 const glw::GLchar* uniform_name = 0; 3602 std::string uniform_name_str; 3603 std::stringstream uniform_name_stream; 3604 3605 /* Get index of uniform block */ 3606 uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name); 3607 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex"); 3608 3609 if (GL_INVALID_INDEX == uniform_block_index) 3610 { 3611 TCU_FAIL("Unifom block is inactive"); 3612 } 3613 3614 /* Get size of uniform block */ 3615 gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size); 3616 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv"); 3617 3618 if (0 == out_buffer_size) 3619 { 3620 TCU_FAIL("Unifom block size is 0"); 3621 } 3622 3623 /* Prepare uniform name */ 3624 uniform_name_stream << "uniform_array"; 3625 3626 uniform_name_str = uniform_name_stream.str(); 3627 uniform_name = uniform_name_str.c_str(); 3628 3629 /* Get index of uniform */ 3630 gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index); 3631 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices"); 3632 3633 if (GL_INVALID_INDEX == index) 3634 { 3635 TCU_FAIL("Unifom is inactive"); 3636 } 3637 3638 /* Verify getActiveUniform results */ 3639 extracted_uniform_name.resize(uniform_name_str.length() * 2); 3640 3641 gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type, 3642 &extracted_uniform_name[0]); 3643 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform"); 3644 3645 if ((n_uniforms != size) || (uniform_type.m_type != type)) 3646 { 3647 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results." 3648 << " Size: " << size << " expected: " << n_uniforms << ". Type: " << type 3649 << " expected: " << uniform_type.m_type 3650 << ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage; 3651 3652 TCU_FAIL("Invalid GetActiveUniform results"); 3653 } 3654 3655 /* Get offset of uniform */ 3656 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset); 3657 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv"); 3658 3659 if (-1 == offset) 3660 { 3661 TCU_FAIL("Unifom has invalid offset"); 3662 } 3663 3664 out_uniform_details.m_offset = offset; 3665 3666 /* Get matrix stride of uniform */ 3667 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride); 3668 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv"); 3669 3670 if (-1 == matrix_stride) 3671 { 3672 TCU_FAIL("Unifom has invalid matrix stride"); 3673 } 3674 3675 out_uniform_details.m_matrix_stride = matrix_stride; 3676 3677 /* Get array stride of uniform */ 3678 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride); 3679 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv"); 3680 3681 if (-1 == matrix_stride) 3682 { 3683 TCU_FAIL("Unifom has invalid matrix stride"); 3684 } 3685 3686 out_uniform_details.m_array_stride = array_stride; 3687 } 3688 3689 /** Prepare source code for "boilerplate" shaders 3690 * 3691 * @param stage_specific_layout String that will replace STAGE_SPECIFIC_LAYOUT token 3692 * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token 3693 * @param out_source_code Source code 3694 **/ 3695 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout, 3696 const glw::GLchar* stage_specific_main_body, 3697 std::string& out_source_code) const 3698 { 3699 /* Shader template */ 3700 static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n" 3701 "\n" 3702 "precision highp float;\n" 3703 "\n" 3704 "STAGE_SPECIFIC_LAYOUT" 3705 "void main()\n" 3706 "{\n" 3707 "STAGE_SPECIFIC_MAIN_BODY" 3708 "}\n" 3709 "\n"; 3710 3711 std::string string = boilerplate_shader_template_code; 3712 3713 /* Tokens */ 3714 static const glw::GLchar* body_token = "STAGE_SPECIFIC_MAIN_BODY"; 3715 static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT"; 3716 3717 size_t search_position = 0; 3718 3719 /* Replace tokens */ 3720 Utils::replaceToken(layout_token, search_position, stage_specific_layout, string); 3721 Utils::replaceToken(body_token, search_position, stage_specific_main_body, string); 3722 3723 /* Store resuls */ 3724 out_source_code = string; 3725 } 3726 3727 /** Prepare program for given combination of shader stage and uniform type 3728 * 3729 * @param shader_stage Shader stage 3730 * @param uniform_type Uniform type 3731 * @param out_program_info Instance of programInfo 3732 **/ 3733 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type, 3734 Utils::programInfo& out_program_info) const 3735 { 3736 /* Stage specific layouts */ 3737 static const glw::GLchar* geometry_shader_layout_code = "layout(points) in;\n" 3738 "layout(points, max_vertices = 1) out;\n" 3739 "\n"; 3740 3741 static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n" 3742 "\n"; 3743 3744 static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n" 3745 "\n"; 3746 3747 /* Stage specific main body */ 3748 static const glw::GLchar* boilerplate_fragment_shader_body_code = " discard;\n"; 3749 3750 static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = " gl_TessLevelOuter[0] = 1.0;\n" 3751 " gl_TessLevelOuter[1] = 1.0;\n" 3752 " gl_TessLevelOuter[2] = 1.0;\n" 3753 " gl_TessLevelOuter[3] = 1.0;\n" 3754 " gl_TessLevelInner[0] = 1.0;\n" 3755 " gl_TessLevelInner[1] = 1.0;\n"; 3756 3757 static const glw::GLchar* boilerplate_vertex_shader_body_code = " gl_Position = vec4(1, 0, 0, 1);\n"; 3758 3759 static const glw::GLchar* corner_vertex_shader_body_code = " if (0 == gl_VertexID)\n" 3760 " {\n" 3761 " gl_Position = vec4(-1, -1, 0, 1);\n" 3762 " }\n" 3763 " else if (1 == gl_VertexID)\n" 3764 " {\n" 3765 " gl_Position = vec4(-1, 1, 0, 1);\n" 3766 " }\n" 3767 " else if (2 == gl_VertexID)\n" 3768 " {\n" 3769 " gl_Position = vec4(1, 1, 0, 1);\n" 3770 " }\n" 3771 " else if (3 == gl_VertexID)\n" 3772 " {\n" 3773 " gl_Position = vec4(1, -1, 0, 1);\n" 3774 " }\n"; 3775 3776 static const glw::GLchar* passthrough_tess_eval_shader_body_code = " result = tcs_tes_result[0];\n"; 3777 3778 static const glw::GLchar* test_shader_body_code = "\n result = verification_result;\n"; 3779 3780 static const glw::GLchar* test_geometry_shader_body_code = "\n result = verification_result;\n" 3781 "\n" 3782 " EmitVertex();\n" 3783 " EndPrimitive();\n"; 3784 3785 static const glw::GLchar* test_tess_ctrl_shader_body_code = 3786 "\n tcs_tes_result[gl_InvocationID] = verification_result;\n" 3787 "\n" 3788 " gl_TessLevelOuter[0] = 1.0;\n" 3789 " gl_TessLevelOuter[1] = 1.0;\n" 3790 " gl_TessLevelOuter[2] = 1.0;\n" 3791 " gl_TessLevelOuter[3] = 1.0;\n" 3792 " gl_TessLevelInner[0] = 1.0;\n" 3793 " gl_TessLevelInner[1] = 1.0;\n"; 3794 3795 /* In variables */ 3796 static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in int tcs_tes_result[];\n"; 3797 3798 /* Out variables */ 3799 static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n"; 3800 3801 static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n"; 3802 3803 static const glw::GLchar* test_shader_out_variable = "out int result;\n"; 3804 3805 /* Varying name */ 3806 static const glw::GLchar* varying_name = "result"; 3807 glw::GLuint n_varyings = 1; 3808 3809 /* Storage for ready shaders */ 3810 std::string compute_shader_code; 3811 std::string fragment_shader_code; 3812 std::string geometry_shader_code; 3813 std::string tess_ctrl_shader_code; 3814 std::string tess_eval_shader_code; 3815 std::string vertex_shader_code; 3816 3817 /* Storage for uniform definition and verification code */ 3818 std::string uniform_definitions; 3819 std::string uniform_verification; 3820 3821 /* Get uniform definition and verification code */ 3822 prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions); 3823 prepareUniformVerification(shader_stage, uniform_type, uniform_verification); 3824 3825 /* Prepare vertex shader */ 3826 switch (shader_stage) 3827 { 3828 case FRAGMENT_SHADER: 3829 3830 prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code); 3831 3832 break; 3833 3834 case GEOMETRY_SHADER: 3835 case TESS_CTRL_SHADER: 3836 case TESS_EVAL_SHADER: 3837 3838 prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code); 3839 3840 break; 3841 3842 case VERTEX_SHADER: 3843 3844 prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */, 3845 test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */, 3846 test_shader_body_code /* body */, vertex_shader_code); 3847 3848 break; 3849 3850 default: 3851 break; 3852 } 3853 3854 /* Prepare fragment shader */ 3855 switch (shader_stage) 3856 { 3857 case FRAGMENT_SHADER: 3858 3859 prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */, 3860 test_fragment_shader_out_variable /* out var */, 3861 uniform_verification.c_str() /* verification */, test_shader_body_code /* body */, 3862 fragment_shader_code); 3863 3864 break; 3865 3866 case GEOMETRY_SHADER: 3867 case TESS_CTRL_SHADER: 3868 case TESS_EVAL_SHADER: 3869 case VERTEX_SHADER: 3870 3871 prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */, 3872 fragment_shader_code); 3873 3874 break; 3875 3876 default: 3877 break; 3878 } 3879 3880 /* Prepare compute, tess_ctrl, tess_eval, geometry shaders */ 3881 switch (shader_stage) 3882 { 3883 case COMPUTE_SHADER: 3884 3885 prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code); 3886 3887 break; 3888 3889 case GEOMETRY_SHADER: 3890 3891 prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */, 3892 "" /* in var */, test_shader_out_variable /* out var */, 3893 uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */, 3894 geometry_shader_code); 3895 3896 break; 3897 3898 case TESS_CTRL_SHADER: 3899 3900 prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */, 3901 "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */, 3902 uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */, 3903 tess_ctrl_shader_code); 3904 3905 prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */, 3906 test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */, 3907 "" /* verification */, passthrough_tess_eval_shader_body_code /* body */, 3908 tess_eval_shader_code); 3909 3910 break; 3911 3912 case TESS_EVAL_SHADER: 3913 3914 prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */, 3915 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code); 3916 3917 prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */, 3918 "" /* in var */, test_shader_out_variable /* out var */, 3919 uniform_verification.c_str() /* verification */, test_shader_body_code /* body */, 3920 tess_eval_shader_code); 3921 3922 break; 3923 3924 default: 3925 break; 3926 }; 3927 3928 /* Select shaders that will be used by program */ 3929 const glw::GLchar* cs_c_str = 0; 3930 const glw::GLchar* fs_c_str = 0; 3931 const glw::GLchar* gs_c_str = 0; 3932 const glw::GLchar* tcs_c_str = 0; 3933 const glw::GLchar* tes_c_str = 0; 3934 const glw::GLchar* vs_c_str = 0; 3935 3936 if (false == compute_shader_code.empty()) 3937 { 3938 cs_c_str = compute_shader_code.c_str(); 3939 } 3940 3941 if (false == fragment_shader_code.empty()) 3942 { 3943 fs_c_str = fragment_shader_code.c_str(); 3944 } 3945 3946 if (false == geometry_shader_code.empty()) 3947 { 3948 gs_c_str = geometry_shader_code.c_str(); 3949 } 3950 3951 if (false == tess_ctrl_shader_code.empty()) 3952 { 3953 tcs_c_str = tess_ctrl_shader_code.c_str(); 3954 } 3955 3956 if (false == tess_eval_shader_code.empty()) 3957 { 3958 tes_c_str = tess_eval_shader_code.c_str(); 3959 } 3960 3961 if (false == vertex_shader_code.empty()) 3962 { 3963 vs_c_str = vertex_shader_code.c_str(); 3964 } 3965 3966 /* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */ 3967 if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage)) 3968 { 3969 n_varyings = 0; 3970 } 3971 3972 /* Build */ 3973 out_program_info.build(cs_c_str, fs_c_str, gs_c_str, tcs_c_str, tes_c_str, vs_c_str, &varying_name, n_varyings); 3974 } 3975 3976 /** Prepare collection of tested shader stages 3977 * 3978 */ 3979 void GPUShaderFP64Test2::prepareShaderStages() 3980 { 3981 /* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */ 3982 if (0 != m_pDispatchCompute) 3983 { 3984 m_shader_stages.push_back(COMPUTE_SHADER); 3985 } 3986 3987 m_shader_stages.push_back(FRAGMENT_SHADER); 3988 m_shader_stages.push_back(GEOMETRY_SHADER); 3989 m_shader_stages.push_back(TESS_CTRL_SHADER); 3990 m_shader_stages.push_back(TESS_EVAL_SHADER); 3991 m_shader_stages.push_back(VERTEX_SHADER); 3992 } 3993 3994 /** Prepare source code for "tested" shader stage 3995 * 3996 * @param stage_specific_layout String that will replace STAGE_SPECIFIC_LAYOUT token 3997 * @param uniform_definitions String that will replace UNIFORM_DEFINITIONS token 3998 * @param in_variable_definitions String that will replace IN_VARIABLE_DEFINITION token 3999 * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token 4000 * @param uniform_verification String that will replace UNIFORM_VERIFICATION token 4001 * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token 4002 * @param out_source_code Shader source code 4003 **/ 4004 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout, 4005 const glw::GLchar* uniform_definitions, 4006 const glw::GLchar* in_variable_definitions, 4007 const glw::GLchar* out_variable_definitions, 4008 const glw::GLchar* uniform_verification, 4009 const glw::GLchar* stage_specific_main_body, 4010 std::string& out_source_code) const 4011 { 4012 /* Shader template */ 4013 static const glw::GLchar* test_shader_template_code = "#version 400 core\n" 4014 "\n" 4015 "precision highp float;\n" 4016 "\n" 4017 "STAGE_SPECIFIC_LAYOUT" 4018 "UNIFORM_DEFINITIONS" 4019 "IN_VARIABLE_DEFINITION" 4020 "OUT_VARIABLE_DEFINITION" 4021 "\n" 4022 "void main()\n" 4023 "{\n" 4024 "UNIFORM_VERIFICATION" 4025 "STAGE_SPECIFIC_MAIN_BODY" 4026 "}\n" 4027 "\n"; 4028 4029 std::string string = test_shader_template_code; 4030 4031 /* Tokens */ 4032 static const glw::GLchar* body_token = "STAGE_SPECIFIC_MAIN_BODY"; 4033 static const glw::GLchar* in_var_token = "IN_VARIABLE_DEFINITION"; 4034 static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT"; 4035 static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION"; 4036 static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS"; 4037 static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION"; 4038 4039 size_t search_position = 0; 4040 4041 /* Replace tokens */ 4042 Utils::replaceToken(layout_token, search_position, stage_specific_layout, string); 4043 Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string); 4044 Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string); 4045 Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string); 4046 Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string); 4047 Utils::replaceToken(body_token, search_position, stage_specific_main_body, string); 4048 4049 /* Store resuls */ 4050 out_source_code = string; 4051 } 4052 4053 /** Prepare source code for "tested" compute shaders 4054 * 4055 * @param uniform_definitions String that will replace UNIFORM_DEFINITIONS token 4056 * @param uniform_verification String that will replace UNIFORM_VERIFICATION token 4057 * @param out_source_code Source code 4058 **/ 4059 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions, 4060 const glw::GLchar* uniform_verification, 4061 std::string& out_source_code) const 4062 { 4063 /* Shader template */ 4064 static const glw::GLchar* test_shader_template_code = 4065 "#version 420 core\n" 4066 "#extension GL_ARB_compute_shader : require\n" 4067 "#extension GL_ARB_shader_image_load_store : require\n" 4068 "\n" 4069 "precision highp float;\n" 4070 "\n" 4071 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 4072 "\n" 4073 "UNIFORM_DEFINITIONS" 4074 "layout(r32i) writeonly uniform iimage2D result;\n" 4075 "\n" 4076 "void main()\n" 4077 "{\n" 4078 "UNIFORM_VERIFICATION" 4079 "\n" 4080 " imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n" 4081 "}\n" 4082 "\n"; 4083 4084 std::string string = test_shader_template_code; 4085 4086 /* Tokens */ 4087 static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS"; 4088 static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION"; 4089 4090 size_t search_position = 0; 4091 4092 /* Replace tokens */ 4093 Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string); 4094 Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string); 4095 4096 /* Store resuls */ 4097 out_source_code = string; 4098 } 4099 4100 /** Prepare source code which defines uniforms for tested shader stage 4101 * 4102 * @param shader_stage Shader stage id 4103 * @param uniform_type Details of uniform type 4104 * @param out_source_code Source code 4105 **/ 4106 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type, 4107 std::string& out_source_code) const 4108 { 4109 const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type); 4110 std::stringstream stream; 4111 4112 /* 4113 * layout(std140) uniform M_UNIFORM_BLOCK_NAME 4114 * { 4115 * TYPE_NAME uniform_array[N_UNIFORMS]; 4116 * }; 4117 */ 4118 stream << "layout(std140) uniform " << m_uniform_block_name << "\n" 4119 "{\n"; 4120 4121 stream << " " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n"; 4122 4123 stream << "};\n\n"; 4124 4125 out_source_code = stream.str(); 4126 } 4127 4128 /** Prepare uniform buffer for test 4129 * 4130 * @param shader_stage Shader stage id 4131 * @param uniform_type Details of uniform type 4132 * @param program_info Program object info 4133 **/ 4134 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type, 4135 const Utils::programInfo& program_info) const 4136 { 4137 glw::GLint buffer_size = 0; 4138 glw::GLuint element_ordinal = 1; 4139 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4140 const glw::GLuint n_columns = uniform_type.m_n_columns; 4141 const glw::GLuint n_rows = uniform_type.m_n_rows; 4142 const glw::GLuint n_elements = n_columns * n_rows; 4143 uniformDetails uniform_details; 4144 const glw::GLuint program_id = program_info.m_program_object_id; 4145 const glw::GLint n_uniforms = getAmountUniforms(shader_stage, uniform_type); 4146 std::vector<glw::GLubyte> uniform_buffer_data; 4147 glw::GLuint uniform_block_index = 0; 4148 4149 /* Get uniform details */ 4150 inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index); 4151 4152 /* Uniform offset and strides */ 4153 const glw::GLuint array_stride = uniform_details.m_array_stride; 4154 const glw::GLuint matrix_stride = uniform_details.m_matrix_stride; 4155 const glw::GLuint uniform_offset = uniform_details.m_offset; 4156 4157 /* Prepare storage for buffer data */ 4158 uniform_buffer_data.resize(buffer_size); 4159 4160 /* Prepare uniform data */ 4161 for (glw::GLint i = 0; i < n_uniforms; ++i) 4162 { 4163 const glw::GLuint array_entry_offset = uniform_offset + i * array_stride; 4164 4165 for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal) 4166 { 4167 const glw::GLuint column = element / n_rows; 4168 const glw::GLuint column_elem = element % n_rows; 4169 const glw::GLdouble value = element_ordinal; 4170 const glw::GLuint value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride + 4171 column_elem * sizeof(glw::GLdouble)); 4172 glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset]; 4173 4174 *value_dst = value; 4175 } 4176 } 4177 4178 /* Update uniform buffer with new set of data */ 4179 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id); 4180 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 4181 4182 gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW); 4183 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData"); 4184 4185 /* Bind uniform block to uniform buffer */ 4186 gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size); 4187 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange"); 4188 4189 gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */); 4190 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding"); 4191 } 4192 4193 /** Prepare collection of tested uniform types 4194 * 4195 **/ 4196 void GPUShaderFP64Test2::prepareUniformTypes() 4197 { 4198 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */)); 4199 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */)); 4200 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */)); 4201 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */)); 4202 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */)); 4203 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */)); 4204 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */)); 4205 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */)); 4206 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */)); 4207 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */)); 4208 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */)); 4209 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */)); 4210 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */)); 4211 } 4212 4213 /** Prepare source code that verifes uniform values 4214 * 4215 * @param shader_stage Shader stage id 4216 * @param uniform_type Details of uniform type 4217 * @param out_source_code Source code 4218 **/ 4219 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type, 4220 std::string& out_source_code) const 4221 { 4222 glw::GLuint element_ordinal = 1; 4223 const glw::GLuint n_columns = uniform_type.m_n_columns; 4224 const glw::GLuint n_rows = uniform_type.m_n_rows; 4225 const glw::GLuint n_elements = n_columns * n_rows; 4226 const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type); 4227 std::stringstream stream; 4228 4229 /* 4230 * int verification_result = M_RESULT_SUCCESS; 4231 * 4232 * for (int i = 0; i < N_UNIFORMS; ++i) 4233 * { 4234 * if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i]) 4235 * { 4236 * verification_result = M_RESULT_FAILURE 4237 * } 4238 * } 4239 */ 4240 stream << " int verification_result = " << m_result_success << ";\n" 4241 "\n" 4242 " for (int i = 0; i < " 4243 << n_uniforms << "; ++i)\n" 4244 " {\n" 4245 " if (" 4246 << uniform_type.m_type_name << "("; 4247 4248 for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal) 4249 { 4250 stream << "i * (" << n_elements << ") + " << element + 1; 4251 4252 if (n_elements != element + 1) 4253 { 4254 stream << ", "; 4255 } 4256 } 4257 4258 stream << ") != uniform_array[i])\n" 4259 " {\n" 4260 " verification_result = " 4261 << m_result_failure << ";\n" 4262 " }\n" 4263 " }\n"; 4264 4265 out_source_code = stream.str(); 4266 } 4267 4268 /** Execute test for given combination of "tested" shader stage and uniform type 4269 * 4270 * @param shader_stage Tested shader stage id 4271 * @param uniform_type Tested uniform type 4272 * 4273 * @return true if test passed, false otherwise 4274 **/ 4275 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const 4276 { 4277 const glw::GLenum draw_primitive = getDrawPrimitiveType(shader_stage); 4278 static const glw::GLint first_vertex = 0; 4279 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4280 const glw::GLsizei n_vertices = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results; 4281 Utils::programInfo program_info(m_context); 4282 bool result = true; 4283 4284 /* Prepare program */ 4285 prepareProgram(shader_stage, uniform_type, program_info); 4286 4287 gl.useProgram(program_info.m_program_object_id); 4288 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 4289 4290 /* Prepare uniform buffer and bind it with uniform block */ 4291 prepareUniforms(shader_stage, uniform_type, program_info); 4292 4293 /* Prepare storage for test results */ 4294 testBegin(program_info.m_program_object_id, shader_stage); 4295 4296 /* Execute */ 4297 if (COMPUTE_SHADER == shader_stage) 4298 { 4299 m_pDispatchCompute(m_texture_width, m_texture_height, 1); 4300 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); 4301 } 4302 else 4303 { 4304 gl.drawArrays(draw_primitive, first_vertex, n_vertices); 4305 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 4306 } 4307 4308 /* Clean after test */ 4309 testEnd(shader_stage); 4310 4311 /* Check results */ 4312 if (false == verifyResults(shader_stage)) 4313 { 4314 m_context.getTestContext().getLog() 4315 << tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage) 4316 << ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage; 4317 4318 result = false; 4319 } 4320 4321 return result; 4322 } 4323 4324 /** Prepare transform feedback buffer, framebuffer or image unit for test results 4325 * 4326 * @param program_id Program object id 4327 * @param shader_stage Tested shader stage id 4328 **/ 4329 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const 4330 { 4331 std::vector<glw::GLint> buffer_data; 4332 const glw::GLenum captured_primitive = getCapturedPrimitiveType(shader_stage); 4333 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4334 4335 /* Prepare buffer filled with m_result_failure */ 4336 buffer_data.resize(m_n_captured_results); 4337 for (glw::GLuint i = 0; i < m_n_captured_results; ++i) 4338 { 4339 buffer_data[i] = m_result_failure; 4340 } 4341 4342 /* Prepare buffer for test results */ 4343 switch (shader_stage) 4344 { 4345 case GEOMETRY_SHADER: 4346 case TESS_CTRL_SHADER: 4347 case TESS_EVAL_SHADER: 4348 case VERTEX_SHADER: 4349 4350 /* Verify getTransformFeedbackVarying results */ 4351 { 4352 glw::GLsizei size = 0; 4353 glw::GLenum type = 0; 4354 glw::GLchar name[16]; 4355 4356 gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type, 4357 name); 4358 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying"); 4359 4360 if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name))) 4361 { 4362 m_context.getTestContext().getLog() 4363 << tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results." 4364 << " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT 4365 << ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage; 4366 4367 TCU_FAIL("Invalid GetTransformFeedbackVarying results"); 4368 } 4369 } 4370 4371 /* Create/clean transform feedback buffer */ 4372 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id); 4373 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 4374 4375 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY); 4376 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData"); 4377 4378 /* Set up transform feedback buffer */ 4379 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */, 4380 m_transform_feedback_buffer_size); 4381 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange"); 4382 4383 gl.beginTransformFeedback(captured_primitive); 4384 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 4385 4386 break; 4387 4388 case FRAGMENT_SHADER: 4389 4390 /* Clean texture */ 4391 gl.bindTexture(GL_TEXTURE_2D, m_texture_id); 4392 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 4393 4394 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height, 4395 GL_RED_INTEGER, GL_INT, &buffer_data[0]); 4396 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 4397 4398 /* Set up texture as color attachment 0 */ 4399 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id); 4400 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer"); 4401 4402 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */); 4403 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D"); 4404 4405 gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height); 4406 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); 4407 4408 break; 4409 4410 case COMPUTE_SHADER: 4411 4412 /* Clean texture */ 4413 gl.bindTexture(GL_TEXTURE_2D, m_texture_id); 4414 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 4415 4416 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height, 4417 GL_RED_INTEGER, GL_INT, &buffer_data[0]); 4418 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 4419 4420 glw::GLint location = gl.getUniformLocation(program_id, "result"); 4421 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 4422 4423 if (-1 == location) 4424 { 4425 TCU_FAIL("Inactive uniform \"result\""); 4426 } 4427 4428 gl.uniform1i(location, 0 /* first image unit */); 4429 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 4430 4431 /* Bind texture to first image unit */ 4432 gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 4433 0 /* layer */, GL_WRITE_ONLY, GL_R32I); 4434 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture"); 4435 4436 break; 4437 } 4438 } 4439 4440 /** Unbind transform feedback buffer, framebuffer or image unit 4441 * 4442 * @param shader_stage Tested shader stage id 4443 **/ 4444 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const 4445 { 4446 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4447 4448 switch (shader_stage) 4449 { 4450 case GEOMETRY_SHADER: 4451 case TESS_CTRL_SHADER: 4452 case TESS_EVAL_SHADER: 4453 case VERTEX_SHADER: 4454 4455 gl.endTransformFeedback(); 4456 4457 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 4458 4459 break; 4460 4461 case FRAGMENT_SHADER: 4462 4463 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */, 4464 0 /* level */); 4465 4466 gl.bindTexture(GL_TEXTURE_2D, 0); 4467 4468 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 4469 4470 break; 4471 4472 case COMPUTE_SHADER: 4473 4474 gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */, 4475 0 /* layer */, GL_WRITE_ONLY, GL_R32I); 4476 4477 break; 4478 } 4479 } 4480 4481 /** Initialize OpenGL objects for test 4482 * 4483 **/ 4484 void GPUShaderFP64Test2::testInit() 4485 { 4486 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4487 4488 /* The test is in 4.0 group. However: 4489 * - compute_shader is core since 4.3 4490 * - compute_shader require at least version 4.2 of GL */ 4491 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) && 4492 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */))) 4493 { 4494 m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute; 4495 } 4496 4497 /* Tesselation patch set up */ 4498 gl.patchParameteri(GL_PATCH_VERTICES, 1); 4499 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); 4500 4501 /* Generate FBO */ 4502 gl.genFramebuffers(1, &m_framebuffer_id); 4503 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers"); 4504 4505 /* Prepare texture */ 4506 gl.genTextures(1, &m_texture_id); 4507 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); 4508 4509 gl.bindTexture(GL_TEXTURE_2D, m_texture_id); 4510 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 4511 4512 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height); 4513 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); 4514 4515 /* Prepare transform feedback buffer */ 4516 gl.genBuffers(1, &m_transform_feedback_buffer_id); 4517 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 4518 4519 /* Generate uniform buffer */ 4520 gl.genBuffers(1, &m_uniform_buffer_id); 4521 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 4522 4523 /* Prepare VAO */ 4524 gl.genVertexArrays(1, &m_vertex_array_object_id); 4525 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); 4526 4527 gl.bindVertexArray(m_vertex_array_object_id); 4528 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray"); 4529 } 4530 4531 /** Result verification, expected result is that whole buffer is filled with m_result_success 4532 * 4533 * @param shader_stage Tested shader stage id 4534 **/ 4535 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const 4536 { 4537 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4538 4539 if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage)) 4540 { 4541 /* Verify contents of texture */ 4542 4543 /* Prepare storage for testure data */ 4544 std::vector<glw::GLint> image_data; 4545 image_data.resize(m_texture_width * m_texture_height); 4546 4547 /* Get texture contents */ 4548 gl.bindTexture(GL_TEXTURE_2D, m_texture_id); 4549 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 4550 4551 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]); 4552 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage"); 4553 4554 for (glw::GLuint y = 0; y < m_texture_width; ++y) 4555 { 4556 for (glw::GLuint x = 0; x < m_texture_height; ++x) 4557 { 4558 const glw::GLuint offset = y * m_texture_width + x; 4559 const glw::GLint value = image_data[offset]; 4560 4561 if (m_result_success != value) 4562 { 4563 m_context.getTestContext().getLog() 4564 << tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")" 4565 << tcu::TestLog::EndMessage; 4566 4567 return false; 4568 } 4569 } 4570 } 4571 4572 return true; 4573 } 4574 else 4575 { 4576 /* Verify contents of transform feedback buffer */ 4577 4578 bool result = true; 4579 4580 /* Get transform feedback data */ 4581 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id); 4582 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 4583 4584 glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 4585 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 4586 4587 for (glw::GLuint i = 0; i < m_n_captured_results; ++i) 4588 { 4589 const glw::GLint value = feedback_data[i]; 4590 4591 if (m_result_success != value) 4592 { 4593 m_context.getTestContext().getLog() << tcu::TestLog::Message 4594 << "Error. Transform feedback buffer contents are wrong at " << i 4595 << tcu::TestLog::EndMessage; 4596 4597 result = false; 4598 break; 4599 } 4600 } 4601 4602 /* Unmap transform feedback buffer */ 4603 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4604 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 4605 4606 return result; 4607 } 4608 } 4609 4610 /* Definitions of static const fields declared in GPUShaderFP64Test3 */ 4611 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0; 4612 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1; 4613 4614 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name = "UniformBlock"; 4615 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block"; 4616 4617 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result = "fs_out_fs_result"; 4618 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result = "gs_fs_gs_result"; 4619 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result = "gs_fs_tcs_result"; 4620 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result = "gs_fs_tes_result"; 4621 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result = "gs_fs_vs_result"; 4622 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result"; 4623 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result = "tcs_tes_vs_result"; 4624 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result = "tes_gs_tcs_result"; 4625 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result = "tes_gs_tes_result"; 4626 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result = "tes_gs_vs_result"; 4627 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result = "vs_tcs_vs_result"; 4628 4629 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */ 4630 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset = -1; 4631 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride = -1; 4632 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0; 4633 4634 /** Constructor 4635 * 4636 * @param context Test context 4637 **/ 4638 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context) 4639 : TestCase(context, "named_uniform_blocks", 4640 "Verifies usage of \"double precision\" floats in \"named uniform block\"") 4641 { 4642 /* Nothing to be done */ 4643 } 4644 4645 /** Deinitialize test 4646 * 4647 **/ 4648 void GPUShaderFP64Test3::deinit() 4649 { 4650 /* GL entry points */ 4651 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4652 4653 /* Clean programs */ 4654 m_packed_program.deinit(m_context); 4655 m_shared_program.deinit(m_context); 4656 m_std140_program.deinit(m_context); 4657 4658 /* Clean frambuffer */ 4659 if (0 != m_framebuffer_id) 4660 { 4661 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 4662 gl.deleteFramebuffers(1, &m_framebuffer_id); 4663 4664 m_framebuffer_id = 0; 4665 } 4666 4667 /* Clean texture */ 4668 if (0 != m_color_texture_id) 4669 { 4670 gl.bindTexture(GL_TEXTURE_2D, 0); 4671 gl.deleteTextures(1, &m_color_texture_id); 4672 4673 m_color_texture_id = 0; 4674 } 4675 4676 /* Clean buffers */ 4677 if (0 != m_transform_feedback_buffer_id) 4678 { 4679 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 4680 gl.deleteBuffers(1, &m_transform_feedback_buffer_id); 4681 4682 m_transform_feedback_buffer_id = 0; 4683 } 4684 4685 if (0 != m_uniform_buffer_id) 4686 { 4687 gl.bindBuffer(GL_UNIFORM_BUFFER, 0); 4688 gl.deleteBuffers(1, &m_uniform_buffer_id); 4689 4690 m_uniform_buffer_id = 0; 4691 } 4692 4693 /* Clean VAO */ 4694 if (0 != m_vertex_array_object_id) 4695 { 4696 gl.bindVertexArray(0); 4697 gl.deleteVertexArrays(1, &m_vertex_array_object_id); 4698 4699 m_vertex_array_object_id = 0; 4700 } 4701 } 4702 4703 /** Execute test 4704 * 4705 * @return tcu::TestNode::STOP 4706 **/ 4707 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate() 4708 { 4709 bool result = true; 4710 4711 /* Check if extension is supported */ 4712 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 4713 { 4714 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported"); 4715 } 4716 4717 /* Initialize test */ 4718 testInit(); 4719 4720 /* Test "packed" uniform buffer layout */ 4721 if (false == test(PACKED)) 4722 { 4723 result = false; 4724 } 4725 4726 /* Test "shared" uniform buffer layout */ 4727 if (false == test(SHARED)) 4728 { 4729 result = false; 4730 } 4731 4732 /* Test "std140" uniform buffer layout */ 4733 if (false == test(STD140)) 4734 { 4735 result = false; 4736 } 4737 4738 /* Set result */ 4739 if (true == result) 4740 { 4741 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4742 } 4743 else 4744 { 4745 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4746 } 4747 4748 /* Done */ 4749 return tcu::TestNode::STOP; 4750 } 4751 4752 /** Constructor 4753 * 4754 **/ 4755 GPUShaderFP64Test3::programInfo::programInfo() 4756 : m_fragment_shader_id(0) 4757 , m_geometry_shader_id(0) 4758 , m_program_object_id(0) 4759 , m_tesselation_control_shader_id(0) 4760 , m_tesselation_evaluation_shader_id(0) 4761 , m_vertex_shader_id(0) 4762 , m_buffer_size(0) 4763 , m_uniform_block_index(0) 4764 { 4765 /* Nothing to be done here */ 4766 } 4767 4768 /** Compile shader 4769 * 4770 * @param context Test context 4771 * @param shader_id Shader object id 4772 * @param shader_code Shader source code 4773 **/ 4774 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id, 4775 const glw::GLchar* shader_code) const 4776 { 4777 /* GL entry points */ 4778 const glw::Functions& gl = context.getRenderContext().getFunctions(); 4779 4780 /* Compilation status */ 4781 glw::GLint status = GL_FALSE; 4782 4783 /* Set source code */ 4784 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0); 4785 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource"); 4786 4787 /* Compile */ 4788 gl.compileShader(shader_id); 4789 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader"); 4790 4791 /* Get compilation status */ 4792 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status); 4793 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 4794 4795 /* Log compilation error */ 4796 if (GL_TRUE != status) 4797 { 4798 glw::GLint length = 0; 4799 std::vector<glw::GLchar> message; 4800 4801 /* Error log length */ 4802 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length); 4803 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); 4804 4805 /* Prepare storage */ 4806 message.resize(length); 4807 4808 /* Get error log */ 4809 gl.getShaderInfoLog(shader_id, length, 0, &message[0]); 4810 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog"); 4811 4812 /* Log */ 4813 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n" 4814 << &message[0] << "\nShader source\n" 4815 << shader_code << tcu::TestLog::EndMessage; 4816 4817 TCU_FAIL("Failed to compile shader"); 4818 } 4819 } 4820 4821 /** Cleans program and attached shaders 4822 * 4823 * @param context Test context 4824 **/ 4825 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context) 4826 { 4827 /* GL entry points */ 4828 const glw::Functions& gl = context.getRenderContext().getFunctions(); 4829 4830 /* Restore default program */ 4831 gl.useProgram(0); 4832 4833 /* Clean program object */ 4834 if (0 != m_program_object_id) 4835 { 4836 gl.deleteProgram(m_program_object_id); 4837 m_program_object_id = 0; 4838 } 4839 4840 /* Clean shaders */ 4841 if (0 != m_fragment_shader_id) 4842 { 4843 gl.deleteShader(m_fragment_shader_id); 4844 m_fragment_shader_id = 0; 4845 } 4846 4847 if (0 != m_geometry_shader_id) 4848 { 4849 gl.deleteShader(m_geometry_shader_id); 4850 m_geometry_shader_id = 0; 4851 } 4852 4853 if (0 != m_tesselation_control_shader_id) 4854 { 4855 gl.deleteShader(m_tesselation_control_shader_id); 4856 m_tesselation_control_shader_id = 0; 4857 } 4858 4859 if (0 != m_tesselation_evaluation_shader_id) 4860 { 4861 gl.deleteShader(m_tesselation_evaluation_shader_id); 4862 m_tesselation_evaluation_shader_id = 0; 4863 } 4864 4865 if (0 != m_vertex_shader_id) 4866 { 4867 gl.deleteShader(m_vertex_shader_id); 4868 m_vertex_shader_id = 0; 4869 } 4870 } 4871 4872 /** Build program and query for uniform layout 4873 * 4874 * @param context Test context 4875 * @param uniform_details Collection of uniform details 4876 * @param fragment_shader_code Fragment shader source code 4877 * @param geometry_shader_code Geometry shader source code 4878 * @param tesselation_control_shader_code Tesselation control shader source code 4879 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code 4880 * @param vertex_shader_code Vertex shader source code 4881 **/ 4882 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details, 4883 const glw::GLchar* fragment_shader_code, 4884 const glw::GLchar* geometry_shader_code, 4885 const glw::GLchar* tesselation_control_shader_code, 4886 const glw::GLchar* tesselation_evaluation_shader_code, 4887 const glw::GLchar* vertex_shader_code) 4888 { 4889 /* GL entry points */ 4890 const glw::Functions& gl = context.getRenderContext().getFunctions(); 4891 4892 /* Names of varyings to be captured with transform feedback */ 4893 static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result, 4894 m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result }; 4895 static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]); 4896 4897 /* Create shader objects */ 4898 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 4899 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER); 4900 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER); 4901 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER); 4902 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 4903 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); 4904 4905 /* Create program object */ 4906 m_program_object_id = gl.createProgram(); 4907 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram"); 4908 4909 /* Set up names of varyings to be captured with transform feedback */ 4910 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS); 4911 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings"); 4912 4913 /* Compile shaders */ 4914 compile(context, m_fragment_shader_id, fragment_shader_code); 4915 compile(context, m_geometry_shader_id, geometry_shader_code); 4916 compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code); 4917 compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code); 4918 compile(context, m_vertex_shader_id, vertex_shader_code); 4919 4920 /* Link program */ 4921 link(context); 4922 4923 /* Inspect program object */ 4924 /* Get index of named uniform block */ 4925 m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name); 4926 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex"); 4927 4928 if (GL_INVALID_INDEX == m_uniform_block_index) 4929 { 4930 TCU_FAIL("Unifom block is inactive"); 4931 } 4932 4933 /* Get size of named uniform block */ 4934 gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size); 4935 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv"); 4936 4937 if (0 == m_buffer_size) 4938 { 4939 TCU_FAIL("Unifom block size is 0"); 4940 } 4941 4942 /* Get information about "double precision" uniforms */ 4943 for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end(); 4944 end != it; ++it) 4945 { 4946 const glw::GLchar* uniform_name = 0; 4947 std::string uniform_name_str; 4948 std::stringstream uniform_name_stream; 4949 glw::GLuint index = 0; 4950 glw::GLint offset = 0; 4951 glw::GLint matrix_stride = 0; 4952 4953 /* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */ 4954 uniform_name_stream << m_uniform_block_name << "." << it->m_name; 4955 4956 uniform_name_str = uniform_name_stream.str(); 4957 uniform_name = uniform_name_str.c_str(); 4958 4959 /* Get index of uniform */ 4960 gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index); 4961 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices"); 4962 4963 if (GL_INVALID_INDEX == index) 4964 { 4965 TCU_FAIL("Unifom is inactive"); 4966 } 4967 4968 /* Get offset of uniform */ 4969 gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset); 4970 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv"); 4971 4972 if (m_invalid_uniform_offset == offset) 4973 { 4974 TCU_FAIL("Unifom has invalid offset"); 4975 } 4976 4977 m_uniform_offsets.push_back(offset); 4978 4979 /* Get matrix stride of uniform */ 4980 gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride); 4981 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv"); 4982 4983 if (m_invalid_uniform_matrix_stride == offset) 4984 { 4985 TCU_FAIL("Unifom has invalid matrix stride"); 4986 } 4987 4988 m_uniform_matrix_strides.push_back(matrix_stride); 4989 } 4990 } 4991 4992 /** Attach shaders and link program 4993 * 4994 * @param context Test context 4995 **/ 4996 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const 4997 { 4998 /* GL entry points */ 4999 const glw::Functions& gl = context.getRenderContext().getFunctions(); 5000 5001 /* Link status */ 5002 glw::GLint status = GL_FALSE; 5003 5004 /* Attach shaders */ 5005 gl.attachShader(m_program_object_id, m_fragment_shader_id); 5006 gl.attachShader(m_program_object_id, m_geometry_shader_id); 5007 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id); 5008 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id); 5009 gl.attachShader(m_program_object_id, m_vertex_shader_id); 5010 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); 5011 5012 /* Link */ 5013 gl.linkProgram(m_program_object_id); 5014 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram"); 5015 5016 /* Get link status */ 5017 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status); 5018 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 5019 5020 /* Log link error */ 5021 if (GL_TRUE != status) 5022 { 5023 glw::GLint length = 0; 5024 std::vector<glw::GLchar> message; 5025 5026 /* Get error log length */ 5027 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length); 5028 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); 5029 5030 message.resize(length); 5031 5032 /* Get error log */ 5033 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]); 5034 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog"); 5035 5036 /* Log */ 5037 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n" 5038 << &message[0] << tcu::TestLog::EndMessage; 5039 5040 TCU_FAIL("Failed to link program"); 5041 } 5042 } 5043 5044 /** Returns "predefined" values that will be used to fill uniform data 5045 * 5046 * @param type_ordinal Ordinal number of "double precision" uniform type 5047 * @param element Index of element in uniform 5048 * 5049 * @return "Predefined" value 5050 **/ 5051 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const 5052 { 5053 return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) + 5054 ((m_base_element - (glw::GLdouble)element) / 4.0); 5055 } 5056 5057 /** Returns a reference of programInfo instance specific for given buffer layout 5058 * 5059 * @param uniform_data_layout Buffer layout 5060 * 5061 * @return Reference to an instance of programInfo 5062 **/ 5063 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const 5064 { 5065 const programInfo* program_info = 0; 5066 5067 switch (uniform_data_layout) 5068 { 5069 case PACKED: 5070 5071 program_info = &m_packed_program; 5072 5073 break; 5074 5075 case SHARED: 5076 5077 program_info = &m_shared_program; 5078 5079 break; 5080 5081 case STD140: 5082 5083 program_info = &m_std140_program; 5084 5085 break; 5086 } 5087 5088 return *program_info; 5089 } 5090 5091 /** Get "name" of buffer layout 5092 * 5093 * @param uniform_data_layout Buffer layout 5094 * 5095 * @return "Name" of layout 5096 **/ 5097 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const 5098 { 5099 const glw::GLchar* layout = ""; 5100 5101 switch (uniform_data_layout) 5102 { 5103 case PACKED: 5104 layout = "packed"; 5105 break; 5106 case SHARED: 5107 layout = "shared"; 5108 break; 5109 case STD140: 5110 layout = "std140"; 5111 break; 5112 } 5113 5114 return layout; 5115 } 5116 5117 /** Prepare programInfo instance for specific buffer layout 5118 * 5119 * @param program_info Instance of programInfo 5120 * @param uniform_data_layout Buffer layout 5121 **/ 5122 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const 5123 { 5124 /* Storage for shader source code */ 5125 std::stringstream fragment_shader_code; 5126 std::stringstream geometry_shader_code; 5127 std::stringstream tess_control_shader_code; 5128 std::stringstream tess_eval_shader_code; 5129 std::stringstream vertex_shader_code; 5130 5131 /* Write preambles */ 5132 writePreamble(fragment_shader_code, FRAGMENT_SHADER); 5133 writePreamble(geometry_shader_code, GEOMETRY_SHADER); 5134 writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER); 5135 writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER); 5136 writePreamble(vertex_shader_code, VERTEX_SHADER); 5137 5138 /* Write definition of named uniform block */ 5139 writeUniformBlock(fragment_shader_code, uniform_data_layout); 5140 writeUniformBlock(geometry_shader_code, uniform_data_layout); 5141 writeUniformBlock(tess_control_shader_code, uniform_data_layout); 5142 writeUniformBlock(tess_eval_shader_code, uniform_data_layout); 5143 writeUniformBlock(vertex_shader_code, uniform_data_layout); 5144 5145 /* Write definitions of varyings */ 5146 writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER); 5147 writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER); 5148 writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER); 5149 writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER); 5150 writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER); 5151 5152 /* Write main routine */ 5153 writeMainBody(fragment_shader_code, FRAGMENT_SHADER); 5154 writeMainBody(geometry_shader_code, GEOMETRY_SHADER); 5155 writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER); 5156 writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER); 5157 writeMainBody(vertex_shader_code, VERTEX_SHADER); 5158 5159 /* Init programInfo instance */ 5160 program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(), 5161 geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(), 5162 tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str()); 5163 } 5164 5165 /** Prepare uniform buffer 5166 * 5167 * @param program_info Instance of programInfo 5168 * @param verify_offsets If uniform offsets should be verified against expected values 5169 * 5170 * @return false if uniform offsets verification result is failure, true otherwise 5171 **/ 5172 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const 5173 { 5174 const glw::GLuint buffer_size = program_info.m_buffer_size; 5175 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5176 bool offset_verification_result = true; 5177 glw::GLuint type_ordinal = 1; 5178 std::vector<uniformDetails>::const_iterator it_uniform_details = m_uniform_details.begin(); 5179 std::vector<glw::GLint>::const_iterator it_uniform_offsets = program_info.m_uniform_offsets.begin(); 5180 std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin(); 5181 5182 /* Prepare storage for uniform buffer data */ 5183 std::vector<glw::GLubyte> buffer_data; 5184 buffer_data.resize(buffer_size); 5185 5186 /* For each "double precision" uniform */ 5187 for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details; 5188 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal) 5189 { 5190 const glw::GLint matrix_stride = *it_uniform_matrix_strides; 5191 const glw::GLuint n_columns = it_uniform_details->m_n_columns; 5192 const glw::GLuint n_elements = it_uniform_details->m_n_elements; 5193 const glw::GLuint column_length = n_elements / n_columns; 5194 const glw::GLint uniform_offset = *it_uniform_offsets; 5195 5196 /* For each element of uniform */ 5197 for (glw::GLuint element = 0; element < n_elements; ++element) 5198 { 5199 const glw::GLuint column = element / column_length; 5200 const glw::GLuint column_elem = element % column_length; 5201 const glw::GLdouble value = getExpectedValue(type_ordinal, element); 5202 const glw::GLuint value_offset = 5203 static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble)); 5204 5205 glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset]; 5206 5207 /* Store value */ 5208 *value_dst = value; 5209 } 5210 5211 /* Uniform offset verification */ 5212 if (true == verify_offsets) 5213 { 5214 const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset; 5215 5216 if (expected_offset != uniform_offset) 5217 { 5218 if (true == offset_verification_result) 5219 { 5220 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage; 5221 } 5222 5223 m_context.getTestContext().getLog() 5224 << tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name 5225 << " has offset: " << uniform_offset << ". Expected offset: " << expected_offset 5226 << tcu::TestLog::EndMessage; 5227 5228 offset_verification_result = false; 5229 } 5230 } 5231 } 5232 5233 /* Update uniform buffer with prepared data */ 5234 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id); 5235 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 5236 5237 gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW); 5238 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData"); 5239 5240 /* Bind uniform buffer as data source for named uniform block */ 5241 gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size); 5242 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange"); 5243 5244 gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */); 5245 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding"); 5246 5247 /* Done */ 5248 return offset_verification_result; 5249 } 5250 5251 /** Prepare data, execute draw call and verify results 5252 * 5253 * @param uniform_data_layout 5254 * 5255 * @return true if test pass, false otherwise 5256 **/ 5257 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const 5258 { 5259 bool are_offsets_verified = (STD140 == uniform_data_layout); 5260 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5261 bool offset_verification_result = true; 5262 const programInfo& program_info = getProgramInfo(uniform_data_layout); 5263 bool result = true; 5264 5265 /* Set up program */ 5266 gl.useProgram(program_info.m_program_object_id); 5267 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 5268 5269 /* Prepare uniform buffer */ 5270 offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified); 5271 5272 if (true == are_offsets_verified && false == offset_verification_result) 5273 { 5274 /* Offsets verification failure was already reported, add info about buffer layout */ 5275 m_context.getTestContext().getLog() << tcu::TestLog::Message 5276 << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout) 5277 << tcu::TestLog::EndMessage; 5278 5279 result = false; 5280 } 5281 5282 /* Set up transform feedback buffer */ 5283 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint)); 5284 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 5285 5286 /* Begin transform feedback */ 5287 gl.beginTransformFeedback(GL_POINTS); 5288 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 5289 5290 /* Execute draw call for singe vertex */ 5291 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */); 5292 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 5293 5294 /* Stop transform feedback */ 5295 gl.endTransformFeedback(); 5296 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 5297 5298 /* Verify results */ 5299 if (false == verifyResults()) 5300 { 5301 /* Result verificatioon failure was already reported, add info about layout */ 5302 m_context.getTestContext().getLog() << tcu::TestLog::Message 5303 << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout) 5304 << tcu::TestLog::EndMessage; 5305 5306 result = false; 5307 } 5308 5309 /* Done */ 5310 return result; 5311 } 5312 5313 void GPUShaderFP64Test3::testInit() 5314 { 5315 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5316 5317 /* Uniform block declaration with std140 offsets calculated 5318 * | align | loc_req | begins | ends | offset in bytes | imp | 5319 * ivec3 dummy1[3] | 4 | 12 | 0 | 12 | 0 | | 5320 * double double_value | 2 | 2 | 12 | 14 | 48 | XXX | 5321 * bool dummy2 | 1 | 1 | 14 | 15 | 56 | | 5322 * dvec2 dvec2_value | 4 | 4 | 16 | 20 | 64 | XXX | 5323 * bvec3 dummy3 | 4 | 4 | 20 | 24 | 80 | | 5324 * dvec3 dvec3_value | 8 | 8 | 24 | 32 | 96 | XXX | 5325 * int dummy4[3] | 4 | 12 | 32 | 44 | 128 | | 5326 * dvec4 dvec4_value | 8 | 8 | 48 | 56 | 192 | XXX | 5327 * bool dummy5 | 1 | 1 | 56 | 57 | 224 | | 5328 * bool dummy6[2] | 4 | 8 | 60 | 68 | 240 | | 5329 * dmat2 dmat2_value | 4 | 8 | 68 | 76 | 272 | XXX | 5330 * dmat3 dmat3_value | 8 | 24 | 80 | 104 | 320 | XXX | 5331 * bool dummy7 | 1 | 1 | 104 | 105 | 416 | | 5332 * dmat4 dmat4_value | 8 | 32 | 112 | 144 | 448 | XXX | 5333 * dmat2x3 dmat2x3_value | 8 | 16 | 144 | 160 | 576 | XXX | 5334 * uvec3 dummy8 | 4 | 4 | 160 | 164 | 640 | | 5335 * dmat2x4 dmat2x4_value | 8 | 16 | 168 | 184 | 672 | XXX | 5336 * dmat3x2 dmat3x2_value | 4 | 12 | 184 | 196 | 736 | XXX | 5337 * bool dummy9 | 1 | 1 | 196 | 197 | 784 | | 5338 * dmat3x4 dmat3x4_value | 8 | 24 | 200 | 224 | 800 | XXX | 5339 * int dummy10 | 1 | 1 | 224 | 225 | 896 | | 5340 * dmat4x2 dmat4x2_value | 4 | 16 | 228 | 244 | 912 | XXX | 5341 * dmat4x3 dmat4x3_value | 8 | 32 | 248 | 280 | 992 | XXX | 5342 */ 5343 5344 /* Prepare "double precision" unfiorms' details */ 5345 m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */, 5346 1 /* n_elements */, "double" /* type_name */)); 5347 m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */, 5348 2 /* n_elements */, "dvec2" /* type_name */)); 5349 m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */, 5350 3 /* n_elements */, "dvec3" /* type_name */)); 5351 m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */, 5352 4 /* n_elements */, "dvec4" /* type_name */)); 5353 m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */, 5354 4 /* n_elements */, "dmat2" /* type_name */)); 5355 m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */, 5356 9 /* n_elements */, "dmat3" /* type_name */)); 5357 m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */, 5358 16 /* n_elements */, "dmat4" /* type_name */)); 5359 m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */, 5360 6 /* n_elements */, "dmat2x3" /* type_name */)); 5361 m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */, 5362 8 /* n_elements */, "dmat2x4" /* type_name */)); 5363 m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */, 5364 6 /* n_elements */, "dmat3x2" /* type_name */)); 5365 m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */, 5366 12 /* n_elements */, "dmat3x4" /* type_name */)); 5367 m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */, 5368 8 /* n_elements */, "dmat4x2" /* type_name */)); 5369 m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */, 5370 12 /* n_elements */, "dmat4x3" /* type_name */)); 5371 5372 /* Get random values for getExpectedValue */ 5373 m_base_element = (glw::GLdouble)(rand() % 13); 5374 m_base_type_ordinal = (glw::GLdouble)(rand() % 213); 5375 5376 /* Prepare programInfos for all buffer layouts */ 5377 prepareProgram(m_packed_program, PACKED); 5378 prepareProgram(m_shared_program, SHARED); 5379 prepareProgram(m_std140_program, STD140); 5380 5381 /* Generate buffers */ 5382 gl.genBuffers(1, &m_transform_feedback_buffer_id); 5383 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 5384 5385 gl.genBuffers(1, &m_uniform_buffer_id); 5386 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 5387 5388 /* Prepare transform feedback buffer */ 5389 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id); 5390 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 5391 5392 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY); 5393 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData"); 5394 5395 /* Prepare texture for color attachment 0 */ 5396 gl.genTextures(1, &m_color_texture_id); 5397 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); 5398 5399 gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id); 5400 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 5401 5402 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */); 5403 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); 5404 5405 /* Prepare FBO with color attachment 0 */ 5406 gl.genFramebuffers(1, &m_framebuffer_id); 5407 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers"); 5408 5409 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id); 5410 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer"); 5411 5412 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id, 5413 0 /* level */); 5414 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D"); 5415 5416 gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */); 5417 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); 5418 5419 /* Prepare VAO */ 5420 gl.genVertexArrays(1, &m_vertex_array_object_id); 5421 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); 5422 5423 gl.bindVertexArray(m_vertex_array_object_id); 5424 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray"); 5425 5426 /* Tesselation patch set up */ 5427 gl.patchParameteri(GL_PATCH_VERTICES, 1); 5428 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); 5429 } 5430 5431 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0 5432 * 5433 * @return true if all values are as expected, false otherwise 5434 **/ 5435 bool GPUShaderFP64Test3::verifyResults() const 5436 { 5437 glw::GLint* feedback_data = 0; 5438 bool fragment_shader_result = false; 5439 bool geometry_shader_result = false; 5440 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5441 bool tess_ctrl_shader_result = false; 5442 bool tess_eval_shader_result = false; 5443 bool vertex_shader_result = false; 5444 5445 /* Prepare storage for testure data */ 5446 std::vector<glw::GLint> image_data; 5447 image_data.resize(1); 5448 5449 /* Get texture contents */ 5450 gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id); 5451 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); 5452 5453 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]); 5454 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage"); 5455 5456 /* Get transform feedback data */ 5457 feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 5458 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 5459 5460 /* Verify results */ 5461 fragment_shader_result = (m_result_success == image_data[0]); 5462 geometry_shader_result = (m_result_success == feedback_data[0]); 5463 tess_ctrl_shader_result = (m_result_success == feedback_data[1]); 5464 tess_eval_shader_result = (m_result_success == feedback_data[2]); 5465 vertex_shader_result = (m_result_success == feedback_data[3]); 5466 5467 /* Unmap transform feedback buffer */ 5468 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5469 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 5470 5471 /* Set result */ 5472 if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result && 5473 tess_eval_shader_result && vertex_shader_result)) 5474 { 5475 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage; 5476 5477 m_context.getTestContext().getLog() << tcu::TestLog::Message 5478 << "Vertex shader stage result: " << vertex_shader_result 5479 << tcu::TestLog::EndMessage; 5480 5481 m_context.getTestContext().getLog() << tcu::TestLog::Message 5482 << "Tesselation control shader stage result: " << tess_ctrl_shader_result 5483 << tcu::TestLog::EndMessage; 5484 5485 m_context.getTestContext().getLog() << tcu::TestLog::Message 5486 << "Tesselation evaluation shader stage result: " << tess_eval_shader_result 5487 << tcu::TestLog::EndMessage; 5488 5489 m_context.getTestContext().getLog() << tcu::TestLog::Message 5490 << "Geometry shader stage result: " << geometry_shader_result 5491 << tcu::TestLog::EndMessage; 5492 5493 m_context.getTestContext().getLog() << tcu::TestLog::Message 5494 << "Fragment shader stage result: " << fragment_shader_result 5495 << tcu::TestLog::EndMessage; 5496 5497 return false; 5498 } 5499 else 5500 { 5501 return true; 5502 } 5503 } 5504 5505 /** Write main routine of <shader_stage> shader to stream 5506 * 5507 * @param stream Output stream with source code of shader 5508 * @param shader_stage Shader stage 5509 **/ 5510 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const 5511 { 5512 glw::GLuint type_ordinal = 1; 5513 const glw::GLchar* varying_name = ""; 5514 5515 /* Select name for varying that will hold result of "that" shader_stage */ 5516 switch (shader_stage) 5517 { 5518 case FRAGMENT_SHADER: 5519 varying_name = m_varying_name_fs_out_fs_result; 5520 break; 5521 case GEOMETRY_SHADER: 5522 varying_name = m_varying_name_gs_fs_gs_result; 5523 break; 5524 case TESS_CONTROL_SHADER: 5525 varying_name = m_varying_name_tcs_tes_tcs_result; 5526 break; 5527 case TESS_EVAL_SHADER: 5528 varying_name = m_varying_name_tes_gs_tes_result; 5529 break; 5530 case VERTEX_SHADER: 5531 varying_name = m_varying_name_vs_tcs_vs_result; 5532 break; 5533 } 5534 5535 /* void main() */ 5536 stream << "void main()\n" 5537 "{\n"; 5538 5539 /* Tesselation levels output */ 5540 if (TESS_CONTROL_SHADER == shader_stage) 5541 { 5542 stream << "gl_TessLevelOuter[0] = 1.0;\n" 5543 "gl_TessLevelOuter[1] = 1.0;\n" 5544 "gl_TessLevelOuter[2] = 1.0;\n" 5545 "gl_TessLevelOuter[3] = 1.0;\n" 5546 "gl_TessLevelInner[0] = 1.0;\n" 5547 "gl_TessLevelInner[1] = 1.0;\n" 5548 "\n"; 5549 } 5550 5551 /* For each "double precision" uniform 5552 * 5553 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME) 5554 * { 5555 * VARYING_NAME = m_result_failure; 5556 * } 5557 */ 5558 for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end(); 5559 end != it; ++it, ++type_ordinal) 5560 { 5561 stream << " "; 5562 5563 /* First comparison is done with if, next with else if */ 5564 if (1 != type_ordinal) 5565 { 5566 stream << "else "; 5567 } 5568 5569 /* if (TYPE_NAME( */ 5570 stream << "if (" << it->m_type_name << "("; 5571 5572 /* PREDIFINED_VALUES */ 5573 for (glw::GLuint element = 0; element < it->m_n_elements; ++element) 5574 { 5575 stream << getExpectedValue(type_ordinal, element); 5576 5577 /* Separate with comma */ 5578 if (it->m_n_elements != element + 1) 5579 { 5580 stream << ", "; 5581 } 5582 } 5583 5584 /* 5585 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME) 5586 * { 5587 * VARYING_NAME 5588 */ 5589 stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n" 5590 " {\n" 5591 " " 5592 << varying_name; 5593 5594 /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */ 5595 if (TESS_CONTROL_SHADER == shader_stage) 5596 { 5597 stream << "[gl_InvocationID]"; 5598 } 5599 5600 /* 5601 * = m_result_failure; 5602 * } 5603 */ 5604 stream << " = " << m_result_failure << ";\n" 5605 << " }\n"; 5606 } 5607 5608 /* If all comparisons are ok 5609 * 5610 * else 5611 * { 5612 * VARYING_NAME = m_result_success; 5613 * } 5614 */ 5615 5616 /* 5617 * else 5618 * { 5619 * VARYING_NAME 5620 */ 5621 stream << " else\n" 5622 " {\n" 5623 " " 5624 << varying_name; 5625 5626 /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */ 5627 if (TESS_CONTROL_SHADER == shader_stage) 5628 { 5629 stream << "[gl_InvocationID]"; 5630 } 5631 5632 /* 5633 * = m_result_success; 5634 * } 5635 * 5636 */ 5637 stream << " = " << m_result_success << ";\n" 5638 << " }\n" 5639 << "\n"; 5640 5641 /* For each pair of "input/output" varyings 5642 * 5643 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME; 5644 **/ 5645 writeVaryingPassthrough(stream, shader_stage); 5646 5647 /* Geometry shader have to emit vertex */ 5648 if (GEOMETRY_SHADER == shader_stage) 5649 { 5650 stream << "\n" 5651 "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);" 5652 "EmitVertex();\n" 5653 "EndPrimitive();\n"; 5654 } 5655 5656 /* Close scope of main */ 5657 stream << "}\n\n"; 5658 } 5659 5660 /** Write shader preamble to stream 5661 * 5662 * @param stream Output stream with source code of shader 5663 * @param shader_stage Shader stage 5664 **/ 5665 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const 5666 { 5667 stream << "#version 400 core\n" 5668 "\n" 5669 "precision highp float;\n" 5670 "\n"; 5671 5672 switch (shader_stage) 5673 { 5674 case FRAGMENT_SHADER: 5675 break; 5676 case GEOMETRY_SHADER: 5677 stream << "layout(points) in;\n" 5678 "layout(points, max_vertices = 1) out;\n" 5679 "\n"; 5680 break; 5681 case TESS_CONTROL_SHADER: 5682 stream << "layout(vertices = 1) out;\n" 5683 "\n"; 5684 break; 5685 case TESS_EVAL_SHADER: 5686 stream << "layout(isolines, point_mode) in;\n" 5687 "\n"; 5688 break; 5689 case VERTEX_SHADER: 5690 break; 5691 } 5692 } 5693 5694 /** Write name uniform blcok definition with specific layout to stream 5695 * 5696 * @param stream Output stream with source code of shader 5697 * @param uniform_data_layout Buffer layout 5698 **/ 5699 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const 5700 { 5701 const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout); 5702 5703 stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n" 5704 "{\n" 5705 " ivec3 dummy1[3];\n" 5706 " double double_value;\n" 5707 " bool dummy2;\n" 5708 " dvec2 dvec2_value;\n" 5709 " bvec3 dummy3;\n" 5710 " dvec3 dvec3_value;\n" 5711 " int dummy4[3];\n" 5712 " dvec4 dvec4_value;\n" 5713 " bool dummy5;\n" 5714 " bool dummy6[2];\n" 5715 " dmat2 dmat2_value;\n" 5716 " dmat3 dmat3_value;\n" 5717 " bool dummy7;\n" 5718 " dmat4 dmat4_value;\n" 5719 " dmat2x3 dmat2x3_value;\n" 5720 " uvec3 dummy8;\n" 5721 " dmat2x4 dmat2x4_value;\n" 5722 " dmat3x2 dmat3x2_value;\n" 5723 " bool dummy9;\n" 5724 " dmat3x4 dmat3x4_value;\n" 5725 " int dummy10;\n" 5726 " dmat4x2 dmat4x2_value;\n" 5727 " dmat4x3 dmat4x3_value;\n" 5728 "} " 5729 << m_uniform_block_instance_name << ";\n"; 5730 5731 stream << "\n"; 5732 } 5733 5734 /** Write definitions of varyings specific for given <shader_stage> to stream 5735 * 5736 * @param stream Output stream with source code of shader 5737 * @param shader_stage Shader stage 5738 **/ 5739 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const 5740 { 5741 static const glw::GLchar* const varying_type = "int"; 5742 5743 switch (shader_stage) 5744 { 5745 case FRAGMENT_SHADER: 5746 5747 /* In */ 5748 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n"; 5749 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n"; 5750 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n"; 5751 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n"; 5752 5753 stream << "\n"; 5754 5755 /* Out */ 5756 stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n"; 5757 5758 break; 5759 5760 case GEOMETRY_SHADER: 5761 5762 /* In */ 5763 stream << "in " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n"; 5764 stream << "in " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n"; 5765 stream << "in " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n"; 5766 5767 stream << "\n"; 5768 5769 /* Out */ 5770 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n"; 5771 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n"; 5772 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n"; 5773 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n"; 5774 5775 break; 5776 5777 case TESS_CONTROL_SHADER: 5778 5779 /* In */ 5780 stream << "in " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n"; 5781 5782 stream << "\n"; 5783 5784 /* Out */ 5785 stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n"; 5786 stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n"; 5787 5788 break; 5789 5790 case TESS_EVAL_SHADER: 5791 5792 /* In */ 5793 stream << "in " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n"; 5794 stream << "in " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n"; 5795 5796 stream << "\n"; 5797 5798 /* Out */ 5799 stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n"; 5800 stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n"; 5801 stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n"; 5802 5803 break; 5804 5805 case VERTEX_SHADER: 5806 5807 /* Out */ 5808 stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n"; 5809 5810 break; 5811 } 5812 5813 stream << "\n"; 5814 } 5815 5816 /** Write passthrough code of "input/output" varying pairs to stream 5817 * 5818 * @param stream Output stream with source code of shader 5819 * @param shader_stage Shader stage 5820 **/ 5821 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const 5822 { 5823 switch (shader_stage) 5824 { 5825 case FRAGMENT_SHADER: 5826 break; 5827 5828 case GEOMETRY_SHADER: 5829 5830 stream << " " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n"; 5831 stream << " " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n"; 5832 stream << " " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n"; 5833 5834 break; 5835 5836 case TESS_CONTROL_SHADER: 5837 5838 stream << " " << m_varying_name_tcs_tes_vs_result 5839 << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n"; 5840 5841 break; 5842 5843 case TESS_EVAL_SHADER: 5844 5845 stream << " " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n"; 5846 stream << " " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n"; 5847 5848 break; 5849 5850 case VERTEX_SHADER: 5851 5852 break; 5853 } 5854 } 5855 5856 /** Constructor. Sets all uniform locations to -1 and sets all 5857 * values to 0. 5858 */ 5859 GPUShaderFP64Test4::_data::_data() 5860 { 5861 memset(&uniform_double, 0, sizeof(uniform_double)); 5862 memset(uniform_dvec2, 0, sizeof(uniform_dvec2)); 5863 memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr)); 5864 memset(uniform_dvec3, 0, sizeof(uniform_dvec3)); 5865 memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr)); 5866 memset(uniform_dvec4, 0, sizeof(uniform_dvec4)); 5867 memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr)); 5868 5869 uniform_location_double = -1; 5870 uniform_location_double_arr[0] = -1; 5871 uniform_location_double_arr[1] = -1; 5872 uniform_location_dvec2 = -1; 5873 uniform_location_dvec2_arr[0] = -1; 5874 uniform_location_dvec2_arr[1] = -1; 5875 uniform_location_dvec3 = -1; 5876 uniform_location_dvec3_arr[0] = -1; 5877 uniform_location_dvec3_arr[1] = -1; 5878 uniform_location_dvec4 = -1; 5879 uniform_location_dvec4_arr[0] = -1; 5880 uniform_location_dvec4_arr[1] = -1; 5881 } 5882 5883 /** Constructor 5884 * 5885 * @param context Rendering context. 5886 */ 5887 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context) 5888 : TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools" 5889 " report correct properties of & values assigned to double-precision uniforms.") 5890 , m_has_test_passed(true) 5891 , m_uniform_name_buffer(0) 5892 , m_cs_id(0) 5893 , m_fs_id(0) 5894 , m_gs_id(0) 5895 , m_po_cs_id(0) 5896 , m_po_noncs_id(0) 5897 , m_tc_id(0) 5898 , m_te_id(0) 5899 , m_vs_id(0) 5900 { 5901 /* Left blank intentionally */ 5902 } 5903 5904 /** Deinitializes all GL objects, as well as releases all bufers, that may 5905 * have beenallocated or created during test execution. 5906 **/ 5907 void GPUShaderFP64Test4::deinit() 5908 { 5909 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5910 5911 if (m_cs_id != 0) 5912 { 5913 gl.deleteShader(m_cs_id); 5914 5915 m_cs_id = 0; 5916 } 5917 5918 if (m_fs_id != 0) 5919 { 5920 gl.deleteShader(m_fs_id); 5921 5922 m_fs_id = 0; 5923 } 5924 5925 if (m_gs_id != 0) 5926 { 5927 gl.deleteShader(m_gs_id); 5928 5929 m_gs_id = 0; 5930 } 5931 5932 if (m_po_cs_id != 0) 5933 { 5934 gl.deleteProgram(m_po_cs_id); 5935 5936 m_po_cs_id = 0; 5937 } 5938 5939 if (m_po_noncs_id != 0) 5940 { 5941 gl.deleteProgram(m_po_noncs_id); 5942 5943 m_po_noncs_id = 0; 5944 } 5945 5946 if (m_tc_id != 0) 5947 { 5948 gl.deleteShader(m_tc_id); 5949 5950 m_tc_id = 0; 5951 } 5952 5953 if (m_te_id != 0) 5954 { 5955 gl.deleteShader(m_te_id); 5956 5957 m_te_id = 0; 5958 } 5959 5960 if (m_uniform_name_buffer != DE_NULL) 5961 { 5962 delete[] m_uniform_name_buffer; 5963 5964 m_uniform_name_buffer = DE_NULL; 5965 } 5966 5967 if (m_vs_id != 0) 5968 { 5969 gl.deleteShader(m_vs_id); 5970 5971 m_vs_id = 0; 5972 } 5973 } 5974 5975 /** Generates double-precision values for all uniforms defined for all program objects 5976 * used by the test. 5977 * 5978 * This function DOES NOT use any GL API. It only calculates & stores the values 5979 * in internal storage for further usage. 5980 */ 5981 void GPUShaderFP64Test4::generateUniformValues() 5982 { 5983 _stage_data* stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs }; 5984 const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]); 5985 5986 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage) 5987 { 5988 _stage_data* stage_ptr = stages[n_stage]; 5989 5990 /* Iterate through all uniform components and assign them double values */ 5991 double* double_ptrs[] = { 5992 &stage_ptr->uniform_structure_arrays[0].uniform_double, 5993 stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0, 5994 stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1, 5995 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0, 5996 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1, 5997 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 2, 5998 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 3, 5999 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0, 6000 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1, 6001 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2, 6002 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 3, 6003 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 4, 6004 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 5, 6005 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0, 6006 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1, 6007 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2, 6008 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3, 6009 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 4, 6010 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 5, 6011 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 6, 6012 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 7, 6013 &stage_ptr->uniform_structure_arrays[1].uniform_double, 6014 stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0, 6015 stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1, 6016 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0, 6017 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1, 6018 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 2, 6019 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 3, 6020 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0, 6021 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1, 6022 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2, 6023 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 3, 6024 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 4, 6025 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 5, 6026 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0, 6027 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1, 6028 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2, 6029 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3, 6030 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 4, 6031 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 5, 6032 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 6, 6033 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 7, 6034 &stage_ptr->uniforms.uniform_double, 6035 stage_ptr->uniforms.uniform_double_arr + 0, 6036 stage_ptr->uniforms.uniform_double_arr + 1, 6037 stage_ptr->uniforms.uniform_dvec2 + 0, 6038 stage_ptr->uniforms.uniform_dvec2 + 1, 6039 stage_ptr->uniforms.uniform_dvec2_arr + 0, 6040 stage_ptr->uniforms.uniform_dvec2_arr + 1, 6041 stage_ptr->uniforms.uniform_dvec2_arr + 2, 6042 stage_ptr->uniforms.uniform_dvec2_arr + 3, 6043 stage_ptr->uniforms.uniform_dvec3 + 0, 6044 stage_ptr->uniforms.uniform_dvec3 + 1, 6045 stage_ptr->uniforms.uniform_dvec3 + 2, 6046 stage_ptr->uniforms.uniform_dvec3_arr + 0, 6047 stage_ptr->uniforms.uniform_dvec3_arr + 1, 6048 stage_ptr->uniforms.uniform_dvec3_arr + 2, 6049 stage_ptr->uniforms.uniform_dvec3_arr + 3, 6050 stage_ptr->uniforms.uniform_dvec3_arr + 4, 6051 stage_ptr->uniforms.uniform_dvec3_arr + 5, 6052 stage_ptr->uniforms.uniform_dvec4 + 0, 6053 stage_ptr->uniforms.uniform_dvec4 + 1, 6054 stage_ptr->uniforms.uniform_dvec4 + 2, 6055 stage_ptr->uniforms.uniform_dvec4 + 3, 6056 stage_ptr->uniforms.uniform_dvec4_arr + 0, 6057 stage_ptr->uniforms.uniform_dvec4_arr + 1, 6058 stage_ptr->uniforms.uniform_dvec4_arr + 2, 6059 stage_ptr->uniforms.uniform_dvec4_arr + 3, 6060 stage_ptr->uniforms.uniform_dvec4_arr + 4, 6061 stage_ptr->uniforms.uniform_dvec4_arr + 5, 6062 stage_ptr->uniforms.uniform_dvec4_arr + 6, 6063 stage_ptr->uniforms.uniform_dvec4_arr + 7, 6064 }; 6065 const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]); 6066 6067 for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr) 6068 { 6069 double* double_ptr = double_ptrs[n_double_ptr]; 6070 6071 /* Generate the value. Use magic numbers to generate a set of double-precision 6072 * floating-point numbers. 6073 */ 6074 static int seed = 16762362; 6075 6076 *double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1); 6077 6078 seed += 751; 6079 } /* for (all pointers to double variables) */ 6080 } /* for (all stages) */ 6081 } 6082 6083 /** Initializes all program & shader objects required to run the test. The function also 6084 * retrieves locations of all uniforms defined by both program objects. 6085 **/ 6086 void GPUShaderFP64Test4::initProgramObjects() 6087 { 6088 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6089 6090 /* Create program & shader objects */ 6091 6092 /* Compute shader support and GL 4.2 required */ 6093 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) && 6094 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */))) 6095 { 6096 m_cs_id = gl.createShader(GL_COMPUTE_SHADER); 6097 } 6098 6099 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 6100 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 6101 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER); 6102 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER); 6103 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 6104 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 6105 6106 /* m_cs_id is initialized only if compute shaders are supported */ 6107 if (0 != m_cs_id) 6108 { 6109 m_po_cs_id = gl.createProgram(); 6110 } 6111 6112 m_po_noncs_id = gl.createProgram(); 6113 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed."); 6114 6115 /* Configure compute shader body */ 6116 const char* cs_body = "#version 420\n" 6117 "#extension GL_ARB_compute_shader : require\n" 6118 "\n" 6119 "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n" 6120 "\n" 6121 "layout(rgba32f) uniform image2D testImage;\n" 6122 "\n" 6123 "uniform double cs_double;\n" 6124 "uniform dvec2 cs_dvec2;\n" 6125 "uniform dvec3 cs_dvec3;\n" 6126 "uniform dvec4 cs_dvec4;\n" 6127 "uniform double cs_double_arr[2];\n" 6128 "uniform dvec2 cs_dvec2_arr [2];\n" 6129 "uniform dvec3 cs_dvec3_arr [2];\n" 6130 "uniform dvec4 cs_dvec4_arr [2];\n" 6131 "\n" 6132 "uniform struct cs_struct\n" 6133 "{\n" 6134 " double struct_double;\n" 6135 " dvec2 struct_dvec2;\n" 6136 " dvec3 struct_dvec3;\n" 6137 " dvec4 struct_dvec4;\n" 6138 "} cs_array[2];\n" 6139 "\n" 6140 "void main()\n" 6141 "{\n" 6142 " double tmp = cs_double * cs_dvec2.x * cs_dvec3.y " 6143 " * cs_dvec4.z *\n" 6144 " cs_double_arr[0] * cs_dvec2_arr[0].x * " 6145 "cs_dvec3_arr[0].z * cs_dvec4_arr[0].w *\n" 6146 " cs_double_arr[1] * cs_dvec2_arr[1].x * " 6147 "cs_dvec3_arr[1].z * cs_dvec4_arr[1].w *\n" 6148 " cs_array[0].struct_double * cs_array[0].struct_dvec2.y * " 6149 "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n" 6150 " cs_array[1].struct_double * cs_array[1].struct_dvec2.y * " 6151 "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n" 6152 "\n" 6153 " imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n" 6154 "}\n"; 6155 6156 /* m_cs_id is initialized only if compute shaders are supported */ 6157 if (0 != m_cs_id) 6158 { 6159 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */); 6160 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 6161 } 6162 6163 /* Configure vertex shader body */ 6164 const char* vs_body = "#version 400\n" 6165 "\n" 6166 "uniform double vs_double;\n" 6167 "uniform dvec2 vs_dvec2;\n" 6168 "uniform dvec3 vs_dvec3;\n" 6169 "uniform dvec4 vs_dvec4;\n" 6170 "uniform double vs_double_arr[2];\n" 6171 "uniform dvec2 vs_dvec2_arr [2];\n" 6172 "uniform dvec3 vs_dvec3_arr [2];\n" 6173 "uniform dvec4 vs_dvec4_arr [2];\n" 6174 "\n" 6175 "uniform struct vs_struct\n" 6176 "{\n" 6177 " double struct_double;\n" 6178 " dvec2 struct_dvec2;\n" 6179 " dvec3 struct_dvec3;\n" 6180 " dvec4 struct_dvec4;\n" 6181 "} vs_array[2];\n" 6182 "\n" 6183 "void main()\n" 6184 "{\n" 6185 " if (vs_double * vs_dvec2.x * vs_dvec3.x " 6186 "* vs_dvec4.x *\n" 6187 " vs_double_arr[0] * vs_dvec2_arr[0].x * vs_dvec3_arr[0].x " 6188 "* vs_dvec4_arr[0].x *\n" 6189 " vs_double_arr[1] * vs_dvec2_arr[1].x * vs_dvec3_arr[1].x " 6190 "* vs_dvec4_arr[1].x *\n" 6191 " vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x " 6192 "* vs_array[0].struct_dvec4.x *\n" 6193 " vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x " 6194 "* vs_array[1].struct_dvec4.x > 1.0)\n" 6195 " {\n" 6196 " gl_Position = vec4(0);\n" 6197 " }\n" 6198 " else\n" 6199 " {\n" 6200 " gl_Position = vec4(1);\n" 6201 " }\n" 6202 "}\n"; 6203 6204 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */); 6205 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 6206 6207 /* Configure tessellation control shader body */ 6208 const char* tc_body = "#version 400\n" 6209 "\n" 6210 "uniform double tc_double;\n" 6211 "uniform dvec2 tc_dvec2;\n" 6212 "uniform dvec3 tc_dvec3;\n" 6213 "uniform dvec4 tc_dvec4;\n" 6214 "uniform double tc_double_arr[2];\n" 6215 "uniform dvec2 tc_dvec2_arr [2];\n" 6216 "uniform dvec3 tc_dvec3_arr [2];\n" 6217 "uniform dvec4 tc_dvec4_arr [2];\n" 6218 "\n" 6219 "uniform struct tc_struct\n" 6220 "{\n" 6221 " double struct_double;\n" 6222 " dvec2 struct_dvec2;\n" 6223 " dvec3 struct_dvec3;\n" 6224 " dvec4 struct_dvec4;\n" 6225 "} tc_array[2];\n" 6226 "\n" 6227 "layout(vertices = 4) out;\n" 6228 "\n" 6229 "void main()\n" 6230 "{\n" 6231 " gl_TessLevelOuter[0] = (tc_double > 1.0) ? 2.0 : 3.0;\n" 6232 " gl_TessLevelOuter[1] = (tc_dvec2.x > 1.0) ? 3.0 : 4.0;\n" 6233 " gl_TessLevelOuter[2] = (tc_dvec3.x > 1.0) ? 4.0 : 5.0;\n" 6234 " gl_TessLevelOuter[3] = (tc_dvec4.x > 1.0) ? 5.0 : 6.0;\n" 6235 " gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n" 6236 " gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n" 6237 "\n" 6238 " if (tc_dvec2_arr[0].y * tc_dvec2_arr[1].y *\n" 6239 " tc_dvec3_arr[0].z * tc_dvec3_arr[1].z *\n" 6240 " tc_dvec4_arr[0].z * tc_dvec4_arr[1].z *\n" 6241 " tc_array[0].struct_double * tc_array[0].struct_dvec2.x * \n" 6242 " tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n" 6243 " tc_array[1].struct_double * tc_array[1].struct_dvec2.x * \n" 6244 " tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n" 6245 " {\n" 6246 " gl_TessLevelInner[1] = 3.0;\n" 6247 " }\n" 6248 "}\n"; 6249 6250 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */); 6251 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 6252 6253 /* Configure tessellation evaluation shader body */ 6254 const char* te_body = "#version 400\n" 6255 "\n" 6256 "uniform double te_double;\n" 6257 "uniform dvec2 te_dvec2;\n" 6258 "uniform dvec3 te_dvec3;\n" 6259 "uniform dvec4 te_dvec4;\n" 6260 "uniform double te_double_arr[2];\n" 6261 "uniform dvec2 te_dvec2_arr [2];\n" 6262 "uniform dvec3 te_dvec3_arr [2];\n" 6263 "uniform dvec4 te_dvec4_arr [2];\n" 6264 "\n" 6265 "uniform struct te_struct\n" 6266 "{\n" 6267 " double struct_double;\n" 6268 " dvec2 struct_dvec2;\n" 6269 " dvec3 struct_dvec3;\n" 6270 " dvec4 struct_dvec4;\n" 6271 "} te_array[2];\n" 6272 "\n" 6273 "layout(triangles) in;\n" 6274 "\n" 6275 "void main()\n" 6276 "{\n" 6277 " if (te_double * te_dvec2.x * te_dvec3.x " 6278 "* te_dvec4.x *\n" 6279 " te_double_arr[0] * te_dvec2_arr[0].x * te_dvec3_arr[0].x " 6280 "* te_dvec4_arr[0].x *\n" 6281 " te_double_arr[1] * te_dvec2_arr[1].x * te_dvec3_arr[1].x " 6282 "* te_dvec4_arr[1].x *\n" 6283 " te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x " 6284 "* te_array[0].struct_dvec4.x *\n" 6285 " te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x " 6286 "* te_array[1].struct_dvec4.x > 1.0)\n" 6287 " {\n" 6288 " gl_Position = gl_in[0].gl_Position;\n" 6289 " }\n" 6290 " else\n" 6291 " {\n" 6292 " gl_Position = gl_in[0].gl_Position + vec4(1);\n" 6293 " }\n" 6294 "}\n"; 6295 6296 gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */); 6297 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 6298 6299 /* Configure geometry shader body */ 6300 const char* gs_body = "#version 400\n" 6301 "\n" 6302 "uniform double gs_double;\n" 6303 "uniform dvec2 gs_dvec2;\n" 6304 "uniform dvec3 gs_dvec3;\n" 6305 "uniform dvec4 gs_dvec4;\n" 6306 "uniform double gs_double_arr[2];\n" 6307 "uniform dvec2 gs_dvec2_arr [2];\n" 6308 "uniform dvec3 gs_dvec3_arr [2];\n" 6309 "uniform dvec4 gs_dvec4_arr [2];\n" 6310 "\n" 6311 "uniform struct gs_struct\n" 6312 "{\n" 6313 " double struct_double;\n" 6314 " dvec2 struct_dvec2;\n" 6315 " dvec3 struct_dvec3;\n" 6316 " dvec4 struct_dvec4;\n" 6317 "} gs_array[2];\n" 6318 "\n" 6319 "layout (points) in;\n" 6320 "layout (points, max_vertices = 1) out;\n" 6321 "\n" 6322 "void main()\n" 6323 "{\n" 6324 " if (gs_double * gs_dvec2.x * gs_dvec3.x " 6325 "* gs_dvec4.x *\n" 6326 " gs_double_arr[0] * gs_dvec2_arr[0].x * gs_dvec3_arr[0].x " 6327 "* gs_dvec4_arr[0].x *\n" 6328 " gs_double_arr[1] * gs_dvec2_arr[1].x * gs_dvec3_arr[1].x " 6329 "* gs_dvec4_arr[1].x *\n" 6330 " gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x " 6331 "* gs_array[0].struct_dvec4.x *\n" 6332 " gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x " 6333 "* gs_array[1].struct_dvec4.x > 1.0)\n" 6334 " {\n" 6335 " gl_Position = gl_in[0].gl_Position;\n" 6336 " }\n" 6337 " else\n" 6338 " {\n" 6339 " gl_Position = gl_in[0].gl_Position + vec4(1);\n" 6340 " }\n" 6341 "\n" 6342 " EmitVertex();\n" 6343 "}\n"; 6344 6345 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */); 6346 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 6347 6348 /* Configure fragment shader body */ 6349 const char* fs_body = "#version 400\n" 6350 "\n" 6351 "uniform double fs_double;\n" 6352 "uniform dvec2 fs_dvec2;\n" 6353 "uniform dvec3 fs_dvec3;\n" 6354 "uniform dvec4 fs_dvec4;\n" 6355 "uniform double fs_double_arr[2];\n" 6356 "uniform dvec2 fs_dvec2_arr [2];\n" 6357 "uniform dvec3 fs_dvec3_arr [2];\n" 6358 "uniform dvec4 fs_dvec4_arr [2];\n" 6359 "\n" 6360 "uniform struct fs_struct\n" 6361 "{\n" 6362 " double struct_double;\n" 6363 " dvec2 struct_dvec2;\n" 6364 " dvec3 struct_dvec3;\n" 6365 " dvec4 struct_dvec4;\n" 6366 "} fs_array[2];\n" 6367 "\n" 6368 "out vec4 result;\n" 6369 "\n" 6370 "void main()\n" 6371 "{\n" 6372 " if (fs_double * fs_dvec2.x * fs_dvec3.x " 6373 "* fs_dvec4.x *\n" 6374 " fs_double_arr[0] * fs_dvec2_arr[0].x * fs_dvec3_arr[0].x " 6375 "* fs_dvec4_arr[0].x *\n" 6376 " fs_double_arr[1] * fs_dvec2_arr[1].x * fs_dvec3_arr[1].x " 6377 "* fs_dvec4_arr[1].x *\n" 6378 " fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x " 6379 "* fs_array[0].struct_dvec4.x *\n" 6380 " fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x " 6381 "* fs_array[1].struct_dvec4.x > 1.0)\n" 6382 " {\n" 6383 " result = vec4(0.0);\n" 6384 " }\n" 6385 " else\n" 6386 " {\n" 6387 " result = vec4(1.0);\n" 6388 " }\n" 6389 "}\n"; 6390 6391 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */); 6392 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 6393 6394 /* Compile the shaders */ 6395 const glw::GLuint shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id }; 6396 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 6397 6398 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 6399 { 6400 glw::GLint compile_status = GL_FALSE; 6401 glw::GLuint so_id = shaders[n_shader]; 6402 6403 /* Skip compute shader if not supported */ 6404 if (0 == so_id) 6405 { 6406 continue; 6407 } 6408 6409 gl.compileShader(so_id); 6410 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 6411 6412 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); 6413 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 6414 6415 if (compile_status != GL_TRUE) 6416 { 6417 TCU_FAIL("Shader compilation failed"); 6418 } 6419 6420 if (so_id == m_cs_id) 6421 { 6422 gl.attachShader(m_po_cs_id, so_id); 6423 } 6424 else 6425 { 6426 gl.attachShader(m_po_noncs_id, so_id); 6427 } 6428 6429 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 6430 } /* for (all shaders) */ 6431 6432 /* Link the program */ 6433 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id }; 6434 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]); 6435 glw::GLint link_status = GL_FALSE; 6436 6437 for (unsigned int n_program = 0; n_program < n_programs; ++n_program) 6438 { 6439 glw::GLuint po_id = programs[n_program]; 6440 6441 /* Skip compute shader program if not supported */ 6442 if (0 == po_id) 6443 { 6444 continue; 6445 } 6446 6447 gl.linkProgram(po_id); 6448 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 6449 6450 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 6451 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed"); 6452 6453 if (link_status != GL_TRUE) 6454 { 6455 TCU_FAIL("Program linking failed"); 6456 } 6457 } /* for (both program objects) */ 6458 6459 /* Retrieve uniform locations */ 6460 _stage_data* cs_stage_data[] = { &m_data_cs }; 6461 static const char* cs_uniform_prefixes[] = { "cs_" }; 6462 static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]); 6463 6464 _stage_data* noncs_stage_data[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs }; 6465 static const char* noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" }; 6466 static const unsigned int n_noncs_uniform_prefixes = 6467 sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]); 6468 6469 for (unsigned int n_program = 0; n_program < n_programs; ++n_program) 6470 { 6471 unsigned int n_uniform_prefixes = DE_NULL; 6472 glw::GLuint po_id = programs[n_program]; 6473 _stage_data** stages_data = DE_NULL; 6474 const char** uniform_prefixes = DE_NULL; 6475 6476 if (n_program == 0) 6477 { 6478 stages_data = cs_stage_data; 6479 uniform_prefixes = cs_uniform_prefixes; 6480 n_uniform_prefixes = n_cs_uniform_prefixes; 6481 } 6482 else 6483 { 6484 stages_data = noncs_stage_data; 6485 uniform_prefixes = noncs_uniform_prefixes; 6486 n_uniform_prefixes = n_noncs_uniform_prefixes; 6487 } 6488 6489 /* Skip compute shader program if not supported */ 6490 if (0 == po_id) 6491 { 6492 continue; 6493 } 6494 6495 /* Uniform names used by the test program consist of a prefix (different for each 6496 * shader stage) and a common part. 6497 */ 6498 for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix) 6499 { 6500 _stage_data* stage_data = stages_data[n_uniform_prefix]; 6501 std::string uniform_prefix = std::string(uniform_prefixes[n_uniform_prefix]); 6502 std::string uniform_double_name = uniform_prefix + "double"; 6503 std::string uniform_double_arr0_name = uniform_prefix + "double_arr[0]"; 6504 std::string uniform_double_arr1_name = uniform_prefix + "double_arr[1]"; 6505 std::string uniform_dvec2_name = uniform_prefix + "dvec2"; 6506 std::string uniform_dvec2_arr0_name = uniform_prefix + "dvec2_arr[0]"; 6507 std::string uniform_dvec2_arr1_name = uniform_prefix + "dvec2_arr[1]"; 6508 std::string uniform_dvec3_name = uniform_prefix + "dvec3"; 6509 std::string uniform_dvec3_arr0_name = uniform_prefix + "dvec3_arr[0]"; 6510 std::string uniform_dvec3_arr1_name = uniform_prefix + "dvec3_arr[1]"; 6511 std::string uniform_dvec4_name = uniform_prefix + "dvec4"; 6512 std::string uniform_dvec4_arr0_name = uniform_prefix + "dvec4_arr[0]"; 6513 std::string uniform_dvec4_arr1_name = uniform_prefix + "dvec4_arr[1]"; 6514 std::string uniform_arr0_double_name = uniform_prefix + "array[0].struct_double"; 6515 std::string uniform_arr0_dvec2_name = uniform_prefix + "array[0].struct_dvec2"; 6516 std::string uniform_arr0_dvec3_name = uniform_prefix + "array[0].struct_dvec3"; 6517 std::string uniform_arr0_dvec4_name = uniform_prefix + "array[0].struct_dvec4"; 6518 std::string uniform_arr1_double_name = uniform_prefix + "array[1].struct_double"; 6519 std::string uniform_arr1_dvec2_name = uniform_prefix + "array[1].struct_dvec2"; 6520 std::string uniform_arr1_dvec3_name = uniform_prefix + "array[1].struct_dvec3"; 6521 std::string uniform_arr1_dvec4_name = uniform_prefix + "array[1].struct_dvec4"; 6522 6523 /* Retrieve uniform locations */ 6524 stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str()); 6525 stage_data->uniforms.uniform_location_double_arr[0] = 6526 gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str()); 6527 stage_data->uniforms.uniform_location_double_arr[1] = 6528 gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str()); 6529 stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str()); 6530 stage_data->uniforms.uniform_location_dvec2_arr[0] = 6531 gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str()); 6532 stage_data->uniforms.uniform_location_dvec2_arr[1] = 6533 gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str()); 6534 stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str()); 6535 stage_data->uniforms.uniform_location_dvec3_arr[0] = 6536 gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str()); 6537 stage_data->uniforms.uniform_location_dvec3_arr[1] = 6538 gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str()); 6539 stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str()); 6540 stage_data->uniforms.uniform_location_dvec4_arr[0] = 6541 gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str()); 6542 stage_data->uniforms.uniform_location_dvec4_arr[1] = 6543 gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str()); 6544 stage_data->uniform_structure_arrays[0].uniform_location_double = 6545 gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str()); 6546 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 = 6547 gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str()); 6548 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 = 6549 gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str()); 6550 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 = 6551 gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str()); 6552 stage_data->uniform_structure_arrays[1].uniform_location_double = 6553 gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str()); 6554 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 = 6555 gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str()); 6556 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 = 6557 gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str()); 6558 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 = 6559 gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str()); 6560 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed."); 6561 6562 if (stage_data->uniforms.uniform_location_double == -1 || 6563 stage_data->uniforms.uniform_location_double_arr[0] == -1 || 6564 stage_data->uniforms.uniform_location_double_arr[1] == -1 || 6565 stage_data->uniforms.uniform_location_dvec2 == -1 || 6566 stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 || 6567 stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 || 6568 stage_data->uniforms.uniform_location_dvec3 == -1 || 6569 stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 || 6570 stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 || 6571 stage_data->uniforms.uniform_location_dvec4 == -1 || 6572 stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 || 6573 stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 || 6574 stage_data->uniform_structure_arrays[0].uniform_location_double == -1 || 6575 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 || 6576 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 || 6577 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 || 6578 stage_data->uniform_structure_arrays[1].uniform_location_double == -1 || 6579 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 || 6580 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 || 6581 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1) 6582 { 6583 TCU_FAIL("At least one uniform is considered inactive which is invalid."); 6584 } 6585 6586 /* Make sure locations of subsequent items in array uniforms are correct */ 6587 if (stage_data->uniforms.uniform_location_double_arr[1] != 6588 (stage_data->uniforms.uniform_location_double_arr[0] + 1) || 6589 stage_data->uniforms.uniform_location_dvec2_arr[1] != 6590 (stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) || 6591 stage_data->uniforms.uniform_location_dvec3_arr[1] != 6592 (stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) || 6593 stage_data->uniforms.uniform_location_dvec4_arr[1] != 6594 (stage_data->uniforms.uniform_location_dvec4_arr[0] + 1)) 6595 { 6596 m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:" 6597 " double_arr[0]:" 6598 << stage_data->uniforms.uniform_location_double_arr[0] 6599 << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1] 6600 << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0] 6601 << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1] 6602 << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0] 6603 << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1] 6604 << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0] 6605 << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1] 6606 << tcu::TestLog::EndMessage; 6607 6608 TCU_FAIL("Double-precision uniform array item locations are invalid."); 6609 } 6610 } /* for (all uniform prefixes) */ 6611 } /* for (both program objects) */ 6612 } 6613 6614 /** Initializes all objects required to run the test. */ 6615 void GPUShaderFP64Test4::initTest() 6616 { 6617 initProgramObjects(); 6618 6619 generateUniformValues(); 6620 initUniformValues(); 6621 } 6622 6623 /** Assigns values generated by generateUniformValues() to uniforms defined by 6624 * both program objects. 6625 **/ 6626 void GPUShaderFP64Test4::initUniformValues() 6627 { 6628 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6629 6630 /* Iterate through all programs */ 6631 _stage_data* cs_stages[] = { &m_data_cs }; 6632 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs }; 6633 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]); 6634 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]); 6635 6636 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id }; 6637 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]); 6638 6639 for (unsigned int n_program = 0; n_program < n_programs; ++n_program) 6640 { 6641 glw::GLuint po_id = programs[n_program]; 6642 unsigned int n_stages = 0; 6643 _stage_data** stage_data = DE_NULL; 6644 6645 if (po_id == m_po_cs_id) 6646 { 6647 n_stages = n_cs_stages; 6648 stage_data = cs_stages; 6649 } 6650 else 6651 { 6652 n_stages = n_noncs_stages; 6653 stage_data = noncs_stages; 6654 } 6655 6656 /* Skip compute shader program if not supported */ 6657 if (0 == po_id) 6658 { 6659 continue; 6660 } 6661 6662 gl.useProgram(po_id); 6663 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 6664 6665 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage) 6666 { 6667 /* Iterate through all uniforms */ 6668 _stage_data* stage_ptr = stage_data[n_stage]; 6669 6670 gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double); 6671 gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]); 6672 gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]); 6673 gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double, 6674 stage_ptr->uniform_structure_arrays[0].uniform_double); 6675 gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double, 6676 stage_ptr->uniform_structure_arrays[1].uniform_double); 6677 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed."); 6678 6679 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2); 6680 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */, 6681 stage_ptr->uniforms.uniform_dvec2_arr + 0); 6682 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */, 6683 stage_ptr->uniforms.uniform_dvec2_arr + 2); 6684 gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */, 6685 stage_ptr->uniform_structure_arrays[0].uniform_dvec2); 6686 gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */, 6687 stage_ptr->uniform_structure_arrays[1].uniform_dvec2); 6688 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed."); 6689 6690 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3); 6691 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */, 6692 stage_ptr->uniforms.uniform_dvec3_arr + 0); 6693 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */, 6694 stage_ptr->uniforms.uniform_dvec3_arr + 3); 6695 gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */, 6696 stage_ptr->uniform_structure_arrays[0].uniform_dvec3); 6697 gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */, 6698 stage_ptr->uniform_structure_arrays[1].uniform_dvec3); 6699 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed."); 6700 6701 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4); 6702 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */, 6703 stage_ptr->uniforms.uniform_dvec4_arr + 0); 6704 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */, 6705 stage_ptr->uniforms.uniform_dvec4_arr + 4); 6706 gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */, 6707 stage_ptr->uniform_structure_arrays[0].uniform_dvec4); 6708 gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */, 6709 stage_ptr->uniform_structure_arrays[1].uniform_dvec4); 6710 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed."); 6711 } /* for (all shader stages) */ 6712 } /* for (both program objects) */ 6713 } 6714 6715 /** Executes test iteration. 6716 * 6717 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 6718 */ 6719 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate() 6720 { 6721 /* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */ 6722 6723 /* Initialize all objects required to run the test */ 6724 initTest(); 6725 6726 /* Verify the implementation reports correct values for all stages we've configured */ 6727 m_has_test_passed &= verifyUniformValues(); 6728 6729 /* Is this also the case when "program interface query" mechanism is used? */ 6730 if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query")) 6731 { 6732 m_has_test_passed &= verifyProgramInterfaceQuerySupport(); 6733 } 6734 6735 /* We're done */ 6736 if (m_has_test_passed) 6737 { 6738 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 6739 } 6740 else 6741 { 6742 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 6743 } 6744 6745 return STOP; 6746 } 6747 6748 /** Verifies that: 6749 * 6750 * a) glGetProgramResourceIndex() 6751 * b) glGetProgramResourceiv() 6752 * c) glGetProgramResourceName() 6753 * 6754 * functions return correct values for double-precision uniforms. 6755 * 6756 * @return true if the verification was passed, false otherwise. 6757 */ 6758 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport() 6759 { 6760 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6761 bool result = true; 6762 6763 /* Iterate through all programs */ 6764 const char* cs_prefixes[] = { "cs_" }; 6765 _stage_data* cs_stages[] = { &m_data_cs }; 6766 const char* noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" }; 6767 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs }; 6768 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]); 6769 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]); 6770 6771 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id }; 6772 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]); 6773 6774 for (unsigned int n_program = 0; n_program < n_programs; ++n_program) 6775 { 6776 glw::GLuint po_id = programs[n_program]; 6777 unsigned int n_stages = 0; 6778 const char** stage_prefixes = DE_NULL; 6779 _stage_data** stage_data = DE_NULL; 6780 6781 if (po_id == m_po_cs_id) 6782 { 6783 n_stages = n_cs_stages; 6784 stage_data = cs_stages; 6785 stage_prefixes = cs_prefixes; 6786 } 6787 else 6788 { 6789 n_stages = n_noncs_stages; 6790 stage_data = noncs_stages; 6791 stage_prefixes = noncs_prefixes; 6792 } 6793 6794 /* Skip compute shader program if not supported */ 6795 if (0 == po_id) 6796 { 6797 continue; 6798 } 6799 6800 /* Determine maximum uniform name length */ 6801 glw::GLint max_uniform_name_length = 0; 6802 6803 gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length); 6804 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed."); 6805 6806 /* Allocate a buffer we will use to hold uniform names */ 6807 m_uniform_name_buffer = new char[max_uniform_name_length]; 6808 6809 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage) 6810 { 6811 /* Iterate through all uniforms */ 6812 _stage_data* stage_ptr = stage_data[n_stage]; 6813 const char* stage_prefix = stage_prefixes[n_stage]; 6814 6815 /* Construct an array that will be used to run the test in an automated manner */ 6816 _program_interface_query_test_item uniforms[] = { 6817 /* array size */ /* name */ /* type */ /* location */ 6818 { 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double }, 6819 { 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] }, 6820 { 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 }, 6821 { 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] }, 6822 { 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 }, 6823 { 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] }, 6824 { 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 }, 6825 { 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] }, 6826 { 1, "array[0].struct_double", GL_DOUBLE, 6827 stage_ptr->uniform_structure_arrays->uniform_location_double }, 6828 { 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2, 6829 stage_ptr->uniform_structure_arrays->uniform_location_dvec2 }, 6830 { 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3, 6831 stage_ptr->uniform_structure_arrays->uniform_location_dvec3 }, 6832 { 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4, 6833 stage_ptr->uniform_structure_arrays->uniform_location_dvec4 }, 6834 { 1, "array[1].struct_double", GL_DOUBLE, 6835 stage_ptr->uniform_structure_arrays->uniform_location_double }, 6836 { 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2, 6837 stage_ptr->uniform_structure_arrays->uniform_location_dvec2 }, 6838 { 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3, 6839 stage_ptr->uniform_structure_arrays->uniform_location_dvec3 }, 6840 { 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4, 6841 stage_ptr->uniform_structure_arrays->uniform_location_dvec4 }, 6842 }; 6843 const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]); 6844 6845 /* Prefix the names with stage-specific string */ 6846 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform) 6847 { 6848 _program_interface_query_test_item& current_item = uniforms[n_uniform]; 6849 6850 current_item.name = std::string(stage_prefix) + current_item.name; 6851 } /* for (all uniform descriptors) */ 6852 6853 const glw::GLenum properties[] = { GL_ARRAY_SIZE, GL_TYPE }; 6854 const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]); 6855 6856 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform) 6857 { 6858 _program_interface_query_test_item& current_item = uniforms[n_uniform]; 6859 glw::GLint n_written_items = 0; 6860 glw::GLint retrieved_array_size = 0; 6861 glw::GLint retrieved_name_length = 0; 6862 glw::GLenum retrieved_type = GL_NONE; 6863 glw::GLint temp_buffer[2] = { 0, GL_NONE }; 6864 6865 /* Retrieve index of the iteration-specific uniform */ 6866 glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str()); 6867 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed."); 6868 6869 /* Make sure glGetProgramResourceName() returns correct values */ 6870 memset(m_uniform_name_buffer, 0, max_uniform_name_length); 6871 6872 gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */ 6873 resource_index, max_uniform_name_length, &retrieved_name_length, 6874 m_uniform_name_buffer); 6875 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed."); 6876 6877 if (current_item.name.length() != (glw::GLuint)retrieved_name_length || 6878 memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0) 6879 { 6880 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index [" 6881 << resource_index << "]" 6882 ": expected:[" 6883 << current_item.name << "]" 6884 ", reported:[" 6885 << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage; 6886 6887 result = false; 6888 continue; 6889 } 6890 6891 /* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */ 6892 gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */ 6893 resource_index, n_properties, properties, 6894 sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer); 6895 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed."); 6896 6897 if (n_written_items != n_properties) 6898 { 6899 TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call."); 6900 } 6901 6902 /* For clarity, copy the retrieved values to separate variables */ 6903 retrieved_array_size = temp_buffer[0]; 6904 retrieved_type = temp_buffer[1]; 6905 6906 /* Verify the values */ 6907 if (retrieved_array_size != current_item.expected_array_size) 6908 { 6909 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform [" 6910 << current_item.name << "]" 6911 << ": expected:[" << current_item.expected_array_size << "]" 6912 ", reported:[" 6913 << retrieved_array_size << "]" << tcu::TestLog::EndMessage; 6914 6915 result = false; 6916 } 6917 6918 if (retrieved_type != current_item.expected_type) 6919 { 6920 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform [" 6921 << current_item.name << "]" 6922 << ": expected:[" << current_item.expected_type << "]" 6923 ", reported:[" 6924 << retrieved_type << "]" << tcu::TestLog::EndMessage; 6925 6926 result = false; 6927 } 6928 } /* for (all uniforms) */ 6929 } /* for (all shader stages) */ 6930 6931 /* We're now OK to release the buffer we used to hold uniform names for 6932 * the program */ 6933 if (m_uniform_name_buffer != DE_NULL) 6934 { 6935 delete[] m_uniform_name_buffer; 6936 6937 m_uniform_name_buffer = DE_NULL; 6938 } 6939 } /* for (both program objects) */ 6940 6941 return result; 6942 } 6943 6944 /** Verifies glGetUniform*() calls return correct values assigned to 6945 * double-precision uniforms. 6946 * 6947 * @return true if all values reported by OpenGL were found to be correct, 6948 * false otherwise. 6949 **/ 6950 bool GPUShaderFP64Test4::verifyUniformValues() 6951 { 6952 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6953 bool result = true; 6954 6955 /* Iterate through all programs */ 6956 _stage_data* cs_stages[] = { &m_data_cs }; 6957 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs }; 6958 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]); 6959 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]); 6960 6961 const glw::GLuint programs[] = { 6962 m_po_noncs_id, m_po_cs_id, 6963 }; 6964 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]); 6965 6966 /* Set up rounding for the tests */ 6967 deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN); 6968 6969 for (unsigned int n_program = 0; n_program < n_programs; ++n_program) 6970 { 6971 glw::GLuint po_id = programs[n_program]; 6972 unsigned int n_stages = 0; 6973 _stage_data** stage_data = DE_NULL; 6974 6975 if (po_id == m_po_cs_id) 6976 { 6977 n_stages = n_cs_stages; 6978 stage_data = cs_stages; 6979 } 6980 else 6981 { 6982 n_stages = n_noncs_stages; 6983 stage_data = noncs_stages; 6984 } 6985 6986 /* Skip compute shader program if not supported */ 6987 if (0 == po_id) 6988 { 6989 continue; 6990 } 6991 6992 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage) 6993 { 6994 /* Iterate through all uniforms */ 6995 _stage_data* stage_ptr = stage_data[n_stage]; 6996 6997 /* Set up arrays that we will guide the automated testing */ 6998 const uniform_value_pair double_uniforms[] = { 6999 uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double), 7000 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0], 7001 stage_ptr->uniforms.uniform_double_arr + 0), 7002 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1], 7003 stage_ptr->uniforms.uniform_double_arr + 1), 7004 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double, 7005 &stage_ptr->uniform_structure_arrays[0].uniform_double), 7006 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double, 7007 &stage_ptr->uniform_structure_arrays[1].uniform_double) 7008 }; 7009 const uniform_value_pair dvec2_uniforms[] = { 7010 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2), 7011 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 7012 stage_ptr->uniforms.uniform_dvec2_arr + 0), 7013 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 7014 stage_ptr->uniforms.uniform_dvec2_arr + 2), 7015 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 7016 stage_ptr->uniform_structure_arrays[0].uniform_dvec2), 7017 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 7018 stage_ptr->uniform_structure_arrays[1].uniform_dvec2) 7019 }; 7020 const uniform_value_pair dvec3_uniforms[] = { 7021 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3), 7022 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 7023 stage_ptr->uniforms.uniform_dvec3_arr + 0), 7024 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 7025 stage_ptr->uniforms.uniform_dvec3_arr + 3), 7026 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 7027 stage_ptr->uniform_structure_arrays[0].uniform_dvec3), 7028 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 7029 stage_ptr->uniform_structure_arrays[1].uniform_dvec3) 7030 }; 7031 const uniform_value_pair dvec4_uniforms[] = { 7032 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4), 7033 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 7034 stage_ptr->uniforms.uniform_dvec4_arr + 0), 7035 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 7036 stage_ptr->uniforms.uniform_dvec4_arr + 4), 7037 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 7038 stage_ptr->uniform_structure_arrays[0].uniform_dvec4), 7039 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 7040 stage_ptr->uniform_structure_arrays[1].uniform_dvec4) 7041 }; 7042 7043 /* Iterate over all uniforms and verify the values reported by the API */ 7044 double returned_double_data[4]; 7045 float returned_float_data[4]; 7046 int returned_int_data[4]; 7047 unsigned int returned_uint_data[4]; 7048 7049 for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type) 7050 { 7051 const uniform_value_pair* current_uv_pairs = NULL; 7052 const unsigned int n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */ 7053 unsigned int n_pairs = 0; 7054 7055 switch (n_type) 7056 { 7057 case 0: /* double */ 7058 { 7059 current_uv_pairs = double_uniforms; 7060 n_pairs = sizeof(double_uniforms) / sizeof(double_uniforms[0]); 7061 7062 break; 7063 } 7064 7065 case 1: /* dvec2 */ 7066 { 7067 current_uv_pairs = dvec2_uniforms; 7068 n_pairs = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]); 7069 7070 break; 7071 } 7072 7073 case 2: /* dvec3 */ 7074 { 7075 current_uv_pairs = dvec3_uniforms; 7076 n_pairs = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]); 7077 7078 break; 7079 } 7080 7081 case 3: /* dvec4 */ 7082 { 7083 current_uv_pairs = dvec4_uniforms; 7084 n_pairs = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]); 7085 7086 break; 7087 } 7088 7089 default: 7090 { 7091 TCU_FAIL("Invalid type index requested"); 7092 } 7093 } /* switch (n_type) */ 7094 7095 for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair) 7096 { 7097 const uniform_value_pair& current_uv_pair = current_uv_pairs[n_pair]; 7098 glw::GLint uniform_location = current_uv_pair.first; 7099 const double* uniform_value = current_uv_pair.second; 7100 7101 /* Retrieve the values from the GL implementation*/ 7102 gl.getUniformdv(po_id, uniform_location, returned_double_data); 7103 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed."); 7104 7105 gl.getUniformfv(po_id, uniform_location, returned_float_data); 7106 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed."); 7107 7108 gl.getUniformiv(po_id, uniform_location, returned_int_data); 7109 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed."); 7110 7111 gl.getUniformuiv(po_id, uniform_location, returned_uint_data); 7112 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed."); 7113 7114 /* Make sure the values reported match the reference values */ 7115 bool can_continue = true; 7116 const float epsilon = 1e-5f; 7117 7118 for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component) 7119 { 7120 if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon) 7121 { 7122 m_testCtx.getLog() 7123 << tcu::TestLog::Message 7124 << "Invalid uniform value reported by glGetUniformdv() for uniform location [" 7125 << uniform_location << "]" 7126 " and component [" 7127 << n_component << "]" 7128 ": retrieved:[" 7129 << returned_double_data[n_component] << "]" 7130 ", expected:[" 7131 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage; 7132 7133 result = false; 7134 } 7135 7136 if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon) 7137 { 7138 m_testCtx.getLog() 7139 << tcu::TestLog::Message 7140 << "Invalid uniform value reported by glGetUniformfv() for uniform location [" 7141 << uniform_location << "]" 7142 " and component [" 7143 << n_component << "]" 7144 ": retrieved:[" 7145 << returned_float_data[n_component] << "]" 7146 ", expected:[" 7147 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage; 7148 7149 result = false; 7150 } 7151 7152 /* ints */ 7153 int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component])); 7154 unsigned int rounded_uniform_value_uint = 7155 (unsigned int)(uniform_value[n_component] > 0.0) ? 7156 ((unsigned int)deFloatRound((float)uniform_value[n_component])) : 7157 0; 7158 7159 if (returned_int_data[n_component] != rounded_uniform_value_sint) 7160 { 7161 m_testCtx.getLog() 7162 << tcu::TestLog::Message 7163 << "Invalid uniform value reported by glGetUniformiv() for uniform location [" 7164 << uniform_location << "]" 7165 " and component [" 7166 << n_component << "]" 7167 ": retrieved:[" 7168 << returned_int_data[n_component] << "]" 7169 ", expected:[" 7170 << rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage; 7171 7172 result = false; 7173 } 7174 7175 if (returned_uint_data[n_component] != rounded_uniform_value_uint) 7176 { 7177 m_testCtx.getLog() 7178 << tcu::TestLog::Message 7179 << "Invalid uniform value reported by glGetUniformuiv() for uniform location [" 7180 << uniform_location << "]" 7181 " and component [" 7182 << n_component << "]" 7183 ": retrieved:[" 7184 << returned_uint_data[n_component] << "]" 7185 ", expected:[" 7186 << rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage; 7187 7188 result = false; 7189 } 7190 } /* for (all components) */ 7191 } /* for (all uniform+value pairs) */ 7192 } /* for (all 4 uniform types) */ 7193 } /* for (all shader stages) */ 7194 } /* for (both program objects) */ 7195 7196 /* All done! */ 7197 return result; 7198 } 7199 7200 /** Constructor 7201 * 7202 * @param context Rendering context. 7203 */ 7204 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context) 7205 : TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision" 7206 " floating-point variables work correctly") 7207 , m_base_value_bo_data(DE_NULL) 7208 , m_base_value_bo_id(0) 7209 , m_has_test_passed(true) 7210 , m_po_base_value_attribute_location(-1) 7211 , m_po_id(0) 7212 , m_vao_id(0) 7213 , m_vs_id(0) 7214 , m_xfb_bo_id(0) 7215 , m_xfb_bo_size(0) 7216 { 7217 /* Set up base value array (as per test spec) */ 7218 m_base_values[0] = -25.12065f; 7219 m_base_values[1] = 0.0f; 7220 m_base_values[2] = 0.001f; 7221 m_base_values[3] = 1.0f; 7222 m_base_values[4] = 256.78901f; 7223 7224 /* Set up swizzle matrix */ 7225 m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE; 7226 m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y; 7227 m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z; 7228 m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W; 7229 m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE; 7230 m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX; 7231 m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY; 7232 m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX; 7233 m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE; 7234 m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX; 7235 m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY; 7236 m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY; 7237 m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE; 7238 m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY; 7239 m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY; 7240 m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW; 7241 } 7242 7243 void GPUShaderFP64Test5::deinit() 7244 { 7245 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7246 7247 if (m_base_value_bo_data != DE_NULL) 7248 { 7249 delete[] m_base_value_bo_data; 7250 7251 m_base_value_bo_data = DE_NULL; 7252 } 7253 7254 if (m_base_value_bo_id != 0) 7255 { 7256 gl.deleteBuffers(1, &m_base_value_bo_id); 7257 7258 m_base_value_bo_id = 0; 7259 } 7260 7261 if (m_vao_id != 0) 7262 { 7263 gl.deleteVertexArrays(1, &m_vao_id); 7264 7265 m_vao_id = 0; 7266 } 7267 7268 if (m_xfb_bo_id != 0) 7269 { 7270 gl.deleteBuffers(1, &m_xfb_bo_id); 7271 7272 m_xfb_bo_id = 0; 7273 } 7274 7275 /* TCU_FAIL will skip the per sub test iteration de-initialization, we need to 7276 * take care of it here 7277 */ 7278 deinitInteration(); 7279 } 7280 7281 /** Deinitializes all buffers and GL objects that may have been generated 7282 * during test execution. 7283 **/ 7284 void GPUShaderFP64Test5::deinitInteration() 7285 { 7286 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7287 7288 if (m_po_id != 0) 7289 { 7290 gl.deleteProgram(m_po_id); 7291 7292 m_po_id = 0; 7293 } 7294 7295 if (m_vs_id != 0) 7296 { 7297 gl.deleteShader(m_vs_id); 7298 7299 m_vs_id = 0; 7300 } 7301 } 7302 7303 /** Executes a single test case iteration using user-provided test case descriptor. 7304 * 7305 * This function may throw a TestError exception if GL implementation misbehaves. 7306 * 7307 * @param test_case Test case descriptor to use. 7308 * 7309 * @return true if the values returned by GL implementation were found to be valid, 7310 * false otherwise. 7311 **/ 7312 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case) 7313 { 7314 bool result = true; 7315 7316 /* Convert the base values array to the type of input attribute we'll be using 7317 * for the iteration. 7318 */ 7319 Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type); 7320 7321 if (base_value_type == Utils::VARIABLE_TYPE_BOOL) 7322 { 7323 /* bools are actually represented by ints, since bool varyings are not allowed */ 7324 base_value_type = Utils::VARIABLE_TYPE_INT; 7325 } 7326 7327 const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type); 7328 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]); 7329 7330 m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values]; 7331 7332 unsigned char* base_value_traveller_ptr = m_base_value_bo_data; 7333 7334 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value) 7335 { 7336 switch (base_value_type) 7337 { 7338 case Utils::VARIABLE_TYPE_DOUBLE: 7339 *((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value]; 7340 break; 7341 case Utils::VARIABLE_TYPE_FLOAT: 7342 *((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value]; 7343 break; 7344 case Utils::VARIABLE_TYPE_INT: 7345 *((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value]; 7346 break; 7347 case Utils::VARIABLE_TYPE_UINT: 7348 *((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value]; 7349 break; 7350 7351 default: 7352 { 7353 TCU_FAIL("Unrecognized base value type"); 7354 } 7355 } 7356 7357 base_value_traveller_ptr += base_value_component_size; 7358 } /* for (all base values) */ 7359 7360 /* Update buffer object storage with the data we've just finished preparing. */ 7361 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7362 7363 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id); 7364 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 7365 7366 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data); 7367 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed."); 7368 7369 /* Configure vertex attribute array corresponding to 'base_value' attribute, so that the 7370 * new data is interpreted correctly. 7371 */ 7372 if (base_value_type == Utils::VARIABLE_TYPE_FLOAT) 7373 { 7374 gl.vertexAttribPointer(m_po_base_value_attribute_location, 1, /* size */ 7375 Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */ 7376 0, /* stride */ 7377 DE_NULL); /* pointer */ 7378 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed."); 7379 } 7380 else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT) 7381 { 7382 gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1, /* size */ 7383 Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */ 7384 DE_NULL); /* pointer */ 7385 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed."); 7386 } 7387 else 7388 { 7389 DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE); 7390 7391 gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */ 7392 GL_DOUBLE, 0, /* stride */ 7393 DE_NULL); /* pointer */ 7394 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed."); 7395 } 7396 7397 gl.enableVertexAttribArray(m_po_base_value_attribute_location); 7398 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed."); 7399 7400 /* Execute the draw call */ 7401 gl.useProgram(m_po_id); 7402 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 7403 7404 gl.beginTransformFeedback(GL_POINTS); 7405 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 7406 { 7407 gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values); 7408 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 7409 } 7410 gl.endTransformFeedback(); 7411 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 7412 7413 /* Map the XFB buffer object into process space */ 7414 void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 7415 7416 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 7417 DE_ASSERT(xfb_data_ptr != NULL); 7418 7419 /* Verify the data */ 7420 result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case); 7421 7422 /* Unmap the XFB BO */ 7423 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 7424 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 7425 7426 /** Good to release the data buffer at this point */ 7427 if (m_base_value_bo_data != DE_NULL) 7428 { 7429 delete[] m_base_value_bo_data; 7430 7431 m_base_value_bo_data = DE_NULL; 7432 } 7433 7434 /* All done */ 7435 return result; 7436 } 7437 7438 /** Returns properties of a swizzle operator described by @param type swizzle type. 7439 * 7440 * @param out_swizzle_string Deref will be used to store a GLSL literal 7441 * corresponding to the specific swizzle operator. 7442 * Must not be NULL. 7443 * @param out_n_components Deref will be used to store the amount of components 7444 * used by the operator. Must not be NULL. 7445 * @param out_component_order Deref will be used to store up to 4 integer values, 7446 * corresponding to component indices described by the 7447 * operator for a particular position. Must not be NULL. 7448 **/ 7449 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string, 7450 unsigned int* out_n_components, unsigned int* out_component_order) 7451 { 7452 unsigned int result_component_order[4] = { 0 }; 7453 unsigned int result_n_components = 0; 7454 std::string result_swizzle_string; 7455 7456 switch (type) 7457 { 7458 case SWIZZLE_TYPE_NONE: 7459 { 7460 result_swizzle_string = ""; 7461 result_n_components = 0; 7462 7463 break; 7464 } 7465 7466 case SWIZZLE_TYPE_XWZY: 7467 { 7468 result_swizzle_string = "xwzy"; 7469 result_n_components = 4; 7470 result_component_order[0] = 0; 7471 result_component_order[1] = 3; 7472 result_component_order[2] = 2; 7473 result_component_order[3] = 1; 7474 7475 break; 7476 } 7477 7478 case SWIZZLE_TYPE_XZXY: 7479 { 7480 result_swizzle_string = "xzxy"; 7481 result_n_components = 4; 7482 result_component_order[0] = 0; 7483 result_component_order[1] = 2; 7484 result_component_order[2] = 0; 7485 result_component_order[3] = 1; 7486 7487 break; 7488 } 7489 7490 case SWIZZLE_TYPE_XZY: 7491 { 7492 result_swizzle_string = "xzy"; 7493 result_n_components = 3; 7494 result_component_order[0] = 0; 7495 result_component_order[1] = 2; 7496 result_component_order[2] = 1; 7497 7498 break; 7499 } 7500 7501 case SWIZZLE_TYPE_XZYW: 7502 { 7503 result_swizzle_string = "xzyw"; 7504 result_n_components = 4; 7505 result_component_order[0] = 0; 7506 result_component_order[1] = 2; 7507 result_component_order[2] = 1; 7508 result_component_order[3] = 3; 7509 7510 break; 7511 } 7512 7513 case SWIZZLE_TYPE_Y: 7514 { 7515 result_swizzle_string = "y"; 7516 result_n_components = 1; 7517 result_component_order[0] = 1; 7518 7519 break; 7520 } 7521 7522 case SWIZZLE_TYPE_YX: 7523 { 7524 result_swizzle_string = "yx"; 7525 result_n_components = 2; 7526 result_component_order[0] = 1; 7527 result_component_order[1] = 0; 7528 7529 break; 7530 } 7531 7532 case SWIZZLE_TYPE_YXX: 7533 { 7534 result_swizzle_string = "yxx"; 7535 result_n_components = 3; 7536 result_component_order[0] = 1; 7537 result_component_order[1] = 0; 7538 result_component_order[2] = 0; 7539 7540 break; 7541 } 7542 7543 case SWIZZLE_TYPE_YXXY: 7544 { 7545 result_swizzle_string = "yxxy"; 7546 result_n_components = 4; 7547 result_component_order[0] = 1; 7548 result_component_order[1] = 0; 7549 result_component_order[2] = 0; 7550 result_component_order[3] = 1; 7551 7552 break; 7553 } 7554 7555 case SWIZZLE_TYPE_Z: 7556 { 7557 result_swizzle_string = "z"; 7558 result_n_components = 1; 7559 result_component_order[0] = 2; 7560 7561 break; 7562 } 7563 7564 case SWIZZLE_TYPE_ZY: 7565 { 7566 result_swizzle_string = "zy"; 7567 result_n_components = 2; 7568 result_component_order[0] = 2; 7569 result_component_order[1] = 1; 7570 7571 break; 7572 } 7573 7574 case SWIZZLE_TYPE_W: 7575 { 7576 result_swizzle_string = "w"; 7577 result_n_components = 1; 7578 result_component_order[0] = 3; 7579 7580 break; 7581 } 7582 7583 case SWIZZLE_TYPE_WX: 7584 { 7585 result_swizzle_string = "wx"; 7586 result_n_components = 2; 7587 result_component_order[0] = 3; 7588 result_component_order[1] = 0; 7589 7590 break; 7591 } 7592 7593 default: 7594 { 7595 TCU_FAIL("Unrecognized swizzle type"); 7596 } 7597 } /* switch (type) */ 7598 7599 if (out_swizzle_string != DE_NULL) 7600 { 7601 *out_swizzle_string = result_swizzle_string; 7602 } 7603 7604 if (out_n_components != DE_NULL) 7605 { 7606 *out_n_components = result_n_components; 7607 } 7608 7609 if (out_component_order != DE_NULL) 7610 { 7611 memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components); 7612 } 7613 } 7614 7615 /** Returns body of a vertex shader that should be used for particular test case, 7616 * given user-specified test case descriptor. 7617 * 7618 * @param test_case Descriptor to use for the query. 7619 * 7620 * @return Requested data. 7621 **/ 7622 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case) 7623 { 7624 std::stringstream result; 7625 const std::string base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type)); 7626 const std::string dst_type_string = Utils::getVariableTypeString(test_case.dst_type); 7627 const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type); 7628 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type); 7629 const std::string src_type_string = Utils::getVariableTypeString(test_case.src_type); 7630 7631 /* Add version preamble */ 7632 result << "#version 420\n" 7633 "\n"; 7634 7635 /* Declare output variables. Note that boolean output variables are not supported, so we need 7636 * to handle that special case correctly */ 7637 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL) 7638 { 7639 result << "out int result;\n"; 7640 } 7641 else 7642 { 7643 result << "out " << dst_type_string << " result;\n"; 7644 } 7645 7646 /* Declare input variables. Handle the bool case exclusively. */ 7647 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL) 7648 { 7649 /* Use ints for bools. We will cast them to bool in the code later. */ 7650 result << "in int base_value;\n"; 7651 } 7652 else 7653 { 7654 result << "in " << base_type_string << " base_value;\n"; 7655 } 7656 7657 /* Declare main() and construct the value we will be casting from. 7658 * 7659 * Note: Addition operations on bool values cause an implicit conversion to int 7660 * which is not allowed. Hence, we skip these operations for this special 7661 * case. 7662 */ 7663 result << "void main()\n" 7664 "{\n" 7665 << src_type_string << " lside_value = "; 7666 7667 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL) 7668 { 7669 result << src_type_string << "(0 != "; 7670 } 7671 else 7672 { 7673 result << src_type_string << "("; 7674 } 7675 7676 if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL) 7677 { 7678 for (unsigned int n_component = 0; n_component < n_src_components; ++n_component) 7679 { 7680 result << "base_value + " << n_component; 7681 7682 if (n_component != (n_src_components - 1)) 7683 { 7684 result << ", "; 7685 } 7686 } /* for (all components) */ 7687 } 7688 else 7689 { 7690 DE_ASSERT(n_src_components == 1); 7691 7692 result << "base_value"; 7693 } 7694 7695 result << ");\n"; 7696 7697 /* Perform the casting operation. Add swizzle operator if possible. */ 7698 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL) 7699 { 7700 /* Handle the bool case exclusively */ 7701 if (test_case.type == TEST_CASE_TYPE_EXPLICIT) 7702 { 7703 result << "result = (bool(lside_value) == false) ? 0 : 1"; 7704 } 7705 else 7706 { 7707 result << "result = (lside_value == false) ? 0 : 1"; 7708 } 7709 } 7710 else 7711 { 7712 if (test_case.type == TEST_CASE_TYPE_EXPLICIT) 7713 { 7714 result << "result = " << dst_type_string << "(lside_value)"; 7715 } 7716 else 7717 { 7718 result << "result = lside_value"; 7719 } 7720 } 7721 7722 if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type)) 7723 { 7724 /* Add a swizzle operator */ 7725 DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4); 7726 DE_ASSERT(n_src_components > 0 && n_src_components <= 4); 7727 7728 unsigned int swizzle_component_order[4] = { 0 }; 7729 unsigned int swizzle_n_components = 0; 7730 _swizzle_type swizzle_operator = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1]; 7731 std::string swizzle_string; 7732 7733 getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order); 7734 7735 if (swizzle_n_components > 0) 7736 { 7737 result << "." << swizzle_string; 7738 } 7739 } 7740 7741 /* Close the shader implementation. */ 7742 result << ";\n" 7743 "}\n"; 7744 7745 return result.str(); 7746 } 7747 7748 /** Initializes program & shader objects needed to run the iteration, given 7749 * user-specified test case descriptor. 7750 * 7751 * This function can throw a TestError exception if a GL error is detected 7752 * during execution. 7753 * 7754 * @param test_case Descriptor to use for the iteration. 7755 **/ 7756 void GPUShaderFP64Test5::initIteration(_test_case& test_case) 7757 { 7758 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7759 7760 /* Create program & shader objects */ 7761 m_po_id = gl.createProgram(); 7762 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 7763 7764 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 7765 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 7766 7767 /* Configure shader body */ 7768 std::string body = getVertexShaderBody(test_case); 7769 const char* body_raw_ptr = body.c_str(); 7770 7771 gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */); 7772 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 7773 7774 /* Store it in the test case descriptor for logging purposes */ 7775 test_case.shader_body = body; 7776 7777 /* Compile the shader */ 7778 glw::GLint compile_status = GL_FALSE; 7779 7780 gl.compileShader(m_vs_id); 7781 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 7782 7783 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); 7784 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 7785 7786 if (compile_status != GL_TRUE) 7787 { 7788 TCU_FAIL("Shader compilation failed"); 7789 } 7790 7791 /* Attach the shader to the program obejct */ 7792 gl.attachShader(m_po_id, m_vs_id); 7793 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 7794 7795 /* Configure XFB for the program object */ 7796 const char* xfb_varying_name = "result"; 7797 7798 gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS); 7799 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed."); 7800 7801 /* Link the program object */ 7802 glw::GLint link_status = GL_FALSE; 7803 7804 gl.linkProgram(m_po_id); 7805 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 7806 7807 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 7808 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 7809 7810 if (link_status != GL_TRUE) 7811 { 7812 TCU_FAIL("Program linking failed"); 7813 } 7814 7815 /* Retrieve attribute locations */ 7816 m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value"); 7817 GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed."); 7818 7819 if (m_po_base_value_attribute_location == -1) 7820 { 7821 TCU_FAIL("'base_value' is considered an inactive attribute which is invalid."); 7822 } 7823 } 7824 7825 /** Initializes GL objects used by all test cases. 7826 * 7827 * This function may throw a TestError exception if GL implementation reports 7828 * an error at any point. 7829 **/ 7830 void GPUShaderFP64Test5::initTest() 7831 { 7832 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 7833 7834 /* Generate buffer object IDs */ 7835 gl.genBuffers(1, &m_base_value_bo_id); 7836 gl.genBuffers(1, &m_xfb_bo_id); 7837 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed."); 7838 7839 /* Allocate buffer object storage for 'base_value' input attribute data. All iterations 7840 * will never eat up more than 1 double (as per test spec) and we will be drawing 7841 * as many points in a single draw call as there are defined in m_base_values array. 7842 */ 7843 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]); 7844 7845 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id); 7846 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 7847 7848 gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW); 7849 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 7850 7851 /* Allocate buffer object storage for XFB data. For each iteratiom we will be using 7852 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be 7853 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested. 7854 */ 7855 const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values; 7856 7857 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 7858 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 7859 7860 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 7861 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 7862 7863 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW); 7864 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 7865 7866 /* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */ 7867 m_xfb_bo_size = xfb_bo_size; 7868 7869 /* Generate a vertex array object we will need to use for the draw calls */ 7870 gl.genVertexArrays(1, &m_vao_id); 7871 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 7872 7873 gl.bindVertexArray(m_vao_id); 7874 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 7875 } 7876 7877 /** Executes test iteration. 7878 * 7879 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 7880 */ 7881 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate() 7882 { 7883 /* Do not execute the test if GL_ARB_texture_view is not supported */ 7884 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 7885 { 7886 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported."); 7887 } 7888 7889 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit")) 7890 { 7891 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported."); 7892 } 7893 7894 /* Initialize GL objects needed to run the tests */ 7895 initTest(); 7896 7897 /* Build iteration array to run the tests in an automated manner */ 7898 _test_case test_cases[] = { 7899 /* test case type */ /* source type */ /* destination type */ 7900 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" }, 7901 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" }, 7902 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" }, 7903 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" }, 7904 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" }, 7905 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" }, 7906 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" }, 7907 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" }, 7908 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" }, 7909 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" }, 7910 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" }, 7911 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" }, 7912 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" }, 7913 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" }, 7914 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" }, 7915 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" }, 7916 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" }, 7917 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" }, 7918 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" }, 7919 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" }, 7920 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" }, 7921 7922 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" }, 7923 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" }, 7924 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" }, 7925 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" }, 7926 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" }, 7927 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" }, 7928 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" }, 7929 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" } 7930 }; 7931 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]); 7932 7933 /* Execute all iterations */ 7934 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case) 7935 { 7936 _test_case& test_case = test_cases[n_test_case]; 7937 7938 /* Initialize a program object we will use to perform the casting */ 7939 initIteration(test_case); 7940 7941 /* Use the program object to XFB the results */ 7942 m_has_test_passed &= executeIteration(test_case); 7943 7944 /* Release the GL Resource for this sub test */ 7945 deinitInteration(); 7946 7947 } /* for (all test cases) */ 7948 /* We're done */ 7949 if (m_has_test_passed) 7950 { 7951 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 7952 } 7953 else 7954 { 7955 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 7956 } 7957 7958 return STOP; 7959 } 7960 7961 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor, 7962 * for which the data have been generated. 7963 * 7964 * @param data_ptr Buffer holding the data XFBed out by the shader. 7965 * @param test_case Descriptor of the test case, for which the vertex shader was 7966 * generated. 7967 * 7968 * @return true if the data were found to be valid, false otherwise. 7969 **/ 7970 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case) 7971 { 7972 const Utils::_variable_type base_dst_type = Utils::getBaseVariableType(test_case.dst_type); 7973 const Utils::_variable_type base_src_type = Utils::getBaseVariableType(test_case.src_type); 7974 const float epsilon = 1e-5f; 7975 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]); 7976 const unsigned int n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type); 7977 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type); 7978 bool result = true; 7979 _swizzle_type swizzle_operator = SWIZZLE_TYPE_NONE; 7980 unsigned int swizzle_order[4] = { 0 }; 7981 const unsigned char* traveller_ptr = data_ptr; 7982 7983 if (!Utils::isMatrixVariableType(test_case.src_type)) 7984 { 7985 DE_ASSERT(n_result_components >= 1 && n_result_components <= 4); 7986 DE_ASSERT(n_src_components >= 1 && n_src_components <= 4); 7987 7988 swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1]; 7989 7990 getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */ 7991 DE_NULL, /* out_n_components */ 7992 swizzle_order); 7993 } 7994 7995 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value) 7996 { 7997 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component) 7998 { 7999 unsigned int n_swizzled_component = n_result_component; 8000 8001 if (swizzle_operator != SWIZZLE_TYPE_NONE) 8002 { 8003 n_swizzled_component = 8004 (n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component]; 8005 } 8006 8007 switch (base_dst_type) 8008 { 8009 case Utils::VARIABLE_TYPE_BOOL: 8010 case Utils::VARIABLE_TYPE_INT: 8011 { 8012 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component); 8013 double expected_value = ref_expected_value; 8014 int result_value = *((int*)traveller_ptr); 8015 8016 if (base_dst_type == Utils::VARIABLE_TYPE_BOOL) 8017 { 8018 if (expected_value != 0.0) 8019 { 8020 expected_value = 1.0; 8021 } 8022 } 8023 8024 if (result_value != (int)expected_value) 8025 { 8026 m_testCtx.getLog() << tcu::TestLog::Message 8027 << "Invalid boolean/integer value obtained when doing an " 8028 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit") 8029 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type) 8030 << "]" 8031 ", component index: [" 8032 << n_swizzled_component << "]" 8033 ", value: [" 8034 << ref_expected_value << "]" 8035 " to GLSL type [" 8036 << Utils::getVariableTypeString(test_case.dst_type) << "]" 8037 ", retrieved value: [" 8038 << result_value << "]" 8039 ", expected value: [" 8040 << (int)expected_value << "]" 8041 ", shader used:\n" 8042 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage; 8043 8044 result = false; 8045 } 8046 8047 traveller_ptr += sizeof(int); 8048 break; 8049 } /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */ 8050 8051 case Utils::VARIABLE_TYPE_DOUBLE: 8052 { 8053 double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component; 8054 double expected_value = ref_expected_value; 8055 double result_value = *((double*)traveller_ptr); 8056 8057 if (base_src_type == Utils::VARIABLE_TYPE_BOOL) 8058 { 8059 expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0; 8060 } 8061 else if (base_src_type == Utils::VARIABLE_TYPE_INT) 8062 { 8063 expected_value = (int)expected_value; 8064 } 8065 else if (base_src_type == Utils::VARIABLE_TYPE_UINT) 8066 { 8067 // Negative values in base values array when converted to unsigned int will be ZERO 8068 // Addition operations done inside the shader in such cases will operate on ZERO rather 8069 // than the negative value being passed. 8070 // Replicate the sequence of conversion and addition operations done on the 8071 // shader input, to calculate the expected values in XFB data in the 8072 // problematic cases. 8073 if (expected_value < 0) 8074 { 8075 expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component; 8076 } 8077 expected_value = (unsigned int)expected_value; 8078 } 8079 8080 traveller_ptr += sizeof(double); 8081 if (de::abs(result_value - expected_value) > epsilon) 8082 { 8083 m_testCtx.getLog() << tcu::TestLog::Message 8084 << "Invalid double-precision floating-point value obtained when doing an " 8085 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit") 8086 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type) 8087 << "]" 8088 ", component index: [" 8089 << n_swizzled_component << "]" 8090 ", value: [" 8091 << ref_expected_value << "]" 8092 " to GLSL type [" 8093 << Utils::getVariableTypeString(test_case.dst_type) << "]" 8094 ", retrieved value: [" 8095 << std::setprecision(16) << result_value << "]" 8096 ", expected value: [" 8097 << std::setprecision(16) << expected_value << "]" 8098 ", shader used:\n" 8099 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage; 8100 8101 result = false; 8102 } 8103 8104 break; 8105 } /* VARIABLE_TYPE_DOUBLE case */ 8106 8107 case Utils::VARIABLE_TYPE_FLOAT: 8108 { 8109 float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component; 8110 float expected_value = ref_expected_value; 8111 float result_value = *((float*)traveller_ptr); 8112 8113 if (base_src_type == Utils::VARIABLE_TYPE_BOOL) 8114 { 8115 expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f; 8116 } 8117 else if (base_src_type == Utils::VARIABLE_TYPE_INT) 8118 { 8119 expected_value = (float)((int)expected_value); 8120 } 8121 else if (base_src_type == Utils::VARIABLE_TYPE_UINT) 8122 { 8123 expected_value = (float)((unsigned int)expected_value); 8124 } 8125 8126 traveller_ptr += sizeof(float); 8127 if (de::abs(result_value - expected_value) > epsilon) 8128 { 8129 m_testCtx.getLog() << tcu::TestLog::Message 8130 << "Invalid single-precision floating-point value obtained when doing an " 8131 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit") 8132 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type) 8133 << "]" 8134 ", component index: [" 8135 << n_swizzled_component << "]" 8136 ", value: [" 8137 << ref_expected_value << "]" 8138 " to GLSL type [" 8139 << Utils::getVariableTypeString(test_case.dst_type) << "]" 8140 ", retrieved value: [" 8141 << std::setprecision(16) << result_value << "]" 8142 ", expected value: [" 8143 << std::setprecision(16) << expected_value << "]" 8144 ", shader used:\n" 8145 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage; 8146 8147 result = false; 8148 } 8149 8150 break; 8151 } /* VARIABLE_TYPE_FLOAT case */ 8152 8153 case Utils::VARIABLE_TYPE_UINT: 8154 { 8155 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component); 8156 double expected_value = ref_expected_value; 8157 unsigned int result_value = *((unsigned int*)traveller_ptr); 8158 8159 traveller_ptr += sizeof(unsigned int); 8160 if (result_value != (unsigned int)expected_value) 8161 { 8162 if (expected_value < 0.0) 8163 { 8164 // It is undefined to convert a negative floating-point value to an uint. 8165 break; 8166 } 8167 8168 m_testCtx.getLog() << tcu::TestLog::Message 8169 << "Invalid unsigned integer value obtained when doing an " 8170 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit") 8171 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type) 8172 << "]" 8173 ", component index: [" 8174 << n_swizzled_component << "]" 8175 ", value: [" 8176 << ref_expected_value << "]" 8177 " to GLSL type [" 8178 << Utils::getVariableTypeString(test_case.dst_type) << "]" 8179 ", retrieved value: [" 8180 << result_value << "]" 8181 ", expected value: [" 8182 << (unsigned int)expected_value << "]" 8183 ", shader used:\n" 8184 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage; 8185 8186 result = false; 8187 } 8188 8189 break; 8190 } /* VARIABLE_TYPE_UINT case */ 8191 8192 default: 8193 { 8194 TCU_FAIL("Unrecognized variable type"); 8195 } 8196 } /* switch (test_case.dst_type) */ 8197 } /* for (all result components) */ 8198 } /* for (all base values) */ 8199 8200 return result; 8201 } 8202 8203 /** Constructor 8204 * 8205 * @param context Rendering context. 8206 */ 8207 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context) 8208 : TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected " 8209 "during compilation time.") 8210 , m_cs_id(0) 8211 , m_fs_id(0) 8212 , m_gs_id(0) 8213 , m_tc_id(0) 8214 , m_te_id(0) 8215 , m_vs_id(0) 8216 , m_has_test_passed(true) 8217 { 8218 } 8219 8220 /** Deinitializes all buffers and GL objects that may have been generated 8221 * during test execution. 8222 **/ 8223 void GPUShaderFP64Test6::deinit() 8224 { 8225 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8226 8227 if (m_cs_id != 0) 8228 { 8229 gl.deleteShader(m_cs_id); 8230 8231 m_cs_id = 0; 8232 } 8233 8234 if (m_fs_id != 0) 8235 { 8236 gl.deleteShader(m_fs_id); 8237 8238 m_fs_id = 0; 8239 } 8240 8241 if (m_gs_id != 0) 8242 { 8243 gl.deleteShader(m_gs_id); 8244 8245 m_gs_id = 0; 8246 } 8247 8248 if (m_tc_id != 0) 8249 { 8250 gl.deleteShader(m_tc_id); 8251 8252 m_tc_id = 0; 8253 } 8254 8255 if (m_te_id != 0) 8256 { 8257 gl.deleteShader(m_te_id); 8258 8259 m_te_id = 0; 8260 } 8261 8262 if (m_vs_id != 0) 8263 { 8264 gl.deleteShader(m_vs_id); 8265 8266 m_vs_id = 0; 8267 } 8268 } 8269 8270 /** Executes a single test case. 8271 * 8272 * This function can throw TestError exceptions if GL implementation reports 8273 * an error. 8274 * 8275 * @param test_case Test case descriptor. 8276 * 8277 * @return true if test case passed, false otherwise. 8278 **/ 8279 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case) 8280 { 8281 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8282 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id }; 8283 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]); 8284 bool result = true; 8285 const char* stage_body = NULL; 8286 const char* stage_name = NULL; 8287 8288 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id) 8289 { 8290 const glw::GLuint so_id = so_ids[n_so_id]; 8291 8292 /* Skip compute shader if it is not supported */ 8293 if (0 == so_id) 8294 { 8295 continue; 8296 } 8297 8298 /* Compile the shader */ 8299 gl.compileShader(so_id); 8300 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 8301 8302 /* Has the compilation failed as expected? */ 8303 glw::GLint compile_status = GL_TRUE; 8304 8305 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); 8306 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 8307 8308 if (compile_status == GL_TRUE) 8309 { 8310 /* What is the current stage's name? */ 8311 if (so_id == m_cs_id) 8312 { 8313 stage_body = test_case.cs_shader_body.c_str(); 8314 stage_name = "Compute shader"; 8315 } 8316 else if (so_id == m_fs_id) 8317 { 8318 stage_body = test_case.fs_shader_body.c_str(); 8319 stage_name = "Fragment shader"; 8320 } 8321 else if (so_id == m_gs_id) 8322 { 8323 stage_body = test_case.gs_shader_body.c_str(); 8324 stage_name = "Geometry shader"; 8325 } 8326 else if (so_id == m_tc_id) 8327 { 8328 stage_body = test_case.tc_shader_body.c_str(); 8329 stage_name = "Tessellation control shader"; 8330 } 8331 else if (so_id == m_te_id) 8332 { 8333 stage_body = test_case.te_shader_body.c_str(); 8334 stage_name = "Tessellation evaluation shader"; 8335 } 8336 else if (so_id == m_vs_id) 8337 { 8338 stage_body = test_case.vs_shader_body.c_str(); 8339 stage_name = "Vertex shader"; 8340 } 8341 else 8342 { 8343 /* Doesn't make much sense to throw exceptions here so.. */ 8344 stage_body = ""; 8345 stage_name = "[?]"; 8346 } 8347 8348 /* This shader should have never compiled successfully! */ 8349 m_testCtx.getLog() << tcu::TestLog::Message << stage_name 8350 << " has been compiled successfully, even though the shader was malformed." 8351 " Following is shader body:\n" 8352 << stage_body << tcu::TestLog::EndMessage; 8353 8354 result = false; 8355 } 8356 } /* for (all shader objects) */ 8357 8358 return result; 8359 } 8360 8361 /** Retrieves body of a compute shader that should be used for the purpose of 8362 * user-specified test case. 8363 * 8364 * @param test_case Test case descriptor to use. 8365 * 8366 * @return Requested string. 8367 **/ 8368 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case) 8369 { 8370 std::stringstream result_sstream; 8371 8372 /* Add pre-amble */ 8373 result_sstream << "#version 420\n" 8374 "#extension GL_ARB_compute_shader : require\n" 8375 "\n" 8376 "layout(local_size_x = 6) in;\n" 8377 "\n" 8378 "void main()\n" 8379 "{\n"; 8380 8381 /* Add local variable declarations */ 8382 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src"; 8383 8384 if (test_case.src_array_size > 1) 8385 { 8386 result_sstream << "[" << test_case.src_array_size << "]"; 8387 } 8388 8389 result_sstream << ";\n"; 8390 8391 if (test_case.wrap_dst_type_in_structure) 8392 { 8393 result_sstream << "struct\n" 8394 "{\n" 8395 << Utils::getVariableTypeString(test_case.dst_type) << " member"; 8396 } 8397 else 8398 { 8399 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst"; 8400 } 8401 8402 result_sstream << ";\n"; 8403 8404 if (test_case.wrap_dst_type_in_structure) 8405 { 8406 result_sstream << "\n} dst;\n"; 8407 } 8408 8409 /* Add actual body */ 8410 result_sstream << "dst = src;\n" 8411 "}\n"; 8412 8413 /* Return the body */ 8414 return result_sstream.str(); 8415 } 8416 8417 /** Retrieves body of a fragment shader that should be used for the purpose of 8418 * user-specified test case. 8419 * 8420 * @param test_case Test case descriptor to use. 8421 * 8422 * @return Requested string. 8423 **/ 8424 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case) 8425 { 8426 std::stringstream result_sstream; 8427 8428 /* Add pre-amble */ 8429 result_sstream << "#version 420\n" 8430 "\n" 8431 "void main()\n" 8432 "{\n"; 8433 8434 /* Add local variable declarations */ 8435 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src"; 8436 8437 if (test_case.src_array_size > 1) 8438 { 8439 result_sstream << "[" << test_case.src_array_size << "]"; 8440 } 8441 8442 result_sstream << ";\n"; 8443 8444 if (test_case.wrap_dst_type_in_structure) 8445 { 8446 result_sstream << "struct\n" 8447 "{\n" 8448 << Utils::getVariableTypeString(test_case.dst_type) << " member"; 8449 } 8450 else 8451 { 8452 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst"; 8453 } 8454 8455 result_sstream << ";\n"; 8456 8457 if (test_case.wrap_dst_type_in_structure) 8458 { 8459 result_sstream << "\n} dst;\n"; 8460 } 8461 8462 /* Add actual body */ 8463 result_sstream << "dst = src;\n" 8464 "}\n"; 8465 8466 /* Return the body */ 8467 return result_sstream.str(); 8468 } 8469 8470 /** Retrieves body of a geometry shader that should be used for the purpose of 8471 * user-specified test case. 8472 * 8473 * @param test_case Test case descriptor to use. 8474 * 8475 * @return Requested string. 8476 **/ 8477 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case) 8478 { 8479 std::stringstream result_sstream; 8480 8481 /* Add preamble */ 8482 result_sstream << "#version 420\n" 8483 "\n" 8484 "layout(points) in;\n" 8485 "layout(max_vertices=1, points) out;\n" 8486 "\n" 8487 "void main()\n" 8488 "{\n"; 8489 8490 /* Add local variable declarations */ 8491 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src"; 8492 8493 if (test_case.src_array_size > 1) 8494 { 8495 result_sstream << "[" << test_case.src_array_size << "]"; 8496 } 8497 8498 result_sstream << ";\n"; 8499 8500 if (test_case.wrap_dst_type_in_structure) 8501 { 8502 result_sstream << "struct\n" 8503 "{\n" 8504 << Utils::getVariableTypeString(test_case.dst_type) << " member"; 8505 } 8506 else 8507 { 8508 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst"; 8509 } 8510 8511 result_sstream << ";\n" 8512 "\n"; 8513 8514 if (test_case.wrap_dst_type_in_structure) 8515 { 8516 result_sstream << "} dst;\n"; 8517 } 8518 8519 /* Add actual body */ 8520 result_sstream << "dst = src;\n" 8521 "}\n"; 8522 8523 /* We're done! */ 8524 return result_sstream.str(); 8525 } 8526 8527 /** Retrieves body of a tesellation control shader that should be used for the purpose of 8528 * user-specified test case. 8529 * 8530 * @param test_case Test case descriptor to use. 8531 * 8532 * @return Requested string. 8533 **/ 8534 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case) 8535 { 8536 std::stringstream result_sstream; 8537 8538 /* Add preamble */ 8539 result_sstream << "#version 420\n" 8540 "\n" 8541 "layout(vertices=4) out;\n" 8542 "\n" 8543 "void main()\n" 8544 "{\n"; 8545 8546 /* Add local variable declarations. */ 8547 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src"; 8548 8549 if (test_case.src_array_size > 1) 8550 { 8551 result_sstream << "[" << test_case.src_array_size << "]"; 8552 } 8553 8554 result_sstream << ";\n"; 8555 8556 if (test_case.wrap_dst_type_in_structure) 8557 { 8558 result_sstream << "struct\n" 8559 "{\n" 8560 << Utils::getVariableTypeString(test_case.dst_type) << " member"; 8561 } 8562 else 8563 { 8564 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst"; 8565 } 8566 8567 if (test_case.wrap_dst_type_in_structure) 8568 { 8569 result_sstream << ";\n" 8570 "} dst;\n"; 8571 } 8572 else 8573 { 8574 result_sstream << ";\n"; 8575 } 8576 8577 /* Continue with the actual body. */ 8578 result_sstream << "gl_TessLevelOuter[0] = 1.0;\n" 8579 "gl_TessLevelOuter[1] = 1.0;\n" 8580 "dst = src;\n" 8581 "}\n"; 8582 8583 /* Return the body */ 8584 return result_sstream.str(); 8585 } 8586 8587 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of 8588 * user-specified test case. 8589 * 8590 * @param test_case Test case descriptor to use. 8591 * 8592 * @return Requested string. 8593 **/ 8594 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case) 8595 { 8596 std::stringstream result_sstream; 8597 8598 /* Add preamble */ 8599 result_sstream << "#version 420\n" 8600 "\n" 8601 "layout(isolines) in;\n" 8602 "\n" 8603 "void main()\n" 8604 "{\n"; 8605 8606 /* Add local variable declarations */ 8607 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src"; 8608 8609 if (test_case.src_array_size > 1) 8610 { 8611 result_sstream << "[" << test_case.src_array_size << "]"; 8612 } 8613 8614 result_sstream << ";\n"; 8615 8616 if (test_case.wrap_dst_type_in_structure) 8617 { 8618 result_sstream << "struct\n" 8619 "{\n" 8620 << Utils::getVariableTypeString(test_case.dst_type) << " member"; 8621 } 8622 else 8623 { 8624 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst"; 8625 } 8626 8627 if (test_case.wrap_dst_type_in_structure) 8628 { 8629 result_sstream << ";\n" 8630 "} dst;\n"; 8631 } 8632 else 8633 { 8634 result_sstream << ";\n"; 8635 } 8636 8637 /* Continue with the actual body. */ 8638 result_sstream << "dst = src;\n"; 8639 8640 /* Complete the body */ 8641 result_sstream << "}\n"; 8642 8643 /* Return the body */ 8644 return result_sstream.str(); 8645 } 8646 8647 /** Retrieves body of a vertex shader that should be used for the purpose of 8648 * user-specified test case. 8649 * 8650 * @param test_case Test case descriptor to use. 8651 * 8652 * @return Requested string. 8653 **/ 8654 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case) 8655 { 8656 std::stringstream result_sstream; 8657 8658 /* Add preamble */ 8659 result_sstream << "#version 420\n" 8660 "\n" 8661 "void main()\n" 8662 "{\n"; 8663 8664 /* Add local variables */ 8665 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src"; 8666 8667 if (test_case.src_array_size > 1) 8668 { 8669 result_sstream << "[" << test_case.src_array_size << "]"; 8670 } 8671 8672 result_sstream << ";\n"; 8673 8674 if (test_case.wrap_dst_type_in_structure) 8675 { 8676 result_sstream << "struct\n" 8677 "{\n" 8678 << Utils::getVariableTypeString(test_case.dst_type) << " member"; 8679 } 8680 else 8681 { 8682 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst"; 8683 } 8684 8685 if (test_case.wrap_dst_type_in_structure) 8686 { 8687 result_sstream << ";\n" 8688 "} dst;\n"; 8689 } 8690 else 8691 { 8692 result_sstream << ";\n"; 8693 } 8694 8695 /* Start actual body */ 8696 result_sstream << "dst = src;\n" 8697 "gl_Position = vec4(1.0);\n" 8698 "}"; 8699 8700 return result_sstream.str(); 8701 } 8702 8703 /** Initializes shader objects required to run the test. */ 8704 void GPUShaderFP64Test6::initTest() 8705 { 8706 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8707 8708 /* Generate shader objects */ 8709 8710 /* Compute shader support and GL 4.2 required */ 8711 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) && 8712 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */))) 8713 { 8714 m_cs_id = gl.createShader(GL_COMPUTE_SHADER); 8715 } 8716 8717 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 8718 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 8719 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER); 8720 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER); 8721 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 8722 8723 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 8724 } 8725 8726 /** Assigns shader bodies to all shader objects that will be used for a single iteration. 8727 * 8728 * @param test_case Test case descriptor to generate the shader bodies for. 8729 **/ 8730 void GPUShaderFP64Test6::initIteration(_test_case& test_case) 8731 { 8732 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8733 8734 test_case.cs_shader_body = getComputeShaderBody(test_case); 8735 test_case.fs_shader_body = getFragmentShaderBody(test_case); 8736 test_case.gs_shader_body = getGeometryShaderBody(test_case); 8737 test_case.tc_shader_body = getTessellationControlShaderBody(test_case); 8738 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case); 8739 test_case.vs_shader_body = getVertexShaderBody(test_case); 8740 8741 /* Assign the bodies to relevant shaders */ 8742 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str(); 8743 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str(); 8744 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str(); 8745 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str(); 8746 const char* te_body_raw_ptr = test_case.te_shader_body.c_str(); 8747 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str(); 8748 8749 /* m_cs_id is initialized only if compute_shader is supported */ 8750 if (0 != m_cs_id) 8751 { 8752 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */); 8753 } 8754 8755 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */); 8756 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */); 8757 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */); 8758 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */); 8759 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */); 8760 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed."); 8761 } 8762 8763 /** Executes test iteration. 8764 * 8765 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 8766 */ 8767 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate() 8768 { 8769 /* Do not execute the test if GL_ARB_texture_view is not supported */ 8770 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 8771 { 8772 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported."); 8773 } 8774 8775 /* Initialize GL objects needed to run the tests */ 8776 initTest(); 8777 8778 /* Build iteration array to run the tests in an automated manner */ 8779 _test_case test_cases[] = { 8780 /* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */ 8781 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" }, 8782 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" }, 8783 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" }, 8784 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" }, 8785 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" }, 8786 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" }, 8787 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" }, 8788 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" }, 8789 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" }, 8790 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" }, 8791 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" }, 8792 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" }, 8793 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" }, 8794 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" }, 8795 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" }, 8796 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" }, 8797 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" }, 8798 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" }, 8799 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" }, 8800 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" }, 8801 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" }, 8802 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" }, 8803 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" }, 8804 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" }, 8805 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" }, 8806 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" }, 8807 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" }, 8808 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" }, 8809 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" }, 8810 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" }, 8811 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" }, 8812 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" }, 8813 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" }, 8814 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" }, 8815 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" }, 8816 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" }, 8817 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" }, 8818 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" }, 8819 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" }, 8820 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" }, 8821 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" }, 8822 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" } 8823 }; 8824 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]); 8825 8826 /* Execute all iterations */ 8827 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case) 8828 { 8829 _test_case& test_case = test_cases[n_test_case]; 8830 8831 /* Initialize a program object we will use to perform the casting */ 8832 initIteration(test_case); 8833 8834 /* Use the program object to XFB the results */ 8835 m_has_test_passed &= executeIteration(test_case); 8836 8837 } /* for (all test cases) */ 8838 8839 /* We're done */ 8840 if (m_has_test_passed) 8841 { 8842 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 8843 } 8844 else 8845 { 8846 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 8847 } 8848 8849 return STOP; 8850 } 8851 8852 /** Constructor 8853 * 8854 * @param context Rendering context. 8855 */ 8856 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context) 8857 : TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly " 8858 "in all shader stages.") 8859 , m_are_double_inputs_supported(false) 8860 , m_fbo_id(0) 8861 , m_fs_id(0) 8862 , m_gs_id(0) 8863 , m_has_test_passed(true) 8864 , m_n_max_components_per_stage(0) 8865 , m_n_xfb_varyings(0) 8866 , m_po_id(0) 8867 , m_tc_id(0) 8868 , m_te_id(0) 8869 , m_to_id(0) 8870 , m_to_data(NULL) 8871 , m_to_height(4) 8872 , m_to_width(4) 8873 , m_xfb_bo_id(0) 8874 , m_xfb_varyings(NULL) 8875 , m_vao_id(0) 8876 , m_vs_id(0) 8877 { 8878 } 8879 8880 /** Compiles all shaders attached to test program object and links it. 8881 * 8882 * @param variables 8883 * 8884 * @return true if the process was executed successfully, false otherwise. 8885 */ 8886 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables) 8887 { 8888 std::string fs_body = getFragmentShaderBody(variables); 8889 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 8890 std::string gs_body = getGeometryShaderBody(variables); 8891 std::string tc_body = getTessellationControlShaderBody(variables); 8892 std::string te_body = getTessellationEvaluationShaderBody(variables); 8893 std::string vs_body = getVertexShaderBody(variables); 8894 bool result = false; 8895 8896 /* Try to link the program object */ 8897 glw::GLint link_status = GL_FALSE; 8898 8899 /* Compile the shaders */ 8900 if (!compileShader(m_fs_id, fs_body)) 8901 { 8902 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage; 8903 8904 goto end; 8905 } 8906 8907 if (!compileShader(m_gs_id, gs_body)) 8908 { 8909 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage; 8910 8911 goto end; 8912 } 8913 8914 if (!compileShader(m_tc_id, tc_body)) 8915 { 8916 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile." 8917 << tcu::TestLog::EndMessage; 8918 8919 goto end; 8920 } 8921 8922 if (!compileShader(m_te_id, te_body)) 8923 { 8924 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile." 8925 << tcu::TestLog::EndMessage; 8926 8927 goto end; 8928 } 8929 8930 if (!compileShader(m_vs_id, vs_body)) 8931 { 8932 m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage; 8933 8934 goto end; 8935 } 8936 8937 /* Configure XFB */ 8938 releaseXFBVaryingNames(); 8939 generateXFBVaryingNames(variables); 8940 8941 gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS); 8942 8943 gl.linkProgram(m_po_id); 8944 8945 /* Have we succeeded? */ 8946 GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed."); 8947 8948 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 8949 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 8950 8951 if (link_status != GL_TRUE) 8952 { 8953 m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link." 8954 << tcu::TestLog::EndMessage; 8955 8956 goto end; 8957 } 8958 8959 /* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */ 8960 if (m_are_double_inputs_supported) 8961 { 8962 const size_t n_variables = variables.size(); 8963 8964 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable) 8965 { 8966 _variable& current_variable = variables[n_variable]; 8967 std::stringstream attribute_name_sstream; 8968 8969 attribute_name_sstream << "in_vs_variable" << n_variable; 8970 8971 if (current_variable.array_size > 1) 8972 { 8973 attribute_name_sstream << "[0]"; 8974 } 8975 8976 current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str()); 8977 8978 if (current_variable.attribute_location == -1) 8979 { 8980 m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named [" 8981 << attribute_name_sstream.str().c_str() 8982 << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage; 8983 8984 m_has_test_passed = false; 8985 goto end; 8986 } 8987 } /* for (all test variables) */ 8988 } /* if (m_are_double_inputs_supported) */ 8989 8990 m_current_fs_body = fs_body; 8991 m_current_gs_body = gs_body; 8992 m_current_tc_body = tc_body; 8993 m_current_te_body = te_body; 8994 m_current_vs_body = vs_body; 8995 8996 result = true; 8997 8998 end: 8999 return result; 9000 } 9001 9002 /** Updates shader object's body and then compiles the shader. 9003 * 9004 * @param body Body to use for the shader. 9005 * 9006 * @return true if the shader compiled successfully, false otherwise. 9007 **/ 9008 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body) 9009 { 9010 const char* body_raw_ptr = body.c_str(); 9011 glw::GLint compile_status = GL_FALSE; 9012 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9013 9014 gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */); 9015 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 9016 9017 gl.compileShader(shader_id); 9018 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 9019 9020 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status); 9021 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 9022 9023 return (compile_status == GL_TRUE); 9024 } 9025 9026 /** Configure storage of a buffer object used for capturing XFB data. 9027 * 9028 * @param variables Holds descriptor for all variables used for the iteration the 9029 * BO is being configured for. Storage size will be directly related 9030 * to the number of the variables and their type. 9031 */ 9032 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables) 9033 { 9034 DE_ASSERT(m_n_xfb_varyings != 0); 9035 9036 /* Geometry shaders outputs 4 vertices making up a triangle strip per draw call. 9037 * The test only draws a single patch, and triangles are caught by transform feed-back. 9038 * Let's initialize the storage, according to the list of variables that will be used 9039 * for the test run. 9040 */ 9041 unsigned int bo_size = 0; 9042 9043 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end(); 9044 variables_iterator++) 9045 { 9046 const _variable& variable = *variables_iterator; 9047 unsigned int n_bytes_needed = static_cast<unsigned int>( 9048 Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double)); 9049 9050 bo_size += n_bytes_needed; 9051 } /* for (all variables) */ 9052 9053 bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */ 9054 9055 /* Set up the BO storage */ 9056 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9057 9058 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW); 9059 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 9060 } 9061 9062 /** Deinitializes all buffers and GL objects that may have been generated 9063 * during test execution. 9064 **/ 9065 void GPUShaderFP64Test7::deinit() 9066 { 9067 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9068 9069 if (m_fbo_id != 0) 9070 { 9071 gl.deleteFramebuffers(1, &m_fbo_id); 9072 9073 m_fbo_id = 0; 9074 } 9075 9076 if (m_fs_id != 0) 9077 { 9078 gl.deleteShader(m_fs_id); 9079 9080 m_fs_id = 0; 9081 } 9082 9083 if (m_gs_id != 0) 9084 { 9085 gl.deleteShader(m_gs_id); 9086 9087 m_gs_id = 0; 9088 } 9089 9090 if (m_po_id != 0) 9091 { 9092 gl.deleteProgram(m_po_id); 9093 9094 m_po_id = 0; 9095 } 9096 9097 if (m_tc_id != 0) 9098 { 9099 gl.deleteShader(m_tc_id); 9100 9101 m_tc_id = 0; 9102 } 9103 9104 if (m_te_id != 0) 9105 { 9106 gl.deleteShader(m_te_id); 9107 9108 m_te_id = 0; 9109 } 9110 9111 if (m_to_data != NULL) 9112 { 9113 delete[] m_to_data; 9114 9115 m_to_data = NULL; 9116 } 9117 9118 if (m_to_id != 0) 9119 { 9120 gl.deleteTextures(1, &m_to_id); 9121 9122 m_to_id = 0; 9123 } 9124 9125 if (m_xfb_bo_id != 0) 9126 { 9127 gl.deleteBuffers(1, &m_xfb_bo_id); 9128 9129 m_xfb_bo_id = 0; 9130 } 9131 9132 if (m_xfb_varyings != DE_NULL) 9133 { 9134 releaseXFBVaryingNames(); 9135 } 9136 9137 if (m_vao_id != 0) 9138 { 9139 gl.deleteVertexArrays(1, &m_vao_id); 9140 9141 m_vao_id = 0; 9142 } 9143 9144 if (m_vs_id != 0) 9145 { 9146 gl.deleteShader(m_vs_id); 9147 9148 m_vs_id = 0; 9149 } 9150 } 9151 9152 /** Executes the functional part of the test (case a) from the test spec) 9153 * 9154 * @param variables Vector of variable descriptors defining properties of 9155 * variables that should be used for the iteration. 9156 * 9157 * @return true if the test passed, false otherwise. 9158 **/ 9159 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables) 9160 { 9161 bool result = true; 9162 9163 /* Build the test program */ 9164 if (!buildTestProgram(variables)) 9165 { 9166 return false; 9167 } 9168 9169 /* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */ 9170 if (m_are_double_inputs_supported) 9171 { 9172 setInputAttributeValues(variables); 9173 } 9174 9175 /* Set up buffer object to hold XFB data. The data will be used for logging purposes 9176 * only, if a data mismatch is detected. 9177 */ 9178 configureXFBBuffer(variables); 9179 9180 /* Issue a draw call using the test program */ 9181 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9182 9183 gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f); 9184 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed."); 9185 9186 gl.clear(GL_COLOR_BUFFER_BIT); 9187 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed."); 9188 9189 gl.useProgram(m_po_id); 9190 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 9191 9192 gl.viewport(0, /* x */ 9193 0, /* y */ 9194 m_to_width, m_to_height); 9195 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed."); 9196 9197 gl.beginTransformFeedback(GL_TRIANGLES); 9198 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 9199 { 9200 gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */); 9201 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 9202 } 9203 gl.endTransformFeedback(); 9204 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 9205 9206 /* Verify color attachment contents */ 9207 const float epsilon = 1.0f / 255.0f; 9208 9209 gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data); 9210 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 9211 9212 for (unsigned int y = 0; y < m_to_height; ++y) 9213 { 9214 const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y; 9215 9216 for (unsigned int x = 0; x < m_to_width; ++x) 9217 { 9218 const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x; 9219 9220 if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon || 9221 de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon) 9222 { 9223 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y 9224 << ")" 9225 "; expected:(0, 255, 0, 0), found: (" 9226 << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2] 9227 << ", " << (int)pixel_ptr[3] 9228 << "), with the following variable types used as varyings:" 9229 << tcu::TestLog::EndMessage; 9230 9231 /* List the variable types that failed the test */ 9232 const size_t n_variables = variables.size(); 9233 9234 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable) 9235 { 9236 m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": " 9237 << Utils::getVariableTypeString(variables[n_variable].type) 9238 << " (array size:" << variables[n_variable].array_size << ")" 9239 << tcu::TestLog::EndMessage; 9240 } /* for (all variable types) */ 9241 9242 /* Log the variable contents */ 9243 logVariableContents(variables); 9244 9245 /* Log shaders used for the iteration */ 9246 m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n" 9247 "\n" 9248 "(VS):\n" 9249 << m_current_vs_body.c_str() << "\n" 9250 << "(TC):\n" 9251 "\n" 9252 << m_current_tc_body.c_str() << "\n" 9253 "(TE):\n" 9254 "\n" 9255 << m_current_te_body.c_str() << "\n" 9256 "(GS):\n" 9257 << m_current_gs_body.c_str() << "\n" 9258 "(FS):\n" 9259 "\n" 9260 << m_current_fs_body.c_str() << tcu::TestLog::EndMessage; 9261 9262 result = false; 9263 9264 goto end; 9265 } 9266 } /* for (all columns) */ 9267 } /* for (all rows) */ 9268 9269 /* All done! */ 9270 end: 9271 return result; 9272 } 9273 9274 /** Takes user-input vector of test variables and allocates & fills an array of strings 9275 * holding names of geometry shader stage varyings that should be captured during 9276 * transform feedback operation. The array will be stored in m_xfb_varyings. 9277 * 9278 * @param variables Holds all test variable descriptors to be used for the iteration. 9279 */ 9280 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables) 9281 { 9282 unsigned int n_variable = 0; 9283 unsigned int n_varying = 0; 9284 unsigned int n_varyings = 0; 9285 9286 if (m_xfb_varyings != NULL) 9287 { 9288 releaseXFBVaryingNames(); 9289 } 9290 9291 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end(); 9292 ++variables_iterator) 9293 { 9294 const _variable& variable = *variables_iterator; 9295 9296 n_varyings += variable.array_size; 9297 } 9298 9299 m_xfb_varyings = new glw::GLchar*[n_varyings]; 9300 9301 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end(); 9302 ++variables_iterator, ++n_variable) 9303 { 9304 const _variable& variable = *variables_iterator; 9305 9306 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying) 9307 { 9308 std::stringstream varying_sstream; 9309 size_t varying_length; 9310 9311 varying_sstream << "gs_variable" << n_variable; 9312 9313 if (variable.array_size > 1) 9314 { 9315 varying_sstream << "[" << array_index << "]"; 9316 } 9317 9318 /* Store the varying name */ 9319 varying_length = varying_sstream.str().length(); 9320 m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */]; 9321 9322 memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length); 9323 m_xfb_varyings[n_varying][varying_length] = 0; 9324 } /* for (all array indices) */ 9325 } /* for (all varyings) */ 9326 9327 m_n_xfb_varyings = n_varyings; 9328 } 9329 9330 /** Retrieves body of a shader that defines input variable of user-specified type & array size 9331 * without using the "flat" keyword. (case c) ) 9332 * 9333 * @param input_variable_type Variable type to use for input variable declaration. 9334 * @param array_size 1 if the variable should not be arrayed; otherwise defines size 9335 * of the arrayed variable. 9336 * 9337 * @return Requested string. 9338 **/ 9339 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput( 9340 Utils::_variable_type input_variable_type, unsigned int array_size) 9341 { 9342 std::stringstream result_sstream; 9343 std::stringstream array_index_stringstream; 9344 std::stringstream array_size_stringstream; 9345 9346 if (array_size > 1) 9347 { 9348 array_index_stringstream << "[0]"; 9349 array_size_stringstream << "[" << array_size << "]"; 9350 } 9351 9352 if (Utils::isMatrixVariableType(input_variable_type)) 9353 { 9354 array_index_stringstream << "[0].x"; 9355 } 9356 else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1) 9357 { 9358 array_index_stringstream << "[0]"; 9359 } 9360 9361 result_sstream << "#version 400\n" 9362 "\n" 9363 "in " 9364 << Utils::getVariableTypeString(input_variable_type) << " test_input" 9365 << array_size_stringstream.str() << ";\n" 9366 "\n" 9367 "out float test_output;\n" 9368 "\n" 9369 "void main()\n" 9370 "{\n" 9371 " if (test_input" 9372 << array_index_stringstream.str() << " > 2.0)\n" 9373 " {\n" 9374 " test_output = 1.0;\n" 9375 " }\n" 9376 " else\n" 9377 " {\n" 9378 " test_output = 3.0;\n" 9379 " }\n" 9380 "}\n"; 9381 9382 return result_sstream.str(); 9383 } 9384 9385 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ). 9386 * 9387 * @param input_variable_type Variable type to use for input variable declaration. 9388 * @param array_size 1 if the variable should not be arrayed; otherwise defines size 9389 * of the arrayed variable. 9390 * 9391 * @return Requested string. 9392 **/ 9393 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput( 9394 Utils::_variable_type output_variable_type, unsigned int array_size) 9395 { 9396 std::stringstream array_index_sstream; 9397 std::stringstream array_size_sstream; 9398 std::stringstream result_sstream; 9399 std::string output_variable_type_string = Utils::getVariableTypeString(output_variable_type); 9400 9401 if (array_size > 1) 9402 { 9403 array_index_sstream << "[0]"; 9404 array_size_sstream << "[" << array_size << "]"; 9405 } 9406 9407 result_sstream << "#version 400\n" 9408 "\n" 9409 "out " 9410 << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n" 9411 "\n" 9412 "void main()\n" 9413 "{\n" 9414 " test_output" 9415 << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n" 9416 "}\n"; 9417 9418 return result_sstream.str(); 9419 } 9420 9421 /** Retrieves body of a fragment shader that uses user-specified set of variables 9422 * to declare contents of input & output block. 9423 * 9424 * @param variables As per description. 9425 * 9426 * @return Requested string. 9427 **/ 9428 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables) 9429 { 9430 std::stringstream result_sstream; 9431 9432 /* Form the pre-amble */ 9433 result_sstream << "#version 400\n" 9434 "\n" 9435 9436 /* Add input block */ 9437 << "in GS_DATA\n" 9438 "{\n" 9439 << getVariableDeclarations("gs", variables, "flat") << "};\n" 9440 "\n" 9441 9442 /* Add output variable */ 9443 << "out vec4 result;\n" 9444 "\n" 9445 9446 /* Add main() definition */ 9447 "void main()\n" 9448 "{\n" 9449 "const double epsilon = 1e-5;\n" 9450 "\n" 9451 "result = vec4(1, 0, 0, 0);\n" 9452 "\n"; 9453 9454 /* Determine expected values first */ 9455 unsigned int base_counter = 1; 9456 const size_t n_variables = variables.size(); 9457 9458 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable) 9459 { 9460 unsigned int variable_array_size = variables[n_variable].array_size; 9461 Utils::_variable_type variable_type = variables[n_variable].type; 9462 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 9463 std::string variable_type_string = Utils::getVariableTypeString(variable_type); 9464 9465 std::stringstream array_size_sstream; 9466 9467 if (variable_array_size > 1) 9468 { 9469 array_size_sstream << "[" << variable_array_size << "]"; 9470 } 9471 9472 /* Local variable declaration */ 9473 result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str() 9474 << ";\n" 9475 "\n"; 9476 9477 /* Set expected values */ 9478 for (unsigned int index = 0; index < variable_array_size; ++index) 9479 { 9480 std::stringstream array_index_sstream; 9481 9482 if (variable_array_size > 1) 9483 { 9484 array_index_sstream << "[" << index << "]"; 9485 } 9486 9487 result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = " 9488 << variable_type_string << "("; 9489 9490 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 9491 { 9492 unsigned int expected_value = 9493 (base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3); 9494 9495 if (m_are_double_inputs_supported) 9496 { 9497 /* VS input attributes */ 9498 //expected_value += (base_counter + 6); 9499 expected_value -= 1; 9500 } 9501 9502 result_sstream << expected_value; 9503 9504 if (n_component != (n_variable_type_components - 1)) 9505 { 9506 result_sstream << ", "; 9507 } 9508 9509 ++base_counter; 9510 } /* for (all components) */ 9511 9512 result_sstream << ");\n"; 9513 } /* for (all array indices) */ 9514 9515 result_sstream << "\n"; 9516 } /* for (all variable types) */ 9517 9518 /* Now that we know the expected values, do a huge conditional check to verify if all 9519 * input variables carry correct information. 9520 */ 9521 result_sstream << "if ("; 9522 9523 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable) 9524 { 9525 unsigned int variable_array_size = variables[n_variable].array_size; 9526 Utils::_variable_type variable_type = variables[n_variable].type; 9527 bool is_variable_type_matrix = Utils::isMatrixVariableType(variable_type); 9528 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 9529 std::string variable_type_string = Utils::getVariableTypeString(variable_type); 9530 9531 for (unsigned int index = 0; index < variable_array_size; ++index) 9532 { 9533 std::stringstream array_index_sstream; 9534 9535 if (variable_array_size > 1) 9536 { 9537 array_index_sstream << "[" << index << "]"; 9538 } 9539 9540 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 9541 { 9542 std::stringstream component_index_sstream; 9543 9544 if (n_variable_type_components > 1) 9545 { 9546 component_index_sstream << "[" << n_component << "]"; 9547 } 9548 9549 result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str(); 9550 9551 if (is_variable_type_matrix) 9552 { 9553 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type); 9554 const unsigned int column = n_component % n_columns; 9555 const unsigned int row = n_component / n_columns; 9556 9557 result_sstream << "[" << column << "]" 9558 "." 9559 << Utils::getComponentAtIndex(row); 9560 } 9561 else 9562 { 9563 result_sstream << component_index_sstream.str(); 9564 } 9565 9566 result_sstream << " - gs_variable" << n_variable << array_index_sstream.str(); 9567 9568 if (is_variable_type_matrix) 9569 { 9570 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type); 9571 const unsigned int column = n_component % n_columns; 9572 const unsigned int row = n_component / n_columns; 9573 9574 result_sstream << "[" << column << "]" 9575 "." 9576 << Utils::getComponentAtIndex(row); 9577 } 9578 else 9579 { 9580 result_sstream << component_index_sstream.str(); 9581 } 9582 9583 result_sstream << ") <= epsilon &&"; 9584 } /* for (all components) */ 9585 } /* for (all array indices) */ 9586 } /* for (all variable types) */ 9587 9588 result_sstream << "true)\n" 9589 "{\n" 9590 " result = vec4(0, 1, 0, 0);\n" 9591 "}\n" 9592 "}\n"; 9593 9594 /* All done */ 9595 return result_sstream.str(); 9596 } 9597 9598 /** Retrieves body of a geometry shader that uses user-specified set of variables 9599 * to declare contents of input & output block. 9600 * 9601 * @param variables As per description. 9602 * 9603 * @return Requested string. 9604 **/ 9605 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables) 9606 { 9607 std::stringstream result_sstream; 9608 9609 /* Form the pre-amble */ 9610 result_sstream << "#version 400\n" 9611 "\n" 9612 "layout(triangles) in;\n" 9613 "layout(triangle_strip, max_vertices=4) out;\n" 9614 "\n" 9615 9616 /* Add the input block */ 9617 "in TE_DATA\n" 9618 "{\n" 9619 << getVariableDeclarations("te", variables) << "} in_data[];\n" 9620 "\n" 9621 9622 /* Add the output block */ 9623 "out GS_DATA\n" 9624 "{\n" 9625 << getVariableDeclarations("gs", variables, "flat") << "};\n" 9626 "\n" 9627 9628 /* Declare main() function */ 9629 "void main()\n" 9630 "{\n"; 9631 9632 /* Take input variables, add a predefined value and forward them to output variables */ 9633 const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 9634 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; 9635 const unsigned int n_quad_vertices = 9636 sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */; 9637 const size_t n_variables = variables.size(); 9638 9639 for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex) 9640 { 9641 unsigned int counter = 4; 9642 const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */; 9643 9644 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable) 9645 { 9646 unsigned int variable_array_size = variables[n_variable].array_size; 9647 Utils::_variable_type variable_type = variables[n_variable].type; 9648 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 9649 std::string variable_type_string = Utils::getVariableTypeString(variable_type); 9650 9651 for (unsigned int index = 0; index < variable_array_size; ++index) 9652 { 9653 std::stringstream array_index_sstream; 9654 9655 if (variable_array_size > 1) 9656 { 9657 array_index_sstream << "[" << index << "]"; 9658 } 9659 9660 result_sstream << "gs_variable" << n_variable << array_index_sstream.str() 9661 << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + " 9662 << variable_type_string << "("; 9663 9664 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 9665 { 9666 result_sstream << (counter++); 9667 9668 if (n_component != (n_variable_type_components - 1)) 9669 { 9670 result_sstream << ", "; 9671 } 9672 } /* for (all components) */ 9673 9674 result_sstream << ");\n"; 9675 } /* for (all array indices) */ 9676 } /* for (all variable types) */ 9677 9678 result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", " 9679 << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n" 9680 "EmitVertex();\n"; 9681 } /* for (all emitted quad vertices) */ 9682 9683 result_sstream << "EndPrimitive();\n" 9684 "}\n"; 9685 9686 /* All done */ 9687 return result_sstream.str(); 9688 } 9689 9690 /** Retrieves body of a tessellation control shader that uses user-specified set of variables 9691 * to declare contents of input & output block. 9692 * 9693 * @param variables As per description. 9694 * 9695 * @return Requested string. 9696 **/ 9697 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables) 9698 { 9699 std::stringstream result_sstream; 9700 9701 /* Form the pre-amble */ 9702 result_sstream << "#version 400\n" 9703 "\n" 9704 "layout (vertices=4) out;\n" 9705 9706 /* Declare input block */ 9707 "in VS_DATA\n" 9708 "{\n" 9709 << getVariableDeclarations("vs", variables) << "} in_data[];\n" 9710 9711 /* Declare output block */ 9712 "out TC_DATA\n" 9713 "{\n" 9714 << getVariableDeclarations("tc", variables) << "} out_data[];\n" 9715 "\n" 9716 9717 /* Define main() */ 9718 "void main()\n" 9719 "{\n" 9720 " gl_TessLevelInner[0] = 1;\n" 9721 " gl_TessLevelInner[1] = 1;\n" 9722 " gl_TessLevelOuter[0] = 1;\n" 9723 " gl_TessLevelOuter[1] = 1;\n" 9724 " gl_TessLevelOuter[2] = 1;\n" 9725 " gl_TessLevelOuter[3] = 1;\n" 9726 "\n"; 9727 9728 /* Take input variables, add a predefined value and forward them to output variables */ 9729 const size_t n_variables = variables.size(); 9730 unsigned int counter = 2; 9731 9732 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable) 9733 { 9734 unsigned int variable_array_size = variables[n_variable].array_size; 9735 Utils::_variable_type variable_type = variables[n_variable].type; 9736 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 9737 std::string variable_type_string = Utils::getVariableTypeString(variable_type); 9738 9739 for (unsigned int index = 0; index < variable_array_size; ++index) 9740 { 9741 std::stringstream array_index_sstream; 9742 9743 if (variable_array_size > 1) 9744 { 9745 array_index_sstream << "[" << index << "]"; 9746 } 9747 9748 result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str() 9749 << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + " 9750 << variable_type_string << "("; 9751 9752 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 9753 { 9754 result_sstream << (counter++); 9755 9756 if (n_component != (n_variable_type_components - 1)) 9757 { 9758 result_sstream << ", "; 9759 } 9760 } 9761 9762 result_sstream << ");\n"; 9763 } /* for (all array indices) */ 9764 } /* for (all variable types) */ 9765 9766 result_sstream << "}\n"; 9767 9768 /* We're done */ 9769 return result_sstream.str(); 9770 } 9771 9772 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables 9773 * to declare contents of input & output block. 9774 * 9775 * @param variables As per description. 9776 * 9777 * @return Requested string. 9778 **/ 9779 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables) 9780 { 9781 std::stringstream result_sstream; 9782 9783 /* Form the pre-amble */ 9784 result_sstream << "#version 400\n" 9785 "\n" 9786 "layout(quads) in;\n" 9787 "\n" 9788 9789 /* Define input block */ 9790 "in TC_DATA\n" 9791 "{\n" 9792 << getVariableDeclarations("tc", variables) << "} in_data[];\n" 9793 "\n" 9794 9795 /* Define output block */ 9796 "out TE_DATA\n" 9797 "{\n" 9798 << getVariableDeclarations("te", variables) << "};\n" 9799 "\n" 9800 9801 /* Define main() */ 9802 "void main()\n" 9803 "{\n"; 9804 9805 /* Take input variables, add a predefined value and forward them to output variables */ 9806 const size_t n_variables = variables.size(); 9807 unsigned int counter = 3; 9808 9809 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable) 9810 { 9811 unsigned int variable_array_size = variables[n_variable].array_size; 9812 Utils::_variable_type variable_type = variables[n_variable].type; 9813 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 9814 std::string variable_type_string = Utils::getVariableTypeString(variable_type); 9815 9816 for (unsigned int index = 0; index < variable_array_size; ++index) 9817 { 9818 std::stringstream array_index_sstream; 9819 9820 if (variable_array_size > 1) 9821 { 9822 array_index_sstream << "[" << index << "]"; 9823 } 9824 9825 result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable" 9826 << n_variable << array_index_sstream.str() << " + " << variable_type_string << "("; 9827 9828 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 9829 { 9830 result_sstream << (counter++); 9831 9832 if (n_component != (n_variable_type_components - 1)) 9833 { 9834 result_sstream << ", "; 9835 } 9836 } /* for (all components) */ 9837 9838 result_sstream << ");\n"; 9839 } /* for (all array indices) */ 9840 } /* for (all variable types) */ 9841 9842 result_sstream << "}\n"; 9843 9844 /* All done */ 9845 return result_sstream.str(); 9846 } 9847 9848 /** Returns a string containing declarations of user-specified set of variables. 9849 * Each declaration can optionally use a layot qualifier requested by the caller. 9850 * 9851 * @param prefix Prefix to use for variable names. 9852 * @param variables List of variables to declare in the result string. 9853 * @param explicit_locations true if each declaration should explicitly define location 9854 * of the variable ( eg. (layout location=X) ) 9855 * @param layout_qualifier Optional qualifier to use for the declaration. Must not 9856 * be NULL. 9857 * 9858 * @return Requested string. 9859 **/ 9860 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables, 9861 const char* layout_qualifier) 9862 { 9863 std::stringstream result_sstream; 9864 9865 /* Define output variables */ 9866 const size_t n_variables = variables.size(); 9867 9868 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable) 9869 { 9870 unsigned int variable_array_size = variables[n_variable].array_size; 9871 Utils::_variable_type variable_type = variables[n_variable].type; 9872 std::string variable_type_string = Utils::getVariableTypeString(variable_type); 9873 9874 result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable; 9875 9876 if (variable_array_size > 1) 9877 { 9878 result_sstream << "[" << variable_array_size << "]"; 9879 } 9880 9881 result_sstream << ";\n"; 9882 } /* for (all user-specified variable types) */ 9883 9884 return result_sstream.str(); 9885 } 9886 9887 /** Retrieves body of a vertex shader that uses user-specified set of variables 9888 * to declare contents of input & output block. 9889 * 9890 * @param variables As per description. 9891 * 9892 * @return Requested string. 9893 **/ 9894 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables) 9895 { 9896 std::stringstream result_sstream; 9897 9898 /* Form pre-amble */ 9899 result_sstream << "#version 400\n" 9900 "\n"; 9901 9902 /* Define input variables if GL_ARB_vertex_attrib_64bit is supported */ 9903 if (m_are_double_inputs_supported) 9904 { 9905 result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n" 9906 << getVariableDeclarations("in_vs", variables, "in"); 9907 } 9908 9909 /* Define output variables */ 9910 result_sstream << "out VS_DATA\n" 9911 "{\n" 9912 << getVariableDeclarations("vs", variables); 9913 9914 /* Define main() */ 9915 result_sstream << "};\n" 9916 "\n" 9917 "void main()\n" 9918 "{\n"; 9919 9920 /* Set output variable values */ 9921 unsigned int counter = 1; 9922 const size_t n_variables = variables.size(); 9923 9924 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable) 9925 { 9926 unsigned int variable_array_size = variables[n_variable].array_size; 9927 Utils::_variable_type variable_type = variables[n_variable].type; 9928 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type); 9929 std::string variable_type_string = Utils::getVariableTypeString(variable_type); 9930 9931 for (unsigned int index = 0; index < variable_array_size; ++index) 9932 { 9933 if (variable_array_size == 1) 9934 { 9935 result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "("; 9936 } 9937 else 9938 { 9939 result_sstream << "vs_variable" << n_variable << "[" << index << "]" 9940 << " = " << variable_type_string << "("; 9941 } 9942 9943 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component) 9944 { 9945 result_sstream << (double)(counter++); 9946 9947 /* Use input attributes, if available */ 9948 if (m_are_double_inputs_supported) 9949 { 9950 result_sstream << " + in_vs_variable" << n_variable; 9951 9952 if (variable_array_size > 1) 9953 { 9954 result_sstream << "[" << index << "]"; 9955 } 9956 9957 if (Utils::isMatrixVariableType(variables[n_variable].type)) 9958 { 9959 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type); 9960 const unsigned int column = n_component % n_columns; 9961 const unsigned int row = n_component / n_columns; 9962 9963 result_sstream << "[" << (column) << "]" 9964 "." 9965 << Utils::getComponentAtIndex(row); 9966 } 9967 else if (n_variable_type_components > 1) 9968 { 9969 result_sstream << "[" << n_component << "]"; 9970 } 9971 } 9972 9973 if (n_component != (n_variable_type_components - 1)) 9974 { 9975 result_sstream << ", "; 9976 } 9977 } /* for (all components) */ 9978 9979 result_sstream << ");\n"; 9980 } 9981 } /* for (all variable types) */ 9982 9983 /* We will be using geometry shader to lay out the actual vertices so 9984 * the only thing we need to make sure is that the vertex never gets 9985 * culled. 9986 */ 9987 result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n" 9988 "}\n"; 9989 9990 /* That's it */ 9991 return result_sstream.str(); 9992 } 9993 9994 /** Initializes shader objects required to run the test. */ 9995 void GPUShaderFP64Test7::initTest() 9996 { 9997 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9998 9999 /* Are double-precision input variables supported? */ 10000 m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"); 10001 10002 /* Create a vertex array object */ 10003 gl.genVertexArrays(1, &m_vao_id); 10004 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 10005 10006 gl.bindVertexArray(m_vao_id); 10007 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 10008 10009 /* Create a texture object we will use as FBO's color attachment */ 10010 gl.genTextures(1, &m_to_id); 10011 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed"); 10012 10013 gl.bindTexture(GL_TEXTURE_2D, m_to_id); 10014 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 10015 10016 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height); 10017 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed."); 10018 10019 /* Allocate temporary buffer to hold the texture data we will be reading 10020 * from color attachment. */ 10021 m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */]; 10022 10023 /* Create and set up a framebuffer object */ 10024 gl.genFramebuffers(1, &m_fbo_id); 10025 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed."); 10026 10027 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 10028 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed."); 10029 10030 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */); 10031 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 10032 10033 /* Create all shader objects */ 10034 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 10035 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 10036 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER); 10037 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER); 10038 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 10039 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 10040 10041 /* Create test program object */ 10042 m_po_id = gl.createProgram(); 10043 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 10044 10045 /* Attach the shaders to the program object */ 10046 gl.attachShader(m_po_id, m_fs_id); 10047 gl.attachShader(m_po_id, m_gs_id); 10048 gl.attachShader(m_po_id, m_tc_id); 10049 gl.attachShader(m_po_id, m_te_id); 10050 gl.attachShader(m_po_id, m_vs_id); 10051 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 10052 10053 /* The test passes double-precision values through the whole rendering pipeline. 10054 * This translates to a notable amount of components that we would need to transfer 10055 * all values in one fell swoop. The number is large enough to exceed minimum 10056 * capabilities as described for OpenGL 4.0 implementations. 10057 * For that reason, the test executes in turns. Each turn is allocated as many 10058 * double-precision scalar/matrix values as supported by the tested GL implementation. 10059 */ 10060 glw::GLint gl_max_fragment_input_components_value = 0; 10061 glw::GLint gl_max_geometry_input_components_value = 0; 10062 glw::GLint gl_max_geometry_output_components_value = 0; 10063 glw::GLint gl_max_tess_control_input_components_value = 0; 10064 glw::GLint gl_max_tess_control_output_components_value = 0; 10065 glw::GLint gl_max_tess_evaluation_input_components_value = 0; 10066 glw::GLint gl_max_tess_evaluation_output_components_value = 0; 10067 glw::GLint gl_max_transform_feedback_interleaved_components_value = 0; 10068 glw::GLint gl_max_vertex_output_components_value = 0; 10069 10070 gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value); 10071 gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value); 10072 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value); 10073 gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value); 10074 gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value); 10075 gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value); 10076 gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value); 10077 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, 10078 &gl_max_transform_feedback_interleaved_components_value); 10079 gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value); 10080 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed."); 10081 10082 m_n_max_components_per_stage = 10083 de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value); 10084 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value); 10085 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value); 10086 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value); 10087 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value); 10088 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value); 10089 m_n_max_components_per_stage = 10090 de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value); 10091 m_n_max_components_per_stage = 10092 de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value); 10093 10094 /* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build 10095 * the input patch */ 10096 gl.patchParameteri(GL_PATCH_VERTICES, 1); 10097 10098 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed."); 10099 10100 /* Initialize a BO we will use to hold XFB data */ 10101 gl.genBuffers(1, &m_xfb_bo_id); 10102 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 10103 10104 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 10105 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 10106 10107 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 10108 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 10109 } 10110 10111 /** Executes test iteration. 10112 * 10113 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10114 */ 10115 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate() 10116 { 10117 /* Do not execute the test if GL_ARB_texture_view is not supported */ 10118 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 10119 { 10120 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported."); 10121 } 10122 10123 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit")) 10124 { 10125 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported."); 10126 } 10127 10128 /* Initialize GL objects required to run the test */ 10129 initTest(); 10130 10131 /* Check the negative cases first */ 10132 const Utils::_variable_type double_variable_types[] = { 10133 Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3, 10134 Utils::VARIABLE_TYPE_DVEC4, Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, 10135 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, 10136 Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, 10137 Utils::VARIABLE_TYPE_DMAT4X3, 10138 }; 10139 const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]); 10140 10141 for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types; 10142 ++n_double_variable_type) 10143 { 10144 for (unsigned int array_size = 1; array_size < 3; ++array_size) 10145 { 10146 Utils::_variable_type variable_type = double_variable_types[n_double_variable_type]; 10147 10148 if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size))) 10149 { 10150 m_testCtx.getLog() << tcu::TestLog::Message 10151 << "A fragment shader with double-precision output variable compiled successfully." 10152 << tcu::TestLog::EndMessage; 10153 10154 m_has_test_passed = false; 10155 } 10156 10157 if (compileShader(m_fs_id, 10158 getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size))) 10159 { 10160 m_testCtx.getLog() 10161 << tcu::TestLog::Message 10162 << "A fragment shader with double-precision input variables lacking flat layout qualifier" 10163 " compiled successfully." 10164 << tcu::TestLog::EndMessage; 10165 10166 m_has_test_passed = false; 10167 } 10168 } 10169 } /* for (all variable types) */ 10170 10171 /* Execute functional test. Split the run into as many iterations as necessary 10172 * so that we do not exceed GL implementation's capabilities. */ 10173 unsigned int n_tested_variables = 0; 10174 _variables variables_to_test; 10175 10176 while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */) 10177 { 10178 glw::GLint total_n_used_components = 0; 10179 10180 /* Use as many variables as possible for the iterations. Do not exceed maximum amount 10181 * of varying components that can be used for all shadr stages. 10182 */ 10183 while (total_n_used_components < m_n_max_components_per_stage && 10184 n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */) 10185 { 10186 _variable new_variable; 10187 unsigned int n_type_components = 0; 10188 glw::GLint n_used_components = 0; 10189 10190 new_variable.array_size = 10191 ((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */ 10192 new_variable.type = double_variable_types[n_tested_variables / 2]; 10193 10194 /* Double-precision varyings can use twice as many components as single-precision FPs */ 10195 n_type_components = 4 /* components per location */ * 10196 Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type); 10197 n_used_components = n_type_components * new_variable.array_size * 2; 10198 10199 /* Do we have enough space? */ 10200 if (total_n_used_components + n_used_components > m_n_max_components_per_stage) 10201 { 10202 if (n_used_components > m_n_max_components_per_stage) 10203 { //if the number of components for this variable is larger than the max_components_per_stage, then skip it. 10204 n_tested_variables++; 10205 } 10206 break; 10207 } 10208 10209 /* We can safely test the type in current iteration */ 10210 total_n_used_components += n_used_components; 10211 n_tested_variables++; 10212 10213 variables_to_test.push_back(new_variable); 10214 } 10215 10216 if (variables_to_test.size() > 0) 10217 { 10218 m_has_test_passed &= executeFunctionalTest(variables_to_test); 10219 10220 variables_to_test.clear(); 10221 } 10222 } 10223 10224 /* We're done */ 10225 if (m_has_test_passed) 10226 { 10227 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 10228 } 10229 else 10230 { 10231 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 10232 } 10233 10234 return STOP; 10235 } 10236 10237 /** Logs contents of test variables, as XFBed out by already executed test iteration. */ 10238 void GPUShaderFP64Test7::logVariableContents(const _variables& variables) 10239 { 10240 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10241 std::stringstream log_sstream; 10242 10243 log_sstream << "Test variable values as retrieved from geometry shader:\n"; 10244 10245 /* Map the XFB BO contents into process space */ 10246 const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 10247 10248 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 10249 10250 /* Read the variable contents. We only care about the set of varyings emitted 10251 * for first vertex in the geometry shader */ 10252 unsigned int n_varying = 0; 10253 const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data; 10254 10255 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end(); 10256 ++variables_iterator, ++n_varying) 10257 { 10258 const _variable& variable = *variables_iterator; 10259 const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type); 10260 const unsigned int n_components = Utils::getNumberOfComponentsForVariableType(variable.type); 10261 10262 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index) 10263 { 10264 log_sstream << "gs_variable" << n_varying; 10265 10266 if (variable.array_size > 1) 10267 { 10268 log_sstream << "[" << array_index << "]"; 10269 } 10270 10271 log_sstream << ": ("; 10272 10273 for (unsigned int n_component = 0; n_component < n_components; ++n_component) 10274 { 10275 log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr); 10276 10277 if (n_component != (n_components - 1)) 10278 { 10279 log_sstream << ", "; 10280 } 10281 10282 traveller_ptr += sizeof(double); 10283 } 10284 10285 log_sstream << ")\n"; 10286 } /* for (all array indices) */ 10287 } /* for (all variables) */ 10288 10289 /* Unmap the BO */ 10290 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 10291 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 10292 10293 /* Pass the logged stream into the framework */ 10294 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage; 10295 } 10296 10297 /** De-allocates an arary holding strings representing names of varyings that 10298 * should be used for transform feed-back. 10299 **/ 10300 void GPUShaderFP64Test7::releaseXFBVaryingNames() 10301 { 10302 for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying) 10303 { 10304 delete[] m_xfb_varyings[n_varying]; 10305 } 10306 10307 delete m_xfb_varyings; 10308 m_xfb_varyings = DE_NULL; 10309 10310 m_n_xfb_varyings = 0; 10311 } 10312 10313 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported. 10314 * Takes a list of test variables used for current iteration and assigns increasing values 10315 * to subsequent input attributes of the test program. 10316 * 10317 * @param variables Test variables of the current iteration. 10318 */ 10319 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables) 10320 { 10321 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10322 unsigned int counter = 6; 10323 10324 for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end(); 10325 variable_iterator++) 10326 { 10327 const _variable& variable = *variable_iterator; 10328 const bool is_matrix_type = Utils::isMatrixVariableType(variable.type); 10329 const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type); 10330 unsigned int n_components = 0; 10331 unsigned int n_columns = 1; 10332 10333 if (is_matrix_type) 10334 { 10335 n_columns = Utils::getNumberOfColumnsForVariableType(variable.type); 10336 n_components = n_total_components / n_columns; 10337 10338 DE_ASSERT(n_total_components % n_columns == 0); 10339 } 10340 else 10341 { 10342 n_components = n_total_components; 10343 } 10344 10345 DE_ASSERT(n_components >= 1 && n_components <= 4); 10346 10347 for (unsigned int index = 0; index < n_columns * variable.array_size; ++index) 10348 { 10349 const double data[] = { -1, -1, -1, -1 }; 10350 10351 switch (n_components) 10352 { 10353 case 1: 10354 { 10355 gl.vertexAttribL1dv(variable.attribute_location + index, data); 10356 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed."); 10357 10358 break; 10359 } 10360 10361 case 2: 10362 { 10363 gl.vertexAttribL2dv(variable.attribute_location + index, data); 10364 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed."); 10365 10366 break; 10367 } 10368 10369 case 3: 10370 { 10371 gl.vertexAttribL3dv(variable.attribute_location + index, data); 10372 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed."); 10373 10374 break; 10375 } 10376 10377 case 4: 10378 { 10379 gl.vertexAttribL4dv(variable.attribute_location + index, data); 10380 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed."); 10381 10382 break; 10383 } 10384 10385 default: 10386 { 10387 TCU_FAIL("Unrecognized number of components"); 10388 } 10389 } /* switch (n_components) */ 10390 10391 /* Make sure VAAs are disabled */ 10392 gl.disableVertexAttribArray(variable.attribute_location + index); 10393 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed."); 10394 10395 counter += n_components; 10396 } /* for (all array indices) */ 10397 } /* for (all variables) */ 10398 } 10399 10400 /** Constructor 10401 * 10402 * @param context Rendering context. 10403 */ 10404 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context) 10405 : TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors " 10406 "are accepted during compilation stage") 10407 , m_cs_id(0) 10408 , m_fs_id(0) 10409 , m_gs_id(0) 10410 , m_tc_id(0) 10411 , m_te_id(0) 10412 , m_vs_id(0) 10413 , m_has_test_passed(true) 10414 { 10415 } 10416 10417 /** Deinitializes all buffers and GL objects that may have been generated 10418 * during test execution. 10419 **/ 10420 void GPUShaderFP64Test8::deinit() 10421 { 10422 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10423 10424 if (m_cs_id != 0) 10425 { 10426 gl.deleteShader(m_cs_id); 10427 10428 m_cs_id = 0; 10429 } 10430 10431 if (m_fs_id != 0) 10432 { 10433 gl.deleteShader(m_fs_id); 10434 10435 m_fs_id = 0; 10436 } 10437 10438 if (m_gs_id != 0) 10439 { 10440 gl.deleteShader(m_gs_id); 10441 10442 m_gs_id = 0; 10443 } 10444 10445 if (m_tc_id != 0) 10446 { 10447 gl.deleteShader(m_tc_id); 10448 10449 m_tc_id = 0; 10450 } 10451 10452 if (m_te_id != 0) 10453 { 10454 gl.deleteShader(m_te_id); 10455 10456 m_te_id = 0; 10457 } 10458 10459 if (m_vs_id != 0) 10460 { 10461 gl.deleteShader(m_vs_id); 10462 10463 m_vs_id = 0; 10464 } 10465 } 10466 10467 /** Executes a single test case. 10468 * 10469 * This function can throw TestError exceptions if GL implementation reports 10470 * an error. 10471 * 10472 * @param test_case Test case descriptor. 10473 * 10474 * @return true if test case passed, false otherwise. 10475 **/ 10476 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case) 10477 { 10478 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10479 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id }; 10480 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]); 10481 bool result = true; 10482 const char* stage_body = NULL; 10483 const char* stage_name = NULL; 10484 10485 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id) 10486 { 10487 const glw::GLuint so_id = so_ids[n_so_id]; 10488 10489 /* Skip compute shader if it is not supported */ 10490 if (0 == so_id) 10491 { 10492 continue; 10493 } 10494 10495 /* Compile the shader */ 10496 gl.compileShader(so_id); 10497 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 10498 10499 /* Has the compilation succeeded as expected? */ 10500 glw::GLint compile_status = GL_FALSE; 10501 10502 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); 10503 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 10504 10505 if (compile_status == GL_FALSE) 10506 { 10507 /* What is the current stage's name? */ 10508 if (so_id == m_cs_id) 10509 { 10510 stage_body = test_case.cs_shader_body.c_str(); 10511 stage_name = "Compute shader"; 10512 } 10513 else if (so_id == m_fs_id) 10514 { 10515 stage_body = test_case.fs_shader_body.c_str(); 10516 stage_name = "Fragment shader"; 10517 } 10518 else if (so_id == m_gs_id) 10519 { 10520 stage_body = test_case.gs_shader_body.c_str(); 10521 stage_name = "Geometry shader"; 10522 } 10523 else if (so_id == m_tc_id) 10524 { 10525 stage_body = test_case.tc_shader_body.c_str(); 10526 stage_name = "Tessellation control shader"; 10527 } 10528 else if (so_id == m_te_id) 10529 { 10530 stage_body = test_case.te_shader_body.c_str(); 10531 stage_name = "Tessellation evaluation shader"; 10532 } 10533 else if (so_id == m_vs_id) 10534 { 10535 stage_body = test_case.vs_shader_body.c_str(); 10536 stage_name = "Vertex shader"; 10537 } 10538 else 10539 { 10540 /* Doesn't make much sense to throw exceptions here so.. */ 10541 stage_body = ""; 10542 stage_name = "[?]"; 10543 } 10544 10545 /* This shader should have never failed to compile! */ 10546 m_testCtx.getLog() << tcu::TestLog::Message << stage_name 10547 << " has not compiled successfully, even though the shader is valid." 10548 " Following is shader's body:\n" 10549 << stage_body << tcu::TestLog::EndMessage; 10550 10551 result = false; 10552 } 10553 } /* for (all shader objects) */ 10554 10555 return result; 10556 } 10557 10558 /** Retrieves all argument lists that can be used to initialize a variable of user-specified 10559 * type. 10560 * 10561 * @param variable_type Variable type to return valid argument lists for. 10562 **/ 10563 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType( 10564 const Utils::_variable_type& variable_type) 10565 { 10566 const Utils::_variable_type matrix_types[] = { 10567 Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4, 10568 Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4, 10569 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3, 10570 }; 10571 const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2, 10572 Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 }; 10573 const unsigned int n_matrix_types = sizeof(matrix_types) / sizeof(matrix_types[0]); 10574 const unsigned int n_scalar_types = sizeof(scalar_types) / sizeof(scalar_types[0]); 10575 const int n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type); 10576 10577 /* Construct the argument list tree root. Each node carries a counter that tells how many components 10578 * have already been assigned. Nodes that eat up all components are considered leaves and do not have 10579 * any children. Otherwise, each node is assigned as many children, as there are types that could be 10580 * used to define a subsequent argument, and its counter is increased by the amount of components 10581 * described by the type. 10582 */ 10583 _argument_list_tree_node root; 10584 10585 root.n_components_used = 0; 10586 root.parent = NULL; 10587 root.type = variable_type; 10588 10589 /* Fill till all leaves use up all available components */ 10590 _argument_list_tree_node_queue nodes_queue; 10591 10592 nodes_queue.push(&root); 10593 10594 do 10595 { 10596 /* Pop the first item in the queue */ 10597 _argument_list_tree_node* current_node_ptr = nodes_queue.front(); 10598 nodes_queue.pop(); 10599 10600 /* Matrix variable types can be defined by a combination of non-matrix variable types OR 10601 * a single matrix variable type. 10602 * 10603 * Let's handle the latter case first. 10604 */ 10605 const int n_components_remaining = n_total_components - current_node_ptr->n_components_used; 10606 10607 if (Utils::isMatrixVariableType(current_node_ptr->type)) 10608 { 10609 /* Iterate through all known matrix types. All the types can be used 10610 * as a constructor, assuming only one value is used to define new matrix's 10611 * contents. */ 10612 for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type) 10613 { 10614 Utils::_variable_type new_argument_type = matrix_types[n_matrix_type]; 10615 10616 /* Construct a new child node. Since GLSL spec clearly states we must not use more 10617 * than one constructor argument if the only argument is a matrix type, mark the node 10618 * as if it defined all available components. 10619 */ 10620 _argument_list_tree_node* new_subnode = new _argument_list_tree_node; 10621 10622 new_subnode->n_components_used = n_total_components; 10623 new_subnode->parent = current_node_ptr; 10624 new_subnode->type = new_argument_type; 10625 10626 /* Add the descriptor to node list but do not add it to the queue. This would be 10627 * a redundant operation, since no new children nodes would have been assigned to 10628 * this node anyway. 10629 */ 10630 current_node_ptr->children.push_back(new_subnode); 10631 } /* for (all matrix types) */ 10632 } /* if (current node's type is a matrix) */ 10633 10634 /* Now for a combination of non-matrix variable types.. */ 10635 if (!Utils::isMatrixVariableType(current_node_ptr->type)) 10636 { 10637 /* Iterate through all known scalar types */ 10638 for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type) 10639 { 10640 Utils::_variable_type new_argument_type = scalar_types[n_scalar_type]; 10641 const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type); 10642 10643 /* Only use the scalar type if we don't exceed the amount of components we can define 10644 * for requested type. 10645 */ 10646 if (n_new_argument_components <= n_components_remaining) 10647 { 10648 /* Form new node descriptor */ 10649 _argument_list_tree_node* new_subnode = new _argument_list_tree_node; 10650 10651 new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used; 10652 new_subnode->parent = current_node_ptr; 10653 new_subnode->type = new_argument_type; 10654 10655 current_node_ptr->children.push_back(new_subnode); 10656 nodes_queue.push(new_subnode); 10657 } 10658 } /* for (all scalar types) */ 10659 } /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */ 10660 } while (nodes_queue.size() > 0); 10661 10662 /* To construct the argument lists, traverse the tree. Each path from root to child 10663 * gives us a single argument list. 10664 * 10665 * First, identify leaf nodes. 10666 */ 10667 _argument_list_tree_nodes leaf_nodes; 10668 10669 nodes_queue.push(&root); 10670 10671 do 10672 { 10673 _argument_list_tree_node* current_node_ptr = nodes_queue.front(); 10674 nodes_queue.pop(); 10675 10676 if (current_node_ptr->children.size() == 0) 10677 { 10678 /* This is a leaf node !*/ 10679 leaf_nodes.push_back(current_node_ptr); 10680 } 10681 else 10682 { 10683 /* Throw all children nodes to the queue */ 10684 const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size(); 10685 10686 for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node) 10687 { 10688 nodes_queue.push(current_node_ptr->children[n_children_node]); 10689 } /* for (all children nodes) */ 10690 } 10691 } while (nodes_queue.size() > 0); 10692 10693 /* For all leaf nodes, move up the tree and construct the argument lists. */ 10694 const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size(); 10695 _argument_lists result; 10696 10697 for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node) 10698 { 10699 _argument_list argument_list; 10700 _argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node]; 10701 10702 do 10703 { 10704 if (current_node_ptr != &root) 10705 { 10706 if (argument_list.size() == 0) 10707 { 10708 argument_list.push_back(current_node_ptr->type); 10709 } 10710 else 10711 { 10712 argument_list.insert(argument_list.begin(), current_node_ptr->type); 10713 } 10714 } 10715 10716 current_node_ptr = current_node_ptr->parent; 10717 } while (current_node_ptr != NULL); 10718 10719 result.push_back(argument_list); 10720 } /* for (all leaf nodes) */ 10721 10722 return result; 10723 } 10724 10725 /** Retrieves body of a compute shader that should be used for the purpose of 10726 * user-specified test case. 10727 * 10728 * @param test_case Test case descriptor to use. 10729 * 10730 * @return Requested string. 10731 **/ 10732 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case) 10733 { 10734 std::stringstream result_sstream; 10735 10736 /* Form the body */ 10737 result_sstream << "#version 420\n" 10738 "#extension GL_ARB_compute_shader : require\n" 10739 "\n" 10740 "layout(local_size_x = 1) in;\n" 10741 "\n" 10742 "void main()\n" 10743 "{\n" 10744 << getGeneralBody(test_case) << "}\n"; 10745 10746 /* Return the body */ 10747 return result_sstream.str(); 10748 } 10749 10750 /** Retrieves body of a fragment shader that should be used for the purpose of 10751 * user-specified test case. 10752 * 10753 * @param test_case Test case descriptor to use. 10754 * 10755 * @return Requested string. 10756 **/ 10757 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case) 10758 { 10759 std::stringstream result_sstream; 10760 10761 /* Form the body */ 10762 result_sstream << "#version 420\n" 10763 "\n" 10764 "void main()\n" 10765 "{\n" 10766 << getGeneralBody(test_case) << "}\n" 10767 "\n"; 10768 10769 /* Return the body */ 10770 return result_sstream.str(); 10771 } 10772 10773 /** Returns a GLSL line that defines and initializes a variable as described by 10774 * user-specified test case descriptor. 10775 * 10776 * @param test_case Test case descriptor to use for the query. 10777 * 10778 * @return As per description 10779 **/ 10780 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case) 10781 { 10782 std::stringstream result_sstream; 10783 10784 /* Form the body */ 10785 std::string variable_type_string = Utils::getVariableTypeString(test_case.type); 10786 10787 result_sstream << variable_type_string << " src = " << variable_type_string << "("; 10788 10789 for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin(); 10790 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++) 10791 { 10792 const Utils::_variable_type argument_variable_type = *argument_list_iterator; 10793 std::string argument_variable_type_string = Utils::getVariableTypeString(argument_variable_type); 10794 const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type); 10795 10796 if (argument_list_iterator != test_case.argument_list.begin()) 10797 { 10798 result_sstream << ", "; 10799 } 10800 10801 result_sstream << argument_variable_type_string << "("; 10802 10803 for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component) 10804 { 10805 result_sstream << (double)(n_component + 1); 10806 10807 if (n_component != (argument_n_components - 1)) 10808 { 10809 result_sstream << ", "; 10810 } 10811 } /* for (all argument components) */ 10812 10813 result_sstream << ")"; 10814 } /* for (all arguments) */ 10815 10816 result_sstream << ");\n"; 10817 10818 return result_sstream.str(); 10819 } 10820 10821 /** Retrieves body of a geometry shader that should be used for the purpose of 10822 * user-specified test case. 10823 * 10824 * @param test_case Test case descriptor to use. 10825 * 10826 * @return Requested string. 10827 **/ 10828 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case) 10829 { 10830 std::stringstream result_sstream; 10831 10832 /* Form the body */ 10833 result_sstream << "#version 420\n" 10834 "\n" 10835 "layout(points) in;\n" 10836 "layout(max_vertices=1, points) out;\n" 10837 "\n" 10838 "void main()\n" 10839 "{\n" 10840 << getGeneralBody(test_case) << "}\n" 10841 "\n"; 10842 10843 /* We're done! */ 10844 return result_sstream.str(); 10845 } 10846 10847 /** Retrieves body of a tesellation control shader that should be used for the purpose of 10848 * user-specified test case. 10849 * 10850 * @param test_case Test case descriptor to use. 10851 * 10852 * @return Requested string. 10853 **/ 10854 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case) 10855 { 10856 std::stringstream result_sstream; 10857 10858 /* Form the body */ 10859 result_sstream << "#version 420\n" 10860 "\n" 10861 "layout(vertices=4) out;\n" 10862 "\n" 10863 "void main()\n" 10864 "{\n" 10865 << getGeneralBody(test_case) << "}\n" 10866 "\n"; 10867 10868 /* Return the body */ 10869 return result_sstream.str(); 10870 } 10871 10872 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of 10873 * user-specified test case. 10874 * 10875 * @param test_case Test case descriptor to use. 10876 * 10877 * @return Requested string. 10878 **/ 10879 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case) 10880 { 10881 std::stringstream result_sstream; 10882 10883 /* Form the body */ 10884 result_sstream << "#version 420\n" 10885 "\n" 10886 "layout(isolines) in;\n" 10887 "\n" 10888 "void main()\n" 10889 "{\n" 10890 << getGeneralBody(test_case) << "}\n" 10891 "\n"; 10892 10893 /* Return the body */ 10894 return result_sstream.str(); 10895 } 10896 10897 /** Retrieves body of a vertex shader that should be used for the purpose of 10898 * user-specified test case. 10899 * 10900 * @param test_case Test case descriptor to use. 10901 * 10902 * @return Requested string. 10903 **/ 10904 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case) 10905 { 10906 std::stringstream result_sstream; 10907 10908 /* Form the body */ 10909 result_sstream << "#version 420\n" 10910 "\n" 10911 "void main()\n" 10912 "{\n" 10913 << getGeneralBody(test_case) << "}\n" 10914 "\n"; 10915 10916 return result_sstream.str(); 10917 } 10918 10919 /** Initializes shader objects required to run the test. */ 10920 void GPUShaderFP64Test8::initTest() 10921 { 10922 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10923 10924 /* Generate shader objects */ 10925 10926 /* Compute shader support and GL 4.2 required */ 10927 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) && 10928 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */))) 10929 { 10930 m_cs_id = gl.createShader(GL_COMPUTE_SHADER); 10931 } 10932 10933 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 10934 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 10935 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER); 10936 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER); 10937 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 10938 10939 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 10940 } 10941 10942 /** Assigns shader bodies to all shader objects that will be used for a single iteration. 10943 * 10944 * @param test_case Test case descriptor to generate the shader bodies for. 10945 **/ 10946 void GPUShaderFP64Test8::initIteration(_test_case& test_case) 10947 { 10948 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 10949 10950 test_case.cs_shader_body = getComputeShaderBody(test_case); 10951 test_case.fs_shader_body = getFragmentShaderBody(test_case); 10952 test_case.gs_shader_body = getGeometryShaderBody(test_case); 10953 test_case.tc_shader_body = getTessellationControlShaderBody(test_case); 10954 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case); 10955 test_case.vs_shader_body = getVertexShaderBody(test_case); 10956 10957 /* Assign the bodies to relevant shaders */ 10958 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str(); 10959 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str(); 10960 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str(); 10961 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str(); 10962 const char* te_body_raw_ptr = test_case.te_shader_body.c_str(); 10963 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str(); 10964 10965 /* m_cs_id is initialized only if compute_shader is supported */ 10966 if (0 != m_cs_id) 10967 { 10968 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */); 10969 } 10970 10971 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */); 10972 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */); 10973 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */); 10974 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */); 10975 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */); 10976 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed."); 10977 } 10978 10979 /** Executes test iteration. 10980 * 10981 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 10982 */ 10983 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate() 10984 { 10985 /* Do not execute the test if GL_ARB_texture_view is not supported */ 10986 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 10987 { 10988 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported."); 10989 } 10990 10991 /* Initialize GL objects needed to run the tests */ 10992 initTest(); 10993 10994 /* Build iteration array to run the tests in an automated manner */ 10995 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, 10996 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, 10997 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4, 10998 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, 10999 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE, 11000 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3, 11001 Utils::VARIABLE_TYPE_DVEC4 }; 11002 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]); 11003 11004 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type) 11005 { 11006 const Utils::_variable_type variable_type = variable_types[n_variable_type]; 11007 11008 /* Construct a set of argument lists valid for the variable type considered */ 11009 _argument_lists argument_lists = getArgumentListsForVariableType(variable_type); 11010 11011 for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin(); 11012 argument_list_iterator != argument_lists.end(); argument_list_iterator++) 11013 { 11014 /* Constructor thwe test case descriptor */ 11015 _test_case test_case; 11016 11017 test_case.argument_list = *argument_list_iterator; 11018 test_case.type = variable_type; 11019 11020 /* Initialize a program object we will use to perform the casting */ 11021 initIteration(test_case); 11022 11023 /* See if the shader compiles. */ 11024 m_has_test_passed &= executeIteration(test_case); 11025 } /* for (all argument lists) */ 11026 } /* for (all variable types) */ 11027 11028 /* We're done */ 11029 if (m_has_test_passed) 11030 { 11031 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11032 } 11033 else 11034 { 11035 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11036 } 11037 11038 return STOP; 11039 } 11040 11041 /** Constructor. 11042 * 11043 * @param context Rendering context. 11044 * 11045 **/ 11046 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context) 11047 : TestCase(context, "operators", "Verifies that general and relational operators work " 11048 "correctly when used against double-precision floating-" 11049 "point types.") 11050 , m_has_test_passed(true) 11051 , m_po_id(0) 11052 , m_xfb_bo_id(0) 11053 , m_vao_id(0) 11054 , m_vs_id(0) 11055 { 11056 /* Left blank intentionally */ 11057 } 11058 11059 /** Deinitializes all ES objects that may have been created during 11060 * test execution. 11061 **/ 11062 void GPUShaderFP64Test9::deinit() 11063 { 11064 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11065 11066 if (m_po_id != 0) 11067 { 11068 gl.deleteProgram(m_po_id); 11069 11070 m_po_id = 0; 11071 } 11072 11073 if (m_xfb_bo_id != 0) 11074 { 11075 gl.deleteBuffers(1, &m_xfb_bo_id); 11076 11077 m_xfb_bo_id = 0; 11078 } 11079 11080 if (m_vao_id != 0) 11081 { 11082 gl.deleteVertexArrays(1, &m_vao_id); 11083 11084 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed."); 11085 } 11086 11087 if (m_vs_id != 0) 11088 { 11089 gl.deleteShader(m_vs_id); 11090 11091 m_vs_id = 0; 11092 } 11093 } 11094 11095 /** Executes a single test iteration using user-specified test case properties. 11096 * 11097 * @param test_case Test case descriptor. 11098 * 11099 * @return true if the pass was successful, false if the test should fail. 11100 **/ 11101 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case) 11102 { 11103 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11104 bool result = true; 11105 11106 /* Activate the test program object */ 11107 gl.useProgram(m_po_id); 11108 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 11109 11110 /* Draw a single point with XFB enabled */ 11111 gl.beginTransformFeedback(GL_POINTS); 11112 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 11113 { 11114 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 11115 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 11116 } 11117 gl.endTransformFeedback(); 11118 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 11119 11120 /* Map the XFB BO into process space */ 11121 const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 11122 11123 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed."); 11124 11125 result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr); 11126 11127 /* Unmap the BO */ 11128 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 11129 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 11130 11131 return result; 11132 } 11133 11134 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result 11135 * under user-specified location. 11136 * 11137 * @param matrix_a_type Type of the l-side matrix. 11138 * @param matrix_a_data Row-ordered data of l-side matrix. 11139 * @param matrix_b_type Type of the r-side matrix. 11140 * @param matrix_b_data Row-ordered data of r-side matrix. 11141 * @param out_result_ptr Deref to be used to store the multiplication result. 11142 **/ 11143 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type, 11144 const std::vector<double>& matrix_a_data, 11145 const Utils::_variable_type& matrix_b_type, 11146 const std::vector<double>& matrix_b_data, double* out_result_ptr) 11147 { 11148 (void)matrix_b_type; 11149 using namespace tcu; 11150 /* To keep the code maintainable, we only consider cases relevant for this test */ 11151 switch (matrix_a_type) 11152 { 11153 case Utils::VARIABLE_TYPE_DMAT2: 11154 { 11155 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2); 11156 11157 tcu::Matrix2d matrix_a(&matrix_a_data[0]); 11158 tcu::Matrix2d matrix_b(&matrix_b_data[0]); 11159 tcu::Matrix2d result; 11160 11161 matrix_a = transpose(matrix_a); 11162 matrix_b = transpose(matrix_b); 11163 result = matrix_a * matrix_b; 11164 11165 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2); 11166 break; 11167 } 11168 11169 case Utils::VARIABLE_TYPE_DMAT2X3: 11170 { 11171 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2); 11172 11173 tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]); 11174 tcu::Matrix<double, 3, 2> matrix_a_transposed; 11175 tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]); 11176 tcu::Matrix<double, 2, 3> matrix_b_transposed; 11177 tcu::Matrix<double, 3, 3> result; 11178 11179 matrix_a_transposed = transpose(matrix_a); 11180 matrix_b_transposed = transpose(matrix_b); 11181 result = matrix_a_transposed * matrix_b_transposed; 11182 11183 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3); 11184 break; 11185 } 11186 11187 case Utils::VARIABLE_TYPE_DMAT2X4: 11188 { 11189 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2); 11190 11191 tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]); 11192 tcu::Matrix<double, 4, 2> matrix_a_transposed; 11193 tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]); 11194 tcu::Matrix<double, 2, 4> matrix_b_transposed; 11195 tcu::Matrix<double, 4, 4> result; 11196 11197 matrix_a_transposed = transpose(matrix_a); 11198 matrix_b_transposed = transpose(matrix_b); 11199 result = matrix_a_transposed * matrix_b_transposed; 11200 11201 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4); 11202 break; 11203 } 11204 11205 case Utils::VARIABLE_TYPE_DMAT3: 11206 { 11207 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3); 11208 11209 tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]); 11210 tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]); 11211 tcu::Matrix<double, 3, 3> result; 11212 11213 matrix_a = transpose(matrix_a); 11214 matrix_b = transpose(matrix_b); 11215 result = matrix_a * matrix_b; 11216 11217 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3); 11218 break; 11219 } 11220 11221 case Utils::VARIABLE_TYPE_DMAT3X2: 11222 { 11223 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3); 11224 11225 tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]); 11226 tcu::Matrix<double, 2, 3> matrix_a_transposed; 11227 tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]); 11228 tcu::Matrix<double, 3, 2> matrix_b_transposed; 11229 tcu::Matrix<double, 2, 2> result; 11230 11231 matrix_a_transposed = transpose(matrix_a); 11232 matrix_b_transposed = transpose(matrix_b); 11233 result = matrix_a_transposed * matrix_b_transposed; 11234 11235 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2); 11236 break; 11237 } 11238 11239 case Utils::VARIABLE_TYPE_DMAT3X4: 11240 { 11241 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3); 11242 11243 tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]); 11244 tcu::Matrix<double, 4, 3> matrix_a_transposed; 11245 tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]); 11246 tcu::Matrix<double, 3, 4> matrix_b_transposed; 11247 tcu::Matrix<double, 4, 4> result; 11248 11249 matrix_a_transposed = transpose(matrix_a); 11250 matrix_b_transposed = transpose(matrix_b); 11251 result = matrix_a_transposed * matrix_b_transposed; 11252 11253 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4); 11254 break; 11255 } 11256 11257 case Utils::VARIABLE_TYPE_DMAT4: 11258 { 11259 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4); 11260 11261 tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]); 11262 tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]); 11263 tcu::Matrix<double, 4, 4> result; 11264 11265 matrix_a = transpose(matrix_a); 11266 matrix_b = transpose(matrix_b); 11267 result = matrix_a * matrix_b; 11268 11269 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4); 11270 break; 11271 } 11272 11273 case Utils::VARIABLE_TYPE_DMAT4X2: 11274 { 11275 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4); 11276 11277 tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]); 11278 tcu::Matrix<double, 2, 4> matrix_a_transposed; 11279 tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]); 11280 tcu::Matrix<double, 4, 2> matrix_b_transposed; 11281 tcu::Matrix<double, 2, 2> result; 11282 11283 matrix_a_transposed = transpose(matrix_a); 11284 matrix_b_transposed = transpose(matrix_b); 11285 result = matrix_a_transposed * matrix_b_transposed; 11286 11287 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2); 11288 break; 11289 } 11290 11291 case Utils::VARIABLE_TYPE_DMAT4X3: 11292 { 11293 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4); 11294 11295 tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]); 11296 tcu::Matrix<double, 3, 4> matrix_a_transposed; 11297 tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]); 11298 tcu::Matrix<double, 4, 3> matrix_b_transposed; 11299 tcu::Matrix<double, 3, 3> result; 11300 11301 matrix_a_transposed = transpose(matrix_a); 11302 matrix_b_transposed = transpose(matrix_b); 11303 result = matrix_a_transposed * matrix_b_transposed; 11304 11305 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3); 11306 break; 11307 } 11308 11309 default: 11310 { 11311 TCU_FAIL("Unrecognized matrix A type"); 11312 } 11313 } /* switch (matrix_a_type) */ 11314 } 11315 11316 /** Returns GLSL operator representation of the user-specified operation. 11317 * 11318 * @param operation_type Internal operation type to retrieve the operator for. 11319 * 11320 * @return As per description. 11321 **/ 11322 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type) 11323 { 11324 const char* result = NULL; 11325 11326 switch (operation_type) 11327 { 11328 case OPERATION_TYPE_ADDITION: 11329 result = "+"; 11330 break; 11331 case OPERATION_TYPE_DIVISION: 11332 result = "/"; 11333 break; 11334 case OPERATION_TYPE_MULTIPLICATION: 11335 result = "*"; 11336 break; 11337 case OPERATION_TYPE_SUBTRACTION: 11338 result = "-"; 11339 break; 11340 11341 case OPERATION_TYPE_PRE_DECREMENTATION: 11342 case OPERATION_TYPE_POST_DECREMENTATION: 11343 { 11344 result = "--"; 11345 11346 break; 11347 } 11348 11349 case OPERATION_TYPE_PRE_INCREMENTATION: 11350 case OPERATION_TYPE_POST_INCREMENTATION: 11351 { 11352 result = "++"; 11353 11354 break; 11355 } 11356 11357 default: 11358 { 11359 TCU_FAIL("Unrecognized operation type"); 11360 } 11361 } /* switch(operation_type) */ 11362 11363 return result; 11364 } 11365 11366 /** Returns a string representing user-specified operation type. 11367 * 11368 * @param operation_type Operation type to return the literal for. 11369 * 11370 * @return Requested string. 11371 **/ 11372 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type) 11373 { 11374 std::string result = "[?]"; 11375 11376 switch (operation_type) 11377 { 11378 case OPERATION_TYPE_ADDITION: 11379 result = "addition"; 11380 break; 11381 case OPERATION_TYPE_DIVISION: 11382 result = "division"; 11383 break; 11384 case OPERATION_TYPE_MULTIPLICATION: 11385 result = "multiplication"; 11386 break; 11387 case OPERATION_TYPE_SUBTRACTION: 11388 result = "subtraction"; 11389 break; 11390 case OPERATION_TYPE_PRE_DECREMENTATION: 11391 result = "pre-decrementation"; 11392 break; 11393 case OPERATION_TYPE_PRE_INCREMENTATION: 11394 result = "pre-incrementation"; 11395 break; 11396 case OPERATION_TYPE_POST_DECREMENTATION: 11397 result = "post-decrementation"; 11398 break; 11399 case OPERATION_TYPE_POST_INCREMENTATION: 11400 result = "post-incrementation"; 11401 break; 11402 11403 default: 11404 { 11405 TCU_FAIL("Unrecognized operation type"); 11406 } 11407 } 11408 11409 return result; 11410 } 11411 11412 /** Returns body of a vertex shader that should be used for user-specified test case 11413 * descriptor. 11414 * 11415 * @param test_case Test case descriptor. 11416 * 11417 * @return Requested GLSL shader body. 11418 **/ 11419 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case) 11420 { 11421 std::stringstream result_sstream; 11422 std::string result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type); 11423 std::string variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type); 11424 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type); 11425 const unsigned int n_variable_components = Utils::getNumberOfComponentsForVariableType(test_case.variable_type); 11426 11427 /* If we are to multiply matrices, we will need to use a different type 11428 * for the result variable if either of the matrices is not square. 11429 */ 11430 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION && 11431 Utils::isMatrixVariableType(test_case.variable_type)) 11432 { 11433 Utils::_variable_type result_variable_type; 11434 Utils::_variable_type transposed_matrix_variable_type = 11435 Utils::getTransposedMatrixVariableType(test_case.variable_type); 11436 11437 result_variable_type = 11438 Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type); 11439 result_variable_type_string = Utils::getVariableTypeString(result_variable_type); 11440 11441 test_case.result_variable_type = result_variable_type; 11442 } 11443 11444 /* Form the pre-amble */ 11445 result_sstream << "#version 400\n" 11446 "\n" 11447 11448 /* Add output variables */ 11449 "out " 11450 << result_variable_type_string << " result;\n" 11451 "out ivec2 result_lt;\n" 11452 "out ivec2 result_lte;\n" 11453 "out ivec2 result_gt;\n" 11454 "out ivec2 result_gte;\n" 11455 "void main()\n" 11456 "{\n"; 11457 11458 /* Form reference values */ 11459 result_sstream << variable_type_string << " reference1 = " << variable_type_string << "("; 11460 11461 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component) 11462 { 11463 result_sstream << (n_variable_component + 1); 11464 11465 if (n_variable_component != (n_variable_components - 1)) 11466 { 11467 result_sstream << ", "; 11468 } 11469 } /* for (all variable components) */ 11470 11471 result_sstream << ");\n"; 11472 11473 for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */ 11474 ++n_ref2_case) 11475 { 11476 Utils::_variable_type compatible_variable_type = test_case.variable_type; 11477 11478 if (Utils::isMatrixVariableType(compatible_variable_type) && 11479 test_case.operation_type == OPERATION_TYPE_MULTIPLICATION) 11480 { 11481 compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type); 11482 } 11483 11484 std::string ref2_variable_type_fp_string = 11485 Utils::getFPVariableTypeStringForVariableType(compatible_variable_type); 11486 std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type); 11487 std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string; 11488 std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2"; 11489 11490 result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "("; 11491 11492 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; 11493 ++n_variable_component) 11494 { 11495 result_sstream << (n_variable_components - (n_variable_component + 1)); 11496 11497 if (n_variable_component != (n_variable_components - 1)) 11498 { 11499 result_sstream << ", "; 11500 } 11501 } /* for (all variable components) */ 11502 11503 result_sstream << ");\n"; 11504 } /* for (both reference2 declarations) */ 11505 11506 /* Add actual body */ 11507 result_sstream << "\n" 11508 "result = "; 11509 11510 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION || 11511 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION) 11512 { 11513 result_sstream << getOperatorForOperationType(test_case.operation_type); 11514 } 11515 11516 result_sstream << "reference1 "; 11517 11518 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION || 11519 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION || 11520 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION || 11521 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION) 11522 { 11523 if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION || 11524 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION) 11525 { 11526 result_sstream << getOperatorForOperationType(test_case.operation_type); 11527 } 11528 } 11529 else 11530 { 11531 result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2"; 11532 } 11533 11534 result_sstream << ";\n"; 11535 11536 if (Utils::isScalarVariableType(test_case.variable_type)) 11537 { 11538 result_sstream << "result_lt [0] = (reference1 < reference2) ? 1 : 0;\n" 11539 "result_lt [1] = (reference1 < reference2f) ? 1 : 0;\n" 11540 "result_lte[0] = (reference1 <= reference2) ? 1 : 0;\n" 11541 "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n" 11542 "result_gt [0] = (reference1 > reference2) ? 1 : 0;\n" 11543 "result_gt [1] = (reference1 > reference2f) ? 1 : 0;\n" 11544 "result_gte[0] = (reference1 >= reference2) ? 1 : 0;\n" 11545 "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n"; 11546 } 11547 else 11548 { 11549 result_sstream << "result_lt [0] = 1;\n" 11550 "result_lt [1] = 1;\n" 11551 "result_lte[0] = 1;\n" 11552 "result_lte[1] = 1;\n" 11553 "result_gt [0] = 1;\n" 11554 "result_gt [1] = 1;\n" 11555 "result_gte[0] = 1;\n" 11556 "result_gte[1] = 1;\n"; 11557 } 11558 11559 result_sstream << "}\n"; 11560 11561 /* All done */ 11562 return result_sstream.str(); 11563 } 11564 11565 /** Initializes all GL objects required to run the test. 11566 * 11567 * This function can throw a TestError exception if the implementation misbehaves. 11568 */ 11569 void GPUShaderFP64Test9::initTest() 11570 { 11571 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11572 11573 /* Create program & vertex shader objects */ 11574 m_po_id = gl.createProgram(); 11575 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 11576 11577 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed."); 11578 11579 /* Attach the shader to the program */ 11580 gl.attachShader(m_po_id, m_vs_id); 11581 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 11582 11583 /* Set up a buffer object */ 11584 gl.genBuffers(1, &m_xfb_bo_id); 11585 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 11586 11587 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id); 11588 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 11589 11590 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id); 11591 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 11592 11593 /* Set up a vertex array object */ 11594 gl.genVertexArrays(1, &m_vao_id); 11595 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 11596 11597 gl.bindVertexArray(m_vao_id); 11598 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 11599 } 11600 11601 /** Initializes all GL objects required to run an iteration described by 11602 * user-specified test case descriptor. 11603 * 11604 * @param test_case Test case descriptor to use for the initialization. 11605 **/ 11606 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case) 11607 { 11608 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 11609 std::string vs_body = getVertexShaderBody(test_case); 11610 const char* vs_body_raw_ptr = vs_body.c_str(); 11611 11612 /* Store the shader's body */ 11613 test_case.vs_body = vs_body; 11614 11615 /* Try to compile the shader */ 11616 glw::GLint compile_status = GL_FALSE; 11617 11618 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */); 11619 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 11620 11621 gl.compileShader(m_vs_id); 11622 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 11623 11624 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); 11625 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 11626 11627 if (compile_status != GL_TRUE) 11628 { 11629 TCU_FAIL("Test shader compilation failed."); 11630 } 11631 11632 /* Configure XFB */ 11633 const char* xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" }; 11634 const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]); 11635 11636 gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS); 11637 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed."); 11638 11639 /* Try to link the program */ 11640 glw::GLint link_status = GL_FALSE; 11641 11642 gl.linkProgram(m_po_id); 11643 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 11644 11645 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 11646 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 11647 11648 if (link_status != GL_TRUE) 11649 { 11650 TCU_FAIL("Test program linking failure"); 11651 } 11652 11653 /* Set up XFB BO data storage */ 11654 const unsigned int result_variable_size = static_cast<unsigned int>( 11655 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double)); 11656 const unsigned int xfb_bo_size = static_cast<unsigned int>( 11657 result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */ 11658 11659 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW); 11660 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 11661 } 11662 11663 /** Executes test iteration. 11664 * 11665 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 11666 */ 11667 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate() 11668 { 11669 /* Do not execute the test if GL_ARB_texture_view is not supported */ 11670 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 11671 { 11672 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported."); 11673 } 11674 11675 /* Initialize all ES objects required to run all the checks */ 11676 initTest(); 11677 11678 /* Iterate through all variable types we want to test */ 11679 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, 11680 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, 11681 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4, 11682 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, 11683 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE, 11684 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3, 11685 Utils::VARIABLE_TYPE_DVEC4 }; 11686 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]); 11687 11688 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type) 11689 { 11690 /* Iterate through all operation types we want to check */ 11691 for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type) 11692 { 11693 _operation_type operation_type = (_operation_type)n_operation_type; 11694 const Utils::_variable_type& variable_type = variable_types[n_variable_type]; 11695 11696 /* Construct test case descriptor */ 11697 _test_case test_case; 11698 11699 test_case.operation_type = operation_type; 11700 test_case.result_variable_type = variable_type; 11701 test_case.variable_type = variable_type; 11702 11703 /* Run the iteration */ 11704 initTestIteration(test_case); 11705 11706 m_has_test_passed &= executeTestIteration(test_case); 11707 } /* for (all operation types) */ 11708 } /* for (all variable types) */ 11709 11710 /* All done. */ 11711 if (m_has_test_passed) 11712 { 11713 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 11714 } 11715 else 11716 { 11717 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 11718 } 11719 11720 return STOP; 11721 } 11722 11723 /** Verifies data XFBed out by the draw call for user-specified test case 11724 * descriptor. 11725 * 11726 * @param test_case Test case descriptor 11727 * @param xfb_data Buffer holding the data XFBed out during the draw call. 11728 * Must not be NULL. 11729 * 11730 * @return true if the data was found to be correct, false otherwise. 11731 **/ 11732 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data) 11733 { 11734 const double epsilon = 1e-5; 11735 const unsigned int n_result_components = 11736 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type); 11737 bool result = true; 11738 const double* xfb_data_result = (const double*)xfb_data; 11739 const int* xfb_data_result_lt = (const int*)(xfb_data_result + n_result_components); 11740 const int* xfb_data_result_lte = (const int*)xfb_data_result_lt + 2; /* cast/non-cast cases */ 11741 const int* xfb_data_result_gt = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */ 11742 const int* xfb_data_result_gte = (const int*)xfb_data_result_gt + 2; /* cast/non-cast cases */ 11743 11744 /* Prepare reference values */ 11745 int modifier; 11746 std::vector<double> reference1; 11747 std::vector<double> reference2; 11748 11749 if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION || 11750 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION) 11751 { 11752 modifier = 1; 11753 } 11754 else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION || 11755 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION) 11756 { 11757 modifier = -1; 11758 } 11759 else 11760 { 11761 modifier = 0; 11762 } 11763 11764 if (Utils::isMatrixVariableType(test_case.variable_type)) 11765 { 11766 /* Matrices may be of different sizes so we need to compute the 11767 * reference values separately for each matrix 11768 */ 11769 const Utils::_variable_type matrix_a_type = test_case.variable_type; 11770 const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type); 11771 const unsigned int n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type); 11772 const unsigned int n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type); 11773 11774 for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component) 11775 { 11776 reference1.push_back(modifier + n_component + 1); 11777 } 11778 11779 for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component) 11780 { 11781 reference2.push_back(n_matrix_b_components - (n_component + 1)); 11782 } 11783 } /* if (Utils::isMatrixVariableType(test_case.variable_type) */ 11784 else 11785 { 11786 /* Generate as many components as will be expected for the result variable */ 11787 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component) 11788 { 11789 reference1.push_back(modifier + n_result_component + 1); 11790 reference2.push_back(n_result_components - (n_result_component + 1)); 11791 } 11792 } 11793 11794 /* Verify the result value(s) */ 11795 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION && 11796 Utils::isMatrixVariableType(test_case.variable_type)) 11797 { 11798 /* Matrix multiplication */ 11799 double expected_result_data[4 * 4]; 11800 Utils::_variable_type matrix_a_type = test_case.variable_type; 11801 Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type); 11802 11803 getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data); 11804 11805 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component) 11806 { 11807 if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon) 11808 { 11809 std::stringstream log_sstream; 11810 11811 log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * " 11812 << Utils::getVariableTypeString(matrix_b_type) 11813 << " matrix multiplication was incorrect; expected:("; 11814 11815 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components; 11816 ++n_logged_component) 11817 { 11818 log_sstream << expected_result_data[n_logged_component]; 11819 11820 if (n_logged_component != (n_result_components - 1)) 11821 { 11822 log_sstream << ", "; 11823 } 11824 } /* for (all components to be logged) */ 11825 11826 log_sstream << "), retrieved:("; 11827 11828 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components; 11829 ++n_logged_component) 11830 { 11831 log_sstream << xfb_data_result[n_logged_component]; 11832 11833 if (n_logged_component != (n_result_components - 1)) 11834 { 11835 log_sstream << ", "; 11836 } 11837 } /* for (all components to be logged) */ 11838 11839 log_sstream << ")"; 11840 11841 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage; 11842 11843 result = false; 11844 break; 11845 } 11846 } /* for (all result components) */ 11847 } /* if (dealing with matrix multiplication) */ 11848 else 11849 { 11850 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component) 11851 { 11852 double expected_value = reference1[n_component]; 11853 11854 switch (test_case.operation_type) 11855 { 11856 case OPERATION_TYPE_ADDITION: 11857 expected_value += reference2[n_component]; 11858 break; 11859 case OPERATION_TYPE_DIVISION: 11860 expected_value /= reference2[n_component]; 11861 break; 11862 case OPERATION_TYPE_MULTIPLICATION: 11863 expected_value *= reference2[n_component]; 11864 break; 11865 case OPERATION_TYPE_SUBTRACTION: 11866 expected_value -= reference2[n_component]; 11867 break; 11868 11869 case OPERATION_TYPE_PRE_DECREMENTATION: 11870 case OPERATION_TYPE_PRE_INCREMENTATION: 11871 { 11872 /* Modifier already applied */ 11873 break; 11874 } 11875 11876 case OPERATION_TYPE_POST_DECREMENTATION: 11877 case OPERATION_TYPE_POST_INCREMENTATION: 11878 { 11879 /* Need to reverse the modification for the purpose of the following check */ 11880 expected_value -= modifier; 11881 11882 break; 11883 } 11884 11885 default: 11886 { 11887 TCU_FAIL("Unrecognized operation type"); 11888 } 11889 } /* switch (test_case.operation_type) */ 11890 11891 if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon) 11892 { 11893 std::string operation_type_string = getOperationTypeString(test_case.operation_type); 11894 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type); 11895 11896 m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type [" 11897 << variable_type_string << "]" 11898 " and operation type [" 11899 << operation_type_string << "]" 11900 " were found invalid." 11901 << tcu::TestLog::EndMessage; 11902 11903 result = false; 11904 break; 11905 } /* if (test case failed) */ 11906 } /* for (all components) */ 11907 } 11908 11909 /* Verify the comparison operation results */ 11910 if (Utils::isScalarVariableType(test_case.variable_type)) 11911 { 11912 DE_ASSERT(n_result_components == 1); 11913 11914 const bool expected_result_lt[2] = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] }; 11915 const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] }; 11916 const bool expected_result_gt[2] = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] }; 11917 const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] }; 11918 11919 if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] || 11920 (xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1]) 11921 { 11922 std::string operation_type_string = getOperationTypeString(test_case.operation_type); 11923 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type); 11924 11925 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for " 11926 "variable type [" 11927 << variable_type_string << "]" 11928 "and operation type [" 11929 << operation_type_string << "]" 11930 "was found invalid; expected:(" 11931 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:(" 11932 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")." 11933 << tcu::TestLog::EndMessage; 11934 11935 result = false; 11936 } 11937 11938 if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] || 11939 (xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1]) 11940 { 11941 std::string operation_type_string = getOperationTypeString(test_case.operation_type); 11942 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type); 11943 11944 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for " 11945 "variable type [" 11946 << variable_type_string << "]" 11947 "and operation type [" 11948 << operation_type_string << "]" 11949 "was found invalid; expected:(" 11950 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:(" 11951 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")." 11952 << tcu::TestLog::EndMessage; 11953 11954 result = false; 11955 } 11956 11957 if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] || 11958 (xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1]) 11959 { 11960 std::string operation_type_string = getOperationTypeString(test_case.operation_type); 11961 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type); 11962 11963 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for " 11964 "variable type [" 11965 << variable_type_string << "]" 11966 "and operation type [" 11967 << operation_type_string << "]" 11968 "was found invalid; expected:(" 11969 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:(" 11970 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")." 11971 << tcu::TestLog::EndMessage; 11972 11973 result = false; 11974 } 11975 11976 if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] || 11977 (xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1]) 11978 { 11979 std::string operation_type_string = getOperationTypeString(test_case.operation_type); 11980 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type); 11981 11982 m_testCtx.getLog() << tcu::TestLog::Message 11983 << "Values reported for greater-than-or-equal operator used for " 11984 "variable type [" 11985 << variable_type_string << "]" 11986 "and operation type [" 11987 << operation_type_string << "]" 11988 "was found invalid; expected:(" 11989 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:(" 11990 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")." 11991 << tcu::TestLog::EndMessage; 11992 11993 result = false; 11994 } 11995 } /* if (Utils::isScalarVariableType(test_case.variable_type) ) */ 11996 else 11997 { 11998 if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 || 11999 xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 || 12000 xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1) 12001 { 12002 std::string operation_type_string = getOperationTypeString(test_case.operation_type); 12003 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type); 12004 12005 m_testCtx.getLog() << tcu::TestLog::Message 12006 << "Invalid value was reported for matrix variable type, for which " 12007 " operator checks are not executed; variable type [" 12008 << variable_type_string << "]" 12009 "and operation type [" 12010 << operation_type_string << "]" << tcu::TestLog::EndMessage; 12011 12012 result = false; 12013 } 12014 } 12015 12016 return result; 12017 } 12018 12019 namespace TypeHelpers 12020 { 12021 /** Get base type for reference types 12022 * 12023 * @tparam T type 12024 **/ 12025 template <typename T> 12026 class referenceToType 12027 { 12028 public: 12029 typedef T result; 12030 }; 12031 12032 template <typename T> 12033 class referenceToType<const T&> 12034 { 12035 public: 12036 typedef T result; 12037 }; 12038 12039 /** Maps variable type with enumeration Utils::_variable_type 12040 * 12041 * @tparam T type 12042 **/ 12043 template <typename T> 12044 class typeInfo; 12045 12046 template <> 12047 class typeInfo<glw::GLboolean> 12048 { 12049 public: 12050 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL; 12051 }; 12052 12053 template <> 12054 class typeInfo<glw::GLdouble> 12055 { 12056 public: 12057 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE; 12058 }; 12059 12060 template <> 12061 class typeInfo<tcu::UVec2> 12062 { 12063 public: 12064 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2; 12065 }; 12066 12067 template <> 12068 class typeInfo<tcu::UVec3> 12069 { 12070 public: 12071 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3; 12072 }; 12073 12074 template <> 12075 class typeInfo<tcu::UVec4> 12076 { 12077 public: 12078 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4; 12079 }; 12080 12081 template <> 12082 class typeInfo<tcu::DVec2> 12083 { 12084 public: 12085 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2; 12086 }; 12087 12088 template <> 12089 class typeInfo<tcu::DVec3> 12090 { 12091 public: 12092 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3; 12093 }; 12094 12095 template <> 12096 class typeInfo<tcu::DVec4> 12097 { 12098 public: 12099 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4; 12100 }; 12101 12102 template <> 12103 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> > 12104 { 12105 public: 12106 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2; 12107 }; 12108 12109 template <> 12110 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> > 12111 { 12112 public: 12113 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3; 12114 }; 12115 12116 template <> 12117 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> > 12118 { 12119 public: 12120 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4; 12121 }; 12122 12123 template <> 12124 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> > 12125 { 12126 public: 12127 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3; 12128 }; 12129 12130 template <> 12131 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> > 12132 { 12133 public: 12134 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2; 12135 }; 12136 12137 template <> 12138 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> > 12139 { 12140 public: 12141 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4; 12142 }; 12143 12144 template <> 12145 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> > 12146 { 12147 public: 12148 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4; 12149 }; 12150 12151 template <> 12152 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> > 12153 { 12154 public: 12155 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2; 12156 }; 12157 12158 template <> 12159 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> > 12160 { 12161 public: 12162 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3; 12163 }; 12164 } /* TypeHelpers */ 12165 12166 /** Implementations of "math" functions required by "GPUShaderFP64Test10" 12167 * 12168 **/ 12169 namespace Math 12170 { 12171 template <typename T> 12172 static T clamp(T x, T minVal, T maxVal); 12173 12174 template <int Size> 12175 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix); 12176 12177 template <int Size> 12178 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src); 12179 12180 template <typename T> 12181 static T determinant(T val); 12182 12183 template <typename T> 12184 static T determinant(const tcu::Matrix<T, 2, 2>& mat); 12185 12186 template <typename T> 12187 static T determinant(const tcu::Matrix<T, 3, 3>& mat); 12188 12189 template <typename T> 12190 static T determinant(const tcu::Matrix<T, 4, 4>& mat); 12191 12192 template <int Size> 12193 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, 12194 glw::GLuint column, glw::GLuint row); 12195 12196 template <int Size> 12197 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left, 12198 const tcu::Vector<glw::GLdouble, Size>& right); 12199 12200 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c); 12201 12202 static glw::GLdouble fract(glw::GLdouble val); 12203 12204 template <typename T> 12205 static T frexp(T val, glw::GLint& exp); 12206 12207 template <int Size> 12208 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left, 12209 const tcu::Vector<glw::GLdouble, Size>& right); 12210 12211 template <int Size> 12212 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left, 12213 const tcu::Vector<glw::GLdouble, Size>& right); 12214 12215 template <int Size> 12216 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix); 12217 12218 static glw::GLdouble inverseSqrt(glw::GLdouble val); 12219 12220 static glw::GLuint isinf_impl(glw::GLdouble val); 12221 12222 static glw::GLuint isnan_impl(glw::GLdouble val); 12223 12224 template <typename T> 12225 static T ldexp(T val, glw::GLint exp); 12226 12227 template <int Size> 12228 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left, 12229 const tcu::Vector<glw::GLdouble, Size>& right); 12230 12231 template <int Size> 12232 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left, 12233 const tcu::Vector<glw::GLdouble, Size>& right); 12234 12235 template <typename T> 12236 static T max(T left, T right); 12237 12238 template <typename T> 12239 static T min(T left, T right); 12240 12241 template <int Size> 12242 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column, 12243 glw::GLuint row); 12244 12245 template <typename T> 12246 static T mix(T left, T right, T weight); 12247 12248 template <typename T> 12249 static T mod(T left, T right); 12250 12251 template <typename T> 12252 static T modf(T val, T& integer); 12253 12254 template <typename T> 12255 static T multiply(T left, T right); 12256 12257 template <int Size> 12258 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left, 12259 const tcu::Vector<glw::GLdouble, Size>& right); 12260 12261 template <int Cols, int Rows> 12262 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left, 12263 const tcu::Vector<glw::GLdouble, Cols>& right); 12264 12265 static glw::GLdouble packDouble2x32(const tcu::UVec2& in); 12266 12267 template <typename T> 12268 static T round(T t); 12269 12270 template <typename T> 12271 static T roundEven(T t); 12272 12273 template <typename T> 12274 static T sign(T t); 12275 12276 template <typename T> 12277 static T smoothStep(T e0, T e1, T val); 12278 12279 template <typename T> 12280 static T step(T edge, T val); 12281 12282 template <typename T, int Rows, int Cols> 12283 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix); 12284 12285 template <typename T> 12286 static T trunc(T t); 12287 12288 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val); 12289 12290 template <typename T> 12291 static T clamp(T x, T minVal, T maxVal) 12292 { 12293 return min(max(x, minVal), maxVal); 12294 } 12295 12296 template <int Size> 12297 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix) 12298 { 12299 tcu::Matrix<glw::GLdouble, Size, Size> result; 12300 12301 for (glw::GLuint c = 0; c < Size; ++c) 12302 { 12303 for (glw::GLuint r = 0; r < Size; ++r) 12304 { 12305 const glw::GLdouble minor_value = minor_impl(matrix, c, r); 12306 12307 result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value; 12308 } 12309 } 12310 12311 return result; 12312 } 12313 12314 template <int Size> 12315 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src) 12316 { 12317 tcu::Vector<glw::GLuint, Size> result; 12318 12319 for (glw::GLint i = 0; i < Size; ++i) 12320 { 12321 if (GL_FALSE != src[i]) 12322 { 12323 result[i] = 1; 12324 } 12325 else 12326 { 12327 result[i] = 0; 12328 } 12329 } 12330 12331 return result; 12332 } 12333 12334 template <typename T> 12335 static T det2(T _00, T _10, T _01, T _11) 12336 { 12337 return _00 * _11 - _01 * _10; 12338 } 12339 12340 template <typename T> 12341 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22) 12342 { 12343 return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12); 12344 } 12345 12346 template <typename T> 12347 static T det4(T _00, T _10, T _20, T _30, T _01, T _11, T _21, T _31, T _02, T _12, T _22, T _32, T _03, T _13, T _23, 12348 T _33) 12349 { 12350 return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) - 12351 _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) + 12352 _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) - 12353 _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23); 12354 } 12355 12356 template <typename T> 12357 static T determinant(T val) 12358 { 12359 return val; 12360 } 12361 12362 template <typename T> 12363 static T determinant(const tcu::Matrix<T, 2, 2>& mat) 12364 { 12365 return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1)); 12366 } 12367 12368 template <typename T> 12369 static T determinant(const tcu::Matrix<T, 3, 3>& mat) 12370 { 12371 return det3(mat(0, 0), mat(0, 1), mat(0, 2), mat(1, 0), mat(1, 1), mat(1, 2), mat(2, 0), mat(2, 1), mat(2, 2)); 12372 } 12373 12374 template <typename T> 12375 static T determinant(const tcu::Matrix<T, 4, 4>& mat) 12376 { 12377 return det4(mat(0, 0), mat(0, 1), mat(0, 2), mat(0, 3), mat(1, 0), mat(1, 1), mat(1, 2), mat(1, 3), mat(2, 0), 12378 mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3)); 12379 } 12380 12381 template <int Size> 12382 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, 12383 glw::GLuint column, glw::GLuint row) 12384 { 12385 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result; 12386 12387 for (glw::GLuint c = 0; c < Size; ++c) 12388 { 12389 /* Skip eliminated column */ 12390 if (column == c) 12391 { 12392 continue; 12393 } 12394 12395 for (glw::GLuint r = 0; r < Size; ++r) 12396 { 12397 /* Skip eliminated row */ 12398 if (row == r) 12399 { 12400 continue; 12401 } 12402 12403 const glw::GLint r_offset = (r > row) ? -1 : 0; 12404 const glw::GLint c_offset = (c > column) ? -1 : 0; 12405 12406 result(r + r_offset, c + c_offset) = matrix(r, c); 12407 } 12408 } 12409 12410 return result; 12411 } 12412 12413 template <int Size> 12414 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left, 12415 const tcu::Vector<glw::GLdouble, Size>& right) 12416 { 12417 return convertBvecToUvec(tcu::equal(left, right)); 12418 } 12419 12420 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c) 12421 { 12422 return a * b + c; 12423 } 12424 12425 static glw::GLdouble fract(glw::GLdouble val) 12426 { 12427 return val - floor(val); 12428 } 12429 12430 template <typename T> 12431 static T frexp(T val, glw::GLint& exp) 12432 { 12433 return ::frexp(val, &exp); 12434 } 12435 12436 template <int Size> 12437 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left, 12438 const tcu::Vector<glw::GLdouble, Size>& right) 12439 { 12440 return convertBvecToUvec(tcu::greaterThan(left, right)); 12441 } 12442 12443 template <int Size> 12444 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left, 12445 const tcu::Vector<glw::GLdouble, Size>& right) 12446 { 12447 return convertBvecToUvec(tcu::greaterThanEqual(left, right)); 12448 } 12449 12450 template <int Size> 12451 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix) 12452 { 12453 const tcu::Matrix<glw::GLdouble, Size, Size> cof = cofactors(matrix); 12454 const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof); 12455 const glw::GLdouble det = determinant(matrix); 12456 const glw::GLdouble inv_det = 1.0 / det; 12457 12458 tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det; 12459 12460 return result; 12461 } 12462 12463 static glw::GLdouble inverseSqrt(glw::GLdouble val) 12464 { 12465 const glw::GLdouble root = sqrt(val); 12466 12467 return (1.0 / root); 12468 } 12469 12470 static glw::GLuint isinf_impl(glw::GLdouble val) 12471 { 12472 const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity(); 12473 12474 return ((infinity == val) || (-infinity == val)); 12475 } 12476 12477 static glw::GLuint isnan_impl(glw::GLdouble val) 12478 { 12479 return val != val; 12480 } 12481 12482 template <typename T> 12483 static T ldexp(T val, glw::GLint exp) 12484 { 12485 return ::ldexp(val, exp); 12486 } 12487 12488 template <int Size> 12489 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left, 12490 const tcu::Vector<glw::GLdouble, Size>& right) 12491 { 12492 return convertBvecToUvec(tcu::lessThan(left, right)); 12493 } 12494 12495 template <int Size> 12496 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left, 12497 const tcu::Vector<glw::GLdouble, Size>& right) 12498 { 12499 return convertBvecToUvec(tcu::lessThanEqual(left, right)); 12500 } 12501 12502 template <typename T> 12503 static T max(T left, T right) 12504 { 12505 return (left >= right) ? left : right; 12506 } 12507 12508 template <typename T> 12509 static T min(T left, T right) 12510 { 12511 return (left <= right) ? left : right; 12512 } 12513 12514 template <int Size> 12515 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column, 12516 glw::GLuint row) 12517 { 12518 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row); 12519 12520 return determinant(eliminated); 12521 } 12522 12523 template <> 12524 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row) 12525 { 12526 const glw::GLuint r = (0 == row) ? 1 : 0; 12527 const glw::GLuint c = (0 == column) ? 1 : 0; 12528 12529 return matrix(r, c); 12530 } 12531 12532 template <typename T> 12533 static T mix(T left, T right, T weight) 12534 { 12535 return left * (1 - weight) + right * (weight); 12536 } 12537 12538 template <typename T> 12539 static T mod(T left, T right) 12540 { 12541 const T div_res = left / right; 12542 const T floored = floor(div_res); 12543 12544 return left - right * floored; 12545 } 12546 12547 template <typename T> 12548 static T modf(T val, T& integer) 12549 { 12550 return ::modf(val, &integer); 12551 } 12552 12553 template <typename T> 12554 static T multiply(T left, T right) 12555 { 12556 T result = left * right; 12557 12558 return result; 12559 } 12560 12561 template <int Size> 12562 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left, 12563 const tcu::Vector<glw::GLdouble, Size>& right) 12564 { 12565 return convertBvecToUvec(tcu::notEqual(left, right)); 12566 } 12567 12568 template <int Cols, int Rows> 12569 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left, 12570 const tcu::Vector<glw::GLdouble, Cols>& right) 12571 { 12572 tcu::Matrix<glw::GLdouble, Rows, 1> left_mat; 12573 tcu::Matrix<glw::GLdouble, 1, Cols> right_mat; 12574 tcu::Matrix<glw::GLdouble, Rows, Cols> result; 12575 12576 for (glw::GLuint i = 0; i < Rows; ++i) 12577 { 12578 left_mat(i, 0) = left[i]; 12579 } 12580 12581 for (glw::GLuint i = 0; i < Cols; ++i) 12582 { 12583 right_mat(0, i) = right[i]; 12584 } 12585 12586 result = left_mat * right_mat; 12587 12588 return result; 12589 } 12590 12591 static glw::GLdouble packDouble2x32(const tcu::UVec2& in) 12592 { 12593 const glw::GLuint buffer[2] = { in[0], in[1] }; 12594 glw::GLdouble result; 12595 memcpy(&result, buffer, sizeof(result)); 12596 return result; 12597 } 12598 12599 template <typename T> 12600 static T round(T t) 12601 { 12602 T frac = fract(t); 12603 T res = t - frac; 12604 12605 if (((T)0.5) < frac) 12606 { 12607 res += ((T)1.0); 12608 } 12609 12610 return res; 12611 } 12612 12613 template <typename T> 12614 static T roundEven(T t) 12615 { 12616 T frac = fract(t); 12617 T res = t - frac; 12618 12619 if (((T)0.5) < frac) 12620 { 12621 res += ((T)1.0); 12622 } 12623 else if ((((T)0.5) == frac) && (0 != ((int)res) % 2)) 12624 { 12625 res += ((T)1.0); 12626 } 12627 12628 return res; 12629 } 12630 12631 template <typename T> 12632 static T sign(T t) 12633 { 12634 if (0 > t) 12635 { 12636 return -1; 12637 } 12638 else if (0 == t) 12639 { 12640 return 0; 12641 } 12642 else 12643 { 12644 return 1; 12645 } 12646 } 12647 12648 template <typename T> 12649 static T smoothStep(T e0, T e1, T val) 12650 { 12651 if (e0 >= val) 12652 { 12653 return 0; 12654 } 12655 12656 if (e1 <= val) 12657 { 12658 return 1; 12659 } 12660 12661 T temp = (val - e0) / (e1 - e0); 12662 12663 T result = temp * temp * (3 - 2 * temp); 12664 12665 return result; 12666 } 12667 12668 template <typename T> 12669 static T step(T edge, T val) 12670 { 12671 if (edge > val) 12672 { 12673 return 0; 12674 } 12675 else 12676 { 12677 return 1; 12678 } 12679 } 12680 12681 template <typename T, int Rows, int Cols> 12682 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix) 12683 { 12684 tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix); 12685 12686 return result; 12687 } 12688 12689 template <typename T> 12690 static T trunc(T t) 12691 { 12692 const T abs_value = de::abs(t); 12693 const T result_value = floor(abs_value); 12694 12695 const T result = sign(t) * result_value; 12696 12697 return result; 12698 } 12699 12700 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val) 12701 { 12702 glw::GLuint* ptr = (glw::GLuint*)&val; 12703 tcu::UVec2 result(ptr[0], ptr[1]); 12704 12705 return result; 12706 } 12707 } /* Math */ 12708 12709 /** Enumeration of tested functions 12710 * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments. 12711 * For example "max" can be called for (dvec3, double). 12712 **/ 12713 enum FunctionEnum 12714 { 12715 FUNCTION_ABS = 0, 12716 FUNCTION_CEIL, 12717 FUNCTION_CLAMP, 12718 FUNCTION_CLAMP_AGAINST_SCALAR, 12719 FUNCTION_CROSS, 12720 FUNCTION_DETERMINANT, 12721 FUNCTION_DISTANCE, 12722 FUNCTION_DOT, 12723 FUNCTION_EQUAL, 12724 FUNCTION_FACEFORWARD, 12725 FUNCTION_FLOOR, 12726 FUNCTION_FMA, 12727 FUNCTION_FRACT, 12728 FUNCTION_FREXP, 12729 FUNCTION_GREATERTHAN, 12730 FUNCTION_GREATERTHANEQUAL, 12731 FUNCTION_INVERSE, 12732 FUNCTION_INVERSESQRT, 12733 FUNCTION_LDEXP, 12734 FUNCTION_LESSTHAN, 12735 FUNCTION_LESSTHANEQUAL, 12736 FUNCTION_LENGTH, 12737 FUNCTION_MATRIXCOMPMULT, 12738 FUNCTION_MAX, 12739 FUNCTION_MAX_AGAINST_SCALAR, 12740 FUNCTION_MIN, 12741 FUNCTION_MIN_AGAINST_SCALAR, 12742 FUNCTION_MIX, 12743 FUNCTION_MOD, 12744 FUNCTION_MOD_AGAINST_SCALAR, 12745 FUNCTION_MODF, 12746 FUNCTION_NORMALIZE, 12747 FUNCTION_NOTEQUAL, 12748 FUNCTION_OUTERPRODUCT, 12749 FUNCTION_PACKDOUBLE2X32, 12750 FUNCTION_REFLECT, 12751 FUNCTION_REFRACT, 12752 FUNCTION_ROUND, 12753 FUNCTION_ROUNDEVEN, 12754 FUNCTION_SIGN, 12755 FUNCTION_SMOOTHSTEP, 12756 FUNCTION_SMOOTHSTEP_AGAINST_SCALAR, 12757 FUNCTION_SQRT, 12758 FUNCTION_STEP, 12759 FUNCTION_STEP_AGAINST_SCALAR, 12760 FUNCTION_TRANSPOSE, 12761 FUNCTION_TRUNC, 12762 FUNCTION_UNPACKDOUBLE2X32, 12763 FUNCTION_ISNAN, 12764 FUNCTION_ISINF, 12765 }; 12766 12767 struct TypeDefinition 12768 { 12769 std::string name; 12770 glw::GLuint n_columns; 12771 glw::GLuint n_rows; 12772 }; 12773 12774 /** Implementation of BuiltinFunctionTest test, description follows: 12775 * 12776 * Verify double-precision support in common functions works correctly. 12777 * All double-precision types that apply for particular cases should 12778 * be tested for the following functions: 12779 * 12780 * - abs(); 12781 * - ceil(); 12782 * - clamp(); 12783 * - cross(); 12784 * - determinant(); 12785 * - distance(); 12786 * - dot(); 12787 * - equal(); 12788 * - faceforward(); 12789 * - floor(); 12790 * - fma(); 12791 * - fract(); 12792 * - frexp(); 12793 * - greaterThan(); 12794 * - greaterThanEqual(); 12795 * - inverse(); 12796 * - inversesqrt(); 12797 * - ldexp(); 12798 * - lessThan(); 12799 * - lessThanEqual(); 12800 * - length(); 12801 * - matrixCompMult(); 12802 * - max(); 12803 * - min(); 12804 * - mix(); 12805 * - mod(); 12806 * - modf(); 12807 * - normalize(); 12808 * - notEqual(); 12809 * - outerProduct(); 12810 * - packDouble2x32(); 12811 * - reflect(); 12812 * - refract(); 12813 * - round(); 12814 * - roundEven(); 12815 * - sign(); 12816 * - smoothstep(); 12817 * - sqrt(); 12818 * - step(); 12819 * - transpose(); 12820 * - trunc(); 12821 * - unpackDouble2x32(); 12822 * - isnan(); 12823 * - isinf(); 12824 * 12825 * The test should work by creating a program object (for each case 12826 * considered), to which a vertex shader should be attached. The 12827 * shader should define input variables that should be used as 12828 * arguments for the function in question. The result of the 12829 * operation should then be XFBed back to the test, where the 12830 * value should be verified. 12831 * 12832 * Reference function implementation from pre-DEQP CTS framework 12833 * should be ported to C for verification purposes where available. 12834 * 12835 * The test should use 1024 different scalar/vector/matrix argument 12836 * combinations. It should pass if all functions are determined 12837 * to work correctly for all argument combinations used. 12838 **/ 12839 class BuiltinFunctionTest : public deqp::TestCase 12840 { 12841 public: 12842 /* Public methods */ 12843 BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function, 12844 TypeDefinition typeDefinition); 12845 12846 virtual void deinit(); 12847 virtual tcu::TestNode::IterateResult iterate(); 12848 12849 /** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code. 12850 * 12851 **/ 12852 class functionObject 12853 { 12854 public: 12855 functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer, 12856 Utils::_variable_type result_type); 12857 12858 virtual ~functionObject() 12859 { 12860 } 12861 12862 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0; 12863 12864 virtual glw::GLuint getArgumentCount() const = 0; 12865 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0; 12866 glw::GLuint getArgumentComponents(glw::GLuint argument) const; 12867 glw::GLuint getArgumentComponentSize(glw::GLuint argument) const; 12868 glw::GLuint getArgumentOffset(glw::GLuint argument) const; 12869 glw::GLuint getArgumentStride() const; 12870 glw::GLuint getArgumentStride(glw::GLuint argument) const; 12871 FunctionEnum getFunctionEnum() const; 12872 const glw::GLchar* getName() const; 12873 glw::GLuint getResultComponents(glw::GLuint result) const; 12874 virtual glw::GLuint getResultCount() const; 12875 glw::GLuint getResultOffset(glw::GLuint result) const; 12876 virtual Utils::_variable_type getResultType(glw::GLuint result) const; 12877 glw::GLuint getResultStride(glw::GLuint result) const; 12878 glw::GLuint getBaseTypeSize(glw::GLuint result) const; 12879 glw::GLuint getResultStride() const; 12880 12881 protected: 12882 const FunctionEnum m_function_enum; 12883 const glw::GLchar* m_function_name; 12884 const glw::GLvoid* m_p_function; 12885 const Utils::_variable_type m_res_type; 12886 }; 12887 12888 private: 12889 /* Private types */ 12890 /** General type enumeration 12891 * 12892 **/ 12893 enum generalType 12894 { 12895 SCALAR = 0, 12896 VECTOR, 12897 MATRIX, 12898 }; 12899 12900 /** Details of variable type 12901 * 12902 **/ 12903 struct typeDetails 12904 { 12905 typeDetails(glw::GLuint n_columns, glw::GLuint n_rows); 12906 12907 generalType m_general_type; 12908 glw::GLuint m_n_columns; 12909 glw::GLuint m_n_rows; 12910 glw::GLenum m_type; 12911 std::string m_type_name; 12912 }; 12913 12914 /* Typedefs for gl.uniform* function pointers */ 12915 typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean, 12916 const glw::GLdouble*); 12917 typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*); 12918 typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*); 12919 typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*); 12920 12921 /* Private methods */ 12922 bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right); 12923 12924 functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type); 12925 12926 uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint argument, 12927 const functionObject& function_object) const; 12928 12929 uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint argument, 12930 const functionObject& function_object) const; 12931 12932 uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint argument, 12933 const functionObject& function_object) const; 12934 12935 uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint argument, 12936 const functionObject& function_object) const; 12937 12938 const glw::GLchar* getUniformName(glw::GLuint argument) const; 12939 const glw::GLchar* getVaryingName(glw::GLuint argument) const; 12940 12941 bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const; 12942 12943 void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const; 12944 12945 void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer); 12946 12947 void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument, 12948 glw::GLubyte* buffer); 12949 12950 void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info); 12951 12952 void prepareTestData(const functionObject& function_object); 12953 void prepareVertexShaderCode(const functionObject& function_object); 12954 12955 bool test(FunctionEnum function, const typeDetails& type); 12956 12957 void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex); 12958 12959 void testInit(); 12960 12961 bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex, 12962 const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src, 12963 const glw::GLvoid* result_src); 12964 12965 bool verifyResults(const functionObject& function_object, glw::GLuint vertex); 12966 12967 /* Private constants */ 12968 static const glw::GLdouble m_epsilon; 12969 static const glw::GLuint m_n_veritces; 12970 12971 /* Private fields */ 12972 glw::GLuint m_transform_feedback_buffer_id; 12973 glw::GLuint m_vertex_array_object_id; 12974 12975 std::vector<glw::GLubyte> m_expected_results_data; 12976 FunctionEnum m_function; 12977 TypeDefinition m_typeDefinition; 12978 std::vector<glw::GLubyte> m_argument_data; 12979 std::string m_vertex_shader_code; 12980 }; 12981 12982 /* Constants used by BuiltinFunctionTest */ 12983 /** Khronos Bug #14010 12984 * Using an epsilon value for comparing floating points is error prone. 12985 * Rather than writing a new floating point comparison function, I am 12986 * increasing the epsilon value to allow greater orders of magnitude 12987 * of floating point values. 12988 **/ 12989 const glw::GLdouble BuiltinFunctionTest::m_epsilon = 0.00002; 12990 const glw::GLuint BuiltinFunctionTest::m_n_veritces = 1024; 12991 12992 /** Implementations of function objects required by "BuiltinFunctionTest" 12993 * 12994 **/ 12995 namespace FunctionObject 12996 { 12997 /** Maps variable type with enumeration Utils::_variable_type 12998 * 12999 * @tparam T type 13000 **/ 13001 template <typename T> 13002 class typeInfo 13003 { 13004 public: 13005 static const Utils::_variable_type variable_type = 13006 TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type; 13007 }; 13008 13009 /** Place data from <in> into <buffer> 13010 * 13011 * @param buffer Buffer 13012 * @param in Input data 13013 **/ 13014 template <typename T> 13015 class pack 13016 { 13017 public: 13018 static void set(glw::GLvoid* buffer, const T& in) 13019 { 13020 *(T*)buffer = in; 13021 } 13022 }; 13023 13024 /** Place tcu::Matrix data from <in> into <buffer> 13025 * 13026 * @param buffer Buffer 13027 * @param in Input data 13028 **/ 13029 template <int Cols, int Rows> 13030 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> > 13031 { 13032 public: 13033 static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in) 13034 { 13035 glw::GLdouble* data = (glw::GLdouble*)buffer; 13036 13037 for (glw::GLint column = 0; column < Cols; ++column) 13038 { 13039 for (glw::GLint row = 0; row < Rows; ++row) 13040 { 13041 glw::GLint index = column * Rows + row; 13042 13043 data[index] = in(row, column); 13044 } 13045 } 13046 } 13047 }; 13048 13049 /** Get data of <out> from <buffer> 13050 * 13051 * @param buffer Buffer 13052 * @param out Output data 13053 **/ 13054 template <typename T> 13055 class unpack 13056 { 13057 public: 13058 static void get(const glw::GLvoid* buffer, T& out) 13059 { 13060 out = *(T*)buffer; 13061 } 13062 }; 13063 13064 /** Get tcu::Matrix data from <buffer> 13065 * 13066 * @param buffer Buffer 13067 * @param out Output data 13068 **/ 13069 template <int Cols, int Rows> 13070 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> > 13071 { 13072 public: 13073 static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out) 13074 { 13075 const glw::GLdouble* data = (glw::GLdouble*)buffer; 13076 13077 for (glw::GLint column = 0; column < Cols; ++column) 13078 { 13079 for (glw::GLint row = 0; row < Rows; ++row) 13080 { 13081 glw::GLint index = column * Rows + row; 13082 13083 out(row, column) = data[index]; 13084 } 13085 } 13086 } 13087 }; 13088 13089 /** Base of unary function classes 13090 * 13091 **/ 13092 class unaryBase : public BuiltinFunctionTest::functionObject 13093 { 13094 public: 13095 unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer, 13096 const Utils::_variable_type res_type, const Utils::_variable_type arg_type) 13097 : functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type) 13098 { 13099 } 13100 13101 virtual glw::GLuint getArgumentCount() const 13102 { 13103 return 1; 13104 } 13105 13106 virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const 13107 { 13108 return m_arg_type; 13109 } 13110 13111 protected: 13112 const Utils::_variable_type m_arg_type; 13113 }; 13114 13115 /** Unary function class. It treats input argument as one variable. 13116 * 13117 * @tparam ResT Type of result 13118 * @tparam ArgT Type of argument 13119 **/ 13120 template <typename ResT, typename ArgT> 13121 class unary : public unaryBase 13122 { 13123 public: 13124 typedef ResT (*functionPointer)(const ArgT&); 13125 13126 unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer) 13127 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type, 13128 typeInfo<ArgT>::variable_type) 13129 { 13130 } 13131 13132 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const 13133 { 13134 ResT result; 13135 ArgT arg; 13136 13137 unpack<ArgT>::get(argument_src, arg); 13138 13139 functionPointer p_function = (functionPointer)m_p_function; 13140 13141 result = p_function(arg); 13142 13143 pack<ResT>::set(result_dst, result); 13144 } 13145 }; 13146 13147 /** Unary function class. It treats input argument as separate components. 13148 * 13149 * @tparam ResT Type of result 13150 **/ 13151 template <typename ResT> 13152 class unaryByComponent : public unaryBase 13153 { 13154 public: 13155 typedef ResT (*functionPointer)(glw::GLdouble); 13156 13157 unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer, 13158 const Utils::_variable_type res_type, const Utils::_variable_type arg_type) 13159 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type) 13160 { 13161 } 13162 13163 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const 13164 { 13165 glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type); 13166 ResT* p_result = (ResT*)result_dst; 13167 glw::GLdouble* p_arg = (glw::GLdouble*)argument_src; 13168 13169 functionPointer p_function = (functionPointer)m_p_function; 13170 13171 for (glw::GLuint component = 0; component < n_components; ++component) 13172 { 13173 p_result[component] = p_function(p_arg[component]); 13174 } 13175 } 13176 }; 13177 13178 /** Class of functions with one input and one output parameter. It treats arguments as separate components. 13179 * 13180 * @tparam ResT Type of result 13181 * @tparam ArgT Type of argument 13182 * @tparam OutT Type of output parameter 13183 **/ 13184 template <typename ResT, typename ArgT, typename OutT> 13185 class unaryWithOutputByComponent : public unaryBase 13186 { 13187 public: 13188 typedef ResT (*functionPointer)(ArgT, OutT&); 13189 13190 unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, 13191 functionPointer function_pointer, const Utils::_variable_type res_type, 13192 const Utils::_variable_type arg_type, const Utils::_variable_type out_type) 13193 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type) 13194 , m_out_type(out_type) 13195 { 13196 } 13197 13198 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const 13199 { 13200 ResT* p_result = (ResT*)result_dst; 13201 OutT* p_out = (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1)); 13202 ArgT* p_arg = (ArgT*)argument_src; 13203 13204 const glw::GLuint n_components_0 = getArgumentComponents(0); 13205 const glw::GLuint n_components_1 = getResultComponents(1); 13206 const glw::GLuint n_components = de::max(n_components_0, n_components_1); 13207 13208 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1; 13209 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1; 13210 13211 functionPointer p_function = (functionPointer)m_p_function; 13212 13213 for (glw::GLuint component = 0; component < n_components; ++component) 13214 { 13215 const ArgT first_arg = p_arg[component * component_step_0]; 13216 OutT& second_arg = p_out[component * component_step_1]; 13217 13218 p_result[component] = p_function(first_arg, second_arg); 13219 } 13220 } 13221 13222 glw::GLuint getResultCount() const 13223 { 13224 return 2; 13225 } 13226 13227 Utils::_variable_type getResultType(glw::GLuint result) const 13228 { 13229 Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN; 13230 13231 switch (result) 13232 { 13233 case 0: 13234 type = m_res_type; 13235 break; 13236 case 1: 13237 type = m_out_type; 13238 break; 13239 default: 13240 TCU_FAIL("Not implemented"); 13241 break; 13242 } 13243 13244 return type; 13245 } 13246 13247 protected: 13248 const Utils::_variable_type m_out_type; 13249 }; 13250 13251 /** Base of binary function classes. 13252 * 13253 **/ 13254 class binaryBase : public BuiltinFunctionTest::functionObject 13255 { 13256 public: 13257 binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer, 13258 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type, 13259 const Utils::_variable_type arg_2_type) 13260 : functionObject(function_enum, function_name, function_pointer, res_type) 13261 , m_arg_1_type(arg_1_type) 13262 , m_arg_2_type(arg_2_type) 13263 { 13264 } 13265 13266 virtual glw::GLuint getArgumentCount() const 13267 { 13268 return 2; 13269 } 13270 13271 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const 13272 { 13273 switch (argument) 13274 { 13275 case 0: 13276 return m_arg_1_type; 13277 break; 13278 case 1: 13279 return m_arg_2_type; 13280 break; 13281 default: 13282 return Utils::VARIABLE_TYPE_UNKNOWN; 13283 break; 13284 } 13285 } 13286 13287 protected: 13288 const Utils::_variable_type m_arg_1_type; 13289 const Utils::_variable_type m_arg_2_type; 13290 }; 13291 13292 /** Binary function class. It treats input arguments as two variables. 13293 * 13294 * @param ResT Type of result 13295 * @param Arg1T Type of first argument 13296 * @param Arg2T Type of second argument 13297 **/ 13298 template <typename ResT, typename Arg1T, typename Arg2T> 13299 class binary : public binaryBase 13300 { 13301 public: 13302 typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&); 13303 13304 binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer) 13305 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type, 13306 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type) 13307 { 13308 } 13309 13310 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const 13311 { 13312 const glw::GLuint argument_1_stride = getArgumentStride(0); 13313 13314 functionPointer p_function = (functionPointer)m_p_function; 13315 13316 Arg1T arg_1; 13317 Arg2T arg_2; 13318 ResT result; 13319 13320 unpack<Arg1T>::get(argument_src, arg_1); 13321 unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2); 13322 13323 result = p_function(arg_1, arg_2); 13324 13325 pack<ResT>::set(result_dst, result); 13326 } 13327 }; 13328 13329 /** Binary function class. It treats input arguments as separate components. 13330 * 13331 * @param ResT Type of result 13332 * @param Arg1T Type of first argument 13333 * @param Arg2T Type of second argument 13334 **/ 13335 template <typename ResT, typename Arg1T, typename Arg2T> 13336 class binaryByComponent : public binaryBase 13337 { 13338 public: 13339 typedef ResT (*functionPointer)(Arg1T, Arg2T); 13340 13341 binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer, 13342 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type, 13343 const Utils::_variable_type arg_2_type) 13344 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type) 13345 { 13346 } 13347 13348 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const 13349 { 13350 ResT* p_result = (ResT*)result_dst; 13351 Arg1T* p_arg_1 = (Arg1T*)argument_src; 13352 Arg2T* p_arg_2 = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1)); 13353 13354 const glw::GLuint n_components_0 = getArgumentComponents(0); 13355 const glw::GLuint n_components_1 = getArgumentComponents(1); 13356 const glw::GLuint n_components = de::max(n_components_0, n_components_1); 13357 13358 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1; 13359 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1; 13360 13361 functionPointer p_function = (functionPointer)m_p_function; 13362 13363 for (glw::GLuint component = 0; component < n_components; ++component) 13364 { 13365 const Arg1T first_arg = p_arg_1[component * component_step_0]; 13366 const Arg2T second_arg = p_arg_2[component * component_step_1]; 13367 13368 p_result[component] = p_function(first_arg, second_arg); 13369 } 13370 } 13371 }; 13372 13373 /** Base of tenary function classes. 13374 * 13375 **/ 13376 class tenaryBase : public BuiltinFunctionTest::functionObject 13377 { 13378 public: 13379 tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer, 13380 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type, 13381 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type) 13382 : functionObject(function_enum, function_name, function_pointer, res_type) 13383 , m_arg_1_type(arg_1_type) 13384 , m_arg_2_type(arg_2_type) 13385 , m_arg_3_type(arg_3_type) 13386 { 13387 } 13388 13389 virtual glw::GLuint getArgumentCount() const 13390 { 13391 return 3; 13392 } 13393 13394 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const 13395 { 13396 switch (argument) 13397 { 13398 case 0: 13399 return m_arg_1_type; 13400 break; 13401 case 1: 13402 return m_arg_2_type; 13403 break; 13404 case 2: 13405 return m_arg_3_type; 13406 break; 13407 default: 13408 return Utils::VARIABLE_TYPE_UNKNOWN; 13409 break; 13410 } 13411 } 13412 13413 protected: 13414 const Utils::_variable_type m_arg_1_type; 13415 const Utils::_variable_type m_arg_2_type; 13416 const Utils::_variable_type m_arg_3_type; 13417 }; 13418 13419 /** Tenary function class. It treats input arguments as three variables. 13420 * 13421 * @param ResT Type of result 13422 * @param Arg1T Type of first argument 13423 * @param Arg2T Type of second argument 13424 * @param Arg3T Type of third argument 13425 **/ 13426 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T> 13427 class tenary : public tenaryBase 13428 { 13429 public: 13430 typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T); 13431 typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T; 13432 typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T; 13433 typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T; 13434 13435 tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer) 13436 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type, 13437 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type) 13438 { 13439 } 13440 13441 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const 13442 { 13443 const glw::GLuint argument_2_offset = getArgumentOffset(1); 13444 const glw::GLuint argument_3_offset = getArgumentOffset(2); 13445 13446 functionPointer p_function = (functionPointer)m_p_function; 13447 13448 arg1T arg_1; 13449 arg2T arg_2; 13450 arg3T arg_3; 13451 ResT result; 13452 13453 unpack<arg1T>::get(argument_src, arg_1); 13454 unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2); 13455 unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3); 13456 13457 result = p_function(arg_1, arg_2, arg_3); 13458 13459 pack<ResT>::set(result_dst, result); 13460 } 13461 }; 13462 13463 /** Tenary function class. It treats input arguments as separate components. 13464 * 13465 13466 **/ 13467 class tenaryByComponent : public tenaryBase 13468 { 13469 public: 13470 typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble); 13471 13472 tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer, 13473 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type, 13474 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type) 13475 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type, 13476 arg_3_type) 13477 { 13478 } 13479 13480 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const 13481 { 13482 glw::GLdouble* p_result = (glw::GLdouble*)result_dst; 13483 const glw::GLdouble* p_arg = (const glw::GLdouble*)argument_src; 13484 13485 const glw::GLuint n_components_0 = getArgumentComponents(0); 13486 const glw::GLuint n_components_1 = getArgumentComponents(1); 13487 const glw::GLuint n_components_2 = getArgumentComponents(2); 13488 const glw::GLuint n_components = de::max(de::max(n_components_0, n_components_1), n_components_2); 13489 13490 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1; 13491 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1; 13492 const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1; 13493 13494 functionPointer p_function = (functionPointer)m_p_function; 13495 13496 for (glw::GLuint component = 0; component < n_components; ++component) 13497 { 13498 const glw::GLdouble first_arg = p_arg[component * component_step_0]; 13499 const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0]; 13500 const glw::GLdouble third_arg = p_arg[component * component_step_2 + n_components_0 + n_components_1]; 13501 13502 p_result[component] = p_function(first_arg, second_arg, third_arg); 13503 } 13504 } 13505 }; 13506 } /* FunctionObject */ 13507 13508 /** Constructor. 13509 * 13510 * @param context Rendering context. 13511 **/ 13512 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function, 13513 TypeDefinition typeDefinition) 13514 : TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types") 13515 , m_transform_feedback_buffer_id(0) 13516 , m_vertex_array_object_id(0) 13517 , m_function(function) 13518 , m_typeDefinition(typeDefinition) 13519 { 13520 /* Nothing to be done here */ 13521 } 13522 13523 /** Deinitializes all GL objects that may have been created during test execution. 13524 * 13525 **/ 13526 void BuiltinFunctionTest::deinit() 13527 { 13528 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 13529 13530 /* Clean buffers */ 13531 if (0 != m_transform_feedback_buffer_id) 13532 { 13533 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 13534 gl.deleteBuffers(1, &m_transform_feedback_buffer_id); 13535 m_transform_feedback_buffer_id = 0; 13536 } 13537 13538 /* Clean VAO */ 13539 if (0 != m_vertex_array_object_id) 13540 { 13541 gl.bindVertexArray(0); 13542 gl.deleteVertexArrays(1, &m_vertex_array_object_id); 13543 m_vertex_array_object_id = 0; 13544 } 13545 } 13546 13547 /** Execute test 13548 * 13549 * @return tcu::TestNode::STOP 13550 **/ 13551 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate() 13552 { 13553 /* Check if extension is supported */ 13554 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) 13555 { 13556 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported"); 13557 } 13558 13559 testInit(); 13560 13561 /* Verify result */ 13562 typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows); 13563 if (test(m_function, type)) 13564 { 13565 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); 13566 } 13567 else 13568 { 13569 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 13570 } 13571 13572 /* Done */ 13573 return tcu::TestNode::STOP; 13574 } 13575 13576 /** Constructor 13577 * 13578 * @param function_enum Function enumeration 13579 * @param function_name Function name 13580 * @param function_pointer Pointer to routine that wiil be executed 13581 * @param result_type Type of result 13582 **/ 13583 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, 13584 glw::GLvoid* function_pointer, Utils::_variable_type result_type) 13585 : m_function_enum(function_enum) 13586 , m_function_name(function_name) 13587 , m_p_function(function_pointer) 13588 , m_res_type(result_type) 13589 { 13590 /* Nothing to be done here */ 13591 } 13592 13593 /** Get number of components for <argument> 13594 * 13595 * @param argument Argument ordinal, starts with 0 13596 * 13597 * @return Number of components 13598 **/ 13599 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const 13600 { 13601 const Utils::_variable_type type = getArgumentType(argument); 13602 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type); 13603 13604 return n_components; 13605 } 13606 13607 /** Get size in bytes of single component of <argument> 13608 * 13609 * @param argument Argument ordinal, starts with 0 13610 * 13611 * @return Size of component 13612 **/ 13613 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const 13614 { 13615 const Utils::_variable_type type = getArgumentType(argument); 13616 const Utils::_variable_type base_type = Utils::getBaseVariableType(type); 13617 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type); 13618 13619 return base_type_size; 13620 } 13621 13622 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing. 13623 * 13624 * @param argument Argument ordinal, starts with 0 13625 * 13626 * @return Offset of arguemnt's data 13627 **/ 13628 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const 13629 { 13630 glw::GLuint result = 0; 13631 13632 for (glw::GLuint i = 0; i < argument; ++i) 13633 { 13634 result += getArgumentStride(i); 13635 } 13636 13637 return result; 13638 } 13639 13640 /** Get stride in bytes of all arguments 13641 * 13642 * @return Stride of all arguments 13643 **/ 13644 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const 13645 { 13646 const glw::GLuint n_args = getArgumentCount(); 13647 glw::GLuint result = 0; 13648 13649 for (glw::GLuint i = 0; i < n_args; ++i) 13650 { 13651 result += getArgumentStride(i); 13652 } 13653 13654 return result; 13655 } 13656 13657 /** Get stride in bytes of <argument> 13658 * 13659 * @param argument Argument ordinal, starts with 0 13660 * 13661 * @return Stride of argument 13662 **/ 13663 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const 13664 { 13665 const glw::GLuint component_size = getArgumentComponentSize(argument); 13666 const glw::GLuint n_components = getArgumentComponents(argument); 13667 13668 return n_components * component_size; 13669 } 13670 13671 /** Get function enumeration 13672 * 13673 * @return Function enumeration 13674 **/ 13675 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const 13676 { 13677 return m_function_enum; 13678 } 13679 13680 /** Get function name 13681 * 13682 * @return Function name 13683 **/ 13684 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const 13685 { 13686 return m_function_name; 13687 } 13688 13689 /** Get number of components for <result> 13690 * 13691 * @param result Result ordinal, starts with 0 13692 * 13693 * @return Number of components 13694 **/ 13695 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const 13696 { 13697 const Utils::_variable_type type = getResultType(result); 13698 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type); 13699 13700 return n_components; 13701 } 13702 13703 /** Get number of results 13704 * 13705 * @return Number of results 13706 **/ 13707 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const 13708 { 13709 return 1; 13710 } 13711 13712 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing. 13713 * 13714 * @param result Result ordinal, starts with 0 13715 * 13716 * @return Offset 13717 **/ 13718 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const 13719 { 13720 glw::GLuint offset = 0; 13721 13722 for (glw::GLuint i = 0; i < result; ++i) 13723 { 13724 offset += getResultStride(i); 13725 offset = deAlign32(offset, getBaseTypeSize(i)); 13726 } 13727 13728 return offset; 13729 } 13730 13731 /** Get stride in bytes of <result>. 13732 * 13733 * @param result Result ordinal, starts with 0 13734 * 13735 * @return Stride 13736 **/ 13737 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const 13738 { 13739 const Utils::_variable_type type = getResultType(result); 13740 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type); 13741 13742 return n_components * getBaseTypeSize(result); 13743 } 13744 13745 /** Get size in bytes of <result> base component. 13746 * 13747 * @param result Result ordinal, starts with 0 13748 * 13749 * @return Alignment 13750 **/ 13751 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const 13752 { 13753 const Utils::_variable_type type = getResultType(result); 13754 const Utils::_variable_type base_type = Utils::getBaseVariableType(type); 13755 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type); 13756 13757 return base_type_size; 13758 } 13759 13760 /** Get stride in bytes of all results. 13761 * 13762 * @return Stride 13763 **/ 13764 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const 13765 { 13766 const glw::GLuint n_results = getResultCount(); 13767 glw::GLuint stride = 0; 13768 glw::GLuint maxAlignment = 0; 13769 13770 for (glw::GLuint i = 0; i < n_results; ++i) 13771 { 13772 const glw::GLuint alignment = getBaseTypeSize(i); 13773 stride += getResultStride(i); 13774 stride = deAlign32(stride, alignment); 13775 maxAlignment = deMaxu32(maxAlignment, alignment); 13776 } 13777 13778 // The stride of all results must also be aligned, 13779 // so results for next vertex are aligned. 13780 return deAlign32(stride, maxAlignment); 13781 } 13782 13783 /** Get type of <result>. 13784 * 13785 * @param result Result ordinal, starts with 0 13786 * 13787 * @return Type 13788 **/ 13789 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const 13790 { 13791 return m_res_type; 13792 } 13793 13794 /** Constructor 13795 * 13796 * @param n_columns Number of columns 13797 * @param n_rows Number of rows 13798 **/ 13799 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows) 13800 : m_n_columns(n_columns), m_n_rows(n_rows) 13801 { 13802 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows); 13803 m_type = Utils::getGLDataTypeOfVariableType(type); 13804 m_type_name = Utils::getVariableTypeString(type); 13805 13806 if (1 == m_n_columns) 13807 { 13808 if (1 == m_n_rows) 13809 { 13810 m_general_type = SCALAR; 13811 } 13812 else 13813 { 13814 m_general_type = VECTOR; 13815 } 13816 } 13817 else 13818 { 13819 m_general_type = MATRIX; 13820 } 13821 } 13822 13823 /** Compare two values 13824 * 13825 * @param type Type of values 13826 * @param left Pointer to left value 13827 * @param right Pointer to right value 13828 * 13829 * @return true if values are equal, false otherwise 13830 **/ 13831 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right) 13832 { 13833 bool result = true; 13834 13835 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type); 13836 const Utils::_variable_type base_type = Utils::getBaseVariableType(type); 13837 13838 switch (base_type) 13839 { 13840 case Utils::VARIABLE_TYPE_DOUBLE: 13841 13842 { 13843 const glw::GLdouble* left_values = (glw::GLdouble*)left; 13844 const glw::GLdouble* right_values = (glw::GLdouble*)right; 13845 13846 for (glw::GLuint component = 0; component < n_components; ++component) 13847 { 13848 const glw::GLdouble left_value = left_values[component]; 13849 const glw::GLdouble right_value = right_values[component]; 13850 13851 if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) && 13852 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value))) 13853 { 13854 result = false; 13855 break; 13856 } 13857 } 13858 } 13859 13860 break; 13861 13862 case Utils::VARIABLE_TYPE_INT: 13863 13864 { 13865 const glw::GLint* left_values = (glw::GLint*)left; 13866 const glw::GLint* right_values = (glw::GLint*)right; 13867 13868 for (glw::GLuint component = 0; component < n_components; ++component) 13869 { 13870 const glw::GLint left_value = left_values[component]; 13871 const glw::GLint right_value = right_values[component]; 13872 13873 if (left_value != right_value) 13874 { 13875 result = false; 13876 break; 13877 } 13878 } 13879 } 13880 13881 break; 13882 13883 case Utils::VARIABLE_TYPE_UINT: 13884 13885 { 13886 const glw::GLuint* left_values = (glw::GLuint*)left; 13887 const glw::GLuint* right_values = (glw::GLuint*)right; 13888 13889 for (glw::GLuint component = 0; component < n_components; ++component) 13890 { 13891 const glw::GLuint left_value = left_values[component]; 13892 const glw::GLuint right_value = right_values[component]; 13893 13894 if (left_value != right_value) 13895 { 13896 result = false; 13897 break; 13898 } 13899 } 13900 } 13901 13902 break; 13903 13904 default: 13905 13906 TCU_FAIL("Not implemented"); 13907 13908 break; 13909 } 13910 13911 return result; 13912 } 13913 13914 /** Create instance of function object for given function enumeration and type 13915 * 13916 * @param function Function enumeration 13917 * @param type Type details 13918 * 13919 * @return Create object 13920 **/ 13921 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum function, 13922 const typeDetails& type) 13923 { 13924 typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2; 13925 typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3; 13926 typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4; 13927 typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2; 13928 typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3; 13929 typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4; 13930 typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2; 13931 typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3; 13932 typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4; 13933 13934 const glw::GLuint n_columns = type.m_n_columns; 13935 const glw::GLuint n_rows = type.m_n_rows; 13936 const Utils::_variable_type scalar_type = Utils::getDoubleVariableType(1, 1); 13937 const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows); 13938 const Utils::_variable_type uint_type = Utils::getUintVariableType(1, n_rows); 13939 const Utils::_variable_type int_type = Utils::getIntVariableType(1, n_rows); 13940 13941 switch (function) 13942 { 13943 case FUNCTION_ABS: 13944 13945 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 13946 function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */); 13947 13948 break; 13949 13950 case FUNCTION_CEIL: 13951 13952 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 13953 function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */); 13954 13955 break; 13956 13957 case FUNCTION_CLAMP: 13958 13959 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */, 13960 variable_type /* arg1_type */, variable_type /* arg2_type */, 13961 variable_type /* arg3_type */); 13962 break; 13963 13964 case FUNCTION_CLAMP_AGAINST_SCALAR: 13965 13966 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */, 13967 variable_type /* arg1_type */, scalar_type /* arg2_type */, 13968 scalar_type /* arg3_type */); 13969 break; 13970 13971 case FUNCTION_CROSS: 13972 13973 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 13974 function, "cross", tcu::cross); 13975 13976 break; 13977 13978 case FUNCTION_DETERMINANT: 13979 13980 switch (variable_type) 13981 { 13982 case Utils::VARIABLE_TYPE_DMAT2: 13983 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant", 13984 Math::determinant); 13985 case Utils::VARIABLE_TYPE_DMAT3: 13986 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant", 13987 Math::determinant); 13988 case Utils::VARIABLE_TYPE_DMAT4: 13989 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant", 13990 Math::determinant); 13991 default: 13992 TCU_FAIL("Not implemented"); 13993 break; 13994 } 13995 13996 break; 13997 13998 case FUNCTION_DISTANCE: 13999 14000 switch (variable_type) 14001 { 14002 case Utils::VARIABLE_TYPE_DVEC2: 14003 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14004 function, "distance", tcu::distance); 14005 break; 14006 case Utils::VARIABLE_TYPE_DVEC3: 14007 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14008 function, "distance", tcu::distance); 14009 break; 14010 case Utils::VARIABLE_TYPE_DVEC4: 14011 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14012 function, "distance", tcu::distance); 14013 break; 14014 default: 14015 break; 14016 } 14017 14018 break; 14019 14020 case FUNCTION_DOT: 14021 14022 switch (variable_type) 14023 { 14024 case Utils::VARIABLE_TYPE_DVEC2: 14025 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14026 function, "dot", tcu::dot); 14027 break; 14028 case Utils::VARIABLE_TYPE_DVEC3: 14029 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14030 function, "dot", tcu::dot); 14031 break; 14032 case Utils::VARIABLE_TYPE_DVEC4: 14033 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14034 function, "dot", tcu::dot); 14035 break; 14036 default: 14037 break; 14038 } 14039 14040 break; 14041 14042 case FUNCTION_EQUAL: 14043 14044 switch (variable_type) 14045 { 14046 case Utils::VARIABLE_TYPE_DVEC2: 14047 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14048 function, "equal", Math::equal); 14049 break; 14050 case Utils::VARIABLE_TYPE_DVEC3: 14051 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14052 function, "equal", Math::equal); 14053 break; 14054 case Utils::VARIABLE_TYPE_DVEC4: 14055 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14056 function, "equal", Math::equal); 14057 break; 14058 default: 14059 break; 14060 } 14061 14062 break; 14063 14064 case FUNCTION_FACEFORWARD: 14065 14066 switch (variable_type) 14067 { 14068 case Utils::VARIABLE_TYPE_DVEC2: 14069 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */, 14070 const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>( 14071 function, "faceforward", tcu::faceForward); 14072 break; 14073 case Utils::VARIABLE_TYPE_DVEC3: 14074 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */, 14075 const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>( 14076 function, "faceforward", tcu::faceForward); 14077 break; 14078 case Utils::VARIABLE_TYPE_DVEC4: 14079 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */, 14080 const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>( 14081 function, "faceforward", tcu::faceForward); 14082 break; 14083 default: 14084 break; 14085 } 14086 14087 break; 14088 14089 case FUNCTION_FLOOR: 14090 14091 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 14092 function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */); 14093 14094 break; 14095 14096 case FUNCTION_FMA: 14097 14098 return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type */, 14099 variable_type /* arg1_type */, variable_type /* arg2_type */, 14100 variable_type /* arg3_type */); 14101 14102 break; 14103 14104 case FUNCTION_FRACT: 14105 14106 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 14107 function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */); 14108 14109 break; 14110 14111 case FUNCTION_FREXP: 14112 14113 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */, 14114 glw::GLint /* OutT */>( 14115 function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */, 14116 int_type /* out_type */); 14117 14118 break; 14119 14120 case FUNCTION_GREATERTHAN: 14121 14122 switch (variable_type) 14123 { 14124 case Utils::VARIABLE_TYPE_DVEC2: 14125 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14126 function, "greaterThan", Math::greaterThan); 14127 break; 14128 case Utils::VARIABLE_TYPE_DVEC3: 14129 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14130 function, "greaterThan", Math::greaterThan); 14131 break; 14132 case Utils::VARIABLE_TYPE_DVEC4: 14133 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14134 function, "greaterThan", Math::greaterThan); 14135 break; 14136 default: 14137 break; 14138 } 14139 14140 break; 14141 14142 case FUNCTION_GREATERTHANEQUAL: 14143 14144 switch (variable_type) 14145 { 14146 case Utils::VARIABLE_TYPE_DVEC2: 14147 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14148 function, "greaterThanEqual", Math::greaterThanEqual); 14149 break; 14150 case Utils::VARIABLE_TYPE_DVEC3: 14151 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14152 function, "greaterThanEqual", Math::greaterThanEqual); 14153 break; 14154 case Utils::VARIABLE_TYPE_DVEC4: 14155 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14156 function, "greaterThanEqual", Math::greaterThanEqual); 14157 break; 14158 default: 14159 break; 14160 } 14161 14162 break; 14163 14164 case FUNCTION_INVERSE: 14165 14166 switch (variable_type) 14167 { 14168 case Utils::VARIABLE_TYPE_DMAT2: 14169 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse); 14170 break; 14171 case Utils::VARIABLE_TYPE_DMAT3: 14172 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse); 14173 break; 14174 case Utils::VARIABLE_TYPE_DMAT4: 14175 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse); 14176 break; 14177 default: 14178 break; 14179 } 14180 14181 break; 14182 14183 case FUNCTION_INVERSESQRT: 14184 14185 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 14186 function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */); 14187 14188 break; 14189 14190 case FUNCTION_LDEXP: 14191 14192 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14193 glw::GLint /* Arg2T */>( 14194 function, "ldexp", ::ldexp, variable_type /* res_type */, variable_type /* arg1_type */, 14195 int_type /* arg2_type */); 14196 14197 break; 14198 14199 case FUNCTION_LESSTHAN: 14200 14201 switch (variable_type) 14202 { 14203 case Utils::VARIABLE_TYPE_DVEC2: 14204 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14205 function, "lessThan", Math::lessThan); 14206 break; 14207 case Utils::VARIABLE_TYPE_DVEC3: 14208 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14209 function, "lessThan", Math::lessThan); 14210 break; 14211 case Utils::VARIABLE_TYPE_DVEC4: 14212 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14213 function, "lessThan", Math::lessThan); 14214 break; 14215 default: 14216 break; 14217 } 14218 14219 break; 14220 14221 case FUNCTION_LESSTHANEQUAL: 14222 14223 switch (variable_type) 14224 { 14225 case Utils::VARIABLE_TYPE_DVEC2: 14226 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14227 function, "lessThanEqual", Math::lessThanEqual); 14228 break; 14229 case Utils::VARIABLE_TYPE_DVEC3: 14230 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14231 function, "lessThanEqual", Math::lessThanEqual); 14232 break; 14233 case Utils::VARIABLE_TYPE_DVEC4: 14234 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14235 function, "lessThanEqual", Math::lessThanEqual); 14236 break; 14237 default: 14238 break; 14239 } 14240 14241 break; 14242 14243 case FUNCTION_LENGTH: 14244 14245 switch (variable_type) 14246 { 14247 case Utils::VARIABLE_TYPE_DVEC2: 14248 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length", 14249 tcu::length); 14250 break; 14251 case Utils::VARIABLE_TYPE_DVEC3: 14252 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length", 14253 tcu::length); 14254 break; 14255 case Utils::VARIABLE_TYPE_DVEC4: 14256 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length", 14257 tcu::length); 14258 break; 14259 default: 14260 break; 14261 } 14262 14263 break; 14264 14265 case FUNCTION_MATRIXCOMPMULT: 14266 14267 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14268 glw::GLdouble /* Arg2T */>( 14269 function, "matrixCompMult", Math::multiply, variable_type /* res_type */, variable_type /* arg1_type */, 14270 variable_type /* arg2_type */); 14271 14272 break; 14273 14274 case FUNCTION_MAX: 14275 14276 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14277 glw::GLdouble /* Arg2T */>( 14278 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */, 14279 variable_type /* arg2_type */); 14280 14281 break; 14282 14283 case FUNCTION_MAX_AGAINST_SCALAR: 14284 14285 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14286 glw::GLdouble /* Arg2T */>( 14287 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */, 14288 scalar_type /* arg2_type */); 14289 14290 break; 14291 14292 case FUNCTION_MIN: 14293 14294 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14295 glw::GLdouble /* Arg2T */>( 14296 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */, 14297 variable_type /* arg2_type */); 14298 14299 break; 14300 14301 case FUNCTION_MIN_AGAINST_SCALAR: 14302 14303 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14304 glw::GLdouble /* Arg2T */>( 14305 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */, 14306 scalar_type /* arg2_type */); 14307 14308 break; 14309 14310 case FUNCTION_MIX: 14311 14312 return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type */, 14313 variable_type /* arg1_type */, variable_type /* arg2_type */, 14314 variable_type /* arg3_type */); 14315 14316 break; 14317 14318 case FUNCTION_MOD: 14319 14320 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14321 glw::GLdouble /* Arg2T */>( 14322 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */, 14323 variable_type /* arg2_type */); 14324 14325 break; 14326 14327 case FUNCTION_MOD_AGAINST_SCALAR: 14328 14329 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14330 glw::GLdouble /* Arg2T */>( 14331 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */, 14332 scalar_type /* arg2_type */); 14333 14334 break; 14335 14336 case FUNCTION_MODF: 14337 14338 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */, 14339 glw::GLdouble /* OutT */>( 14340 function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */, 14341 variable_type /* out_type */); 14342 14343 break; 14344 14345 case FUNCTION_NORMALIZE: 14346 14347 switch (variable_type) 14348 { 14349 case Utils::VARIABLE_TYPE_DVEC2: 14350 return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize", 14351 tcu::normalize); 14352 break; 14353 case Utils::VARIABLE_TYPE_DVEC3: 14354 return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize", 14355 tcu::normalize); 14356 break; 14357 case Utils::VARIABLE_TYPE_DVEC4: 14358 return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize", 14359 tcu::normalize); 14360 break; 14361 default: 14362 break; 14363 } 14364 14365 break; 14366 14367 case FUNCTION_NOTEQUAL: 14368 14369 switch (variable_type) 14370 { 14371 case Utils::VARIABLE_TYPE_DVEC2: 14372 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14373 function, "notEqual", Math::notEqual); 14374 break; 14375 case Utils::VARIABLE_TYPE_DVEC3: 14376 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14377 function, "notEqual", Math::notEqual); 14378 break; 14379 case Utils::VARIABLE_TYPE_DVEC4: 14380 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14381 function, "notEqual", Math::notEqual); 14382 break; 14383 default: 14384 break; 14385 } 14386 14387 break; 14388 14389 case FUNCTION_OUTERPRODUCT: 14390 14391 switch (variable_type) 14392 { 14393 case Utils::VARIABLE_TYPE_DMAT2: 14394 return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14395 function, "outerProduct", Math::outerProduct); 14396 break; 14397 case Utils::VARIABLE_TYPE_DMAT2X3: 14398 return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14399 function, "outerProduct", Math::outerProduct); 14400 break; 14401 case Utils::VARIABLE_TYPE_DMAT2X4: 14402 return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14403 function, "outerProduct", Math::outerProduct); 14404 break; 14405 case Utils::VARIABLE_TYPE_DMAT3: 14406 return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14407 function, "outerProduct", Math::outerProduct); 14408 break; 14409 case Utils::VARIABLE_TYPE_DMAT3X2: 14410 return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14411 function, "outerProduct", Math::outerProduct); 14412 break; 14413 case Utils::VARIABLE_TYPE_DMAT3X4: 14414 return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14415 function, "outerProduct", Math::outerProduct); 14416 break; 14417 case Utils::VARIABLE_TYPE_DMAT4: 14418 return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14419 function, "outerProduct", Math::outerProduct); 14420 break; 14421 case Utils::VARIABLE_TYPE_DMAT4X2: 14422 return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14423 function, "outerProduct", Math::outerProduct); 14424 break; 14425 case Utils::VARIABLE_TYPE_DMAT4X3: 14426 return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14427 function, "outerProduct", Math::outerProduct); 14428 break; 14429 default: 14430 break; 14431 } 14432 14433 break; 14434 14435 case FUNCTION_PACKDOUBLE2X32: 14436 14437 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32", 14438 Math::packDouble2x32); 14439 14440 break; 14441 14442 case FUNCTION_REFLECT: 14443 14444 switch (variable_type) 14445 { 14446 case Utils::VARIABLE_TYPE_DVEC2: 14447 return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>( 14448 function, "reflect", tcu::reflect); 14449 break; 14450 case Utils::VARIABLE_TYPE_DVEC3: 14451 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>( 14452 function, "reflect", tcu::reflect); 14453 break; 14454 case Utils::VARIABLE_TYPE_DVEC4: 14455 return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>( 14456 function, "reflect", tcu::reflect); 14457 break; 14458 default: 14459 break; 14460 } 14461 14462 break; 14463 14464 case FUNCTION_REFRACT: 14465 14466 switch (variable_type) 14467 { 14468 case Utils::VARIABLE_TYPE_DVEC2: 14469 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */, 14470 const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>( 14471 function, "refract", tcu::refract); 14472 break; 14473 case Utils::VARIABLE_TYPE_DVEC3: 14474 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */, 14475 const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>( 14476 function, "refract", tcu::refract); 14477 break; 14478 case Utils::VARIABLE_TYPE_DVEC4: 14479 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */, 14480 const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>( 14481 function, "refract", tcu::refract); 14482 break; 14483 default: 14484 break; 14485 } 14486 14487 break; 14488 14489 case FUNCTION_ROUND: 14490 14491 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 14492 function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */); 14493 14494 break; 14495 14496 case FUNCTION_ROUNDEVEN: 14497 14498 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 14499 function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */); 14500 14501 break; 14502 14503 case FUNCTION_SIGN: 14504 14505 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 14506 function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */); 14507 14508 break; 14509 14510 case FUNCTION_SMOOTHSTEP: 14511 14512 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep, 14513 variable_type /* res_type */, variable_type /* arg1_type */, 14514 variable_type /* arg2_type */, variable_type /* arg3_type */); 14515 14516 break; 14517 14518 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: 14519 14520 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep, 14521 variable_type /* res_type */, scalar_type /* arg1_type */, 14522 scalar_type /* arg2_type */, variable_type /* arg3_type */); 14523 14524 break; 14525 14526 case FUNCTION_SQRT: 14527 14528 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 14529 function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */); 14530 14531 break; 14532 14533 case FUNCTION_STEP: 14534 14535 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14536 glw::GLdouble /* Arg2T */>( 14537 function, "step", Math::step, variable_type /* res_type */, variable_type /* arg1_type */, 14538 variable_type /* arg2_type */); 14539 14540 break; 14541 14542 case FUNCTION_STEP_AGAINST_SCALAR: 14543 14544 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */, 14545 glw::GLdouble /* Arg2T */>( 14546 function, "step", Math::step, variable_type /* res_type */, scalar_type /* arg1_type */, 14547 variable_type /* arg2_type */); 14548 14549 break; 14550 14551 case FUNCTION_TRANSPOSE: 14552 14553 switch (variable_type) 14554 { 14555 case Utils::VARIABLE_TYPE_DMAT2: 14556 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose", 14557 Math::transpose); 14558 break; 14559 case Utils::VARIABLE_TYPE_DMAT2X3: 14560 return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose", 14561 Math::transpose); 14562 break; 14563 case Utils::VARIABLE_TYPE_DMAT2X4: 14564 return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose", 14565 Math::transpose); 14566 break; 14567 case Utils::VARIABLE_TYPE_DMAT3: 14568 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose", 14569 Math::transpose); 14570 break; 14571 case Utils::VARIABLE_TYPE_DMAT3X2: 14572 return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose", 14573 Math::transpose); 14574 break; 14575 case Utils::VARIABLE_TYPE_DMAT3X4: 14576 return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose", 14577 Math::transpose); 14578 break; 14579 case Utils::VARIABLE_TYPE_DMAT4: 14580 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose", 14581 Math::transpose); 14582 break; 14583 case Utils::VARIABLE_TYPE_DMAT4X2: 14584 return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose", 14585 Math::transpose); 14586 break; 14587 case Utils::VARIABLE_TYPE_DMAT4X3: 14588 return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose", 14589 Math::transpose); 14590 break; 14591 default: 14592 break; 14593 } 14594 14595 break; 14596 14597 case FUNCTION_TRUNC: 14598 14599 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>( 14600 function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */); 14601 14602 break; 14603 14604 case FUNCTION_UNPACKDOUBLE2X32: 14605 14606 return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32", 14607 Math::unpackDouble2x32); 14608 14609 break; 14610 14611 case FUNCTION_ISNAN: 14612 14613 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>( 14614 function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */); 14615 14616 break; 14617 14618 case FUNCTION_ISINF: 14619 14620 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>( 14621 function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */); 14622 14623 break; 14624 14625 default: 14626 TCU_FAIL("Not implemented"); 14627 return 0; 14628 break; 14629 } 14630 14631 TCU_FAIL("Not implemented"); 14632 return 0; 14633 } 14634 14635 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double. 14636 * 14637 * @param argument Argument index 14638 * @param function_object Function object 14639 * 14640 * @return Function pointer 14641 **/ 14642 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat( 14643 glw::GLuint argument, const functionObject& function_object) const 14644 { 14645 const Utils::_variable_type argument_type = function_object.getArgumentType(argument); 14646 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 14647 14648 switch (argument_type) 14649 { 14650 case Utils::VARIABLE_TYPE_DMAT2: 14651 return gl.uniformMatrix2dv; 14652 break; 14653 case Utils::VARIABLE_TYPE_DMAT2X3: 14654 return gl.uniformMatrix2x3dv; 14655 break; 14656 case Utils::VARIABLE_TYPE_DMAT2X4: 14657 return gl.uniformMatrix2x4dv; 14658 break; 14659 case Utils::VARIABLE_TYPE_DMAT3: 14660 return gl.uniformMatrix3dv; 14661 break; 14662 case Utils::VARIABLE_TYPE_DMAT3X2: 14663 return gl.uniformMatrix3x2dv; 14664 break; 14665 case Utils::VARIABLE_TYPE_DMAT3X4: 14666 return gl.uniformMatrix3x4dv; 14667 break; 14668 case Utils::VARIABLE_TYPE_DMAT4: 14669 return gl.uniformMatrix4dv; 14670 break; 14671 case Utils::VARIABLE_TYPE_DMAT4X2: 14672 return gl.uniformMatrix4x2dv; 14673 break; 14674 case Utils::VARIABLE_TYPE_DMAT4X3: 14675 return gl.uniformMatrix4x3dv; 14676 break; 14677 default: 14678 break; 14679 } 14680 14681 TCU_FAIL("Not implemented"); 14682 return 0; 14683 } 14684 14685 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double. 14686 * 14687 * @param argument Argument index 14688 * @param function_object Function object 14689 * 14690 * @return Function pointer 14691 **/ 14692 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec( 14693 glw::GLuint argument, const functionObject& function_object) const 14694 { 14695 const Utils::_variable_type argument_type = function_object.getArgumentType(argument); 14696 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 14697 14698 switch (argument_type) 14699 { 14700 case Utils::VARIABLE_TYPE_DOUBLE: 14701 return gl.uniform1dv; 14702 break; 14703 case Utils::VARIABLE_TYPE_DVEC2: 14704 return gl.uniform2dv; 14705 break; 14706 case Utils::VARIABLE_TYPE_DVEC3: 14707 return gl.uniform3dv; 14708 break; 14709 case Utils::VARIABLE_TYPE_DVEC4: 14710 return gl.uniform4dv; 14711 break; 14712 default: 14713 TCU_FAIL("Not implemented"); 14714 break; 14715 } 14716 14717 return 0; 14718 } 14719 14720 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer. 14721 * 14722 * @param argument Argument index 14723 * @param function_object Function object 14724 * 14725 * @return Function pointer 14726 **/ 14727 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec( 14728 glw::GLuint argument, const functionObject& function_object) const 14729 { 14730 const Utils::_variable_type argument_type = function_object.getArgumentType(argument); 14731 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 14732 14733 switch (argument_type) 14734 { 14735 case Utils::VARIABLE_TYPE_INT: 14736 return gl.uniform1iv; 14737 break; 14738 case Utils::VARIABLE_TYPE_IVEC2: 14739 return gl.uniform2iv; 14740 break; 14741 case Utils::VARIABLE_TYPE_IVEC3: 14742 return gl.uniform3iv; 14743 break; 14744 case Utils::VARIABLE_TYPE_IVEC4: 14745 return gl.uniform4iv; 14746 break; 14747 default: 14748 TCU_FAIL("Not implemented"); 14749 break; 14750 } 14751 14752 return 0; 14753 } 14754 14755 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer. 14756 * 14757 * @param argument Argument index 14758 * @param function_object Function object 14759 * 14760 * @return Function pointer 14761 **/ 14762 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec( 14763 glw::GLuint argument, const functionObject& function_object) const 14764 { 14765 const Utils::_variable_type argument_type = function_object.getArgumentType(argument); 14766 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 14767 14768 switch (argument_type) 14769 { 14770 case Utils::VARIABLE_TYPE_UVEC2: 14771 return gl.uniform2uiv; 14772 break; 14773 default: 14774 TCU_FAIL("Not implemented"); 14775 break; 14776 } 14777 14778 return 0; 14779 } 14780 14781 /** Get name of uniform that will be used as <argument>. 14782 * 14783 * @param argument Argument index 14784 * 14785 * @return Name of uniform 14786 **/ 14787 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const 14788 { 14789 switch (argument) 14790 { 14791 case 0: 14792 return "uniform_0"; 14793 break; 14794 case 1: 14795 return "uniform_1"; 14796 break; 14797 case 2: 14798 return "uniform_2"; 14799 break; 14800 default: 14801 TCU_FAIL("Not implemented"); 14802 return 0; 14803 break; 14804 } 14805 } 14806 14807 /** Get name of varying that will be used as <result>. 14808 * 14809 * @param result Result index 14810 * 14811 * @return Name of varying 14812 **/ 14813 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const 14814 { 14815 switch (result) 14816 { 14817 case 0: 14818 return "result_0"; 14819 break; 14820 case 1: 14821 return "result_1"; 14822 break; 14823 case 2: 14824 return "result_2"; 14825 break; 14826 default: 14827 TCU_FAIL("Not implemented"); 14828 return 0; 14829 break; 14830 } 14831 } 14832 14833 /** Check if given combination of function and type is implemented 14834 * 14835 * @param function Function enumeration 14836 * @param type Type details 14837 * 14838 * @return true if function is available for given type, false otherwise 14839 **/ 14840 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const 14841 { 14842 static const bool look_up_table[][3] = { 14843 /* SCALAR, VECTOR, MATRIX */ 14844 /* FUNCTION_ABS: */ { true, true, false }, 14845 /* FUNCTION_CEIL: */ { true, true, false }, 14846 /* FUNCTION_CLAMP: */ { true, true, false }, 14847 /* FUNCTION_CLAMP_AGAINST_SCALAR: */ { false, true, false }, 14848 /* FUNCTION_CROSS: */ { false, true, false }, 14849 /* FUNCTION_DETERMINANT: */ { false, false, true }, 14850 /* FUNCTION_DISTANCE: */ { false, true, false }, 14851 /* FUNCTION_DOT: */ { false, true, false }, 14852 /* FUNCTION_EQUAL: */ { false, true, false }, 14853 /* FUNCTION_FACEFORWARD: */ { false, true, false }, 14854 /* FUNCTION_FLOOR: */ { true, true, false }, 14855 /* FUNCTION_FMA: */ { true, true, false }, 14856 /* FUNCTION_FRACT: */ { true, true, false }, 14857 /* FUNCTION_FREXP: */ { true, true, false }, 14858 /* FUNCTION_GREATERTHAN: */ { false, true, false }, 14859 /* FUNCTION_GREATERTHANEQUAL: */ { false, true, false }, 14860 /* FUNCTION_INVERSE: */ { false, false, true }, 14861 /* FUNCTION_INVERSESQRT: */ { true, true, false }, 14862 /* FUNCTION_LDEXP: */ { true, true, false }, 14863 /* FUNCTION_LESSTHAN: */ { false, true, false }, 14864 /* FUNCTION_LESSTHANEQUAL: */ { false, true, false }, 14865 /* FUNCTION_LENGTH: */ { false, true, false }, 14866 /* FUNCTION_MATRIXCOMPMULT: */ { false, false, true }, 14867 /* FUNCTION_MAX: */ { true, true, false }, 14868 /* FUNCTION_MAX_AGAINST_SCALAR: */ { false, true, false }, 14869 /* FUNCTION_MIN: */ { true, true, false }, 14870 /* FUNCTION_MIN_AGAINST_SCALAR: */ { false, true, false }, 14871 /* FUNCTION_MIX: */ { true, true, false }, 14872 /* FUNCTION_MOD: */ { true, true, false }, 14873 /* FUNCTION_MOD_AGAINST_SCALAR: */ { false, true, false }, 14874 /* FUNCTION_MODF: */ { true, true, false }, 14875 /* FUNCTION_NORMALIZE: */ { false, true, false }, 14876 /* FUNCTION_NOTEQUAL: */ { false, true, false }, 14877 /* FUNCTION_OUTERPRODUCT: */ { false, false, true }, 14878 /* FUNCTION_PACKDOUBLE2X32: */ { true, false, false }, 14879 /* FUNCTION_REFLECT: */ { false, true, false }, 14880 /* FUNCTION_REFRACT: */ { false, true, false }, 14881 /* FUNCTION_ROUND: */ { true, true, false }, 14882 /* FUNCTION_ROUNDEVEN: */ { true, true, false }, 14883 /* FUNCTION_SIGN: */ { true, false, false }, 14884 /* FUNCTION_SMOOTHSTEP: */ { true, true, false }, 14885 /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false }, 14886 /* FUNCTION_SQRT: */ { true, true, false }, 14887 /* FUNCTION_STEP: */ { true, true, false }, 14888 /* FUNCTION_STEP_AGAINST_SCALAR: */ { false, true, false }, 14889 /* FUNCTION_TRANSPOSE: */ { false, false, false }, 14890 /* FUNCTION_TRUNC: */ { true, true, false }, 14891 /* FUNCTION_UNPACKDOUBLE2X32: */ { true, false, false }, 14892 /* FUNCTION_ISNAN: */ { true, true, false }, 14893 /* FUNCTION_ISINF: */ { true, true, false }, 14894 }; 14895 14896 bool result = look_up_table[function][type.m_general_type]; 14897 14898 if (true == result) 14899 { 14900 switch (function) 14901 { 14902 case FUNCTION_CROSS: /* Only 3 element vectors */ 14903 result = (3 == type.m_n_rows); 14904 break; 14905 case FUNCTION_DETERMINANT: /* Only square matrices */ 14906 case FUNCTION_INVERSE: 14907 result = (type.m_n_columns == type.m_n_rows); 14908 break; 14909 default: 14910 break; 14911 } 14912 } 14913 14914 return result; 14915 } 14916 14917 /** Logs variable of given type: name (type) [values] 14918 * 14919 * @param buffer Source of data 14920 * @param name Name of variable 14921 * @param type Type of variable 14922 **/ 14923 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, 14924 Utils::_variable_type type) const 14925 { 14926 const Utils::_variable_type base_type = Utils::getBaseVariableType(type); 14927 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type); 14928 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; 14929 14930 message << name << " (" << Utils::getVariableTypeString(type) << ") ["; 14931 14932 for (glw::GLuint component = 0; component < n_components; ++component) 14933 { 14934 if (0 != component) 14935 { 14936 message << ", "; 14937 } 14938 14939 switch (base_type) 14940 { 14941 case Utils::VARIABLE_TYPE_DOUBLE: 14942 message << ((glw::GLdouble*)buffer)[component]; 14943 break; 14944 case Utils::VARIABLE_TYPE_INT: 14945 message << ((glw::GLint*)buffer)[component]; 14946 break; 14947 case Utils::VARIABLE_TYPE_UINT: 14948 message << ((glw::GLuint*)buffer)[component]; 14949 break; 14950 default: 14951 TCU_FAIL("Not implemented"); 14952 } 14953 } 14954 14955 message << "]" << tcu::TestLog::EndMessage; 14956 } 14957 14958 /** Prepare input arguments, data are stored in <buffer> 14959 * 14960 * @param function_object Function object 14961 * @param vertex Vertex index 14962 * @param buffer Buffer pointer 14963 **/ 14964 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex, 14965 glw::GLubyte* buffer) 14966 { 14967 const glw::GLuint n_arguments = function_object.getArgumentCount(); 14968 14969 for (glw::GLuint argument = 0; argument < n_arguments; ++argument) 14970 { 14971 const glw::GLuint offset = function_object.getArgumentOffset(argument); 14972 14973 prepareComponents(function_object, vertex, argument, buffer + offset); 14974 } 14975 } 14976 14977 /** Prepare components for given <function_object>, <vertex> and <argument> 14978 * 14979 * @param function_object Function object 14980 * @param vertex Vertex index 14981 * @param argument Argument index 14982 * @param buffer Buffer pointer 14983 **/ 14984 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex, 14985 glw::GLuint argument, glw::GLubyte* buffer) 14986 { 14987 glw::GLuint argument_index[3] = { 0 }; 14988 glw::GLuint argument_reset[3] = { 0 }; 14989 glw::GLuint argument_step[3] = { 0 }; 14990 glw::GLdouble double_argument_start[3] = { 0.0 }; 14991 const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument)); 14992 glw::GLuint int_argument_start = -4; 14993 const glw::GLuint n_arguments = function_object.getArgumentCount(); 14994 const glw::GLuint n_components = function_object.getArgumentComponents(argument); 14995 glw::GLuint uint_argument_start = 0; 14996 14997 switch (n_arguments) 14998 { 14999 case 1: 15000 argument_step[0] = 1; 15001 argument_reset[0] = 1024; 15002 double_argument_start[0] = -511.5; 15003 break; 15004 case 2: 15005 argument_step[0] = 32; 15006 argument_step[1] = 1; 15007 argument_reset[0] = 32; 15008 argument_reset[1] = 32; 15009 double_argument_start[0] = -15.5; 15010 double_argument_start[1] = -15.5; 15011 break; 15012 case 3: 15013 argument_step[0] = 64; 15014 argument_step[1] = 8; 15015 argument_step[2] = 1; 15016 argument_reset[0] = 16; 15017 argument_reset[1] = 8; 15018 argument_reset[2] = 8; 15019 double_argument_start[0] = -7.5; 15020 double_argument_start[1] = -3.5; 15021 double_argument_start[2] = -3.5; 15022 break; 15023 default: 15024 TCU_FAIL("Not implemented"); 15025 return; 15026 break; 15027 }; 15028 15029 switch (function_object.getFunctionEnum()) 15030 { 15031 case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */ 15032 case FUNCTION_CLAMP_AGAINST_SCALAR: 15033 double_argument_start[2] = 4.5; 15034 break; 15035 case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */ 15036 double_argument_start[0] = 16.5; 15037 break; 15038 case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */ 15039 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: 15040 argument_step[0] = 1; 15041 argument_step[1] = 8; 15042 argument_step[2] = 64; 15043 argument_reset[0] = 8; 15044 argument_reset[1] = 8; 15045 argument_reset[2] = 16; 15046 double_argument_start[0] = -3.5; 15047 double_argument_start[1] = 4.5; 15048 double_argument_start[2] = -7.5; 15049 break; 15050 default: 15051 break; 15052 } 15053 15054 for (glw::GLuint i = 0; i < n_arguments; ++i) 15055 { 15056 argument_index[i] = (vertex / argument_step[i]) % argument_reset[i]; 15057 } 15058 15059 switch (base_arg_type) 15060 { 15061 case Utils::VARIABLE_TYPE_DOUBLE: 15062 { 15063 glw::GLdouble* argument_dst = (glw::GLdouble*)buffer; 15064 15065 double_argument_start[argument] += argument_index[argument]; 15066 15067 for (glw::GLuint component = 0; component < n_components; ++component) 15068 { 15069 glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0; 15070 15071 switch (function_object.getFunctionEnum()) 15072 { 15073 case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */ 15074 if (0.5 == Math::fract(value)) 15075 { 15076 value += 0.01; 15077 } 15078 break; 15079 default: 15080 break; 15081 } 15082 15083 argument_dst[component] = value; 15084 } 15085 } 15086 break; 15087 case Utils::VARIABLE_TYPE_INT: 15088 { 15089 glw::GLint* argument_dst = (glw::GLint*)buffer; 15090 15091 uint_argument_start += argument_index[argument]; 15092 15093 for (glw::GLuint component = 0; component < n_components; ++component) 15094 { 15095 const glw::GLint value = int_argument_start + component; 15096 15097 argument_dst[component] = value; 15098 } 15099 } 15100 break; 15101 case Utils::VARIABLE_TYPE_UINT: 15102 { 15103 glw::GLuint* argument_dst = (glw::GLuint*)buffer; 15104 15105 uint_argument_start += argument_index[argument]; 15106 15107 for (glw::GLuint component = 0; component < n_components; ++component) 15108 { 15109 const glw::GLuint value = uint_argument_start + component; 15110 15111 argument_dst[component] = value; 15112 } 15113 } 15114 break; 15115 default: 15116 TCU_FAIL("Not implemented"); 15117 return; 15118 break; 15119 } 15120 } 15121 15122 /** Prepare programInfo for given functionObject 15123 * 15124 * @param function_object Function object 15125 * @param out_program_info Program info 15126 **/ 15127 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info) 15128 { 15129 const glw::GLuint n_varying_names = function_object.getResultCount(); 15130 static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) }; 15131 15132 prepareVertexShaderCode(function_object); 15133 15134 out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(), 15135 varying_names, n_varying_names); 15136 } 15137 15138 /** Prepare input data and expected results for given function object 15139 * 15140 * @param function_object Function object 15141 **/ 15142 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object) 15143 { 15144 const glw::GLuint result_stride = function_object.getResultStride(); 15145 const glw::GLuint result_buffer_size = result_stride * m_n_veritces; 15146 const glw::GLuint argument_stride = function_object.getArgumentStride(); 15147 const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride; 15148 15149 m_argument_data.clear(); 15150 m_expected_results_data.clear(); 15151 15152 m_argument_data.resize(argument_buffer_size); 15153 m_expected_results_data.resize(result_buffer_size); 15154 15155 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex) 15156 { 15157 const glw::GLuint result_offset = vertex * result_stride; 15158 glw::GLdouble* result_dst = (glw::GLdouble*)&m_expected_results_data[result_offset]; 15159 const glw::GLuint argument_offset = vertex * argument_stride; 15160 glw::GLubyte* argument_dst = &m_argument_data[argument_offset]; 15161 15162 prepareArgument(function_object, vertex, argument_dst); 15163 function_object.call(result_dst, argument_dst); 15164 } 15165 } 15166 15167 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code. 15168 * 15169 * @param function_object Function object 15170 **/ 15171 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object) 15172 { 15173 static const glw::GLchar* shader_template_code = "#version 400 core\n" 15174 "\n" 15175 "precision highp float;\n" 15176 "\n" 15177 "ARGUMENT_DEFINITION" 15178 "\n" 15179 "RESULT_DEFINITION" 15180 "\n" 15181 "void main()\n" 15182 "{\n" 15183 " RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n" 15184 "}\n" 15185 "\n"; 15186 15187 static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION"; 15188 static const glw::GLchar* argument_token = "ARGUMENT"; 15189 static const glw::GLchar* function_name_token = "FUNCTION_NAME"; 15190 static const glw::GLchar* result_definition_token = "RESULT_DEFINITION"; 15191 static const glw::GLchar* result_name_token = "RESULT_NAME"; 15192 static const glw::GLchar* result_type_token = "RESULT_TYPE"; 15193 static const glw::GLchar* uniform_name_token = "UNIFORM_NAME"; 15194 static const glw::GLchar* uniform_type_token = "UNIFORM_TYPE"; 15195 15196 static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION"; 15197 static const glw::GLchar* argument_str = ", UNIFORM_NAMEARGUMENT"; 15198 static const glw::GLchar* first_argument = "UNIFORM_NAMEARGUMENT"; 15199 static const glw::GLchar* result_definition = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION"; 15200 15201 const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition); 15202 const glw::GLuint first_argument_length = (glw::GLuint)strlen(first_argument); 15203 const glw::GLuint n_arguments = function_object.getArgumentCount(); 15204 const glw::GLuint n_results = function_object.getResultCount(); 15205 const glw::GLuint result_definition_length = (glw::GLuint)strlen(result_definition); 15206 std::string result_type = Utils::getVariableTypeString(function_object.getResultType(0)); 15207 15208 size_t search_position = 0; 15209 std::string string = shader_template_code; 15210 15211 /* Replace ARGUMENT_DEFINITION with definitions */ 15212 for (glw::GLuint argument = 0; argument < n_arguments; ++argument) 15213 { 15214 Utils::_variable_type argument_type = function_object.getArgumentType(argument); 15215 const glw::GLchar* uniform_name = getUniformName(argument); 15216 std::string uniform_type = Utils::getVariableTypeString(argument_type); 15217 15218 Utils::replaceToken(argument_definition_token, search_position, argument_definition, string); 15219 15220 search_position -= argument_definition_length; 15221 15222 Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string); 15223 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string); 15224 } 15225 15226 /* Remove ARGUMENT_DEFINITION */ 15227 Utils::replaceToken(argument_definition_token, search_position, "", string); 15228 15229 /* Replace RESULT_DEFINITION with definitions */ 15230 for (glw::GLuint result = 0; result < n_results; ++result) 15231 { 15232 Utils::_variable_type variable_type = function_object.getResultType(result); 15233 const glw::GLchar* varying_name = getVaryingName(result); 15234 std::string varying_type = Utils::getVariableTypeString(variable_type); 15235 15236 Utils::replaceToken(result_definition_token, search_position, result_definition, string); 15237 15238 search_position -= result_definition_length; 15239 15240 Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string); 15241 Utils::replaceToken(result_name_token, search_position, varying_name, string); 15242 } 15243 15244 /* Remove RESULT_DEFINITION */ 15245 Utils::replaceToken(result_definition_token, search_position, "", string); 15246 15247 /* Replace RESULT_NAME */ 15248 Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string); 15249 15250 /* Replace RESULT_TYPE */ 15251 Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string); 15252 15253 /* Replace FUNCTION_NAME */ 15254 Utils::replaceToken(function_name_token, search_position, function_object.getName(), string); 15255 15256 /* Replace ARGUMENT with list of arguments */ 15257 for (glw::GLuint argument = 0; argument < n_arguments; ++argument) 15258 { 15259 const glw::GLchar* uniform_name = getUniformName(argument); 15260 15261 if (0 == argument) 15262 { 15263 Utils::replaceToken(argument_token, search_position, first_argument, string); 15264 } 15265 else 15266 { 15267 Utils::replaceToken(argument_token, search_position, argument_str, string); 15268 } 15269 15270 search_position -= first_argument_length; 15271 15272 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string); 15273 } 15274 15275 for (glw::GLuint result = 1; result < n_results; ++result) 15276 { 15277 const glw::GLchar* varying_name = getVaryingName(result); 15278 15279 Utils::replaceToken(argument_token, search_position, argument_str, string); 15280 15281 search_position -= first_argument_length; 15282 15283 Utils::replaceToken(uniform_name_token, search_position, varying_name, string); 15284 } 15285 15286 /* Remove ARGUMENT */ 15287 Utils::replaceToken(argument_token, search_position, "", string); 15288 15289 m_vertex_shader_code = string; 15290 } 15291 15292 /** Test single function with one type 15293 * 15294 * param function Function enumeration 15295 * param type Type details 15296 * 15297 * @return true if test pass (or function is not available for <type>), false otherwise 15298 **/ 15299 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type) 15300 { 15301 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 15302 15303 /* Skip if function is not implemented for type */ 15304 if (false == isFunctionImplemented(function, type)) 15305 { 15306 return true; 15307 } 15308 15309 Utils::programInfo program(m_context); 15310 de::UniquePtr<functionObject> function_object(getFunctionObject(function, type)); 15311 15312 prepareProgram(*function_object, program); 15313 prepareTestData(*function_object); 15314 15315 /* Set up program */ 15316 gl.useProgram(program.m_program_object_id); 15317 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); 15318 15319 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex) 15320 { 15321 testBegin(*function_object, program.m_program_object_id, vertex); 15322 15323 gl.beginTransformFeedback(GL_POINTS); 15324 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback"); 15325 15326 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 15327 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); 15328 15329 gl.endTransformFeedback(); 15330 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback"); 15331 15332 if (false == verifyResults(*function_object, vertex)) 15333 { 15334 return false; 15335 } 15336 } 15337 15338 return true; 15339 } 15340 15341 /** Update transform feedback buffer and uniforms 15342 * 15343 * @param function_object Function object 15344 * @param program_id Program object id 15345 * @param vertex Vertex index 15346 **/ 15347 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex) 15348 { 15349 const glw::GLuint arguments_stride = function_object.getArgumentStride(); 15350 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 15351 const glw::GLuint n_arguments = function_object.getArgumentCount(); 15352 const glw::GLuint result_buffer_size = function_object.getResultStride(); 15353 const glw::GLuint vertex_offset = arguments_stride * vertex; 15354 15355 /* Update transform feedback buffer */ 15356 std::vector<glw::GLubyte> transform_feedback_buffer_data; 15357 transform_feedback_buffer_data.resize(result_buffer_size); 15358 15359 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id); 15360 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 15361 15362 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0], 15363 GL_DYNAMIC_COPY); 15364 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData"); 15365 15366 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */, 15367 result_buffer_size); 15368 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange"); 15369 15370 /* Update VAO */ 15371 gl.bindVertexArray(m_vertex_array_object_id); 15372 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray"); 15373 15374 for (glw::GLuint argument = 0; argument < n_arguments; ++argument) 15375 { 15376 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument); 15377 const Utils::_variable_type argument_type = function_object.getArgumentType(argument); 15378 const glw::GLuint n_columns = Utils::getNumberOfColumnsForVariableType(argument_type); 15379 const glw::GLchar* uniform_name = getUniformName(argument); 15380 const glw::GLint uniform_location = gl.getUniformLocation(program_id, uniform_name); 15381 const glw::GLdouble* uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset]; 15382 15383 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation"); 15384 15385 if (-1 == uniform_location) 15386 { 15387 TCU_FAIL("Inactive uniform"); 15388 } 15389 15390 if (1 == n_columns) 15391 { 15392 switch (Utils::getBaseVariableType(argument_type)) 15393 { 15394 case Utils::VARIABLE_TYPE_DOUBLE: 15395 { 15396 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object); 15397 15398 p_uniform_function(uniform_location, 1 /* count */, uniform_src); 15399 } 15400 break; 15401 case Utils::VARIABLE_TYPE_UINT: 15402 { 15403 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object); 15404 15405 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src); 15406 } 15407 break; 15408 case Utils::VARIABLE_TYPE_INT: 15409 { 15410 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object); 15411 15412 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src); 15413 } 15414 break; 15415 default: 15416 TCU_FAIL("Not implemented"); 15417 break; 15418 } 15419 } 15420 else 15421 { 15422 uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object); 15423 15424 p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src); 15425 } 15426 } 15427 } 15428 15429 /** Init GL obejcts 15430 * 15431 **/ 15432 void BuiltinFunctionTest::testInit() 15433 { 15434 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 15435 15436 gl.genBuffers(1, &m_transform_feedback_buffer_id); 15437 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 15438 15439 gl.genVertexArrays(1, &m_vertex_array_object_id); 15440 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); 15441 15442 gl.enable(GL_RASTERIZER_DISCARD); 15443 } 15444 15445 /** Checks if function result is an acceptable edge case 15446 * 15447 * @param function_object Function object 15448 * @param vertex Vertex index 15449 * 15450 * @return true if all results are as expected, false otherwise 15451 **/ 15452 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex, 15453 const Utils::_variable_type result_type, 15454 const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src) 15455 { 15456 FunctionEnum function_type = function_object.getFunctionEnum(); 15457 switch (function_type) 15458 { 15459 // mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL 15460 // allows for some error in division, so a/a could actually end up being 1.0 - 1ULP. 15461 // In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a. 15462 case FUNCTION_MOD: 15463 case FUNCTION_MOD_AGAINST_SCALAR: 15464 { 15465 const glw::GLuint arguments_stride = function_object.getArgumentStride(); 15466 const glw::GLuint vertex_offset = arguments_stride * vertex; 15467 const glw::GLuint argument_1_offset = function_object.getArgumentOffset(0); 15468 const glw::GLuint argument_2_offset = function_object.getArgumentOffset(1); 15469 const glw::GLuint argument_1_index = argument_1_offset + vertex_offset; 15470 const glw::GLuint argument_2_index = argument_2_offset + vertex_offset; 15471 const glw::GLubyte* argument_1_bytes = &m_argument_data[argument_1_index]; 15472 const glw::GLubyte* argument_2_bytes = &m_argument_data[argument_2_index]; 15473 const glw::GLdouble* argument_1 = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes); 15474 const glw::GLdouble* argument_2 = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes); 15475 const glw::GLdouble* expected_result = reinterpret_cast<const glw::GLdouble*>(expected_result_src); 15476 const glw::GLdouble* actual_result = reinterpret_cast<const glw::GLdouble*>(result_src); 15477 bool edge_case_present = false; 15478 bool recheck = false; 15479 15480 // verify if there is a mod(a, a) case and prepare new expected result 15481 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(result_type); 15482 std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0); 15483 for (glw::GLuint component = 0; component < n_components; ++component) 15484 { 15485 glw::GLdouble expected_result_component = expected_result[component]; 15486 glw::GLdouble actual_result_component = actual_result[component]; 15487 glw::GLdouble argument_1_component = argument_1[component]; 15488 glw::GLdouble argument_2_component = argument_2[(function_type == FUNCTION_MOD) ? component : 0]; 15489 15490 // if coresponding components of arguments are equal and if component of first argument 15491 // and component of result are equal then expected result must be corrected 15492 edge_case_present = (m_epsilon > de::abs(argument_1_component - argument_2_component)) && 15493 (m_epsilon > de::abs(argument_1_component - actual_result_component)); 15494 recheck |= edge_case_present; 15495 corrected_expected_result[component] = edge_case_present ? argument_1_component : expected_result_component; 15496 } 15497 15498 // recheck test result with corrected expected result 15499 return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src)); 15500 } 15501 default: 15502 return false; 15503 } 15504 } 15505 15506 /** Compare contents of transform feedback buffer with expected results 15507 * 15508 * @param function_object Function object 15509 * @param vertex Vertex index 15510 * 15511 * @return true if all results are as expected, false otherwise 15512 **/ 15513 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex) 15514 { 15515 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 15516 bool test_result = true; 15517 const glw::GLuint n_results = function_object.getResultCount(); 15518 const glw::GLuint results_stride = function_object.getResultStride(); 15519 const glw::GLuint results_offset = vertex * results_stride; 15520 const glw::GLubyte* expected_results = &m_expected_results_data[results_offset]; 15521 15522 /* Get transform feedback data */ 15523 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id); 15524 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); 15525 15526 glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 15527 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); 15528 15529 for (glw::GLuint result = 0; result < n_results; ++result) 15530 { 15531 const Utils::_variable_type result_type = function_object.getResultType(result); 15532 const glw::GLuint result_offset = function_object.getResultOffset(result); 15533 15534 const glw::GLvoid* expected_result_src = expected_results + result_offset; 15535 const glw::GLvoid* result_src = feedback_data + result_offset; 15536 15537 if (compare(result_type, expected_result_src, result_src)) 15538 continue; 15539 15540 if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src)) 15541 { 15542 test_result = false; 15543 break; 15544 } 15545 } 15546 15547 /* Unmap transform feedback buffer */ 15548 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 15549 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); 15550 15551 if (false == test_result) 15552 { 15553 const glw::GLuint argument_stride = function_object.getArgumentStride(); 15554 const glw::GLuint arguments_offset = vertex * argument_stride; 15555 15556 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result." 15557 << tcu::TestLog::EndMessage; 15558 15559 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName() 15560 << tcu::TestLog::EndMessage; 15561 15562 for (glw::GLuint result = 0; result < n_results; ++result) 15563 { 15564 const Utils::_variable_type result_type = function_object.getResultType(result); 15565 const glw::GLuint result_offset = function_object.getResultOffset(result); 15566 15567 const glw::GLvoid* expected_result_src = expected_results + result_offset; 15568 const glw::GLvoid* result_src = feedback_data + result_offset; 15569 15570 logVariableType(result_src, "Result", result_type); 15571 logVariableType(expected_result_src, "Expected result", result_type); 15572 } 15573 15574 for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument) 15575 { 15576 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument); 15577 const glw::GLubyte* argument_src = &m_argument_data[arguments_offset + argument_offset]; 15578 15579 logVariableType(argument_src, "Argument", function_object.getArgumentType(argument)); 15580 } 15581 15582 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n" 15583 << m_vertex_shader_code << tcu::TestLog::EndMessage; 15584 } 15585 15586 return test_result; 15587 } 15588 15589 /** Constructor. 15590 * 15591 * @param context Rendering context. 15592 **/ 15593 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context) 15594 : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality") 15595 { 15596 /* Left blank on purpose */ 15597 } 15598 15599 /** Initializes a texture_storage_multisample test group. 15600 * 15601 **/ 15602 void GPUShaderFP64Tests::init(void) 15603 { 15604 TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", ""); 15605 fp64->addChild(new GPUShaderFP64Test1(m_context)); 15606 fp64->addChild(new GPUShaderFP64Test2(m_context)); 15607 fp64->addChild(new GPUShaderFP64Test3(m_context)); 15608 fp64->addChild(new GPUShaderFP64Test4(m_context)); 15609 fp64->addChild(new GPUShaderFP64Test5(m_context)); 15610 fp64->addChild(new GPUShaderFP64Test6(m_context)); 15611 fp64->addChild(new GPUShaderFP64Test7(m_context)); 15612 fp64->addChild(new GPUShaderFP64Test8(m_context)); 15613 fp64->addChild(new GPUShaderFP64Test9(m_context)); 15614 addChild(fp64); 15615 15616 TypeDefinition typeDefinition[] = 15617 { 15618 { "double", 1, 1 }, 15619 { "dvec2", 1, 2 }, 15620 { "dvec3", 1, 3 }, 15621 { "dvec4", 1, 4 }, 15622 { "dmat2", 2, 2 }, 15623 { "dmat2x3", 2, 3 }, 15624 { "dmat2x4", 2, 4 }, 15625 { "dmat3x2", 3, 2 }, 15626 { "dmat3", 3, 3 }, 15627 { "dmat3x4", 3, 4 }, 15628 { "dmat4x2", 4, 2 }, 15629 { "dmat4x3", 4, 3 }, 15630 { "dmat4", 4, 4 } 15631 }; 15632 15633 struct BuiltinFunctions 15634 { 15635 std::string name; 15636 FunctionEnum function; 15637 } builtinFunctions[] = { 15638 { "abs", FUNCTION_ABS }, 15639 { "ceil", FUNCTION_CEIL }, 15640 { "clamp", FUNCTION_CLAMP }, 15641 { "clamp_against_scalar", FUNCTION_CLAMP_AGAINST_SCALAR }, 15642 { "cross", FUNCTION_CROSS }, 15643 { "determinant", FUNCTION_DETERMINANT }, 15644 { "distance", FUNCTION_DISTANCE }, 15645 { "dot", FUNCTION_DOT }, 15646 { "equal", FUNCTION_EQUAL }, 15647 { "faceforward", FUNCTION_FACEFORWARD }, 15648 { "floor", FUNCTION_FLOOR }, 15649 { "fma", FUNCTION_FMA }, 15650 { "fract", FUNCTION_FRACT }, 15651 { "frexp", FUNCTION_FREXP }, 15652 { "greaterthan", FUNCTION_GREATERTHAN }, 15653 { "greaterthanequal", FUNCTION_GREATERTHANEQUAL }, 15654 { "inverse", FUNCTION_INVERSE }, 15655 { "inversesqrt", FUNCTION_INVERSESQRT }, 15656 { "ldexp", FUNCTION_LDEXP }, 15657 { "lessthan", FUNCTION_LESSTHAN }, 15658 { "lessthanequal", FUNCTION_LESSTHANEQUAL }, 15659 { "length", FUNCTION_LENGTH }, 15660 { "matrixcompmult", FUNCTION_MATRIXCOMPMULT }, 15661 { "max", FUNCTION_MAX }, 15662 { "max_against_scalar", FUNCTION_MAX_AGAINST_SCALAR }, 15663 { "min", FUNCTION_MIN }, 15664 { "min_against_scalar", FUNCTION_MIN_AGAINST_SCALAR }, 15665 { "mix", FUNCTION_MIX }, 15666 { "mod", FUNCTION_MOD }, 15667 { "mod_against_scalar", FUNCTION_MOD_AGAINST_SCALAR }, 15668 { "modf", FUNCTION_MODF }, 15669 { "normalize", FUNCTION_NORMALIZE }, 15670 { "notequal", FUNCTION_NOTEQUAL }, 15671 { "outerproduct", FUNCTION_OUTERPRODUCT }, 15672 { "packdouble2x32", FUNCTION_PACKDOUBLE2X32 }, 15673 { "reflect", FUNCTION_REFLECT }, 15674 { "refract", FUNCTION_REFRACT }, 15675 { "round", FUNCTION_ROUND }, 15676 { "roundeven", FUNCTION_ROUNDEVEN }, 15677 { "sign", FUNCTION_SIGN }, 15678 { "smoothstep", FUNCTION_SMOOTHSTEP }, 15679 { "smoothstep_against_scalar", FUNCTION_SMOOTHSTEP_AGAINST_SCALAR }, 15680 { "sqrt", FUNCTION_SQRT }, 15681 { "step", FUNCTION_STEP }, 15682 { "step_against_scalar", FUNCTION_STEP_AGAINST_SCALAR }, 15683 { "transpose", FUNCTION_TRANSPOSE }, 15684 { "trunc", FUNCTION_TRUNC }, 15685 { "unpackdouble2x32", FUNCTION_UNPACKDOUBLE2X32 }, 15686 { "isnan", FUNCTION_ISNAN }, 15687 { "isinf", FUNCTION_ISINF } 15688 }; 15689 15690 TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", ""); 15691 for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i) 15692 { 15693 const BuiltinFunctions& bf = builtinFunctions[i]; 15694 for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j) 15695 { 15696 std::string caseName = bf.name + "_" + typeDefinition[j].name; 15697 builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j])); 15698 } 15699 } 15700 addChild(builin); 15701 } 15702 15703 } /* glcts namespace */ 15704