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 #include "esextcGeometryShaderRendering.hpp" 25 26 #include "gluContextInfo.hpp" 27 #include "gluDefs.hpp" 28 #include "glwEnums.hpp" 29 #include "glwFunctions.hpp" 30 #include "tcuTestLog.hpp" 31 #include <cmath> 32 #include <cstdlib> 33 #include <cstring> 34 35 namespace glcts 36 { 37 38 /** Constructor of the geometry shader test base class. 39 * 40 * @param context Rendering context 41 * @param name Name of the test 42 * @param description Description of the test 43 **/ 44 GeometryShaderRendering::GeometryShaderRendering(Context& context, const ExtParameters& extParams, const char* name, 45 const char* description) 46 : TestCaseGroupBase(context, extParams, name, description) 47 { 48 /* Left blank intentionally */ 49 } 50 51 /** Retrieves test name for specific <input layout qualifier, 52 * output layout qualifier, draw call mode> combination. 53 * 54 * @param input Input layout qualifier. 55 * @param output_type Output layout qualifier. 56 * @param drawcall_mode Draw call mode. 57 * 58 * NOTE: This function throws TestError exception if the requested combination 59 * is considered invalid. 60 * 61 * @return Requested string. 62 **/ 63 const char* GeometryShaderRendering::getTestName(_shader_input input, _shader_output_type output_type, 64 glw::GLenum drawcall_mode) 65 { 66 const char* result = NULL; 67 68 switch (input) 69 { 70 case SHADER_INPUT_POINTS: 71 { 72 switch (output_type) 73 { 74 case SHADER_OUTPUT_TYPE_LINE_STRIP: 75 result = "points_input_line_strip_output"; 76 break; 77 case SHADER_OUTPUT_TYPE_POINTS: 78 result = "points_input_points_output"; 79 break; 80 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 81 result = "points_input_triangles_output"; 82 break; 83 84 default: 85 { 86 TCU_FAIL("Unrecognized shader output type requested"); 87 } 88 } /* switch (output_type) */ 89 90 break; 91 } 92 93 case SHADER_INPUT_LINES: 94 { 95 switch (output_type) 96 { 97 case SHADER_OUTPUT_TYPE_LINE_STRIP: 98 { 99 switch (drawcall_mode) 100 { 101 case GL_LINES: 102 result = "lines_input_line_strip_output_lines_drawcall"; 103 break; 104 case GL_LINE_STRIP: 105 result = "lines_input_line_strip_output_line_strip_drawcall"; 106 break; 107 case GL_LINE_LOOP: 108 result = "lines_input_line_strip_output_line_loop_drawcall"; 109 break; 110 111 default: 112 { 113 TCU_FAIL("UNrecognized draw call mode"); 114 } 115 } /* switch (drawcall_mode) */ 116 117 break; 118 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */ 119 120 case SHADER_OUTPUT_TYPE_POINTS: 121 { 122 switch (drawcall_mode) 123 { 124 case GL_LINES: 125 result = "lines_input_points_output_lines_drawcall"; 126 break; 127 case GL_LINE_STRIP: 128 result = "lines_input_points_output_line_strip_drawcall"; 129 break; 130 case GL_LINE_LOOP: 131 result = "lines_input_points_output_line_loop_drawcall"; 132 break; 133 134 default: 135 { 136 TCU_FAIL("UNrecognized draw call mode"); 137 } 138 } /* switch (drawcall_mode) */ 139 140 break; 141 } /* case SHADER_OUTPUT_TYPE_POINTS: */ 142 143 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 144 { 145 switch (drawcall_mode) 146 { 147 case GL_LINES: 148 result = "lines_input_triangle_strip_output_lines_drawcall"; 149 break; 150 case GL_LINE_STRIP: 151 result = "lines_input_triangle_strip_output_line_strip_drawcall"; 152 break; 153 case GL_LINE_LOOP: 154 result = "lines_input_triangle_strip_output_line_loop_drawcall"; 155 break; 156 157 default: 158 { 159 TCU_FAIL("UNrecognized draw call mode"); 160 } 161 } /* switch (drawcall_mode) */ 162 163 break; 164 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */ 165 166 default: 167 { 168 TCU_FAIL("Unrecognized shader output type requested"); 169 } 170 } /* switch (output_type) */ 171 172 break; 173 } /* case SHADER_INPUT_LINES:*/ 174 175 case SHADER_INPUT_LINES_WITH_ADJACENCY: 176 { 177 switch (output_type) 178 { 179 case SHADER_OUTPUT_TYPE_LINE_STRIP: 180 { 181 if ((drawcall_mode == GL_LINES_ADJACENCY_EXT) || (drawcall_mode == GL_LINES_ADJACENCY)) 182 { 183 result = "lines_with_adjacency_input_line_strip_output_lines_adjacency_drawcall"; 184 } 185 else if ((drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) || (drawcall_mode == GL_LINE_STRIP_ADJACENCY)) 186 { 187 result = "lines_with_adjacency_input_line_strip_output_line_strip_drawcall"; 188 } 189 else 190 { 191 TCU_FAIL("Unrecognized draw call mode"); 192 } 193 194 break; 195 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */ 196 197 case SHADER_OUTPUT_TYPE_POINTS: 198 { 199 if ((drawcall_mode == GL_LINES_ADJACENCY_EXT) || (drawcall_mode == GL_LINES_ADJACENCY)) 200 { 201 result = "lines_with_adjacency_input_points_output_lines_adjacency_drawcall"; 202 } 203 else if ((drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) || (drawcall_mode == GL_LINE_STRIP_ADJACENCY)) 204 { 205 result = "lines_with_adjacency_input_points_output_line_strip_drawcall"; 206 } 207 else 208 { 209 TCU_FAIL("Unrecognized draw call mode"); 210 } 211 212 break; 213 } /* case SHADER_OUTPUT_TYPE_POINTS: */ 214 215 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 216 { 217 if ((drawcall_mode == GL_LINES_ADJACENCY_EXT) || (drawcall_mode == GL_LINES_ADJACENCY)) 218 { 219 result = "lines_with_adjacency_input_triangle_strip_output_lines_adjacency_drawcall"; 220 } 221 else if ((drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) || (drawcall_mode == GL_LINE_STRIP_ADJACENCY)) 222 { 223 result = "lines_with_adjacency_input_triangle_strip_output_line_strip_drawcall"; 224 } 225 else 226 { 227 TCU_FAIL("Unrecognized draw call mode"); 228 } 229 230 break; 231 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */ 232 233 default: 234 { 235 TCU_FAIL("Unrecognized shader output type requested"); 236 } 237 } /* switch (output_type) */ 238 239 break; 240 } /* case SHADER_INPUT_LINES_WITH_ADJACENCY: */ 241 242 case SHADER_INPUT_TRIANGLES: 243 { 244 switch (output_type) 245 { 246 case SHADER_OUTPUT_TYPE_LINE_STRIP: 247 { 248 switch (drawcall_mode) 249 { 250 case GL_TRIANGLES: 251 result = "triangles_input_line_strip_output_triangles_drawcall"; 252 break; 253 case GL_TRIANGLE_FAN: 254 result = "triangles_input_line_strip_output_triangle_fan_drawcall"; 255 break; 256 case GL_TRIANGLE_STRIP: 257 result = "triangles_input_line_strip_output_triangle_strip_drawcall"; 258 break; 259 260 default: 261 { 262 TCU_FAIL("Unrecognized draw call mode"); 263 } 264 } /* switch (drawcall_mode) */ 265 266 break; 267 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */ 268 269 case SHADER_OUTPUT_TYPE_POINTS: 270 { 271 switch (drawcall_mode) 272 { 273 case GL_TRIANGLES: 274 result = "triangles_input_points_output_triangles_drawcall"; 275 break; 276 case GL_TRIANGLE_FAN: 277 result = "triangles_input_points_output_triangle_fan_drawcall"; 278 break; 279 case GL_TRIANGLE_STRIP: 280 result = "triangles_input_points_output_triangle_strip_drawcall"; 281 break; 282 283 default: 284 { 285 TCU_FAIL("Unrecognized draw call mode"); 286 } 287 } /* switch (drawcall_mode) */ 288 289 break; 290 } /* case SHADER_OUTPUT_TYPE_POINTS: */ 291 292 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 293 { 294 switch (drawcall_mode) 295 { 296 case GL_TRIANGLES: 297 result = "triangles_input_triangle_strip_output_triangles_drawcall"; 298 break; 299 case GL_TRIANGLE_FAN: 300 result = "triangles_input_triangle_strip_output_triangle_fan_drawcall"; 301 break; 302 case GL_TRIANGLE_STRIP: 303 result = "triangles_input_triangle_strip_output_triangle_strip_drawcall"; 304 break; 305 306 default: 307 { 308 TCU_FAIL("Unrecognized draw call mode"); 309 } 310 } /* switch (drawcall_mode) */ 311 312 break; 313 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */ 314 315 default: 316 { 317 TCU_FAIL("Unrecognized shader output type requested"); 318 } 319 } /* switch (output_type) */ 320 321 break; 322 } /* case SHADER_INPUT_TRIANGLES: */ 323 324 case SHADER_INPUT_TRIANGLES_WITH_ADJACENCY: 325 { 326 switch (output_type) 327 { 328 case SHADER_OUTPUT_TYPE_LINE_STRIP: 329 { 330 if ((drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT) || (drawcall_mode == GL_TRIANGLES_ADJACENCY)) 331 { 332 result = "triangles_with_adjacency_input_line_strip_output_triangles_adjacency_drawcall"; 333 } 334 else if ((drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) || 335 (drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY)) 336 { 337 result = "triangles_with_adjacency_input_line_strip_output_triangle_strip_adjacency_drawcall"; 338 } 339 else 340 { 341 TCU_FAIL("Unrecognized draw call mode"); 342 } 343 344 break; 345 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */ 346 347 case SHADER_OUTPUT_TYPE_POINTS: 348 { 349 if ((drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT) || (drawcall_mode == GL_TRIANGLES_ADJACENCY)) 350 { 351 result = "triangles_with_adjacency_input_points_output_triangles_adjacency_drawcall"; 352 } 353 else if ((drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) || 354 (drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY)) 355 { 356 result = "triangles_with_adjacency_input_points_output_triangle_strip_adjacency_drawcall"; 357 break; 358 } 359 else 360 { 361 TCU_FAIL("Unrecognized draw call mode"); 362 } 363 364 break; 365 } /* case SHADER_OUTPUT_TYPE_POINTS:*/ 366 367 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 368 { 369 if ((drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT) || (drawcall_mode == GL_TRIANGLES_ADJACENCY)) 370 { 371 result = "triangles_with_adjacency_input_triangle_strip_output_triangles_adjacency_drawcall"; 372 } 373 else if ((drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) || 374 (drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY)) 375 { 376 result = "triangles_with_adjacency_input_triangle_strip_output_triangle_strip_adjacency_drawcall"; 377 } 378 else 379 { 380 TCU_FAIL("Unrecognized draw call mode"); 381 } 382 383 break; 384 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */ 385 386 default: 387 { 388 TCU_FAIL("Unrecognized shader output type requested"); 389 } 390 } /* switch (output_type) */ 391 392 break; 393 } /* case SHADER_INPUT_TRIANGLES_WITH_ADJACENCY: */ 394 395 default: 396 { 397 /* Unrecognized geometry shader input layout qualifier */ 398 TCU_FAIL("Unrecognized layout qualifier"); 399 } 400 } /* switch (input) */ 401 402 return result; 403 } 404 405 /* Initializes child instances of the group that will execute actual tests. */ 406 void GeometryShaderRendering::init(void) 407 { 408 /* Initialize base class */ 409 TestCaseGroupBase::init(); 410 411 /* General variables */ 412 glw::GLenum drawcall_mode = GL_NONE; 413 _shader_input input = SHADER_INPUT_UNKNOWN; 414 415 const glw::GLenum iterations[] = { /* geometry shader input layout qualifier */ /* draw call mode. */ 416 SHADER_INPUT_POINTS, GL_POINTS, SHADER_INPUT_LINES, GL_LINES, SHADER_INPUT_LINES, 417 GL_LINE_STRIP, SHADER_INPUT_LINES, GL_LINE_LOOP, 418 SHADER_INPUT_LINES_WITH_ADJACENCY, GL_LINES_ADJACENCY_EXT, 419 SHADER_INPUT_LINES_WITH_ADJACENCY, GL_LINE_STRIP_ADJACENCY_EXT, 420 SHADER_INPUT_TRIANGLES, GL_TRIANGLES, SHADER_INPUT_TRIANGLES, GL_TRIANGLE_FAN, 421 SHADER_INPUT_TRIANGLES, GL_TRIANGLE_STRIP, SHADER_INPUT_TRIANGLES_WITH_ADJACENCY, 422 GL_TRIANGLES_ADJACENCY_EXT, SHADER_INPUT_TRIANGLES_WITH_ADJACENCY, 423 GL_TRIANGLE_STRIP_ADJACENCY_EXT }; 424 const unsigned int n_iterations = sizeof(iterations) / sizeof(iterations[0]) / 2; 425 unsigned int n_output = 0; 426 427 for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration) 428 { 429 /* Retrieve iteration-specific input layout qualifier and draw call mode data */ 430 input = (_shader_input)iterations[n_iteration * 2 + 0]; 431 drawcall_mode = iterations[n_iteration * 2 + 1]; 432 433 /* Instantiate a worker. Each worker needs to be initialized & executed separately for each 434 * of the three supported input layout qualifiers.*/ 435 for (n_output = 0; n_output < SHADER_OUTPUT_TYPE_COUNT; ++n_output) 436 { 437 _shader_output_type output_type = (_shader_output_type)n_output; 438 const char* name = getTestName(input, output_type, drawcall_mode); 439 440 switch (input) 441 { 442 case SHADER_INPUT_POINTS: 443 { 444 addChild( 445 new GeometryShaderRenderingPointsCase(m_context, m_extParams, name, drawcall_mode, output_type)); 446 447 break; 448 } 449 450 case SHADER_INPUT_LINES: 451 { 452 addChild(new GeometryShaderRenderingLinesCase(m_context, m_extParams, name, false, drawcall_mode, 453 output_type)); 454 455 break; 456 } /* case SHADER_INPUT_LINES:*/ 457 458 case SHADER_INPUT_LINES_WITH_ADJACENCY: 459 { 460 addChild(new GeometryShaderRenderingLinesCase(m_context, m_extParams, name, true, drawcall_mode, 461 output_type)); 462 463 break; 464 } /* case SHADER_INPUT_LINES_WITH_ADJACENCY: */ 465 466 case SHADER_INPUT_TRIANGLES: 467 { 468 addChild(new GeometryShaderRenderingTrianglesCase(m_context, m_extParams, name, false, drawcall_mode, 469 output_type)); 470 471 break; 472 } 473 474 case SHADER_INPUT_TRIANGLES_WITH_ADJACENCY: 475 { 476 addChild(new GeometryShaderRenderingTrianglesCase(m_context, m_extParams, name, true, drawcall_mode, 477 output_type)); 478 479 break; 480 } 481 482 default: 483 { 484 /* Unrecognized geometry shader input layout qualifier */ 485 TCU_FAIL("Unrecognized layout qualifier"); 486 } 487 } /* switch (input) */ 488 } /* for (all output layout qualifiers) */ 489 } /* for (all iterations) */ 490 } 491 492 /** Base worker implementation */ 493 /** Constructor. 494 * 495 * @param context Rendering context. 496 * @param testContext Test context. 497 * @param name Name of the test. 498 * @param description Description of what the test does. 499 **/ 500 GeometryShaderRenderingCase::GeometryShaderRenderingCase(Context& context, const ExtParameters& extParams, 501 const char* name, const char* description) 502 : TestCaseBase(context, extParams, name, description) 503 , m_context(context) 504 , m_instanced_raw_arrays_bo_id(0) 505 , m_instanced_unordered_arrays_bo_id(0) 506 , m_instanced_unordered_elements_bo_id(0) 507 , m_noninstanced_raw_arrays_bo_id(0) 508 , m_noninstanced_unordered_arrays_bo_id(0) 509 , m_noninstanced_unordered_elements_bo_id(0) 510 , m_fs_id(0) 511 , m_gs_id(0) 512 , m_po_id(0) 513 , m_renderingTargetSize_uniform_location(0) 514 , m_singleRenderingTargetSize_uniform_location(0) 515 , m_vao_id(0) 516 , m_vs_id(0) 517 , m_fbo_id(0) 518 , m_read_fbo_id(0) 519 , m_to_id(0) 520 , m_instanced_fbo_id(0) 521 , m_instanced_read_fbo_id(0) 522 , m_instanced_to_id(0) 523 { 524 /* Left blank intentionally */ 525 } 526 527 /** Releases all GLES objects initialized by the base class for geometry shader rendering case implementations. */ 528 void GeometryShaderRenderingCase::deinit() 529 { 530 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 531 532 if (m_fbo_id != 0) 533 { 534 gl.deleteFramebuffers(1, &m_fbo_id); 535 536 m_fbo_id = 0; 537 } 538 539 if (m_fs_id != 0) 540 { 541 gl.deleteShader(m_fs_id); 542 543 m_fs_id = 0; 544 } 545 546 if (m_gs_id != 0) 547 { 548 gl.deleteShader(m_gs_id); 549 550 m_gs_id = 0; 551 } 552 553 if (m_instanced_fbo_id != 0) 554 { 555 gl.deleteFramebuffers(1, &m_instanced_fbo_id); 556 557 m_instanced_fbo_id = 0; 558 } 559 560 if (m_instanced_read_fbo_id != 0) 561 { 562 gl.deleteFramebuffers(1, &m_instanced_read_fbo_id); 563 564 m_instanced_read_fbo_id = 0; 565 } 566 567 if (m_instanced_to_id != 0) 568 { 569 gl.deleteTextures(1, &m_instanced_to_id); 570 571 m_instanced_to_id = 0; 572 } 573 574 if (m_po_id != 0) 575 { 576 gl.deleteProgram(m_po_id); 577 578 m_po_id = 0; 579 } 580 581 if (m_instanced_raw_arrays_bo_id != 0) 582 { 583 gl.deleteBuffers(1, &m_instanced_raw_arrays_bo_id); 584 585 m_instanced_raw_arrays_bo_id = 0; 586 } 587 588 if (m_instanced_unordered_arrays_bo_id != 0) 589 { 590 gl.deleteBuffers(1, &m_instanced_unordered_arrays_bo_id); 591 592 m_instanced_unordered_arrays_bo_id = 0; 593 } 594 595 if (m_instanced_unordered_elements_bo_id != 0) 596 { 597 gl.deleteBuffers(1, &m_instanced_unordered_elements_bo_id); 598 599 m_instanced_unordered_elements_bo_id = 0; 600 } 601 602 if (m_noninstanced_raw_arrays_bo_id != 0) 603 { 604 gl.deleteBuffers(1, &m_noninstanced_raw_arrays_bo_id); 605 606 m_noninstanced_raw_arrays_bo_id = 0; 607 } 608 609 if (m_noninstanced_unordered_arrays_bo_id != 0) 610 { 611 gl.deleteBuffers(1, &m_noninstanced_unordered_arrays_bo_id); 612 613 m_noninstanced_unordered_arrays_bo_id = 0; 614 } 615 616 if (m_noninstanced_unordered_elements_bo_id != 0) 617 { 618 gl.deleteBuffers(1, &m_noninstanced_unordered_elements_bo_id); 619 620 m_noninstanced_unordered_elements_bo_id = 0; 621 } 622 623 if (m_read_fbo_id != 0) 624 { 625 gl.deleteFramebuffers(1, &m_read_fbo_id); 626 627 m_read_fbo_id = 0; 628 } 629 630 if (m_to_id != 0) 631 { 632 gl.deleteTextures(1, &m_to_id); 633 634 m_to_id = 0; 635 } 636 637 if (m_vao_id != 0) 638 { 639 gl.deleteVertexArrays(1, &m_vao_id); 640 641 m_vao_id = 0; 642 } 643 644 if (m_vs_id != 0) 645 { 646 gl.deleteShader(m_vs_id); 647 648 m_vs_id = 0; 649 } 650 } 651 652 /** Executes actual geometry shader-based rendering test, using an user-specified draw call. 653 * 654 * @param type Type of the draw call to use for the test. 655 **/ 656 void GeometryShaderRenderingCase::executeTest(GeometryShaderRenderingCase::_draw_call_type type) 657 { 658 glw::GLuint draw_fbo_id = 0; 659 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 660 const glw::GLenum index_type = getUnorderedElementsDataType(); 661 const glw::GLubyte max_elements_index = getUnorderedElementsMaxIndex(); 662 const glw::GLubyte min_elements_index = getUnorderedElementsMinIndex(); 663 const glw::GLenum mode = getDrawCallMode(); 664 unsigned int n_elements = getAmountOfElementsPerInstance(); 665 unsigned int n_instance = 0; 666 unsigned int n_instances = getAmountOfDrawInstances(); 667 const unsigned int n_vertices = getAmountOfVerticesPerInstance(); 668 const glw::GLint position_attribute_location = gl.getAttribLocation(m_po_id, "position"); 669 glw::GLuint read_fbo_id = 0; 670 unsigned int rt_height = 0; 671 unsigned int rt_width = 0; 672 unsigned int single_rt_height = 0; 673 unsigned int single_rt_width = 0; 674 675 /* Reduce n_instances to 1 for non-instanced draw call modes */ 676 if (type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS || type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS || 677 type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS) 678 { 679 draw_fbo_id = m_fbo_id; 680 n_instances = 1; 681 read_fbo_id = m_read_fbo_id; 682 } 683 else 684 { 685 draw_fbo_id = m_instanced_fbo_id; 686 read_fbo_id = m_instanced_read_fbo_id; 687 } 688 689 /* Retrieve render-target size */ 690 getRenderTargetSize(n_instances, &rt_width, &rt_height); 691 getRenderTargetSize(1, &single_rt_width, &single_rt_height); 692 693 /* Configure GL_ARRAY_BUFFER binding */ 694 switch (type) 695 { 696 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS: 697 { 698 gl.bindBuffer(GL_ARRAY_BUFFER, m_noninstanced_raw_arrays_bo_id); 699 700 break; 701 } 702 703 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED: 704 { 705 gl.bindBuffer(GL_ARRAY_BUFFER, m_instanced_raw_arrays_bo_id); 706 707 break; 708 } 709 710 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED: 711 { 712 gl.bindBuffer(GL_ARRAY_BUFFER, m_instanced_unordered_arrays_bo_id); 713 714 break; 715 } 716 717 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS: 718 case DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS: 719 { 720 gl.bindBuffer(GL_ARRAY_BUFFER, m_noninstanced_unordered_arrays_bo_id); 721 722 break; 723 } 724 725 default: 726 { 727 /* Unrecognized draw call mode */ 728 TCU_FAIL("Unrecognized draw call mode"); 729 } 730 } /* switch (type) */ 731 732 gl.vertexAttribPointer(position_attribute_location, 4, GL_FLOAT, GL_FALSE, 0 /* stride */, NULL); 733 gl.enableVertexAttribArray(position_attribute_location); 734 735 /* Configure GL_ELEMENT_ARRAY_BUFFER binding */ 736 switch (type) 737 { 738 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS: 739 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED: 740 { 741 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 742 743 break; 744 } 745 746 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED: 747 { 748 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_instanced_unordered_elements_bo_id); 749 750 break; 751 } 752 753 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS: 754 case DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS: 755 { 756 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_noninstanced_unordered_elements_bo_id); 757 758 break; 759 } 760 761 default: 762 { 763 /* Unrecognized draw call mode */ 764 TCU_FAIL("Unrecognized draw call mode"); 765 } 766 } /* switch (type) */ 767 768 /* Configure draw framebuffer */ 769 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_fbo_id); 770 gl.viewport(0 /* x */, 0 /* y */, rt_width, rt_height); 771 772 /* Clear the color buffer. */ 773 gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */); 774 gl.clear(GL_COLOR_BUFFER_BIT); 775 776 GLU_EXPECT_NO_ERROR(gl.getError(), "Test set-up failed."); 777 778 /* Render the test geometry */ 779 gl.useProgram(m_po_id); 780 gl.uniform2i(m_renderingTargetSize_uniform_location, rt_width, rt_height); 781 gl.uniform2i(m_singleRenderingTargetSize_uniform_location, single_rt_width, single_rt_height); 782 783 setUniformsBeforeDrawCall(type); 784 785 switch (type) 786 { 787 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS: 788 { 789 gl.drawArrays(mode, 0 /* first */, n_vertices); 790 791 break; 792 } 793 794 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED: 795 { 796 gl.drawArraysInstanced(mode, 0 /* first */, n_vertices, n_instances); 797 798 break; 799 } 800 801 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS: 802 { 803 gl.drawElements(mode, n_elements, index_type, NULL); 804 805 break; 806 } 807 808 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED: 809 { 810 gl.drawElementsInstanced(mode, n_elements, index_type, NULL, n_instances); 811 812 break; 813 } 814 815 case DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS: 816 { 817 gl.drawRangeElements(mode, min_elements_index, max_elements_index, n_elements, index_type, NULL); 818 819 break; 820 } 821 822 default: 823 { 824 /* Unrecognized draw call mode */ 825 TCU_FAIL("Unrecognized draw call mode"); 826 } 827 } /* switch (type) */ 828 829 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed."); 830 831 /* Retrieve rendered data */ 832 unsigned char* rendered_data = new unsigned char[rt_height * rt_width * 4 /* components */]; 833 834 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo_id); 835 gl.readPixels(0 /* x */, 0 /* y */, rt_width, rt_height, GL_RGBA, GL_UNSIGNED_BYTE, rendered_data); 836 837 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 838 839 /* Verify if the test succeeded */ 840 for (n_instance = 0; n_instance < n_instances; ++n_instance) 841 { 842 verify(type, n_instance, rendered_data); 843 } /* for (all instances) */ 844 845 /* Release the data buffer */ 846 delete[] rendered_data; 847 } 848 849 /** Initializes ES objects required to execute a set of tests for particular input layout qualifier. */ 850 void GeometryShaderRenderingCase::initTest() 851 { 852 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 853 854 /* Retrieve derivative class' properties */ 855 std::string fs_code = getFragmentShaderCode(); 856 std::string gs_code = getGeometryShaderCode(); 857 unsigned int n = 0; 858 unsigned int n_instances = getAmountOfDrawInstances(); 859 std::string vs_code = getVertexShaderCode(); 860 861 /* Set pixel storage properties before we continue */ 862 gl.pixelStorei(GL_PACK_ALIGNMENT, 1); 863 gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1); 864 865 /* Create buffer objects the derivative implementation will fill with data */ 866 gl.genBuffers(1, &m_instanced_raw_arrays_bo_id); 867 gl.genBuffers(1, &m_instanced_unordered_arrays_bo_id); 868 gl.genBuffers(1, &m_instanced_unordered_elements_bo_id); 869 gl.genBuffers(1, &m_noninstanced_raw_arrays_bo_id); 870 gl.genBuffers(1, &m_noninstanced_unordered_arrays_bo_id); 871 gl.genBuffers(1, &m_noninstanced_unordered_elements_bo_id); 872 873 /* Set up a separate set of objects, that will be used for testing instanced and non-instanced draw calls */ 874 for (n = 0; n < 2 /* non-/instanced draw calls */; ++n) 875 { 876 bool is_instanced = (n == 1); 877 878 glw::GLuint* draw_fbo_id_ptr = !is_instanced ? &m_fbo_id : &m_instanced_fbo_id; 879 glw::GLuint* read_fbo_id_ptr = (!is_instanced) ? &m_read_fbo_id : &m_instanced_read_fbo_id; 880 unsigned int to_height = 0; 881 unsigned int to_width = 0; 882 glw::GLuint* to_id_ptr = (!is_instanced) ? &m_to_id : &m_instanced_to_id; 883 884 /* n == 0: non-instanced draw calls, instanced otherwise */ 885 getRenderTargetSize((n == 0) ? 1 : n_instances, &to_width, &to_height); 886 887 /* Create a texture object we will be rendering to */ 888 gl.genTextures(1, to_id_ptr); 889 gl.bindTexture(GL_TEXTURE_2D, *to_id_ptr); 890 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, to_width, to_height); 891 892 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure a 2D texture object"); 893 894 /* Create and configure a framebuffer object that will be used for rendering */ 895 gl.genFramebuffers(1, draw_fbo_id_ptr); 896 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *draw_fbo_id_ptr); 897 898 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *to_id_ptr, 0 /* level */); 899 900 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure draw framebuffer object"); 901 902 if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 903 { 904 TCU_FAIL("Draw framebuffer is reported to be incomplete"); 905 } /* if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) */ 906 907 /* Create and bind a FBO we will use for reading rendered data */ 908 gl.genFramebuffers(1, read_fbo_id_ptr); 909 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *read_fbo_id_ptr); 910 911 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *to_id_ptr, 0 /* level */); 912 913 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure read framebuffer object"); 914 915 if (gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 916 { 917 TCU_FAIL("Read framebuffer is reported to be incomplete"); 918 } /* if (gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) */ 919 920 /* Fill the iteration-specific buffer objects with data */ 921 glw::GLuint raw_arrays_bo_id = (is_instanced) ? m_instanced_raw_arrays_bo_id : m_noninstanced_raw_arrays_bo_id; 922 unsigned int raw_arrays_bo_size = getRawArraysDataBufferSize(is_instanced); 923 const void* raw_arrays_data = getRawArraysDataBuffer(is_instanced); 924 glw::GLuint unordered_arrays_bo_id = 925 (is_instanced) ? m_instanced_unordered_arrays_bo_id : m_noninstanced_unordered_arrays_bo_id; 926 unsigned int unordered_arrays_bo_size = getUnorderedArraysDataBufferSize(is_instanced); 927 const void* unordered_arrays_data = getUnorderedArraysDataBuffer(is_instanced); 928 glw::GLuint unordered_elements_bo_id = 929 (is_instanced) ? m_instanced_unordered_elements_bo_id : m_noninstanced_unordered_elements_bo_id; 930 unsigned int unordered_elements_bo_size = getUnorderedElementsDataBufferSize(is_instanced); 931 const void* unordered_elements_data = getUnorderedElementsDataBuffer(is_instanced); 932 933 gl.bindBuffer(GL_ARRAY_BUFFER, raw_arrays_bo_id); 934 gl.bufferData(GL_ARRAY_BUFFER, raw_arrays_bo_size, raw_arrays_data, GL_STATIC_COPY); 935 936 gl.bindBuffer(GL_ARRAY_BUFFER, unordered_arrays_bo_id); 937 gl.bufferData(GL_ARRAY_BUFFER, unordered_arrays_bo_size, unordered_arrays_data, GL_STATIC_COPY); 938 939 gl.bindBuffer(GL_ARRAY_BUFFER, unordered_elements_bo_id); 940 gl.bufferData(GL_ARRAY_BUFFER, unordered_elements_bo_size, unordered_elements_data, GL_STATIC_COPY); 941 } 942 943 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure test buffer objects"); 944 945 /* Create and bind a VAO */ 946 gl.genVertexArrays(1, &m_vao_id); 947 gl.bindVertexArray(m_vao_id); 948 949 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate & bind a vertex array object"); 950 951 /* Create and configure program & shader objects that will be used for the test case */ 952 const char* fs_code_ptr = fs_code.c_str(); 953 const char* gs_code_ptr = gs_code.c_str(); 954 const char* vs_code_ptr = vs_code.c_str(); 955 956 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 957 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 958 m_po_id = gl.createProgram(); 959 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 960 961 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader/program objects"); 962 963 if (!buildProgram(m_po_id, m_fs_id, 1, &fs_code_ptr, m_gs_id, 1, &gs_code_ptr, m_vs_id, 1, &vs_code_ptr)) 964 { 965 TCU_FAIL("Could not build shader program"); 966 } 967 968 /* Retrieve uniform locations */ 969 m_renderingTargetSize_uniform_location = gl.getUniformLocation(m_po_id, "renderingTargetSize"); 970 m_singleRenderingTargetSize_uniform_location = gl.getUniformLocation(m_po_id, "singleRenderingTargetSize"); 971 } 972 973 /* Checks all draw call types for a specific Geometry Shader input layout qualifier. 974 * 975 * @return Always STOP. 976 */ 977 tcu::TestNode::IterateResult GeometryShaderRenderingCase::iterate() 978 { 979 if (!m_is_geometry_shader_extension_supported) 980 { 981 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 982 } 983 984 initTest(); 985 986 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_ARRAYS); 987 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED); 988 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_ELEMENTS); 989 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED); 990 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS); 991 992 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 993 return STOP; 994 } 995 996 /** Constructor. 997 * 998 * @param drawcall_mode Draw call mode that should be tested with this test case instance. 999 * @param output_type Geometry shader output type to be used. 1000 * @param context Rendering context; 1001 * @param testContext Test context; 1002 * @param name Test name. 1003 **/ 1004 GeometryShaderRenderingPointsCase::GeometryShaderRenderingPointsCase(Context& context, const ExtParameters& extParams, 1005 const char* name, glw::GLenum drawcall_mode, 1006 _shader_output_type output_type) 1007 : GeometryShaderRenderingCase( 1008 context, extParams, name, 1009 "Verifies all draw calls work correctly for specific input+output+draw call mode combination") 1010 , m_output_type(output_type) 1011 { 1012 /* Sanity checks */ 1013 if (drawcall_mode != GL_POINTS) 1014 { 1015 TCU_FAIL("Only GL_POINTS draw call mode is supported for 'points' geometry shader input layout qualifier test " 1016 "implementation"); 1017 } 1018 1019 if (output_type != SHADER_OUTPUT_TYPE_POINTS && output_type != SHADER_OUTPUT_TYPE_LINE_STRIP && 1020 output_type != SHADER_OUTPUT_TYPE_TRIANGLE_STRIP) 1021 { 1022 TCU_FAIL("Unsupported output layout qualifier type requested for 'points' geometry shader input layout " 1023 "qualifier test implementation"); 1024 } 1025 1026 /* Retrieve rendertarget resolution for a single-instance case. 1027 * 1028 * Y coordinates will be dynamically updated in a vertex shader for 1029 * multiple-instance tests. That's fine, since in multi-instanced tests 1030 * we only expand the rendertarget's height; its width is unaffected. 1031 */ 1032 unsigned int rendertarget_height = 0; 1033 unsigned int rendertarget_width = 0; 1034 1035 getRenderTargetSize(1, &rendertarget_width, &rendertarget_height); 1036 1037 /* Generate raw vertex array data. Note we do not differentiate between instanced and 1038 * non-instanced cases for geometry shaders that emit points */ 1039 const unsigned int raw_array_data_size = getRawArraysDataBufferSize(false); 1040 1041 m_raw_array_data = new float[raw_array_data_size / sizeof(float)]; 1042 1043 for (unsigned int n_point = 0; n_point < 8 /* points, as per test spec */; ++n_point) 1044 { 1045 switch (m_output_type) 1046 { 1047 case SHADER_OUTPUT_TYPE_LINE_STRIP: 1048 { 1049 m_raw_array_data[n_point * 4 + 0] = 1050 -1 + ((float(3 + 7 * n_point) + 0.5f) / float(rendertarget_width)) * 2.0f; 1051 m_raw_array_data[n_point * 4 + 1] = -1 + ((float(3.0f + 0.5f)) / float(rendertarget_height)) * 2.0f; 1052 m_raw_array_data[n_point * 4 + 2] = 0.0f; 1053 m_raw_array_data[n_point * 4 + 3] = 1.0f; 1054 1055 break; 1056 } 1057 1058 case SHADER_OUTPUT_TYPE_POINTS: 1059 { 1060 m_raw_array_data[n_point * 4 + 0] = 1061 -1 + ((float(1 + 5 * n_point) + 0.5f) / float(rendertarget_width)) * 2.0f; 1062 m_raw_array_data[n_point * 4 + 1] = -1 + (float(1.5f + 0.5f) / float(rendertarget_height)) * 2.0f; 1063 m_raw_array_data[n_point * 4 + 2] = 0.0f; 1064 m_raw_array_data[n_point * 4 + 3] = 1.0f; 1065 1066 break; 1067 } 1068 1069 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 1070 { 1071 m_raw_array_data[n_point * 4 + 0] = -1 + ((float(6 * n_point) + 0.5f) / float(rendertarget_width)) * 2.0f; 1072 m_raw_array_data[n_point * 4 + 1] = -1.0f; 1073 m_raw_array_data[n_point * 4 + 2] = 0.0f; 1074 m_raw_array_data[n_point * 4 + 3] = 1.0f; 1075 1076 break; 1077 } 1078 1079 default: 1080 { 1081 TCU_FAIL("Unsupported shader output layout qualifier requested"); 1082 } 1083 } /* switch (m_output_type) */ 1084 } /* for (all points) */ 1085 1086 /* Generate unordered data - we do not differentiate between instanced & non-instanced cases 1087 * for "points" tests 1088 */ 1089 const unsigned int unordered_array_data_size = getUnorderedArraysDataBufferSize(false); 1090 const unsigned int unordered_elements_data_size = getUnorderedElementsDataBufferSize(false); 1091 1092 m_unordered_array_data = new float[unordered_array_data_size / sizeof(float)]; 1093 m_unordered_elements_data = new unsigned char[unordered_elements_data_size]; 1094 1095 for (unsigned int n_point = 0; n_point < 8 /* points, as per test spec */; ++n_point) 1096 { 1097 memcpy(m_unordered_array_data + n_point * 4, m_raw_array_data + (8 - n_point - 1) * 4, 1098 sizeof(float) * 4 /* components */); 1099 } /* for (all points) */ 1100 1101 for (unsigned int n_point = 0; n_point < 8 /* points, as per test spec */; ++n_point) 1102 { 1103 m_unordered_elements_data[n_point] = (unsigned char)((n_point * 2) % 8 + n_point / 4); 1104 } /* for (all points) */ 1105 } 1106 1107 /** Destructor. */ 1108 GeometryShaderRenderingPointsCase::~GeometryShaderRenderingPointsCase() 1109 { 1110 if (m_raw_array_data != NULL) 1111 { 1112 delete[] m_raw_array_data; 1113 1114 m_raw_array_data = NULL; 1115 } 1116 1117 if (m_unordered_array_data != NULL) 1118 { 1119 delete[] m_unordered_array_data; 1120 1121 m_unordered_array_data = NULL; 1122 } 1123 1124 if (m_unordered_elements_data != NULL) 1125 { 1126 delete[] m_unordered_elements_data; 1127 1128 m_unordered_elements_data = NULL; 1129 } 1130 } 1131 1132 /** Retrieves amount of instances that should be drawn with glDraw*Elements() calls. 1133 * 1134 * @return As per description. 1135 **/ 1136 unsigned int GeometryShaderRenderingPointsCase::getAmountOfDrawInstances() 1137 { 1138 return 4 /* instances */; 1139 } 1140 1141 /** Retrieves amount of indices that should be used for rendering a single instance 1142 * (glDraw*Elements() calls only) 1143 * 1144 * @return As per description. 1145 */ 1146 unsigned int GeometryShaderRenderingPointsCase::getAmountOfElementsPerInstance() 1147 { 1148 return 8 /* elements */; 1149 } 1150 1151 /** Retrieves amount of vertices that should be used for rendering a single instance 1152 * (glDrawArrays*() calls only) 1153 * 1154 * @return As per description. 1155 **/ 1156 unsigned int GeometryShaderRenderingPointsCase::getAmountOfVerticesPerInstance() 1157 { 1158 return 8 /* points */; 1159 } 1160 1161 /** Draw call mode that should be used glDraw*() calls. 1162 * 1163 * @return As per description. 1164 **/ 1165 glw::GLenum GeometryShaderRenderingPointsCase::getDrawCallMode() 1166 { 1167 return GL_POINTS; 1168 } 1169 1170 /** Source code for a fragment shader that should be used for the test. 1171 * 1172 * @return As per description. 1173 **/ 1174 std::string GeometryShaderRenderingPointsCase::getFragmentShaderCode() 1175 { 1176 static std::string fs_code = "${VERSION}\n" 1177 "\n" 1178 "precision highp float;\n" 1179 "\n" 1180 "in vec4 gs_fs_color;\n" 1181 "out vec4 result;\n" 1182 "\n" 1183 "void main()\n" 1184 "{\n" 1185 " result = gs_fs_color;\n" 1186 "}\n"; 1187 1188 return fs_code; 1189 } 1190 1191 /** Source code for a geometry shader that should be used for the test. 1192 * 1193 * @return As per description. 1194 **/ 1195 std::string GeometryShaderRenderingPointsCase::getGeometryShaderCode() 1196 { 1197 static const char* lines_gs_code = "${VERSION}\n" 1198 "\n" 1199 "${GEOMETRY_SHADER_ENABLE}\n" 1200 "\n" 1201 "layout(points) in;\n" 1202 "layout(line_strip, max_vertices=15) out;\n" 1203 "\n" 1204 "in vec4 vs_gs_color[1];\n" 1205 "out vec4 gs_fs_color;\n" 1206 "\n" 1207 "uniform ivec2 renderingTargetSize;\n" 1208 "\n" 1209 "void main()\n" 1210 "{\n" 1211 " float bias = 0.0035;" 1212 " for (int delta = 1; delta <= 3; ++delta)\n" 1213 " {\n" 1214 " float dx = float(delta * 2) / float(renderingTargetSize.x) + bias;\n" 1215 " float dy = float(delta * 2) / float(renderingTargetSize.y) + bias;\n" 1216 "\n" 1217 /* TL->TR */ 1218 " gs_fs_color = vs_gs_color[0];\n" 1219 " gl_Position = gl_in[0].gl_Position + vec4(-dx, -dy, 0, 0);\n" 1220 " EmitVertex();\n" 1221 " gs_fs_color = vs_gs_color[0];\n" 1222 " gl_Position = gl_in[0].gl_Position + vec4(dx, -dy, 0, 0);\n" 1223 " EmitVertex();\n" 1224 /* TR->BR */ 1225 " gs_fs_color = vs_gs_color[0];\n" 1226 " gl_Position = gl_in[0].gl_Position + vec4(dx, dy, 0, 0);\n" 1227 " EmitVertex();\n" 1228 /* BR->BL */ 1229 " gs_fs_color = vs_gs_color[0];\n" 1230 " gl_Position = gl_in[0].gl_Position + vec4(-dx, dy, 0, 0);\n" 1231 " EmitVertex();\n" 1232 /* BL->TL */ 1233 " gs_fs_color = vs_gs_color[0];\n" 1234 " gl_Position = gl_in[0].gl_Position + vec4(-dx, -dy, 0, 0);\n" 1235 " EmitVertex();\n" 1236 " EndPrimitive();\n" 1237 " }\n" 1238 "}\n"; 1239 1240 static const char* points_gs_code = "${VERSION}\n" 1241 "\n" 1242 "${GEOMETRY_SHADER_ENABLE}\n" 1243 "\n" 1244 "layout(points) in;\n" 1245 "layout(points, max_vertices=9) out;\n" 1246 "\n" 1247 "in vec4 vs_gs_color[1];\n" 1248 "out vec4 gs_fs_color;\n" 1249 "\n" 1250 "uniform ivec2 renderingTargetSize;\n" 1251 "\n" 1252 "void main()\n" 1253 "{\n" 1254 " float dx = 2.0 / float(renderingTargetSize.x);\n" 1255 " float dy = 2.0 / float(renderingTargetSize.y);\n" 1256 "\n" 1257 /* TL */ 1258 " gs_fs_color = vs_gs_color[0];\n" 1259 " gl_Position = gl_in[0].gl_Position + vec4(-dx, -dy, 0, 0);\n" 1260 " EmitVertex();\n" 1261 /* TM */ 1262 " gs_fs_color = vs_gs_color[0];\n" 1263 " gl_Position = gl_in[0].gl_Position + vec4(0, -dy, 0, 0);\n" 1264 " EmitVertex();\n" 1265 /* TR */ 1266 " gs_fs_color = vs_gs_color[0];\n" 1267 " gl_Position = gl_in[0].gl_Position + vec4(dx, -dy, 0, 0);\n" 1268 " EmitVertex();\n" 1269 /* L */ 1270 " gs_fs_color = vs_gs_color[0];\n" 1271 " gl_Position = gl_in[0].gl_Position + vec4(-dx, 0, 0, 0); \n" 1272 " EmitVertex();\n" 1273 /* M */ 1274 " gs_fs_color = vs_gs_color[0];\n" 1275 " gl_Position = gl_in[0].gl_Position;\n" 1276 " EmitVertex();\n" 1277 /* R */ 1278 " gs_fs_color = vs_gs_color[0];\n" 1279 " gl_Position = gl_in[0].gl_Position + vec4(dx, 0, 0, 0);\n" 1280 " EmitVertex();\n" 1281 /* BL */ 1282 " gs_fs_color = vs_gs_color[0];\n" 1283 " gl_Position = gl_in[0].gl_Position + vec4(-dx, dy, 0, 0);\n" 1284 " EmitVertex();\n" 1285 /* BM */ 1286 " gs_fs_color = vs_gs_color[0];\n" 1287 " gl_Position = gl_in[0].gl_Position + vec4(0, dy, 0, 0);\n" 1288 " EmitVertex();\n" 1289 /* BR */ 1290 " gs_fs_color = vs_gs_color[0];\n" 1291 " gl_Position = gl_in[0].gl_Position + vec4(dx, dy, 0, 0);\n" 1292 " EmitVertex();\n" 1293 "}\n"; 1294 1295 static const char* triangles_gs_code = "${VERSION}\n" 1296 "\n" 1297 "${GEOMETRY_SHADER_ENABLE}\n" 1298 "\n" 1299 "layout(points) in;\n" 1300 "layout(triangle_strip, max_vertices=6) out;\n" 1301 "\n" 1302 "in vec4 vs_gs_color[1];\n" 1303 "out vec4 gs_fs_color;\n" 1304 "\n" 1305 "uniform ivec2 renderingTargetSize;\n" 1306 "\n" 1307 "void main()\n" 1308 "{\n" 1309 /* Assume that point position corresponds to TL corner. */ 1310 " float dx = float(2.0) / float(renderingTargetSize.x);\n" 1311 " float dy = float(2.0) / float(renderingTargetSize.y);\n" 1312 "\n" 1313 /* BL 1 */ 1314 " gs_fs_color = vec4(vs_gs_color[0].x, 0, 0, 0);\n" 1315 " gl_Position = gl_in[0].gl_Position + vec4(0, 6.0 * dy, 0, 0);\n" 1316 " EmitVertex();\n" 1317 /* TL 1 */ 1318 " gs_fs_color = vec4(vs_gs_color[0].x, 0, 0, 0);\n" 1319 " gl_Position = gl_in[0].gl_Position;\n" 1320 " EmitVertex();\n" 1321 /* BR 1 */ 1322 " gs_fs_color = vec4(vs_gs_color[0].x, 0, 0, 0);\n" 1323 " gl_Position = gl_in[0].gl_Position + vec4(6.0 * dx, 6.0 * dy, 0, 0);\n" 1324 " EmitVertex();\n" 1325 " EndPrimitive();\n" 1326 /* BR 2 */ 1327 " gs_fs_color = vec4(0, vs_gs_color[0].y, 0, 0);\n" 1328 " gl_Position = gl_in[0].gl_Position + vec4(6.0 * dx, 6.0 * dy, 0, 0);\n" 1329 " EmitVertex();\n" 1330 /* TL 2 */ 1331 " gs_fs_color = vec4(0, vs_gs_color[0].y, 0, 0);\n" 1332 " gl_Position = gl_in[0].gl_Position;\n" 1333 " EmitVertex();\n" 1334 /* TR 2 */ 1335 " gs_fs_color = vec4(0, vs_gs_color[0].y, 0, 0);\n" 1336 " gl_Position = gl_in[0].gl_Position + vec4(6.0 * dx, 0, 0, 0);\n" 1337 " EmitVertex();\n" 1338 " EndPrimitive();\n" 1339 "}\n"; 1340 const char* result = NULL; 1341 1342 switch (m_output_type) 1343 { 1344 case SHADER_OUTPUT_TYPE_LINE_STRIP: 1345 { 1346 result = lines_gs_code; 1347 1348 break; 1349 } 1350 1351 case SHADER_OUTPUT_TYPE_POINTS: 1352 { 1353 result = points_gs_code; 1354 1355 break; 1356 } 1357 1358 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 1359 { 1360 result = triangles_gs_code; 1361 1362 break; 1363 } 1364 1365 default: 1366 { 1367 TCU_FAIL("Requested shader output layout qualifier is unsupported"); 1368 } 1369 } /* switch (m_output_type) */ 1370 1371 return result; 1372 } 1373 1374 /** Returns amount of bytes that should be allocated for a buffer object to hold 1375 * vertex data to be used for glDrawArrays*() calls. 1376 * 1377 * @param instanced Ignored. 1378 * 1379 * @return As per description. 1380 **/ 1381 glw::GLuint GeometryShaderRenderingPointsCase::getRawArraysDataBufferSize(bool /*instanced*/) 1382 { 1383 1384 return sizeof(float) * (1 /* point */ * 4 /* coordinates */) * 8 /* points in total, as per test spec */; 1385 } 1386 1387 /** Returns vertex data for the test. Only to be used for glDrawArrays*() calls. 1388 * 1389 * @param instanced Ignored. 1390 * 1391 * @return As per description. 1392 **/ 1393 const void* GeometryShaderRenderingPointsCase::getRawArraysDataBuffer(bool /*instanced*/) 1394 { 1395 return m_raw_array_data; 1396 } 1397 1398 /** Retrieves resolution of off-screen rendering buffer that should be used for the test. 1399 * 1400 * @param n_instances Amount of draw call instances this render target will be used for. 1401 * @param out_width Deref will be used to store rendertarget's width. Must not be NULL. 1402 * @param out_height Deref will be used to store rendertarget's height. Must not be NULL. 1403 **/ 1404 void GeometryShaderRenderingPointsCase::getRenderTargetSize(unsigned int n_instances, unsigned int* out_width, 1405 unsigned int* out_height) 1406 { 1407 switch (m_output_type) 1408 { 1409 case SHADER_OUTPUT_TYPE_LINE_STRIP: 1410 { 1411 *out_width = 56; /* as per test spec */ 1412 *out_height = 7 * n_instances; /* as per test spec */ 1413 1414 break; 1415 } 1416 1417 case SHADER_OUTPUT_TYPE_POINTS: 1418 { 1419 *out_width = 38; /* as per test spec */ 1420 *out_height = 3 * n_instances + 2 * (n_instances - 1); /* as per test spec */ 1421 1422 break; 1423 } 1424 1425 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 1426 { 1427 *out_width = 48; /* as per test spec */ 1428 *out_height = 6 * n_instances; /* as per test spec */ 1429 1430 break; 1431 } 1432 1433 default: 1434 { 1435 TCU_FAIL("Unsupported shader output type"); 1436 } 1437 } /* switch (m_output_type) */ 1438 } 1439 1440 /** Returns amount of bytes that should be allocated for a buffer object to hold 1441 * vertex data to be used for glDrawElements*() calls. 1442 * 1443 * @param instanced Ignored. 1444 * 1445 * @return As per description. 1446 **/ 1447 glw::GLuint GeometryShaderRenderingPointsCase::getUnorderedArraysDataBufferSize(bool /*instanced*/) 1448 { 1449 1450 /* Note: No difference between non-instanced and instanced cases for this class */ 1451 return sizeof(float) * (1 /* point */ * 4 /* coordinates */) * 8 /* points in total, as per test spec */; 1452 } 1453 1454 /** Returns vertex data for the test. Only to be used for glDrawElements*() calls. 1455 * 1456 * @param instanced Ignored. 1457 * 1458 * @return As per description. 1459 **/ 1460 const void* GeometryShaderRenderingPointsCase::getUnorderedArraysDataBuffer(bool /*instanced*/) 1461 { 1462 1463 /* Note: No difference between non-instanced and instanced cases for this class */ 1464 return m_unordered_array_data; 1465 } 1466 1467 /** Returns amount of bytes that should be allocated for a buffer object to hold 1468 * index data to be used for glDrawElements*() calls. 1469 * 1470 * @param instanced Ignored. 1471 * 1472 * @return As per description. 1473 */ 1474 glw::GLuint GeometryShaderRenderingPointsCase::getUnorderedElementsDataBufferSize(bool /*instanced*/) 1475 { 1476 1477 /* Note: No difference between non-instanced and instanced cases for this class */ 1478 return 8 /* indices */ * sizeof(unsigned char); 1479 } 1480 1481 /** Returns index data for the test. Only to be used for glDrawElements*() calls. 1482 * 1483 * @param instanced Ignored. 1484 * 1485 * @return As per description. 1486 **/ 1487 const void* GeometryShaderRenderingPointsCase::getUnorderedElementsDataBuffer(bool /*instanced*/) 1488 { 1489 1490 /* Note: No difference between non-instanced and instanced cases for this class */ 1491 return m_unordered_elements_data; 1492 } 1493 1494 /** Returns type of the index, to be used for glDrawElements*() calls. 1495 * 1496 * @return As per description. 1497 **/ 1498 glw::GLenum GeometryShaderRenderingPointsCase::getUnorderedElementsDataType() 1499 { 1500 return GL_UNSIGNED_BYTE; 1501 } 1502 1503 /** Retrieves maximum index value. To be used for glDrawRangeElements() test only. 1504 * 1505 * @return As per description. 1506 **/ 1507 glw::GLubyte GeometryShaderRenderingPointsCase::getUnorderedElementsMaxIndex() 1508 { 1509 return 8 /* up to 8 points will be rendered */; 1510 } 1511 1512 /** Retrieves minimum index value. To be used for glDrawRangeElements() test only. 1513 * 1514 * @return As per description. 1515 **/ 1516 glw::GLubyte GeometryShaderRenderingPointsCase::getUnorderedElementsMinIndex() 1517 { 1518 return 0; 1519 } 1520 1521 /** Retrieves vertex shader code to be used for the test. 1522 * 1523 * @return As per description. 1524 **/ 1525 std::string GeometryShaderRenderingPointsCase::getVertexShaderCode() 1526 { 1527 static std::string lines_vs_code = 1528 "${VERSION}\n" 1529 "\n" 1530 "in vec4 position;\n" 1531 "uniform ivec2 renderingTargetSize;\n" 1532 "out vec4 vs_gs_color;\n" 1533 "\n" 1534 "void main()\n" 1535 "{\n" 1536 /* non-instanced draw call cases */ 1537 " if (renderingTargetSize.y == 7)\n" 1538 " {\n" 1539 " gl_Position = position;" 1540 " }\n" 1541 " else\n" 1542 " {\n" 1543 /* instanced draw call cases: */ 1544 " gl_Position = vec4(position.x, \n" 1545 " -1.0 + ((float(3 + gl_InstanceID * 7)) / float(renderingTargetSize.y - 1)) * 2.0,\n" 1546 " position.zw);\n" 1547 " }\n" 1548 "\n" 1549 " switch(gl_VertexID)\n" 1550 " {\n" 1551 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 1552 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 1553 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 1554 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 1555 " case 4: vs_gs_color = vec4(1, 1, 0, 0); break;\n" 1556 " case 5: vs_gs_color = vec4(1, 0, 1, 0); break;\n" 1557 " case 6: vs_gs_color = vec4(1, 0, 0, 1); break;\n" 1558 " case 7: vs_gs_color = vec4(1, 1, 1, 0); break;\n" 1559 " case 8: vs_gs_color = vec4(1, 1, 0, 1); break;\n" 1560 " }\n" 1561 "}\n"; 1562 1563 static std::string points_vs_code = 1564 "${VERSION}\n" 1565 "\n" 1566 "in vec4 position;\n" 1567 "uniform ivec2 renderingTargetSize;\n" 1568 "out vec4 vs_gs_color;\n" 1569 "\n" 1570 "void main()\n" 1571 "{\n" 1572 " gl_PointSize = 1.0;\n" 1573 "\n" 1574 /* non-instanced draw call cases */ 1575 " if (renderingTargetSize.y == 3)\n" 1576 " {\n" 1577 " gl_Position = position;\n" 1578 " }\n" 1579 /* instanced draw call cases */ 1580 " else\n" 1581 " {\n" 1582 " gl_Position = vec4(position.x,\n" 1583 " -1.0 + (1.5 + float(5 * gl_InstanceID)) / float(renderingTargetSize.y) * 2.0,\n" 1584 " position.zw);\n" 1585 " }\n" 1586 "\n" 1587 " switch(gl_VertexID)\n" 1588 " {\n" 1589 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 1590 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 1591 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 1592 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 1593 " case 4: vs_gs_color = vec4(1, 1, 0, 0); break;\n" 1594 " case 5: vs_gs_color = vec4(1, 0, 1, 0); break;\n" 1595 " case 6: vs_gs_color = vec4(1, 0, 0, 1); break;\n" 1596 " case 7: vs_gs_color = vec4(1, 1, 1, 0); break;\n" 1597 " case 8: vs_gs_color = vec4(1, 1, 0, 1); break;\n" 1598 " }\n" 1599 "}\n"; 1600 1601 static std::string triangles_vs_code = 1602 "${VERSION}\n" 1603 "\n" 1604 "in vec4 position;\n" 1605 "uniform ivec2 renderingTargetSize;\n" 1606 "out vec4 vs_gs_color;\n" 1607 "\n" 1608 "void main()\n" 1609 "{\n" 1610 " if (renderingTargetSize.y == 6)\n" 1611 " {\n" 1612 " gl_Position = position;\n" 1613 " }\n" 1614 " else\n" 1615 " {\n" 1616 " gl_Position = vec4(position.x,\n" 1617 " position.y + float(gl_InstanceID) * 6.0 / float(renderingTargetSize.y) * 2.0,\n" 1618 " position.zw);\n" 1619 " }\n" 1620 "\n" 1621 " switch(gl_VertexID)\n" 1622 " {\n" 1623 " case 0: vs_gs_color = vec4(0.1, 0.8, 0, 0); break;\n" 1624 " case 1: vs_gs_color = vec4(0.2, 0.7, 0, 0); break;\n" 1625 " case 2: vs_gs_color = vec4(0.3, 0.6, 1, 0); break;\n" 1626 " case 3: vs_gs_color = vec4(0.4, 0.5, 0, 1); break;\n" 1627 " case 4: vs_gs_color = vec4(0.5, 0.4, 0, 0); break;\n" 1628 " case 5: vs_gs_color = vec4(0.6, 0.3, 1, 0); break;\n" 1629 " case 6: vs_gs_color = vec4(0.7, 0.2, 0, 1); break;\n" 1630 " case 7: vs_gs_color = vec4(0.8, 0.1, 1, 0); break;\n" 1631 " }\n" 1632 "}\n"; 1633 std::string result; 1634 1635 switch (m_output_type) 1636 { 1637 case SHADER_OUTPUT_TYPE_LINE_STRIP: 1638 { 1639 result = lines_vs_code; 1640 1641 break; 1642 } 1643 1644 case SHADER_OUTPUT_TYPE_POINTS: 1645 { 1646 result = points_vs_code; 1647 1648 break; 1649 } 1650 1651 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 1652 { 1653 result = triangles_vs_code; 1654 1655 break; 1656 } 1657 1658 default: 1659 { 1660 TCU_FAIL("Unsupported shader output type used"); 1661 } 1662 } /* switch (m_output_type) */ 1663 1664 return result; 1665 } 1666 1667 /** Verifies that the rendered data is correct. 1668 * 1669 * @param drawcall_type Type of the draw call that was used to render the geometry. 1670 * @param instance_id Instance ID to be verified. Use 0 for non-instanced draw calls. 1671 * @param data Contents of the rendertarget after the test has finished rendering. 1672 **/ 1673 void GeometryShaderRenderingPointsCase::verify(_draw_call_type drawcall_type, unsigned int instance_id, 1674 const unsigned char* data) 1675 { 1676 /* The array is directly related to vertex shader contents for "points" and "line_strip" 1677 * outputs */ 1678 static const unsigned char ref_data[] = { 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 1679 0, 0, 0, 255, 255, 255, 0, 0, 255, 0, 255, 0, 1680 255, 0, 0, 255, 255, 255, 255, 0, 255, 255, 0, 255 }; 1681 /* The array refers to colors as defined in vertex shader used for "triangle_strip" 1682 * output. 1683 */ 1684 static const unsigned char ref_data_triangle_strip[] = { 1685 (unsigned char)(0.1f * 255), (unsigned char)(0.8f * 255), 0, 0, 1686 (unsigned char)(0.2f * 255), (unsigned char)(0.7f * 255), 0, 0, 1687 (unsigned char)(0.3f * 255), (unsigned char)(0.6f * 255), 255, 0, 1688 (unsigned char)(0.4f * 255), (unsigned char)(0.5f * 255), 0, 255, 1689 (unsigned char)(0.5f * 255), (unsigned char)(0.4f * 255), 0, 0, 1690 (unsigned char)(0.6f * 255), (unsigned char)(0.3f * 255), 255, 0, 1691 (unsigned char)(0.7f * 255), (unsigned char)(0.2f * 255), 0, 255, 1692 (unsigned char)(0.8f * 255), (unsigned char)(0.1f * 255), 255, 0 1693 }; 1694 unsigned int rt_height = 0; 1695 unsigned int rt_width = 0; 1696 1697 /* Retrieve render-target size */ 1698 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED || 1699 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED) 1700 { 1701 getRenderTargetSize(getAmountOfDrawInstances(), &rt_width, &rt_height); 1702 } 1703 else 1704 { 1705 getRenderTargetSize(1, &rt_width, &rt_height); 1706 } 1707 1708 switch (m_output_type) 1709 { 1710 case SHADER_OUTPUT_TYPE_LINE_STRIP: 1711 { 1712 for (unsigned int n_point = 0; n_point < 8 /* points */; ++n_point) 1713 { 1714 /* Each point takes a 7x7 block. The test should verify that the second "nested" block 1715 * is of the valid color. Blocks can be built on top of each other if instanced draw 1716 * calls are used. */ 1717 const unsigned char* reference_data = NULL; 1718 const unsigned char* rendered_data = NULL; 1719 const int row_width = rt_width * 4 /* components */; 1720 const int sample_region_edge_px = 5 /* pixels */; 1721 1722 for (int n_edge = 0; n_edge < 4 /* edges */; ++n_edge) 1723 { 1724 /* Edge 1: TL->TR 1725 * Edge 2: TR->BR 1726 * Edge 3: BR->BL 1727 * Edge 4: BL->TL 1728 */ 1729 int dx = 0; 1730 int dy = 0; 1731 int x = 0; 1732 int x_start = 0; 1733 int y = 0; 1734 int y_start = 0; 1735 1736 switch (n_edge) 1737 { 1738 /* NOTE: The numbers here are as per test spec */ 1739 case 0: 1740 dx = 1 /* px */; 1741 dy = 0 /* px */; 1742 x_start = 1 /* px */; 1743 y_start = 1 /* px */; 1744 break; 1745 case 1: 1746 dx = 0 /* px */; 1747 dy = 1 /* px */; 1748 x_start = 5 /* px */; 1749 y_start = 1 /* px */; 1750 break; 1751 case 2: 1752 dx = -1 /* px */; 1753 dy = 0 /* px */; 1754 x_start = 5 /* px */; 1755 y_start = 5 /* px */; 1756 break; 1757 case 3: 1758 dx = 0 /* px */; 1759 dy = -1 /* px */; 1760 x_start = 1 /* px */; 1761 y_start = 5 /* px */; 1762 break; 1763 1764 default: 1765 { 1766 TCU_FAIL("Invalid edge index"); 1767 } 1768 } /* switch (n_edge) */ 1769 1770 /* What color should the pixels have? */ 1771 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS || 1772 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED) 1773 { 1774 reference_data = ref_data + n_point * 4 /* components */; 1775 x = x_start + n_point * 7 /* pixel block size */; 1776 y = y_start + instance_id * 7 /* pixel block size */; 1777 } 1778 else 1779 { 1780 int index = m_unordered_elements_data[n_point]; 1781 1782 reference_data = ref_data + (8 - 1 - index) * 4 /* components */; 1783 x = x_start + index * 7 /* pixel block size */; 1784 y = y_start + instance_id * 7 /* pixel block size */; 1785 } 1786 1787 /* Verify edge pixels */ 1788 for (int n_pixel = 0; n_pixel < sample_region_edge_px; ++n_pixel) 1789 { 1790 rendered_data = data + y * row_width + x * 4 /* components */; 1791 1792 if (memcmp(rendered_data, reference_data, 4 /* components */) != 0) 1793 { 1794 m_testCtx.getLog() << tcu::TestLog::Message << "At (" << (int)x << ", " << (int)y 1795 << "), " 1796 "rendered data (" 1797 << (int)rendered_data[0] << ", " << (int)rendered_data[1] << ", " 1798 << (int)rendered_data[2] << ", " << (int)rendered_data[3] 1799 << ") " 1800 "is different from reference data (" 1801 << (int)reference_data[0] << ", " << (int)reference_data[1] << ", " 1802 << (int)reference_data[2] << ", " << (int)reference_data[3] << ")" 1803 << tcu::TestLog::EndMessage; 1804 1805 TCU_FAIL("Data comparison failed"); 1806 } /* if (data comparison failed) */ 1807 1808 /* Move to next pixel */ 1809 x += dx; 1810 y += dy; 1811 } /* for (all pixels) */ 1812 } /* for (all edges) */ 1813 } /* for (all points) */ 1814 1815 break; 1816 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */ 1817 1818 case SHADER_OUTPUT_TYPE_POINTS: 1819 { 1820 /* For each 3px high row, we want to sample the second row. Area of a single "pixel" (incl. delta) 1821 * can take no more than 5px, with the actual sampled area located in the second pixel. 1822 */ 1823 const int sample_region_width_px = 5; /* pixels */ 1824 1825 for (int n = 0; n < 8 /* points */; ++n) 1826 { 1827 int x = 0; 1828 int y = 0; 1829 const unsigned char* reference_data = NULL; 1830 const unsigned char* rendered_data = NULL; 1831 1832 /* Different ordering is used for indexed draw calls */ 1833 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS || 1834 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED || 1835 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS) 1836 { 1837 /* For indexed calls, vertex data is laid out in a reversed ordered */ 1838 int index = m_unordered_elements_data[n]; 1839 1840 x = index * sample_region_width_px + 1; 1841 y = instance_id * 5 + 1; /* middle row */ 1842 reference_data = ref_data + ((8 - 1 - index) * 4 /* components */); 1843 rendered_data = data + (y * rt_width + x) * 4 /* components */; 1844 } /* if (draw call is indiced) */ 1845 else 1846 { 1847 x = n * sample_region_width_px + 1; 1848 y = instance_id * 5 + 1; /* middle row */ 1849 reference_data = ref_data + (n * 4 /* components */); 1850 rendered_data = data + (y * rt_width + x) * 4 /* components */; 1851 } 1852 1853 if (memcmp(rendered_data, reference_data, 4 /* components */) != 0) 1854 { 1855 m_testCtx.getLog() << tcu::TestLog::Message << "Reference data: [" << (int)reference_data[0] << ", " 1856 << (int)reference_data[1] << ", " << (int)reference_data[2] << ", " 1857 << (int)reference_data[3] << "] " 1858 "for pixel at (" 1859 << x << ", " << y << ") " 1860 "does not match [" 1861 << (int)rendered_data[0] << ", " << (int)rendered_data[1] << ", " 1862 << (int)rendered_data[2] << ", " << (int)rendered_data[3] << ")."; 1863 1864 TCU_FAIL("Data comparison failed."); 1865 } /* if (memcmp(rendered_data, reference_data, 4) != 0) */ 1866 } /* for (all points) */ 1867 1868 break; 1869 } /* case SHADER_OUTPUT_TYPE_POINTS: */ 1870 1871 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 1872 { 1873 /* A pair of adjacent triangles is contained within a 6x6 bounding box. 1874 * The box is defined by top-left corner which is located at input point's 1875 * location. 1876 * The left triangle should only use red channel, the one on the right 1877 * should only use green channel. 1878 * We find centroid for each triangle, sample its color and make sure 1879 * it's valid. 1880 */ 1881 for (int n_point = 0; n_point < 8 /* points */; ++n_point) 1882 { 1883 const unsigned int epsilon = 1; 1884 int point_x = 0; 1885 int point_y = 6 * instance_id; 1886 const unsigned char* rendered_data = NULL; 1887 const unsigned char* reference_data = 0; 1888 const unsigned int row_width = rt_width * 4 /* components */; 1889 int t1[6 /* 3 * {x, y} */] = { 0 }; 1890 int t2[6 /* 3 * {x, y} */] = { 0 }; 1891 int t1_center[2 /* {x, y} */] = { 0 }; 1892 int t2_center[2 /* {x, y} */] = { 0 }; 1893 1894 /* Different ordering is used for indexed draw calls */ 1895 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS || 1896 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED || 1897 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS) 1898 { 1899 int index = m_unordered_elements_data[n_point]; 1900 1901 point_x = 6 * index; 1902 reference_data = ref_data_triangle_strip + (8 - 1 - index) * 4 /* components */; 1903 } 1904 else 1905 { 1906 point_x = 6 * n_point; 1907 reference_data = ref_data_triangle_strip + n_point * 4 /* components */; 1908 } 1909 1910 /* Calculate triangle vertex locations (corresponds to geometry shader logic) */ 1911 t1[0] = point_x; 1912 t1[1] = point_y + 6; 1913 t1[2] = point_x; 1914 t1[3] = point_y; 1915 t1[4] = point_x + 6; 1916 t1[5] = point_y + 6; 1917 1918 t2[0] = point_x + 6; 1919 t2[1] = point_y + 6; 1920 t2[2] = point_x; 1921 t2[3] = point_y; 1922 t2[4] = point_x + 6; 1923 t2[5] = point_y; 1924 1925 /* Calculate centroid locations */ 1926 t1_center[0] = (t1[0] + t1[2] + t1[4]) / 3; 1927 t2_center[0] = (t2[0] + t2[2] + t2[4]) / 3; 1928 t1_center[1] = (t1[1] + t1[3] + t1[5]) / 3; 1929 t2_center[1] = (t2[1] + t2[3] + t2[5]) / 3; 1930 1931 /* Check the first triangle */ 1932 point_x = t1_center[0]; 1933 point_y = t1_center[1]; 1934 1935 rendered_data = data + point_y * row_width + point_x * 4 /* components */; 1936 1937 if ((unsigned int)de::abs((int)rendered_data[0] - reference_data[0]) > epsilon || rendered_data[1] != 0 || 1938 rendered_data[2] != 0 || rendered_data[3] != 0) 1939 { 1940 m_testCtx.getLog() << tcu::TestLog::Message << "At (" << (int)point_x << ", " << (int)point_y << ") " 1941 << "rendered pixel (" << (int)rendered_data[0] << ", " << (int)rendered_data[1] 1942 << ", " << (int)rendered_data[2] << ", " << (int)rendered_data[3] << ") " 1943 << "is different than (" << (int)reference_data[0] << ", 0, 0, 0)." 1944 << tcu::TestLog::EndMessage; 1945 1946 TCU_FAIL("Data comparison failed."); 1947 } 1948 1949 /* Check the other triangle */ 1950 point_x = t2_center[0]; 1951 point_y = t2_center[1]; 1952 1953 rendered_data = data + point_y * row_width + point_x * 4 /* components */; 1954 1955 if (rendered_data[0] != 0 || (unsigned int)de::abs((int)rendered_data[1] - reference_data[1]) > epsilon || 1956 rendered_data[2] != 0 || rendered_data[3] != 0) 1957 { 1958 m_testCtx.getLog() << tcu::TestLog::Message << "At (" << (int)point_x << ", " << (int)point_y << ") " 1959 << "rendered pixel (" << (int)rendered_data[0] << ", " << (int)rendered_data[1] 1960 << ", " << (int)rendered_data[2] << ", " << (int)rendered_data[3] << ") " 1961 << "is different than (0, " << (int)reference_data[1] << ", 0, 0)." 1962 << tcu::TestLog::EndMessage; 1963 1964 TCU_FAIL("Data comparison failed."); 1965 } 1966 } /* for (all points) */ 1967 1968 break; 1969 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:*/ 1970 1971 default: 1972 { 1973 TCU_FAIL("Unsupported output layout qualifier requested."); 1974 1975 break; 1976 } 1977 } /* switch(m_output_type) */ 1978 } 1979 1980 /* "lines" input primitive test implementation */ 1981 /** Constructor. 1982 * 1983 * @param use_adjacency_data true if the test case is being instantiated for draw call modes that will 1984 * features adjacency data, 1985 * false otherwise. 1986 * @param drawcall_mode GL draw call mode that will be used for the tests. 1987 * @param output_type Shader output type that the test case is being instantiated for. 1988 * @param context Rendering context; 1989 * @param testContext Test context; 1990 * @param name Test name. 1991 **/ 1992 GeometryShaderRenderingLinesCase::GeometryShaderRenderingLinesCase(Context& context, const ExtParameters& extParams, 1993 const char* name, bool use_adjacency_data, 1994 glw::GLenum drawcall_mode, 1995 _shader_output_type output_type) 1996 : GeometryShaderRenderingCase( 1997 context, extParams, name, 1998 "Verifies all draw calls work correctly for specific input+output+draw call mode combination") 1999 , m_output_type(output_type) 2000 , m_drawcall_mode(drawcall_mode) 2001 , m_use_adjacency_data(use_adjacency_data) 2002 , m_raw_array_instanced_data(0) 2003 , m_raw_array_instanced_data_size(0) 2004 , m_raw_array_noninstanced_data(0) 2005 , m_raw_array_noninstanced_data_size(0) 2006 , m_unordered_array_instanced_data(0) 2007 , m_unordered_array_instanced_data_size(0) 2008 , m_unordered_array_noninstanced_data(0) 2009 , m_unordered_array_noninstanced_data_size(0) 2010 , m_unordered_elements_instanced_data(0) 2011 , m_unordered_elements_instanced_data_size(0) 2012 , m_unordered_elements_noninstanced_data(0) 2013 , m_unordered_elements_noninstanced_data_size(0) 2014 , m_unordered_elements_max_index(16) /* maximum amount of vertices generated for this case */ 2015 , m_unordered_elements_min_index(0) 2016 { 2017 /* Sanity checks */ 2018 if (!m_use_adjacency_data) 2019 { 2020 if (drawcall_mode != GL_LINE_LOOP && drawcall_mode != GL_LINE_STRIP && drawcall_mode != GL_LINES) 2021 { 2022 TCU_FAIL("Only GL_LINE_LOOP or GL_LINE_STRIP or GL_LINES draw call modes are supported for 'lines' " 2023 "geometry shader input layout qualifier test implementation"); 2024 } 2025 } 2026 else 2027 { 2028 if (drawcall_mode != GL_LINES_ADJACENCY_EXT && drawcall_mode != GL_LINE_STRIP_ADJACENCY_EXT) 2029 { 2030 TCU_FAIL("Only GL_LINES_ADJACENCY_EXT or GL_LINE_STRIP_ADJACENCY_EXT draw call modes are supported for " 2031 "'lines_adjacency' geometry shader input layout qualifier test implementation"); 2032 } 2033 } 2034 2035 if (output_type != SHADER_OUTPUT_TYPE_POINTS && output_type != SHADER_OUTPUT_TYPE_LINE_STRIP && 2036 output_type != SHADER_OUTPUT_TYPE_TRIANGLE_STRIP) 2037 { 2038 TCU_FAIL("Unsupported output layout qualifier type requested for 'lines' geometry shader input layout " 2039 "qualifier test implementation"); 2040 } 2041 2042 /* Generate data in two flavors - one for non-instanced case, the other one for instanced case */ 2043 for (int n_case = 0; n_case < 2 /* cases */; ++n_case) 2044 { 2045 bool is_instanced = (n_case != 0); 2046 int n_instances = 0; 2047 float** raw_arrays_data_ptr = NULL; 2048 unsigned int* raw_arrays_data_size_ptr = NULL; 2049 unsigned int rendertarget_height = 0; 2050 unsigned int rendertarget_width = 0; 2051 float** unordered_arrays_data_ptr = NULL; 2052 unsigned int* unordered_arrays_data_size_ptr = NULL; 2053 unsigned char** unordered_elements_data_ptr = NULL; 2054 unsigned int* unordered_elements_data_size_ptr = NULL; 2055 2056 if (!is_instanced) 2057 { 2058 /* Non-instanced case */ 2059 n_instances = 1; 2060 raw_arrays_data_ptr = &m_raw_array_noninstanced_data; 2061 raw_arrays_data_size_ptr = &m_raw_array_noninstanced_data_size; 2062 unordered_arrays_data_ptr = &m_unordered_array_noninstanced_data; 2063 unordered_arrays_data_size_ptr = &m_unordered_array_noninstanced_data_size; 2064 unordered_elements_data_ptr = &m_unordered_elements_noninstanced_data; 2065 unordered_elements_data_size_ptr = &m_unordered_elements_noninstanced_data_size; 2066 } 2067 else 2068 { 2069 /* Instanced case */ 2070 n_instances = getAmountOfDrawInstances(); 2071 raw_arrays_data_ptr = &m_raw_array_instanced_data; 2072 raw_arrays_data_size_ptr = &m_raw_array_instanced_data_size; 2073 unordered_arrays_data_ptr = &m_unordered_array_instanced_data; 2074 unordered_arrays_data_size_ptr = &m_unordered_array_instanced_data_size; 2075 unordered_elements_data_ptr = &m_unordered_elements_instanced_data; 2076 unordered_elements_data_size_ptr = &m_unordered_elements_instanced_data_size; 2077 } 2078 2079 getRenderTargetSize(n_instances, &rendertarget_width, &rendertarget_height); 2080 2081 /* Store full-screen quad coordinates that will be used for actual array data generation. */ 2082 float dx = 2.0f / float(rendertarget_width); 2083 float dy = 2.0f / float(rendertarget_height); 2084 2085 /* Generate raw vertex array data */ 2086 2087 float* raw_array_data_traveller = NULL; 2088 unsigned int single_rt_height = 0; 2089 unsigned int single_rt_width = 0; 2090 unsigned int whole_rt_width = 0; 2091 unsigned int whole_rt_height = 0; 2092 2093 switch (m_drawcall_mode) 2094 { 2095 case GL_LINE_LOOP: 2096 { 2097 *raw_arrays_data_size_ptr = 4 /* vertices making up the line strip */ * 4 /* components */ * sizeof(float); 2098 2099 break; 2100 } 2101 2102 case GL_LINE_STRIP: 2103 { 2104 *raw_arrays_data_size_ptr = 5 /* vertices making up the line strip */ * 4 /* components */ * sizeof(float); 2105 2106 break; 2107 } 2108 2109 case GL_LINE_STRIP_ADJACENCY_EXT: 2110 { 2111 *raw_arrays_data_size_ptr = 2112 (5 /* vertices making up the line strip */ + 2 /* additional start/end adjacency vertices */) * 2113 4 /* components */ 2114 * sizeof(float); 2115 2116 break; 2117 } 2118 2119 case GL_LINES: 2120 { 2121 *raw_arrays_data_size_ptr = 2122 2 /* points per line segment */ * 4 /* lines */ * 4 /* components */ * sizeof(float); 2123 2124 break; 2125 } 2126 2127 case GL_LINES_ADJACENCY_EXT: 2128 { 2129 *raw_arrays_data_size_ptr = 2130 4 /* points per line segment */ * 4 /* lines */ * 4 /* components */ * sizeof(float); 2131 2132 break; 2133 } 2134 2135 default: 2136 { 2137 TCU_FAIL("Unrecognized draw call mode"); 2138 } 2139 } /* switch (m_drawcall_mode) */ 2140 2141 *raw_arrays_data_ptr = new float[*raw_arrays_data_size_ptr / sizeof(float)]; 2142 raw_array_data_traveller = *raw_arrays_data_ptr; 2143 2144 getRenderTargetSize(1, &single_rt_width, &single_rt_height); 2145 getRenderTargetSize(getAmountOfDrawInstances(), &whole_rt_width, &whole_rt_height); 2146 2147 /* Generate the data */ 2148 float end_y = 0; 2149 std::vector<tcu::Vec4> quad_coordinates; 2150 float start_y = 0; 2151 float w = 1.0f; 2152 2153 if (n_instances != 1) 2154 { 2155 float delta = float(single_rt_height) / float(whole_rt_height); 2156 2157 /* Y coordinates are calculated in a vertex shader in multi-instanced case */ 2158 start_y = 0.0f; 2159 end_y = 0.0f; 2160 w = delta; 2161 } 2162 else 2163 { 2164 start_y = -1; 2165 end_y = 1; 2166 } 2167 2168 /* X, Y coordinates: correspond to X & Y locations of the vertex. 2169 * Z coordinates: set to 0 if the vertex is located on top edge, otherwise set to 1. 2170 * W coordinate: stores the delta (single-instanced RT height / multi-instanced RT height). 2171 */ 2172 float dx_multiplier = 1.5f; /* Default value for lines and line_strip output layout qualifiers */ 2173 float dy_multiplier = 1.5f; /* Default value for lines and line_strip output layout qualifiers */ 2174 2175 if (m_output_type == SHADER_OUTPUT_TYPE_TRIANGLE_STRIP) 2176 { 2177 dx_multiplier = 0.0f; 2178 dy_multiplier = 0.0f; 2179 } 2180 2181 quad_coordinates.push_back(tcu::Vec4(-1 + dx_multiplier * dx, start_y + dy_multiplier * dy, 0, w)); /* TL */ 2182 quad_coordinates.push_back(tcu::Vec4(1 - dx_multiplier * dx, start_y + dy_multiplier * dy, 0, w)); /* TR */ 2183 quad_coordinates.push_back(tcu::Vec4(1 - dx_multiplier * dx, end_y - dy_multiplier * dy, 1, w)); /* BR */ 2184 quad_coordinates.push_back(tcu::Vec4(-1 + dx_multiplier * dx, end_y - dy_multiplier * dy, 1, w)); /* BL */ 2185 2186 for (int n_line_segment = 0; n_line_segment < 4 /* edges */; ++n_line_segment) 2187 { 2188 /* Note we need to clamp coordinate indices here */ 2189 int coordinate0_index = (4 + n_line_segment - 1) % 4; /* protect against negative modulo values */ 2190 int coordinate1_index = (n_line_segment) % 4; 2191 int coordinate2_index = (n_line_segment + 1) % 4; 2192 int coordinate3_index = (n_line_segment + 2) % 4; 2193 const tcu::Vec4& coordinate0 = quad_coordinates[coordinate0_index]; 2194 const tcu::Vec4& coordinate1 = quad_coordinates[coordinate1_index]; 2195 const tcu::Vec4& coordinate2 = quad_coordinates[coordinate2_index]; 2196 const tcu::Vec4& coordinate3 = quad_coordinates[coordinate3_index]; 2197 2198 /* For GL_LINES, we need to explicitly define start & end-points for each segment. 2199 * For GL_LINE_STRIP, we only need to explicitly define first start point. Following 2200 * vertices define subsequent points making up the line strip. 2201 * For GL_LINE_LOOP, we need all the data we used for GL_LINE_STRIP excluding the very 2202 * last vertex. 2203 * 2204 * For GL_LINES_ADJACENCY_EXT, we extend GL_LINES data by vertices preceding and following points 2205 * that make up a single line segment. 2206 * For GL_LINE_STRIP_ADJACENCY_EXT, we extend GL_LINE_STRIP data by including a vertex preceding the 2207 * actual first vertex, and by including a vertex that follows the end vertex closing the line 2208 * strip. 2209 */ 2210 2211 /* Preceding vertex */ 2212 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || 2213 (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT && n_line_segment == 0)) 2214 { 2215 *raw_array_data_traveller = coordinate0.x(); 2216 raw_array_data_traveller++; 2217 *raw_array_data_traveller = coordinate0.y(); 2218 raw_array_data_traveller++; 2219 *raw_array_data_traveller = coordinate0.z(); 2220 raw_array_data_traveller++; 2221 *raw_array_data_traveller = coordinate0.w(); 2222 raw_array_data_traveller++; 2223 } 2224 2225 /* Vertex 1 */ 2226 if ((m_drawcall_mode != GL_LINE_STRIP && m_drawcall_mode != GL_LINE_STRIP_ADJACENCY_EXT && 2227 m_drawcall_mode != GL_LINE_LOOP) || 2228 ((m_drawcall_mode == GL_LINE_STRIP || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT || 2229 m_drawcall_mode == GL_LINE_LOOP) && 2230 n_line_segment == 0)) 2231 { 2232 *raw_array_data_traveller = coordinate1.x(); 2233 raw_array_data_traveller++; 2234 *raw_array_data_traveller = coordinate1.y(); 2235 raw_array_data_traveller++; 2236 *raw_array_data_traveller = coordinate1.z(); 2237 raw_array_data_traveller++; 2238 *raw_array_data_traveller = coordinate1.w(); 2239 raw_array_data_traveller++; 2240 } 2241 2242 /* Vertex 2 */ 2243 if (m_drawcall_mode != GL_LINE_LOOP || (m_drawcall_mode == GL_LINE_LOOP && n_line_segment != 3)) 2244 { 2245 *raw_array_data_traveller = coordinate2.x(); 2246 raw_array_data_traveller++; 2247 *raw_array_data_traveller = coordinate2.y(); 2248 raw_array_data_traveller++; 2249 *raw_array_data_traveller = coordinate2.z(); 2250 raw_array_data_traveller++; 2251 *raw_array_data_traveller = coordinate2.w(); 2252 raw_array_data_traveller++; 2253 } 2254 2255 /* Following vertex */ 2256 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || 2257 (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT && n_line_segment == 3)) 2258 { 2259 *raw_array_data_traveller = coordinate3.x(); 2260 raw_array_data_traveller++; 2261 *raw_array_data_traveller = coordinate3.y(); 2262 raw_array_data_traveller++; 2263 *raw_array_data_traveller = coordinate3.z(); 2264 raw_array_data_traveller++; 2265 *raw_array_data_traveller = coordinate3.w(); 2266 raw_array_data_traveller++; 2267 } 2268 } /* for (all line segments) */ 2269 2270 /* Generate unordered data: 2271 * 2272 * The way we organise data in this case is that: 2273 * 2274 * - For index data, start and end points are flipped for each line segment. 2275 * - For vertex data, vertex locations are stored to correspond to this order. 2276 * 2277 * We *DO NOT* modify the order in which we draw the line segments, since that could make the verification 2278 * process even more complex than it already is. 2279 */ 2280 switch (m_drawcall_mode) 2281 { 2282 case GL_LINE_LOOP: 2283 { 2284 *unordered_arrays_data_size_ptr = *raw_arrays_data_size_ptr; 2285 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr / sizeof(float)]; 2286 2287 *unordered_elements_data_size_ptr = sizeof(unsigned char) * 4 /* points */; 2288 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr]; 2289 2290 for (unsigned int index = 0; index < 4 /* points */; ++index) 2291 { 2292 /* Gives 3-{0, 1, 2, 3} */ 2293 int new_index = 3 - index; 2294 2295 /* Store index data */ 2296 (*unordered_elements_data_ptr)[index] = (unsigned char)new_index; 2297 2298 /* Store vertex data */ 2299 memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */, 2300 (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */); 2301 } /* for (all indices) */ 2302 2303 break; 2304 } 2305 2306 case GL_LINE_STRIP: 2307 { 2308 *unordered_arrays_data_size_ptr = *raw_arrays_data_size_ptr; 2309 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr / sizeof(float)]; 2310 2311 *unordered_elements_data_size_ptr = sizeof(unsigned char) * 5 /* points */; 2312 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr]; 2313 2314 for (unsigned int index = 0; index < 5 /* points */; ++index) 2315 { 2316 /* Gives 4-{0, 1, 2, 3, 4} */ 2317 int new_index = 4 - index; 2318 2319 /* Store index data */ 2320 (*unordered_elements_data_ptr)[index] = (unsigned char)new_index; 2321 2322 /* Store vertex data */ 2323 memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */, 2324 (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */); 2325 } /* for (all indices) */ 2326 2327 break; 2328 } 2329 2330 case GL_LINES: 2331 { 2332 *unordered_arrays_data_size_ptr = sizeof(float) * 8 /* points */ * 4 /* components */; 2333 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr / sizeof(float)]; 2334 2335 *unordered_elements_data_size_ptr = sizeof(unsigned char) * 8 /* points */; 2336 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr]; 2337 2338 for (unsigned int index = 0; index < 8 /* points */; ++index) 2339 { 2340 /* Gives 7-{(1, 0), (3, 2), (5, 4), (7, 6)} */ 2341 int new_index = 7 - ((index / 2) * 2 + (index + 1) % 2); 2342 2343 /* Store index data */ 2344 (*unordered_elements_data_ptr)[index] = (unsigned char)new_index; 2345 2346 /* Store vertex data */ 2347 memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */, 2348 (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */); 2349 } /* for (all indices) */ 2350 2351 break; 2352 } /* case GL_LINES: */ 2353 2354 case GL_LINES_ADJACENCY_EXT: 2355 case GL_LINE_STRIP_ADJACENCY_EXT: 2356 { 2357 /* For adjacency case, we may simplify the approach. Since the index data is now also going 2358 * to include references to adjacent vertices, we can use the same ordering as in raw arrays data. 2359 * Should the implementation misinterpret the data, it will treat adjacent vertex indices as actual 2360 * vertex indices, breaking the verification. 2361 */ 2362 /* For array data, just point to unique vertex locations. Use the same order as in raw arrays data case 2363 * to simplify the vertex shader for the pass. 2364 **/ 2365 *unordered_arrays_data_size_ptr = sizeof(float) * 4 /* points */ * 4 /* components */; 2366 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr / sizeof(float)]; 2367 2368 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT) 2369 { 2370 *unordered_elements_data_size_ptr = 2371 sizeof(unsigned char) * 4 /* vertices per line segment */ * 4 /* line segments */; 2372 } 2373 else 2374 { 2375 *unordered_elements_data_size_ptr = 2376 sizeof(unsigned char) * (5 /* vertices making up a line strip */ + 2 /* start/end vertices */); 2377 } 2378 2379 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr]; 2380 2381 for (int n = 0; n < 4; ++n) 2382 { 2383 (*unordered_arrays_data_ptr)[4 * n + 0] = quad_coordinates[n].x(); 2384 (*unordered_arrays_data_ptr)[4 * n + 1] = quad_coordinates[n].y(); 2385 (*unordered_arrays_data_ptr)[4 * n + 2] = quad_coordinates[n].z(); 2386 (*unordered_arrays_data_ptr)[4 * n + 3] = quad_coordinates[n].w(); 2387 } 2388 2389 /* For elements data, we just walk over the quad and make sure we turn a full circle */ 2390 unsigned char* elements_data_traveller_ptr = *unordered_elements_data_ptr; 2391 2392 for (int n = 0; n < 4; ++n) 2393 { 2394 int component0_index = (n + 4 - 1) % 4; /* protect against underflow */ 2395 int component1_index = (n) % 4; 2396 int component2_index = (n + 1) % 4; 2397 int component3_index = (n + 2) % 4; 2398 2399 if (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) 2400 { 2401 /* Vertex adjacent to start vertex - include only at start */ 2402 if (n == 0) 2403 { 2404 *elements_data_traveller_ptr = (unsigned char)component0_index; 2405 2406 ++elements_data_traveller_ptr; 2407 } 2408 2409 /* Vertex index */ 2410 *elements_data_traveller_ptr = (unsigned char)component1_index; 2411 2412 ++elements_data_traveller_ptr; 2413 2414 /* End vertex and the adjacent vertex - include only for final iteration */ 2415 if (n == 3) 2416 { 2417 /* End vertex */ 2418 *elements_data_traveller_ptr = (unsigned char)component2_index; 2419 2420 ++elements_data_traveller_ptr; 2421 2422 /* Adjacent vertex */ 2423 *elements_data_traveller_ptr = (unsigned char)component3_index; 2424 2425 ++elements_data_traveller_ptr; 2426 } 2427 } 2428 else 2429 { 2430 /* GL_LINES_ADJACENCY_EXT */ 2431 *elements_data_traveller_ptr = (unsigned char)component0_index; 2432 ++elements_data_traveller_ptr; 2433 *elements_data_traveller_ptr = (unsigned char)component1_index; 2434 ++elements_data_traveller_ptr; 2435 *elements_data_traveller_ptr = (unsigned char)component2_index; 2436 ++elements_data_traveller_ptr; 2437 *elements_data_traveller_ptr = (unsigned char)component3_index; 2438 ++elements_data_traveller_ptr; 2439 } 2440 } 2441 2442 break; 2443 } /* case GL_LINES: */ 2444 2445 default: 2446 { 2447 TCU_FAIL("Unrecognized draw call mode"); 2448 } 2449 } /* switch (m_drawcall_mode) */ 2450 } /* for (both cases) */ 2451 } 2452 2453 /** Destructor. */ 2454 GeometryShaderRenderingLinesCase::~GeometryShaderRenderingLinesCase() 2455 { 2456 if (m_raw_array_instanced_data != NULL) 2457 { 2458 delete[] m_raw_array_instanced_data; 2459 2460 m_raw_array_instanced_data = NULL; 2461 } 2462 2463 if (m_raw_array_noninstanced_data != NULL) 2464 { 2465 delete[] m_raw_array_noninstanced_data; 2466 2467 m_raw_array_noninstanced_data = NULL; 2468 } 2469 2470 if (m_unordered_array_instanced_data != NULL) 2471 { 2472 delete[] m_unordered_array_instanced_data; 2473 2474 m_unordered_array_instanced_data = NULL; 2475 } 2476 2477 if (m_unordered_array_noninstanced_data != NULL) 2478 { 2479 delete[] m_unordered_array_noninstanced_data; 2480 2481 m_unordered_array_noninstanced_data = NULL; 2482 } 2483 2484 if (m_unordered_elements_instanced_data != NULL) 2485 { 2486 delete[] m_unordered_elements_instanced_data; 2487 2488 m_unordered_elements_instanced_data = NULL; 2489 } 2490 2491 if (m_unordered_elements_noninstanced_data != NULL) 2492 { 2493 delete[] m_unordered_elements_noninstanced_data; 2494 2495 m_unordered_elements_noninstanced_data = NULL; 2496 } 2497 } 2498 2499 /** Retrieves amount of instances that should be drawn with glDraw*Elements() calls. 2500 * 2501 * @return As per description. 2502 **/ 2503 unsigned int GeometryShaderRenderingLinesCase::getAmountOfDrawInstances() 2504 { 2505 return 4; 2506 } 2507 2508 /** Retrieves amount of indices that should be used for rendering a single instance 2509 * (glDraw*Elements() calls only) 2510 * 2511 * @return As per description. 2512 */ 2513 unsigned int GeometryShaderRenderingLinesCase::getAmountOfElementsPerInstance() 2514 { 2515 unsigned int result = 0; 2516 2517 switch (m_drawcall_mode) 2518 { 2519 case GL_LINE_LOOP: 2520 result = 4; 2521 break; 2522 case GL_LINE_STRIP: 2523 result = 5; 2524 break; 2525 case GL_LINE_STRIP_ADJACENCY_EXT: 2526 result = 7; 2527 break; 2528 case GL_LINES: 2529 result = 8; 2530 break; 2531 case GL_LINES_ADJACENCY_EXT: 2532 result = 16; 2533 break; 2534 2535 default: 2536 { 2537 TCU_FAIL("Unrecognized draw call mode"); 2538 } 2539 } /* switch (m_drawcall_mode) */ 2540 2541 return result; 2542 } 2543 2544 /** Retrieves amount of vertices that should be used for rendering a single instance 2545 * (glDrawArrays*() calls only) 2546 * 2547 * @return As per description. 2548 **/ 2549 unsigned int GeometryShaderRenderingLinesCase::getAmountOfVerticesPerInstance() 2550 { 2551 unsigned int result = 0; 2552 2553 switch (m_drawcall_mode) 2554 { 2555 case GL_LINE_LOOP: 2556 result = 4; 2557 break; 2558 case GL_LINE_STRIP: 2559 result = 5; 2560 break; 2561 case GL_LINE_STRIP_ADJACENCY_EXT: 2562 result = 7; 2563 break; 2564 case GL_LINES: 2565 result = 8; 2566 break; 2567 case GL_LINES_ADJACENCY_EXT: 2568 result = 16; 2569 break; 2570 2571 default: 2572 { 2573 TCU_FAIL("Unrecognized draw call mode"); 2574 } 2575 } /* switch (m_drawcall_mode) */ 2576 2577 return result; 2578 } 2579 2580 /** Draw call mode that should be used glDraw*() calls. 2581 * 2582 * @return As per description. 2583 **/ 2584 glw::GLenum GeometryShaderRenderingLinesCase::getDrawCallMode() 2585 { 2586 return m_drawcall_mode; 2587 } 2588 2589 /** Source code for a fragment shader that should be used for the test. 2590 * 2591 * @return As per description. 2592 **/ 2593 std::string GeometryShaderRenderingLinesCase::getFragmentShaderCode() 2594 { 2595 static std::string fs_code = "${VERSION}\n" 2596 "\n" 2597 "precision highp float;\n" 2598 "\n" 2599 "in vec4 gs_fs_color;\n" 2600 "out vec4 result;\n" 2601 "\n" 2602 "void main()\n" 2603 "{\n" 2604 " result = gs_fs_color;\n" 2605 "}\n"; 2606 2607 return fs_code; 2608 } 2609 2610 /** Source code for a geometry shader that should be used for the test. 2611 * 2612 * @return As per description. 2613 **/ 2614 std::string GeometryShaderRenderingLinesCase::getGeometryShaderCode() 2615 { 2616 static const char* lines_in_line_strip_out_gs_code_preamble = "${VERSION}\n" 2617 "\n" 2618 "${GEOMETRY_SHADER_ENABLE}\n" 2619 "\n" 2620 "layout(lines) in;\n" 2621 "layout(line_strip, max_vertices=6) out;\n" 2622 "\n" 2623 "#define N_VERTICES_IN (2)\n" 2624 "#define N_VERTEX0 (0)\n" 2625 "#define N_VERTEX1 (1)\n" 2626 "\n"; 2627 2628 static const char* lines_adjacency_in_line_strip_out_gs_code_preamble = "${VERSION}\n" 2629 "\n" 2630 "${GEOMETRY_SHADER_ENABLE}\n" 2631 "\n" 2632 "layout(lines_adjacency) in;\n" 2633 "layout(line_strip, max_vertices=6) out;\n" 2634 "\n" 2635 "#define N_VERTICES_IN (4)\n" 2636 "#define N_VERTEX0 (1)\n" 2637 "#define N_VERTEX1 (2)\n" 2638 "\n"; 2639 2640 static const char* lines_gs_code_main = "\n" 2641 "in vec4 vs_gs_color[N_VERTICES_IN];\n" 2642 "out vec4 gs_fs_color;\n" 2643 "\n" 2644 "uniform ivec2 renderingTargetSize;\n" 2645 "\n" 2646 "void main()\n" 2647 "{\n" 2648 " float dx = float(2.0) / float(renderingTargetSize.x);\n" 2649 " float dy = float(2.0) / float(renderingTargetSize.y);\n" 2650 "\n" 2651 " vec4 start_pos = gl_in[N_VERTEX0].gl_Position;\n" 2652 " vec4 end_pos = gl_in[N_VERTEX1].gl_Position;\n" 2653 " vec4 start_col = vs_gs_color[N_VERTEX0];\n" 2654 " vec4 end_col = vs_gs_color[N_VERTEX1];\n" 2655 "\n" 2656 /* Determine if this is a horizontal or vertical edge */ 2657 " if (start_pos.x != end_pos.x)\n" 2658 " {\n" 2659 /* Bottom line segment */ 2660 " gl_Position = vec4(-1.0, start_pos.y + dy, 0, 1);\n" 2661 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2662 " EmitVertex();\n" 2663 "\n" 2664 " gl_Position = vec4(1.0, end_pos.y + dy, 0, 1);\n" 2665 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2666 " EmitVertex();\n" 2667 " EndPrimitive();\n" 2668 /* Middle line segment */ 2669 " gl_Position = vec4(-1.0, start_pos.y, 0, 1);\n" 2670 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2671 " EmitVertex();\n" 2672 "\n" 2673 " gl_Position = vec4(1.0, end_pos.y, 0, 1);\n" 2674 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2675 " EmitVertex();\n" 2676 " EndPrimitive();\n" 2677 /* Top line segment */ 2678 " gl_Position = vec4(-1.0, start_pos.y - dy, 0, 1);\n" 2679 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2680 " EmitVertex();\n" 2681 "\n" 2682 " gl_Position = vec4(1.0, end_pos.y - dy, 0, 1);\n" 2683 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2684 " EmitVertex();\n" 2685 " EndPrimitive();\n" 2686 " }\n" 2687 " else\n" 2688 " {\n" 2689 /* Left line segment */ 2690 " gl_Position = vec4(start_pos.x - dx, start_pos.y, 0, 1);\n" 2691 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2692 " EmitVertex();\n" 2693 "\n" 2694 " gl_Position = vec4(end_pos.x - dx, end_pos.y, 0, 1);\n" 2695 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2696 " EmitVertex();\n" 2697 " EndPrimitive();\n" 2698 /* Middle line segment */ 2699 " gl_Position = vec4(start_pos.x, start_pos.y, 0, 1);\n" 2700 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2701 " EmitVertex();\n" 2702 "\n" 2703 " gl_Position = vec4(end_pos.x, end_pos.y, 0, 1);\n" 2704 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2705 " EmitVertex();\n" 2706 " EndPrimitive();\n" 2707 /* Right line segment */ 2708 " gl_Position = vec4(start_pos.x + dx, start_pos.y, 0, 1);\n" 2709 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2710 " EmitVertex();\n" 2711 "\n" 2712 " gl_Position = vec4(end_pos.x + dx, end_pos.y, 0, 1);\n" 2713 " gs_fs_color = mix(start_col, end_col, 0.5);\n" 2714 " EmitVertex();\n" 2715 " EndPrimitive();\n" 2716 " }\n" 2717 "}\n"; 2718 2719 static const char* lines_in_points_out_gs_code_preamble = "${VERSION}\n" 2720 "\n" 2721 "${GEOMETRY_SHADER_ENABLE}\n" 2722 "\n" 2723 "layout(lines) in;\n" 2724 "layout(points, max_vertices=72) out;\n" 2725 "\n" 2726 "#define N_VERTEX0 (0)\n" 2727 "#define N_VERTEX1 (1)\n" 2728 "#define N_VERTICES_IN (2)\n" 2729 "\n"; 2730 2731 static const char* lines_adjacency_in_points_out_gs_code_preamble = "${VERSION}\n" 2732 "\n" 2733 "${GEOMETRY_SHADER_ENABLE}\n" 2734 "\n" 2735 "layout(lines_adjacency) in;\n" 2736 "layout(points, max_vertices=72) out;\n" 2737 "\n" 2738 "#define N_VERTEX0 (1)\n" 2739 "#define N_VERTEX1 (2)\n" 2740 "#define N_VERTICES_IN (4)\n" 2741 "\n"; 2742 2743 static const char* points_gs_code_main = "\n" 2744 "in vec4 vs_gs_color[N_VERTICES_IN];\n" 2745 "out vec4 gs_fs_color;\n" 2746 "\n" 2747 "uniform ivec2 renderingTargetSize;\n" 2748 "\n" 2749 "void main()\n" 2750 "{\n" 2751 " float dx = float(2.0) / float(renderingTargetSize.x);\n" 2752 " float dy = float(2.0) / float(renderingTargetSize.y);\n" 2753 "\n" 2754 " vec4 start_pos = gl_in[N_VERTEX0].gl_Position;\n" 2755 " vec4 end_pos = gl_in[N_VERTEX1].gl_Position;\n" 2756 " vec4 start_col = vs_gs_color[N_VERTEX0];\n" 2757 " vec4 end_col = vs_gs_color[N_VERTEX1];\n" 2758 " vec4 delta_col = (end_col - start_col) / vec4(7.0);\n" 2759 " vec4 delta_pos = (end_pos - start_pos) / vec4(7.0);\n" 2760 "\n" 2761 " for (int n_point = 0; n_point < 8; ++n_point)\n" 2762 " {\n" 2763 " vec4 ref_color = start_col + vec4(float(n_point)) * delta_col;\n" 2764 " vec4 ref_pos = start_pos + vec4(float(n_point)) * delta_pos;\n" 2765 "\n" 2766 /* TL */ 2767 " gl_Position = ref_pos + vec4(-dx, -dy, 0, 0);\n" 2768 " gs_fs_color = ref_color;\n" 2769 " EmitVertex();\n" 2770 /* TM */ 2771 " gl_Position = ref_pos + vec4(0, -dy, 0, 0);\n" 2772 " gs_fs_color = ref_color;\n" 2773 " EmitVertex();\n" 2774 /* TR */ 2775 " gl_Position = ref_pos + vec4(dx, -dy, 0, 0);\n" 2776 " gs_fs_color = ref_color;\n" 2777 " EmitVertex();\n" 2778 /* ML */ 2779 " gl_Position = ref_pos + vec4(-dx, 0, 0, 0);\n" 2780 " gs_fs_color = ref_color;\n" 2781 " EmitVertex();\n" 2782 /* MM */ 2783 " gl_Position = ref_pos + vec4(0, 0, 0, 0);\n" 2784 " gs_fs_color = ref_color;\n" 2785 " EmitVertex();\n" 2786 /* MR */ 2787 " gl_Position = ref_pos + vec4(dx, 0, 0, 0);\n" 2788 " gs_fs_color = ref_color;\n" 2789 " EmitVertex();\n" 2790 /* BL */ 2791 " gl_Position = ref_pos + vec4(-dx, dy, 0, 0);\n" 2792 " gs_fs_color = ref_color;\n" 2793 " EmitVertex();\n" 2794 /* BM */ 2795 " gl_Position = ref_pos + vec4(0, dy, 0, 0);\n" 2796 " gs_fs_color = ref_color;\n" 2797 " EmitVertex();\n" 2798 /* BR */ 2799 " gl_Position = ref_pos + vec4(dx, dy, 0, 0);\n" 2800 " gs_fs_color = ref_color;\n" 2801 " EmitVertex();\n" 2802 " }\n" 2803 "}\n"; 2804 2805 static const char* lines_adjacency_in_triangle_strip_out_gs_code_preamble = 2806 "${VERSION}\n" 2807 "\n" 2808 "${GEOMETRY_SHADER_ENABLE}\n" 2809 "\n" 2810 "layout(lines_adjacency) in;\n" 2811 "layout(triangle_strip, max_vertices=3) out;\n" 2812 "\n" 2813 "#define N_VERTEX0 (1)\n" 2814 "#define N_VERTEX1 (2)\n" 2815 "#define N_VERTICES_IN (4)\n"; 2816 2817 static const char* lines_in_triangle_strip_out_gs_code_preamble = "${VERSION}\n" 2818 "\n" 2819 "${GEOMETRY_SHADER_ENABLE}\n" 2820 "\n" 2821 "layout(lines) in;\n" 2822 "layout(triangle_strip, max_vertices=3) out;\n" 2823 "\n" 2824 "#define N_VERTEX0 (0)\n" 2825 "#define N_VERTEX1 (1)\n" 2826 "#define N_VERTICES_IN (2)\n"; 2827 2828 static const char* triangles_gs_code_main = "flat in int instance_id[N_VERTICES_IN];\n" 2829 " in vec4 vs_gs_color[N_VERTICES_IN];\n" 2830 " out vec4 gs_fs_color;\n" 2831 "\n" 2832 "uniform ivec2 renderingTargetSize;\n" 2833 "\n" 2834 "void main()\n" 2835 "{\n" 2836 " float dx = float(1.5) / float(renderingTargetSize.x);\n" 2837 " float dy = float(1.5) / float(renderingTargetSize.y);\n" 2838 "\n" 2839 " gl_Position = gl_in[N_VERTEX0].gl_Position;\n" 2840 " gs_fs_color = vs_gs_color[N_VERTEX0];\n" 2841 " EmitVertex();\n" 2842 "\n" 2843 " gl_Position = gl_in[N_VERTEX1].gl_Position;\n" 2844 " gs_fs_color = vs_gs_color[N_VERTEX0];\n" 2845 " EmitVertex();\n" 2846 "\n" 2847 " if (renderingTargetSize.y == 45 /* block size */)\n" 2848 " {\n" 2849 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 2850 " }\n" 2851 " else\n" 2852 " {\n" 2853 /* Each block takes 1/4th of the total render target. 2854 * Third vertex should be placed in the middle of the block. 2855 */ 2856 " float y = -1.0 + 1.0 / 4.0 + float(instance_id[0]) * 0.5;\n" 2857 "\n" 2858 " gl_Position = vec4(0.0, y, 0.0, 1.0);\n" 2859 " }\n" 2860 "\n" 2861 " gs_fs_color = vs_gs_color[N_VERTEX0];\n" 2862 " EmitVertex();\n" 2863 "\n" 2864 " EndPrimitive();\n" 2865 "}\n"; 2866 std::string result; 2867 2868 switch (m_output_type) 2869 { 2870 case SHADER_OUTPUT_TYPE_LINE_STRIP: 2871 { 2872 std::stringstream lines_adjacency_gs_code_stringstream; 2873 std::string lines_adjacency_gs_code_string; 2874 std::stringstream lines_gs_code_stringstream; 2875 std::string lines_gs_code_string; 2876 2877 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) 2878 { 2879 /* First request for lines_adjacency GS, form the string */ 2880 lines_adjacency_gs_code_stringstream << lines_adjacency_in_line_strip_out_gs_code_preamble 2881 << lines_gs_code_main; 2882 2883 lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str(); 2884 result = lines_adjacency_gs_code_string; 2885 } 2886 else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP) 2887 { 2888 /* First request for lines GS, form the string */ 2889 lines_gs_code_stringstream << lines_in_line_strip_out_gs_code_preamble << lines_gs_code_main; 2890 2891 lines_gs_code_string = lines_gs_code_stringstream.str(); 2892 result = lines_gs_code_string; 2893 } 2894 else 2895 { 2896 TCU_FAIL("Unrecognized draw call mode"); 2897 } 2898 2899 break; 2900 } 2901 2902 case SHADER_OUTPUT_TYPE_POINTS: 2903 { 2904 std::stringstream lines_adjacency_gs_code_stringstream; 2905 std::string lines_adjacency_gs_code_string; 2906 std::stringstream lines_gs_code_stringstream; 2907 std::string lines_gs_code_string; 2908 2909 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) 2910 { 2911 /* First request for lines_adjacency GS, form the string */ 2912 lines_adjacency_gs_code_stringstream << lines_adjacency_in_points_out_gs_code_preamble 2913 << points_gs_code_main; 2914 2915 lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str(); 2916 result = lines_adjacency_gs_code_string; 2917 } 2918 else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP) 2919 { 2920 /* First request for lines GS, form the string */ 2921 lines_gs_code_stringstream << lines_in_points_out_gs_code_preamble << points_gs_code_main; 2922 2923 lines_gs_code_string = lines_gs_code_stringstream.str(); 2924 result = lines_gs_code_string; 2925 } 2926 else 2927 { 2928 TCU_FAIL("Unrecognized draw call mode"); 2929 } 2930 2931 break; 2932 } 2933 2934 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 2935 { 2936 std::stringstream lines_adjacency_gs_code_stringstream; 2937 std::string lines_adjacency_gs_code_string; 2938 std::stringstream lines_gs_code_stringstream; 2939 std::string lines_gs_code_string; 2940 2941 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) 2942 { 2943 /* First request for lines_adjacency GS, form the string */ 2944 lines_adjacency_gs_code_stringstream << lines_adjacency_in_triangle_strip_out_gs_code_preamble 2945 << triangles_gs_code_main; 2946 2947 lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str(); 2948 result = lines_adjacency_gs_code_string; 2949 } 2950 else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP) 2951 { 2952 /* First request for lines GS, form the string */ 2953 lines_gs_code_stringstream << lines_in_triangle_strip_out_gs_code_preamble << triangles_gs_code_main; 2954 2955 lines_gs_code_string = lines_gs_code_stringstream.str(); 2956 result = lines_gs_code_string; 2957 } 2958 else 2959 { 2960 TCU_FAIL("Unrecognized draw call mode"); 2961 } 2962 2963 break; 2964 } 2965 2966 default: 2967 { 2968 TCU_FAIL("Requested shader output layout qualifier is unsupported"); 2969 } 2970 } /* switch (m_output_type) */ 2971 2972 return result; 2973 } 2974 2975 /** Returns amount of bytes that should be allocated for a buffer object to hold 2976 * vertex data to be used for glDrawArrays*() calls. 2977 * 2978 * @param instanced True if the data is to be used in regard to instanced draw calls, 2979 * false otherwise. 2980 * 2981 * @return As per description. 2982 **/ 2983 glw::GLuint GeometryShaderRenderingLinesCase::getRawArraysDataBufferSize(bool instanced) 2984 { 2985 return instanced ? m_raw_array_instanced_data_size : m_raw_array_noninstanced_data_size; 2986 } 2987 2988 /** Returns vertex data for the test. Only to be used for glDrawArrays*() calls. 2989 * 2990 * @param instanced True if the data is to be used in regard to instanced draw calls, 2991 * false otherwise. 2992 * 2993 * @return As per description. 2994 **/ 2995 const void* GeometryShaderRenderingLinesCase::getRawArraysDataBuffer(bool instanced) 2996 { 2997 return instanced ? m_raw_array_instanced_data : m_raw_array_noninstanced_data; 2998 } 2999 3000 /** Retrieves resolution of off-screen rendering buffer that should be used for the test. 3001 * 3002 * @param n_instances Amount of draw call instances this render target will be used for. 3003 * @param out_width Deref will be used to store rendertarget's width. Must not be NULL. 3004 * @param out_height Deref will be used to store rendertarget's height. Must not be NULL. 3005 **/ 3006 void GeometryShaderRenderingLinesCase::getRenderTargetSize(unsigned int n_instances, unsigned int* out_width, 3007 unsigned int* out_height) 3008 { 3009 switch (m_output_type) 3010 { 3011 case SHADER_OUTPUT_TYPE_LINE_STRIP: 3012 case SHADER_OUTPUT_TYPE_POINTS: 3013 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 3014 { 3015 /* For SHADER_OUTPUT_TYPE_POINTS: 3016 * An edge size of 45px should be used. Given that each input will generate a 3x3 block, 3017 * this should give us a delta of 3px between the "quads". 3018 * 3019 * For instanced draw calls, use a delta of 3px as well. 3020 * 3021 * For SHADER_OUTPUT_TYPE_LINE_STRIP: 3022 * Each rectangle outline will take a 45x45 block. No vertical delta needs to be used. 3023 * 3024 * For SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 3025 * Each combination of 4 triangles makes up a triangles that takes 45x45 area. 3026 * No vertical delta needs to be used. 3027 */ 3028 *out_width = 3 /* 'pixel' size */ * 8 + 3 /* Delta size */ * 7; 3029 *out_height = (3 /* 'pixel' size */ * 8 + 3 /* Delta size */ * 7) * n_instances; 3030 3031 break; 3032 } 3033 3034 default: 3035 { 3036 TCU_FAIL("Unsupported shader output type"); 3037 } 3038 } /* switch (m_output_type) */ 3039 } 3040 3041 /** Returns amount of bytes that should be allocated for a buffer object to hold 3042 * vertex data to be used for glDrawElements*() calls. 3043 * 3044 * @param instanced true if the call is being made for an instanced draw call, false otherwise. 3045 * 3046 * @return As per description. 3047 **/ 3048 glw::GLuint GeometryShaderRenderingLinesCase::getUnorderedArraysDataBufferSize(bool instanced) 3049 { 3050 return (instanced) ? m_unordered_array_instanced_data_size : m_unordered_array_noninstanced_data_size; 3051 } 3052 3053 /** Returns vertex data for the test. Only to be used for glDrawElements*() calls. 3054 * 3055 * @param instanced true if the call is being made for an instanced draw call, false otherwise. 3056 * 3057 * @return As per description. 3058 **/ 3059 const void* GeometryShaderRenderingLinesCase::getUnorderedArraysDataBuffer(bool instanced) 3060 { 3061 return instanced ? m_unordered_array_instanced_data : m_unordered_array_noninstanced_data; 3062 } 3063 3064 /** Returns amount of bytes that should be allocated for a buffer object to hold 3065 * index data to be used for glDrawElements*() calls. 3066 * 3067 * @param instanced true if the call is being made for an instanced draw call, false otherwise. 3068 * 3069 * @return As per description. 3070 **/ 3071 glw::GLuint GeometryShaderRenderingLinesCase::getUnorderedElementsDataBufferSize(bool instanced) 3072 { 3073 return instanced ? m_unordered_elements_instanced_data_size : m_unordered_elements_noninstanced_data_size; 3074 } 3075 3076 /** Returns index data for the test. Only to be used for glDrawElements*() calls. 3077 * 3078 * @param instanced true if the call is being made for an instanced draw call, false otherwise. 3079 * 3080 **/ 3081 const void* GeometryShaderRenderingLinesCase::getUnorderedElementsDataBuffer(bool instanced) 3082 { 3083 return instanced ? m_unordered_elements_instanced_data : m_unordered_elements_noninstanced_data; 3084 } 3085 3086 /** Returns type of the index, to be used for glDrawElements*() calls. 3087 * 3088 * @return As per description. 3089 **/ 3090 glw::GLenum GeometryShaderRenderingLinesCase::getUnorderedElementsDataType() 3091 { 3092 return GL_UNSIGNED_BYTE; 3093 } 3094 3095 /** Retrieves maximum index value. To be used for glDrawRangeElements() test only. 3096 * 3097 * @return As per description. 3098 **/ 3099 glw::GLubyte GeometryShaderRenderingLinesCase::getUnorderedElementsMaxIndex() 3100 { 3101 return m_unordered_elements_max_index; 3102 } 3103 3104 /** Retrieves minimum index value. To be used for glDrawRangeElements() test only. 3105 * 3106 * @return As per description. 3107 **/ 3108 glw::GLubyte GeometryShaderRenderingLinesCase::getUnorderedElementsMinIndex() 3109 { 3110 return m_unordered_elements_min_index; 3111 } 3112 3113 /** Retrieves vertex shader code to be used for the test. 3114 * 3115 * @return As per description. 3116 **/ 3117 std::string GeometryShaderRenderingLinesCase::getVertexShaderCode() 3118 { 3119 static std::string vs_code = 3120 "${VERSION}\n" 3121 "\n" 3122 " in vec4 position;\n" 3123 " uniform bool is_indexed_draw_call;\n" 3124 " uniform bool is_gl_lines_adjacency_draw_call;\n" 3125 " uniform bool is_gl_line_strip_adjacency_draw_call;\n" 3126 " uniform bool is_gl_lines_draw_call;\n" 3127 " uniform bool is_gl_line_loop_draw_call;\n" 3128 " uniform ivec2 renderingTargetSize;\n" 3129 "flat out int instance_id;\n" 3130 " out vec4 vs_gs_color;\n" 3131 "\n" 3132 "void main()\n" 3133 "{\n" 3134 " instance_id = gl_InstanceID;\n" 3135 "\n" 3136 /* non-instanced */ 3137 " if (renderingTargetSize.y == 45 /* block size */)\n" 3138 " {\n" 3139 " gl_Position = position;\n" 3140 " }\n" 3141 " else\n" 3142 " {\n" 3143 " bool represents_top_edge = (position.z == 0.0);\n" 3144 " float delta = position.w;\n" 3145 " float y = 0.0;\n" 3146 "\n" 3147 " if (represents_top_edge)\n" 3148 " {\n" 3149 /* top vertices */ 3150 " y = position.y + float(gl_InstanceID) * delta * 2.0 - 1.0;\n" 3151 " }\n" 3152 " else\n" 3153 " {\n" 3154 " y = position.y + float(gl_InstanceID) * delta * 2.0 - 1.0 + delta * 2.0;\n" 3155 /* bottom vertices */ 3156 " }\n" 3157 "\n" 3158 " gl_Position = vec4(position.x,\n" 3159 " y,\n" 3160 " position.z,\n" 3161 " 1.0);\n" 3162 " }\n" 3163 "\n" 3164 " vs_gs_color = vec4(0, 0, 0, 0);\n" 3165 "\n" 3166 " if (is_gl_line_loop_draw_call)\n" 3167 " {\n" 3168 /* GL_LINE_LOOP */ 3169 " if (!is_indexed_draw_call)\n" 3170 " {\n" 3171 " switch(gl_VertexID)\n" 3172 " {\n" 3173 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3174 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3175 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3176 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3177 " }\n" 3178 " }\n" 3179 " else\n" 3180 " {\n" 3181 " switch(gl_VertexID)\n" 3182 " {\n" 3183 " case 3: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3184 " case 0: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3185 " case 1: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3186 " case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3187 " }\n" 3188 " }\n" 3189 " }\n" 3190 " else\n" 3191 " if (is_gl_line_strip_adjacency_draw_call)\n" 3192 " {\n" 3193 /* GL_LINE_STRIP_ADJACENCY_EXT */ 3194 " if (!is_indexed_draw_call)\n" 3195 " {\n" 3196 " switch(gl_VertexID)\n" 3197 " {\n" 3198 " case 1:\n" 3199 " case 5: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3200 " case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3201 " case 3: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3202 " case 0:\n" 3203 " case 4: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3204 " }\n" 3205 " }\n" 3206 " else\n" 3207 " {\n" 3208 " switch(gl_VertexID)\n" 3209 " {\n" 3210 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3211 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3212 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3213 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3214 " }\n" 3215 " }\n" 3216 " }\n" 3217 " else\n" 3218 " if (is_gl_lines_adjacency_draw_call)\n" 3219 " {\n" 3220 /* GL_LINES_ADJACENCY_EXT */ 3221 " if (!is_indexed_draw_call)\n" 3222 " {\n" 3223 " switch(gl_VertexID)\n" 3224 " {\n" 3225 " case 1:\n" 3226 " case 14: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3227 "\n" 3228 " case 2:\n" 3229 " case 5: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3230 3231 " case 6:\n" 3232 " case 9: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3233 3234 " case 10:\n" 3235 " case 13: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3236 " }\n" 3237 " }\n" 3238 " else\n" 3239 " {\n" 3240 " switch(gl_VertexID)\n" 3241 " {\n" 3242 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3243 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3244 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3245 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3246 " }\n" 3247 " }\n" 3248 " }\n" 3249 " else\n" 3250 " if (is_gl_lines_draw_call)\n" 3251 " {\n" 3252 /* GL_LINES */ 3253 " if (!is_indexed_draw_call)\n" 3254 " {\n" 3255 " switch(gl_VertexID)\n" 3256 " {\n" 3257 " case 0:\n" 3258 " case 7: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3259 "\n" 3260 " case 1:\n" 3261 " case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3262 3263 " case 3:\n" 3264 " case 4: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3265 3266 " case 5:\n" 3267 " case 6: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3268 " }\n" 3269 " }\n" 3270 " else\n" 3271 " {\n" 3272 " switch(gl_VertexID)\n" 3273 " {\n" 3274 " case 6:\n" 3275 " case 1: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3276 "\n" 3277 " case 7:\n" 3278 " case 4: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3279 3280 " case 5:\n" 3281 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3282 3283 " case 3:\n" 3284 " case 0: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3285 " }\n" 3286 " }\n" 3287 " }\n" 3288 " else\n" 3289 " {\n" 3290 /* GL_LINE_STRIP */ 3291 " if (!is_indexed_draw_call)\n" 3292 " {\n" 3293 " switch(gl_VertexID)\n" 3294 " {\n" 3295 " case 0:\n" 3296 " case 4: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3297 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3298 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3299 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3300 " }\n" 3301 " }\n" 3302 " else\n" 3303 " {\n" 3304 " switch(gl_VertexID)\n" 3305 " {\n" 3306 " case 0:\n" 3307 " case 4: vs_gs_color = vec4(1, 0, 0, 0); break;\n" 3308 " case 1: vs_gs_color = vec4(0, 0, 0, 1); break;\n" 3309 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n" 3310 " case 3: vs_gs_color = vec4(0, 1, 0, 0); break;\n" 3311 " }\n" 3312 " }\n" 3313 " }\n" 3314 "}\n"; 3315 3316 std::string result; 3317 3318 switch (m_output_type) 3319 { 3320 case SHADER_OUTPUT_TYPE_LINE_STRIP: 3321 case SHADER_OUTPUT_TYPE_POINTS: 3322 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 3323 { 3324 result = vs_code; 3325 3326 break; 3327 } 3328 3329 default: 3330 { 3331 TCU_FAIL("Unsupported shader output type used"); 3332 } 3333 } /* switch (m_output_type) */ 3334 3335 return result; 3336 } 3337 3338 /** Sets test-specific uniforms for a program object that is then used for the draw call. 3339 * 3340 * @param drawcall_type Type of the draw call that is to follow right after this function is called. 3341 **/ 3342 void GeometryShaderRenderingLinesCase::setUniformsBeforeDrawCall(_draw_call_type drawcall_type) 3343 { 3344 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3345 glw::GLint is_gl_line_loop_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_gl_line_loop_draw_call"); 3346 glw::GLint is_gl_line_strip_adjacency_draw_call_uniform_location = 3347 gl.getUniformLocation(m_po_id, "is_gl_line_strip_adjacency_draw_call"); 3348 glw::GLint is_gl_lines_adjacency_draw_call_uniform_location = 3349 gl.getUniformLocation(m_po_id, "is_gl_lines_adjacency_draw_call"); 3350 glw::GLint is_gl_lines_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_gl_lines_draw_call"); 3351 glw::GLint is_indexed_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_indexed_draw_call"); 3352 3353 TCU_CHECK(is_gl_line_loop_draw_call_uniform_location != -1); 3354 TCU_CHECK(is_gl_line_strip_adjacency_draw_call_uniform_location != -1); 3355 TCU_CHECK(is_gl_lines_adjacency_draw_call_uniform_location != -1); 3356 TCU_CHECK(is_gl_lines_draw_call_uniform_location != -1); 3357 TCU_CHECK(is_indexed_draw_call_uniform_location != -1); 3358 3359 gl.uniform1i(is_indexed_draw_call_uniform_location, (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS || 3360 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED || 3361 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS)); 3362 gl.uniform1i(is_gl_line_loop_draw_call_uniform_location, (m_drawcall_mode == GL_LINE_LOOP)); 3363 gl.uniform1i(is_gl_line_strip_adjacency_draw_call_uniform_location, 3364 (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)); 3365 gl.uniform1i(is_gl_lines_adjacency_draw_call_uniform_location, (m_drawcall_mode == GL_LINES_ADJACENCY_EXT)); 3366 gl.uniform1i(is_gl_lines_draw_call_uniform_location, (m_drawcall_mode == GL_LINES)); 3367 } 3368 3369 /** Verifies that the rendered data is correct. 3370 * 3371 * @param drawcall_type Type of the draw call that was used to render the geometry. 3372 * @param instance_id Instance ID to be verified. Use 0 for non-instanced draw calls. 3373 * @param data Contents of the rendertarget after the test has finished rendering. 3374 **/ 3375 void GeometryShaderRenderingLinesCase::verify(_draw_call_type drawcall_type, unsigned int instance_id, 3376 const unsigned char* data) 3377 { 3378 const float epsilon = 1.0f / 256.0f; 3379 unsigned int rt_height = 0; 3380 unsigned int rt_width = 0; 3381 unsigned int single_rt_height = 0; 3382 unsigned int single_rt_width = 0; 3383 3384 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED || 3385 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED) 3386 { 3387 getRenderTargetSize(getAmountOfDrawInstances(), &rt_width, &rt_height); 3388 } 3389 else 3390 { 3391 getRenderTargetSize(1, &rt_width, &rt_height); 3392 } 3393 3394 getRenderTargetSize(1, &single_rt_width, &single_rt_height); 3395 3396 /* Verification is output type-specific */ 3397 const unsigned int row_width = rt_width * 4 /* components */; 3398 3399 switch (m_output_type) 3400 { 3401 case SHADER_OUTPUT_TYPE_LINE_STRIP: 3402 { 3403 /* The test renders a rectangle outline with 3 line segments for each edge. 3404 * The verification checks color of each edge's middle line segment. 3405 * 3406 * Corners are skipped to keep the implementation simple. */ 3407 for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge) 3408 { 3409 /* Determine edge-specific properties: 3410 * 3411 * Edge 0 - top edge; 3412 * Edge 1 - right edge; 3413 * Edge 2 - bottom edge; 3414 * Edge 3 - left edge. 3415 * 3416 **/ 3417 int end_x = 0; 3418 int end_y = 0; 3419 tcu::Vec4 expected_rgba; 3420 int start_x = 0; 3421 int start_y = 0; 3422 3423 switch (n_edge) 3424 { 3425 case 0: 3426 { 3427 /* Top edge */ 3428 start_x = 3; /* skip the corner */ 3429 start_y = 1 + instance_id * single_rt_height; /* middle segment */ 3430 3431 end_x = single_rt_width - 3; /* skip the corner */ 3432 end_y = start_y; 3433 3434 expected_rgba = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f) + 3435 tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f); 3436 3437 break; 3438 } 3439 3440 case 1: 3441 { 3442 /* Right edge */ 3443 start_x = single_rt_width - 2; /* middle segment */ 3444 start_y = 3 + instance_id * single_rt_height; /* skip the corner */ 3445 3446 end_x = start_x; 3447 end_y = start_y + single_rt_height - 6; /* skip the corners */ 3448 3449 expected_rgba = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f) + 3450 tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f) * tcu::Vec4(0.5f); 3451 3452 break; 3453 } 3454 3455 case 2: 3456 { 3457 /* Bottom edge */ 3458 start_x = 3; /* skip the corner */ 3459 start_y = single_rt_height - 3 + instance_id * single_rt_height; /* middle segment */ 3460 3461 end_x = single_rt_width - 6; /* skip the corners */ 3462 end_y = start_y; 3463 3464 expected_rgba = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f) * tcu::Vec4(0.5f) + 3465 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * tcu::Vec4(0.5f); 3466 3467 break; 3468 } 3469 3470 case 3: 3471 { 3472 /* Left edge */ 3473 start_x = 1; /* middle segment */ 3474 start_y = 3 + instance_id * single_rt_height; /* skip the corner */ 3475 3476 end_x = start_x; 3477 end_y = start_y + single_rt_height - 6; /* skip the corners */ 3478 3479 expected_rgba = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * tcu::Vec4(0.5f) + 3480 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f); 3481 3482 break; 3483 } 3484 3485 default: 3486 { 3487 TCU_FAIL("Unrecognized edge index"); 3488 } 3489 } /* switch(n_edge) */ 3490 3491 /* Move over the edge and make sure the rendered pixels are valid */ 3492 int dx = (end_x != start_x) ? 1 : 0; 3493 int dy = (end_y != start_y) ? 1 : 0; 3494 int n_pixels = (end_x - start_x) + (end_y - start_y); 3495 3496 for (int n_pixel = 0; n_pixel < n_pixels; ++n_pixel) 3497 { 3498 int cur_x = start_x + n_pixel * dx; 3499 int cur_y = start_y + n_pixel * dy; 3500 3501 /* Calculate expected and rendered pixel color */ 3502 const unsigned char* read_data = data + cur_y * row_width + cur_x * 4 /* components */; 3503 float rendered_rgba[4] = { 0 }; 3504 3505 for (unsigned int n_channel = 0; n_channel < 4 /* RGBA */; ++n_channel) 3506 { 3507 rendered_rgba[n_channel] = float(read_data[n_channel]) / 255.0f; 3508 } 3509 3510 /* Compare the data */ 3511 if (de::abs(rendered_rgba[0] - expected_rgba[0]) > epsilon || 3512 de::abs(rendered_rgba[1] - expected_rgba[1]) > epsilon || 3513 de::abs(rendered_rgba[2] - expected_rgba[2]) > epsilon || 3514 de::abs(rendered_rgba[3] - expected_rgba[3]) > epsilon) 3515 { 3516 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << cur_x << ", " << cur_y 3517 << ") " 3518 << "equal (" << rendered_rgba[0] << ", " << rendered_rgba[1] << ", " 3519 << rendered_rgba[2] << ", " << rendered_rgba[3] << ") " 3520 << "exceeds allowed epsilon when compared to reference data equal (" 3521 << expected_rgba[0] << ", " << expected_rgba[1] << ", " << expected_rgba[2] 3522 << ", " << expected_rgba[3] << ")." << tcu::TestLog::EndMessage; 3523 3524 TCU_FAIL("Data comparison failed"); 3525 } /* if (data comparison failed) */ 3526 } /* for (all points) */ 3527 } /* for (all edges) */ 3528 3529 break; 3530 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */ 3531 3532 case SHADER_OUTPUT_TYPE_POINTS: 3533 { 3534 /* Verify centers of the points generated by geometry shader */ 3535 int dx = 0; 3536 int dy = 0; 3537 3538 bool ignore_first_point = false; 3539 int start_x = 0; 3540 int start_y = 0; 3541 3542 tcu::Vec4 end_color; 3543 tcu::Vec4 start_color; 3544 3545 for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge) 3546 { 3547 /* Determine edge-specific properties: 3548 * 3549 * Edge 0 - top edge; NOTE: the test should skip point at (1px, 1px) as it is overwritten by 3550 * edge 3! 3551 * Edge 1 - right edge; 3552 * Edge 2 - bottom edge; 3553 * Edge 3 - left edge. 3554 * 3555 **/ 3556 switch (n_edge) 3557 { 3558 case 0: 3559 { 3560 dx = 6; 3561 dy = 0; 3562 ignore_first_point = true; 3563 start_x = 1; 3564 start_y = 1 + instance_id * single_rt_height; 3565 3566 end_color = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f); 3567 start_color = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); 3568 3569 break; 3570 } 3571 3572 case 1: 3573 { 3574 dx = 0; 3575 dy = 6; 3576 ignore_first_point = false; 3577 start_x = single_rt_width - 1; 3578 start_y = 1 + instance_id * single_rt_height; 3579 3580 end_color = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f); 3581 start_color = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f); 3582 3583 break; 3584 } 3585 3586 case 2: 3587 { 3588 dx = -6; 3589 dy = 0; 3590 ignore_first_point = false; 3591 start_x = single_rt_width - 1; 3592 start_y = single_rt_height - 1 + instance_id * single_rt_height; 3593 3594 end_color = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); 3595 start_color = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f); 3596 3597 break; 3598 } 3599 3600 case 3: 3601 { 3602 dx = 0; 3603 dy = -6; 3604 ignore_first_point = false; 3605 start_x = 1; 3606 start_y = single_rt_height - 1 + instance_id * single_rt_height; 3607 3608 end_color = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); 3609 start_color = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); 3610 3611 break; 3612 } 3613 3614 default: 3615 { 3616 TCU_FAIL("Unrecognized edge index"); 3617 } 3618 } /* switch(n_edge) */ 3619 3620 for (unsigned int n_point = 0; n_point < 8 /* points */; ++n_point) 3621 { 3622 int cur_x = start_x + n_point * dx; 3623 int cur_y = start_y + n_point * dy; 3624 3625 /* Skip the iteration if we're dealing with a first point, for which 3626 * the comparison should be skipped */ 3627 if (ignore_first_point && n_point == 0) 3628 { 3629 continue; 3630 } 3631 3632 /* Calculate expected and rendered pixel color */ 3633 const unsigned char* read_data = data + cur_y * row_width + cur_x * 4 /* components */; 3634 float reference_rgba[4] = { 0 }; 3635 float rendered_rgba[4] = { 0 }; 3636 3637 for (unsigned int n_channel = 0; n_channel < 4 /* RGBA */; ++n_channel) 3638 { 3639 reference_rgba[n_channel] = start_color[n_channel] + 3640 (end_color[n_channel] - start_color[n_channel]) * float(n_point) / 7.0f; 3641 rendered_rgba[n_channel] = (float)(read_data[n_channel]) / 255.0f; 3642 } 3643 3644 /* Compare the data */ 3645 if (de::abs(rendered_rgba[0] - reference_rgba[0]) > epsilon || 3646 de::abs(rendered_rgba[1] - reference_rgba[1]) > epsilon || 3647 de::abs(rendered_rgba[2] - reference_rgba[2]) > epsilon || 3648 de::abs(rendered_rgba[3] - reference_rgba[3]) > epsilon) 3649 { 3650 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << cur_x << ", " << cur_y 3651 << ") " 3652 << "equal (" << rendered_rgba[0] << ", " << rendered_rgba[1] << ", " 3653 << rendered_rgba[2] << ", " << rendered_rgba[3] << ") " 3654 << "exceeds allowed epsilon when compared to reference data equal (" 3655 << reference_rgba[0] << ", " << reference_rgba[1] << ", " << reference_rgba[2] 3656 << ", " << reference_rgba[3] << ")." << tcu::TestLog::EndMessage; 3657 3658 TCU_FAIL("Data comparison failed"); 3659 } /* if (data comparison failed) */ 3660 3661 } /* for (all points) */ 3662 } /* for (all edges) */ 3663 3664 /* Done */ 3665 break; 3666 } /* case SHADER_OUTPUT_TYPE_POINTS: */ 3667 3668 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 3669 { 3670 /* The test renders four triangles - two vertices are taken from each edge and the third 3671 * one is set at (0, 0, 0, 1) (screen-space). The rendering output is verified by 3672 * sampling centroids off each triangle */ 3673 for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge) 3674 { 3675 /* Determine edge-specific properties */ 3676 tcu::Vec2 centroid; 3677 tcu::Vec4 reference_rgba; 3678 tcu::Vec2 v1; 3679 tcu::Vec2 v2; 3680 tcu::Vec2 v3 = tcu::Vec2(0.5f, 0.5f + float(instance_id)); 3681 3682 switch (n_edge) 3683 { 3684 case 0: 3685 { 3686 /* Top edge */ 3687 v1 = tcu::Vec2(0.0f, float(instance_id) + 0.0f); 3688 v2 = tcu::Vec2(1.0f, float(instance_id) + 0.0f); 3689 3690 reference_rgba = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); 3691 3692 break; 3693 } 3694 3695 case 1: 3696 { 3697 /* Right edge */ 3698 v1 = tcu::Vec2(1.0f, float(instance_id) + 0.0f); 3699 v2 = tcu::Vec2(1.0f, float(instance_id) + 1.0f); 3700 3701 reference_rgba = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f); 3702 3703 break; 3704 } 3705 3706 case 2: 3707 { 3708 /* Bottom edge */ 3709 v1 = tcu::Vec2(0.0f, float(instance_id) + 1.0f); 3710 v2 = tcu::Vec2(1.0f, float(instance_id) + 1.0f); 3711 3712 reference_rgba = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f); 3713 3714 break; 3715 } 3716 3717 case 3: 3718 { 3719 /* Left edge */ 3720 v1 = tcu::Vec2(0.0f, float(instance_id) + 0.0f); 3721 v2 = tcu::Vec2(0.0f, float(instance_id) + 1.0f); 3722 3723 reference_rgba = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); 3724 3725 break; 3726 } 3727 3728 default: 3729 { 3730 TCU_FAIL("Unrecognized edge index"); 3731 } 3732 } /* switch (n_edge) */ 3733 3734 /* Calculate centroid of the triangle. */ 3735 centroid[0] = (v1[0] + v2[0] + v3[0]) / 3.0f; 3736 centroid[1] = (v1[1] + v2[1] + v3[1]) / 3.0f; 3737 3738 /* Retrieve the sample */ 3739 int centroid_xy[2] = { int(centroid[0] * float(single_rt_width)), 3740 int(centroid[1] * float(single_rt_height)) }; 3741 const unsigned char* rendered_rgba_ubyte = 3742 data + centroid_xy[1] * row_width + centroid_xy[0] * 4 /* components */; 3743 const float rendered_rgba_float[] = { 3744 float(rendered_rgba_ubyte[0]) / 255.0f, float(rendered_rgba_ubyte[1]) / 255.0f, 3745 float(rendered_rgba_ubyte[2]) / 255.0f, float(rendered_rgba_ubyte[3]) / 255.0f, 3746 }; 3747 3748 /* Compare the reference and rendered pixels */ 3749 if (de::abs(rendered_rgba_float[0] - reference_rgba[0]) > epsilon || 3750 de::abs(rendered_rgba_float[1] - reference_rgba[1]) > epsilon || 3751 de::abs(rendered_rgba_float[2] - reference_rgba[2]) > epsilon || 3752 de::abs(rendered_rgba_float[3] - reference_rgba[3]) > epsilon) 3753 { 3754 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << centroid_xy[0] << ", " 3755 << centroid_xy[1] << ") " 3756 << "equal (" << rendered_rgba_float[0] << ", " << rendered_rgba_float[1] << ", " 3757 << rendered_rgba_float[2] << ", " << rendered_rgba_float[3] << ") " 3758 << "exceeds allowed epsilon when compared to reference data equal (" 3759 << reference_rgba[0] << ", " << reference_rgba[1] << ", " << reference_rgba[2] 3760 << ", " << reference_rgba[3] << ")." << tcu::TestLog::EndMessage; 3761 3762 TCU_FAIL("Data comparison failed"); 3763 } /* if (data comparison failed) */ 3764 } /* for (all edges) */ 3765 3766 break; 3767 } 3768 3769 default: 3770 { 3771 TCU_FAIL("Unsupported shader output type used"); 3772 } 3773 } /* switch (m_output_type) */ 3774 } 3775 3776 /** Constructor. 3777 * 3778 * @param use_adjacency_data true if the test case is being instantiated for draw call modes that will 3779 * features adjacency data, 3780 * false otherwise. 3781 * @param drawcall_mode GL draw call mode that will be used for the tests. 3782 * @param output_type Shader output type that the test case is being instantiated for. 3783 * @param context Rendering context; 3784 * @param testContext Test context; 3785 * @param name Test name. 3786 **/ 3787 GeometryShaderRenderingTrianglesCase::GeometryShaderRenderingTrianglesCase(Context& context, 3788 const ExtParameters& extParams, 3789 const char* name, bool use_adjacency_data, 3790 glw::GLenum drawcall_mode, 3791 _shader_output_type output_type) 3792 : GeometryShaderRenderingCase( 3793 context, extParams, name, 3794 "Verifies all draw calls work correctly for specific input+output+draw call mode combination") 3795 , m_output_type(output_type) 3796 , m_drawcall_mode(drawcall_mode) 3797 , m_use_adjacency_data(use_adjacency_data) 3798 , m_raw_array_instanced_data(0) 3799 , m_raw_array_instanced_data_size(0) 3800 , m_raw_array_noninstanced_data(0) 3801 , m_raw_array_noninstanced_data_size(0) 3802 , m_unordered_array_instanced_data(0) 3803 , m_unordered_array_instanced_data_size(0) 3804 , m_unordered_array_noninstanced_data(0) 3805 , m_unordered_array_noninstanced_data_size(0) 3806 , m_unordered_elements_instanced_data(0) 3807 , m_unordered_elements_instanced_data_size(0) 3808 , m_unordered_elements_noninstanced_data(0) 3809 , m_unordered_elements_noninstanced_data_size(0) 3810 , m_unordered_elements_max_index(24) /* maximum amount of vertices generated by this test case */ 3811 , m_unordered_elements_min_index(0) 3812 { 3813 /* Sanity checks */ 3814 if (!m_use_adjacency_data) 3815 { 3816 if (drawcall_mode != GL_TRIANGLES && drawcall_mode != GL_TRIANGLE_STRIP && drawcall_mode != GL_TRIANGLE_FAN) 3817 { 3818 TCU_FAIL("Only GL_TRIANGLES or GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN draw call modes are supported for " 3819 "'triangles' geometry shader input layout qualifier test implementation"); 3820 } 3821 } 3822 else 3823 { 3824 if (drawcall_mode != GL_TRIANGLES_ADJACENCY_EXT && drawcall_mode != GL_TRIANGLE_STRIP_ADJACENCY_EXT) 3825 { 3826 TCU_FAIL("Only GL_TRIANGLES_ADJACENCY_EXT or GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call modes are supported " 3827 "for 'triangles_adjacency' geometry shader input layout qualifier test implementation"); 3828 } 3829 } 3830 3831 if (output_type != SHADER_OUTPUT_TYPE_POINTS && output_type != SHADER_OUTPUT_TYPE_LINE_STRIP && 3832 output_type != SHADER_OUTPUT_TYPE_TRIANGLE_STRIP) 3833 { 3834 TCU_FAIL("Unsupported output layout qualifier type requested for 'triangles' geometry shader input layout " 3835 "qualifier test implementation"); 3836 } 3837 3838 /* Generate data in two flavors - one for non-instanced case, the other one for instanced case */ 3839 for (int n_case = 0; n_case < 2 /* cases */; ++n_case) 3840 { 3841 bool is_instanced = (n_case != 0); 3842 int n_instances = 0; 3843 float** raw_arrays_data_ptr = NULL; 3844 unsigned int* raw_arrays_data_size_ptr = NULL; 3845 unsigned int rendertarget_height = 0; 3846 unsigned int rendertarget_width = 0; 3847 float** unordered_arrays_data_ptr = NULL; 3848 unsigned int* unordered_arrays_data_size_ptr = NULL; 3849 unsigned char** unordered_elements_data_ptr = NULL; 3850 unsigned int* unordered_elements_data_size_ptr = NULL; 3851 3852 if (!is_instanced) 3853 { 3854 /* Non-instanced case */ 3855 n_instances = 1; 3856 raw_arrays_data_ptr = &m_raw_array_noninstanced_data; 3857 raw_arrays_data_size_ptr = &m_raw_array_noninstanced_data_size; 3858 unordered_arrays_data_ptr = &m_unordered_array_noninstanced_data; 3859 unordered_arrays_data_size_ptr = &m_unordered_array_noninstanced_data_size; 3860 unordered_elements_data_ptr = &m_unordered_elements_noninstanced_data; 3861 unordered_elements_data_size_ptr = &m_unordered_elements_noninstanced_data_size; 3862 } 3863 else 3864 { 3865 /* Instanced case */ 3866 n_instances = getAmountOfDrawInstances(); 3867 raw_arrays_data_ptr = &m_raw_array_instanced_data; 3868 raw_arrays_data_size_ptr = &m_raw_array_instanced_data_size; 3869 unordered_arrays_data_ptr = &m_unordered_array_instanced_data; 3870 unordered_arrays_data_size_ptr = &m_unordered_array_instanced_data_size; 3871 unordered_elements_data_ptr = &m_unordered_elements_instanced_data; 3872 unordered_elements_data_size_ptr = &m_unordered_elements_instanced_data_size; 3873 } 3874 3875 getRenderTargetSize(n_instances, &rendertarget_width, &rendertarget_height); 3876 3877 /* Store full-screen quad coordinates that will be used for actual array data generation. */ 3878 float dx = 2.0f / float(rendertarget_width); 3879 float dy = 2.0f / float(rendertarget_height); 3880 3881 /* Generate raw vertex array data */ 3882 unsigned int single_rt_height = 0; 3883 unsigned int single_rt_width = 0; 3884 unsigned int whole_rt_width = 0; 3885 unsigned int whole_rt_height = 0; 3886 3887 *raw_arrays_data_size_ptr = 3888 static_cast<unsigned int>(getAmountOfVerticesPerInstance() * 4 /* components */ * sizeof(float)); 3889 *raw_arrays_data_ptr = new float[*raw_arrays_data_size_ptr / sizeof(float)]; 3890 3891 getRenderTargetSize(1, &single_rt_width, &single_rt_height); 3892 getRenderTargetSize(getAmountOfDrawInstances(), &whole_rt_width, &whole_rt_height); 3893 3894 /* Generate the general coordinates storage first. 3895 * 3896 * For non-instanced draw calls, we only need to draw a single instance, hence we are free 3897 * to use screen-space coordinates. 3898 * For instanced draw calls, we'll have the vertex shader add gl_InstanceID-specific deltas 3899 * to make sure the vertices are laid out correctly, so map <-1, 1> range to <0, screen_space_height_of_single_instance> 3900 */ 3901 std::vector<tcu::Vec4> data_coordinates; 3902 float dx_multiplier = 0.0f; 3903 float dy_multiplier = 0.0f; 3904 float end_y = 0.0f; 3905 float mid_y = 0.0f; 3906 float start_y = 0.0f; 3907 3908 if (is_instanced) 3909 { 3910 start_y = -1.0f; 3911 end_y = start_y + float(single_rt_height) / float(whole_rt_height) * 2.0f; 3912 mid_y = start_y + (end_y - start_y) * 0.5f; 3913 } 3914 else 3915 { 3916 end_y = 1.0f; 3917 mid_y = 0.0f; 3918 start_y = -1.0f; 3919 } 3920 3921 if (output_type == SHADER_OUTPUT_TYPE_POINTS) 3922 { 3923 dx_multiplier = 1.5f; 3924 dy_multiplier = 1.5f; 3925 } 3926 else if (output_type == SHADER_OUTPUT_TYPE_LINE_STRIP) 3927 { 3928 dx_multiplier = 1.5f; 3929 dy_multiplier = 1.5f; 3930 } 3931 3932 /* W stores information whether given vertex is the middle vertex */ 3933 data_coordinates.push_back(tcu::Vec4(0, mid_y, 0, 1)); /* Middle vertex */ 3934 data_coordinates.push_back(tcu::Vec4(-1 + dx * dx_multiplier, mid_y, 0, 0)); /* Left vertex */ 3935 data_coordinates.push_back(tcu::Vec4(0, start_y + dy * dy_multiplier, 0, 0)); /* Top vertex */ 3936 data_coordinates.push_back(tcu::Vec4(1 - dx * dx_multiplier, mid_y, 0, 0)); /* Right vertex */ 3937 data_coordinates.push_back(tcu::Vec4(0, end_y - dy * dy_multiplier, 0, 0)); /* Bottom vertex */ 3938 3939 /* Now that we have the general storage ready, we can generate raw array data for specific draw 3940 * call that this specific test instance will be verifying */ 3941 int n_raw_array_indices = 0; 3942 int raw_array_indices[24] = { -1 }; /* 12 is a max for all supported input geometry */ 3943 float* raw_array_traveller_ptr = *raw_arrays_data_ptr; 3944 3945 for (unsigned int n = 0; n < sizeof(raw_array_indices) / sizeof(raw_array_indices[0]); ++n) 3946 { 3947 raw_array_indices[n] = -1; 3948 } 3949 3950 switch (m_drawcall_mode) 3951 { 3952 case GL_TRIANGLES: 3953 { 3954 /* ABC triangle */ 3955 raw_array_indices[0] = 0; 3956 raw_array_indices[1] = 1; 3957 raw_array_indices[2] = 2; 3958 3959 /* ACD triangle */ 3960 raw_array_indices[3] = 0; 3961 raw_array_indices[4] = 2; 3962 raw_array_indices[5] = 3; 3963 3964 /* ADE triangle */ 3965 raw_array_indices[6] = 0; 3966 raw_array_indices[7] = 3; 3967 raw_array_indices[8] = 4; 3968 3969 /* AEB triangle */ 3970 raw_array_indices[9] = 0; 3971 raw_array_indices[10] = 4; 3972 raw_array_indices[11] = 1; 3973 3974 n_raw_array_indices = 12; 3975 3976 break; 3977 } /* case GL_TRIANGLES: */ 3978 3979 case GL_TRIANGLES_ADJACENCY_EXT: 3980 { 3981 /* Note: Geometry shader used by this test does not rely on adjacency data 3982 * so we will fill corresponding indices with meaningless information 3983 * (always first vertex data) */ 3984 /* ABC triangle */ 3985 raw_array_indices[0] = 0; 3986 raw_array_indices[1] = 0; 3987 raw_array_indices[2] = 1; 3988 raw_array_indices[3] = 0; 3989 raw_array_indices[4] = 2; 3990 raw_array_indices[5] = 0; 3991 3992 /* ACD triangle */ 3993 raw_array_indices[6] = 0; 3994 raw_array_indices[7] = 0; 3995 raw_array_indices[8] = 2; 3996 raw_array_indices[9] = 0; 3997 raw_array_indices[10] = 3; 3998 raw_array_indices[11] = 0; 3999 4000 /* ADE triangle */ 4001 raw_array_indices[12] = 0; 4002 raw_array_indices[13] = 0; 4003 raw_array_indices[14] = 3; 4004 raw_array_indices[15] = 0; 4005 raw_array_indices[16] = 4; 4006 raw_array_indices[17] = 0; 4007 4008 /* AEB triangle */ 4009 raw_array_indices[18] = 0; 4010 raw_array_indices[19] = 0; 4011 raw_array_indices[20] = 4; 4012 raw_array_indices[21] = 0; 4013 raw_array_indices[22] = 1; 4014 raw_array_indices[23] = 0; 4015 4016 n_raw_array_indices = 24; 4017 4018 break; 4019 } /* case GL_TRIANGLES_ADJACENCY_EXT:*/ 4020 4021 case GL_TRIANGLE_FAN: 4022 { 4023 /* ABCDEB */ 4024 raw_array_indices[0] = 0; 4025 raw_array_indices[1] = 1; 4026 raw_array_indices[2] = 2; 4027 raw_array_indices[3] = 3; 4028 raw_array_indices[4] = 4; 4029 raw_array_indices[5] = 1; 4030 4031 n_raw_array_indices = 6; 4032 4033 break; 4034 } /* case GL_TRIANGLE_FAN: */ 4035 4036 case GL_TRIANGLE_STRIP: 4037 { 4038 /* BACDAEB. 4039 * 4040 * Note that this will generate a degenerate triangle (ACD & CDA) but that's fine 4041 * since we only sample triangle centroids in this test. 4042 */ 4043 raw_array_indices[0] = 1; 4044 raw_array_indices[1] = 0; 4045 raw_array_indices[2] = 2; 4046 raw_array_indices[3] = 3; 4047 raw_array_indices[4] = 0; 4048 raw_array_indices[5] = 4; 4049 raw_array_indices[6] = 1; 4050 4051 n_raw_array_indices = 7; 4052 4053 break; 4054 } /* case GL_TRIANGLE_STRIP: */ 4055 4056 case GL_TRIANGLE_STRIP_ADJACENCY_EXT: 4057 { 4058 /* Order as in GL_TRIANGLE_STRIP case. Adjacency data not needed for the test, 4059 * hence any data can be used. 4060 */ 4061 raw_array_indices[0] = 1; 4062 raw_array_indices[1] = 0; 4063 raw_array_indices[2] = 0; 4064 raw_array_indices[3] = 0; 4065 raw_array_indices[4] = 2; 4066 raw_array_indices[5] = 0; 4067 raw_array_indices[6] = 3; 4068 raw_array_indices[7] = 0; 4069 raw_array_indices[8] = 0; 4070 raw_array_indices[9] = 0; 4071 raw_array_indices[10] = 4; 4072 raw_array_indices[11] = 0; 4073 raw_array_indices[12] = 1; 4074 raw_array_indices[13] = 0; 4075 4076 n_raw_array_indices = 14; 4077 break; 4078 } /* case GL_TRIANGLE_STRIP_ADJACENCY_EXT: */ 4079 4080 default: 4081 { 4082 TCU_FAIL("Unsupported draw call mode"); 4083 } 4084 } /* switch (m_drawcall_mode) */ 4085 4086 for (int index = 0; index < n_raw_array_indices; ++index) 4087 { 4088 if (raw_array_indices[index] != -1) 4089 { 4090 *raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].x(); 4091 raw_array_traveller_ptr++; 4092 *raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].y(); 4093 raw_array_traveller_ptr++; 4094 *raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].z(); 4095 raw_array_traveller_ptr++; 4096 *raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].w(); 4097 raw_array_traveller_ptr++; 4098 } 4099 } 4100 4101 /* Generate unordered data: 4102 * 4103 * Store vertices in reversed order and configure indices so that the pipeline receives 4104 * vertex data in original order */ 4105 *unordered_arrays_data_size_ptr = *raw_arrays_data_size_ptr; 4106 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr]; 4107 *unordered_elements_data_size_ptr = static_cast<unsigned int>(n_raw_array_indices * sizeof(unsigned char)); 4108 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr]; 4109 4110 /* Set unordered array data first */ 4111 for (int index = 0; index < n_raw_array_indices; ++index) 4112 { 4113 memcpy(*unordered_arrays_data_ptr + 4 /* components */ * (n_raw_array_indices - 1 - index), 4114 *raw_arrays_data_ptr + 4 /* components */ * index, sizeof(float) * 4 /* components */); 4115 } 4116 4117 /* Followed by index data */ 4118 for (int n = 0; n < n_raw_array_indices; ++n) 4119 { 4120 (*unordered_elements_data_ptr)[n] = (unsigned char)(n_raw_array_indices - 1 - n); 4121 } 4122 } /* for (both cases) */ 4123 } 4124 4125 /** Destructor. */ 4126 GeometryShaderRenderingTrianglesCase::~GeometryShaderRenderingTrianglesCase() 4127 { 4128 if (m_raw_array_instanced_data != NULL) 4129 { 4130 delete[] m_raw_array_instanced_data; 4131 4132 m_raw_array_instanced_data = NULL; 4133 } 4134 4135 if (m_raw_array_noninstanced_data != NULL) 4136 { 4137 delete[] m_raw_array_noninstanced_data; 4138 4139 m_raw_array_noninstanced_data = NULL; 4140 } 4141 4142 if (m_unordered_array_instanced_data != NULL) 4143 { 4144 delete[] m_unordered_array_instanced_data; 4145 4146 m_unordered_array_instanced_data = NULL; 4147 } 4148 4149 if (m_unordered_array_noninstanced_data != NULL) 4150 { 4151 delete[] m_unordered_array_noninstanced_data; 4152 4153 m_unordered_array_noninstanced_data = NULL; 4154 } 4155 4156 if (m_unordered_elements_instanced_data != NULL) 4157 { 4158 delete[] m_unordered_elements_instanced_data; 4159 4160 m_unordered_elements_instanced_data = NULL; 4161 } 4162 4163 if (m_unordered_elements_noninstanced_data != NULL) 4164 { 4165 delete[] m_unordered_elements_noninstanced_data; 4166 4167 m_unordered_elements_noninstanced_data = NULL; 4168 } 4169 } 4170 4171 /** Retrieves amount of instances that should be drawn with glDraw*Elements() calls. 4172 * 4173 * @return As per description. 4174 **/ 4175 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfDrawInstances() 4176 { 4177 return 8; 4178 } 4179 4180 /** Retrieves amount of indices that should be used for rendering a single instance 4181 * (glDraw*Elements() calls only) 4182 * 4183 * @return As per description. 4184 */ 4185 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfElementsPerInstance() 4186 { 4187 /* No difference between instanced and non-instanced case. */ 4188 return static_cast<unsigned int>(m_unordered_elements_instanced_data_size / sizeof(unsigned char)); 4189 } 4190 4191 /** Retrieves amount of vertices that should be used for rendering a single instance 4192 * (glDrawArrays*() calls only) 4193 * 4194 * @return As per description. 4195 **/ 4196 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfVerticesPerInstance() 4197 { 4198 unsigned int result = 0; 4199 4200 switch (m_drawcall_mode) 4201 { 4202 case GL_TRIANGLES: 4203 { 4204 result = 3 /* vertices making up a single triangle */ * 4 /* triangles */; 4205 4206 break; 4207 } 4208 4209 case GL_TRIANGLES_ADJACENCY_EXT: 4210 { 4211 result = 3 /* vertices making up a single triangle */ * 4 /* triangles */ * 2 /* adjacency data */; 4212 4213 break; 4214 } 4215 4216 case GL_TRIANGLE_FAN: 4217 { 4218 result = 6 /* vertices in total */; 4219 4220 break; 4221 } 4222 4223 case GL_TRIANGLE_STRIP: 4224 { 4225 result = 7 /* vertices in total */; 4226 4227 break; 4228 } 4229 4230 case GL_TRIANGLE_STRIP_ADJACENCY_EXT: 4231 { 4232 /* As per extension specification */ 4233 result = (5 /* triangles */ + 2) * 2; 4234 4235 break; 4236 } 4237 4238 default: 4239 { 4240 TCU_FAIL("Unrecognized draw call mode"); 4241 } 4242 } /* switch (m_drawcall_mode) */ 4243 4244 return result; 4245 } 4246 4247 /** Draw call mode that should be used glDraw*() calls. 4248 * 4249 * @return As per description. 4250 **/ 4251 glw::GLenum GeometryShaderRenderingTrianglesCase::getDrawCallMode() 4252 { 4253 return m_drawcall_mode; 4254 } 4255 4256 /** Source code for a fragment shader that should be used for the test. 4257 * 4258 * @return As per description. 4259 **/ 4260 std::string GeometryShaderRenderingTrianglesCase::getFragmentShaderCode() 4261 { 4262 static std::string fs_code = "${VERSION}\n" 4263 "\n" 4264 "precision highp float;\n" 4265 "\n" 4266 "in vec4 gs_fs_color;\n" 4267 "out vec4 result;\n" 4268 "\n" 4269 "void main()\n" 4270 "{\n" 4271 " result = gs_fs_color;\n" 4272 "}\n"; 4273 4274 return fs_code; 4275 } 4276 4277 /** Source code for a geometry shader that should be used for the test. 4278 * 4279 * @return As per description. 4280 **/ 4281 std::string GeometryShaderRenderingTrianglesCase::getGeometryShaderCode() 4282 { 4283 static const char* gs_triangles_in_lines_out_preamble = "${VERSION}\n" 4284 "\n" 4285 "${GEOMETRY_SHADER_ENABLE}\n" 4286 "\n" 4287 "layout(triangles) in;\n" 4288 "layout(line_strip, max_vertices=24) out;\n" 4289 "\n" 4290 "#define N_VERTICES (3)\n" 4291 "#define N_VERTEX0 (0)\n" 4292 "#define N_VERTEX1 (1)\n" 4293 "#define N_VERTEX2 (2)\n" 4294 "\n"; 4295 4296 static const char* gs_triangles_adjacency_in_lines_out_preamble = "${VERSION}\n" 4297 "\n" 4298 "${GEOMETRY_SHADER_ENABLE}\n" 4299 "\n" 4300 "layout(triangles_adjacency) in;\n" 4301 "layout(line_strip, max_vertices=24) out;\n" 4302 "\n" 4303 "#define N_VERTICES (6)\n" 4304 "#define N_VERTEX0 (0)\n" 4305 "#define N_VERTEX1 (2)\n" 4306 "#define N_VERTEX2 (4)\n" 4307 "\n"; 4308 4309 static const char* gs_lines_code = 4310 "uniform ivec2 renderingTargetSize;\n" 4311 "\n" 4312 "in vec4 vs_gs_color[N_VERTICES];\n" 4313 "out vec4 gs_fs_color;\n" 4314 "\n" 4315 "void main()\n" 4316 "{\n" 4317 " float dx = 2.0 / float(renderingTargetSize.x);\n" 4318 " float dy = 2.0 / float(renderingTargetSize.y);\n" 4319 "\n" 4320 " vec2 min_xy = gl_in[N_VERTEX0].gl_Position.xy;\n" 4321 " vec2 max_xy = gl_in[N_VERTEX0].gl_Position.xy;\n" 4322 "\n" 4323 " min_xy[0] = min(gl_in[N_VERTEX1].gl_Position.x, min_xy[0]);\n" 4324 " min_xy[0] = min(gl_in[N_VERTEX2].gl_Position.x, min_xy[0]);\n" 4325 " min_xy[1] = min(gl_in[N_VERTEX1].gl_Position.y, min_xy[1]);\n" 4326 " min_xy[1] = min(gl_in[N_VERTEX2].gl_Position.y, min_xy[1]);\n" 4327 "\n" 4328 " max_xy[0] = max(gl_in[N_VERTEX1].gl_Position.x, max_xy[0]);\n" 4329 " max_xy[0] = max(gl_in[N_VERTEX2].gl_Position.x, max_xy[0]);\n" 4330 " max_xy[1] = max(gl_in[N_VERTEX1].gl_Position.y, max_xy[1]);\n" 4331 " max_xy[1] = max(gl_in[N_VERTEX2].gl_Position.y, max_xy[1]);\n" 4332 "\n" 4333 " for (int n = 0; n < 3 /* segment \"sub\"-line */; ++n)\n" 4334 " {\n" 4335 " float hor_line_delta = 0.0;\n" 4336 " float ver_line_delta = 0.0;\n" 4337 "\n" 4338 " switch(n)\n" 4339 " {\n" 4340 " case 0: hor_line_delta = -dx; ver_line_delta = -dy; break;\n" 4341 " case 1: break;\n" 4342 " case 2: hor_line_delta = dx; ver_line_delta = dy; break;\n" 4343 " }\n" 4344 "\n" 4345 /* BL->TL */ 4346 " gl_Position = vec4(min_xy[0] - hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n" 4347 " gs_fs_color = vs_gs_color[N_VERTEX0];\n" 4348 " EmitVertex();\n" 4349 " gl_Position = vec4(min_xy[0] - hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n" 4350 " gs_fs_color = vs_gs_color[N_VERTEX0];\n" 4351 " EmitVertex();\n" 4352 " EndPrimitive();\n" 4353 /* TL->TR */ 4354 " gl_Position = vec4(max_xy[0] + hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n" 4355 " gs_fs_color = vs_gs_color[N_VERTEX1];\n" 4356 " EmitVertex();\n" 4357 " gl_Position = vec4(min_xy[0] - hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n" 4358 " gs_fs_color = vs_gs_color[N_VERTEX1];\n" 4359 " EmitVertex();\n" 4360 " EndPrimitive();\n" 4361 /* TR->BR */ 4362 " gl_Position = vec4(max_xy[0] + hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n" 4363 " gs_fs_color = vs_gs_color[N_VERTEX2];\n" 4364 " EmitVertex();\n" 4365 " gl_Position = vec4(max_xy[0] + hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n" 4366 " gs_fs_color = vs_gs_color[N_VERTEX2];\n" 4367 " EmitVertex();\n" 4368 " EndPrimitive();\n" 4369 /* BR->BL */ 4370 " gl_Position = vec4(min_xy[0] - hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n" 4371 " gs_fs_color = vec4(vs_gs_color[N_VERTEX0].r, vs_gs_color[N_VERTEX1].g, vs_gs_color[N_VERTEX2].b, " 4372 "vs_gs_color[N_VERTEX0].a);\n" 4373 " EmitVertex();\n" 4374 " gl_Position = vec4(max_xy[0] + hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n" 4375 " gs_fs_color = vec4(vs_gs_color[N_VERTEX0].r, vs_gs_color[N_VERTEX1].g, vs_gs_color[N_VERTEX2].b, " 4376 "vs_gs_color[N_VERTEX0].a);\n" 4377 " EmitVertex();\n" 4378 " EndPrimitive();\n" 4379 " }\n" 4380 "}\n"; 4381 4382 static const char* gs_triangles_in_points_out_preamble = "${VERSION}\n" 4383 "\n" 4384 "${GEOMETRY_SHADER_ENABLE}\n" 4385 "\n" 4386 "layout(triangles) in;\n" 4387 "layout(points, max_vertices=27) out;\n" 4388 "\n" 4389 "#define N_VERTICES (3)\n" 4390 "#define N_VERTEX0 (0)\n" 4391 "#define N_VERTEX1 (1)\n" 4392 "#define N_VERTEX2 (2)\n" 4393 "\n"; 4394 4395 static const char* gs_triangles_adjacency_in_points_out_preamble = "${VERSION}\n" 4396 "\n" 4397 "${GEOMETRY_SHADER_ENABLE}\n" 4398 "\n" 4399 "layout(triangles_adjacency) in;\n" 4400 "layout(points, max_vertices=27) out;\n" 4401 "\n" 4402 "#define N_VERTICES (6)\n" 4403 "#define N_VERTEX0 (0)\n" 4404 "#define N_VERTEX1 (2)\n" 4405 "#define N_VERTEX2 (4)\n" 4406 "\n"; 4407 4408 static const char* gs_points_code = 4409 "uniform ivec2 renderingTargetSize;\n" 4410 "\n" 4411 "in vec4 vs_gs_color[N_VERTICES];\n" 4412 "out vec4 gs_fs_color;\n" 4413 "\n" 4414 "void main()\n" 4415 "{\n" 4416 " float dx = 2.0 / float(renderingTargetSize.x);\n" 4417 " float dy = 2.0 / float(renderingTargetSize.y);\n" 4418 "\n" 4419 " for (int n = 0; n < 3 /* vertices */; ++n)\n" 4420 " {\n" 4421 " int vertex_index = (n == 0) ? N_VERTEX0 : \n" 4422 " (n == 1) ? N_VERTEX1 : \n" 4423 " N_VERTEX2;\n" 4424 /* TL */ 4425 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, -dy, 0, 0);\n" 4426 " gs_fs_color = vs_gs_color[vertex_index];\n" 4427 " EmitVertex();\n" 4428 /* TM */ 4429 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, -dy, 0, 0);\n" 4430 " gs_fs_color = vs_gs_color[vertex_index];\n" 4431 " EmitVertex();\n" 4432 /* TR */ 4433 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, -dy, 0, 0);\n" 4434 " gs_fs_color = vs_gs_color[vertex_index];\n" 4435 " EmitVertex();\n" 4436 /* ML */ 4437 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, 0, 0, 0);\n" 4438 " gs_fs_color = vs_gs_color[vertex_index];\n" 4439 " EmitVertex();\n" 4440 /* MM */ 4441 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, 0, 0, 0);\n" 4442 " gs_fs_color = vs_gs_color[vertex_index];\n" 4443 " EmitVertex();\n" 4444 /* MR */ 4445 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, 0, 0, 0);\n" 4446 " gs_fs_color = vs_gs_color[vertex_index];\n" 4447 " EmitVertex();\n" 4448 /* BL */ 4449 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, dy, 0, 0);\n" 4450 " gs_fs_color = vs_gs_color[vertex_index];\n" 4451 " EmitVertex();\n" 4452 /* BM */ 4453 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, dy, 0, 0);\n" 4454 " gs_fs_color = vs_gs_color[vertex_index];\n" 4455 " EmitVertex();\n" 4456 /* BR */ 4457 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, dy, 0, 0);\n" 4458 " gs_fs_color = vs_gs_color[vertex_index];\n" 4459 " EmitVertex();\n" 4460 " }\n" 4461 "}\n"; 4462 4463 static const char* gs_triangles_in_triangles_out_preamble = "${VERSION}\n" 4464 "\n" 4465 "${GEOMETRY_SHADER_ENABLE}\n" 4466 "\n" 4467 "layout(triangles) in;\n" 4468 "layout(triangle_strip, max_vertices=6) out;\n" 4469 "\n" 4470 "#define N_VERTICES (3)\n" 4471 "#define N_VERTEX0 (0)\n" 4472 "#define N_VERTEX1 (1)\n" 4473 "#define N_VERTEX2 (2)\n" 4474 "\n"; 4475 4476 static const char* gs_triangles_adjacency_in_triangles_out_preamble = 4477 "${VERSION}\n" 4478 "\n" 4479 "${GEOMETRY_SHADER_ENABLE}\n" 4480 "\n" 4481 "layout(triangles_adjacency) in;\n" 4482 "layout(triangle_strip, max_vertices=6) out;\n" 4483 "\n" 4484 "#define N_VERTICES (6)\n" 4485 "#define N_VERTEX0 (0)\n" 4486 "#define N_VERTEX1 (2)\n" 4487 "#define N_VERTEX2 (4)\n" 4488 "\n"; 4489 4490 static const char* gs_triangles_code = "uniform ivec2 renderingTargetSize;\n" 4491 "\n" 4492 "in vec4 vs_gs_color[N_VERTICES];\n" 4493 "out vec4 gs_fs_color;\n" 4494 "\n" 4495 "void main()\n" 4496 "{\n" 4497 " float dx = 2.0 / float(renderingTargetSize.x);\n" 4498 " float dy = 2.0 / float(renderingTargetSize.y);\n" 4499 "\n" 4500 " vec4 v0 = gl_in[N_VERTEX0].gl_Position;\n" 4501 " vec4 v1 = gl_in[N_VERTEX1].gl_Position;\n" 4502 " vec4 v2 = gl_in[N_VERTEX2].gl_Position;\n" 4503 " vec4 a = v0;\n" 4504 " vec4 b;\n" 4505 " vec4 c;\n" 4506 " vec4 d;\n" 4507 "\n" 4508 /* Sort incoming vertices: 4509 * 4510 * a) a - vertex in origin. 4511 * b) b - vertex located on the same height as a. 4512 * c) c - remaining vertex. 4513 */ 4514 " if (abs(v1.w) >= 1.0)\n" 4515 " {\n" 4516 " a = v1;\n" 4517 " \n" 4518 " if (abs(v0.x - a.x) < dx)\n" 4519 " {\n" 4520 " b = v0;\n" 4521 " c = v2;\n" 4522 " }\n" 4523 " else\n" 4524 " {\n" 4525 " b = v2;\n" 4526 " c = v0;\n" 4527 " }\n" 4528 " }\n" 4529 " else\n" 4530 " if (abs(v2.w) >= 1.0)\n" 4531 " {\n" 4532 " a = v2;\n" 4533 " \n" 4534 " if (abs(v0.x - a.x) < dx)\n" 4535 " {\n" 4536 " b = v0;\n" 4537 " c = v1;\n" 4538 " }\n" 4539 " else\n" 4540 " {\n" 4541 " b = v1;\n" 4542 " c = v0;\n" 4543 " }\n" 4544 " }\n" 4545 " else\n" 4546 " {\n" 4547 " if (abs(v1.x - a.x) < dx)\n" 4548 " {\n" 4549 " b = v1;\n" 4550 " c = v2;\n" 4551 " }\n" 4552 " else\n" 4553 " {\n" 4554 " b = v2;\n" 4555 " c = v1;\n" 4556 " }\n" 4557 " }\n" 4558 " \n" 4559 " d = (b + c) * vec4(0.5);\n" 4560 /* Now given the following configuration: (orientation does not matter) 4561 * 4562 * B 4563 * |\ 4564 * | D 4565 * | \ 4566 * A---C 4567 * 4568 * emit ABD and ACD triangles */ 4569 4570 /* First sub-triangle */ 4571 " gl_Position = vec4(a.xyz, 1);\n" 4572 " gs_fs_color = vs_gs_color[N_VERTEX0];\n" 4573 " EmitVertex();\n" 4574 "\n" 4575 " gl_Position = vec4(b.xyz, 1);\n" 4576 " gs_fs_color = vs_gs_color[N_VERTEX0];\n" 4577 " EmitVertex();\n" 4578 "\n" 4579 " gl_Position = vec4(d.xyz, 1);\n" 4580 " gs_fs_color = vs_gs_color[N_VERTEX0];\n" 4581 " EmitVertex();\n" 4582 " EndPrimitive();\n" 4583 /* Second sub-triangle */ 4584 " gl_Position = vec4(a.xyz, 1);\n" 4585 " gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n" 4586 " EmitVertex();\n" 4587 "\n" 4588 " gl_Position = vec4(c.xyz, 1);\n" 4589 " gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n" 4590 " EmitVertex();\n" 4591 "\n" 4592 " gl_Position = vec4(d.xyz, 1);\n" 4593 " gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n" 4594 " EmitVertex();\n" 4595 " EndPrimitive();\n" 4596 "}\n"; 4597 4598 std::string result; 4599 4600 switch (m_output_type) 4601 { 4602 case SHADER_OUTPUT_TYPE_POINTS: 4603 { 4604 std::stringstream gs_triangles_code_stringstream; 4605 std::string gs_triangles_code_string; 4606 std::stringstream gs_triangles_adjacency_code_stringstream; 4607 std::string gs_triangles_adjacency_code_string; 4608 4609 switch (m_drawcall_mode) 4610 { 4611 case GL_TRIANGLE_FAN: 4612 case GL_TRIANGLE_STRIP: 4613 case GL_TRIANGLES: 4614 { 4615 gs_triangles_code_stringstream << gs_triangles_in_points_out_preamble << gs_points_code; 4616 4617 gs_triangles_code_string = gs_triangles_code_stringstream.str(); 4618 result = gs_triangles_code_string; 4619 4620 break; 4621 } 4622 4623 case GL_TRIANGLES_ADJACENCY_EXT: 4624 case GL_TRIANGLE_STRIP_ADJACENCY_EXT: 4625 { 4626 gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_points_out_preamble << gs_points_code; 4627 4628 gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str(); 4629 result = gs_triangles_adjacency_code_string; 4630 4631 break; 4632 } 4633 4634 default: 4635 { 4636 TCU_FAIL("Unrecognized draw call mode"); 4637 } 4638 } 4639 4640 break; 4641 } 4642 4643 case SHADER_OUTPUT_TYPE_LINE_STRIP: 4644 { 4645 std::stringstream gs_triangles_code_stringstream; 4646 std::string gs_triangles_code_string; 4647 std::stringstream gs_triangles_adjacency_code_stringstream; 4648 std::string gs_triangles_adjacency_code_string; 4649 4650 switch (m_drawcall_mode) 4651 { 4652 case GL_TRIANGLE_FAN: 4653 case GL_TRIANGLE_STRIP: 4654 case GL_TRIANGLES: 4655 { 4656 gs_triangles_code_stringstream << gs_triangles_in_lines_out_preamble << gs_lines_code; 4657 4658 gs_triangles_code_string = gs_triangles_code_stringstream.str(); 4659 result = gs_triangles_code_string; 4660 4661 break; 4662 } 4663 4664 case GL_TRIANGLES_ADJACENCY_EXT: 4665 case GL_TRIANGLE_STRIP_ADJACENCY_EXT: 4666 { 4667 gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_lines_out_preamble << gs_lines_code; 4668 4669 gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str(); 4670 result = gs_triangles_adjacency_code_string; 4671 4672 break; 4673 } 4674 4675 default: 4676 { 4677 TCU_FAIL("Unrecognized draw call mode"); 4678 } 4679 } 4680 4681 break; 4682 } 4683 4684 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 4685 { 4686 std::stringstream gs_triangles_code_stringstream; 4687 std::string gs_triangles_code_string; 4688 std::stringstream gs_triangles_adjacency_code_stringstream; 4689 std::string gs_triangles_adjacency_code_string; 4690 4691 switch (m_drawcall_mode) 4692 { 4693 case GL_TRIANGLE_FAN: 4694 case GL_TRIANGLE_STRIP: 4695 case GL_TRIANGLES: 4696 { 4697 gs_triangles_code_stringstream << gs_triangles_in_triangles_out_preamble << gs_triangles_code; 4698 4699 gs_triangles_code_string = gs_triangles_code_stringstream.str(); 4700 result = gs_triangles_code_string; 4701 4702 break; 4703 } /* case GL_TRIANGLES: */ 4704 4705 case GL_TRIANGLES_ADJACENCY_EXT: 4706 case GL_TRIANGLE_STRIP_ADJACENCY_EXT: 4707 { 4708 gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_triangles_out_preamble 4709 << gs_triangles_code; 4710 4711 gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str(); 4712 result = gs_triangles_adjacency_code_string; 4713 4714 break; 4715 } 4716 4717 default: 4718 { 4719 TCU_FAIL("Unrecognized draw call mode"); 4720 } 4721 } /* switch (m_drawcall_mode) */ 4722 4723 break; 4724 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */ 4725 4726 default: 4727 { 4728 TCU_FAIL("Unsupported shader output type"); 4729 } 4730 } /* switch (drawcall_mode) */ 4731 4732 return result; 4733 } 4734 4735 /** Returns amount of bytes that should be allocated for a buffer object to hold 4736 * vertex data to be used for glDrawArrays*() calls. 4737 * 4738 * @param instanced True if the data is to be used in regard to instanced draw calls, 4739 * false otherwise. 4740 * 4741 * @return As per description. 4742 **/ 4743 glw::GLuint GeometryShaderRenderingTrianglesCase::getRawArraysDataBufferSize(bool instanced) 4744 { 4745 return instanced ? m_raw_array_instanced_data_size : m_raw_array_noninstanced_data_size; 4746 } 4747 4748 /** Returns vertex data for the test. Only to be used for glDrawArrays*() calls. 4749 * 4750 * @param instanced True if the data is to be used in regard to instanced draw calls, 4751 * false otherwise. 4752 * 4753 * @return As per description. 4754 **/ 4755 const void* GeometryShaderRenderingTrianglesCase::getRawArraysDataBuffer(bool instanced) 4756 { 4757 return instanced ? m_raw_array_instanced_data : m_raw_array_noninstanced_data; 4758 } 4759 4760 /** Retrieves resolution of off-screen rendering buffer that should be used for the test. 4761 * 4762 * @param n_instances Amount of draw call instances this render target will be used for. 4763 * @param out_width Deref will be used to store rendertarget's width. Must not be NULL. 4764 * @param out_height Deref will be used to store rendertarget's height. Must not be NULL. 4765 **/ 4766 void GeometryShaderRenderingTrianglesCase::getRenderTargetSize(unsigned int n_instances, unsigned int* out_width, 4767 unsigned int* out_height) 4768 { 4769 switch (m_output_type) 4770 { 4771 case SHADER_OUTPUT_TYPE_LINE_STRIP: 4772 case SHADER_OUTPUT_TYPE_POINTS: 4773 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 4774 { 4775 *out_width = 29; /* as per test spec */ 4776 *out_height = 29 * n_instances; /* as per test spec */ 4777 4778 break; 4779 } 4780 4781 default: 4782 { 4783 TCU_FAIL("Unsupported output type"); 4784 } 4785 } 4786 } 4787 4788 /** Returns amount of bytes that should be allocated for a buffer object to hold 4789 * vertex data to be used for glDrawElements*() calls. 4790 * 4791 * @param instanced true if the call is being made for an instanced draw call, false otherwise. 4792 * 4793 * @return As per description. 4794 **/ 4795 glw::GLuint GeometryShaderRenderingTrianglesCase::getUnorderedArraysDataBufferSize(bool instanced) 4796 { 4797 return (instanced) ? m_unordered_array_instanced_data_size : m_unordered_array_noninstanced_data_size; 4798 } 4799 4800 /** Returns vertex data for the test. Only to be used for glDrawElements*() calls. 4801 * 4802 * @param instanced true if the call is being made for an instanced draw call, false otherwise. 4803 * 4804 * @return As per description. 4805 **/ 4806 const void* GeometryShaderRenderingTrianglesCase::getUnorderedArraysDataBuffer(bool instanced) 4807 { 4808 return instanced ? m_unordered_array_instanced_data : m_unordered_array_noninstanced_data; 4809 } 4810 4811 /** Returns amount of bytes that should be allocated for a buffer object to hold 4812 * index data to be used for glDrawElements*() calls. 4813 * 4814 * @param instanced true if the call is being made for an instanced draw call, false otherwise. 4815 * 4816 * @return As per description. 4817 **/ 4818 glw::GLuint GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataBufferSize(bool instanced) 4819 { 4820 return instanced ? m_unordered_elements_instanced_data_size : m_unordered_elements_noninstanced_data_size; 4821 } 4822 4823 /** Returns index data for the test. Only to be used for glDrawElements*() calls. 4824 * 4825 * @param instanced true if the call is being made for an instanced draw call, false otherwise. 4826 * 4827 * @return As per description. 4828 **/ 4829 const void* GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataBuffer(bool instanced) 4830 { 4831 return instanced ? m_unordered_elements_instanced_data : m_unordered_elements_noninstanced_data; 4832 } 4833 4834 /** Returns type of the index, to be used for glDrawElements*() calls. 4835 * 4836 * @return As per description. 4837 **/ 4838 glw::GLenum GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataType() 4839 { 4840 return GL_UNSIGNED_BYTE; 4841 } 4842 4843 /** Retrieves maximum index value. To be used for glDrawRangeElements() test only. 4844 * 4845 * @return As per description. 4846 **/ 4847 glw::GLubyte GeometryShaderRenderingTrianglesCase::getUnorderedElementsMaxIndex() 4848 { 4849 return m_unordered_elements_max_index; 4850 } 4851 4852 /** Retrieves minimum index value. To be used for glDrawRangeElements() test only. 4853 * 4854 * @return As per description. 4855 **/ 4856 glw::GLubyte GeometryShaderRenderingTrianglesCase::getUnorderedElementsMinIndex() 4857 { 4858 return m_unordered_elements_min_index; 4859 } 4860 4861 /** Retrieves vertex shader code to be used for the test. 4862 * 4863 * @return As per description. 4864 **/ 4865 std::string GeometryShaderRenderingTrianglesCase::getVertexShaderCode() 4866 { 4867 static std::string vs_code = 4868 "${VERSION}\n" 4869 "\n" 4870 "in vec4 position;\n" 4871 "out vec4 vs_gs_color;\n" 4872 "\n" 4873 "uniform bool is_lines_output;\n" 4874 "uniform bool is_indexed_draw_call;\n" 4875 "uniform bool is_instanced_draw_call;\n" 4876 "uniform bool is_points_output;\n" 4877 "uniform bool is_triangle_fan_input;\n" 4878 "uniform bool is_triangle_strip_input;\n" 4879 "uniform bool is_triangle_strip_adjacency_input;\n" 4880 "uniform bool is_triangles_adjacency_input;\n" 4881 "uniform bool is_triangles_input;\n" 4882 "uniform bool is_triangles_output;\n" 4883 "uniform ivec2 renderingTargetSize;\n" 4884 "uniform ivec2 singleRenderingTargetSize;\n" 4885 "\n" 4886 "void main()\n" 4887 "{\n" 4888 " gl_Position = position + vec4(float(gl_InstanceID) ) * vec4(0, float(singleRenderingTargetSize.y) / " 4889 "float(renderingTargetSize.y), 0, 0) * vec4(2.0);\n" 4890 " vs_gs_color = vec4(1.0, 0.0, 0.0, 0.0);\n" 4891 "\n" 4892 /*********************************** LINES OUTPUT *******************************/ 4893 " if (is_lines_output)\n" 4894 " {\n" 4895 " if (!is_indexed_draw_call)\n" 4896 " {\n" 4897 /* Non-indiced draw calls: */ 4898 /* GL_TRIANGLE_FAN draw call mode */ 4899 " if (is_triangle_fan_input)\n" 4900 " {\n" 4901 " switch(gl_VertexID)\n" 4902 " {\n" 4903 " case 0: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4904 " case 1:\n" 4905 " case 5: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 4906 " case 2: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 4907 " case 3: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 4908 " case 4: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 4909 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 4910 " }\n" /* switch(gl_VertexID) */ 4911 " }\n" /* if (is_triangle_fan_input) */ 4912 " else\n" 4913 /* GL_TRIANGLE_STRIP draw call mode */ 4914 " if (is_triangle_strip_input)\n" 4915 " {\n" 4916 " switch(gl_VertexID)\n" 4917 " {\n" 4918 " case 1:\n" 4919 " case 6: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 4920 " case 0:\n" 4921 " case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4922 " case 2: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 4923 " case 3: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 4924 " case 5: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 4925 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 4926 " }\n" /* switch(gl_VertexID) */ 4927 " }\n" /* if (is_triangle_strip_input) */ 4928 " else\n" 4929 /* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */ 4930 " if (is_triangle_strip_adjacency_input)\n" 4931 " {\n" 4932 " switch(gl_VertexID)\n" 4933 " {\n" 4934 " case 2:\n" 4935 " case 12: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 4936 " case 0:\n" 4937 " case 8: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4938 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 4939 " case 6: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 4940 " case 10: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 4941 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 4942 " }\n" /* switch(gl_VertexID) */ 4943 " }\n" /* if (is_triangle_strip_adjacency_input) */ 4944 " else\n" 4945 " if (is_triangles_input)\n" 4946 " {\n" 4947 /* GL_TRIANGLES draw call mode */ 4948 " switch(gl_VertexID)\n" 4949 " {\n" 4950 " case 0: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4951 " case 1: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 4952 " case 2: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 4953 " case 3: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4954 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 4955 " case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 4956 " case 6: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4957 " case 7: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 4958 " case 8: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 4959 " case 9: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4960 " case 10: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 4961 " case 11: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 4962 " }\n" /* switch(gl_VertexID) */ 4963 " }\n" /* if (is_triangles_input) */ 4964 " else\n" 4965 " if (is_triangles_adjacency_input)\n" 4966 " {\n" 4967 /* GL_TRIANGLES_ADJACENCY_EXT draw call mode */ 4968 " vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n" 4969 "\n" 4970 " switch(gl_VertexID)\n" 4971 " {\n" 4972 /* TL triangle */ 4973 " case 0: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4974 " case 2: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 4975 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 4976 /* TR triangle */ 4977 " case 6: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4978 " case 8: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 4979 " case 10: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 4980 /* BR triangle */ 4981 " case 12: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4982 " case 14: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 4983 " case 16: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 4984 /* BL triangle */ 4985 " case 18: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 4986 " case 20: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 4987 " case 22: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 4988 " }\n" /* switch (gl_VertexID) */ 4989 " }\n" /* if (is_triangles_adjacency_input) */ 4990 " }\n" /* if (!is_indexed_draw_call) */ 4991 " else\n" 4992 " {\n" 4993 /* Indiced draw call: */ 4994 " if (is_triangles_input)\n" 4995 " {\n" 4996 /* GL_TRIANGLES draw call mode */ 4997 " switch(gl_VertexID)\n" 4998 " {\n" 4999 " case 11: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5000 " case 10: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5001 " case 9: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5002 " case 8: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5003 " case 7: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5004 " case 6: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5005 " case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5006 " case 4: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5007 " case 3: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5008 " case 2: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5009 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5010 " case 0: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5011 " }\n" /* switch(gl_VertexID) */ 5012 " }\n" /* if (is_triangles_input) */ 5013 " else\n" 5014 " if (is_triangle_fan_input)\n" 5015 " {\n" 5016 /* GL_TRIANGLE_FAN draw call mode */ 5017 " switch(gl_VertexID)\n" 5018 " {\n" 5019 " case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5020 " case 4:\n" 5021 " case 0: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5022 " case 3: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5023 " case 2: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5024 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5025 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5026 " }\n" /* switch(gl_VertexID) */ 5027 " }\n" /*( if (is_triangle_fan_input) */ 5028 " else\n" 5029 " if (is_triangle_strip_input)\n" 5030 " {\n" 5031 /* GL_TRIANGLE_STRIP draw call mode */ 5032 " switch (gl_VertexID)\n" 5033 " {\n" 5034 " case 5:\n" 5035 " case 0: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5036 " case 6:\n" 5037 " case 2: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5038 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5039 " case 3: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5040 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5041 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5042 " }\n" /* switch(gl_VertexID) */ 5043 " }\n" /* if (is_triangle_strip_input) */ 5044 " else\n" 5045 " if (is_triangle_strip_adjacency_input)\n" 5046 " {\n" 5047 /* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */ 5048 " switch(gl_VertexID)\n" 5049 " {\n" 5050 " case 11:\n" 5051 " case 1: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5052 " case 13:\n" 5053 " case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5054 " case 9: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5055 " case 7: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5056 " case 3: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5057 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5058 " }\n" /* switch(gl_VertexID) */ 5059 " }\n" /* if (is_triangle_strip_adjacency_input) */ 5060 " else\n" 5061 " if (is_triangles_adjacency_input)\n" 5062 " {\n" 5063 /* GL_TRIANGLES_ADJACENCY_EXT draw call mode */ 5064 " vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n" 5065 "\n" 5066 " switch(gl_VertexID)\n" 5067 " {\n" 5068 /* TL triangle */ 5069 " case 23: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5070 " case 21: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5071 " case 19: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5072 /* TR triangle */ 5073 " case 17: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5074 " case 15: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5075 " case 13: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5076 /* BR triangle */ 5077 " case 11: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5078 " case 9: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5079 " case 7: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5080 /* BL triangle */ 5081 " case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5082 " case 3: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5083 " case 1: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5084 " }\n" /* switch(gl_VertexID) */ 5085 " }\n" /* if (is_triangles_adjacency_input) */ 5086 " }\n" 5087 " }\n" /* if (is_lines_output) */ 5088 " else\n" 5089 /*********************************** POINTS OUTPUT *******************************/ 5090 " if (is_points_output)\n" 5091 " {\n" 5092 " if (!is_indexed_draw_call)\n" 5093 " {\n" 5094 /* Non-indiced draw calls */ 5095 " if (is_triangles_adjacency_input)\n" 5096 " {\n" 5097 /* GL_TRIANGLES_ADJACENCY_EXT draw call mode */ 5098 " vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n" 5099 "\n" 5100 " switch (gl_VertexID)\n" 5101 " {\n" 5102 " case 0:\n" 5103 " case 6:\n" 5104 " case 12:\n" 5105 " case 18: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5106 " case 2:\n" 5107 " case 22: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5108 " case 4:\n" 5109 " case 8: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5110 " case 10:\n" 5111 " case 14: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5112 " case 16:\n" 5113 " case 20: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5114 " }\n" /* switch (gl_VertexID) */ 5115 " }\n" /* if (is_triangles_adjacency_input) */ 5116 " else\n" 5117 " if (is_triangle_fan_input)\n" 5118 " {\n" 5119 /* GL_TRIANGLE_FAN draw call mode */ 5120 " switch(gl_VertexID)\n" 5121 " {\n" 5122 " case 0: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5123 " case 1:\n" 5124 " case 5: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5125 " case 2: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5126 " case 3: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5127 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5128 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5129 " }\n" /* switch(gl_VertexID) */ 5130 " }\n" /* if (is_triangle_fan_input) */ 5131 " else\n" 5132 " if (is_triangle_strip_input)\n" 5133 " {\n" 5134 /* GL_TRIANGLE_STRIP draw call mode */ 5135 " switch (gl_VertexID)\n" 5136 " {\n" 5137 " case 1:\n" 5138 " case 4: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5139 " case 0:\n" 5140 " case 6: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5141 " case 2: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5142 " case 3: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5143 " case 5: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5144 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5145 " }\n" /* switch(gl_VertexID) */ 5146 " }\n" /* if (is_triangle_strip_input) */ 5147 " else\n" 5148 " if (is_triangle_strip_adjacency_input)\n" 5149 " {\n" 5150 /* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */ 5151 " switch (gl_VertexID)\n" 5152 " {\n" 5153 " case 2:\n" 5154 " case 8: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5155 " case 0:\n" 5156 " case 12: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5157 " case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5158 " case 6: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5159 " case 10: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5160 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5161 " }\n" /* switch(gl_VertexID) */ 5162 " }\n" /* if (is_triangle_strip_input) */ 5163 " else\n" 5164 " if (is_triangles_input)\n" 5165 " {\n" 5166 /* GL_TRIANGLES draw call mode */ 5167 " switch (gl_VertexID)\n" 5168 " {\n" 5169 /* A */ 5170 " case 0:\n" 5171 " case 3:\n" 5172 " case 6:\n" 5173 " case 9: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5174 /* B */ 5175 " case 1:\n" 5176 " case 11: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5177 /* C */ 5178 " case 2:\n" 5179 " case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5180 /* D */ 5181 " case 5:\n" 5182 " case 7: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5183 /* E */ 5184 " case 8:\n" 5185 " case 10: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5186 " }\n" /* switch (gl_VertexID) */ 5187 " }\n" /* if (is_triangles_input) */ 5188 " }\n" /* if (!is_indexed_draw_call) "*/ 5189 " else\n" 5190 " {\n" 5191 /* Indiced draw calls: */ 5192 " if (is_triangle_fan_input)\n" 5193 " {\n" 5194 /* GL_TRIANGLE_FAN input */ 5195 " switch (gl_VertexID)\n" 5196 " {\n" 5197 " case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5198 " case 4:\n" 5199 " case 0: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5200 " case 3: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5201 " case 2: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5202 " case 1: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5203 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5204 " }\n" /* switch(gl_VertexID) */ 5205 " }\n" /* if (is_triangle_fan_input) */ 5206 " else\n" 5207 " if (is_triangle_strip_input)\n" 5208 " {\n" 5209 " switch (gl_VertexID)\n" 5210 " {\n" 5211 " case 5:\n" 5212 " case 2: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5213 " case 6:\n" 5214 " case 0: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5215 " case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5216 " case 3: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5217 " case 1: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5218 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5219 " }\n" /* switch(gl_VertexID) */ 5220 " }\n" /* if (is_triangle_strip_input) */ 5221 " else\n" 5222 " if (is_triangle_strip_adjacency_input)\n" 5223 " {\n" 5224 /* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */ 5225 " switch (gl_VertexID)\n" 5226 " {\n" 5227 " case 11:\n" 5228 " case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5229 " case 13:\n" 5230 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5231 " case 9: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5232 " case 7: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5233 " case 3: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5234 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n" 5235 " }\n" /* switch(gl_VertexID) */ 5236 " }\n" /* if (is_triangle_strip_adjacency_input) */ 5237 " else\n" 5238 " if (is_triangles_adjacency_input)\n" 5239 " {\n" 5240 " vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n" 5241 /* GL_TRIANGLES_ADJACENCY_EXT input */ 5242 " switch (gl_VertexID)\n" 5243 " {\n" 5244 /* A */ 5245 " case 23:\n" 5246 " case 17:\n" 5247 " case 11:\n" 5248 " case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5249 /* B */ 5250 " case 21:\n" 5251 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5252 /* C */ 5253 " case 19:\n" 5254 " case 15: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5255 /* D */ 5256 " case 13:\n" 5257 " case 9: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5258 /* E */ 5259 " case 7:\n" 5260 " case 3: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5261 " }\n" /* switch (gl_VertexID) */ 5262 " }\n" /* if (is_triangles_adjacency_input) */ 5263 " else\n" 5264 " if (is_triangles_input)\n" 5265 " {\n" 5266 /* GL_TRIANGLES input */ 5267 " switch (gl_VertexID)\n" 5268 " {\n" 5269 " case 11:\n" 5270 " case 8:\n" 5271 " case 5:\n" 5272 " case 2: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n" 5273 " case 10:\n" 5274 " case 0: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n" 5275 " case 9:\n" 5276 " case 7: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n" 5277 " case 6:\n" 5278 " case 4: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n" 5279 " case 3:\n" 5280 " case 1: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n" 5281 " }\n" /* switch (gl_VertexID) */ 5282 " }\n" /* if (is_triangles_input) */ 5283 " }\n" 5284 " }\n" /* if (is_points_output) */ 5285 " else\n" 5286 /*********************************** TRIANGLES OUTPUT *******************************/ 5287 " if (is_triangles_output)\n" 5288 " {\n" 5289 " int vertex_id = 0;\n" 5290 "\n" 5291 " if (!is_indexed_draw_call && is_triangles_adjacency_input && (gl_VertexID % 2 == 0) )\n" 5292 " {\n" 5293 " vertex_id = gl_VertexID / 2 + 1;\n" 5294 " }\n" 5295 " else\n" 5296 " {\n" 5297 " vertex_id = gl_VertexID + 1;\n" 5298 " }\n" 5299 "\n" 5300 " vs_gs_color = vec4(float(vertex_id) / 48.0, float(vertex_id % 3) / 2.0, float(vertex_id % 4) / 3.0, " 5301 "float(vertex_id % 5) / 4.0);\n" 5302 " }\n" 5303 "}\n"; 5304 std::string result; 5305 5306 switch (m_output_type) 5307 { 5308 case SHADER_OUTPUT_TYPE_LINE_STRIP: 5309 case SHADER_OUTPUT_TYPE_POINTS: 5310 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 5311 { 5312 result = vs_code; 5313 5314 break; 5315 } 5316 5317 default: 5318 { 5319 TCU_FAIL("Unrecognized output type"); 5320 } 5321 } /* switch (m_output_type) */ 5322 5323 return result; 5324 } 5325 5326 /** Sets test-specific uniforms for a program object that is then used for the draw call. 5327 * 5328 * @param drawcall_type Type of the draw call that is to follow right after this function is called. 5329 **/ 5330 void GeometryShaderRenderingTrianglesCase::setUniformsBeforeDrawCall(_draw_call_type drawcall_type) 5331 { 5332 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5333 5334 glw::GLint is_lines_output_uniform_location = gl.getUniformLocation(m_po_id, "is_lines_output"); 5335 glw::GLint is_indexed_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_indexed_draw_call"); 5336 glw::GLint is_instanced_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_instanced_draw_call"); 5337 glw::GLint is_points_output_uniform_location = gl.getUniformLocation(m_po_id, "is_points_output"); 5338 glw::GLint is_triangle_fan_input_uniform_location = gl.getUniformLocation(m_po_id, "is_triangle_fan_input"); 5339 glw::GLint is_triangle_strip_input_uniform_location = gl.getUniformLocation(m_po_id, "is_triangle_strip_input"); 5340 glw::GLint is_triangle_strip_adjacency_input_uniform_location = 5341 gl.getUniformLocation(m_po_id, "is_triangle_strip_adjacency_input"); 5342 glw::GLint is_triangles_adjacency_input_uniform_location = 5343 gl.getUniformLocation(m_po_id, "is_triangles_adjacency_input"); 5344 glw::GLint is_triangles_input_uniform_location = gl.getUniformLocation(m_po_id, "is_triangles_input"); 5345 glw::GLint is_triangles_output_uniform_location = gl.getUniformLocation(m_po_id, "is_triangles_output"); 5346 5347 gl.uniform1i(is_lines_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_LINE_STRIP); 5348 gl.uniform1i(is_points_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_POINTS); 5349 gl.uniform1i(is_triangle_fan_input_uniform_location, m_drawcall_mode == GL_TRIANGLE_FAN); 5350 gl.uniform1i(is_triangle_strip_input_uniform_location, m_drawcall_mode == GL_TRIANGLE_STRIP); 5351 gl.uniform1i(is_triangles_adjacency_input_uniform_location, m_drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT); 5352 gl.uniform1i(is_triangle_strip_adjacency_input_uniform_location, 5353 m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT); 5354 gl.uniform1i(is_triangles_input_uniform_location, m_drawcall_mode == GL_TRIANGLES); 5355 gl.uniform1i(is_triangles_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_TRIANGLE_STRIP); 5356 gl.uniform1i(is_indexed_draw_call_uniform_location, (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS || 5357 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED || 5358 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS)); 5359 gl.uniform1i(is_instanced_draw_call_uniform_location, 5360 (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED) || 5361 (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED)); 5362 } 5363 5364 /** Verifies that the rendered data is correct. 5365 * 5366 * @param drawcall_type Type of the draw call that was used to render the geometry. 5367 * @param instance_id Instance ID to be verified. Use 0 for non-instanced draw calls. 5368 * @param data Contents of the rendertarget after the test has finished rendering. 5369 **/ 5370 void GeometryShaderRenderingTrianglesCase::verify(_draw_call_type drawcall_type, unsigned int instance_id, 5371 const unsigned char* data) 5372 { 5373 const float epsilon = 1.0f / 256.0f; 5374 float dx = 0.0f; 5375 float dy = 0.0f; 5376 unsigned int single_rt_height = 0; 5377 unsigned int single_rt_width = 0; 5378 5379 getRenderTargetSize(1, &single_rt_width, &single_rt_height); 5380 5381 dx = 2.0f / float(single_rt_width); 5382 dy = 2.0f / float(single_rt_height); 5383 5384 switch (m_output_type) 5385 { 5386 case SHADER_OUTPUT_TYPE_LINE_STRIP: 5387 { 5388 /* Reference color data, taken directly from vertex shader. These are assigned 5389 * to subsequent vertex ids, starting from 0. 5390 */ 5391 const float ref_color_data[] = { /* TL triangle */ 5392 0.1f, 0.2f, 0.3f, 0.4f, 0.2f, 0.3f, 0.4f, 0.5f, 0.3f, 0.4f, 0.5f, 0.6f, 5393 /* TR triangle */ 5394 0.1f, 0.2f, 0.3f, 0.4f, 0.3f, 0.4f, 0.5f, 0.6f, 0.4f, 0.5f, 0.6f, 0.7f, 5395 /* BR triangle */ 5396 0.1f, 0.2f, 0.3f, 0.4f, 0.4f, 0.5f, 0.6f, 0.7f, 0.5f, 0.6f, 0.7f, 0.8f, 5397 /* BL triangle */ 5398 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.2f, 0.3f, 0.4f, 0.5f 5399 }; 5400 5401 /* Assuming single-instanced case, the test divides the screen-space into four adjacent quads. 5402 * Internal edges will overlap. Given their different coloring, we exclude them from verification. 5403 * This means we're only interested in checking the quad exteriors. 5404 * 5405 * GS takes a single triangle (ABC), calculates max & min XY of the BB and: 5406 * - uses (A.r, A.g, A.b, A.a) for left line segment (bottom left->top-left) (line segment index in code:0) 5407 * - uses (B.r, B.g, B.b, B.a) for top line segment (top-left->top-right) (line segment index in code:1) 5408 * - uses (C.r, C.g, C.b, C.a) for right line segment (top-right->bottom-right) (line segment index in code:2) 5409 * - uses (A.r, B.g, C.b, A.a) for bottom line segment (bottom-right->bottom-left) (line segment index in code:3) 5410 * 5411 * The test feeds input triangles arranged in the following order: 5412 * 1) Top-left corner; (quarter index in code:0); 5413 * 2) Top-right corner; (quarter index in code:1); 5414 * 3) Bottom-right corner; (quarter index in code:2); 5415 * 4) Bottom-left corner; (quarter index in code:3); 5416 * 5417 * The test renders line segments of width 3 by rendering three lines of width 1 next to each other. 5418 * 5419 * Sample locations are precomputed - they are centers of line segments being considered. 5420 * 5421 * Expected color is computed on-the-fly in code, to ease investigation for driver developers, 5422 * in case this test fails on any ES (or GL) implementation. 5423 */ 5424 int ref_line_segment_index = -1; 5425 int ref_quarter_index = -1; 5426 float ref_sample_rgba[4] = { 0, 0, 0, 0 }; 5427 float ref_sample_xy_float[2] = { 0 }; 5428 int ref_sample_xy_int[2] = { 0 }; 5429 int ref_triangle_index = -1; 5430 5431 for (int n_edge = 0; n_edge < 8 /* edges */; ++n_edge) 5432 { 5433 switch (n_edge) 5434 { 5435 case 0: 5436 { 5437 /* Top left half, left edge */ 5438 ref_line_segment_index = 0; 5439 ref_quarter_index = 0; 5440 ref_triangle_index = 0; 5441 5442 break; 5443 } 5444 5445 case 1: 5446 { 5447 /* Top-left half, top edge. */ 5448 ref_line_segment_index = 1; 5449 ref_quarter_index = 0; 5450 ref_triangle_index = 0; 5451 5452 break; 5453 } 5454 5455 case 2: 5456 { 5457 /* Top-right half, top edge. */ 5458 ref_line_segment_index = 1; 5459 ref_quarter_index = 1; 5460 ref_triangle_index = 1; 5461 5462 break; 5463 } 5464 5465 case 3: 5466 { 5467 /* Top-right half, right edge. */ 5468 ref_line_segment_index = 2; 5469 ref_quarter_index = 1; 5470 ref_triangle_index = 1; 5471 5472 break; 5473 } 5474 5475 case 4: 5476 { 5477 /* Bottom-right half, right edge. */ 5478 ref_line_segment_index = 2; 5479 ref_quarter_index = 2; 5480 ref_triangle_index = 2; 5481 5482 break; 5483 } 5484 5485 case 5: 5486 { 5487 /* Bottom-right half, bottom edge. */ 5488 ref_line_segment_index = 3; 5489 ref_quarter_index = 2; 5490 ref_triangle_index = 2; 5491 5492 break; 5493 } 5494 5495 case 6: 5496 { 5497 /* Bottom-left half, bottom edge. */ 5498 ref_line_segment_index = 3; 5499 ref_quarter_index = 3; 5500 ref_triangle_index = 3; 5501 5502 break; 5503 } 5504 5505 case 7: 5506 { 5507 /* Bottom-left half, left edge. */ 5508 ref_line_segment_index = 0; 5509 ref_quarter_index = 3; 5510 ref_triangle_index = 3; 5511 5512 break; 5513 } 5514 5515 default: 5516 { 5517 TCU_FAIL("Unrecognized edge index"); 5518 } 5519 } /* switch (n_edge) */ 5520 5521 /* Compute reference color. 5522 * 5523 * When drawing with GL_TRIANGLE_STRIP data or GL_TRIANGLE_STRIP_ADJACENCY_EXT, top-right triangle is drawn two times. 5524 * During second re-draw, a different combination of vertex colors is used. 5525 * Take this into account. 5526 */ 5527 switch (ref_line_segment_index) 5528 { 5529 case 0: 5530 { 5531 /* Left segment */ 5532 memcpy(ref_sample_rgba, 5533 ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ + 5534 0 /* first vertex data */, 5535 sizeof(float) * 4 /* components */); 5536 5537 if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) && 5538 ref_triangle_index == 1 /* top-right triangle */) 5539 { 5540 /* First vertex */ 5541 ref_sample_rgba[0] = 0.3f; 5542 ref_sample_rgba[1] = 0.4f; 5543 ref_sample_rgba[2] = 0.5f; 5544 ref_sample_rgba[3] = 0.6f; 5545 } 5546 5547 break; 5548 } 5549 5550 case 1: 5551 { 5552 /* Top segment */ 5553 memcpy(ref_sample_rgba, 5554 ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ + 5555 4 /* second vertex data */, 5556 sizeof(float) * 4 /* components */); 5557 5558 if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) && 5559 ref_triangle_index == 1 /* top-right triangle */) 5560 { 5561 /* Second vertex */ 5562 ref_sample_rgba[0] = 0.4f; 5563 ref_sample_rgba[1] = 0.5f; 5564 ref_sample_rgba[2] = 0.6f; 5565 ref_sample_rgba[3] = 0.7f; 5566 } 5567 break; 5568 } 5569 5570 case 2: 5571 { 5572 /* Right segment */ 5573 memcpy(ref_sample_rgba, 5574 ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ + 5575 8 /* third vertex data */, 5576 sizeof(float) * 4 /* components */); 5577 5578 if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) && 5579 ref_triangle_index == 1 /* top-right triangle */) 5580 { 5581 /* Third vertex */ 5582 ref_sample_rgba[0] = 0.1f; 5583 ref_sample_rgba[1] = 0.2f; 5584 ref_sample_rgba[2] = 0.3f; 5585 ref_sample_rgba[3] = 0.4f; 5586 } 5587 5588 break; 5589 } 5590 5591 case 3: 5592 { 5593 /* Bottom segment */ 5594 ref_sample_rgba[0] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ + 5595 0 /* 1st vertex, red */]; 5596 ref_sample_rgba[1] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ + 5597 5 /* 2nd vertex, green */]; 5598 ref_sample_rgba[2] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ + 5599 10 /* 3rd vertex, blue */]; 5600 ref_sample_rgba[3] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ + 5601 3 /* 1st vertex, alpha */]; 5602 5603 if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) && 5604 ref_triangle_index == 1 /* top-right triangle */) 5605 { 5606 /* Combination of components of three vertices */ 5607 ref_sample_rgba[0] = 0.3f; 5608 ref_sample_rgba[1] = 0.5f; 5609 ref_sample_rgba[2] = 0.3f; 5610 ref_sample_rgba[3] = 0.6f; 5611 } 5612 5613 break; 5614 } 5615 5616 default: 5617 { 5618 TCU_FAIL("Unrecognized line segment index"); 5619 } 5620 } 5621 5622 /* Retrieve quad coordinates */ 5623 float quad_x1y1x2y2[4] = { 0 }; 5624 5625 switch (ref_quarter_index) 5626 { 5627 case 0: 5628 { 5629 /* Top-left quarter */ 5630 quad_x1y1x2y2[0] = 0.0f; 5631 quad_x1y1x2y2[1] = 0.0f; 5632 quad_x1y1x2y2[2] = 0.5f; 5633 quad_x1y1x2y2[3] = 0.5f; 5634 5635 break; 5636 } 5637 5638 case 1: 5639 { 5640 /* Top-right quarter */ 5641 quad_x1y1x2y2[0] = 0.5f; 5642 quad_x1y1x2y2[1] = 0.0f; 5643 quad_x1y1x2y2[2] = 1.0f; 5644 quad_x1y1x2y2[3] = 0.5f; 5645 5646 break; 5647 } 5648 5649 case 2: 5650 { 5651 /* Bottom-right quarter */ 5652 quad_x1y1x2y2[0] = 0.5f; 5653 quad_x1y1x2y2[1] = 0.5f; 5654 quad_x1y1x2y2[2] = 1.0f; 5655 quad_x1y1x2y2[3] = 1.0f; 5656 5657 break; 5658 } 5659 5660 case 3: 5661 { 5662 /* Bottom-left quarter */ 5663 quad_x1y1x2y2[0] = 0.0f; 5664 quad_x1y1x2y2[1] = 0.5f; 5665 quad_x1y1x2y2[2] = 0.5f; 5666 quad_x1y1x2y2[3] = 1.0f; 5667 5668 break; 5669 } 5670 5671 default: 5672 { 5673 TCU_FAIL("Unrecognized quarter index"); 5674 } 5675 } /* switch (ref_quarter_index) */ 5676 5677 /* Reduce quad coordinates to line segment coordinates */ 5678 switch (ref_line_segment_index) 5679 { 5680 case 0: 5681 { 5682 /* Left segment */ 5683 quad_x1y1x2y2[2] = quad_x1y1x2y2[0]; 5684 5685 break; 5686 } 5687 5688 case 1: 5689 { 5690 /* Top segment */ 5691 quad_x1y1x2y2[3] = quad_x1y1x2y2[1]; 5692 5693 break; 5694 } 5695 5696 case 2: 5697 { 5698 /* Right segment */ 5699 quad_x1y1x2y2[0] = quad_x1y1x2y2[2]; 5700 5701 break; 5702 } 5703 5704 case 3: 5705 { 5706 /* Bottom segment */ 5707 quad_x1y1x2y2[1] = quad_x1y1x2y2[3]; 5708 5709 break; 5710 } 5711 5712 default: 5713 { 5714 TCU_FAIL("Unrecognized line segment index"); 5715 } 5716 } 5717 5718 /* Compute sample location. Move one pixel ahead in direction of the bottom-right corner to make 5719 * sure we sample from the center of the line segment. 5720 **/ 5721 ref_sample_xy_float[0] = quad_x1y1x2y2[0] + (quad_x1y1x2y2[2] - quad_x1y1x2y2[0]) * 0.5f; 5722 ref_sample_xy_float[1] = quad_x1y1x2y2[1] + (quad_x1y1x2y2[3] - quad_x1y1x2y2[1]) * 0.5f; 5723 5724 ref_sample_xy_int[0] = int(ref_sample_xy_float[0] * float(single_rt_width - 1)); 5725 ref_sample_xy_int[1] = int(ref_sample_xy_float[1] * float(single_rt_height - 1)); 5726 5727 /* If this is n-th instance, offset sample locations so that they point to rendering results specific 5728 * to instance of our concern */ 5729 ref_sample_xy_int[1] += instance_id * single_rt_height; 5730 5731 /* Compare the rendered data with reference data */ 5732 const int pixel_size = 4 /* components */; 5733 const int row_width = single_rt_width * pixel_size; 5734 const unsigned char* rendered_data_ptr = 5735 data + row_width * ref_sample_xy_int[1] + ref_sample_xy_int[0] * pixel_size; 5736 const float rendered_data[4] = { float(rendered_data_ptr[0]) / 255.0f, float(rendered_data_ptr[1]) / 255.0f, 5737 float(rendered_data_ptr[2]) / 255.0f, 5738 float(rendered_data_ptr[3]) / 255.0f }; 5739 5740 if (de::abs(rendered_data[0] - ref_sample_rgba[0]) > epsilon || 5741 de::abs(rendered_data[1] - ref_sample_rgba[1]) > epsilon || 5742 de::abs(rendered_data[2] - ref_sample_rgba[2]) > epsilon || 5743 de::abs(rendered_data[3] - ref_sample_rgba[3]) > epsilon) 5744 { 5745 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << ref_sample_xy_int[0] << ", " 5746 << ref_sample_xy_int[1] << ") " 5747 << "equal (" << rendered_data[0] << ", " << rendered_data[1] << ", " 5748 << rendered_data[2] << ", " << rendered_data[3] << ") " 5749 << "exceeds allowed epsilon when compared to reference data equal (" 5750 << ref_sample_rgba[0] << ", " << ref_sample_rgba[1] << ", " << ref_sample_rgba[2] 5751 << ", " << ref_sample_rgba[3] << ")." << tcu::TestLog::EndMessage; 5752 5753 TCU_FAIL("Data comparison failed"); 5754 } /* if (data comparison failed) */ 5755 } /* for (all edges) */ 5756 5757 /* All done */ 5758 break; 5759 } 5760 5761 case SHADER_OUTPUT_TYPE_POINTS: 5762 { 5763 /* In this case, the test should have rendered 6 large points. 5764 * Verification checks if centers of these blobs carry valid values. 5765 */ 5766 const float ref_data[] = { 5767 /* Position (<-1, 1> x <-1, 1>) */ 5768 0.0f, -1.0f + float(instance_id) * 2.0f + dy, /* top */ 5769 0.1f, 0.2f, 5770 0.3f, 0.4f, /* rgba */ 5771 5772 0.0f, 0.0f + float(instance_id) * 2.0f, /* middle */ 5773 0.4f, 0.5f, 5774 0.6f, 0.7f, /* rgba */ 5775 5776 -1.0f + dx, 0.0f + float(instance_id) * 2.0f, /* left */ 5777 0.5f, 0.6f, 5778 0.7f, 0.8f, /* rgba */ 5779 5780 1.0f - dx, 0.0f + float(instance_id) * 2.0f, /* right */ 5781 0.2f, 0.3f, 5782 0.4f, 0.5f, /* rgba */ 5783 5784 0.0f, 1.0f + float(instance_id) * 2.0f - dy, /* bottom */ 5785 0.3f, 0.4f, 5786 0.5f, 0.6f, /* rgba */ 5787 }; 5788 const unsigned int n_points = 5; /* total number of points to check */ 5789 5790 for (unsigned int n_point = 0; n_point < n_points; ++n_point) 5791 { 5792 /* Retrieve data from the array */ 5793 tcu::Vec4 color_float = tcu::Vec4(ref_data[n_point * 6 + 2], ref_data[n_point * 6 + 3], 5794 ref_data[n_point * 6 + 4], ref_data[n_point * 6 + 5]); 5795 tcu::Vec2 position_float = tcu::Vec2(ref_data[n_point * 6 + 0], ref_data[n_point * 6 + 1]); 5796 5797 /* Convert position data to texture space */ 5798 int position[] = { int((position_float[0] * 0.5f + 0.5f) * float(single_rt_width)), 5799 int((position_float[1] * 0.5f + 0.5f) * float(single_rt_height)) }; 5800 5801 /* Compare the data */ 5802 const int pixel_size = 4 /* components */; 5803 const int row_width = single_rt_width * pixel_size; 5804 const unsigned char* rendered_data = data + row_width * position[1] + position[0] * pixel_size; 5805 float rendered_data_float[] = { float(rendered_data[0]) / 255.0f, float(rendered_data[1]) / 255.0f, 5806 float(rendered_data[2]) / 255.0f, float(rendered_data[3]) / 255.0f }; 5807 5808 if (de::abs(rendered_data_float[0] - color_float[0]) > epsilon || 5809 de::abs(rendered_data_float[1] - color_float[1]) > epsilon || 5810 de::abs(rendered_data_float[2] - color_float[2]) > epsilon || 5811 de::abs(rendered_data_float[3] - color_float[3]) > epsilon) 5812 { 5813 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << position[0] << ", " 5814 << position[1] << ") " 5815 << "equal (" << rendered_data_float[0] << ", " << rendered_data_float[1] << ", " 5816 << rendered_data_float[2] << ", " << rendered_data_float[3] << ") " 5817 << "exceeds allowed epsilon when compared to reference data equal (" 5818 << color_float[0] << ", " << color_float[1] << ", " << color_float[2] << ", " 5819 << color_float[3] << ")." << tcu::TestLog::EndMessage; 5820 5821 TCU_FAIL("Data comparison failed"); 5822 } 5823 } /* for (all points) */ 5824 5825 break; 5826 } 5827 5828 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: 5829 { 5830 /* The test feeds the rendering pipeline with 4 triangles (per instance), which should 5831 * be converted to 8 differently colored triangles at the geometry shader stage. 5832 */ 5833 for (unsigned int n_triangle = 0; n_triangle < 8 /* triangles */; ++n_triangle) 5834 { 5835 /* Retrieve base triangle-specific properties */ 5836 tcu::Vec2 base_triangle_v1; 5837 tcu::Vec2 base_triangle_v2; 5838 tcu::Vec2 base_triangle_v3; 5839 5840 switch (n_triangle / 2) 5841 /* two sub-triangles per a triangle must be checked */ 5842 { 5843 case 0: 5844 { 5845 /* Top-left triangle */ 5846 base_triangle_v1[0] = 0.5f; 5847 base_triangle_v1[1] = 0.5f; 5848 base_triangle_v2[0] = 0.0f; 5849 base_triangle_v2[1] = 0.5f; 5850 base_triangle_v3[0] = 0.5f; 5851 base_triangle_v3[1] = 0.0f; 5852 5853 break; 5854 } 5855 5856 case 1: 5857 { 5858 /* Top-right triangle */ 5859 base_triangle_v1[0] = 0.5f; 5860 base_triangle_v1[1] = 0.5f; 5861 base_triangle_v2[0] = 0.5f; 5862 base_triangle_v2[1] = 0.0f; 5863 base_triangle_v3[0] = 1.0f; 5864 base_triangle_v3[1] = 0.5f; 5865 5866 break; 5867 } 5868 5869 case 2: 5870 { 5871 /* Bottom-right triangle */ 5872 base_triangle_v1[0] = 0.5f; 5873 base_triangle_v1[1] = 0.5f; 5874 base_triangle_v2[0] = 1.0f; 5875 base_triangle_v2[1] = 0.5f; 5876 base_triangle_v3[0] = 0.5f; 5877 base_triangle_v3[1] = 1.0f; 5878 5879 break; 5880 } 5881 5882 case 3: 5883 { 5884 /* Bottom-left triangle */ 5885 base_triangle_v1[0] = 0.5f; 5886 base_triangle_v1[1] = 0.5f; 5887 base_triangle_v2[0] = 0.0f; 5888 base_triangle_v2[1] = 0.5f; 5889 base_triangle_v3[0] = 0.5f; 5890 base_triangle_v3[1] = 1.0f; 5891 5892 break; 5893 } 5894 } /* switch (n_triangle) */ 5895 5896 /* Compute coordinates of the iteration-specific triangle. This logic has been 5897 * ported directly from the geometry shader */ 5898 tcu::Vec4 expected_sample_color_rgba; 5899 glw::GLuint expected_sample_color_vertex_id = 0; 5900 tcu::Vec2 triangle_vertex1; 5901 tcu::Vec2 triangle_vertex2; 5902 tcu::Vec2 triangle_vertex3; 5903 tcu::Vec2 a = base_triangle_v1; 5904 tcu::Vec2 b; 5905 tcu::Vec2 c; 5906 tcu::Vec2 d; 5907 5908 if (base_triangle_v2.x() == 0.5f && base_triangle_v2.y() == 0.5f) 5909 { 5910 a = base_triangle_v2; 5911 5912 if (de::abs(base_triangle_v1.x() - a.x()) < dx * 0.5f) 5913 { 5914 b = base_triangle_v1; 5915 c = base_triangle_v3; 5916 } 5917 else 5918 { 5919 b = base_triangle_v3; 5920 c = base_triangle_v1; 5921 } 5922 } 5923 else if (base_triangle_v3.x() == 0.5f && base_triangle_v3.y() == 0.5f) 5924 { 5925 a = base_triangle_v3; 5926 5927 if (de::abs(base_triangle_v1.x() - a.x()) < dx * 0.5f) 5928 { 5929 b = base_triangle_v1; 5930 c = base_triangle_v2; 5931 } 5932 else 5933 { 5934 b = base_triangle_v2; 5935 c = base_triangle_v1; 5936 } 5937 } 5938 else 5939 { 5940 if (de::abs(base_triangle_v2.x() - a.x()) < dx * 0.5f) 5941 { 5942 b = base_triangle_v2; 5943 c = base_triangle_v3; 5944 } 5945 else 5946 { 5947 b = base_triangle_v3; 5948 c = base_triangle_v2; 5949 } 5950 } 5951 5952 d = (b + c) * tcu::Vec2(0.5f); 5953 5954 if (n_triangle % 2 == 0) 5955 { 5956 switch (m_drawcall_mode) 5957 { 5958 case GL_TRIANGLES: 5959 case GL_TRIANGLES_ADJACENCY_EXT: 5960 { 5961 /* First sub-triangle */ 5962 expected_sample_color_vertex_id = 3 /* vertices per triangle */ * (n_triangle / 2) + 0; 5963 5964 break; 5965 } /* GL_TRIANGLEs or GL_TRIANGLES_ADJACENCY_EXT cases */ 5966 5967 case GL_TRIANGLE_FAN: 5968 { 5969 /* First sub-triangle in this case is always assigned vertex id of 0, as 0 stands for 5970 * the hub vertex */ 5971 expected_sample_color_vertex_id = 0; 5972 5973 break; 5974 } 5975 5976 case GL_TRIANGLE_STRIP: 5977 case GL_TRIANGLE_STRIP_ADJACENCY_EXT: 5978 { 5979 bool is_adjacency_data_present = (m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT); 5980 5981 /* These vertex ids correspond to index of vertex A which changes between triangle 5982 * orientations, hence the repeated expected vertex ID for cases 4 and 6 */ 5983 switch (n_triangle) 5984 { 5985 /* Top-left triangle, first sub-triangle */ 5986 case 0: 5987 { 5988 expected_sample_color_vertex_id = 0; 5989 5990 break; 5991 } 5992 5993 /* Top-right triangle, first sub-triangle */ 5994 case 2: 5995 { 5996 expected_sample_color_vertex_id = 2 * (is_adjacency_data_present ? 2 : 1); 5997 5998 break; 5999 } 6000 6001 /* Bottom-right triangle, first sub-triangle */ 6002 case 4: 6003 { 6004 expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1); 6005 6006 break; 6007 } 6008 6009 /* Bottom-left triangle, first sub-triangle */ 6010 case 6: 6011 { 6012 expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1); 6013 6014 break; 6015 } 6016 6017 default: 6018 { 6019 TCU_FAIL("Unrecognized triangle index"); 6020 } 6021 } 6022 6023 break; 6024 } 6025 6026 default: 6027 { 6028 TCU_FAIL("Unrecognized draw call mode"); 6029 } 6030 } /* switch (m_drawcall_mode) */ 6031 6032 triangle_vertex1 = a; 6033 triangle_vertex2 = b; 6034 triangle_vertex3 = d; 6035 } /* if (n_triangle % 2 == 0) */ 6036 else 6037 { 6038 /* Second sub-triangle */ 6039 switch (m_drawcall_mode) 6040 { 6041 case GL_TRIANGLES: 6042 case GL_TRIANGLES_ADJACENCY_EXT: 6043 { 6044 expected_sample_color_vertex_id = 3 /* vertices per triangle */ * (n_triangle / 2) + 2; 6045 6046 break; 6047 } 6048 6049 case GL_TRIANGLE_FAN: 6050 { 6051 expected_sample_color_vertex_id = 2 + n_triangle / 2; 6052 6053 break; 6054 } 6055 6056 case GL_TRIANGLE_STRIP: 6057 case GL_TRIANGLE_STRIP_ADJACENCY_EXT: 6058 { 6059 bool is_adjacency_data_present = (m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT); 6060 6061 switch (n_triangle) 6062 { 6063 /* Top-left triangle, second sub-triangle */ 6064 case 1: 6065 { 6066 expected_sample_color_vertex_id = 2 * (is_adjacency_data_present ? 2 : 1); 6067 6068 break; 6069 } 6070 6071 /* Top-right triangle, second sub-triangle */ 6072 case 3: 6073 { 6074 expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1); 6075 6076 break; 6077 } 6078 6079 /* Bottom-right triangle, second sub-triangle */ 6080 case 5: 6081 { 6082 expected_sample_color_vertex_id = 5 * (is_adjacency_data_present ? 2 : 1); 6083 6084 break; 6085 } 6086 6087 /* Bottom-left triangle, second sub-triangle */ 6088 case 7: 6089 { 6090 expected_sample_color_vertex_id = 6 * (is_adjacency_data_present ? 2 : 1); 6091 6092 break; 6093 } 6094 6095 default: 6096 { 6097 TCU_FAIL("Unrecognized triangle index"); 6098 } 6099 } 6100 6101 break; 6102 } 6103 6104 default: 6105 { 6106 TCU_FAIL("UNrecognized draw call mode"); 6107 } 6108 } /* switch (m_drawcall_mode) */ 6109 6110 triangle_vertex1 = a; 6111 triangle_vertex2 = c; 6112 triangle_vertex3 = d; 6113 } 6114 6115 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS || 6116 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED || 6117 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS) 6118 { 6119 switch (m_drawcall_mode) 6120 { 6121 case GL_TRIANGLE_FAN: 6122 case GL_TRIANGLE_STRIP: 6123 case GL_TRIANGLE_STRIP_ADJACENCY_EXT: 6124 case GL_TRIANGLES: 6125 { 6126 expected_sample_color_vertex_id = 6127 (getAmountOfVerticesPerInstance() - 1) - expected_sample_color_vertex_id; 6128 6129 break; 6130 } 6131 6132 case GL_TRIANGLES_ADJACENCY_EXT: 6133 { 6134 /* In adjacency input, every even vertex is used for rendering. */ 6135 expected_sample_color_vertex_id = 6136 (getAmountOfVerticesPerInstance() - 1) - expected_sample_color_vertex_id * 2; 6137 6138 break; 6139 } 6140 6141 default: 6142 { 6143 TCU_FAIL("Unrecognized draw call mode"); 6144 } 6145 } 6146 } 6147 6148 /* Compute sample's reference color - logic as in vertex shader */ 6149 expected_sample_color_rgba[0] = float((expected_sample_color_vertex_id + 1)) / 48.0f; 6150 expected_sample_color_rgba[1] = float((expected_sample_color_vertex_id + 1) % 3) / 2.0f; 6151 expected_sample_color_rgba[2] = float((expected_sample_color_vertex_id + 1) % 4) / 3.0f; 6152 expected_sample_color_rgba[3] = float((expected_sample_color_vertex_id + 1) % 5) / 4.0f; 6153 6154 if (n_triangle % 2 == 1) 6155 { 6156 expected_sample_color_rgba[0] *= 2.0f; 6157 } 6158 6159 /* Compute sample location */ 6160 tcu::Vec2 sample_location; 6161 int sample_location_int[2]; /* X & Y coordinates */ 6162 6163 sample_location = (triangle_vertex1 + triangle_vertex2 + triangle_vertex3) / 3.0f; 6164 sample_location_int[0] = int(sample_location[0] * static_cast<float>(single_rt_width - 1) + 0.5f); 6165 sample_location_int[1] = int(sample_location[1] * static_cast<float>(single_rt_height - 1) + 0.5f) + 6166 instance_id * single_rt_height; 6167 6168 /* Retrieve rendered data */ 6169 const unsigned int pixel_size = 4 /* components */; 6170 const unsigned int row_width = single_rt_width * pixel_size; 6171 const unsigned char* rendered_data = 6172 data + row_width * sample_location_int[1] + sample_location_int[0] * pixel_size; 6173 6174 tcu::Vec4 rendered_data_rgba = 6175 tcu::Vec4(float(rendered_data[0]) / 255.0f, float(rendered_data[1]) / 255.0f, 6176 float(rendered_data[2]) / 255.0f, float(rendered_data[3]) / 255.0f); 6177 6178 /* Compare rendered data with reference color information */ 6179 if (de::abs(rendered_data_rgba[0] - expected_sample_color_rgba[0]) > epsilon || 6180 de::abs(rendered_data_rgba[1] - expected_sample_color_rgba[1]) > epsilon || 6181 de::abs(rendered_data_rgba[2] - expected_sample_color_rgba[2]) > epsilon || 6182 de::abs(rendered_data_rgba[3] - expected_sample_color_rgba[3]) > epsilon) 6183 { 6184 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << sample_location[0] << ", " 6185 << sample_location[1] << ") " 6186 << "equal (" << rendered_data_rgba[0] << ", " << rendered_data_rgba[1] << ", " 6187 << rendered_data_rgba[2] << ", " << rendered_data_rgba[3] << ") " 6188 << "exceeds allowed epsilon when compared to reference data equal (" 6189 << expected_sample_color_rgba[0] << ", " << expected_sample_color_rgba[1] << ", " 6190 << expected_sample_color_rgba[2] << ", " << expected_sample_color_rgba[3] << ")." 6191 << tcu::TestLog::EndMessage; 6192 6193 TCU_FAIL("Data comparison failed"); 6194 } /* if (data comparison failed) */ 6195 } /* for (all triangles) */ 6196 /* All done */ 6197 break; 6198 } 6199 6200 default: 6201 { 6202 TCU_FAIL("Unrecognized output type"); 6203 } 6204 } 6205 } 6206 6207 } // namespace glcts 6208