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 "esextcTessellationShaderTCTE.hpp" 25 #include "esextcTessellationShaderUtils.hpp" 26 #include "gluContextInfo.hpp" 27 #include "gluDefs.hpp" 28 #include "glwEnums.hpp" 29 #include "glwFunctions.hpp" 30 #include "tcuTestLog.hpp" 31 #include <algorithm> 32 33 namespace glcts 34 { 35 /** Constructor 36 * 37 * @param context Test context 38 **/ 39 TessellationShaderTCTETests::TessellationShaderTCTETests(glcts::Context& context, const ExtParameters& extParams) 40 : TestCaseGroupBase(context, extParams, "tessellation_control_to_tessellation_evaluation", 41 "Verifies various aspects of communication between tessellation " 42 "control and tessellation evaluation stages") 43 { 44 /* No implementation needed */ 45 } 46 47 /** 48 * Initializes test groups for geometry shader tests 49 **/ 50 void TessellationShaderTCTETests::init(void) 51 { 52 addChild(new glcts::TessellationShaderTCTEDataPassThrough(m_context, m_extParams)); 53 addChild(new glcts::TessellationShaderTCTEgl_in(m_context, m_extParams)); 54 addChild(new glcts::TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize(m_context, m_extParams)); 55 addChild(new glcts::TessellationShaderTCTEgl_PatchVerticesIn(m_context, m_extParams)); 56 addChild(new glcts::TessellationShaderTCTEgl_TessLevel(m_context, m_extParams)); 57 } 58 59 /** Constructor 60 * 61 * @param context Test context 62 **/ 63 TessellationShaderTCTEDataPassThrough::TessellationShaderTCTEDataPassThrough(Context& context, 64 const ExtParameters& extParams) 65 : TestCaseBase(context, extParams, "data_pass_through", 66 "Verifies data is correctly passed down the VS->TC->TS->(GS) pipeline.") 67 , m_bo_id(0) 68 , m_n_input_vertices_per_run(4) 69 , m_utils_ptr(DE_NULL) 70 , m_vao_id(0) 71 { 72 /* Left blank on purpose */ 73 } 74 75 /** Deinitializes all ES objects created for the test. */ 76 void TessellationShaderTCTEDataPassThrough::deinit() 77 { 78 /** Call base class' deinit() function */ 79 TestCaseBase::deinit(); 80 81 if (!m_is_tessellation_shader_supported) 82 { 83 return; 84 } 85 86 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 87 88 /* Revert GL_PATCH_VERTICES_EXT value to the default setting */ 89 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 90 91 /* Disable GL_RASTERIZER_DISCARD mode */ 92 gl.disable(GL_RASTERIZER_DISCARD); 93 94 /* Revert TF buffer object bindings */ 95 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 96 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 97 98 /* Unbind vertex array object */ 99 gl.bindVertexArray(0); 100 101 /* Release all objects we might've created */ 102 if (m_bo_id != 0) 103 { 104 gl.deleteBuffers(1, &m_bo_id); 105 106 m_bo_id = 0; 107 } 108 109 if (m_vao_id != 0) 110 { 111 gl.deleteVertexArrays(1, &m_vao_id); 112 113 m_vao_id = 0; 114 } 115 116 for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it) 117 { 118 deinitTestRun(*it); 119 } 120 m_runs.clear(); 121 122 /* Release Utils instance */ 123 if (m_utils_ptr != DE_NULL) 124 { 125 delete m_utils_ptr; 126 127 m_utils_ptr = DE_NULL; 128 } 129 } 130 131 /** Deinitializes all ES object created for a specific test run. **/ 132 void TessellationShaderTCTEDataPassThrough::deinitTestRun(_run& run) 133 { 134 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 135 136 if (run.fs_id != 0) 137 { 138 gl.deleteShader(run.fs_id); 139 140 run.fs_id = 0; 141 } 142 143 if (run.gs_id != 0) 144 { 145 gl.deleteShader(run.gs_id); 146 147 run.gs_id = 0; 148 } 149 150 if (run.po_id != 0) 151 { 152 gl.deleteProgram(run.po_id); 153 154 run.po_id = 0; 155 } 156 157 if (run.tcs_id != 0) 158 { 159 gl.deleteShader(run.tcs_id); 160 161 run.tcs_id = 0; 162 } 163 164 if (run.tes_id != 0) 165 { 166 gl.deleteShader(run.tes_id); 167 168 run.tes_id = 0; 169 } 170 171 if (run.vs_id != 0) 172 { 173 gl.deleteShader(run.vs_id); 174 175 run.vs_id = 0; 176 } 177 } 178 179 /** Initializes all ES objects that will be used for the test. */ 180 void TessellationShaderTCTEDataPassThrough::initTest() 181 { 182 /* The test requires EXT_tessellation_shader */ 183 if (!m_is_tessellation_shader_supported) 184 { 185 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 186 } 187 188 /* Create an Utils instance */ 189 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 190 191 m_utils_ptr = new TessellationShaderUtils(gl, this); 192 193 /* Initialize vertex array object */ 194 gl.genVertexArrays(1, &m_vao_id); 195 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 196 197 gl.bindVertexArray(m_vao_id); 198 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 199 200 /* Our program objects take a single vertex per patch */ 201 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1); 202 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed"); 203 204 /* Disable rasterization */ 205 gl.enable(GL_RASTERIZER_DISCARD); 206 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed"); 207 208 /* Create a buffer object we will use for XFB */ 209 gl.genBuffers(1, &m_bo_id); 210 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 211 212 /* Set up XFB buffer object bindings */ 213 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 214 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); 215 216 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 217 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed"); 218 219 /* Prepare all the runs */ 220 const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, 221 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 222 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 223 const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 224 225 /* Iterate over all supported primitive modes */ 226 for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 227 { 228 _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 229 230 /* If geometry shaders are supported, include a separate iteration to include them 231 * in the pipeline 232 */ 233 for (int n_gs_stage_usage = 0; n_gs_stage_usage < ((m_is_geometry_shader_extension_supported) ? 2 : 1); 234 ++n_gs_stage_usage) 235 { 236 bool use_gs_stage = (n_gs_stage_usage == 1); 237 238 /* If geometry shaders support gl_PointSize, include a separate iteration to pass 239 * point size data as well */ 240 for (int n_gs_pointsize_usage = 0; 241 n_gs_pointsize_usage < ((m_is_geometry_shader_point_size_supported) ? 2 : 1); ++n_gs_pointsize_usage) 242 { 243 bool use_gs_pointsize_data = (n_gs_pointsize_usage == 1); 244 245 /* If tessellation shaders support gl_PointSize, include a separate iteration to pass 246 * point size data as well */ 247 for (int n_ts_pointsize_usage = 0; 248 n_ts_pointsize_usage < ((m_is_tessellation_shader_point_size_supported) ? 2 : 1); 249 ++n_ts_pointsize_usage) 250 { 251 bool use_ts_pointsize_data = (n_ts_pointsize_usage == 1); 252 253 /* Note: it does not make sense to try to pass gl_PointSize data 254 * in geometry stage if tessellation stage did not provide it. 255 */ 256 if (!use_ts_pointsize_data && use_gs_pointsize_data) 257 { 258 continue; 259 } 260 261 /* Initialize test run data */ 262 _run run; 263 264 executeTestRun(run, primitive_mode, use_gs_stage, use_gs_pointsize_data, use_ts_pointsize_data); 265 266 /* Store the run for later usage */ 267 m_runs.push_back(run); 268 } /* for (tessellation point size data usage off and on cases) */ 269 } /* for (geometry point size data usage off and on cases) */ 270 } /* for (GS stage usage) */ 271 } /* for (all primitive modes) */ 272 } 273 274 /** Initializes a test run, executes it and gathers all the rendered data for further 275 * processing. Extracted data is stored in the run descriptor. 276 * 277 * @param run Test run descriptor to fill with ES object data, 278 * as well as generated data. 279 * @param primitive_mode Primitive mode to use for the test run. 280 * @param should_use_geometry_shader true if the test run should use Geometry Shader stage, 281 * false otherwise. 282 * @param should_pass_point_size_data_in_gs true if the test run should define two output variables 283 * in Geometry Shader, later set to gl_PointSize values from 284 * TC and TE stages. False to skip them. 285 * Only set to true if GL_EXT_geometry_point_size extension 286 * is supported. 287 * @param should_pass_point_size_data_in_ts true if the test run should define two output variables 288 * in both Tessellation Shader types, set to gl_PointSize values 289 * as accessible during execution. False to skip the definitions. 290 * Only set to true if GL_EXT_tessellation_point_size extension 291 * is supported. 292 */ 293 void TessellationShaderTCTEDataPassThrough::executeTestRun(_run& run, _tessellation_primitive_mode primitive_mode, 294 bool should_use_geometry_shader, 295 bool should_pass_point_size_data_in_gs, 296 bool should_pass_point_size_data_in_ts) 297 { 298 run.primitive_mode = primitive_mode; 299 300 /* Retrieve ES entry-points before we start */ 301 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 302 303 /* Create a program object first */ 304 run.po_id = gl.createProgram(); 305 306 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 307 308 /* Create all shader objects we wil be later attaching to the program object */ 309 run.fs_id = gl.createShader(GL_FRAGMENT_SHADER); 310 run.tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 311 run.tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 312 run.vs_id = gl.createShader(GL_VERTEX_SHADER); 313 314 if (should_use_geometry_shader) 315 { 316 run.gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 317 } 318 319 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed"); 320 321 /* Attach the shader objects to the program object */ 322 gl.attachShader(run.po_id, run.fs_id); 323 gl.attachShader(run.po_id, run.tcs_id); 324 gl.attachShader(run.po_id, run.tes_id); 325 gl.attachShader(run.po_id, run.vs_id); 326 327 if (should_use_geometry_shader) 328 { 329 gl.attachShader(run.po_id, run.gs_id); 330 } 331 332 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed"); 333 334 /* Set vertex shader's body */ 335 const char* vs_body = "${VERSION}\n" 336 "\n" 337 "${SHADER_IO_BLOCKS_REQUIRE}\n" 338 "\n" 339 "out OUT_VS\n" 340 "{\n" 341 " vec4 value1;\n" 342 " ivec4 value2;\n" 343 "} out_data;\n" 344 "\n" 345 "void main()\n" 346 "{\n" 347 " gl_Position = vec4( float(gl_VertexID) );\n" 348 " gl_PointSize = 1.0 / float(gl_VertexID + 1);\n" 349 " out_data.value1 = vec4(float(gl_VertexID), float(gl_VertexID) * 0.5,\n" 350 " float(gl_VertexID) * 0.25, float(gl_VertexID) * 0.125);\n" 351 " out_data.value2 = ivec4(gl_VertexID, gl_VertexID + 1,\n" 352 " gl_VertexID + 2, gl_VertexID + 3);\n" 353 "}\n"; 354 355 shaderSourceSpecialized(run.vs_id, 1 /* count */, &vs_body); 356 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for vertex shader"); 357 358 /* Set dummy fragment shader's body */ 359 const char* fs_body = "${VERSION}\n" 360 "\n" 361 "void main()\n" 362 "{\n" 363 "}\n"; 364 365 shaderSourceSpecialized(run.fs_id, 1 /* count */, &fs_body); 366 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for fragment shader"); 367 368 /* Set tessellation control shader's body */ 369 { 370 std::stringstream body_sstream; 371 std::string body_string; 372 const char* body_raw_ptr = DE_NULL; 373 374 body_sstream << "${VERSION}\n" 375 "\n" 376 "${TESSELLATION_SHADER_REQUIRE}\n"; 377 378 if (should_pass_point_size_data_in_ts) 379 { 380 body_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n"; 381 } 382 383 body_sstream << "\n" 384 "layout(vertices = 2) out;\n" 385 "\n" 386 "in OUT_VS\n" 387 "{\n" 388 " vec4 value1;\n" 389 " ivec4 value2;\n" 390 "} in_vs_data[];\n" 391 "\n" 392 "out OUT_TC\n" 393 "{\n"; 394 395 if (should_pass_point_size_data_in_ts) 396 { 397 body_sstream << " float tc_pointSize;\n"; 398 } 399 400 body_sstream << " vec4 tc_position;\n" 401 " vec4 tc_value1;\n" 402 " ivec4 tc_value2;\n" 403 "} out_data[];\n" 404 "\n" 405 "patch out vec4 tc_patch_data;\n" 406 "\n" 407 "void main()\n" 408 "{\n" 409 " int multiplier = 1;\n" 410 "\n" 411 " if (gl_InvocationID == 0)\n" 412 " {\n" 413 " multiplier = 2;\n" 414 " }\n"; 415 416 if (should_pass_point_size_data_in_ts) 417 { 418 body_sstream << " out_data [gl_InvocationID].tc_pointSize = gl_in[0].gl_PointSize;\n" 419 " gl_out [gl_InvocationID].gl_PointSize = gl_in[0].gl_PointSize * 2.0;\n"; 420 } 421 422 body_sstream << " out_data [gl_InvocationID].tc_position = gl_in [0].gl_Position;\n" 423 " out_data [gl_InvocationID].tc_value1 = in_vs_data[0].value1 * " 424 "vec4(float(multiplier) );\n" 425 " out_data [gl_InvocationID].tc_value2 = in_vs_data[0].value2 * ivec4( " 426 "multiplier);\n" 427 " gl_out [gl_InvocationID].gl_Position = gl_in [0].gl_Position + vec4(3.0);\n" 428 " gl_TessLevelInner[0] = 4.0;\n" 429 " gl_TessLevelInner[1] = 4.0;\n" 430 " gl_TessLevelOuter[0] = 4.0;\n" 431 " gl_TessLevelOuter[1] = 4.0;\n" 432 " gl_TessLevelOuter[2] = 4.0;\n" 433 " gl_TessLevelOuter[3] = 4.0;\n" 434 "\n" 435 " if (gl_InvocationID == 0)\n" 436 " {\n" 437 " tc_patch_data = in_vs_data[0].value1 * vec4(float(multiplier) );\n" 438 " }\n" 439 "}\n"; 440 441 body_string = body_sstream.str(); 442 body_raw_ptr = body_string.c_str(); 443 444 shaderSourceSpecialized(run.tcs_id, 1 /* count */, &body_raw_ptr); 445 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation control shader"); 446 } 447 448 /* Set tessellation evaluation shader's body */ 449 { 450 std::stringstream body_sstream; 451 std::string body_string; 452 const char* body_raw_ptr = DE_NULL; 453 454 /* Preamble */ 455 body_sstream << "${VERSION}\n" 456 "\n" 457 "${TESSELLATION_SHADER_REQUIRE}\n"; 458 459 if (should_pass_point_size_data_in_ts) 460 { 461 body_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n"; 462 } 463 464 /* Layout qualifiers */ 465 body_sstream << "\n" 466 "layout(PRIMITIVE_MODE, point_mode) in;\n" 467 "\n" 468 469 /* Input block definition starts here: */ 470 "in OUT_TC\n" 471 "{\n"; 472 473 if (should_pass_point_size_data_in_ts) 474 { 475 body_sstream << " float tc_pointSize;\n"; 476 } 477 478 body_sstream << " vec4 tc_position;\n" 479 " vec4 tc_value1;\n" 480 " ivec4 tc_value2;\n" 481 "} in_data[];\n" 482 "\n" 483 "patch in vec4 tc_patch_data;\n" 484 "\n"; 485 /* Input block definition ends here. */ 486 487 /* Output block definition (only defined if GS stage is present) starts here: */ 488 if (should_use_geometry_shader) 489 { 490 body_sstream << "out OUT_TE\n" 491 "{\n"; 492 493 /* Output block contents */ 494 if (should_pass_point_size_data_in_ts) 495 { 496 body_sstream << " float tc_pointSize;\n" 497 " float te_pointSize;\n"; 498 } 499 500 body_sstream << " vec4 tc_position;\n" 501 " vec4 tc_value1;\n" 502 " ivec4 tc_value2;\n" 503 " vec4 te_position;\n" 504 "} out_data;\n"; 505 } 506 /* Output block definition ends here. */ 507 else 508 { 509 if (should_pass_point_size_data_in_ts) 510 { 511 body_sstream << "out float tc_pointSize;\n" 512 "out float te_pointSize;\n"; 513 } 514 515 body_sstream << "out vec4 tc_position;\n" 516 "out vec4 tc_value1;\n" 517 "flat out ivec4 tc_value2;\n" 518 "out vec4 te_position;\n" 519 "out vec4 te_patch_data;\n"; 520 } 521 522 body_sstream << "\n" 523 "void main()\n" 524 "{\n"; 525 526 if (should_use_geometry_shader) 527 { 528 body_sstream << "#define OUTPUT_VARIABLE(x) out_data.x\n"; 529 } 530 else 531 { 532 body_sstream << "#define OUTPUT_VARIABLE(x) x\n"; 533 } 534 535 if (should_pass_point_size_data_in_ts) 536 { 537 body_sstream << " OUTPUT_VARIABLE(tc_pointSize) = in_data[1].tc_pointSize;\n" 538 " OUTPUT_VARIABLE(te_pointSize) = gl_in[1].gl_PointSize;\n"; 539 } 540 541 body_sstream << " OUTPUT_VARIABLE(tc_position) = in_data[1].tc_position;\n" 542 " OUTPUT_VARIABLE(tc_value1) = in_data[0].tc_value1;\n" 543 " OUTPUT_VARIABLE(tc_value2) = in_data[1].tc_value2;\n" 544 " OUTPUT_VARIABLE(te_position) = gl_in[0].gl_Position;\n"; 545 546 if (!should_use_geometry_shader) 547 { 548 body_sstream << " OUTPUT_VARIABLE(te_patch_data) = tc_patch_data;\n"; 549 } 550 body_sstream << "}\n"; 551 552 body_string = body_sstream.str(); 553 554 /* Replace PRIMITIVE_MODE token with user-requested primitive mode */ 555 std::string primitive_mode_replacement = TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode); 556 std::string primitive_mode_token = "PRIMITIVE_MODE"; 557 std::size_t primitive_mode_token_position = std::string::npos; 558 559 primitive_mode_token_position = body_string.find(primitive_mode_token); 560 561 while (primitive_mode_token_position != std::string::npos) 562 { 563 body_string = body_string.replace(primitive_mode_token_position, primitive_mode_token.length(), 564 primitive_mode_replacement); 565 566 primitive_mode_token_position = body_string.find(primitive_mode_token); 567 } 568 569 body_raw_ptr = body_string.c_str(); 570 571 shaderSourceSpecialized(run.tes_id, 1 /* count */, &body_raw_ptr); 572 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation evaluation shader"); 573 } 574 575 /* Set geometry shader's body (if requested) */ 576 if (should_use_geometry_shader) 577 { 578 std::stringstream body_sstream; 579 std::string body_string; 580 const char* body_raw_ptr = DE_NULL; 581 582 body_sstream << "${VERSION}\n" 583 "\n" 584 "${GEOMETRY_SHADER_REQUIRE}\n"; 585 586 if (should_pass_point_size_data_in_gs) 587 { 588 body_sstream << "${GEOMETRY_POINT_SIZE_REQUIRE}\n"; 589 } 590 591 body_sstream << "${SHADER_IO_BLOCKS_REQUIRE}\n" 592 "\n" 593 "layout(points) in;\n" 594 "layout(max_vertices = 2, points) out;\n" 595 "\n" 596 "in OUT_TE\n" 597 "{\n"; 598 599 if (should_pass_point_size_data_in_ts) 600 { 601 body_sstream << " float tc_pointSize;\n" 602 " float te_pointSize;\n"; 603 } 604 605 body_sstream << " vec4 tc_position;\n" 606 " vec4 tc_value1;\n" 607 " ivec4 tc_value2;\n" 608 " vec4 te_position;\n" 609 "} in_data[1];\n" 610 "\n" 611 "out float gs_tc_pointSize;\n" 612 "out float gs_te_pointSize;\n" 613 "out vec4 gs_tc_position;\n" 614 "out vec4 gs_tc_value1;\n" 615 "flat out ivec4 gs_tc_value2;\n" 616 "out vec4 gs_te_position;\n" 617 "\n" 618 "void main()\n" 619 "{\n"; 620 621 if (should_pass_point_size_data_in_gs) 622 { 623 body_sstream << " gs_tc_pointSize = in_data[0].tc_pointSize;\n" 624 " gs_te_pointSize = in_data[0].te_pointSize;\n"; 625 } 626 627 body_sstream << " gs_tc_position = in_data[0].tc_position;\n" 628 " gs_tc_value1 = in_data[0].tc_value1;\n" 629 " gs_tc_value2 = in_data[0].tc_value2;\n" 630 " gs_te_position = in_data[0].te_position;\n" 631 " EmitVertex();\n"; 632 633 if (should_pass_point_size_data_in_gs) 634 { 635 body_sstream << " gs_tc_pointSize = in_data[0].tc_pointSize + 1.0;\n" 636 " gs_te_pointSize = in_data[0].te_pointSize + 1.0;\n"; 637 } 638 639 body_sstream << " gs_tc_position = in_data[0].tc_position + vec4(1.0);\n" 640 " gs_tc_value1 = in_data[0].tc_value1 + vec4(1.0);\n" 641 " gs_tc_value2 = in_data[0].tc_value2 + ivec4(1);\n" 642 " gs_te_position = in_data[0].te_position + vec4(1.0);\n" 643 "\n" 644 " EmitVertex();\n" 645 "\n" 646 "}\n"; 647 648 body_string = body_sstream.str(); 649 body_raw_ptr = body_string.c_str(); 650 651 shaderSourceSpecialized(run.gs_id, 1 /* count */, &body_raw_ptr); 652 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for geometry shader"); 653 } 654 655 /* Configure varyings */ 656 unsigned int n_varyings = 0; 657 int varying_tc_pointSize_offset = -1; 658 int varying_tc_position_offset = -1; 659 int varying_tc_value1_offset = -1; 660 int varying_tc_value2_offset = -1; 661 int varying_te_patch_data_offset = -1; 662 int varying_te_pointSize_offset = -1; 663 int varying_te_position_offset = -1; 664 const unsigned int varying_patch_data_size = sizeof(float) * 4; /* vec4 */ 665 const unsigned int varying_pointSize_size = sizeof(float); 666 const unsigned int varying_position_size = sizeof(float) * 4; /* vec4 */ 667 const unsigned int varying_value1_size = sizeof(float) * 4; /* vec4 */ 668 const unsigned int varying_value2_size = sizeof(int) * 4; /* ivec4 */ 669 const char** varyings = DE_NULL; 670 unsigned int varyings_size = 0; 671 672 const char* gs_non_point_size_varyings[] = { "gs_tc_position", "gs_tc_value1", "gs_tc_value2", "gs_te_position" }; 673 const char* gs_point_size_varyings[] = { "gs_tc_position", "gs_tc_value1", "gs_tc_value2", 674 "gs_te_position", "gs_tc_pointSize", "gs_te_pointSize" }; 675 const char* non_gs_non_point_size_varyings[] = { "tc_position", "tc_value1", "tc_value2", "te_position", 676 "te_patch_data" }; 677 const char* non_gs_point_size_varyings[] = { "tc_position", "tc_value1", "tc_value2", "te_position", 678 "tc_pointSize", "te_pointSize", "te_patch_data" }; 679 680 if (should_use_geometry_shader) 681 { 682 if (should_pass_point_size_data_in_gs) 683 { 684 n_varyings = sizeof(gs_point_size_varyings) / sizeof(gs_point_size_varyings[0]); 685 varyings = gs_point_size_varyings; 686 varyings_size = varying_position_size + /* gs_tc_position */ 687 varying_value1_size + /* gs_tc_value1 */ 688 varying_value2_size + /* gs_tc_value2 */ 689 varying_position_size + /* gs_te_position */ 690 varying_pointSize_size + /* gs_tc_pointSize */ 691 varying_pointSize_size; /* gs_te_pointSize */ 692 693 varying_tc_position_offset = 0; 694 varying_tc_value1_offset = varying_tc_position_offset + varying_position_size; 695 varying_tc_value2_offset = varying_tc_value1_offset + varying_value1_size; 696 varying_te_position_offset = varying_tc_value2_offset + varying_value2_size; 697 varying_tc_pointSize_offset = varying_te_position_offset + varying_position_size; 698 varying_te_pointSize_offset = varying_tc_pointSize_offset + varying_pointSize_size; 699 } 700 else 701 { 702 n_varyings = sizeof(gs_non_point_size_varyings) / sizeof(gs_non_point_size_varyings[0]); 703 varyings = gs_non_point_size_varyings; 704 varyings_size = varying_position_size + /* gs_tc_position */ 705 varying_value1_size + /* gs_tc_value1 */ 706 varying_value2_size + /* gs_tc_value2 */ 707 varying_position_size; /* gs_te_position */ 708 709 varying_tc_position_offset = 0; 710 varying_tc_value1_offset = varying_tc_position_offset + varying_position_size; 711 varying_tc_value2_offset = varying_tc_value1_offset + varying_value1_size; 712 varying_te_position_offset = varying_tc_value2_offset + varying_value2_size; 713 } 714 } /* if (should_use_geometry_shader) */ 715 else 716 { 717 if (should_pass_point_size_data_in_ts) 718 { 719 n_varyings = sizeof(non_gs_point_size_varyings) / sizeof(non_gs_point_size_varyings[0]); 720 varyings = non_gs_point_size_varyings; 721 varyings_size = varying_position_size + /* tc_position */ 722 varying_value1_size + /* tc_value1 */ 723 varying_value2_size + /* tc_value2 */ 724 varying_position_size + /* te_position */ 725 varying_pointSize_size + /* tc_pointSize */ 726 varying_pointSize_size + /* te_pointSize */ 727 varying_patch_data_size; /* tc_patch_data */ 728 729 varying_tc_position_offset = 0; 730 varying_tc_value1_offset = varying_tc_position_offset + varying_position_size; 731 varying_tc_value2_offset = varying_tc_value1_offset + varying_value1_size; 732 varying_te_position_offset = varying_tc_value2_offset + varying_value2_size; 733 varying_tc_pointSize_offset = varying_te_position_offset + varying_position_size; 734 varying_te_pointSize_offset = varying_tc_pointSize_offset + varying_pointSize_size; 735 varying_te_patch_data_offset = varying_te_pointSize_offset + varying_pointSize_size; 736 } 737 else 738 { 739 n_varyings = sizeof(non_gs_non_point_size_varyings) / sizeof(non_gs_non_point_size_varyings[0]); 740 varyings = non_gs_non_point_size_varyings; 741 varyings_size = varying_position_size + /* tc_position */ 742 varying_value1_size + /* tc_value1 */ 743 varying_value2_size + /* tc_value2 */ 744 varying_position_size + /* te_position */ 745 varying_patch_data_size; /* tc_patch_data */ 746 747 varying_tc_position_offset = 0; 748 varying_tc_value1_offset = varying_tc_position_offset + varying_position_size; 749 varying_tc_value2_offset = varying_tc_value1_offset + varying_value1_size; 750 varying_te_position_offset = varying_tc_value2_offset + varying_value2_size; 751 varying_te_patch_data_offset = varying_te_position_offset + varying_position_size; 752 } 753 } 754 755 gl.transformFeedbackVaryings(run.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS); 756 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed"); 757 758 /* Compile all the shader objects */ 759 const glw::GLuint shaders[] = { run.fs_id, run.gs_id, run.tcs_id, run.tes_id, run.vs_id }; 760 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 761 762 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 763 { 764 glw::GLuint shader = shaders[n_shader]; 765 766 if (shader != 0) 767 { 768 m_utils_ptr->compileShaders(1 /* n_shaders */, &shader, true); 769 } 770 } 771 772 /* Link the program object */ 773 gl.linkProgram(run.po_id); 774 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed"); 775 776 /* Make sure the linking has succeeded */ 777 glw::GLint link_status = GL_FALSE; 778 779 gl.getProgramiv(run.po_id, GL_LINK_STATUS, &link_status); 780 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed"); 781 782 if (link_status != GL_TRUE) 783 { 784 TCU_FAIL("Program linking failed"); 785 } 786 787 /* Now that we have a linked program object, it's time to determine how much space 788 * we will need to hold XFB data. 789 */ 790 unsigned int bo_size = 0; 791 unsigned int n_result_tess_coords = 0; 792 const float tess_levels[] = /* as per shaders constructed by the test */ 793 { 4.0f, 4.0f, 4.0f, 4.0f }; 794 795 n_result_tess_coords = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 796 run.primitive_mode, tess_levels, tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 797 true); /* is_point_mode_enabled */ 798 799 if (should_use_geometry_shader) 800 { 801 /* Geometry shader will output twice as many vertices */ 802 n_result_tess_coords *= 2; 803 } 804 805 run.n_result_vertices_per_patch = n_result_tess_coords; 806 n_result_tess_coords *= m_n_input_vertices_per_run; 807 bo_size = n_result_tess_coords * varyings_size; 808 809 /* Proceed with buffer object storage allocation */ 810 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, /* data */ 811 GL_STATIC_DRAW); 812 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed"); 813 814 /* Great, time to actually render the data! */ 815 glw::GLenum tf_mode = 816 TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, true); /* is_point_mode_enabled */ 817 818 gl.useProgram(run.po_id); 819 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed"); 820 821 gl.beginTransformFeedback(tf_mode); 822 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed"); 823 { 824 gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, m_n_input_vertices_per_run); 825 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 826 } 827 gl.endTransformFeedback(); 828 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed"); 829 830 /* The data should have landed in the buffer object storage by now. Map the BO into 831 * process space. */ 832 const void* bo_ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 833 bo_size, GL_MAP_READ_BIT); 834 835 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed"); 836 837 /* Extract varyings' data */ 838 for (unsigned int n_tess_coord = 0; n_tess_coord < n_result_tess_coords; ++n_tess_coord) 839 { 840 const char* data = (const char*)bo_ptr + n_tess_coord * varyings_size; 841 842 if (varying_tc_position_offset != -1) 843 { 844 const float* position_data((const float*)(data + varying_tc_position_offset)); 845 _vec4 new_entry(position_data[0], position_data[1], position_data[2], position_data[3]); 846 847 run.result_tc_position_data.push_back(new_entry); 848 } 849 850 if (varying_tc_value1_offset != -1) 851 { 852 const float* value1_data((const float*)(data + varying_tc_value1_offset)); 853 _vec4 new_entry(value1_data[0], value1_data[1], value1_data[2], value1_data[3]); 854 855 run.result_tc_value1_data.push_back(new_entry); 856 } 857 858 if (varying_tc_value2_offset != -1) 859 { 860 const int* value2_data((const int*)(data + varying_tc_value2_offset)); 861 _ivec4 new_entry(value2_data[0], value2_data[1], value2_data[2], value2_data[3]); 862 863 run.result_tc_value2_data.push_back(new_entry); 864 } 865 866 if (varying_te_position_offset != -1) 867 { 868 const float* position_data((const float*)(data + varying_te_position_offset)); 869 _vec4 new_entry(position_data[0], position_data[1], position_data[2], position_data[3]); 870 871 run.result_te_position_data.push_back(new_entry); 872 } 873 874 if (varying_tc_pointSize_offset != -1) 875 { 876 const float* pointSize_ptr((const float*)(data + varying_tc_pointSize_offset)); 877 878 run.result_tc_pointSize_data.push_back(*pointSize_ptr); 879 } 880 881 if (varying_te_pointSize_offset != -1) 882 { 883 const float* pointSize_ptr((const float*)(data + varying_te_pointSize_offset)); 884 885 run.result_te_pointSize_data.push_back(*pointSize_ptr); 886 } 887 888 if (varying_te_patch_data_offset != -1) 889 { 890 const float* patch_data_ptr((const float*)(data + varying_te_patch_data_offset)); 891 _vec4 new_entry(patch_data_ptr[0], patch_data_ptr[1], patch_data_ptr[2], patch_data_ptr[3]); 892 893 run.result_te_patch_data.push_back(new_entry); 894 } 895 } /* for (all XFB data associated with tessellated coordinates) */ 896 897 /* Now that we're done extracting the data we need, we're fine to unmap the buffer object */ 898 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 899 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed"); 900 } 901 902 /** Executes the test. 903 * 904 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 905 * 906 * Note the function throws exception should an error occur! 907 * 908 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 909 **/ 910 tcu::TestNode::IterateResult TessellationShaderTCTEDataPassThrough::iterate(void) 911 { 912 const float epsilon = 1e-5f; 913 914 /* Initialize ES test objects */ 915 initTest(); 916 917 /* Iterate over all runs */ 918 for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); ++run_iterator) 919 { 920 const _run& run = *run_iterator; 921 922 /* Check result tc_pointSize data if available */ 923 unsigned int n_vertex = 0; 924 925 for (std::vector<glw::GLfloat>::const_iterator data_iterator = run.result_tc_pointSize_data.begin(); 926 data_iterator != run.result_tc_pointSize_data.end(); data_iterator++, n_vertex++) 927 { 928 const glw::GLfloat data = *data_iterator; 929 unsigned int vertex_id = n_vertex / run.n_result_vertices_per_patch; 930 float expected_value = 1.0f / (float(vertex_id) + 1.0f); 931 932 if (run.gs_id != 0 && (n_vertex % 2) != 0) 933 { 934 /* Odd vertices emitted by geometry shader add 1 to all components */ 935 expected_value += 1.0f; 936 } 937 938 if (de::abs(data - expected_value) > epsilon) 939 { 940 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_pointSize value found at index [" << n_vertex 941 << "];" 942 " expected:[" 943 << expected_value << "], " 944 " found:[" 945 << data << "]." << tcu::TestLog::EndMessage; 946 947 TCU_FAIL("Invalid tc_pointSize value found"); 948 } 949 } 950 951 /* Check result tc_position data if available */ 952 n_vertex -= n_vertex; 953 954 for (std::vector<_vec4>::const_iterator data_iterator = run.result_tc_position_data.begin(); 955 data_iterator != run.result_tc_position_data.end(); data_iterator++, n_vertex++) 956 { 957 const _vec4& data = *data_iterator; 958 float expected_value = (float)(n_vertex / run.n_result_vertices_per_patch); 959 960 if (run.gs_id != 0 && (n_vertex % 2) != 0) 961 { 962 /* Odd vertices emitted by geometry shader add 1 to all components */ 963 expected_value += 1.0f; 964 } 965 966 if (de::abs(data.x - expected_value) > epsilon || de::abs(data.y - expected_value) > epsilon || 967 de::abs(data.z - expected_value) > epsilon || de::abs(data.w - expected_value) > epsilon) 968 { 969 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_position value found at index [" << n_vertex 970 << "];" 971 " expected:" 972 " [" 973 << expected_value << ", " << expected_value << ", " << expected_value << ", " 974 << expected_value << "], found:" 975 " [" 976 << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]." 977 << tcu::TestLog::EndMessage; 978 979 TCU_FAIL("Invalid tc_position value found"); 980 } 981 } 982 983 /* Check result tc_value1 data if available */ 984 n_vertex -= n_vertex; 985 986 for (std::vector<_vec4>::const_iterator data_iterator = run.result_tc_value1_data.begin(); 987 data_iterator != run.result_tc_value1_data.end(); data_iterator++, n_vertex++) 988 { 989 const _vec4& data = *data_iterator; 990 unsigned int vertex_id = n_vertex / run.n_result_vertices_per_patch; 991 _vec4 expected_value = _vec4((float)vertex_id, ((float)vertex_id) * 0.5f, ((float)vertex_id) * 0.25f, 992 ((float)vertex_id) * 0.125f); 993 994 /* TE uses an even vertex outputted by TC, so we need 995 * to multiply the expected value by 2. 996 */ 997 expected_value.x *= 2.0f; 998 expected_value.y *= 2.0f; 999 expected_value.z *= 2.0f; 1000 expected_value.w *= 2.0f; 1001 1002 if (run.gs_id != 0 && (n_vertex % 2) != 0) 1003 { 1004 /* Odd vertices emitted by geometry shader add 1 to all components */ 1005 expected_value.x += 1.0f; 1006 expected_value.y += 1.0f; 1007 expected_value.z += 1.0f; 1008 expected_value.w += 1.0f; 1009 } 1010 1011 if (de::abs(data.x - expected_value.x) > epsilon || de::abs(data.y - expected_value.y) > epsilon || 1012 de::abs(data.z - expected_value.z) > epsilon || de::abs(data.w - expected_value.w) > epsilon) 1013 { 1014 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_value1 value found at index [" << n_vertex 1015 << "];" 1016 " expected:" 1017 " [" 1018 << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", " 1019 << expected_value.w << "], found:" 1020 " [" 1021 << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]." 1022 << tcu::TestLog::EndMessage; 1023 1024 TCU_FAIL("Invalid tc_value1 value found"); 1025 } 1026 } 1027 1028 /* Check result tc_value2 data if available */ 1029 n_vertex -= n_vertex; 1030 1031 for (std::vector<_ivec4>::const_iterator data_iterator = run.result_tc_value2_data.begin(); 1032 data_iterator != run.result_tc_value2_data.end(); data_iterator++, n_vertex++) 1033 { 1034 const _ivec4& data = *data_iterator; 1035 unsigned int vertex_id = n_vertex / run.n_result_vertices_per_patch; 1036 _ivec4 expected_value = _ivec4(vertex_id, vertex_id + 1, vertex_id + 2, vertex_id + 3); 1037 1038 if (run.gs_id != 0 && (n_vertex % 2) != 0) 1039 { 1040 /* Odd vertices emitted by geometry shader add 1 to all components */ 1041 expected_value.x++; 1042 expected_value.y++; 1043 expected_value.z++; 1044 expected_value.w++; 1045 } 1046 1047 if (data.x != expected_value.x || data.y != expected_value.y || data.z != expected_value.z || 1048 data.w != expected_value.w) 1049 { 1050 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_value2 value found at index [" << n_vertex 1051 << "];" 1052 " expected:" 1053 " [" 1054 << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", " 1055 << expected_value.w << "], found:" 1056 " [" 1057 << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]." 1058 << tcu::TestLog::EndMessage; 1059 1060 TCU_FAIL("Invalid tc_value2 value found"); 1061 } 1062 } 1063 1064 /* Check result te_pointSize data if available */ 1065 n_vertex -= n_vertex; 1066 1067 for (std::vector<glw::GLfloat>::const_iterator data_iterator = run.result_te_pointSize_data.begin(); 1068 data_iterator != run.result_te_pointSize_data.end(); data_iterator++, n_vertex++) 1069 { 1070 const glw::GLfloat data = *data_iterator; 1071 unsigned int vertex_id = n_vertex / run.n_result_vertices_per_patch; 1072 float expected_value = 2.0f / (float(vertex_id) + 1.0f); 1073 1074 if (run.gs_id != 0 && (n_vertex % 2) != 0) 1075 { 1076 /* Odd vertices emitted by geometry shader add 1 to all components */ 1077 expected_value += 1.0f; 1078 } 1079 1080 if (de::abs(data - expected_value) > epsilon) 1081 { 1082 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid te_pointSize value found at index [" << n_vertex 1083 << "];" 1084 " expected:[" 1085 << expected_value << "], " 1086 " found:[" 1087 << data << "]." << tcu::TestLog::EndMessage; 1088 1089 TCU_FAIL("Invalid te_pointSize value found"); 1090 } 1091 } 1092 1093 /* Check result te_position data if available */ 1094 n_vertex -= n_vertex; 1095 1096 for (std::vector<_vec4>::const_iterator data_iterator = run.result_te_position_data.begin(); 1097 data_iterator != run.result_te_position_data.end(); data_iterator++, n_vertex++) 1098 { 1099 const _vec4& data = *data_iterator; 1100 float expected_value = (float)(n_vertex / run.n_result_vertices_per_patch); 1101 1102 /* te_position should be equal to tc_position, with 3 added to all components */ 1103 expected_value += 3.0f; 1104 1105 if (run.gs_id != 0 && (n_vertex % 2) != 0) 1106 { 1107 /* Odd vertices emitted by geometry shader add 1 to all components */ 1108 expected_value += 1.0f; 1109 } 1110 1111 if (de::abs(data.x - expected_value) > epsilon || de::abs(data.y - expected_value) > epsilon || 1112 de::abs(data.z - expected_value) > epsilon || de::abs(data.w - expected_value) > epsilon) 1113 { 1114 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid te_position value found at index [" << n_vertex 1115 << "];" 1116 " expected:" 1117 " [" 1118 << expected_value << ", " << expected_value << ", " << expected_value << ", " 1119 << expected_value << "], found:" 1120 " [" 1121 << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]." 1122 << tcu::TestLog::EndMessage; 1123 1124 TCU_FAIL("Invalid te_position value found"); 1125 } 1126 } 1127 1128 /* Check result tc_patch_data data if available */ 1129 n_vertex -= n_vertex; 1130 1131 for (std::vector<_vec4>::const_iterator data_iterator = run.result_te_patch_data.begin(); 1132 data_iterator != run.result_te_patch_data.end(); data_iterator++, n_vertex++) 1133 { 1134 const _vec4& data = *data_iterator; 1135 unsigned int vertex_id = n_vertex / run.n_result_vertices_per_patch; 1136 _vec4 expected_value = _vec4((float)vertex_id, ((float)vertex_id) * 0.5f, ((float)vertex_id) * 0.25f, 1137 ((float)vertex_id) * 0.125f); 1138 1139 /* TE uses an even vertex outputted by TC, so we need 1140 * to multiply the expected value by 2. 1141 */ 1142 expected_value.x *= 2.0f; 1143 expected_value.y *= 2.0f; 1144 expected_value.z *= 2.0f; 1145 expected_value.w *= 2.0f; 1146 1147 if (de::abs(data.x - expected_value.x) > epsilon || de::abs(data.y - expected_value.y) > epsilon || 1148 de::abs(data.z - expected_value.z) > epsilon || de::abs(data.w - expected_value.w) > epsilon) 1149 { 1150 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_patch_data value found at index [" 1151 << n_vertex << "];" 1152 " expected:" 1153 " [" 1154 << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", " 1155 << expected_value.w << "], found:" 1156 " [" 1157 << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]." 1158 << tcu::TestLog::EndMessage; 1159 1160 TCU_FAIL("Invalid tc_patch_data value found"); 1161 } 1162 } 1163 } /* for (all runs) */ 1164 1165 /* All done */ 1166 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1167 return STOP; 1168 } 1169 1170 /** Constructor 1171 * 1172 * @param context Test context 1173 **/ 1174 TessellationShaderTCTEgl_in::TessellationShaderTCTEgl_in(Context& context, const ExtParameters& extParams) 1175 : TestCaseBase(context, extParams, "gl_in", "Verifies values of gl_in[] in a tessellation evaluation shader " 1176 "are taken from output variables of a tessellation control shader" 1177 "if one is present.") 1178 , m_bo_id(0) 1179 , m_fs_id(0) 1180 , m_po_id(0) 1181 , m_tcs_id(0) 1182 , m_tes_id(0) 1183 , m_vao_id(0) 1184 , m_vs_id(0) 1185 { 1186 /* Left blank on purpose */ 1187 } 1188 1189 /** Deinitializes all ES objects created for the test. */ 1190 void TessellationShaderTCTEgl_in::deinit() 1191 { 1192 /** Call base class' deinit() function */ 1193 TestCaseBase::deinit(); 1194 1195 if (!m_is_tessellation_shader_supported) 1196 { 1197 return; 1198 } 1199 1200 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1201 1202 /* Revert TF buffer object bindings */ 1203 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 1204 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 1205 1206 /* Reset GL_PATCH_VERTICES_EXT value to the default setting */ 1207 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 1208 1209 /* Disable GL_RASTERIZER_DISCARD mdoe */ 1210 gl.disable(GL_RASTERIZER_DISCARD); 1211 1212 /* Unbind vertex array object */ 1213 gl.bindVertexArray(0); 1214 1215 /* Release all objects we might've created */ 1216 if (m_bo_id != 0) 1217 { 1218 gl.deleteBuffers(1, &m_bo_id); 1219 1220 m_bo_id = 0; 1221 } 1222 1223 if (m_fs_id != 0) 1224 { 1225 gl.deleteShader(m_fs_id); 1226 1227 m_fs_id = 0; 1228 } 1229 1230 if (m_po_id != 0) 1231 { 1232 gl.deleteProgram(m_po_id); 1233 1234 m_po_id = 0; 1235 } 1236 1237 if (m_tcs_id != 0) 1238 { 1239 gl.deleteShader(m_tcs_id); 1240 1241 m_tcs_id = 0; 1242 } 1243 1244 if (m_tes_id != 0) 1245 { 1246 gl.deleteShader(m_tes_id); 1247 1248 m_tes_id = 0; 1249 } 1250 1251 if (m_vs_id != 0) 1252 { 1253 gl.deleteShader(m_vs_id); 1254 1255 m_vs_id = 0; 1256 } 1257 1258 if (m_vao_id != 0) 1259 { 1260 gl.deleteVertexArrays(1, &m_vao_id); 1261 1262 m_vao_id = 0; 1263 } 1264 } 1265 1266 /** Initializes all ES objects that will be used for the test. */ 1267 void TessellationShaderTCTEgl_in::initTest() 1268 { 1269 /* The test requires EXT_tessellation_shader */ 1270 if (!m_is_tessellation_shader_supported) 1271 { 1272 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 1273 } 1274 1275 /* Generate a program object we will later configure */ 1276 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1277 1278 /* Initialize vertex array object */ 1279 gl.genVertexArrays(1, &m_vao_id); 1280 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 1281 1282 gl.bindVertexArray(m_vao_id); 1283 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 1284 1285 /* Create program object */ 1286 m_po_id = gl.createProgram(); 1287 1288 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 1289 1290 /* Generate shader objects the test will use */ 1291 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1292 m_tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 1293 m_tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 1294 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1295 1296 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 1297 1298 /* Configure fragment shader */ 1299 const char* fs_body = "${VERSION}\n" 1300 "\n" 1301 "void main()\n" 1302 "{\n" 1303 "}\n"; 1304 1305 shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body); 1306 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object"); 1307 1308 /* Configure tessellation control shader */ 1309 const char* tc_body = "${VERSION}\n" 1310 "\n" 1311 /* Required EXT_tessellation_shader functionality */ 1312 "${TESSELLATION_SHADER_REQUIRE}\n" 1313 "\n" 1314 "layout (vertices = 1) out;\n" 1315 "\n" 1316 "out float out_float[];\n" 1317 "out int out_int[];\n" 1318 "out ivec3 out_ivec3[];\n" 1319 "out mat2 out_mat2[];\n" 1320 "out uint out_uint[];\n" 1321 "out uvec2 out_uvec2[];\n" 1322 "out vec4 out_vec4[];\n" 1323 "\n" 1324 "out struct\n" 1325 "{\n" 1326 " int test1;\n" 1327 " float test2;\n" 1328 "} out_struct[];\n" 1329 /* Body */ 1330 "void main()\n" 1331 "{\n" 1332 " gl_out [gl_InvocationID].gl_Position = vec4(5.0, 6.0, 7.0, 8.0);\n" 1333 " gl_TessLevelOuter[0] = 1.0;\n" 1334 " gl_TessLevelOuter[1] = 1.0;\n" 1335 "\n" 1336 " out_float[gl_InvocationID] = 22.0;\n" 1337 " out_int [gl_InvocationID] = 23;\n" 1338 " out_ivec3[gl_InvocationID] = ivec3(24, 25, 26);\n" 1339 " out_mat2 [gl_InvocationID] = mat2(vec2(27.0, 28.0), vec2(29.0, 30.0) );\n" 1340 " out_uint [gl_InvocationID] = 31u;\n" 1341 " out_uvec2[gl_InvocationID] = uvec2(32, 33);\n" 1342 " out_vec4 [gl_InvocationID] = vec4(34.0, 35.0, 36.0, 37.0);\n" 1343 "\n" 1344 " out_struct[gl_InvocationID].test1 = 38;\n" 1345 " out_struct[gl_InvocationID].test2 = 39.0;\n" 1346 "}\n"; 1347 1348 shaderSourceSpecialized(m_tcs_id, 1 /* count */, &tc_body); 1349 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object"); 1350 1351 /* Configure tessellation evaluation shader */ 1352 const char* te_body = "${VERSION}\n" 1353 "\n" 1354 "${TESSELLATION_SHADER_REQUIRE}\n" 1355 "\n" 1356 "layout (isolines, point_mode) in;\n" 1357 "\n" 1358 "in float out_float[];\n" 1359 "in int out_int[];\n" 1360 "in ivec3 out_ivec3[];\n" 1361 "in mat2 out_mat2[];\n" 1362 "in uint out_uint[];\n" 1363 "in uvec2 out_uvec2[];\n" 1364 "in vec4 out_vec4[];\n" 1365 "in struct\n" 1366 "{\n" 1367 " int test1;\n" 1368 " float test2;\n" 1369 "} out_struct[];\n" 1370 "\n" 1371 "out float result_float;\n" 1372 "flat out int result_int;\n" 1373 "flat out ivec3 result_ivec3;\n" 1374 "out mat2 result_mat2;\n" 1375 "flat out int result_struct_test1;\n" 1376 "out float result_struct_test2;\n" 1377 "flat out uint result_uint;\n" 1378 "flat out uvec2 result_uvec2;\n" 1379 "out vec4 result_vec4;\n" 1380 "\n" 1381 "void main()\n" 1382 "{\n" 1383 " gl_Position = gl_in[0].gl_Position;\n" 1384 "\n" 1385 " result_float = out_float [0];\n" 1386 " result_int = out_int [0];\n" 1387 " result_ivec3 = out_ivec3 [0];\n" 1388 " result_mat2 = out_mat2 [0];\n" 1389 " result_struct_test1 = out_struct[0].test1;\n" 1390 " result_struct_test2 = out_struct[0].test2;\n" 1391 " result_uint = out_uint [0];\n" 1392 " result_uvec2 = out_uvec2 [0];\n" 1393 " result_vec4 = out_vec4 [0];\n" 1394 "}\n"; 1395 1396 shaderSourceSpecialized(m_tes_id, 1 /* count */, &te_body); 1397 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object"); 1398 1399 /* Configure vertex shader */ 1400 const char* vs_body = "${VERSION}\n" 1401 "\n" 1402 "${SHADER_IO_BLOCKS_ENABLE}\n" 1403 "\n" 1404 "out float out_float;\n" 1405 "flat out int out_int;\n" 1406 "flat out ivec3 out_ivec3;\n" 1407 "out mat2 out_mat2;\n" 1408 "flat out uint out_uint;\n" 1409 "flat out uvec2 out_uvec2;\n" 1410 "out vec4 out_vec4;\n" 1411 "\n" 1412 "flat out struct\n" 1413 "{\n" 1414 " int test1;\n" 1415 " float test2;\n" 1416 "} out_struct;\n" 1417 "\n" 1418 "void main()\n" 1419 "{\n" 1420 " gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n" 1421 "\n" 1422 " out_float = 1.0;\n" 1423 " out_int = 2;\n" 1424 " out_ivec3 = ivec3(3, 4, 5);\n" 1425 " out_mat2 = mat2(vec2(6.0, 7.0), vec2(8.0, 9.0) );\n" 1426 " out_uint = 10u;\n" 1427 " out_uvec2 = uvec2(11u, 12u);\n" 1428 " out_vec4 = vec4(12.0, 13.0, 14.0, 15.0);\n" 1429 " out_struct.test1 = 20;\n" 1430 " out_struct.test2 = 21.0;\n" 1431 "}\n"; 1432 1433 shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body); 1434 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object"); 1435 1436 /* Compile all shaders of our interest */ 1437 const glw::GLuint shaders[] = { m_fs_id, m_tcs_id, m_tes_id, m_vs_id }; 1438 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 1439 1440 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 1441 { 1442 glw::GLint compile_status = GL_FALSE; 1443 glw::GLuint shader = shaders[n_shader]; 1444 1445 gl.compileShader(shader); 1446 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 1447 1448 gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); 1449 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 1450 1451 if (compile_status != GL_TRUE) 1452 { 1453 const char* src[] = { fs_body, tc_body, te_body, vs_body }; 1454 m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader 1455 << " failed.\n" 1456 << "Info log:\n" 1457 << getCompilationInfoLog(shader) << "Shader:\n" 1458 << src[n_shader] << tcu::TestLog::EndMessage; 1459 1460 TCU_FAIL("Shader compilation failed"); 1461 } 1462 } /* for (all shaders) */ 1463 1464 /* Attach the shaders to the test program object, set up XFB and then link the program */ 1465 glw::GLint link_status = GL_FALSE; 1466 glw::GLint n_xfb_varyings = 0; 1467 const glw::GLchar** xfb_varyings = NULL; 1468 glw::GLint xfb_size = 0; 1469 1470 getXFBProperties(&xfb_varyings, &n_xfb_varyings, &xfb_size); 1471 1472 gl.transformFeedbackVaryings(m_po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS); 1473 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed"); 1474 1475 gl.attachShader(m_po_id, m_fs_id); 1476 gl.attachShader(m_po_id, m_tcs_id); 1477 gl.attachShader(m_po_id, m_tes_id); 1478 gl.attachShader(m_po_id, m_vs_id); 1479 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 1480 1481 gl.linkProgram(m_po_id); 1482 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 1483 1484 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 1485 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 1486 1487 if (link_status != GL_TRUE) 1488 { 1489 TCU_FAIL("Program linking failed"); 1490 } 1491 1492 /* Generate and set up a buffer object we will use to hold XFBed data. */ 1493 gl.genBuffers(1, &m_bo_id); 1494 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed"); 1495 1496 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 1497 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed"); 1498 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 1499 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed"); 1500 1501 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_size, NULL /* data */, GL_STATIC_DRAW); 1502 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed"); 1503 1504 /* We're good to execute the test! */ 1505 } 1506 1507 /** Retrieves XFB-specific properties that are used in various locations of 1508 * this test implementation. 1509 * 1510 * @param out_names Deref will be used to store location of an array keeping 1511 * names of varyings that should be used for TF. Can be NULL, 1512 * in which case nothing will be stored under *out_names. 1513 * @param out_n_names Deref will be used to store number of strings the @param 1514 * out_names array holds. Can be NULL, in which case nothing 1515 * will be stored under *out_n_names. 1516 * @param out_xfb_size Deref will be used to store amount of bytes needed to hold 1517 * all data generated by a draw call used by this test. Can be 1518 * NULL, in which case nothing will be stored under *out_xfb_size. 1519 **/ 1520 void TessellationShaderTCTEgl_in::getXFBProperties(const glw::GLchar*** out_names, glw::GLint* out_n_names, 1521 glw::GLint* out_xfb_size) 1522 { 1523 static const glw::GLchar* xfb_varyings[] = { "result_float", "result_int", "result_ivec3", 1524 "result_mat2", "result_struct_test1", "result_struct_test2", 1525 "result_uint", "result_uvec2", "result_vec4", 1526 "gl_Position" }; 1527 static const unsigned int xfb_size = (sizeof(float) + /* result_float */ 1528 sizeof(int) + /* result_int */ 1529 sizeof(int) * 3 + /* result_ivec3 */ 1530 sizeof(float) * 4 + /* result_mat2 */ 1531 sizeof(int) + /* result_struct_test1 */ 1532 sizeof(float) + /* result_struct_test2 */ 1533 sizeof(int) + /* result_uint */ 1534 sizeof(int) * 2 + /* result_uvec2 */ 1535 sizeof(float) * 4 + /* result_vec4 */ 1536 sizeof(float) * 4) * /* gl_Position */ 1537 2; /* two points will be generated by tessellation */ 1538 1539 static const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]); 1540 1541 if (out_names != NULL) 1542 { 1543 *out_names = xfb_varyings; 1544 } 1545 1546 if (out_n_names != NULL) 1547 { 1548 *out_n_names = n_xfb_varyings; 1549 } 1550 1551 if (out_xfb_size != NULL) 1552 { 1553 /* NOTE: Tessellator is expected to generate two points for the purpose of 1554 * this test, which is why we need to multiply the amount of bytes store 1555 * in xfb_size by two. 1556 */ 1557 *out_xfb_size = xfb_size * 2; 1558 } 1559 } 1560 1561 /** Executes the test. 1562 * 1563 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 1564 * 1565 * Note the function throws exception should an error occur! 1566 * 1567 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 1568 **/ 1569 tcu::TestNode::IterateResult TessellationShaderTCTEgl_in::iterate(void) 1570 { 1571 /* Initialize ES test objects */ 1572 initTest(); 1573 1574 /* Our program object takes a single vertex per patch */ 1575 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1576 1577 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1); 1578 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed"); 1579 1580 /* Render the geometry. We're only interested in XFB data, not the visual outcome, 1581 * so disable rasterization before we fire a draw call. 1582 */ 1583 gl.useProgram(m_po_id); 1584 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 1585 1586 gl.enable(GL_RASTERIZER_DISCARD); 1587 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed"); 1588 1589 gl.beginTransformFeedback(GL_POINTS); 1590 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_POINTS) call failed"); 1591 { 1592 gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* count */); 1593 1594 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed"); 1595 } 1596 gl.endTransformFeedback(); 1597 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed"); 1598 1599 /* Download the data we stored with TF */ 1600 glw::GLint n_xfb_names = 0; 1601 void* rendered_data = NULL; 1602 const glw::GLchar** xfb_names = NULL; 1603 glw::GLint xfb_size = 0; 1604 1605 getXFBProperties(&xfb_names, &n_xfb_names, &xfb_size); 1606 1607 rendered_data = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, xfb_size, GL_MAP_READ_BIT); 1608 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 1609 1610 /* Move through the result buffer and make sure the values we retrieved are valid. 1611 * Note that two points will be generated by the tessellator, so run the checks 1612 * twice. 1613 */ 1614 typedef enum { 1615 XFB_VARYING_TYPE_FLOAT, 1616 XFB_VARYING_TYPE_INT, 1617 1618 XFB_VARYING_TYPE_UNKNOWN 1619 } _xfb_varying_type; 1620 1621 unsigned char* traveller_ptr = (unsigned char*)rendered_data; 1622 1623 for (glw::GLint n_point = 0; n_point < 2 /* points */; ++n_point) 1624 { 1625 for (glw::GLint n_xfb_name = 0; n_xfb_name < n_xfb_names; ++n_xfb_name) 1626 { 1627 glw::GLfloat expected_value_float[4] = { 0.0f }; 1628 glw::GLint expected_value_int[4] = { 0 }; 1629 std::string name = xfb_names[n_xfb_name]; 1630 unsigned int n_varying_components = 0; 1631 _xfb_varying_type varying_type = XFB_VARYING_TYPE_UNKNOWN; 1632 1633 if (name.compare("result_float") == 0) 1634 { 1635 expected_value_float[0] = 22.0f; 1636 n_varying_components = 1; 1637 varying_type = XFB_VARYING_TYPE_FLOAT; 1638 } 1639 else if (name.compare("result_int") == 0) 1640 { 1641 expected_value_int[0] = 23; 1642 n_varying_components = 1; 1643 varying_type = XFB_VARYING_TYPE_INT; 1644 } 1645 else if (name.compare("result_ivec3") == 0) 1646 { 1647 expected_value_int[0] = 24; 1648 expected_value_int[1] = 25; 1649 expected_value_int[2] = 26; 1650 n_varying_components = 3; 1651 varying_type = XFB_VARYING_TYPE_INT; 1652 } 1653 else if (name.compare("result_mat2") == 0) 1654 { 1655 expected_value_float[0] = 27.0f; 1656 expected_value_float[1] = 28.0f; 1657 expected_value_float[2] = 29.0f; 1658 expected_value_float[3] = 30.0f; 1659 n_varying_components = 4; 1660 varying_type = XFB_VARYING_TYPE_FLOAT; 1661 } 1662 else if (name.compare("result_struct_test1") == 0) 1663 { 1664 expected_value_int[0] = 38; 1665 n_varying_components = 1; 1666 varying_type = XFB_VARYING_TYPE_INT; 1667 } 1668 else if (name.compare("result_struct_test2") == 0) 1669 { 1670 expected_value_float[0] = 39.0f; 1671 n_varying_components = 1; 1672 varying_type = XFB_VARYING_TYPE_FLOAT; 1673 } 1674 else if (name.compare("result_uint") == 0) 1675 { 1676 expected_value_int[0] = 31; 1677 n_varying_components = 1; 1678 varying_type = XFB_VARYING_TYPE_INT; 1679 } 1680 else if (name.compare("result_uvec2") == 0) 1681 { 1682 expected_value_int[0] = 32; 1683 expected_value_int[1] = 33; 1684 n_varying_components = 2; 1685 varying_type = XFB_VARYING_TYPE_INT; 1686 } 1687 else if (name.compare("result_vec4") == 0) 1688 { 1689 expected_value_float[0] = 34.0f; 1690 expected_value_float[1] = 35.0f; 1691 expected_value_float[2] = 36.0f; 1692 expected_value_float[3] = 37.0f; 1693 n_varying_components = 4; 1694 varying_type = XFB_VARYING_TYPE_FLOAT; 1695 } 1696 else if (name.compare("gl_Position") == 0) 1697 { 1698 expected_value_float[0] = 5.0f; 1699 expected_value_float[1] = 6.0f; 1700 expected_value_float[2] = 7.0f; 1701 expected_value_float[3] = 8.0f; 1702 n_varying_components = 4; 1703 varying_type = XFB_VARYING_TYPE_FLOAT; 1704 } 1705 else 1706 { 1707 TCU_FAIL("Unrecognized XFB name"); 1708 } 1709 1710 /* Move through the requested amount of components and perform type-specific 1711 * comparison. 1712 */ 1713 const float epsilon = (float)1e-5; 1714 1715 for (unsigned int n_component = 0; n_component < n_varying_components; ++n_component) 1716 { 1717 switch (varying_type) 1718 { 1719 case XFB_VARYING_TYPE_FLOAT: 1720 { 1721 glw::GLfloat* rendered_value = (glw::GLfloat*)traveller_ptr; 1722 1723 if (de::abs(*rendered_value - expected_value_float[n_component]) > epsilon) 1724 { 1725 m_testCtx.getLog() 1726 << tcu::TestLog::Message << "Invalid component at index [" << n_component << "] " 1727 << "(found:" << *rendered_value << " expected:" << expected_value_float[n_component] 1728 << ") for varying [" << name.c_str() << "]" << tcu::TestLog::EndMessage; 1729 } 1730 1731 traveller_ptr += sizeof(glw::GLfloat); 1732 1733 break; 1734 } 1735 1736 case XFB_VARYING_TYPE_INT: 1737 { 1738 glw::GLint* rendered_value = (glw::GLint*)traveller_ptr; 1739 1740 if (*rendered_value != expected_value_int[n_component]) 1741 { 1742 m_testCtx.getLog() 1743 << tcu::TestLog::Message << "Invalid component at index [" << n_component << "] " 1744 << "(found:" << *rendered_value << " expected:" << expected_value_int[n_component] 1745 << ") for varying [" << name.c_str() << "]" << tcu::TestLog::EndMessage; 1746 1747 TCU_FAIL("Invalid rendered value"); 1748 } 1749 1750 traveller_ptr += sizeof(glw::GLint); 1751 1752 break; 1753 } 1754 1755 default: 1756 { 1757 TCU_FAIL("Unrecognized varying type"); 1758 } 1759 } /* switch(varying_type) */ 1760 1761 } /* for (all components) */ 1762 } /* for (all XFBed variables) */ 1763 } /* for (both points) */ 1764 1765 /* Unmap the BO */ 1766 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 1767 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 1768 1769 /* All done */ 1770 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1771 return STOP; 1772 } 1773 1774 /** Constructor 1775 * 1776 * @param context Test context 1777 **/ 1778 TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize:: 1779 TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize(Context& context, const ExtParameters& extParams) 1780 : TestCaseBase(context, extParams, "gl_MaxPatchVertices_Position_PointSize", 1781 "Verifies gl_Position and gl_PointSize (if supported) " 1782 "are set to correct values in TE stage. Checks if up to " 1783 "gl_MaxPatchVertices input block values can be accessed " 1784 "from TE stage. Also verifies if TC/TE stage properties " 1785 "can be correctly queried for both regular and separate " 1786 "program objects.") 1787 , m_bo_id(0) 1788 , m_gl_max_patch_vertices_value(0) 1789 , m_gl_max_tess_gen_level_value(0) 1790 , m_utils_ptr(DE_NULL) 1791 , m_vao_id(0) 1792 { 1793 /* Left blank on purpose */ 1794 } 1795 1796 /** Deinitializes all ES objects created for the test. */ 1797 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::deinit() 1798 { 1799 /** Call base class' deinit() function */ 1800 TestCaseBase::deinit(); 1801 1802 if (!m_is_tessellation_shader_supported) 1803 { 1804 return; 1805 } 1806 1807 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1808 1809 /* Revert TF buffer object bindings */ 1810 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 1811 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 1812 1813 /* Reset GL_PATCH_VERTICES_EXT value to the default setting */ 1814 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 1815 1816 /* Disable GL_RASTERIZER_DISCARD mode */ 1817 gl.disable(GL_RASTERIZER_DISCARD); 1818 1819 /* Unbind vertex array object */ 1820 gl.bindVertexArray(0); 1821 1822 /* Release all objects we might've created */ 1823 if (m_bo_id != 0) 1824 { 1825 gl.deleteBuffers(1, &m_bo_id); 1826 1827 m_bo_id = 0; 1828 } 1829 if (m_vao_id != 0) 1830 { 1831 gl.deleteVertexArrays(1, &m_vao_id); 1832 1833 m_vao_id = 0; 1834 } 1835 1836 if (m_utils_ptr != DE_NULL) 1837 { 1838 delete m_utils_ptr; 1839 1840 m_utils_ptr = DE_NULL; 1841 } 1842 1843 /* Release all test runs */ 1844 for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it) 1845 { 1846 deinitTestRun(*it); 1847 } 1848 m_runs.clear(); 1849 } 1850 1851 /** Deinitializes all ES objects generated for a test run */ 1852 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::deinitTestRun(_run& run) 1853 { 1854 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1855 1856 if (run.fs_id != 0) 1857 { 1858 gl.deleteShader(run.fs_id); 1859 1860 run.fs_id = 0; 1861 } 1862 1863 if (run.fs_program_id != 0) 1864 { 1865 gl.deleteProgram(run.fs_program_id); 1866 1867 run.fs_program_id = 0; 1868 } 1869 1870 if (run.pipeline_object_id != 0) 1871 { 1872 gl.deleteProgramPipelines(1, &run.pipeline_object_id); 1873 1874 run.pipeline_object_id = 0; 1875 } 1876 1877 if (run.po_id != 0) 1878 { 1879 gl.deleteProgram(run.po_id); 1880 1881 run.po_id = 0; 1882 } 1883 1884 if (run.tc_id != 0) 1885 { 1886 gl.deleteShader(run.tc_id); 1887 1888 run.tc_id = 0; 1889 } 1890 1891 if (run.tc_program_id != 0) 1892 { 1893 gl.deleteProgram(run.tc_program_id); 1894 1895 run.tc_program_id = 0; 1896 } 1897 1898 if (run.te_id != 0) 1899 { 1900 gl.deleteShader(run.te_id); 1901 1902 run.te_id = 0; 1903 } 1904 1905 if (run.te_program_id != 0) 1906 { 1907 gl.deleteProgram(run.te_program_id); 1908 1909 run.te_program_id = 0; 1910 } 1911 1912 if (run.vs_id != 0) 1913 { 1914 gl.deleteShader(run.vs_id); 1915 1916 run.vs_id = 0; 1917 } 1918 1919 if (run.vs_program_id != 0) 1920 { 1921 gl.deleteProgram(run.vs_program_id); 1922 1923 run.vs_program_id = 0; 1924 } 1925 } 1926 1927 /** Retrieves a dummy fragment shader code to be used for forming program objects 1928 * used by the test. 1929 * 1930 * @return As per description. 1931 **/ 1932 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getFragmentShaderCode( 1933 bool should_accept_pointsize_data) 1934 { 1935 // Requires input to match previous stage's output 1936 std::stringstream result_code; 1937 1938 result_code << "${VERSION}\n" 1939 "\n" 1940 "${SHADER_IO_BLOCKS_REQUIRE}\n" 1941 "\n" 1942 "precision highp float;\n" 1943 "precision highp int;\n" 1944 "out layout (location = 0) vec4 col;\n"; 1945 1946 if (should_accept_pointsize_data) 1947 { 1948 result_code << "in float te_pointsize;\n"; 1949 } 1950 1951 result_code << "in vec4 te_position;\n" 1952 "in vec2 te_value1;\n" 1953 "in flat ivec4 te_value2;\n" 1954 "\n" 1955 "void main()\n" 1956 "{\n" 1957 " col = vec4(1.0, 1.0, 1.0, 1.0);\n" 1958 "}\n"; 1959 1960 return result_code.str(); 1961 } 1962 1963 /** Retrieves tessellation control shader source code, given user-provided arguments. 1964 * 1965 * @param should_pass_pointsize_data true if Tessellation Control shader should configure 1966 * gl_PointSize value. This should be only set to true 1967 * if the tested ES implementation reports support of 1968 * GL_EXT_tessellation_point_size extension. 1969 * @param inner_tess_levels Two FP values defining inner tessellation level values. 1970 * Must not be NULL. 1971 * @param outer_tess_levels Four FP values defining outer tessellation level values. 1972 * Must not be NULL. 1973 * 1974 * @return As per description. 1975 **/ 1976 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getTessellationControlShaderCode( 1977 bool should_pass_pointsize_data, const glw::GLfloat* inner_tess_levels, const glw::GLfloat* outer_tess_levels) 1978 { 1979 std::stringstream result_code; 1980 1981 result_code << "${VERSION}\n" 1982 "\n" 1983 "${TESSELLATION_SHADER_REQUIRE}\n"; 1984 1985 if (should_pass_pointsize_data) 1986 { 1987 result_code << "${TESSELLATION_POINT_SIZE_REQUIRE}\n"; 1988 } 1989 1990 result_code << "\n" 1991 "layout(vertices = " 1992 << m_gl_max_patch_vertices_value << ") out;\n" 1993 "\n"; 1994 if (should_pass_pointsize_data) 1995 { 1996 result_code << "${IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE}"; 1997 result_code << "${OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE}"; 1998 } 1999 else 2000 { 2001 result_code << "${IN_PER_VERTEX_DECL_ARRAY}"; 2002 result_code << "${OUT_PER_VERTEX_DECL_ARRAY}"; 2003 } 2004 result_code << "out OUT_TC\n" 2005 "{\n" 2006 " vec2 value1;\n" 2007 " ivec4 value2;\n" 2008 "} result[];\n" 2009 "\n" 2010 "void main()\n" 2011 "{\n"; 2012 2013 if (should_pass_pointsize_data) 2014 { 2015 result_code << " gl_out[gl_InvocationID].gl_PointSize = 1.0 / float(gl_InvocationID + 1);\n"; 2016 } 2017 2018 result_code << " gl_out[gl_InvocationID].gl_Position = vec4( float(gl_InvocationID * 4 + 0), " 2019 "float(gl_InvocationID * 4 + 1),\n" 2020 " float(gl_InvocationID * 4 + 2), " 2021 "float(gl_InvocationID * 4 + 3));\n" 2022 " result[gl_InvocationID].value1 = vec2(1.0 / float(gl_InvocationID + 1), 1.0 / " 2023 "float(gl_InvocationID + 2) );\n" 2024 " result[gl_InvocationID].value2 = ivec4( gl_InvocationID + 1, " 2025 "gl_InvocationID + 2,\n" 2026 " gl_InvocationID + 3, " 2027 "gl_InvocationID + 4);\n" 2028 "\n" 2029 " gl_TessLevelInner[0] = float(" 2030 << inner_tess_levels[0] << ");\n" 2031 " gl_TessLevelInner[1] = float(" 2032 << inner_tess_levels[1] << ");\n" 2033 " gl_TessLevelOuter[0] = float(" 2034 << outer_tess_levels[0] << ");\n" 2035 " gl_TessLevelOuter[1] = float(" 2036 << outer_tess_levels[1] << ");\n" 2037 " gl_TessLevelOuter[2] = float(" 2038 << outer_tess_levels[2] << ");\n" 2039 " gl_TessLevelOuter[3] = float(" 2040 << outer_tess_levels[3] << ");\n" 2041 "}\n"; 2042 2043 return result_code.str(); 2044 } 2045 2046 /** Retrieves tessellation evaluation shader source code, given user-provided arguments. 2047 * 2048 * @param should_pass_pointsize_data true if Tessellation Evaluation shader should set 2049 * gl_PointSize to the value set by Tessellation Control 2050 * stage. This should be only set to true if the tested 2051 * ES implementation reports support of GL_EXT_tessellation_point_size 2052 * extension, and TC stage assigns a value to gl_PointSize. 2053 * @param primitive_mode Primitive mode to use for the stage. 2054 * @param vertex_ordering Vertex ordering to use for the stage. 2055 * @param vertex_spacing Vertex spacing to use for the stage. 2056 * @param is_point_mode_enabled true to make the TE stage work in point mode, false otherwise. 2057 * 2058 * @return As per description. 2059 **/ 2060 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getTessellationEvaluationShaderCode( 2061 bool should_pass_pointsize_data, _tessellation_primitive_mode primitive_mode, 2062 _tessellation_shader_vertex_ordering vertex_ordering, _tessellation_shader_vertex_spacing vertex_spacing, 2063 bool is_point_mode_enabled) 2064 { 2065 std::stringstream result_sstream; 2066 std::string result; 2067 2068 result_sstream << "${VERSION}\n" 2069 "\n" 2070 "${TESSELLATION_SHADER_REQUIRE}\n"; 2071 2072 if (should_pass_pointsize_data) 2073 { 2074 result_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n"; 2075 } 2076 2077 result_sstream << "\n" 2078 "layout (TESSELLATOR_PRIMITIVE_MODE VERTEX_SPACING_MODE VERTEX_ORDERING POINT_MODE) in;\n" 2079 "\n"; 2080 if (should_pass_pointsize_data) 2081 { 2082 result_sstream << "${IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE}"; 2083 result_sstream << "${OUT_PER_VERTEX_DECL_POINT_SIZE}"; 2084 } 2085 else 2086 { 2087 result_sstream << "${IN_PER_VERTEX_DECL_ARRAY}"; 2088 result_sstream << "${OUT_PER_VERTEX_DECL}"; 2089 } 2090 result_sstream << "in OUT_TC\n" 2091 "{\n" 2092 " vec2 value1;\n" 2093 " ivec4 value2;\n" 2094 "} tc_data[];\n" 2095 "\n"; 2096 2097 if (should_pass_pointsize_data) 2098 { 2099 result_sstream << "out float te_pointsize;\n"; 2100 } 2101 2102 result_sstream << "out vec4 te_position;\n" 2103 "out vec2 te_value1;\n" 2104 "out flat ivec4 te_value2;\n" 2105 "\n" 2106 "void main()\n" 2107 "{\n"; 2108 2109 if (should_pass_pointsize_data) 2110 { 2111 result_sstream << " te_pointsize = 0.0;\n"; 2112 } 2113 2114 result_sstream << " te_position = vec4 (0.0);\n" 2115 " te_value1 = vec2 (0.0);\n" 2116 " te_value2 = ivec4(0);\n" 2117 "\n" 2118 " for (int n = 0; n < " 2119 << m_gl_max_patch_vertices_value << "; ++n)\n" 2120 " {\n"; 2121 2122 if (should_pass_pointsize_data) 2123 { 2124 result_sstream << " te_pointsize += gl_in[n].gl_PointSize;\n"; 2125 } 2126 2127 result_sstream << " te_position += gl_in [n].gl_Position;\n" 2128 " te_value1 += tc_data[n].value1;\n" 2129 " te_value2 += tc_data[n].value2;\n" 2130 " }\n" 2131 "}\n"; 2132 2133 result = result_sstream.str(); 2134 2135 /* Replace the tokens */ 2136 const char* point_mode_token = "POINT_MODE"; 2137 std::size_t point_mode_token_index = std::string::npos; 2138 std::string primitive_mode_string = TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode); 2139 const char* primitive_mode_token = "TESSELLATOR_PRIMITIVE_MODE"; 2140 std::size_t primitive_mode_token_index = std::string::npos; 2141 std::string vertex_ordering_string; 2142 const char* vertex_ordering_token = "VERTEX_ORDERING"; 2143 std::size_t vertex_ordering_token_index = std::string::npos; 2144 std::string vertex_spacing_mode_string; 2145 const char* vertex_spacing_token = "VERTEX_SPACING_MODE"; 2146 std::size_t vertex_spacing_token_index = std::string::npos; 2147 2148 /* Prepare the vertex ordering token. We need to do this manually, because the default vertex spacing 2149 * mode translates to empty string and the shader would fail to compile if we hadn't taken care of the 2150 * comma 2151 */ 2152 if (vertex_ordering == TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT) 2153 { 2154 vertex_ordering_string = TessellationShaderUtils::getESTokenForVertexOrderingMode(vertex_ordering); 2155 } 2156 else 2157 { 2158 std::stringstream helper_sstream; 2159 2160 helper_sstream << ", " << TessellationShaderUtils::getESTokenForVertexOrderingMode(vertex_ordering); 2161 2162 vertex_ordering_string = helper_sstream.str(); 2163 } 2164 2165 /* Do the same for vertex spacing token */ 2166 if (vertex_spacing == TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT) 2167 { 2168 vertex_spacing_mode_string = TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing); 2169 } 2170 else 2171 { 2172 std::stringstream helper_sstream; 2173 2174 helper_sstream << ", " << TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing); 2175 2176 vertex_spacing_mode_string = helper_sstream.str(); 2177 } 2178 2179 /* Primitive mode */ 2180 while ((primitive_mode_token_index = result.find(primitive_mode_token)) != std::string::npos) 2181 { 2182 result = result.replace(primitive_mode_token_index, strlen(primitive_mode_token), primitive_mode_string); 2183 2184 primitive_mode_token_index = result.find(primitive_mode_token); 2185 } 2186 2187 /* Vertex ordering */ 2188 while ((vertex_ordering_token_index = result.find(vertex_ordering_token)) != std::string::npos) 2189 { 2190 result = result.replace(vertex_ordering_token_index, strlen(vertex_ordering_token), vertex_ordering_string); 2191 2192 vertex_ordering_token_index = result.find(vertex_ordering_token); 2193 } 2194 2195 /* Vertex spacing */ 2196 while ((vertex_spacing_token_index = result.find(vertex_spacing_token)) != std::string::npos) 2197 { 2198 result = result.replace(vertex_spacing_token_index, strlen(vertex_spacing_token), vertex_spacing_mode_string); 2199 2200 vertex_spacing_token_index = result.find(vertex_spacing_token); 2201 } 2202 2203 /* Point mode */ 2204 while ((point_mode_token_index = result.find(point_mode_token)) != std::string::npos) 2205 { 2206 result = result.replace(point_mode_token_index, strlen(point_mode_token), 2207 (is_point_mode_enabled) ? ", point_mode" : ""); 2208 2209 point_mode_token_index = result.find(point_mode_token); 2210 } 2211 2212 return result; 2213 } 2214 2215 /** Retrieves a dummy vertex shader code to be used for forming program objects 2216 * used by the test. 2217 * 2218 * @return As per description. 2219 **/ 2220 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getVertexShaderCode( 2221 bool should_pass_pointsize_data) 2222 { 2223 std::stringstream result_sstream; 2224 result_sstream << "${VERSION}\n\n"; 2225 if (should_pass_pointsize_data) 2226 { 2227 result_sstream << "${OUT_PER_VERTEX_DECL_POINT_SIZE}"; 2228 } 2229 else 2230 { 2231 result_sstream << "${OUT_PER_VERTEX_DECL}"; 2232 } 2233 result_sstream << "\n" 2234 "void main()\n" 2235 "{\n" 2236 "}\n"; 2237 2238 return result_sstream.str(); 2239 } 2240 2241 /** Initializes all ES objects that will be used for the test. */ 2242 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::initTest() 2243 { 2244 /* The test requires EXT_tessellation_shader */ 2245 if (!m_is_tessellation_shader_supported) 2246 { 2247 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 2248 } 2249 2250 /* Retrieve ES entry-points */ 2251 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2252 2253 /* Initialize vertex array object */ 2254 gl.genVertexArrays(1, &m_vao_id); 2255 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 2256 2257 gl.bindVertexArray(m_vao_id); 2258 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 2259 2260 /* Generate a buffer object we will use to hold XFB data */ 2261 gl.genBuffers(1, &m_bo_id); 2262 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 2263 2264 /* Configure XFB buffer object bindings */ 2265 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 2266 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 2267 2268 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() / glBindBufferBase() call(s) failed"); 2269 2270 /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */ 2271 gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &m_gl_max_tess_gen_level_value); 2272 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 2273 2274 /* Retrieve GL_MAX_PATCH_VERTICES_EXT value */ 2275 gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices_value); 2276 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_PATCH_VERTICES_EXT pname"); 2277 2278 /* We only need 1 vertex per input patch */ 2279 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1); 2280 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname"); 2281 2282 /* Disable rasterization */ 2283 gl.enable(GL_RASTERIZER_DISCARD); 2284 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed"); 2285 2286 /* Spawn utilities class instance */ 2287 m_utils_ptr = new TessellationShaderUtils(gl, this); 2288 2289 /* Initialize all test iterations */ 2290 bool point_mode_enabled_flags[] = { false, true }; 2291 const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, 2292 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 2293 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 2294 const _tessellation_shader_vertex_ordering vertex_ordering_modes[] = { 2295 TESSELLATION_SHADER_VERTEX_ORDERING_CCW, TESSELLATION_SHADER_VERTEX_ORDERING_CW, 2296 TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT 2297 }; 2298 const _tessellation_shader_vertex_spacing vertex_spacing_modes[] = { 2299 TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN, 2300 TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD, TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT 2301 }; 2302 const unsigned int n_point_mode_enabled_flags = 2303 sizeof(point_mode_enabled_flags) / sizeof(point_mode_enabled_flags[0]); 2304 const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 2305 const unsigned int n_vertex_ordering_modes = sizeof(vertex_ordering_modes) / sizeof(vertex_ordering_modes[0]); 2306 const unsigned int n_vertex_spacing_modes = sizeof(vertex_spacing_modes) / sizeof(vertex_spacing_modes[0]); 2307 2308 bool deleteResources = false; 2309 2310 for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; n_primitive_mode++) 2311 { 2312 _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 2313 _tessellation_levels_set tessellation_levels = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode( 2314 primitive_mode, m_gl_max_tess_gen_level_value, TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE); 2315 2316 for (_tessellation_levels_set_const_iterator tessellation_levels_iterator = tessellation_levels.begin(); 2317 tessellation_levels_iterator != tessellation_levels.end(); tessellation_levels_iterator++) 2318 { 2319 const _tessellation_levels& tess_levels = *tessellation_levels_iterator; 2320 2321 for (unsigned int n_vertex_ordering_mode = 0; n_vertex_ordering_mode < n_vertex_ordering_modes; 2322 ++n_vertex_ordering_mode) 2323 { 2324 _tessellation_shader_vertex_ordering vertex_ordering = vertex_ordering_modes[n_vertex_ordering_mode]; 2325 2326 for (unsigned int n_vertex_spacing_mode = 0; n_vertex_spacing_mode < n_vertex_spacing_modes; 2327 ++n_vertex_spacing_mode) 2328 { 2329 _tessellation_shader_vertex_spacing vertex_spacing = vertex_spacing_modes[n_vertex_spacing_mode]; 2330 2331 for (unsigned int n_point_mode_enabled_flag = 0; 2332 n_point_mode_enabled_flag < n_point_mode_enabled_flags; ++n_point_mode_enabled_flag) 2333 { 2334 bool is_point_mode_enabled = point_mode_enabled_flags[n_point_mode_enabled_flag]; 2335 2336 /* Only create gl_PointSize-enabled runs if the implementation supports 2337 * GL_EXT_tessellation_point_size extension 2338 */ 2339 if (!m_is_tessellation_shader_point_size_supported && is_point_mode_enabled) 2340 { 2341 continue; 2342 } 2343 2344 /* Execute the test run */ 2345 _run run; 2346 2347 memcpy(run.inner, tess_levels.inner, sizeof(run.inner)); 2348 memcpy(run.outer, tess_levels.outer, sizeof(run.outer)); 2349 2350 run.point_mode = is_point_mode_enabled; 2351 run.primitive_mode = primitive_mode; 2352 run.vertex_ordering = vertex_ordering; 2353 run.vertex_spacing = vertex_spacing; 2354 2355 initTestRun(run); 2356 2357 if (deleteResources) 2358 { 2359 deinitTestRun(run); 2360 } 2361 2362 deleteResources = true; 2363 2364 /* Store it for further processing */ 2365 m_runs.push_back(run); 2366 } /* for (all 'point mode' enabled flags) */ 2367 } /* for (all vertex spacing modes) */ 2368 } /* for (all vertex ordering modes) */ 2369 } /* for (all tessellation levels for active primitive mode) */ 2370 } /* for (all primitive modes) */ 2371 } 2372 2373 /** Initializes all ES objects used by the test, captures the tessellation coordinates 2374 * and stores them in the descriptor. 2375 * Also performs a handful of other minor checks, as described by test specification. 2376 * 2377 * @param run Run descriptor to operate on. 2378 **/ 2379 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::initTestRun(_run& run) 2380 { 2381 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2382 2383 /* Build shader objects */ 2384 run.fs_id = gl.createShader(GL_FRAGMENT_SHADER); 2385 run.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 2386 run.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 2387 run.vs_id = gl.createShader(GL_VERTEX_SHADER); 2388 2389 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed"); 2390 2391 /* Generate fragment shader (or stand-alone program) */ 2392 std::string fs_code_string = getFragmentShaderCode(run.point_mode); 2393 const char* fs_code_raw_ptr = fs_code_string.c_str(); 2394 2395 shaderSourceSpecialized(run.fs_id, 1 /* count */, &fs_code_raw_ptr); 2396 2397 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for fragment shader"); 2398 2399 /* Generate tessellation control shader (or stand-alone program) */ 2400 std::string tc_code_string = getTessellationControlShaderCode(run.point_mode, run.inner, run.outer); 2401 const char* tc_code_raw_ptr = tc_code_string.c_str(); 2402 2403 shaderSourceSpecialized(run.tc_id, 1 /* count */, &tc_code_raw_ptr); 2404 2405 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation control shader"); 2406 2407 /* Generate tessellation evaluation shader (or stand-alone program) */ 2408 std::string te_code_string = getTessellationEvaluationShaderCode( 2409 run.point_mode, run.primitive_mode, run.vertex_ordering, run.vertex_spacing, run.point_mode); 2410 const char* te_code_raw_ptr = te_code_string.c_str(); 2411 2412 shaderSourceSpecialized(run.te_id, 1 /* count */, &te_code_raw_ptr); 2413 2414 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation evaluation shader"); 2415 2416 /* Generate vertex shader (or stand-alone program) */ 2417 std::string vs_code_string = getVertexShaderCode(run.point_mode); 2418 const char* vs_code_raw_ptr = vs_code_string.c_str(); 2419 2420 shaderSourceSpecialized(run.vs_id, 1 /* count */, &vs_code_raw_ptr); 2421 2422 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for vertex shader"); 2423 2424 /* Compile all shaders first. Also make sure the shader objects we have 2425 * attached are correctly reported. 2426 */ 2427 const glw::GLuint shaders[] = { run.fs_id, run.tc_id, run.te_id, run.vs_id }; 2428 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 2429 2430 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 2431 { 2432 glw::GLint compile_status = GL_FALSE; 2433 glw::GLint shader = shaders[n_shader]; 2434 2435 gl.compileShader(shader); 2436 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed"); 2437 2438 gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); 2439 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed"); 2440 2441 if (compile_status != GL_TRUE) 2442 { 2443 m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n" 2444 << getCompilationInfoLog(shader) << "\nShader:\n" 2445 << getShaderSource(shader) << tcu::TestLog::EndMessage; 2446 TCU_FAIL("Shader compilation failed"); 2447 } 2448 } 2449 2450 /* Run two iterations: 2451 * 2452 * 1) First, using a program object; 2453 * 2) The other one using pipeline objects; 2454 */ 2455 for (unsigned int n_iteration = 0; n_iteration < 2 /* program / pipeline objects */; ++n_iteration) 2456 { 2457 bool should_use_program_object = (n_iteration == 0); 2458 2459 /* Generate container object(s) first */ 2460 if (!should_use_program_object) 2461 { 2462 gl.genProgramPipelines(1, &run.pipeline_object_id); 2463 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() failed"); 2464 2465 /* As per test spec, make sure no tessellation stages are defined for 2466 * a pipeline object by default */ 2467 glw::GLint program_tc_id = 1; 2468 glw::GLint program_te_id = 1; 2469 2470 gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER, &program_tc_id); 2471 gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER, &program_te_id); 2472 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() failed"); 2473 2474 if (program_tc_id != 0 || program_te_id != 0) 2475 { 2476 GLU_EXPECT_NO_ERROR(gl.getError(), "A pipeline object returned a non-zero ID of " 2477 "a separate program object when asked for TC/TE" 2478 " program ID."); 2479 } 2480 } 2481 else 2482 { 2483 run.po_id = gl.createProgram(); 2484 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 2485 } 2486 2487 if (!should_use_program_object) 2488 { 2489 run.fs_program_id = gl.createProgram(); 2490 run.tc_program_id = gl.createProgram(); 2491 run.te_program_id = gl.createProgram(); 2492 run.vs_program_id = gl.createProgram(); 2493 2494 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed"); 2495 } 2496 2497 /* Link program object(s) (and configure the pipeline object, if necessary) */ 2498 const glw::GLuint programs_for_pipeline_iteration[] = { run.fs_program_id, run.tc_program_id, run.te_program_id, 2499 run.vs_program_id }; 2500 const glw::GLuint programs_for_program_iteration[] = { run.po_id }; 2501 const unsigned int n_programs_for_pipeline_iteration = 2502 sizeof(programs_for_pipeline_iteration) / sizeof(programs_for_pipeline_iteration[0]); 2503 const unsigned int n_programs_for_program_iteration = 2504 sizeof(programs_for_program_iteration) / sizeof(programs_for_program_iteration[0]); 2505 2506 unsigned int n_programs = 0; 2507 const glw::GLuint* programs = DE_NULL; 2508 int xfb_pointsize_data_offset = -1; 2509 int xfb_position_data_offset = -1; 2510 int xfb_value1_data_offset = -1; 2511 int xfb_value2_data_offset = -1; 2512 int xfb_varyings_size = 0; 2513 2514 if (should_use_program_object) 2515 { 2516 n_programs = n_programs_for_program_iteration; 2517 programs = programs_for_program_iteration; 2518 } 2519 else 2520 { 2521 n_programs = n_programs_for_pipeline_iteration; 2522 programs = programs_for_pipeline_iteration; 2523 } 2524 2525 /* Attach and verify shader objects */ 2526 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 2527 { 2528 glw::GLuint parent_po_id = 0; 2529 glw::GLuint shader = shaders[n_shader]; 2530 2531 if (should_use_program_object) 2532 { 2533 gl.attachShader(run.po_id, shader); 2534 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed"); 2535 2536 parent_po_id = run.po_id; 2537 } 2538 else 2539 { 2540 if (shader == run.fs_id) 2541 { 2542 gl.attachShader(run.fs_program_id, run.fs_id); 2543 2544 parent_po_id = run.fs_program_id; 2545 } 2546 else if (shader == run.tc_id) 2547 { 2548 gl.attachShader(run.tc_program_id, run.tc_id); 2549 2550 parent_po_id = run.tc_program_id; 2551 } 2552 else if (shader == run.te_id) 2553 { 2554 gl.attachShader(run.te_program_id, run.te_id); 2555 2556 parent_po_id = run.te_program_id; 2557 } 2558 else 2559 { 2560 DE_ASSERT(shader == run.vs_id); 2561 2562 gl.attachShader(run.vs_program_id, run.vs_id); 2563 2564 parent_po_id = run.vs_program_id; 2565 } 2566 2567 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed"); 2568 } 2569 2570 /* Make sure the shader object we've attached is reported as a part 2571 * of the program object. 2572 */ 2573 unsigned int attached_shaders[n_shaders] = { 0 }; 2574 bool has_found_attached_shader = false; 2575 glw::GLsizei n_attached_shaders = 0; 2576 2577 memset(attached_shaders, 0, sizeof(attached_shaders)); 2578 2579 gl.getAttachedShaders(parent_po_id, n_shaders, &n_attached_shaders, attached_shaders); 2580 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttachedShaders() failed"); 2581 2582 for (glw::GLsizei n_attached_shader = 0; n_attached_shader < n_attached_shaders; n_attached_shader++) 2583 { 2584 if (attached_shaders[n_attached_shader] == shader) 2585 { 2586 has_found_attached_shader = true; 2587 2588 break; 2589 } 2590 } /* for (all attached shader object IDs) */ 2591 2592 if (!has_found_attached_shader) 2593 { 2594 TCU_FAIL("A shader object that was successfully attached to a program " 2595 "object was not reported as one by subsequent glGetAttachedShaders() " 2596 "call"); 2597 } 2598 } 2599 2600 /* Set up XFB */ 2601 const char* xfb_varyings_w_pointsize[] = { "te_position", "te_value1", "te_value2", "te_pointsize" }; 2602 const char* xfb_varyings_wo_pointsize[] = { 2603 "te_position", "te_value1", "te_value2", 2604 }; 2605 const char** xfb_varyings = DE_NULL; 2606 unsigned int n_xfb_varyings = 0; 2607 2608 if (run.point_mode) 2609 { 2610 xfb_varyings = xfb_varyings_w_pointsize; 2611 n_xfb_varyings = sizeof(xfb_varyings_w_pointsize) / sizeof(xfb_varyings_w_pointsize[0]); 2612 2613 xfb_position_data_offset = 0; 2614 xfb_value1_data_offset = 2615 static_cast<unsigned int>(xfb_position_data_offset + sizeof(float) * 4); /* size of te_position */ 2616 xfb_value2_data_offset = 2617 static_cast<unsigned int>(xfb_value1_data_offset + sizeof(float) * 2); /* size of te_value1 */ 2618 xfb_pointsize_data_offset = 2619 static_cast<unsigned int>(xfb_value2_data_offset + sizeof(int) * 4); /* size of te_value2 */ 2620 2621 xfb_varyings_size = sizeof(float) * 4 + /* size of te_position */ 2622 sizeof(float) * 2 + /* size of te_value1 */ 2623 sizeof(int) * 4 + /* size of te_value2 */ 2624 sizeof(int); /* size of te_pointsize */ 2625 } 2626 else 2627 { 2628 xfb_varyings = xfb_varyings_wo_pointsize; 2629 n_xfb_varyings = sizeof(xfb_varyings_wo_pointsize) / sizeof(xfb_varyings_wo_pointsize[0]); 2630 2631 xfb_position_data_offset = 0; 2632 xfb_value1_data_offset = 2633 static_cast<unsigned int>(xfb_position_data_offset + sizeof(float) * 4); /* size of te_position */ 2634 xfb_value2_data_offset = 2635 static_cast<unsigned int>(xfb_value1_data_offset + sizeof(float) * 2); /* size of te_value1 */ 2636 2637 xfb_varyings_size = sizeof(float) * 4 + /* size of te_position */ 2638 sizeof(float) * 2 + /* size of te_value1 */ 2639 sizeof(int) * 4; 2640 } 2641 2642 if (!should_use_program_object) 2643 { 2644 gl.transformFeedbackVaryings(run.te_program_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS); 2645 2646 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed"); 2647 } 2648 else 2649 { 2650 gl.transformFeedbackVaryings(run.po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS); 2651 2652 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed"); 2653 } 2654 2655 /* Mark all program objects as separable for pipeline run */ 2656 if (!should_use_program_object) 2657 { 2658 for (unsigned int n_program = 0; n_program < n_programs; ++n_program) 2659 { 2660 glw::GLuint program = programs[n_program]; 2661 2662 gl.programParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE); 2663 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() failed."); 2664 } 2665 } 2666 2667 /* Link the program object(s) */ 2668 for (unsigned int n_program = 0; n_program < n_programs; ++n_program) 2669 { 2670 glw::GLint link_status = GL_FALSE; 2671 glw::GLuint program = programs[n_program]; 2672 2673 gl.linkProgram(program); 2674 GLU_EXPECT_NO_ERROR(gl.getError(), "Program linking failed"); 2675 2676 gl.getProgramiv(program, GL_LINK_STATUS, &link_status); 2677 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed"); 2678 2679 if (link_status != GL_TRUE) 2680 { 2681 m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n" 2682 << getLinkingInfoLog(program) << tcu::TestLog::EndMessage; 2683 TCU_FAIL("Program linking failed"); 2684 } 2685 2686 /* Make sure glGetProgramiv() reports correct tessellation properties for 2687 * the program object we've just linked successfully */ 2688 if (program == run.po_id || program == run.tc_program_id || program == run.te_program_id) 2689 { 2690 glw::GLenum expected_tess_gen_mode_value = GL_NONE; 2691 glw::GLenum expected_tess_gen_spacing_value = GL_NONE; 2692 glw::GLenum expected_tess_gen_vertex_order_value = GL_NONE; 2693 glw::GLint tess_control_output_vertices_value = GL_NONE; 2694 glw::GLint tess_gen_mode_value = GL_NONE; 2695 glw::GLint tess_gen_point_mode_value = GL_NONE; 2696 glw::GLint tess_gen_spacing_value = GL_NONE; 2697 glw::GLint tess_gen_vertex_order_value = GL_NONE; 2698 2699 switch (run.primitive_mode) 2700 { 2701 case TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES: 2702 expected_tess_gen_mode_value = m_glExtTokens.ISOLINES; 2703 break; 2704 case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS: 2705 expected_tess_gen_mode_value = m_glExtTokens.QUADS; 2706 break; 2707 case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES: 2708 expected_tess_gen_mode_value = GL_TRIANGLES; 2709 break; 2710 2711 default: 2712 { 2713 /* Unrecognized primitive mode? */ 2714 DE_ASSERT(false); 2715 } 2716 } /* switch (run.primitive_mode) */ 2717 2718 switch (run.vertex_spacing) 2719 { 2720 case TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT: 2721 case TESSELLATION_SHADER_VERTEX_SPACING_EQUAL: 2722 expected_tess_gen_spacing_value = GL_EQUAL; 2723 break; 2724 case TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN: 2725 expected_tess_gen_spacing_value = m_glExtTokens.FRACTIONAL_EVEN; 2726 break; 2727 case TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD: 2728 expected_tess_gen_spacing_value = m_glExtTokens.FRACTIONAL_ODD; 2729 break; 2730 2731 default: 2732 { 2733 /* Unrecognized vertex spacing mode? */ 2734 DE_ASSERT(false); 2735 } 2736 } /* switch (run.vertex_spacing) */ 2737 2738 switch (run.vertex_ordering) 2739 { 2740 case TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT: 2741 case TESSELLATION_SHADER_VERTEX_ORDERING_CCW: 2742 expected_tess_gen_vertex_order_value = GL_CCW; 2743 break; 2744 case TESSELLATION_SHADER_VERTEX_ORDERING_CW: 2745 expected_tess_gen_vertex_order_value = GL_CW; 2746 break; 2747 2748 default: 2749 { 2750 /* Unrecognized vertex ordering mode? */ 2751 DE_ASSERT(false); 2752 } 2753 } /* switch (run.vertex_ordering) */ 2754 2755 if (program == run.po_id || program == run.tc_program_id) 2756 { 2757 gl.getProgramiv(program, m_glExtTokens.TESS_CONTROL_OUTPUT_VERTICES, 2758 &tess_control_output_vertices_value); 2759 GLU_EXPECT_NO_ERROR(gl.getError(), 2760 "glGetProgramiv() failed for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT pname"); 2761 2762 if (tess_control_output_vertices_value != m_gl_max_patch_vertices_value) 2763 { 2764 TCU_FAIL( 2765 "Invalid value returned by glGetProgramiv() for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT query"); 2766 } 2767 } 2768 2769 if (program == run.po_id || program == run.te_program_id) 2770 { 2771 gl.getProgramiv(program, m_glExtTokens.TESS_GEN_MODE, &tess_gen_mode_value); 2772 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_MODE_EXT pname"); 2773 2774 if ((glw::GLuint)tess_gen_mode_value != expected_tess_gen_mode_value) 2775 { 2776 TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_MODE_EXT query"); 2777 } 2778 } 2779 2780 if (program == run.po_id || program == run.te_program_id) 2781 { 2782 gl.getProgramiv(program, m_glExtTokens.TESS_GEN_SPACING, &tess_gen_spacing_value); 2783 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_SPACING_EXT pname"); 2784 2785 if ((glw::GLuint)tess_gen_spacing_value != expected_tess_gen_spacing_value) 2786 { 2787 TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_SPACING_EXT query"); 2788 } 2789 } 2790 2791 if (program == run.po_id || program == run.te_program_id) 2792 { 2793 gl.getProgramiv(program, m_glExtTokens.TESS_GEN_VERTEX_ORDER, &tess_gen_vertex_order_value); 2794 GLU_EXPECT_NO_ERROR(gl.getError(), 2795 "glGetProgramiv() failed for GL_TESS_GEN_VERTEX_ORDER_EXT pname"); 2796 2797 if ((glw::GLuint)tess_gen_vertex_order_value != expected_tess_gen_vertex_order_value) 2798 { 2799 TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_VERTEX_ORDER_EXT query"); 2800 } 2801 } 2802 2803 if (program == run.po_id || program == run.te_program_id) 2804 { 2805 gl.getProgramiv(program, m_glExtTokens.TESS_GEN_POINT_MODE, &tess_gen_point_mode_value); 2806 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_POINT_MODE_EXT pname"); 2807 2808 if (tess_gen_point_mode_value != ((run.point_mode) ? GL_TRUE : GL_FALSE)) 2809 { 2810 TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_POINT_MODE_EXT query"); 2811 } 2812 } 2813 } /* if (program == run.po_id || program == run.tc_program_id || program == run.te_program_id) */ 2814 } /* for (all considered program objects) */ 2815 2816 if (!should_use_program_object) 2817 { 2818 /* Attach all stages to the pipeline object */ 2819 gl.useProgramStages(run.pipeline_object_id, GL_FRAGMENT_SHADER_BIT, run.fs_program_id); 2820 gl.useProgramStages(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER_BIT, run.tc_program_id); 2821 gl.useProgramStages(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER_BIT, run.te_program_id); 2822 gl.useProgramStages(run.pipeline_object_id, GL_VERTEX_SHADER_BIT, run.vs_program_id); 2823 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed"); 2824 2825 /* Make sure the pipeline object validates correctly */ 2826 glw::GLint validate_status = GL_FALSE; 2827 2828 gl.validateProgramPipeline(run.pipeline_object_id); 2829 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed"); 2830 2831 gl.getProgramPipelineiv(run.pipeline_object_id, GL_VALIDATE_STATUS, &validate_status); 2832 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed"); 2833 2834 if (validate_status != GL_TRUE) 2835 { 2836 m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n" 2837 << getPipelineInfoLog(run.pipeline_object_id) << "\n\nVertex Shader:\n" 2838 << vs_code_raw_ptr << "\n\nTessellation Control Shader:\n" 2839 << tc_code_raw_ptr << "\n\nTessellation Evaluation Shader:\n" 2840 << te_code_raw_ptr << "\n\nFragment Shader:\n" 2841 << fs_code_raw_ptr << tcu::TestLog::EndMessage; 2842 TCU_FAIL("Pipeline object was found to be invalid"); 2843 } 2844 } 2845 2846 /* Determine how many vertices are going to be generated by the tessellator 2847 * for particular tessellation configuration. 2848 */ 2849 unsigned int n_vertices_generated = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 2850 run.primitive_mode, run.inner, run.outer, run.vertex_spacing, run.point_mode); 2851 2852 /* Allocate enough space to hold the result XFB data */ 2853 const unsigned int bo_size = xfb_varyings_size * n_vertices_generated; 2854 2855 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW); 2856 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed"); 2857 2858 /* Use the pipeline or program object and render the data */ 2859 glw::GLenum tf_mode = TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, run.point_mode); 2860 2861 if (should_use_program_object) 2862 { 2863 gl.bindProgramPipeline(0); 2864 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed"); 2865 2866 gl.useProgram(run.po_id); 2867 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 2868 } 2869 else 2870 { 2871 gl.bindProgramPipeline(run.pipeline_object_id); 2872 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed"); 2873 2874 gl.useProgram(0); 2875 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 2876 } 2877 2878 gl.beginTransformFeedback(tf_mode); 2879 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed"); 2880 { 2881 gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* count */); 2882 2883 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed"); 2884 } 2885 gl.endTransformFeedback(); 2886 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed"); 2887 2888 /* Map the buffer object contents into process space */ 2889 const char* xfb_data = (const char*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 2890 bo_size, GL_MAP_READ_BIT); 2891 2892 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed"); 2893 2894 /* Iterate through all vertices and extract all captured data. To reduce amount 2895 * of time necessary to verify the generated data, only store *unique* values. 2896 */ 2897 for (unsigned int n_vertex = 0; n_vertex < n_vertices_generated; ++n_vertex) 2898 { 2899 if (xfb_pointsize_data_offset != -1) 2900 { 2901 const float* data_ptr = 2902 (const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_pointsize_data_offset); 2903 2904 if (std::find(run.result_pointsize_data.begin(), run.result_pointsize_data.end(), *data_ptr) == 2905 run.result_pointsize_data.end()) 2906 { 2907 run.result_pointsize_data.push_back(*data_ptr); 2908 } 2909 } 2910 2911 if (xfb_position_data_offset != -1) 2912 { 2913 const float* data_ptr = 2914 (const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_position_data_offset); 2915 _vec4 new_item = _vec4(data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]); 2916 2917 if (std::find(run.result_position_data.begin(), run.result_position_data.end(), new_item) == 2918 run.result_position_data.end()) 2919 { 2920 run.result_position_data.push_back(new_item); 2921 } 2922 } 2923 2924 if (xfb_value1_data_offset != -1) 2925 { 2926 const float* data_ptr = 2927 (const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_value1_data_offset); 2928 _vec2 new_item = _vec2(data_ptr[0], data_ptr[1]); 2929 2930 if (std::find(run.result_value1_data.begin(), run.result_value1_data.end(), new_item) == 2931 run.result_value1_data.end()) 2932 { 2933 run.result_value1_data.push_back(new_item); 2934 } 2935 } 2936 2937 if (xfb_value2_data_offset != -1) 2938 { 2939 const int* data_ptr = (const int*)(xfb_data + xfb_varyings_size * n_vertex + xfb_value2_data_offset); 2940 _ivec4 new_item = _ivec4(data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]); 2941 2942 if (std::find(run.result_value2_data.begin(), run.result_value2_data.end(), new_item) == 2943 run.result_value2_data.end()) 2944 { 2945 run.result_value2_data.push_back(new_item); 2946 } 2947 } 2948 } /* for (all result tessellation coordinates) */ 2949 2950 /* Good to unmap the buffer object at this point */ 2951 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 2952 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed"); 2953 } /* for (two iterations) */ 2954 } 2955 2956 /** Executes the test. 2957 * 2958 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 2959 * 2960 * Note the function throws exception should an error occur! 2961 * 2962 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 2963 **/ 2964 tcu::TestNode::IterateResult TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::iterate(void) 2965 { 2966 /* Initialize ES test objects */ 2967 initTest(); 2968 2969 /* Calculate reference values that should be generated for all runs */ 2970 float reference_result_pointsize(0); 2971 _vec4 reference_result_position(0, 0, 0, 0); 2972 _vec2 reference_result_value1(0, 0); 2973 _ivec4 reference_result_value2(0, 0, 0, 0); 2974 const float epsilon = (float)1e-5; 2975 2976 for (glw::GLint n_invocation = 0; n_invocation < m_gl_max_patch_vertices_value; ++n_invocation) 2977 { 2978 /* As per TC and TE shaders */ 2979 reference_result_pointsize += 1.0f / static_cast<float>(n_invocation + 1); 2980 2981 reference_result_position.x += static_cast<float>(n_invocation * 4 + 0); 2982 reference_result_position.y += static_cast<float>(n_invocation * 4 + 1); 2983 reference_result_position.z += static_cast<float>(n_invocation * 4 + 2); 2984 reference_result_position.w += static_cast<float>(n_invocation * 4 + 3); 2985 2986 reference_result_value1.x += 1.0f / static_cast<float>(n_invocation + 1); 2987 reference_result_value1.y += 1.0f / static_cast<float>(n_invocation + 2); 2988 2989 reference_result_value2.x += (n_invocation + 1); 2990 reference_result_value2.y += (n_invocation + 2); 2991 reference_result_value2.z += (n_invocation + 3); 2992 reference_result_value2.w += (n_invocation + 4); 2993 } 2994 2995 /* Iterate through test runs and analyse the result data */ 2996 for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++) 2997 { 2998 const _run& run = *run_iterator; 2999 3000 /* For the very first run, make sure that the type of tessellation shader objects 3001 * is reported correctly for both program and pipeline object cases. 3002 */ 3003 if (run_iterator == m_runs.begin()) 3004 { 3005 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3006 glw::GLint shader_type_tc = GL_NONE; 3007 glw::GLint shader_type_te = GL_NONE; 3008 3009 /* Program objects first */ 3010 gl.getShaderiv(run.tc_id, GL_SHADER_TYPE, &shader_type_tc); 3011 gl.getShaderiv(run.te_id, GL_SHADER_TYPE, &shader_type_te); 3012 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call(s) failed"); 3013 3014 if ((glw::GLenum)shader_type_tc != m_glExtTokens.TESS_CONTROL_SHADER) 3015 { 3016 TCU_FAIL("Invalid shader type reported by glGetShaderiv() for a tessellation control shader"); 3017 } 3018 3019 if ((glw::GLenum)shader_type_te != m_glExtTokens.TESS_EVALUATION_SHADER) 3020 { 3021 TCU_FAIL("Invalid shader type reported by glGetShaderiv() for a tessellation evaluation shader"); 3022 } 3023 3024 /* Let's query the pipeline object now */ 3025 glw::GLint shader_id_tc = 0; 3026 glw::GLint shader_id_te = 0; 3027 3028 gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER, &shader_id_tc); 3029 gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER, &shader_id_te); 3030 3031 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() failed for GL_TESS_CONTROL_SHADER_EXT / " 3032 "GL_TESS_EVALUATION_SHADER_EXT enum(s)"); 3033 3034 if ((glw::GLuint)shader_id_tc != run.tc_program_id) 3035 { 3036 TCU_FAIL("Invalid separate program object ID reported for Tessellation Control stage"); 3037 } 3038 3039 if ((glw::GLuint)shader_id_te != run.te_program_id) 3040 { 3041 TCU_FAIL("Invalid separate program object ID reported for Tessellation Evaluation stage"); 3042 } 3043 } 3044 3045 if ((run.point_mode && run.result_pointsize_data.size() != 1) || 3046 (run.point_mode && de::abs(run.result_pointsize_data[0] - reference_result_pointsize) > epsilon)) 3047 { 3048 /* It is a test bug if result_pointsize_data.size() == 0 */ 3049 DE_ASSERT(run.result_pointsize_data.size() > 0); 3050 3051 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set gl_PointSize value to " 3052 << run.result_pointsize_data[0] << " instead of expected value " 3053 << reference_result_pointsize << tcu::TestLog::EndMessage; 3054 3055 TCU_FAIL("Invalid gl_PointSize data exposed in TE stage"); 3056 } 3057 3058 if (run.result_position_data.size() != 1 || run.result_position_data[0] != reference_result_position) 3059 { 3060 /* It is a test bug if result_position_data.size() == 0 */ 3061 DE_ASSERT(run.result_position_data.size() > 0); 3062 3063 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set gl_Position to " 3064 << " (" << run.result_position_data[0].x << ", " << run.result_position_data[0].y << ", " 3065 << run.result_position_data[0].z << ", " << run.result_position_data[0].w 3066 << " ) instead of expected value" 3067 " (" 3068 << reference_result_position.x << ", " << reference_result_position.y << ", " 3069 << reference_result_position.z << ", " << reference_result_position.w << ")" 3070 << tcu::TestLog::EndMessage; 3071 3072 TCU_FAIL("Invalid gl_Position data exposed in TE stage"); 3073 } 3074 3075 if (run.result_value1_data.size() != 1 || 3076 de::abs(run.result_value1_data[0].x - reference_result_value1.x) > epsilon || 3077 de::abs(run.result_value1_data[0].y - reference_result_value1.y) > epsilon) 3078 { 3079 /* It is a test bug if result_value1_data.size() == 0 */ 3080 DE_ASSERT(run.result_value1_data.size() > 0); 3081 3082 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set te_value1 to " 3083 << " (" << run.result_value1_data[0].x << ", " << run.result_value1_data[0].y 3084 << " ) instead of expected value" 3085 " (" 3086 << reference_result_value1.x << ", " << reference_result_value1.y << ")" 3087 << tcu::TestLog::EndMessage; 3088 3089 TCU_FAIL("Invalid gl_Position data exposed in TE stage"); 3090 } 3091 3092 if (run.result_value2_data.size() != 1 || run.result_value2_data[0] != reference_result_value2) 3093 { 3094 /* It is a test bug if result_value2_data.size() == 0 */ 3095 DE_ASSERT(run.result_value2_data.size() > 0); 3096 3097 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set te_value2 to " 3098 << " (" << run.result_value2_data[0].x << ", " << run.result_value2_data[0].y << ", " 3099 << run.result_value2_data[0].z << ", " << run.result_value2_data[0].w 3100 << " ) instead of expected value" 3101 " (" 3102 << reference_result_value2.x << ", " << reference_result_value2.y << ", " 3103 << reference_result_value2.z << ", " << reference_result_value2.w << ")" 3104 << tcu::TestLog::EndMessage; 3105 3106 TCU_FAIL("Invalid value2 data saved in TE stage"); 3107 } 3108 } /* for (all runs) */ 3109 3110 /* All done */ 3111 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3112 return STOP; 3113 } 3114 3115 /** Constructor 3116 * 3117 * @param context Test context 3118 **/ 3119 TessellationShaderTCTEgl_TessLevel::TessellationShaderTCTEgl_TessLevel(Context& context, const ExtParameters& extParams) 3120 : TestCaseBase(context, extParams, "gl_tessLevel", 3121 "Verifies gl_TessLevelOuter and gl_TessLevelInner patch variable " 3122 "values in a tessellation evaluation shader are valid and correspond" 3123 "to values configured in a tessellation control shader (should one be " 3124 "present) or to the default values, as set with glPatchParameterfv() calls") 3125 , m_gl_max_tess_gen_level_value(0) 3126 , m_bo_id(0) 3127 , m_vao_id(0) 3128 { 3129 /* Left blank on purpose */ 3130 } 3131 3132 /** Deinitializes all ES objects created for the test. */ 3133 void TessellationShaderTCTEgl_TessLevel::deinit() 3134 { 3135 /** Call base class' deinit() function */ 3136 TestCaseBase::deinit(); 3137 3138 if (!m_is_tessellation_shader_supported) 3139 { 3140 return; 3141 } 3142 3143 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3144 3145 /* Reset TF buffer object bindings */ 3146 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 3147 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 3148 3149 /* Reset GL_PATCH_VERTICES_EXT value to the default setting */ 3150 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 3151 3152 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 3153 { 3154 /* Revert GL_PATCH_DEFAULT_INNER_LEVEL and GL_PATCH_DEFAULT_OUTER_LEVEL pname 3155 * values to the default settings */ 3156 const float default_levels[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 3157 gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, default_levels); 3158 gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, default_levels); 3159 } 3160 3161 /* Disable GL_RASTERIZER_DISCARD mode */ 3162 gl.disable(GL_RASTERIZER_DISCARD); 3163 3164 /* Unbind vertex array object */ 3165 gl.bindVertexArray(0); 3166 3167 /* Release all objects we might've created */ 3168 if (m_bo_id != 0) 3169 { 3170 gl.deleteBuffers(1, &m_bo_id); 3171 3172 m_bo_id = 0; 3173 } 3174 3175 if (m_vao_id != 0) 3176 { 3177 gl.deleteVertexArrays(1, &m_vao_id); 3178 3179 m_vao_id = 0; 3180 } 3181 3182 for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it) 3183 { 3184 deinitTestDescriptor(&*it); 3185 } 3186 m_tests.clear(); 3187 } 3188 3189 /** Deinitializes ES objects created for particular test pass. 3190 * 3191 * @param test_ptr Test run descriptor. Must not be NULL. 3192 * 3193 **/ 3194 void TessellationShaderTCTEgl_TessLevel::deinitTestDescriptor(_test_descriptor* test_ptr) 3195 { 3196 /* Call base class' deinit() */ 3197 TestCaseBase::deinit(); 3198 3199 /* Release all objects */ 3200 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3201 3202 if (test_ptr->fs_id != 0) 3203 { 3204 gl.deleteShader(test_ptr->fs_id); 3205 3206 test_ptr->fs_id = 0; 3207 } 3208 3209 if (test_ptr->po_id != 0) 3210 { 3211 gl.deleteProgram(test_ptr->po_id); 3212 3213 test_ptr->po_id = 0; 3214 } 3215 3216 if (test_ptr->tcs_id != 0) 3217 { 3218 gl.deleteShader(test_ptr->tcs_id); 3219 3220 test_ptr->tcs_id = 0; 3221 } 3222 3223 if (test_ptr->tes_id != 0) 3224 { 3225 gl.deleteShader(test_ptr->tes_id); 3226 3227 test_ptr->tes_id = 0; 3228 } 3229 3230 if (test_ptr->vs_id != 0) 3231 { 3232 gl.deleteShader(test_ptr->vs_id); 3233 3234 test_ptr->vs_id = 0; 3235 } 3236 } 3237 3238 /** Initializes all ES objects that will be used for the test. */ 3239 void TessellationShaderTCTEgl_TessLevel::initTest() 3240 { 3241 /* The test requires EXT_tessellation_shader */ 3242 if (!m_is_tessellation_shader_supported) 3243 { 3244 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 3245 } 3246 3247 /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value before we carry on */ 3248 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3249 3250 /* Initialize vertex array object */ 3251 gl.genVertexArrays(1, &m_vao_id); 3252 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 3253 3254 gl.bindVertexArray(m_vao_id); 3255 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 3256 3257 /* Retrieve gen level */ 3258 gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &m_gl_max_tess_gen_level_value); 3259 3260 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() for GL_MAX_TESS_GEN_LEVEL_EXT pname failed"); 3261 3262 /* Initialize test descriptors */ 3263 _test_descriptor test_tcs_tes_equal; 3264 _test_descriptor test_tcs_tes_fe; 3265 _test_descriptor test_tcs_tes_fo; 3266 _test_descriptor test_tes_equal; 3267 _test_descriptor test_tes_fe; 3268 _test_descriptor test_tes_fo; 3269 3270 initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_equal, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL); 3271 initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_fe, 3272 TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN); 3273 initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_fo, 3274 TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD); 3275 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 3276 { 3277 initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_equal, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL); 3278 initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_fe, 3279 TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN); 3280 initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_fo, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD); 3281 } 3282 3283 m_tests.push_back(test_tcs_tes_equal); 3284 m_tests.push_back(test_tcs_tes_fe); 3285 m_tests.push_back(test_tcs_tes_fo); 3286 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 3287 { 3288 m_tests.push_back(test_tes_equal); 3289 m_tests.push_back(test_tes_fe); 3290 m_tests.push_back(test_tes_fo); 3291 } 3292 3293 /* Generate and set up a buffer object we will use to hold XFBed data. 3294 * 3295 * NOTE: We do not set the buffer object's storage here because its size 3296 * is iteration-specific. 3297 **/ 3298 gl.genBuffers(1, &m_bo_id); 3299 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed"); 3300 3301 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 3302 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed"); 3303 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 3304 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed"); 3305 3306 /* We're good to execute the test! */ 3307 } 3308 3309 /** Initializes ES objects for a particular tess pass. 3310 * 3311 * @param test_type Determines test type to be used for initialization. 3312 * TEST_TYPE_TCS_TES will use both TC and TE stages, 3313 * TEST_TYPE_TES will assume only TE stage should be used. 3314 * @param out_test_ptr Deref will be used to store object data. Must not be NULL. 3315 * @param vertex_spacing_mode Vertex spacing mode to use for the TE stage. 3316 * 3317 **/ 3318 void TessellationShaderTCTEgl_TessLevel::initTestDescriptor(_tessellation_test_type test_type, 3319 _test_descriptor* out_test_ptr, 3320 _tessellation_shader_vertex_spacing vertex_spacing_mode) 3321 { 3322 out_test_ptr->type = test_type; 3323 out_test_ptr->vertex_spacing = vertex_spacing_mode; 3324 3325 /* Generate a program object we will later configure */ 3326 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3327 3328 out_test_ptr->po_id = gl.createProgram(); 3329 3330 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 3331 3332 /* Generate shader objects the test will use */ 3333 out_test_ptr->fs_id = gl.createShader(GL_FRAGMENT_SHADER); 3334 out_test_ptr->vs_id = gl.createShader(GL_VERTEX_SHADER); 3335 3336 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES) 3337 { 3338 out_test_ptr->tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 3339 } 3340 3341 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES) 3342 { 3343 out_test_ptr->tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 3344 } 3345 3346 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 3347 3348 /* Configure fragment shader */ 3349 const char* fs_body = "${VERSION}\n" 3350 "\n" 3351 "void main()\n" 3352 "{\n" 3353 "}\n"; 3354 3355 shaderSourceSpecialized(out_test_ptr->fs_id, 1 /* count */, &fs_body); 3356 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object"); 3357 3358 /* Configure tessellation control shader */ 3359 const char* tc_body = "${VERSION}\n" 3360 "\n" 3361 /* Required EXT_tessellation_shader functionality */ 3362 "${TESSELLATION_SHADER_REQUIRE}\n" 3363 "\n" 3364 "layout (vertices = 4) out;\n" 3365 "\n" 3366 "uniform vec2 inner_tess_levels;\n" 3367 "uniform vec4 outer_tess_levels;\n" 3368 "\n" 3369 "void main()\n" 3370 "{\n" 3371 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 3372 " if (gl_InvocationID == 0) {\n" 3373 " gl_TessLevelInner[0] = inner_tess_levels[0];\n" 3374 " gl_TessLevelInner[1] = inner_tess_levels[1];\n" 3375 " gl_TessLevelOuter[0] = outer_tess_levels[0];\n" 3376 " gl_TessLevelOuter[1] = outer_tess_levels[1];\n" 3377 " gl_TessLevelOuter[2] = outer_tess_levels[2];\n" 3378 " gl_TessLevelOuter[3] = outer_tess_levels[3];\n" 3379 " }\n" 3380 "}\n"; 3381 3382 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES) 3383 { 3384 shaderSourceSpecialized(out_test_ptr->tcs_id, 1 /* count */, &tc_body); 3385 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object"); 3386 } 3387 3388 /* Configure tessellation evaluation shader */ 3389 const char* te_body = "${VERSION}\n" 3390 "\n" 3391 "${TESSELLATION_SHADER_REQUIRE}\n" 3392 "\n" 3393 "layout (quads, point_mode, VERTEX_SPACING_MODE) in;\n" 3394 "\n" 3395 "out vec2 result_tess_level_inner;\n" 3396 "out vec4 result_tess_level_outer;\n" 3397 "\n" 3398 "void main()\n" 3399 "{\n" 3400 " vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n" 3401 " vec4 p2 = mix(gl_in[2].gl_Position,gl_in[3].gl_Position,gl_TessCoord.x);\n" 3402 " gl_Position = mix(p1, p2, gl_TessCoord.y);\n" 3403 "\n" 3404 " result_tess_level_inner = vec2(gl_TessLevelInner[0],\n" 3405 " gl_TessLevelInner[1]);\n" 3406 " result_tess_level_outer = vec4(gl_TessLevelOuter[0],\n" 3407 " gl_TessLevelOuter[1],\n" 3408 " gl_TessLevelOuter[2],\n" 3409 " gl_TessLevelOuter[3]);\n" 3410 "}\n"; 3411 3412 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES) 3413 { 3414 /* Replace VERTEX_SPACING_MODE with the mode provided by the caller */ 3415 std::stringstream te_body_stringstream; 3416 std::string te_body_string; 3417 const std::string token = "VERTEX_SPACING_MODE"; 3418 std::size_t token_index; 3419 std::string vertex_spacing_string = 3420 TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing_mode); 3421 3422 te_body_stringstream << te_body; 3423 te_body_string = te_body_stringstream.str(); 3424 3425 token_index = te_body_string.find(token); 3426 3427 while (token_index != std::string::npos) 3428 { 3429 te_body_string = te_body_string.replace(token_index, token.length(), vertex_spacing_string.c_str()); 3430 3431 token_index = te_body_string.find(token); 3432 } 3433 3434 /* Set the shader source */ 3435 const char* te_body_string_raw = te_body_string.c_str(); 3436 3437 shaderSourceSpecialized(out_test_ptr->tes_id, 1 /* count */, &te_body_string_raw); 3438 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object"); 3439 } 3440 3441 /* Configure vertex shader */ 3442 const char* vs_body = "${VERSION}\n" 3443 "\n" 3444 "void main()\n" 3445 "{\n" 3446 " gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n" 3447 "}\n"; 3448 3449 shaderSourceSpecialized(out_test_ptr->vs_id, 1 /* count */, &vs_body); 3450 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object"); 3451 3452 /* Compile all shaders of our interest */ 3453 const glw::GLuint shaders[] = { out_test_ptr->fs_id, out_test_ptr->tcs_id, out_test_ptr->tes_id, 3454 out_test_ptr->vs_id }; 3455 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 3456 3457 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 3458 { 3459 glw::GLint compile_status = GL_FALSE; 3460 glw::GLuint shader = shaders[n_shader]; 3461 3462 if (shader != 0) 3463 { 3464 gl.compileShader(shader); 3465 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 3466 3467 gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); 3468 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 3469 3470 if (compile_status != GL_TRUE) 3471 { 3472 m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader 3473 << " failed." << tcu::TestLog::EndMessage; 3474 3475 TCU_FAIL("Shader compilation failed"); 3476 } 3477 } /* if (shader != 0) */ 3478 } /* for (all shaders) */ 3479 3480 /* Attach the shaders to the test program object, set up XFB and then link the program */ 3481 glw::GLint link_status = GL_FALSE; 3482 const char* varyings[] = { "result_tess_level_inner", "result_tess_level_outer" }; 3483 const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]); 3484 3485 gl.transformFeedbackVaryings(out_test_ptr->po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS); 3486 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed"); 3487 3488 gl.attachShader(out_test_ptr->po_id, out_test_ptr->fs_id); 3489 gl.attachShader(out_test_ptr->po_id, out_test_ptr->vs_id); 3490 3491 if (out_test_ptr->tcs_id != 0) 3492 { 3493 gl.attachShader(out_test_ptr->po_id, out_test_ptr->tcs_id); 3494 } 3495 3496 if (out_test_ptr->tes_id != 0) 3497 { 3498 gl.attachShader(out_test_ptr->po_id, out_test_ptr->tes_id); 3499 } 3500 3501 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 3502 3503 gl.linkProgram(out_test_ptr->po_id); 3504 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 3505 3506 gl.getProgramiv(out_test_ptr->po_id, GL_LINK_STATUS, &link_status); 3507 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 3508 3509 if (link_status != GL_TRUE) 3510 { 3511 TCU_FAIL("Program linking failed"); 3512 } 3513 3514 /* Retrieve uniform locations */ 3515 out_test_ptr->inner_tess_levels_uniform_location = gl.getUniformLocation(out_test_ptr->po_id, "inner_tess_levels"); 3516 out_test_ptr->outer_tess_levels_uniform_location = gl.getUniformLocation(out_test_ptr->po_id, "outer_tess_levels"); 3517 3518 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed"); 3519 3520 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES) 3521 { 3522 DE_ASSERT(out_test_ptr->inner_tess_levels_uniform_location != -1); 3523 DE_ASSERT(out_test_ptr->outer_tess_levels_uniform_location != -1); 3524 } 3525 } 3526 3527 /** Executes the test. 3528 * 3529 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 3530 * 3531 * Note the function throws exception should an error occur! 3532 * 3533 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 3534 **/ 3535 tcu::TestNode::IterateResult TessellationShaderTCTEgl_TessLevel::iterate(void) 3536 { 3537 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3538 3539 /* Initialize ES test objects */ 3540 initTest(); 3541 3542 /* Our program object takes a single quad per patch */ 3543 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 4); 3544 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed"); 3545 3546 /* Prepare for rendering */ 3547 gl.enable(GL_RASTERIZER_DISCARD); 3548 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed."); 3549 3550 /* We will iterate through all added tests. */ 3551 for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); ++test_iterator) 3552 { 3553 /* Iterate through a few different inner/outer tessellation level combinations */ 3554 glw::GLfloat tessellation_level_combinations[] = { 3555 /* inner[0] */ /* inner[1] */ /* outer[0] */ /* outer[1] */ /* outer[2] */ /* outer[3] */ 3556 1.1f, 1.4f, 2.7f, 3.1f, 4.4f, 5.7f, 64.2f, 32.5f, 16.8f, 8.2f, 4.5f, 2.8f, 3.3f, 6.6f, 9.9f, 12.3f, 15.6f, 3557 18.9f 3558 }; 3559 const unsigned int n_tessellation_level_combinations = sizeof(tessellation_level_combinations) / 3560 sizeof(tessellation_level_combinations[0]) / 3561 6; /* 2 inner + 4 outer levels */ 3562 3563 for (unsigned int n_combination = 0; n_combination < n_tessellation_level_combinations; ++n_combination) 3564 { 3565 glw::GLfloat inner_tess_level[] = { tessellation_level_combinations[n_combination * 6 + 0], 3566 tessellation_level_combinations[n_combination * 6 + 1] }; 3567 3568 glw::GLfloat outer_tess_level[] = { tessellation_level_combinations[n_combination * 6 + 2], 3569 tessellation_level_combinations[n_combination * 6 + 3], 3570 tessellation_level_combinations[n_combination * 6 + 4], 3571 tessellation_level_combinations[n_combination * 6 + 5] }; 3572 3573 TessellationShaderUtils tessUtils(gl, this); 3574 const unsigned int n_rendered_vertices = tessUtils.getAmountOfVerticesGeneratedByTessellator( 3575 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, inner_tess_level, outer_tess_level, 3576 test_iterator->vertex_spacing, true); /* is_point_mode_enabled */ 3577 3578 /* Test type determines how the tessellation levels should be set. */ 3579 gl.useProgram(test_iterator->po_id); 3580 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 3581 3582 switch (test_iterator->type) 3583 { 3584 case TESSELLATION_TEST_TYPE_TCS_TES: 3585 { 3586 gl.uniform2fv(test_iterator->inner_tess_levels_uniform_location, 1, /* count */ 3587 inner_tess_level); 3588 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2fv() call failed"); 3589 3590 gl.uniform4fv(test_iterator->outer_tess_levels_uniform_location, 1, /* count */ 3591 outer_tess_level); 3592 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed"); 3593 3594 break; 3595 } 3596 3597 case TESSELLATION_TEST_TYPE_TES: 3598 { 3599 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 3600 { 3601 gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, inner_tess_level); 3602 3603 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() call failed for" 3604 " GL_PATCH_DEFAULT_INNER_LEVEL pname"); 3605 3606 gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, outer_tess_level); 3607 3608 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() call failed for" 3609 " GL_PATCH_DEFAULT_OUTER_LEVEL pname"); 3610 } 3611 break; 3612 } 3613 3614 default: 3615 { 3616 TCU_FAIL("Unrecognized test type"); 3617 } 3618 } /* switch (test_iterator->type) */ 3619 3620 /* Set up storage properties for the buffer object, to which XFBed data will be 3621 * written. 3622 */ 3623 const unsigned int n_bytes_needed = 3624 static_cast<unsigned int>(n_rendered_vertices * (2 /* vec2 */ + 4 /* vec4 */) * sizeof(float)); 3625 3626 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL /* data */, GL_STATIC_DRAW); 3627 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed"); 3628 3629 /* Render the test geometry */ 3630 gl.beginTransformFeedback(GL_POINTS); 3631 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed"); 3632 { 3633 /* A single vertex will do, since we configured GL_PATCH_VERTICES_EXT to be 1 */ 3634 gl.drawArrays(GL_PATCHES_EXT, 0 /* first */, 4 /* count */); 3635 3636 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed"); 3637 } 3638 gl.endTransformFeedback(); 3639 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed"); 3640 3641 /* Now that the BO is filled with data, map it so we can check the storage's contents */ 3642 const float* mapped_data_ptr = (const float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 3643 n_bytes_needed, GL_MAP_READ_BIT); 3644 3645 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 3646 3647 /* Verify the contents. For each result vertex, inner/outer tessellation levels should 3648 * be unchanged. */ 3649 const float epsilon = (float)1e-5; 3650 const unsigned int n_result_points = 3651 static_cast<unsigned int>(n_bytes_needed / sizeof(float) / (2 /* vec2 */ + 4 /* vec4 */)); 3652 3653 for (unsigned int n_point = 0; n_point < n_result_points; ++n_point) 3654 { 3655 const float* point_data_ptr = mapped_data_ptr + (2 /* vec2 */ + 4 /* vec4 */) * n_point; 3656 3657 if (de::abs(point_data_ptr[2] - outer_tess_level[0]) > epsilon || 3658 de::abs(point_data_ptr[3] - outer_tess_level[1]) > epsilon) 3659 { 3660 std::string vertex_spacing_mode_string = 3661 TessellationShaderUtils::getESTokenForVertexSpacingMode(test_iterator->vertex_spacing); 3662 3663 m_testCtx.getLog() << tcu::TestLog::Message 3664 << "Invalid inner/outer tessellation level used in TE stage;" 3665 << " expected outer:(" << outer_tess_level[0] << ", " << outer_tess_level[1] 3666 << ") " 3667 << " rendered outer:(" << point_data_ptr[2] << ", " << point_data_ptr[3] << ")" 3668 << " vertex spacing mode: " << vertex_spacing_mode_string.c_str() 3669 << tcu::TestLog::EndMessage; 3670 3671 TCU_FAIL("Invalid inner/outer tessellation level used in TE stage"); 3672 } 3673 } /* for (all points) */ 3674 3675 /* All done - unmap the storage */ 3676 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3677 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 3678 } /* for (all tess level combinations) */ 3679 } /* for (all tests) */ 3680 3681 /* All done */ 3682 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3683 return STOP; 3684 } 3685 3686 /** Constructor 3687 * 3688 * @param context Test context 3689 **/ 3690 TessellationShaderTCTEgl_PatchVerticesIn::TessellationShaderTCTEgl_PatchVerticesIn(Context& context, 3691 const ExtParameters& extParams) 3692 : TestCaseBase(context, extParams, "gl_PatchVerticesIn", 3693 "Verifies gl_PatchVerticesIn size is valid in a tessellation" 3694 " evaluation shader and corresponds to the value configured in" 3695 " a tessellation control shader (should one be present) or to" 3696 " the default value, as set with glPatchParameteriEXT() call") 3697 , m_gl_max_patch_vertices_value(0) 3698 , m_bo_id(0) 3699 , m_vao_id(0) 3700 { 3701 /* Left blank on purpose */ 3702 } 3703 3704 /** Deinitializes all ES objects created for the test. */ 3705 void TessellationShaderTCTEgl_PatchVerticesIn::deinit() 3706 { 3707 /** Call base class' deinit() function */ 3708 TestCaseBase::deinit(); 3709 3710 if (!m_is_tessellation_shader_supported) 3711 { 3712 return; 3713 } 3714 3715 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3716 3717 /* Reset TF buffer object bindings */ 3718 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 3719 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 3720 3721 /* Disable GL_RASTERIZER_DISCARD mode */ 3722 gl.disable(GL_RASTERIZER_DISCARD); 3723 3724 /* Reset GL_PATCH_VERTICES_EXT to the default setting */ 3725 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 3726 3727 /* Unbind vertex array object */ 3728 gl.bindVertexArray(0); 3729 3730 /* Release all objects we might've created */ 3731 if (m_bo_id != 0) 3732 { 3733 gl.deleteBuffers(1, &m_bo_id); 3734 3735 m_bo_id = 0; 3736 } 3737 3738 if (m_vao_id != 0) 3739 { 3740 gl.deleteVertexArrays(1, &m_vao_id); 3741 3742 m_vao_id = 0; 3743 } 3744 3745 for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it) 3746 { 3747 deinitTestDescriptor(&*it); 3748 } 3749 m_tests.clear(); 3750 } 3751 3752 /** Deinitializes ES objects created for particular test pass. 3753 * 3754 * @param test_ptr Test run descriptor. Must not be NULL. 3755 * 3756 **/ 3757 void TessellationShaderTCTEgl_PatchVerticesIn::deinitTestDescriptor(_test_descriptor* test_ptr) 3758 { 3759 /* Call base class' deinit() */ 3760 TestCaseBase::deinit(); 3761 3762 /* Release all objects */ 3763 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3764 3765 if (test_ptr->fs_id != 0) 3766 { 3767 gl.deleteShader(test_ptr->fs_id); 3768 3769 test_ptr->fs_id = 0; 3770 } 3771 3772 if (test_ptr->po_id != 0) 3773 { 3774 gl.deleteProgram(test_ptr->po_id); 3775 3776 test_ptr->po_id = 0; 3777 } 3778 3779 if (test_ptr->tcs_id != 0) 3780 { 3781 gl.deleteShader(test_ptr->tcs_id); 3782 3783 test_ptr->tcs_id = 0; 3784 } 3785 3786 if (test_ptr->tes_id != 0) 3787 { 3788 gl.deleteShader(test_ptr->tes_id); 3789 3790 test_ptr->tes_id = 0; 3791 } 3792 3793 if (test_ptr->vs_id != 0) 3794 { 3795 gl.deleteShader(test_ptr->vs_id); 3796 3797 test_ptr->vs_id = 0; 3798 } 3799 } 3800 3801 /** Initializes all ES objects that will be used for the test. */ 3802 void TessellationShaderTCTEgl_PatchVerticesIn::initTest() 3803 { 3804 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3805 3806 /* The test requires EXT_tessellation_shader */ 3807 if (!m_is_tessellation_shader_supported) 3808 { 3809 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 3810 } 3811 3812 /* Initialize vertex array object */ 3813 gl.genVertexArrays(1, &m_vao_id); 3814 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 3815 3816 gl.bindVertexArray(m_vao_id); 3817 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 3818 3819 /* Retrieve GL_MAX_PATCH_VERTICES_EXT value before we carry on */ 3820 gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices_value); 3821 3822 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() for GL_MAX_PATCH_VERTICES_EXT pname failed"); 3823 3824 /* Initialize test descriptors. 3825 * 3826 * Make sure the values we use are multiples of 4 - this is because we're using isolines in the 3827 * tessellation stage, and in order to have the requested amount of line segments generated, we need 3828 * to use a multiply of 4 vertices per patch */ 3829 glw::GLint n_half_max_patch_vertices_mul_4 = m_gl_max_patch_vertices_value / 2; 3830 glw::GLint n_max_patch_vertices_mul_4 = m_gl_max_patch_vertices_value; 3831 3832 if ((n_half_max_patch_vertices_mul_4 % 4) != 0) 3833 { 3834 /* Round to nearest mul-of-4 integer */ 3835 n_half_max_patch_vertices_mul_4 += (4 - (m_gl_max_patch_vertices_value / 2) % 4); 3836 } 3837 3838 if ((n_max_patch_vertices_mul_4 % 4) != 0) 3839 { 3840 /* Round to previous nearest mul-of-4 integer */ 3841 n_max_patch_vertices_mul_4 -= (m_gl_max_patch_vertices_value % 4); 3842 } 3843 3844 _test_descriptor test_tcs_tes_4; 3845 _test_descriptor test_tcs_tes_half_max_patch_vertices_mul_4; 3846 _test_descriptor test_tcs_tes_max_patch_vertices_mul_4; 3847 _test_descriptor test_tes_4; 3848 _test_descriptor test_tes_half_max_patch_vertices_mul_4; 3849 _test_descriptor test_tes_max_patch_vertices_mul_4; 3850 3851 initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_4, 4); 3852 initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_half_max_patch_vertices_mul_4, 3853 n_half_max_patch_vertices_mul_4); 3854 initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_max_patch_vertices_mul_4, 3855 n_max_patch_vertices_mul_4); 3856 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 3857 { 3858 initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_4, 4); 3859 initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_half_max_patch_vertices_mul_4, 3860 n_half_max_patch_vertices_mul_4); 3861 initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_max_patch_vertices_mul_4, n_max_patch_vertices_mul_4); 3862 } 3863 3864 m_tests.push_back(test_tcs_tes_4); 3865 m_tests.push_back(test_tcs_tes_half_max_patch_vertices_mul_4); 3866 m_tests.push_back(test_tcs_tes_max_patch_vertices_mul_4); 3867 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 3868 { 3869 m_tests.push_back(test_tes_4); 3870 m_tests.push_back(test_tes_half_max_patch_vertices_mul_4); 3871 m_tests.push_back(test_tes_max_patch_vertices_mul_4); 3872 } 3873 3874 /* Generate and set up a buffer object we will use to hold XFBed data. 3875 * 3876 * NOTE: We do not set the buffer object's storage here because its size 3877 * is iteration-specific. 3878 **/ 3879 gl.genBuffers(1, &m_bo_id); 3880 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed"); 3881 3882 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 3883 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed"); 3884 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 3885 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed"); 3886 3887 /* We're good to execute the test! */ 3888 } 3889 3890 /** Initializes ES objects for a particular tess pass. 3891 * 3892 * @param test_type Determines test type to be used for initialization. 3893 * TEST_TYPE_TCS_TES will use both TC and TE stages, 3894 * TEST_TYPE_TES will assume only TE stage should be used. 3895 * @param out_test_ptr Deref will be used to store object data. Must not be NULL. 3896 * @param input_patch_size Tells how many vertices should be used per patch for hte 3897 * result program object. 3898 **/ 3899 void TessellationShaderTCTEgl_PatchVerticesIn::initTestDescriptor(_tessellation_test_type test_type, 3900 _test_descriptor* out_test_ptr, 3901 unsigned int input_patch_size) 3902 { 3903 out_test_ptr->input_patch_size = input_patch_size; 3904 out_test_ptr->type = test_type; 3905 3906 /* Generate a program object we will later configure */ 3907 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3908 3909 out_test_ptr->po_id = gl.createProgram(); 3910 3911 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 3912 3913 /* Generate shader objects the test will use */ 3914 out_test_ptr->fs_id = gl.createShader(GL_FRAGMENT_SHADER); 3915 out_test_ptr->vs_id = gl.createShader(GL_VERTEX_SHADER); 3916 3917 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES) 3918 { 3919 out_test_ptr->tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 3920 } 3921 3922 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES) 3923 { 3924 out_test_ptr->tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 3925 } 3926 3927 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 3928 3929 /* Configure fragment shader */ 3930 const char* fs_body = "${VERSION}\n" 3931 "\n" 3932 "void main()\n" 3933 "{\n" 3934 "}\n"; 3935 3936 shaderSourceSpecialized(out_test_ptr->fs_id, 1 /* count */, &fs_body); 3937 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object"); 3938 3939 /* Configure tessellation control shader */ 3940 const char* tc_body = "${VERSION}\n" 3941 "\n" 3942 /* Required EXT_tessellation_shader functionality */ 3943 "${TESSELLATION_SHADER_REQUIRE}\n" 3944 "\n" 3945 "layout (vertices = VERTICES_TOKEN) out;\n" 3946 "\n" 3947 "void main()\n" 3948 "{\n" 3949 " gl_out [gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 3950 " gl_TessLevelOuter[0] = 1.0;\n" 3951 " gl_TessLevelOuter[1] = 1.0;\n" 3952 "}\n"; 3953 3954 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES) 3955 { 3956 const char* result_body = NULL; 3957 std::string tc_body_string = tc_body; 3958 std::size_t token_index = -1; 3959 const char* token_string = "VERTICES_TOKEN"; 3960 std::stringstream vertices_stringstream; 3961 std::string vertices_string; 3962 3963 vertices_stringstream << input_patch_size; 3964 vertices_string = vertices_stringstream.str(); 3965 3966 while ((token_index = tc_body_string.find(token_string)) != std::string::npos) 3967 { 3968 tc_body_string = tc_body_string.replace(token_index, strlen(token_string), vertices_string); 3969 } 3970 3971 result_body = tc_body_string.c_str(); 3972 3973 shaderSourceSpecialized(out_test_ptr->tcs_id, 1 /* count */, &result_body); 3974 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object"); 3975 } 3976 3977 /* Configure tessellation evaluation shader */ 3978 const char* te_body = "${VERSION}\n" 3979 "\n" 3980 "${TESSELLATION_SHADER_REQUIRE}\n" 3981 "\n" 3982 "layout (isolines, point_mode) in;\n" 3983 "\n" 3984 "flat out int result_PatchVerticesIn;\n" 3985 "\n" 3986 "void main()\n" 3987 "{\n" 3988 " gl_Position = gl_in[0].gl_Position;\n" 3989 "\n" 3990 " result_PatchVerticesIn = gl_PatchVerticesIn;\n" 3991 "}\n"; 3992 3993 shaderSourceSpecialized(out_test_ptr->tes_id, 1 /* count */, &te_body); 3994 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object"); 3995 3996 /* Configure vertex shader */ 3997 const char* vs_body = "${VERSION}\n" 3998 "\n" 3999 "void main()\n" 4000 "{\n" 4001 " gl_Position = vec4(float(gl_VertexID), 2.0, 3.0, 4.0);\n" 4002 "}\n"; 4003 4004 shaderSourceSpecialized(out_test_ptr->vs_id, 1 /* count */, &vs_body); 4005 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object"); 4006 4007 /* Compile all shaders of our interest */ 4008 const glw::GLuint shaders[] = { out_test_ptr->fs_id, out_test_ptr->tcs_id, out_test_ptr->tes_id, 4009 out_test_ptr->vs_id }; 4010 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 4011 4012 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 4013 { 4014 glw::GLint compile_status = GL_FALSE; 4015 glw::GLuint shader = shaders[n_shader]; 4016 4017 if (shader != 0) 4018 { 4019 gl.compileShader(shader); 4020 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 4021 4022 gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); 4023 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); 4024 4025 if (compile_status != GL_TRUE) 4026 { 4027 m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader 4028 << " failed." << tcu::TestLog::EndMessage; 4029 4030 TCU_FAIL("Shader compilation failed"); 4031 } 4032 } /* if (shader != 0) */ 4033 } /* for (all shaders) */ 4034 4035 /* Attach the shaders to the test program object, set up XFB and then link the program */ 4036 glw::GLint link_status = GL_FALSE; 4037 const char* varyings[] = { 4038 "result_PatchVerticesIn", 4039 }; 4040 const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]); 4041 4042 gl.transformFeedbackVaryings(out_test_ptr->po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS); 4043 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed"); 4044 4045 gl.attachShader(out_test_ptr->po_id, out_test_ptr->fs_id); 4046 gl.attachShader(out_test_ptr->po_id, out_test_ptr->vs_id); 4047 4048 if (out_test_ptr->tcs_id != 0) 4049 { 4050 gl.attachShader(out_test_ptr->po_id, out_test_ptr->tcs_id); 4051 } 4052 4053 if (out_test_ptr->tes_id != 0) 4054 { 4055 gl.attachShader(out_test_ptr->po_id, out_test_ptr->tes_id); 4056 } 4057 4058 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 4059 4060 gl.linkProgram(out_test_ptr->po_id); 4061 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 4062 4063 gl.getProgramiv(out_test_ptr->po_id, GL_LINK_STATUS, &link_status); 4064 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 4065 4066 if (link_status != GL_TRUE) 4067 { 4068 TCU_FAIL("Program linking failed"); 4069 } 4070 } 4071 4072 /** Executes the test. 4073 * 4074 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 4075 * 4076 * Note the function throws exception should an error occur! 4077 * 4078 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 4079 **/ 4080 tcu::TestNode::IterateResult TessellationShaderTCTEgl_PatchVerticesIn::iterate(void) 4081 { 4082 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4083 4084 /* Initialize ES test objects */ 4085 initTest(); 4086 4087 /* Prepare for rendering */ 4088 gl.enable(GL_RASTERIZER_DISCARD); 4089 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed."); 4090 4091 /* We will iterate through all added tests. */ 4092 for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); ++test_iterator) 4093 { 4094 /* Activate test-specific program object first. */ 4095 gl.useProgram(test_iterator->po_id); 4096 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 4097 4098 /* Test type tells determines how the tessellation levels should be set. 4099 * We don't need to do anything specific if TCS+TES are in, but if no 4100 * TCS is present, we need to configure default amount of input patch-vertices 4101 * to the test-specific value. 4102 */ 4103 glw::GLint n_patch_vertices = 0; 4104 4105 switch (test_iterator->type) 4106 { 4107 case TESSELLATION_TEST_TYPE_TCS_TES: 4108 { 4109 /* We're using isolines mode which requires at least 4 input vertices per patch */ 4110 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 4); 4111 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() for GL_PATCH_VERTICES_EXT failed."); 4112 4113 n_patch_vertices = 4; 4114 4115 break; 4116 } 4117 4118 case TESSELLATION_TEST_TYPE_TES: 4119 { 4120 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, test_iterator->input_patch_size); 4121 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed"); 4122 4123 n_patch_vertices = test_iterator->input_patch_size; 4124 4125 break; 4126 } 4127 4128 default: 4129 { 4130 TCU_FAIL("Unrecognized test type"); 4131 } 4132 } /* switch (test_iterator->type) */ 4133 4134 /* Set up storage properties for the buffer object, to which XFBed data will be 4135 * written. 4136 **/ 4137 const unsigned int n_bytes_needed = sizeof(int) * 2; /* the tessellator will output two vertices */ 4138 4139 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL /* data */, GL_STATIC_DRAW); 4140 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed"); 4141 4142 /* Render the test geometry */ 4143 gl.beginTransformFeedback(GL_POINTS); 4144 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed"); 4145 { 4146 /* Pass a single patch only */ 4147 gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, n_patch_vertices); 4148 4149 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed"); 4150 } 4151 gl.endTransformFeedback(); 4152 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed"); 4153 4154 /* Now that the BO is filled with data, map it so we can check the storage's contents */ 4155 const int* mapped_data_ptr = (const int*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 4156 n_bytes_needed, GL_MAP_READ_BIT); 4157 4158 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 4159 4160 /* Verify the contents. Make sure the value we retrieved is equal to the test-specific 4161 * amount of vertices per patch. 4162 */ 4163 for (unsigned int n_vertex = 0; n_vertex < 2 /* output vertices */; ++n_vertex) 4164 { 4165 unsigned int te_PatchVerticesInSize = mapped_data_ptr[n_vertex]; 4166 4167 if (te_PatchVerticesInSize != test_iterator->input_patch_size) 4168 { 4169 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PatchVerticesIn defined for TE stage " 4170 << " and result vertex index:" << n_vertex 4171 << " expected:" << test_iterator->input_patch_size 4172 << " rendered:" << te_PatchVerticesInSize << tcu::TestLog::EndMessage; 4173 4174 TCU_FAIL("Invalid gl_PatchVerticesIn size used in TE stage"); 4175 } /* if (comparison failed) */ 4176 } 4177 4178 /* All done - unmap the storage */ 4179 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4180 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 4181 } /* for (all tests) */ 4182 4183 /* All done */ 4184 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4185 return STOP; 4186 } 4187 4188 } /* namespace glcts */ 4189