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 "esextcTessellationShaderTessellation.hpp" 25 #include "gluContextInfo.hpp" 26 #include "gluDefs.hpp" 27 #include "glwEnums.hpp" 28 #include "glwFunctions.hpp" 29 #include "tcuTestLog.hpp" 30 #include <cstdlib> 31 32 namespace glcts 33 { 34 35 /** Vertex shader source code for max_in_out_attributes test. */ 36 const char* TessellationShaderTessellationMaxInOut::m_vs_code = 37 "${VERSION}\n" 38 "\n" 39 "${TESSELLATION_SHADER_REQUIRE}\n" 40 "${SHADER_IO_BLOCKS_ENABLE}\n" 41 "\n" 42 "precision highp float;\n" 43 "\n" 44 "layout(location = 0) in vec4 in_fv;\n" 45 "\n" 46 "out Vertex\n" 47 "{\n" 48 " /* Note: we need to leave some space for gl_Position */\n" 49 " vec4 value[(gl_MaxTessControlInputComponents) / 4 - 1];\n" 50 "} outVertex;\n" 51 "\n" 52 "void main()\n" 53 "{\n" 54 " gl_Position = in_fv;\n" 55 "\n" 56 " for (int i = 0 ; i < (gl_MaxTessControlInputComponents - " 57 "4) / 4 ; i++)\n" /* Max vec4 output attributes - gl_Position */ 58 " {\n" 59 " outVertex.value[i] = vec4(float(4*i), float(4*i) + " 60 "1.0, float(4*i) + 2.0, float(4*i) + 3.0);\n" 61 " }\n" 62 "}\n"; 63 64 /* Tessellation Control Shader code for max_in_out_attributes test */ 65 const char* TessellationShaderTessellationMaxInOut::m_tcs_code_1 = 66 "${VERSION}\n" 67 "\n" 68 "${TESSELLATION_SHADER_REQUIRE}\n" 69 "\n" 70 "precision highp float;\n" 71 "\n" 72 "layout(vertices = 2) out;\n" 73 "\n" 74 "in Vertex\n" 75 "{\n" 76 " /* Note: we need to leave some space for gl_Position */\n" 77 " vec4 value[(gl_MaxTessControlInputComponents - 4) / 4];\n" 78 "} inVertex[];\n" 79 "\n" 80 "out Vertex\n" 81 "{\n" 82 " /* Note: we need to leave some space for gl_Position */\n" 83 " vec4 value[(gl_MaxTessControlOutputComponents - 4) / 4];\n" 84 "} outVariables[];\n" 85 "\n" 86 "void main()\n" 87 "{\n" 88 " gl_TessLevelInner[0] = 1.0;\n" 89 " gl_TessLevelInner[1] = 1.0;\n" 90 " gl_TessLevelOuter[0] = 1.0;\n" 91 " gl_TessLevelOuter[1] = 1.0;\n" 92 " gl_TessLevelOuter[2] = 1.0;\n" 93 " gl_TessLevelOuter[3] = 1.0;\n" 94 "\n" 95 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 96 "\n" 97 " for (int j = 0; j < (gl_MaxTessControlOutputComponents - 4) / 4; j++)\n" 98 " {\n" 99 " outVariables[gl_InvocationID].value[j] = vec4(float(4*j), float(4*j) + 1.0, float(4*j) + 2.0, float(4*j) " 100 "+ 3.0);\n" 101 "\n" 102 " for (int i = 0; i < (gl_MaxTessControlInputComponents-4)/4; i++)\n" 103 " {\n" 104 " outVariables[gl_InvocationID].value[j] += inVertex[gl_InvocationID].value[i];\n" 105 " }\n" 106 " }\n" 107 "}\n"; 108 109 /* Tessellation Control Shader code for max_in_out_attributes test */ 110 const char* TessellationShaderTessellationMaxInOut::m_tcs_code_2 = 111 "${VERSION}\n" 112 "\n" 113 "${TESSELLATION_SHADER_REQUIRE}\n" 114 "\n" 115 "precision highp float;\n" 116 "\n" 117 "layout(vertices = 2) out;\n" 118 "\n" 119 "patch out vec4 value[gl_MaxTessPatchComponents/4];\n" 120 "\n" 121 "void main()\n" 122 "{\n" 123 " gl_TessLevelInner[0] = 1.0;\n" 124 " gl_TessLevelInner[1] = 1.0;\n" 125 " gl_TessLevelOuter[0] = 1.0;\n" 126 " gl_TessLevelOuter[1] = 1.0;\n" 127 " gl_TessLevelOuter[2] = 1.0;\n" 128 " gl_TessLevelOuter[3] = 1.0;\n" 129 "\n" 130 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 131 "\n" 132 " for (int j = 0; j < gl_MaxTessPatchComponents / 4; j++)\n" 133 " {\n" 134 " value[j] = vec4(float(4*j), float(4*j) + 1.0, float(4*j) + 2.0, float(4*j) + 3.0);\n" 135 " }\n" 136 "}\n"; 137 138 /* Tessellation Evaluation Shader code for max_in_out_attributes test */ 139 const char* TessellationShaderTessellationMaxInOut::m_tes_code_1 = 140 "${VERSION}\n" 141 "\n" 142 "${TESSELLATION_SHADER_REQUIRE}\n" 143 "\n" 144 "precision highp float;\n" 145 "\n" 146 "layout (isolines, point_mode) in;\n" 147 "\n" 148 "in Vertex\n" 149 "{\n" 150 " vec4 value[(gl_MaxTessEvaluationInputComponents - 4) / 4];\n" 151 "} inVariables[];\n" 152 "\n" 153 "out Vertex\n" 154 "{\n" 155 " vec4 value[(gl_MaxTessEvaluationOutputComponents - 4) / 4];\n" 156 "} outVariables;\n" 157 "\n" 158 "void main()\n" 159 "{\n" 160 " gl_Position = gl_in[0].gl_Position;\n" 161 "\n" 162 " for (int j = 0; j < (gl_MaxTessEvaluationOutputComponents - 4) / 4; j++)\n" 163 " {\n" 164 " outVariables.value[j] = vec4(float(4*j), float(4*j) + 1.0, float(4*j) + 2.0, float(4*j) + 3.0);\n" 165 "\n" 166 " for (int i = 0 ; i < (gl_MaxTessEvaluationInputComponents - 4) / 4; i++)\n" 167 " {\n" 168 " outVariables.value[j] += inVariables[0].value[i];\n" 169 " }\n" 170 " }\n" 171 "}\n"; 172 173 /* Tessellation Evaluation Shader code for max_in_out_attributes test */ 174 const char* TessellationShaderTessellationMaxInOut::m_tes_code_2 = 175 "${VERSION}\n" 176 "\n" 177 "${TESSELLATION_SHADER_REQUIRE}\n" 178 "\n" 179 "precision highp float;\n" 180 "\n" 181 "layout (isolines, point_mode) in;\n" 182 "\n" 183 "patch in vec4 value[gl_MaxTessPatchComponents / 4];\n" 184 "\n" 185 "out vec4 out_value;\n" 186 "\n" 187 "void main()\n" 188 "{\n" 189 " gl_Position = gl_in[0].gl_Position;\n" 190 " out_value = vec4(0.0);\n" 191 "\n" 192 " for (int i = 0; i < gl_MaxTessPatchComponents / 4; i++)\n" 193 " {\n" 194 " out_value += value[i];\n" 195 " }\n" 196 "}\n"; 197 198 /* Fragment Shader code for max_in_out_attributes test */ 199 const char* TessellationShaderTessellationMaxInOut::m_fs_code = "${VERSION}\n" 200 "\n" 201 "void main()\n" 202 "{\n" 203 "}\n"; 204 205 /** Constructor 206 * 207 * @param context Test context 208 **/ 209 TessellationShaderTessellationTests::TessellationShaderTessellationTests(glcts::Context& context, 210 const ExtParameters& extParams) 211 : TestCaseGroupBase(context, extParams, "tessellation_shader_tessellation", 212 "Verifies general tessellation functionality") 213 { 214 /* No implementation needed */ 215 } 216 217 /** 218 * Initializes test groups for geometry shader tests 219 **/ 220 void TessellationShaderTessellationTests::init(void) 221 { 222 addChild( 223 new glcts::TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID(m_context, m_extParams)); 224 addChild( 225 new glcts::TessellationShaderTessellationgl_TessCoord(m_context, m_extParams, TESSELLATION_TEST_TYPE_TCS_TES)); 226 addChild(new glcts::TessellationShaderTessellationgl_TessCoord(m_context, m_extParams, TESSELLATION_TEST_TYPE_TES)); 227 addChild(new glcts::TessellationShaderTessellationInputPatchDiscard(m_context, m_extParams)); 228 addChild(new glcts::TessellationShaderTessellationMaxInOut(m_context, m_extParams)); 229 } 230 231 /** Constructor 232 * 233 * @param context Test context 234 **/ 235 TessellationShaderTessellationInputPatchDiscard::TessellationShaderTessellationInputPatchDiscard( 236 Context& context, const ExtParameters& extParams) 237 : TestCaseBase(context, extParams, "input_patch_discard", 238 "Verifies that patches, for which relevant outer tessellation levels have" 239 " been defined to 0 or less, are discard by the tessellation primitive " 240 " generator.") 241 , m_bo_id(0) 242 , m_fs_id(0) 243 , m_vs_id(0) 244 , m_vao_id(0) 245 , m_utils_ptr(0) 246 { 247 /* Left blank on purpose */ 248 } 249 250 /** Deinitializes ES objects created for the test. */ 251 void TessellationShaderTessellationInputPatchDiscard::deinit() 252 { 253 /* Call base class' deinit() */ 254 TestCaseBase::deinit(); 255 256 if (!m_is_tessellation_shader_supported) 257 { 258 return; 259 } 260 261 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 262 263 /* Remove TF buffer object bindings */ 264 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 265 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 266 267 /* Disable GL_RASTERIZER_DISCARD mode */ 268 gl.disable(GL_RASTERIZER_DISCARD); 269 270 /* Restore GL_PATCH_VERTICES_EXT value */ 271 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 272 273 /* Unbind vertex array object */ 274 gl.bindVertexArray(0); 275 276 /* Free all ES objects we allocated for the test */ 277 if (m_bo_id != 0) 278 { 279 gl.deleteBuffers(1, &m_bo_id); 280 281 m_bo_id = 0; 282 } 283 284 if (m_fs_id != 0) 285 { 286 gl.deleteShader(m_fs_id); 287 288 m_fs_id = 0; 289 } 290 291 if (m_vs_id != 0) 292 { 293 gl.deleteShader(m_vs_id); 294 295 m_vs_id = 0; 296 } 297 298 if (m_vao_id != 0) 299 { 300 gl.deleteVertexArrays(1, &m_vao_id); 301 302 m_vao_id = 0; 303 } 304 305 /* Deinitialize all test descriptors */ 306 for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it) 307 { 308 deinitRun(*it); 309 } 310 m_runs.clear(); 311 312 /* Release tessellation shader test utilities instance */ 313 if (m_utils_ptr != NULL) 314 { 315 delete m_utils_ptr; 316 317 m_utils_ptr = NULL; 318 } 319 } 320 321 /** Deinitialize all test pass-specific ES objects. 322 * 323 * @param test Descriptor of a test pass to deinitialize. 324 **/ 325 void TessellationShaderTessellationInputPatchDiscard::deinitRun(_run& run) 326 { 327 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 328 329 if (run.po_id != 0) 330 { 331 gl.deleteProgram(run.po_id); 332 333 run.po_id = 0; 334 } 335 336 if (run.tc_id != 0) 337 { 338 gl.deleteShader(run.tc_id); 339 340 run.tc_id = 0; 341 } 342 343 if (run.te_id != 0) 344 { 345 gl.deleteShader(run.te_id); 346 347 run.te_id = 0; 348 } 349 } 350 351 /** Returns source code of a tessellation control shader for the test. 352 * 353 * @return Requested string. 354 **/ 355 std::string TessellationShaderTessellationInputPatchDiscard::getTCCode() 356 { 357 std::string result; 358 359 result = "${VERSION}\n" 360 "\n" 361 "${TESSELLATION_SHADER_REQUIRE}\n" 362 "\n" 363 "layout(vertices = 2) out;\n" 364 "\n" 365 "out int tc_primitive_id[];\n" 366 "\n" 367 "void main()\n" 368 "{\n" 369 " if ((gl_PrimitiveID % 4) == 0)\n" 370 " {\n" 371 " gl_TessLevelOuter[0] = 0.0;\n" 372 " gl_TessLevelOuter[1] = 0.0;\n" 373 " gl_TessLevelOuter[2] = 0.0;\n" 374 " gl_TessLevelOuter[3] = 0.0;\n" 375 " }\n" 376 " else\n" 377 " if ((gl_PrimitiveID % 4) == 2)\n" 378 " {\n" 379 " gl_TessLevelOuter[0] = -1.0;\n" 380 " gl_TessLevelOuter[1] = -1.0;\n" 381 " gl_TessLevelOuter[2] = -1.0;\n" 382 " gl_TessLevelOuter[3] = -1.0;\n" 383 " }\n" 384 " else\n" 385 " {\n" 386 " gl_TessLevelOuter[0] = 1.0;\n" 387 " gl_TessLevelOuter[1] = 1.0;\n" 388 " gl_TessLevelOuter[2] = 1.0;\n" 389 " gl_TessLevelOuter[3] = 1.0;\n" 390 " }\n" 391 "\n" 392 " gl_TessLevelInner[0] = 1.0;\n" 393 " gl_TessLevelInner[1] = 1.0;\n" 394 " gl_out [gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n" 395 " tc_primitive_id [gl_InvocationID] = gl_PrimitiveID;\n" 396 "}\n"; 397 398 return result; 399 } 400 401 /** Returns source code of a tessellation evaluation shader for the test, 402 * given user-specified vertex spacing and primitive modes. 403 * 404 * Throws TestError exception if either of the arguments is invalid. 405 * 406 * @param primitive_mode Primitive mode to use in the shader. 407 * 408 * @return Requested string. 409 **/ 410 std::string TessellationShaderTessellationInputPatchDiscard::getTECode(_tessellation_primitive_mode primitive_mode) 411 { 412 std::string result = "${VERSION}\n" 413 "\n" 414 "${TESSELLATION_SHADER_REQUIRE}\n" 415 "\n" 416 "layout(PRIMITIVE_MODE) in;\n" 417 "\n" 418 "in int tc_primitive_id [];\n" 419 "out ivec2 te_tc_primitive_id;\n" 420 "out int te_primitive_id;\n" 421 "\n" 422 "void main()\n" 423 "{\n" 424 " te_tc_primitive_id[0] = tc_primitive_id[0];\n" 425 " te_tc_primitive_id[1] = tc_primitive_id[1];\n" 426 " te_primitive_id = gl_PrimitiveID;\n" 427 "}\n"; 428 429 /* Replace PRIMITIVE_MODE token with actual primitive_mode */ 430 std::string primitive_mode_string = TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode); 431 const char* primitive_mode_token = "PRIMITIVE_MODE"; 432 std::size_t primitive_mode_token_index = std::string::npos; 433 434 while ((primitive_mode_token_index = result.find(primitive_mode_token)) != std::string::npos) 435 { 436 result = result.replace(primitive_mode_token_index, strlen(primitive_mode_token), primitive_mode_string); 437 438 primitive_mode_token_index = result.find(primitive_mode_token); 439 } 440 441 /* Done */ 442 return result; 443 } 444 445 /** Initializes ES objects necessary to run the test. */ 446 void TessellationShaderTessellationInputPatchDiscard::initTest() 447 { 448 /* Skip if required extensions are not supported. */ 449 if (!m_is_tessellation_shader_supported) 450 { 451 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 452 } 453 454 /* Generate all test-wide objects needed for test execution */ 455 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 456 m_utils_ptr = new TessellationShaderUtils(gl, this); 457 458 gl.genVertexArrays(1, &m_vao_id); 459 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 460 461 gl.bindVertexArray(m_vao_id); 462 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 463 464 gl.genBuffers(1, &m_bo_id); 465 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 466 467 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 468 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 469 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 470 471 /* Configure fragment shader body */ 472 const char* fs_body = "${VERSION}\n" 473 "\n" 474 "void main()\n" 475 "{\n" 476 "}\n"; 477 478 shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body); 479 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader"); 480 481 /* Configure vertex shader body */ 482 const char* vs_body = "${VERSION}\n" 483 "\n" 484 "void main()\n" 485 "{\n" 486 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" 487 "}\n"; 488 489 shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body); 490 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader"); 491 492 /* Compile all the shaders */ 493 const glw::GLuint shaders[] = { m_fs_id, m_vs_id }; 494 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 495 496 m_utils_ptr->compileShaders(n_shaders, shaders, true); 497 498 /* Initialize all the runs. */ 499 const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, 500 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 501 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 502 const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 503 504 for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 505 { 506 /* Initialize the run */ 507 _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 508 _run run; 509 510 initRun(run, primitive_mode); 511 512 /* Store the run */ 513 m_runs.push_back(run); 514 } /* for (all primitive modes) */ 515 516 /* Set up buffer object bindings. Storage size will be determined on 517 * a per-iteration basis. 518 **/ 519 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 520 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); 521 522 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 523 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed"); 524 } 525 526 /** Initializes all ES objects necessary to run a specific test pass. 527 * 528 * Throws TestError exception if any of the arguments is found invalid. 529 * 530 * @param run Run descriptor to fill with IDs of initialized objects. 531 * @param primitive_mode Primitive mode to use for the pass. 532 **/ 533 void TessellationShaderTessellationInputPatchDiscard::initRun(_run& run, _tessellation_primitive_mode primitive_mode) 534 { 535 run.primitive_mode = primitive_mode; 536 537 /* Set up a program object for the descriptor */ 538 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 539 540 run.po_id = gl.createProgram(); 541 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 542 543 /* Set up tessellation shader objects. */ 544 run.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 545 run.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 546 547 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed"); 548 549 /* Configure tessellation control shader body */ 550 std::string tc_body = getTCCode(); 551 const char* tc_body_raw_ptr = tc_body.c_str(); 552 553 shaderSourceSpecialized(run.tc_id, 1 /* count */, &tc_body_raw_ptr); 554 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader"); 555 556 /* Configure tessellation evaluation shader body */ 557 std::string te_body = getTECode(primitive_mode); 558 const char* te_body_raw_ptr = te_body.c_str(); 559 560 shaderSourceSpecialized(run.te_id, 1 /* count */, &te_body_raw_ptr); 561 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader"); 562 563 /* Compile the tessellation evaluation shader */ 564 glw::GLuint shaders[] = { run.tc_id, run.te_id }; 565 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 566 567 m_utils_ptr->compileShaders(n_shaders, shaders, true); 568 569 /* Attach all shader to the program object */ 570 gl.attachShader(run.po_id, m_fs_id); 571 gl.attachShader(run.po_id, run.tc_id); 572 gl.attachShader(run.po_id, run.te_id); 573 gl.attachShader(run.po_id, m_vs_id); 574 575 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed"); 576 577 /* Set up XFB */ 578 const char* varyings[] = { "te_tc_primitive_id", "te_primitive_id" }; 579 const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]); 580 581 gl.transformFeedbackVaryings(run.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS); 582 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed"); 583 584 /* Link the program object */ 585 glw::GLint link_status = GL_FALSE; 586 587 gl.linkProgram(run.po_id); 588 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed"); 589 590 gl.getProgramiv(run.po_id, GL_LINK_STATUS, &link_status); 591 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed"); 592 593 if (link_status != GL_TRUE) 594 { 595 TCU_FAIL("Program linking failed"); 596 } 597 } 598 599 /** Executes the test. 600 * 601 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 602 * 603 * Note the function throws exception should an error occur! 604 * 605 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 606 **/ 607 tcu::TestNode::IterateResult TessellationShaderTessellationInputPatchDiscard::iterate(void) 608 { 609 /* Do not execute if required extensions are not supported. */ 610 if (!m_is_tessellation_shader_supported) 611 { 612 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 613 } 614 615 /* Initialize ES test objects */ 616 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 617 618 initTest(); 619 620 /* We don't need rasterization for this test */ 621 gl.enable(GL_RASTERIZER_DISCARD); 622 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed."); 623 624 /* Configure amount of vertices per input patch */ 625 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1); 626 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname"); 627 628 /* Iterate through all tests configured */ 629 for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++) 630 { 631 const _run& run = *run_iterator; 632 633 /* Set up XFB target BO storage size. Each input patch will generate: 634 * 635 * a) 1 ivec2 and 1 int IF it is an odd patch; 636 * b) 0 bytes otherwise. 637 * 638 * This gives us a total of 2 * (sizeof(int)*2 + sizeof(int)) = 24 bytes per result coordinate, 639 * assuming it does not get discarded along the way. 640 * 641 * Amount of vertices that TE processes is mode-dependent. Note that for 'quads' we use 6 instead 642 * of 4 because the geometry will be broken down to triangles (1 quad = 2 triangles = 6 vertices) 643 * later in the pipeline. 644 */ 645 const unsigned int n_total_primitives = 4; 646 const unsigned int n_vertices_per_patch = 647 ((run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES) ? 648 2 : 649 (run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS) ? 6 : 3); 650 const unsigned int n_bytes_per_result_vertex = sizeof(int) + 2 * sizeof(int); 651 const unsigned int n_bytes_needed = (n_total_primitives / 2) * n_vertices_per_patch * n_bytes_per_result_vertex; 652 653 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL, /* data */ 654 GL_STATIC_DRAW); 655 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 656 657 /* Activate the program object */ 658 gl.useProgram(run.po_id); 659 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed"); 660 661 /* Draw the test geometry. */ 662 glw::GLenum tf_mode = 663 TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, false); /* is_point_mode_enabled */ 664 665 gl.beginTransformFeedback(tf_mode); 666 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed."); 667 668 gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* vertices per patch */ * n_total_primitives); 669 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 670 671 gl.endTransformFeedback(); 672 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed"); 673 674 /* Map the BO with result data into user space */ 675 int* result_data = (int*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 676 n_bytes_needed, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); 677 678 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed"); 679 680 /* Verification is based on the following reasoning: 681 * 682 * a) Both TC and TE stages should operate on the same primitive IDs (no re-ordering 683 * of the IDs is allowed) 684 * b) Under test-specific configuration, tessellator will output 2 line segments (4 coordinates). 685 * Two first two coordinates will be generated during tessellation of the second primitive, 686 * and the other two coordinates will be generated during tessellation of the fourth primitive 687 * (out of all four primitives that will enter the pipeline). 688 * c) In case of quads, 6 first coordinates will be generated during tessellation of the second primitive, 689 * and the other six will be generated during tessellation of the fourth primitive. 690 * d) Finally, tessellator will output 2 triangles (6 coordinates). The first three coordinates will 691 * be generated during tessellation of the second primitive, and the other two for the fourth 692 * primitive. 693 * */ 694 const int expected_primitive_ids[] = { 695 1, /* second primitive */ 696 3 /* fourth primitive */ 697 }; 698 const unsigned int n_expected_primitive_ids = 699 sizeof(expected_primitive_ids) / sizeof(expected_primitive_ids[0]); 700 const unsigned int n_expected_repetitions = 701 (run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES) ? 702 2 : 703 (run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS) ? 6 : 3; 704 const int* traveller_ptr = result_data; 705 706 for (unsigned int n_primitive_id = 0; n_primitive_id < n_expected_primitive_ids; ++n_primitive_id) 707 { 708 int expected_primitive_id = expected_primitive_ids[n_primitive_id]; 709 710 for (unsigned int n_repetition = 0; n_repetition < n_expected_repetitions; ++n_repetition) 711 { 712 for (unsigned int n_integer = 0; n_integer < 3 /* ivec2 + int */; ++n_integer) 713 { 714 if (*traveller_ptr != expected_primitive_id) 715 { 716 std::string primitive_mode_string = 717 TessellationShaderUtils::getESTokenForPrimitiveMode(run.primitive_mode); 718 719 m_testCtx.getLog() << tcu::TestLog::Message << "For primitive mode: " << primitive_mode_string 720 << " invalid gl_PrimitiveID of value " << *traveller_ptr 721 << " was found instead of expected " << expected_primitive_id 722 << " at index:" << n_primitive_id * 3 /* ivec2 + int */ + n_integer 723 << tcu::TestLog::EndMessage; 724 725 TCU_FAIL("Discard mechanism failed"); 726 } 727 728 traveller_ptr++; 729 } /* for (all captured integers) */ 730 } /* for (all repetitions) */ 731 } /* for (all non-discarded primitive ids) */ 732 733 /* Clear the buffer storage space before we unmap it */ 734 memset(result_data, 0, n_bytes_needed); 735 736 /* Unmap the BO */ 737 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 738 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed"); 739 } 740 741 /* All done */ 742 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 743 return STOP; 744 } 745 746 /** Constructor 747 * 748 * @param context Test context 749 **/ 750 TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID:: 751 TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID(Context& context, 752 const ExtParameters& extParams) 753 : TestCaseBase(context, extParams, "gl_InvocationID_PatchVerticesIn_PrimitiveID", 754 "Verifies that gl_InvocationID, gl_PatchVerticesIn and gl_PrimitiveID " 755 "are assigned correct values in TC and TE stages (where appropriate), " 756 "when invoked with arrayed and indiced draw calls. Also verifies that " 757 "restarting primitive topology does not restart primitive ID counter.") 758 , m_bo_id(0) 759 , m_fs_id(0) 760 , m_vs_id(0) 761 , m_vao_id(0) 762 , m_utils_ptr(0) 763 { 764 /* Left blank on purpose */ 765 } 766 767 /** Deinitializes ES objects created for the test. */ 768 void TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::deinit() 769 { 770 /* Call base class' deinit() */ 771 TestCaseBase::deinit(); 772 773 if (!m_is_tessellation_shader_supported) 774 { 775 return; 776 } 777 778 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 779 780 /* Disable modes this test has enabled */ 781 gl.disable(GL_RASTERIZER_DISCARD); 782 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_RASTERIZER_DISCARD) failed"); 783 784 gl.disable(GL_PRIMITIVE_RESTART_FIXED_INDEX); 785 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX) failed"); 786 787 /* Remove TF buffer object bindings */ 788 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 789 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 790 791 /* Restore GL_PATCH_VERTICES_EXT value */ 792 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 793 794 /* Unbind vertex array object */ 795 gl.bindVertexArray(0); 796 797 /* Free all ES objects we allocated for the test */ 798 if (m_bo_id != 0) 799 { 800 gl.deleteBuffers(1, &m_bo_id); 801 802 m_bo_id = 0; 803 } 804 805 if (m_fs_id != 0) 806 { 807 gl.deleteShader(m_fs_id); 808 809 m_fs_id = 0; 810 } 811 812 if (m_vs_id != 0) 813 { 814 gl.deleteShader(m_vs_id); 815 816 m_vs_id = 0; 817 } 818 819 if (m_vao_id != 0) 820 { 821 gl.deleteVertexArrays(1, &m_vao_id); 822 823 m_vao_id = 0; 824 } 825 826 /* Deinitialize all run descriptors */ 827 for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it) 828 { 829 deinitRun(*it); 830 } 831 m_runs.clear(); 832 833 /* Release tessellation shader test utilities instance */ 834 if (m_utils_ptr != NULL) 835 { 836 delete m_utils_ptr; 837 838 m_utils_ptr = NULL; 839 } 840 } 841 842 /** Deinitialize all test pass-specific ES objects. 843 * 844 * @param test Descriptor of a test pass to deinitialize. 845 **/ 846 void TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::deinitRun(_run& run) 847 { 848 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 849 850 if (run.bo_indices_id != 0) 851 { 852 gl.deleteBuffers(1, &run.bo_indices_id); 853 854 run.bo_indices_id = 0; 855 } 856 857 if (run.po_id != 0) 858 { 859 gl.deleteProgram(run.po_id); 860 861 run.po_id = 0; 862 } 863 864 if (run.tc_id != 0) 865 { 866 gl.deleteShader(run.tc_id); 867 868 run.tc_id = 0; 869 } 870 871 if (run.te_id != 0) 872 { 873 gl.deleteShader(run.te_id); 874 875 run.te_id = 0; 876 } 877 } 878 879 /** Returns source code of a tessellation control shader. 880 * 881 * @param n_patch_vertices Amount of vertices per patch to 882 * output in TC stage; 883 * 884 * @return Requested string. 885 **/ 886 std::string TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::getTCCode( 887 glw::GLuint n_patch_vertices) 888 { 889 static const char* tc_body = 890 "${VERSION}\n" 891 "\n" 892 "${TESSELLATION_SHADER_REQUIRE}\n" 893 "\n" 894 "layout(vertices = N_PATCH_VERTICES) out;\n" 895 "\n" 896 "out TC_OUT\n" 897 "{\n" 898 " int tc_invocation_id;\n" 899 " int tc_patch_vertices_in;\n" 900 " int tc_primitive_id;\n" 901 "} out_te[];\n" 902 "\n" 903 "void main()\n" 904 "{\n" 905 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 906 " out_te[gl_InvocationID].tc_invocation_id = gl_InvocationID;\n" 907 " out_te[gl_InvocationID].tc_patch_vertices_in = gl_PatchVerticesIn;\n" 908 " out_te[gl_InvocationID].tc_primitive_id = gl_PrimitiveID;\n" 909 "\n" 910 " gl_TessLevelInner[0] = 4.0;\n" 911 " gl_TessLevelInner[1] = 4.0;\n" 912 " gl_TessLevelOuter[0] = 4.0;\n" 913 " gl_TessLevelOuter[1] = 4.0;\n" 914 " gl_TessLevelOuter[2] = 4.0;\n" 915 " gl_TessLevelOuter[3] = 4.0;\n" 916 "}\n"; 917 918 /* Construct a string out of user-provided integer value */ 919 std::stringstream n_patch_vertices_sstream; 920 std::string n_patch_vertices_string; 921 922 n_patch_vertices_sstream << n_patch_vertices; 923 n_patch_vertices_string = n_patch_vertices_sstream.str(); 924 925 /* Replace N_PATCH_VERTICES with user-provided value */ 926 std::string result = tc_body; 927 const std::string token = "N_PATCH_VERTICES"; 928 std::size_t token_index = std::string::npos; 929 930 while ((token_index = result.find(token)) != std::string::npos) 931 { 932 result = result.replace(token_index, token.length(), n_patch_vertices_string.c_str()); 933 934 token_index = result.find(token); 935 } 936 937 return result; 938 } 939 940 /** Returns source code of a tessellation evaluation shader for the test, 941 * given user-specified primitive mode. 942 * 943 * Throws TestError exception if either of the arguments is invalid. 944 * 945 * @param primitive_mode Primitive mode to use in the shader. 946 * 947 * @return Requested string. 948 **/ 949 std::string TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::getTECode( 950 _tessellation_primitive_mode primitive_mode) 951 { 952 static const char* te_body = "${VERSION}\n" 953 "\n" 954 "${TESSELLATION_SHADER_REQUIRE}\n" 955 "\n" 956 "layout(PRIMITIVE_MODE) in;\n" 957 "\n" 958 "in TC_OUT\n" 959 "{\n" 960 " int tc_invocation_id;\n" 961 " int tc_patch_vertices_in;\n" 962 " int tc_primitive_id;\n" 963 "} in_tc[];\n" 964 "\n" 965 "out int te_tc_invocation_id;\n" 966 "out int te_tc_patch_vertices_in;\n" 967 "out int te_tc_primitive_id;\n" 968 "out int te_patch_vertices_in;\n" 969 "out int te_primitive_id;\n" 970 "\n" 971 "void main()\n" 972 "{\n" 973 " te_tc_invocation_id = in_tc[gl_PatchVerticesIn-1].tc_invocation_id;\n" 974 " te_tc_patch_vertices_in = in_tc[gl_PatchVerticesIn-1].tc_patch_vertices_in;\n" 975 " te_tc_primitive_id = in_tc[gl_PatchVerticesIn-1].tc_primitive_id;\n" 976 " te_patch_vertices_in = gl_PatchVerticesIn;\n" 977 " te_primitive_id = gl_PrimitiveID;\n" 978 "}"; 979 980 /* Replace PRIMITIVE_MODE with user-provided value */ 981 std::string primitive_mode_string = TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode); 982 std::string result = te_body; 983 const std::string token = "PRIMITIVE_MODE"; 984 std::size_t token_index = std::string::npos; 985 986 while ((token_index = result.find(token)) != std::string::npos) 987 { 988 result = result.replace(token_index, token.length(), primitive_mode_string.c_str()); 989 990 token_index = result.find(token); 991 } 992 993 return result; 994 } 995 996 /** Initializes ES objects necessary to run the test. */ 997 void TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::initTest() 998 { 999 /* Skip if required extensions are not supported. */ 1000 if (!m_is_tessellation_shader_supported) 1001 { 1002 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 1003 } 1004 1005 /* Set up Utils instance */ 1006 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1007 1008 m_utils_ptr = new TessellationShaderUtils(gl, this); 1009 1010 /* Initialize vertex array object */ 1011 gl.genVertexArrays(1, &m_vao_id); 1012 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 1013 1014 gl.bindVertexArray(m_vao_id); 1015 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 1016 1017 /* Generate all test-wide objects needed for test execution */ 1018 gl.genBuffers(1, &m_bo_id); 1019 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 1020 1021 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1022 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1023 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 1024 1025 /* Configure fragment shader body */ 1026 const char* fs_body = "${VERSION}\n" 1027 "\n" 1028 "void main()\n" 1029 "{\n" 1030 "}\n"; 1031 1032 shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body); 1033 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader"); 1034 1035 /* Configure vertex shader body */ 1036 const char* vs_body = "${VERSION}\n" 1037 "\n" 1038 "in vec4 vertex_data;\n" 1039 "\n" 1040 "void main()\n" 1041 "{\n" 1042 " gl_Position = vertex_data;\n" 1043 "}\n"; 1044 1045 shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body); 1046 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader"); 1047 1048 /* Compile all the shaders */ 1049 const glw::GLuint shaders[] = { m_fs_id, m_vs_id }; 1050 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 1051 1052 m_utils_ptr->compileShaders(n_shaders, shaders, true /* should_succeed */); 1053 1054 /* Retrieve GL_MAX_PATCH_VERTICES_EXT value before we continue */ 1055 glw::GLint gl_max_patch_vertices_value = 0; 1056 1057 gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &gl_max_patch_vertices_value); 1058 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_PATCH_VERTICES_EXT pname"); 1059 1060 /* Initialize all test passes */ 1061 const unsigned int drawcall_count_multipliers[] = { 3, 6 }; 1062 const bool is_indiced_draw_call_flags[] = { false, true }; 1063 const glw::GLint n_instances[] = { 1, 4 }; 1064 const glw::GLint n_patch_vertices[] = { 4, gl_max_patch_vertices_value / 2, gl_max_patch_vertices_value }; 1065 const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, 1066 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 1067 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 1068 const unsigned int n_drawcall_count_multipliers = 1069 sizeof(drawcall_count_multipliers) / sizeof(drawcall_count_multipliers[0]); 1070 const unsigned int n_is_indiced_draw_call_flags = 1071 sizeof(is_indiced_draw_call_flags) / sizeof(is_indiced_draw_call_flags[0]); 1072 const unsigned int n_n_instances = sizeof(n_instances) / sizeof(n_instances[0]); 1073 const unsigned int n_n_patch_vertices = sizeof(n_patch_vertices) / sizeof(n_patch_vertices[0]); 1074 const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 1075 1076 for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 1077 { 1078 _tessellation_primitive_mode current_primitive_mode = primitive_modes[n_primitive_mode]; 1079 1080 for (unsigned int n_patch_vertices_item = 0; n_patch_vertices_item < n_n_patch_vertices; 1081 ++n_patch_vertices_item) 1082 { 1083 glw::GLint current_n_patch_vertices = n_patch_vertices[n_patch_vertices_item]; 1084 1085 for (unsigned int n_is_indiced_draw_call_flag = 0; 1086 n_is_indiced_draw_call_flag < n_is_indiced_draw_call_flags; ++n_is_indiced_draw_call_flag) 1087 { 1088 bool current_is_indiced_draw_call = is_indiced_draw_call_flags[n_is_indiced_draw_call_flag]; 1089 1090 for (unsigned int n_instances_item = 0; n_instances_item < n_n_instances; ++n_instances_item) 1091 { 1092 glw::GLint current_n_instances = n_instances[n_instances_item]; 1093 1094 for (unsigned int n_drawcall_count_multiplier = 0; 1095 n_drawcall_count_multiplier < n_drawcall_count_multipliers; ++n_drawcall_count_multiplier) 1096 { 1097 const unsigned int drawcall_count_multiplier = 1098 drawcall_count_multipliers[n_drawcall_count_multiplier]; 1099 1100 /* Form the run descriptor */ 1101 _run run; 1102 1103 initRun(run, current_primitive_mode, current_n_patch_vertices, current_is_indiced_draw_call, 1104 current_n_instances, drawcall_count_multiplier); 1105 1106 /* Store the descriptor for later execution */ 1107 m_runs.push_back(run); 1108 } 1109 } /* for (all 'number of instances' settings) */ 1110 } /* for (all 'is indiced draw call' flags) */ 1111 } /* for (all 'n patch vertices' settings) */ 1112 } /* for (all primitive modes) */ 1113 1114 /* Set up buffer object bindings. Storage size will be determined on 1115 * a per-iteration basis. 1116 **/ 1117 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 1118 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); 1119 1120 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 1121 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed"); 1122 } 1123 1124 /** Initializes all ES objects necessary to run a specific test pass. 1125 * 1126 * Throws TestError exception if any of the arguments is found invalid. 1127 * 1128 * @param run Test run descriptor to fill with IDs of initialized objects. 1129 * @param primitive_mode Primitive mode to use for the pass. 1130 * @param n_patch_vertices Amount of output patch vertices to use for the pass. 1131 * @param is_indiced true if the draw call to be used for the test run should be indiced; 1132 * false to use the non-indiced one. 1133 * @param n_instances Amount of instances to use for the draw call. Set to 1 if the draw 1134 * call should be non-instanced. 1135 * @param drawcall_count_multiplier Will be used to multiply the "count" argument of the draw call API 1136 * function, effectively multiplying amount of primitives that will be 1137 * generated by the tessellator. 1138 **/ 1139 void TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::initRun( 1140 _run& run, _tessellation_primitive_mode primitive_mode, glw::GLint n_patch_vertices, bool is_indiced, 1141 glw::GLint n_instances, unsigned int drawcall_count_multiplier) 1142 { 1143 run.drawcall_count_multiplier = drawcall_count_multiplier; 1144 run.drawcall_is_indiced = is_indiced; 1145 run.n_instances = n_instances; 1146 run.n_patch_vertices = n_patch_vertices; 1147 run.primitive_mode = primitive_mode; 1148 1149 /* Set up a program object for the descriptor */ 1150 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1151 1152 run.po_id = gl.createProgram(); 1153 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 1154 1155 /* Set up tessellation control shader object */ 1156 std::string tc_body = getTCCode(n_patch_vertices); 1157 const char* tc_body_raw_ptr = tc_body.c_str(); 1158 1159 run.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 1160 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed"); 1161 1162 shaderSourceSpecialized(run.tc_id, 1 /* count */, &tc_body_raw_ptr); 1163 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader"); 1164 1165 /* Set up tessellation evaluation shader object. */ 1166 std::string te_body = getTECode(primitive_mode); 1167 const char* te_body_raw_ptr = te_body.c_str(); 1168 1169 run.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 1170 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed"); 1171 1172 shaderSourceSpecialized(run.te_id, 1 /* count */, &te_body_raw_ptr); 1173 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader"); 1174 1175 /* Compile the shaders */ 1176 const glw::GLuint shader_ids[] = { run.tc_id, run.te_id }; 1177 const unsigned int n_shader_ids = sizeof(shader_ids) / sizeof(shader_ids[0]); 1178 1179 m_utils_ptr->compileShaders(n_shader_ids, shader_ids, true /* should_succeed */); 1180 1181 /* Attach all shader to the program object */ 1182 gl.attachShader(run.po_id, m_fs_id); 1183 gl.attachShader(run.po_id, run.te_id); 1184 gl.attachShader(run.po_id, m_vs_id); 1185 gl.attachShader(run.po_id, run.tc_id); 1186 1187 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed"); 1188 1189 /* Set up XFB */ 1190 const char* varyings[] = { "te_tc_invocation_id", "te_tc_patch_vertices_in", "te_tc_primitive_id", 1191 "te_patch_vertices_in", "te_primitive_id" }; 1192 const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]); 1193 1194 gl.transformFeedbackVaryings(run.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS); 1195 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed"); 1196 1197 /* Link the program object */ 1198 glw::GLint link_status = GL_FALSE; 1199 1200 gl.linkProgram(run.po_id); 1201 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed"); 1202 1203 gl.getProgramiv(run.po_id, GL_LINK_STATUS, &link_status); 1204 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed"); 1205 1206 if (link_status != GL_TRUE) 1207 { 1208 TCU_FAIL("Program linking failed"); 1209 } 1210 1211 /* If this is going to be an indiced draw call, we need to initialize a buffer 1212 * object that will hold index data. GL_UNSIGNED_BYTE index type will be always 1213 * used for the purpose of this test. 1214 */ 1215 if (is_indiced) 1216 { 1217 gl.genBuffers(1, &run.bo_indices_id); 1218 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 1219 1220 /* Implementations are allowed NOT to support primitive restarting for patches. 1221 * Take this into account and do not insert restart indices, if ES reports no 1222 * support. 1223 */ 1224 glw::GLboolean is_primitive_restart_supported = GL_TRUE; 1225 1226 gl.getBooleanv(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED, &is_primitive_restart_supported); 1227 GLU_EXPECT_NO_ERROR(gl.getError(), 1228 "glGetIntegerv() failed for GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED pname"); 1229 1230 /* Set up index buffer storage. Note that we're not using any attributes 1231 * in any stage - our goal is just to make sure the primitive counter does 1232 * not restart whenever restart index is encountered during a draw call */ 1233 DE_ASSERT(run.n_patch_vertices > 3); 1234 DE_ASSERT(run.drawcall_count_multiplier > 1); 1235 1236 const unsigned int interleave_rate = run.n_patch_vertices * 2; 1237 unsigned char* bo_contents = DE_NULL; 1238 unsigned int bo_size = 1239 static_cast<unsigned int>(sizeof(unsigned char) * run.n_patch_vertices * run.drawcall_count_multiplier); 1240 1241 /* Count in restart indices if necessary */ 1242 if (is_primitive_restart_supported) 1243 { 1244 run.n_restart_indices = (bo_size / interleave_rate); 1245 bo_size += 1 /* restart index */ * run.n_restart_indices; 1246 } 1247 1248 /* Allocate space for the index buffer */ 1249 bo_contents = new unsigned char[bo_size]; 1250 1251 /* Interleave the restart index every two complete sets of vertices, each set 1252 * making up a full set of vertices. Fill all other indices with zeros. The 1253 * indices don't really matter since test shaders do not use any attributes - 1254 * what we want to verify is that the restart index does not break the primitive 1255 * id counter. 1256 * 1257 * NOTE: Our interleave rate is just an arbitrary value that makes 1258 * sense, given the multipliers we use for the test */ 1259 const unsigned char restart_index = 0xFF; 1260 1261 memset(bo_contents, 0, bo_size); 1262 1263 if (is_primitive_restart_supported) 1264 { 1265 for (unsigned int n_index = interleave_rate; n_index < bo_size; n_index += interleave_rate) 1266 { 1267 bo_contents[n_index] = restart_index; 1268 1269 /* Move one index ahead */ 1270 n_index++; 1271 } 1272 } 1273 1274 /* Set up the buffer object storage */ 1275 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, run.bo_indices_id); 1276 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); 1277 1278 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, bo_size, bo_contents, GL_STATIC_DRAW); 1279 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 1280 1281 /* Release the buffer */ 1282 delete[] bo_contents; 1283 1284 bo_contents = NULL; 1285 } 1286 1287 /* Retrieve amount of tessellation coordinates. 1288 * 1289 * Note: this test assumes a constant tessellation level value of 4 for all 1290 * inner/outer tessellation levels */ 1291 const glw::GLfloat tess_levels[] = { 4.0f, 4.0f, 4.0f, 4.0f }; 1292 1293 run.n_result_vertices = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 1294 run.primitive_mode, tess_levels, tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 1295 false); /* is_point_mode_enabled */ 1296 1297 /* The value we have at this point is for single patch only. To end up 1298 * with actual amount of coordinates that will be generated by the tessellator, 1299 * we need to multiply it by drawcall_count_multiplier * n_instances */ 1300 run.n_result_vertices *= run.drawcall_count_multiplier * run.n_instances; 1301 1302 /* We're done! */ 1303 } 1304 1305 /** Executes the test. 1306 * 1307 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 1308 * 1309 * Note the function throws exception should an error occur! 1310 * 1311 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 1312 **/ 1313 tcu::TestNode::IterateResult TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::iterate(void) 1314 { 1315 /* Do not execute if required extensions are not supported. */ 1316 if (!m_is_tessellation_shader_supported) 1317 { 1318 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 1319 } 1320 1321 /* Initialize ES test objects */ 1322 initTest(); 1323 1324 /* Initialize tessellation shader utilities */ 1325 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1326 1327 /* We don't need rasterization for this test */ 1328 gl.enable(GL_RASTERIZER_DISCARD); 1329 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed."); 1330 1331 /* Enable GL_PRIMITIVE_RESTART_FIXED_INDEX mode for indiced draw calls. */ 1332 gl.enable(GL_PRIMITIVE_RESTART_FIXED_INDEX); 1333 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX) failed."); 1334 1335 /* Iterate through all test runs configured */ 1336 for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++) 1337 { 1338 const _run& run = *run_iterator; 1339 1340 /* Configure run-specific amount of vertices per patch */ 1341 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, run.n_patch_vertices); 1342 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname"); 1343 1344 /* Activate run-specific program object */ 1345 gl.useProgram(run.po_id); 1346 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed"); 1347 1348 /* Update GL_ELEMENT_ARRAY_BUFFER binding, depending on run properties */ 1349 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, (run.drawcall_is_indiced) ? run.bo_indices_id : 0); 1350 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not update GL_ELEMENT_ARRAY_BUFFER binding"); 1351 1352 /* Update transform feedback buffer bindings */ 1353 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 1354 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); 1355 1356 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 1357 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed"); 1358 1359 /* Update the transform feedback buffer object storage. For each generated 1360 * tessellated coordinate, TE stage will output 5 integers. */ 1361 glw::GLint bo_size = static_cast<glw::GLint>(run.n_result_vertices * 5 /* ints */ * sizeof(int)); 1362 1363 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, GL_STATIC_DRAW); 1364 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 1365 1366 /* Render the geometry */ 1367 glw::GLint drawcall_count = run.n_patch_vertices * run.drawcall_count_multiplier + run.n_restart_indices; 1368 glw::GLenum tf_mode = 1369 TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, false); /* is_point_mode_enabled */ 1370 1371 gl.beginTransformFeedback(tf_mode); 1372 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed"); 1373 { 1374 if (run.drawcall_is_indiced) 1375 { 1376 if (run.n_instances != 1) 1377 { 1378 gl.drawElementsInstanced(m_glExtTokens.PATCHES, drawcall_count, GL_UNSIGNED_BYTE, 1379 DE_NULL, /* indices */ 1380 run.n_instances); 1381 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstanced() failed"); 1382 } /* if (run.n_instances != 0) */ 1383 else 1384 { 1385 gl.drawElements(m_glExtTokens.PATCHES, drawcall_count, GL_UNSIGNED_BYTE, DE_NULL); /* indices */ 1386 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() failed"); 1387 } 1388 } /* if (run.drawcall_is_indiced) */ 1389 else 1390 { 1391 if (run.n_instances != 1) 1392 { 1393 gl.drawArraysInstanced(m_glExtTokens.PATCHES, 0, /* first */ 1394 drawcall_count, run.n_instances); 1395 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArraysInstanced() failed"); 1396 } 1397 else 1398 { 1399 gl.drawArrays(m_glExtTokens.PATCHES, 0, /* first */ 1400 drawcall_count); 1401 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 1402 } 1403 } 1404 } 1405 gl.endTransformFeedback(); 1406 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed"); 1407 1408 /* Map the result buffer object */ 1409 const int* result_data = (const int*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 1410 bo_size, GL_MAP_READ_BIT); 1411 1412 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed"); 1413 1414 /* Verify gl_InvocationID values used in both stages were correct. In TE: 1415 * 1416 * te_tc_invocation_id = in_tc[gl_PatchVerticesIn-1].tc_invocation_id; 1417 * 1418 * In the list of varyings passed to glTransformFeedbackVaryings(), 1419 * te_tc_invocation_id is the very first item, so no need to offset 1420 * result_data when initializing result_traveller_ptr below. 1421 */ 1422 const unsigned int n_int_varyings_per_tess_coordinate = 5; 1423 const int* result_traveller_ptr = result_data; 1424 1425 for (unsigned int n_coordinate = 0; n_coordinate < run.n_result_vertices; 1426 ++n_coordinate, result_traveller_ptr += n_int_varyings_per_tess_coordinate) 1427 { 1428 const int expected_invocation_id = run.n_patch_vertices - 1; 1429 const int invocation_id_value = *result_traveller_ptr; 1430 1431 if (invocation_id_value != expected_invocation_id) 1432 { 1433 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_InvocationID value (" << invocation_id_value 1434 << ") " 1435 "was found for result coordinate at index " 1436 << n_coordinate << " " 1437 "instead of expected value (" 1438 << expected_invocation_id << ")." << tcu::TestLog::EndMessage; 1439 1440 TCU_FAIL("Invalid gl_InvocationID value used in TC stage"); 1441 } 1442 } /* for (all result coordinates) */ 1443 1444 /* Verify gl_PrimitiveID values used in both stages were correct. In TE: 1445 * 1446 * te_tc_primitive_id = in_tc[gl_PatchVerticesIn-1].tc_primitive_id; 1447 * te_primitive_id = gl_PrimitiveID; 1448 * 1449 * In the list of varyings passed to glTransformFeedbackVaryings(), 1450 * te_tc_primitive_id is passed as 3rd string and te_primitive_id is located on 1451 * 5th location. 1452 */ 1453 const unsigned int n_result_vertices_per_patch_vertex_batch = 1454 run.n_result_vertices / run.drawcall_count_multiplier / run.n_instances; 1455 const unsigned int n_result_vertices_per_instance = run.n_result_vertices / run.n_instances; 1456 1457 for (unsigned int n_coordinate = 0; n_coordinate < run.n_result_vertices; ++n_coordinate) 1458 { 1459 unsigned int actual_n_coordinate = n_coordinate; 1460 1461 /* Subsequent instances reset gl_PrimitiveID counter */ 1462 while (actual_n_coordinate >= n_result_vertices_per_instance) 1463 { 1464 actual_n_coordinate -= n_result_vertices_per_instance; 1465 } 1466 1467 /* Calculate expected gl_PrimitiveID value */ 1468 const int expected_primitive_id = actual_n_coordinate / n_result_vertices_per_patch_vertex_batch; 1469 1470 /* te_tc_primitive_id */ 1471 result_traveller_ptr = 1472 result_data + n_coordinate * n_int_varyings_per_tess_coordinate + 2; /* as per comment */ 1473 1474 if (*result_traveller_ptr != expected_primitive_id) 1475 { 1476 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PrimitiveID value (" << *result_traveller_ptr 1477 << ") " 1478 "was used in TC stage instead of expected value (" 1479 << expected_primitive_id << ") " 1480 " as stored for result coordinate at index " 1481 << n_coordinate << "." << tcu::TestLog::EndMessage; 1482 1483 TCU_FAIL("Invalid gl_PrimitiveID value used in TC stage"); 1484 } 1485 1486 /* te_primitive_id */ 1487 result_traveller_ptr = 1488 result_data + n_coordinate * n_int_varyings_per_tess_coordinate + 4; /* as per comment */ 1489 1490 if (*result_traveller_ptr != expected_primitive_id) 1491 { 1492 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PrimitiveID value (" << *result_traveller_ptr 1493 << ") " 1494 "was used in TE stage instead of expected value (" 1495 << expected_primitive_id << ") " 1496 " as stored for result coordinate at index " 1497 << n_coordinate << "." << tcu::TestLog::EndMessage; 1498 1499 TCU_FAIL("Invalid gl_PrimitiveID value used in TE stage"); 1500 } 1501 } /* for (all result coordinates) */ 1502 1503 /* Verify gl_PatchVerticesIn values used in both stages were correct. In TE: 1504 * 1505 * te_tc_patch_vertices_in = in_tc[gl_PatchVerticesIn-1].tc_patch_vertices_in; 1506 * te_patch_vertices_in = gl_PatchVerticesIn; 1507 * 1508 * In the list of varyings passed to glTransformFeedbackVaryings(), 1509 * te_tc_patch_vertices_in takes 2nd location and te_patch_vertices_in is 1510 * located at 4th position. 1511 * 1512 **/ 1513 for (unsigned int n_coordinate = 0; n_coordinate < run.n_result_vertices; ++n_coordinate) 1514 { 1515 const int expected_patch_vertices_in_value = run.n_patch_vertices; 1516 1517 /* te_tc_patch_vertices_in */ 1518 result_traveller_ptr = 1519 result_data + n_coordinate * n_int_varyings_per_tess_coordinate + 1; /* as per comment */ 1520 1521 if (*result_traveller_ptr != expected_patch_vertices_in_value) 1522 { 1523 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PatchVerticesIn value (" 1524 << *result_traveller_ptr << ") " 1525 "was used in TC stage instead of expected value (" 1526 << expected_patch_vertices_in_value << ") " 1527 " as stored for result coordinate at index " 1528 << n_coordinate << "." << tcu::TestLog::EndMessage; 1529 1530 TCU_FAIL("Invalid gl_PatchVerticesIn value used in TC stage"); 1531 } 1532 1533 /* te_patch_vertices_in */ 1534 result_traveller_ptr = 1535 result_data + n_coordinate * n_int_varyings_per_tess_coordinate + 3; /* as per comment */ 1536 1537 if (*result_traveller_ptr != expected_patch_vertices_in_value) 1538 { 1539 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PatchVerticesIn value (" 1540 << *result_traveller_ptr << ") " 1541 "was used in TE stage instead of expected value (" 1542 << expected_patch_vertices_in_value << ") " 1543 " as stored for result coordinate at index " 1544 << n_coordinate << "." << tcu::TestLog::EndMessage; 1545 } 1546 } /* for (all result coordinates) */ 1547 1548 /* Unmap the buffer object - we're done with this iteration */ 1549 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 1550 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed"); 1551 } /* for (all runs) */ 1552 1553 /* All done */ 1554 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1555 return STOP; 1556 } 1557 1558 std::string TessellationShaderTessellationgl_TessCoord::getTypeName(_tessellation_test_type test_type) 1559 { 1560 static const char* names[2] = { "TCS_TES", "TES" }; 1561 DE_ASSERT(0 <= test_type && test_type <= DE_LENGTH_OF_ARRAY(names)); 1562 DE_STATIC_ASSERT(0 == TESSELLATION_TEST_TYPE_TCS_TES && 1 == TESSELLATION_TEST_TYPE_TES); 1563 return names[test_type]; 1564 } 1565 1566 /** Constructor 1567 * 1568 * @param context Test context 1569 **/ 1570 TessellationShaderTessellationgl_TessCoord::TessellationShaderTessellationgl_TessCoord( 1571 Context& context, const ExtParameters& extParams, _tessellation_test_type test_type) 1572 : TestCaseBase(context, extParams, getTypeName(test_type).c_str(), 1573 "Verifies that u, v, w components of gl_TessCoord are within " 1574 "range for a variety of input/outer tessellation level combinations " 1575 "for all primitive modes. Verifies each component is within valid " 1576 " range. Also checks that w is always equal to 0 for isolines mode.") 1577 , m_test_type(test_type) 1578 , m_bo_id(0) 1579 , m_broken_ts_id(0) 1580 , m_fs_id(0) 1581 , m_vs_id(0) 1582 , m_vao_id(0) 1583 , m_utils_ptr(0) 1584 { 1585 /* Left blank on purpose */ 1586 } 1587 1588 /** Deinitializes ES objects created for the test. */ 1589 void TessellationShaderTessellationgl_TessCoord::deinit() 1590 { 1591 /* Call base class' deinit() */ 1592 TestCaseBase::deinit(); 1593 1594 if (!m_is_tessellation_shader_supported) 1595 { 1596 return; 1597 } 1598 1599 if (glu::isContextTypeES(m_context.getRenderContext().getType()) && m_test_type == TESSELLATION_TEST_TYPE_TES) 1600 { 1601 return; 1602 } 1603 1604 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1605 1606 /* Revert buffer object bindings */ 1607 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 1608 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 1609 1610 /* Disable GL_RASTERIZER_DISCARD mode */ 1611 gl.disable(GL_RASTERIZER_DISCARD); 1612 1613 /* Restore GL_PATCH_VERTICES_EXT, GL_PATCH_DEFAULT_INNER_LEVEL and 1614 * GL_PATCH_DEFAULT_OUTER_LEVEL values */ 1615 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 1616 { 1617 const float default_tess_levels[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 1618 gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, default_tess_levels); 1619 gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, default_tess_levels); 1620 } 1621 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 1622 1623 /* Unbind vertex array object */ 1624 gl.bindVertexArray(0); 1625 1626 /* Free all ES objects we allocated for the test */ 1627 if (m_bo_id != 0) 1628 { 1629 gl.deleteBuffers(1, &m_bo_id); 1630 1631 m_bo_id = 0; 1632 } 1633 1634 if (m_broken_ts_id != 0) 1635 { 1636 gl.deleteShader(m_broken_ts_id); 1637 1638 m_broken_ts_id = 0; 1639 } 1640 1641 if (m_fs_id != 0) 1642 { 1643 gl.deleteShader(m_fs_id); 1644 1645 m_fs_id = 0; 1646 } 1647 1648 if (m_vs_id != 0) 1649 { 1650 gl.deleteShader(m_vs_id); 1651 1652 m_vs_id = 0; 1653 } 1654 1655 if (m_vao_id != 0) 1656 { 1657 gl.deleteVertexArrays(1, &m_vao_id); 1658 1659 m_vao_id = 0; 1660 } 1661 1662 /* Deinitialize all test descriptors */ 1663 for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it) 1664 { 1665 deinitTestDescriptor(*it); 1666 } 1667 m_tests.clear(); 1668 1669 /* Release tessellation shader test utilities instance */ 1670 if (m_utils_ptr != NULL) 1671 { 1672 delete m_utils_ptr; 1673 1674 m_utils_ptr = NULL; 1675 } 1676 } 1677 1678 /** Deinitialize all test pass-specific ES objects. 1679 * 1680 * @param test Descriptor of a test pass to deinitialize. 1681 **/ 1682 void TessellationShaderTessellationgl_TessCoord::deinitTestDescriptor(_test_descriptor& test) 1683 { 1684 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1685 1686 if (test.po_id != 0) 1687 { 1688 gl.deleteProgram(test.po_id); 1689 1690 test.po_id = 0; 1691 } 1692 1693 if (test.tc_id != 0) 1694 { 1695 gl.deleteShader(test.tc_id); 1696 1697 test.tc_id = 0; 1698 } 1699 1700 if (test.te_id != 0) 1701 { 1702 gl.deleteShader(test.te_id); 1703 1704 test.te_id = 0; 1705 } 1706 } 1707 1708 /** Returns source code of a tessellation control shader for the test, 1709 * given user-specified amount of output patch vertices. 1710 * 1711 * @param n_patch_vertices Amount of output patch vertices for TC stage. 1712 * 1713 * @return Requested string. 1714 **/ 1715 std::string TessellationShaderTessellationgl_TessCoord::getTCCode(glw::GLint n_patch_vertices) 1716 { 1717 return TessellationShaderUtils::getGenericTCCode(n_patch_vertices, true); 1718 } 1719 1720 /** Returns source code of a tessellation evaluation shader for the test, 1721 * given user-specified vertex spacing and primitive modes. 1722 * 1723 * Throws TestError exception if either of the arguments is invalid. 1724 * 1725 * @param vertex_spacing Vertex spacing mode to use in the shader. 1726 * @param primitive_mode Primitive mode to use in the shader. 1727 * 1728 * @return Requested string. 1729 **/ 1730 std::string TessellationShaderTessellationgl_TessCoord::getTECode(_tessellation_shader_vertex_spacing vertex_spacing, 1731 _tessellation_primitive_mode primitive_mode) 1732 { 1733 return TessellationShaderUtils::getGenericTECode(vertex_spacing, primitive_mode, 1734 TESSELLATION_SHADER_VERTEX_ORDERING_CCW, false); 1735 } 1736 1737 /** Initializes ES objects necessary to run the test. */ 1738 void TessellationShaderTessellationgl_TessCoord::initTest() 1739 { 1740 /* Skip if required extensions are not supported. */ 1741 if (!m_is_tessellation_shader_supported) 1742 { 1743 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 1744 } 1745 1746 if (glu::isContextTypeES(m_context.getRenderContext().getType()) && m_test_type == TESSELLATION_TEST_TYPE_TES) 1747 { 1748 throw tcu::NotSupportedError("Test can't be run in ES context"); 1749 } 1750 1751 /* Generate all test-wide objects needed for test execution */ 1752 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1753 1754 gl.genVertexArrays(1, &m_vao_id); 1755 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 1756 1757 gl.bindVertexArray(m_vao_id); 1758 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 1759 1760 gl.genBuffers(1, &m_bo_id); 1761 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 1762 1763 m_broken_ts_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 1764 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1765 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1766 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 1767 1768 /* Configure fragment shader body */ 1769 const char* fs_body = "${VERSION}\n" 1770 "\n" 1771 "void main()\n" 1772 "{\n" 1773 "}\n"; 1774 1775 shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body); 1776 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader"); 1777 1778 /* Configure vertex shader body */ 1779 const char* vs_body = "${VERSION}\n" 1780 "\n" 1781 "void main()\n" 1782 "{\n" 1783 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" 1784 "}\n"; 1785 1786 shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body); 1787 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader"); 1788 1789 /* Compile all the shaders */ 1790 const glw::GLuint shaders[] = { m_fs_id, m_vs_id }; 1791 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 1792 1793 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 1794 { 1795 glw::GLuint shader = shaders[n_shader]; 1796 1797 if (shader != 0) 1798 { 1799 glw::GLint compile_status = GL_FALSE; 1800 1801 gl.compileShader(shader); 1802 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed"); 1803 1804 gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); 1805 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed"); 1806 1807 if (compile_status != GL_TRUE) 1808 { 1809 TCU_FAIL("Shader compilation failed"); 1810 } 1811 } 1812 } /* for (all shaders) */ 1813 1814 /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value before we start looping */ 1815 glw::GLint gl_max_tess_gen_level_value = 0; 1816 1817 gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 1818 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 1819 1820 /* Initialize all test passes - iterate over all primitive modes supported.. */ 1821 for (int primitive_mode = static_cast<int>(TESSELLATION_SHADER_PRIMITIVE_MODE_FIRST); 1822 primitive_mode != static_cast<int>(TESSELLATION_SHADER_PRIMITIVE_MODE_COUNT); primitive_mode++) 1823 { 1824 /* Iterate over all tessellation level combinations defined for current primitive mode */ 1825 _tessellation_levels_set tessellation_levels = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode( 1826 static_cast<_tessellation_primitive_mode>(primitive_mode), gl_max_tess_gen_level_value, 1827 TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE); 1828 1829 for (_tessellation_levels_set_const_iterator levels_iterator = tessellation_levels.begin(); 1830 levels_iterator != tessellation_levels.end(); levels_iterator++) 1831 { 1832 const _tessellation_levels& levels = *levels_iterator; 1833 _test_descriptor test; 1834 1835 initTestDescriptor(test, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 1836 static_cast<_tessellation_primitive_mode>(primitive_mode), 1, /* n_patch_vertices */ 1837 levels.inner, levels.outer, m_test_type); 1838 1839 /* Store the test descriptor */ 1840 m_tests.push_back(test); 1841 } /* for (all tessellation level combinations for current primitive mode) */ 1842 } /* for (all primitive modes) */ 1843 1844 /* Set up buffer object bindings. Storage size will be determined on 1845 * a per-iteration basis. 1846 **/ 1847 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 1848 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed"); 1849 1850 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id); 1851 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed"); 1852 } 1853 1854 /** Initializes all ES objects necessary to run a specific test pass. 1855 * 1856 * Throws TestError exception if any of the arguments is found invalid. 1857 * 1858 * @param test Test descriptor to fill with IDs of initialized objects. 1859 * @param vertex_spacing Vertex spacing mode to use for the pass. 1860 * @param primitive_mode Primitive mode to use for the pass. 1861 * @param n_patch_vertices Amount of output patch vertices to use for the pass. 1862 * @param inner_tess_level Inner tessellation level values to be used for the pass. 1863 * Must not be NULL. 1864 * @param outer_tess_level Outer tessellation level values to be used for the pass. 1865 * Must not be NULL. 1866 * @param test_type Defines which tessellation stages should be defined for the pass. 1867 **/ 1868 void TessellationShaderTessellationgl_TessCoord::initTestDescriptor( 1869 _test_descriptor& test, _tessellation_shader_vertex_spacing vertex_spacing, 1870 _tessellation_primitive_mode primitive_mode, glw::GLint n_patch_vertices, const float* inner_tess_level, 1871 const float* outer_tess_level, _tessellation_test_type test_type) 1872 { 1873 test.n_patch_vertices = n_patch_vertices; 1874 test.primitive_mode = primitive_mode; 1875 test.type = test_type; 1876 test.vertex_spacing = vertex_spacing; 1877 1878 memcpy(test.tess_level_inner, inner_tess_level, sizeof(float) * 2 /* components */); 1879 memcpy(test.tess_level_outer, outer_tess_level, sizeof(float) * 4 /* components */); 1880 1881 /* Set up a program object for the descriptor */ 1882 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1883 1884 test.po_id = gl.createProgram(); 1885 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 1886 1887 /* Set up a pass-specific tessellation shader objects. */ 1888 if (test_type == TESSELLATION_TEST_TYPE_TCS_TES) 1889 { 1890 test.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 1891 } 1892 1893 test.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 1894 1895 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed"); 1896 1897 /* Configure tessellation control shader body */ 1898 if (test.tc_id != 0) 1899 { 1900 std::string tc_body = getTCCode(n_patch_vertices); 1901 const char* tc_body_raw_ptr = tc_body.c_str(); 1902 1903 shaderSourceSpecialized(test.tc_id, 1 /* count */, &tc_body_raw_ptr); 1904 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader"); 1905 } 1906 1907 /* Configure tessellation evaluation shader body */ 1908 std::string te_body = getTECode(vertex_spacing, primitive_mode); 1909 const char* te_body_raw_ptr = te_body.c_str(); 1910 1911 shaderSourceSpecialized(test.te_id, 1 /* count */, &te_body_raw_ptr); 1912 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader"); 1913 1914 /* Compile the tessellation evaluation shader */ 1915 glw::GLint compile_status = GL_FALSE; 1916 glw::GLuint shaders[] = { test.tc_id, test.te_id }; 1917 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]); 1918 1919 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) 1920 { 1921 glw::GLuint shader = shaders[n_shader]; 1922 1923 if (shader != 0) 1924 { 1925 gl.compileShader(shader); 1926 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed for tessellation shader"); 1927 1928 gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); 1929 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed for tessellation shader"); 1930 1931 if (compile_status != GL_TRUE) 1932 { 1933 TCU_FAIL("Tessellation shader compilation failed"); 1934 } 1935 } 1936 } /* for (all shaders) */ 1937 1938 /* Attach all shader to the program object */ 1939 gl.attachShader(test.po_id, m_fs_id); 1940 gl.attachShader(test.po_id, test.te_id); 1941 gl.attachShader(test.po_id, m_vs_id); 1942 1943 if (test.tc_id != 0) 1944 { 1945 gl.attachShader(test.po_id, test.tc_id); 1946 } 1947 1948 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed"); 1949 1950 /* Set up XFB */ 1951 const char* varyings[] = { "result_uvw" }; 1952 const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]); 1953 1954 gl.transformFeedbackVaryings(test.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS); 1955 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed"); 1956 1957 /* Link the program object */ 1958 glw::GLint link_status = GL_FALSE; 1959 1960 gl.linkProgram(test.po_id); 1961 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed"); 1962 1963 gl.getProgramiv(test.po_id, GL_LINK_STATUS, &link_status); 1964 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed"); 1965 1966 if (link_status != GL_TRUE) 1967 { 1968 TCU_FAIL("Program linking failed"); 1969 } 1970 1971 /* If TCS stage is present, set up the corresponding uniforms as needed */ 1972 if (test.type == TESSELLATION_TEST_TYPE_TCS_TES) 1973 { 1974 test.inner_tess_level_uniform_location = gl.getUniformLocation(test.po_id, "inner_tess_level"); 1975 test.outer_tess_level_uniform_location = gl.getUniformLocation(test.po_id, "outer_tess_level"); 1976 1977 DE_ASSERT(test.inner_tess_level_uniform_location != -1); 1978 DE_ASSERT(test.outer_tess_level_uniform_location != -1); 1979 1980 /* Now that we have the locations, let's configure the uniforms */ 1981 gl.useProgram(test.po_id); 1982 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 1983 1984 gl.uniform2fv(test.inner_tess_level_uniform_location, 1, /* count */ 1985 test.tess_level_inner); 1986 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2fv() call failed"); 1987 1988 gl.uniform4fv(test.outer_tess_level_uniform_location, 1, /* count */ 1989 test.tess_level_outer); 1990 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed"); 1991 } 1992 } 1993 1994 /** Executes the test. 1995 * 1996 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 1997 * 1998 * Note the function throws exception should an error occur! 1999 * 2000 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 2001 **/ 2002 tcu::TestNode::IterateResult TessellationShaderTessellationgl_TessCoord::iterate(void) 2003 { 2004 /* Do not execute if required extensions are not supported. */ 2005 if (!m_is_geometry_shader_extension_supported || !m_is_tessellation_shader_supported) 2006 { 2007 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 2008 } 2009 2010 /* On ES skip test configurations that don't have TCS. */ 2011 if (isContextTypeES(m_context.getRenderContext().getType()) && (m_test_type == TESSELLATION_TEST_TYPE_TES)) 2012 { 2013 throw tcu::NotSupportedError("Implementation requires TCS and TES be used together; skipping."); 2014 } 2015 2016 /* Initialize ES test objects */ 2017 initTest(); 2018 2019 /* Initialize tessellation shader utilities */ 2020 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2021 2022 m_utils_ptr = new TessellationShaderUtils(gl, this); 2023 2024 /* We don't need rasterization for this test */ 2025 gl.enable(GL_RASTERIZER_DISCARD); 2026 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed."); 2027 2028 /* Iterate through all tests configured */ 2029 for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); test_iterator++) 2030 { 2031 const _test_descriptor& test = *test_iterator; 2032 2033 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 2034 { 2035 /* If there is no TCS defined, define inner/outer tessellation levels */ 2036 if (test.type == TESSELLATION_TEST_TYPE_TES) 2037 { 2038 gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, test.tess_level_inner); 2039 GLU_EXPECT_NO_ERROR(gl.getError(), 2040 "glPatchParameterfv() failed for GL_PATCH_DEFAULT_INNER_LEVEL pname"); 2041 2042 gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, test.tess_level_outer); 2043 GLU_EXPECT_NO_ERROR(gl.getError(), 2044 "glPatchParameterfv() failed for GL_PATCH_DEFAULT_OUTER_LEVEL pname"); 2045 } 2046 } 2047 2048 /* Configure amount of vertices per patch */ 2049 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, test.n_patch_vertices); 2050 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname"); 2051 2052 /* Set up XFB target BO storage size. We will be capturing a total of 12 FP components per 2053 * result vertex. 2054 */ 2055 unsigned int n_bytes_needed = 0; 2056 unsigned int n_result_vertices = 0; 2057 2058 n_result_vertices = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 2059 test.primitive_mode, test.tess_level_inner, test.tess_level_outer, test.vertex_spacing, false); 2060 n_bytes_needed = static_cast<unsigned int>(n_result_vertices * sizeof(float) * 12 /* components */); 2061 2062 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL, /* data */ 2063 GL_STATIC_DRAW); 2064 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 2065 2066 /* Activate the program object */ 2067 gl.useProgram(test.po_id); 2068 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed"); 2069 2070 /* Draw the test geometry. */ 2071 glw::GLenum tf_mode = TessellationShaderUtils::getTFModeForPrimitiveMode(test.primitive_mode, false); 2072 2073 gl.beginTransformFeedback(tf_mode); 2074 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_PATCHES_EXT) failed."); 2075 2076 gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, test.n_patch_vertices); 2077 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 2078 2079 gl.endTransformFeedback(); 2080 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed"); 2081 2082 /* Map the BO with result data into user space */ 2083 const float* vertex_data = (const float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 2084 n_bytes_needed, GL_MAP_READ_BIT); 2085 2086 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed"); 2087 2088 /* (test 1): Make sure that u+v+w == 1 (applicable for triangles only) */ 2089 const float epsilon = 1e-5f; 2090 2091 if (test.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES) 2092 { 2093 for (unsigned int n_vertex = 0; n_vertex < n_result_vertices; ++n_vertex) 2094 { 2095 const float* vertex_uvw = vertex_data + 3 /* components */ * n_vertex; 2096 float sum_uvw = vertex_uvw[0] + vertex_uvw[1] + vertex_uvw[2]; 2097 2098 if (de::abs(sum_uvw - 1.0f) > epsilon) 2099 { 2100 m_testCtx.getLog() << tcu::TestLog::Message << "For triangles, U+V+W coordinates outputted " 2101 "by tessellator should sum up to 1.0. Instead, the " 2102 "following coordinates:" 2103 << " (" << vertex_uvw[0] << ", " << vertex_uvw[1] << ", " << vertex_uvw[2] 2104 << ") " 2105 "sum up to " 2106 << sum_uvw << "." << tcu::TestLog::EndMessage; 2107 2108 TCU_FAIL("U+V+W coordinates do not add up to 1, even though triangle/tessellation" 2109 " was requested"); 2110 } 2111 } /* for (all vertices) */ 2112 } /* if (we're dealing with triangles or quads) */ 2113 2114 /* (test 2): Make sure that u, v, w e <0, 1> (always applicable) */ 2115 for (unsigned int n_vertex = 0; n_vertex < n_result_vertices; ++n_vertex) 2116 { 2117 const float* vertex_uvw = vertex_data + 3 /* components */ * n_vertex; 2118 2119 if (!(vertex_uvw[0] >= 0.0f && vertex_uvw[0] <= 1.0f && vertex_uvw[1] >= 0.0f && vertex_uvw[1] <= 1.0f && 2120 vertex_uvw[2] >= 0.0f && vertex_uvw[2] <= 1.0f)) 2121 { 2122 m_testCtx.getLog() << tcu::TestLog::Message 2123 << "U, V and W coordinates outputted by the tessellator should " 2124 "be within <0, 1> range. However, " 2125 << "vertex at index: " << n_vertex << "is defined by the following triple:" 2126 << " (" << vertex_uvw[0] << ", " << vertex_uvw[1] << ", " << vertex_uvw[2] << ")." 2127 << tcu::TestLog::EndMessage; 2128 2129 TCU_FAIL("U/V/W coordinate outputted by the tessellator is outside allowed range."); 2130 } 2131 } /* for (all vertices) */ 2132 2133 /* (test 3): Make sure w is always zero (applicable to quads and isolines) */ 2134 if (test.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS || 2135 test.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES) 2136 { 2137 for (unsigned int n_vertex = 0; n_vertex < n_result_vertices; ++n_vertex) 2138 { 2139 const float* vertex_uvw = vertex_data + 3 /* components */ * n_vertex; 2140 2141 if (de::abs(vertex_uvw[2]) > epsilon) 2142 { 2143 m_testCtx.getLog() << tcu::TestLog::Message 2144 << "W coordinate should be zero for all vertices outputted " 2145 "for isolines and quads; for at least one vertex, W was " 2146 "found to be equal to: " 2147 << vertex_uvw[2] << tcu::TestLog::EndMessage; 2148 2149 TCU_FAIL("W coordinate was found to be non-zero for at least one tessellation coordinate" 2150 " generated in either quads or isolines primitive mode"); 2151 } 2152 } /* for (all vertices) */ 2153 } /* if (we're dealing with quads or isolines) */ 2154 2155 /* Unmap the BO */ 2156 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 2157 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed"); 2158 } 2159 2160 /* All done */ 2161 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2162 return STOP; 2163 } 2164 2165 /** Constructor 2166 * 2167 * @param context Test context 2168 * @param name Test case's name 2169 * @param description Test case's desricption 2170 **/ 2171 TessellationShaderTessellationMaxInOut::TessellationShaderTessellationMaxInOut(Context& context, 2172 const ExtParameters& extParams) 2173 : TestCaseBase(context, extParams, "max_in_out_attributes", 2174 "Make sure it is possible to use up GL_MAX_TESS_*_COMPONENTS_EXT.") 2175 , m_po_id_1(0) 2176 , m_po_id_2(0) 2177 , m_fs_id(0) 2178 , m_tcs_id_1(0) 2179 , m_tcs_id_2(0) 2180 , m_tes_id_1(0) 2181 , m_tes_id_2(0) 2182 , m_vs_id_1(0) 2183 , m_vs_id_2(0) 2184 , m_tf_bo_id_1(0) 2185 , m_tf_bo_id_2(0) 2186 , m_patch_data_bo_id(0) 2187 , m_vao_id(0) 2188 , m_gl_max_tess_control_input_components_value(0) 2189 , m_gl_max_tess_control_output_components_value(0) 2190 , m_gl_max_tess_evaluation_input_components_value(0) 2191 , m_gl_max_tess_evaluation_output_components_value(0) 2192 , m_gl_max_transform_feedback_interleaved_components_value(0) 2193 , m_gl_max_tess_patch_components_value(0) 2194 , m_gl_max_vertex_output_components_value(0) 2195 , m_ref_vertex_attributes(DE_NULL) 2196 , m_tf_varyings_names(DE_NULL) 2197 { 2198 m_ref_patch_attributes[0] = 0.0f; 2199 m_ref_patch_attributes[1] = 0.0f; 2200 m_ref_patch_attributes[2] = 0.0f; 2201 m_ref_patch_attributes[3] = 0.0f; 2202 } 2203 2204 /** Deinitializes all ES objects created for the test. */ 2205 void TessellationShaderTessellationMaxInOut::deinit(void) 2206 { 2207 /* Call base class deinitialization routine */ 2208 TestCaseBase::deinit(); 2209 2210 if (!m_is_tessellation_shader_supported) 2211 { 2212 return; 2213 } 2214 2215 /* Deallocate dynamic arrays */ 2216 if (m_ref_vertex_attributes != DE_NULL) 2217 { 2218 free(m_ref_vertex_attributes); 2219 2220 m_ref_vertex_attributes = DE_NULL; 2221 } 2222 2223 /* Deallocate the varyings array */ 2224 if (m_tf_varyings_names != DE_NULL) 2225 { 2226 for (int i = 0; i < (m_gl_max_tess_evaluation_output_components_value) / 4 - 1 /* gl_Position */; i++) 2227 { 2228 if (m_tf_varyings_names[i] != DE_NULL) 2229 { 2230 free(m_tf_varyings_names[i]); 2231 2232 m_tf_varyings_names[i] = DE_NULL; 2233 } 2234 } 2235 2236 free(m_tf_varyings_names); 2237 2238 m_tf_varyings_names = DE_NULL; 2239 } 2240 2241 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2242 2243 /* Reset GL_PATCH_VERTICES_EXT pname value */ 2244 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 2245 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed!"); 2246 2247 /* Unbind vertex array object */ 2248 gl.bindVertexArray(0); 2249 2250 /* Release ES objects */ 2251 if (m_fs_id != 0) 2252 { 2253 gl.deleteShader(m_fs_id); 2254 2255 m_fs_id = 0; 2256 } 2257 2258 if (m_po_id_1 != 0) 2259 { 2260 gl.deleteProgram(m_po_id_1); 2261 2262 m_po_id_1 = 0; 2263 } 2264 2265 if (m_po_id_2 != 0) 2266 { 2267 gl.deleteProgram(m_po_id_2); 2268 2269 m_po_id_2 = 0; 2270 } 2271 2272 if (m_tcs_id_1 != 0) 2273 { 2274 gl.deleteShader(m_tcs_id_1); 2275 2276 m_tcs_id_1 = 0; 2277 } 2278 2279 if (m_tcs_id_2 != 0) 2280 { 2281 gl.deleteShader(m_tcs_id_2); 2282 2283 m_tcs_id_2 = 0; 2284 } 2285 2286 if (m_tes_id_1 != 0) 2287 { 2288 gl.deleteShader(m_tes_id_1); 2289 2290 m_tes_id_1 = 0; 2291 } 2292 2293 if (m_tes_id_2 != 0) 2294 { 2295 gl.deleteShader(m_tes_id_2); 2296 2297 m_tes_id_2 = 0; 2298 } 2299 2300 if (m_vs_id_1 != 0) 2301 { 2302 gl.deleteShader(m_vs_id_1); 2303 2304 m_vs_id_1 = 0; 2305 } 2306 2307 if (m_vs_id_2 != 0) 2308 { 2309 gl.deleteShader(m_vs_id_2); 2310 2311 m_vs_id_2 = 0; 2312 } 2313 2314 if (m_tf_bo_id_1 != 0) 2315 { 2316 gl.deleteBuffers(1, &m_tf_bo_id_1); 2317 2318 m_tf_bo_id_1 = 0; 2319 } 2320 2321 if (m_tf_bo_id_2 != 0) 2322 { 2323 gl.deleteBuffers(1, &m_tf_bo_id_2); 2324 2325 m_tf_bo_id_2 = 0; 2326 } 2327 2328 if (m_patch_data_bo_id != 0) 2329 { 2330 gl.deleteBuffers(1, &m_patch_data_bo_id); 2331 2332 m_patch_data_bo_id = 0; 2333 } 2334 2335 if (m_vao_id != 0) 2336 { 2337 gl.deleteVertexArrays(1, &m_vao_id); 2338 2339 m_vao_id = 0; 2340 } 2341 } 2342 2343 /** Executes the test. 2344 * 2345 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 2346 * 2347 * Note the function throws exception should an error occur! 2348 * 2349 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 2350 **/ 2351 tcu::TestNode::IterateResult TessellationShaderTessellationMaxInOut::iterate(void) 2352 { 2353 /* Retrieve ES entry-points. */ 2354 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2355 2356 /* Initialize test-specific ES objects. */ 2357 initTest(); 2358 2359 /* Execute test case 1 */ 2360 gl.useProgram(m_po_id_1); 2361 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!"); 2362 2363 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 2364 m_tf_bo_id_1); 2365 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed!"); 2366 2367 gl.beginTransformFeedback(GL_POINTS); 2368 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed"); 2369 2370 gl.drawArrays(m_glExtTokens.PATCHES, 0, /* first */ 2371 2); /* count */ 2372 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 2373 2374 gl.endTransformFeedback(); 2375 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed"); 2376 2377 /* Verify the rendered data. */ 2378 bool test_passed = true; 2379 2380 test_passed &= compareValues("Per-vertex components test ", m_ref_vertex_attributes, 2381 m_gl_max_tess_evaluation_output_components_value / 4); 2382 2383 /* Execute test case 2 */ 2384 gl.useProgram(m_po_id_2); 2385 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!"); 2386 2387 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 2388 m_tf_bo_id_2); 2389 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed!"); 2390 2391 gl.beginTransformFeedback(GL_POINTS); 2392 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed"); 2393 2394 gl.drawArrays(m_glExtTokens.PATCHES, 0, /* first */ 2395 2); /* count */ 2396 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 2397 2398 gl.endTransformFeedback(); 2399 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed"); 2400 2401 /* Verify the rendered data */ 2402 test_passed &= 2403 compareValues("Per-patch components test ", m_ref_patch_attributes, 1 /* amount of output vectors */); 2404 2405 /* Test passed. */ 2406 if (test_passed) 2407 { 2408 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2409 } 2410 else 2411 { 2412 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2413 } 2414 2415 return STOP; 2416 } 2417 2418 /** Sets up buffer objects. 2419 * 2420 * Note the function throws exception should an error occur! 2421 **/ 2422 void TessellationShaderTessellationMaxInOut::initBufferObjects(void) 2423 { 2424 /* Retrieve ES entry-points. */ 2425 glw::GLint bo_size = 0; 2426 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2427 2428 /* Transform feedback buffer object for case 1 */ 2429 gl.genBuffers(1, &m_tf_bo_id_1); 2430 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!"); 2431 2432 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_tf_bo_id_1); 2433 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 2434 2435 bo_size = static_cast<glw::GLint>(2 /* vertices */ 2436 * 4 /* components */ 2437 * m_gl_max_tess_evaluation_output_components_value / 4 /* attributes */ 2438 * sizeof(glw::GLfloat)); /* attribute size */ 2439 2440 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, NULL, GL_STATIC_DRAW); 2441 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 2442 2443 /* Transform feedback buffer object for case 2 */ 2444 bo_size = 2 * /* vertices */ 2445 sizeof(glw::GLfloat) * 4; /* components */ 2446 2447 gl.genBuffers(1, &m_tf_bo_id_2); 2448 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!"); 2449 2450 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_tf_bo_id_2); 2451 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 2452 2453 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, NULL, GL_STATIC_DRAW); 2454 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 2455 2456 /* Set up vertex data buffer storage */ 2457 glw::GLfloat vertices[2 /* vertices */ * 4 /* components */]; 2458 2459 bo_size = sizeof(vertices); 2460 vertices[0] = 0.f; 2461 vertices[1] = 0.f; 2462 vertices[2] = 0.f; 2463 vertices[3] = 1.f; 2464 vertices[4] = 1.f; 2465 vertices[5] = 1.f; 2466 vertices[6] = 1.f; 2467 vertices[7] = 1.f; 2468 2469 gl.genBuffers(1, &m_patch_data_bo_id); 2470 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!"); 2471 2472 gl.bindBuffer(GL_ARRAY_BUFFER, m_patch_data_bo_id); 2473 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 2474 2475 gl.bufferData(GL_ARRAY_BUFFER, bo_size, vertices, GL_STATIC_DRAW); 2476 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed!"); 2477 2478 gl.enableVertexAttribArray(0); 2479 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed!"); 2480 2481 gl.vertexAttribPointer(0, /* index */ 2482 4, /* size */ 2483 GL_FLOAT, GL_FALSE, /* normalized */ 2484 0, /* stride */ 2485 0); /* pointer */ 2486 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed!"); 2487 } 2488 2489 /** Initializes the test. 2490 * 2491 * Note the function throws exception should an error occur! 2492 **/ 2493 void TessellationShaderTessellationMaxInOut::initProgramObjects(void) 2494 { 2495 /* Retrieve ES entry-points */ 2496 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2497 2498 /* Create program objects. */ 2499 m_po_id_1 = gl.createProgram(); 2500 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!"); 2501 2502 m_po_id_2 = gl.createProgram(); 2503 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!"); 2504 2505 /* Set up all the shader objects that will be used for the test */ 2506 m_vs_id_1 = gl.createShader(GL_VERTEX_SHADER); 2507 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_VERTEX_SHADER) failed!"); 2508 2509 m_vs_id_2 = gl.createShader(GL_VERTEX_SHADER); 2510 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_VERTEX_SHADER) failed!"); 2511 2512 m_tcs_id_1 = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 2513 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_CONTROL_SHADER_EXT) failed!"); 2514 2515 m_tcs_id_2 = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 2516 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_CONTROL_SHADER_EXT) failed!"); 2517 2518 m_tes_id_1 = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 2519 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_EVALUATION_SHADER_EXT) failed!"); 2520 2521 m_tes_id_2 = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 2522 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_EVALUATION_SHADER_EXT) failed!"); 2523 2524 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 2525 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_FRAGMENT_SHADER) failed!"); 2526 2527 /* Transform Feedback setup for case 1 2528 * 2529 * Varyings array: m_tf_varyings_names[i < m_gl_max_tess_evaluation_output_components_value / 4-1] == "Vertex.value[i]" 2530 * m_tf_varyings_names[i == m_gl_max_tess_evaluation_output_components_value / 4-1] == "gl_Position" 2531 */ 2532 const char position_varying[] = "gl_Position"; 2533 2534 m_tf_varyings_names = (char**)malloc((m_gl_max_tess_evaluation_output_components_value / 4) * sizeof(char*)); 2535 2536 if (m_tf_varyings_names == DE_NULL) 2537 { 2538 throw tcu::ResourceError("Unable to allocate memory!"); 2539 } 2540 2541 for (int i = 0; i < (m_gl_max_tess_evaluation_output_components_value) / 4 /* attributes */ - 1 /* gl_Position */; 2542 i++) 2543 { 2544 std::stringstream tf_varying_stream; 2545 const char* tf_varying_raw_ptr = DE_NULL; 2546 std::string tf_varying_string; 2547 2548 tf_varying_stream << "Vertex.value[" << i << "]"; 2549 tf_varying_string = tf_varying_stream.str(); 2550 tf_varying_raw_ptr = tf_varying_string.c_str(); 2551 2552 m_tf_varyings_names[i] = (char*)malloc(strlen(tf_varying_raw_ptr) + 1 /* '\0' */); 2553 if (m_tf_varyings_names[i] == DE_NULL) 2554 { 2555 throw tcu::ResourceError("Unable to allocate memory!"); 2556 } 2557 2558 memcpy(m_tf_varyings_names[i], tf_varying_raw_ptr, strlen(tf_varying_raw_ptr) + 1); 2559 } 2560 2561 m_tf_varyings_names[m_gl_max_tess_evaluation_output_components_value / 4 - 1 /* gl_Position */] = 2562 (char*)malloc(sizeof(position_varying)); 2563 if (m_tf_varyings_names[m_gl_max_tess_evaluation_output_components_value / 4 - 1 /* gl_Position */] == DE_NULL) 2564 { 2565 throw tcu::ResourceError("Unable to allocate memory!"); 2566 } 2567 2568 memcpy(m_tf_varyings_names[m_gl_max_tess_evaluation_output_components_value / 4 - 1 /* gl_Position */], 2569 position_varying, sizeof(position_varying)); 2570 2571 /* Set up XFB */ 2572 gl.transformFeedbackVaryings(m_po_id_1, m_gl_max_tess_evaluation_output_components_value / 4, m_tf_varyings_names, 2573 GL_INTERLEAVED_ATTRIBS); 2574 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!"); 2575 2576 /* Set up program objects */ 2577 const char* vs_code_raw_ptr = m_vs_code; 2578 const char* tcs_code_1_raw_ptr = m_tcs_code_1; 2579 const char* tes_code_1_raw_ptr = m_tes_code_1; 2580 const char* tcs_code_2_raw_ptr = m_tcs_code_2; 2581 const char* tes_code_2_raw_ptr = m_tes_code_2; 2582 2583 /* Build a program object to test case 1. */ 2584 if (!TessellationShaderTessellationMaxInOut::buildProgram(m_po_id_1, m_vs_id_1, 1, &vs_code_raw_ptr, m_tcs_id_1, 1, 2585 &tcs_code_1_raw_ptr, m_tes_id_1, 1, &tes_code_1_raw_ptr, 2586 m_fs_id, 1, &m_fs_code)) 2587 { 2588 TCU_FAIL("Could not build first test program object"); 2589 } 2590 2591 /* Tranform Feedback setup for case 2 */ 2592 const char* const tf_varying_2 = "out_value"; 2593 2594 gl.transformFeedbackVaryings(m_po_id_2, 1 /* count */, &tf_varying_2, GL_INTERLEAVED_ATTRIBS); 2595 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!"); 2596 2597 /* Build a program object for case 2 */ 2598 if (!(TessellationShaderTessellationMaxInOut::buildProgram(m_po_id_2, m_vs_id_2, 1, &vs_code_raw_ptr, m_tcs_id_2, 1, 2599 &tcs_code_2_raw_ptr, m_tes_id_2, 1, &tes_code_2_raw_ptr, 2600 m_fs_id, 1, &m_fs_code))) 2601 { 2602 TCU_FAIL("Could not link second test program object"); 2603 } 2604 } 2605 2606 /** Initializes the test. 2607 * 2608 * Note the function throws exception should an error occur! 2609 **/ 2610 void TessellationShaderTessellationMaxInOut::initTest(void) 2611 { 2612 /* Render state setup */ 2613 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2614 2615 /* Skip if required extensions are not supported. */ 2616 if (!m_is_tessellation_shader_supported) 2617 { 2618 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 2619 } 2620 2621 /* Initialize vertex array object */ 2622 gl.genVertexArrays(1, &m_vao_id); 2623 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 2624 2625 gl.bindVertexArray(m_vao_id); 2626 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 2627 2628 /* All tessellation control shaders used by this test assume two 2629 * vertices are going to be provided per input patch. */ 2630 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 2); 2631 2632 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed!"); 2633 2634 /* Carry on with initialization */ 2635 retrieveGLConstantValues(); 2636 initProgramObjects(); 2637 initBufferObjects(); 2638 initReferenceValues(); 2639 2640 gl.enable(GL_RASTERIZER_DISCARD); 2641 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(RASTERIZER_DISCARD) failed!"); 2642 } 2643 2644 /** Initializes reference values that will be compared against 2645 * values generated by the program object. 2646 * Fills m_ref_vertex_attributes and m_ref_patch_attributes arrays. 2647 * These arrays are later used by compareValues() function. 2648 **/ 2649 void TessellationShaderTessellationMaxInOut::initReferenceValues(void) 2650 { 2651 /* Allocate vertex attribute array data needed for reference values preparation. */ 2652 int max_array_size = de::max(m_gl_max_tess_control_input_components_value, 2653 de::max(m_gl_max_tess_control_output_components_value, 2654 de::max(m_gl_max_tess_evaluation_input_components_value, 2655 m_gl_max_tess_evaluation_output_components_value))); 2656 2657 m_ref_vertex_attributes = (glw::GLfloat*)malloc(sizeof(glw::GLfloat) * (max_array_size)); 2658 if (m_ref_vertex_attributes == DE_NULL) 2659 { 2660 throw tcu::ResourceError("Unable to allocate memory!"); 2661 } 2662 2663 /* We need to create an array consisting of gl_max_tess_evaluation_output_components items. 2664 * The array will be filled with the following values: 2665 * 2666 * reference_value[0], 2667 * (...) 2668 * reference_value[gl_max_tess_evaluation_output_components / 4 - 2], 2669 * reference_gl_Position 2670 * 2671 * which corresponds to output block defined for Tessellation Evaluation Stage: 2672 * 2673 * out Vertex 2674 * { 2675 * vec4 value[(gl_MaxTessControlInputComponents) / 4 - 1]; 2676 * } outVertex; 2677 * 2678 * + gl_Position. 2679 */ 2680 glw::GLfloat sumInTCS[] = { 0.0f, 0.0f, 0.0f, 0.0f }; 2681 glw::GLfloat sumInTES[] = { 0.0f, 0.0f, 0.0f, 0.0f }; 2682 2683 for (int i = 0; i < m_gl_max_tess_control_input_components_value - 4; /* gl_Position */ 2684 i++) 2685 { 2686 m_ref_vertex_attributes[i] = (glw::GLfloat)i; 2687 } 2688 2689 for (int i = 0; i < m_gl_max_tess_control_input_components_value - 4; /* gl_Position */ 2690 i++) 2691 { 2692 sumInTCS[i % 4 /* component selector */] += m_ref_vertex_attributes[i]; 2693 } 2694 2695 for (int i = 0; i < m_gl_max_tess_control_output_components_value - 4; /* gl_Position */ 2696 i++) 2697 { 2698 m_ref_vertex_attributes[i] = sumInTCS[i % 4] + (glw::GLfloat)i; 2699 } 2700 2701 for (int i = m_gl_max_tess_control_input_components_value - 4; /* gl_Position */ 2702 i < m_gl_max_tess_control_output_components_value - 4; /* gl_Position */ 2703 i++) 2704 { 2705 m_ref_vertex_attributes[i] = (glw::GLfloat)i; 2706 } 2707 2708 for (int i = 0; i < m_gl_max_tess_evaluation_input_components_value - 4; /* gl_Position */ 2709 i++) 2710 { 2711 sumInTES[i % 4 /* component selector */] += m_ref_vertex_attributes[i]; 2712 } 2713 2714 for (int i = 0; i < m_gl_max_tess_evaluation_output_components_value - 4; /* gl_Position */ 2715 i++) 2716 { 2717 m_ref_vertex_attributes[i] = sumInTES[i % 4 /* component selector */] + (glw::GLfloat)i; 2718 } 2719 2720 for (int i = m_gl_max_tess_evaluation_input_components_value - 4; /* gl_Position */ 2721 i < m_gl_max_tess_evaluation_output_components_value - 4; /* gl_Position */ 2722 i++) 2723 { 2724 m_ref_vertex_attributes[i] = (glw::GLfloat)i; 2725 } 2726 2727 /* Store gl_Position reference values (only first vertex will be compared) */ 2728 m_ref_vertex_attributes[m_gl_max_tess_evaluation_output_components_value - 4] = 0.0f; 2729 m_ref_vertex_attributes[m_gl_max_tess_evaluation_output_components_value - 3] = 0.0f; 2730 m_ref_vertex_attributes[m_gl_max_tess_evaluation_output_components_value - 2] = 0.0f; 2731 m_ref_vertex_attributes[m_gl_max_tess_evaluation_output_components_value - 1] = 1.0f; 2732 2733 /* Set up reference data for case 2 2734 * 2735 * Only one output vector will be needed for comparison. 2736 */ 2737 m_ref_patch_attributes[0] = 0.0f; 2738 m_ref_patch_attributes[1] = 0.0f; 2739 m_ref_patch_attributes[2] = 0.0f; 2740 m_ref_patch_attributes[3] = 0.0f; 2741 2742 for (int i = 0; i < m_gl_max_tess_patch_components_value; i++) 2743 { 2744 m_ref_patch_attributes[i % 4] += (glw::GLfloat)i; 2745 } 2746 } 2747 2748 /** Retrieve OpenGL state and implementation values. 2749 * 2750 * Note the function throws exception should an error occur! 2751 **/ 2752 void TessellationShaderTessellationMaxInOut::retrieveGLConstantValues(void) 2753 { 2754 /* Retrieve ES entry-points. */ 2755 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2756 2757 /* Query implementation constants */ 2758 gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &m_gl_max_vertex_output_components_value); 2759 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_VERTEX_OUTPUT_COMPONENTS pname!"); 2760 2761 gl.getIntegerv(m_glExtTokens.MAX_TESS_CONTROL_INPUT_COMPONENTS, &m_gl_max_tess_control_input_components_value); 2762 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT pname!"); 2763 2764 gl.getIntegerv(m_glExtTokens.MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &m_gl_max_tess_control_output_components_value); 2765 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT pname!"); 2766 2767 gl.getIntegerv(m_glExtTokens.MAX_TESS_PATCH_COMPONENTS, &m_gl_max_tess_patch_components_value); 2768 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_PATCH_COMPONENTS_EXT pname!"); 2769 2770 gl.getIntegerv(m_glExtTokens.MAX_TESS_EVALUATION_INPUT_COMPONENTS, 2771 &m_gl_max_tess_evaluation_input_components_value); 2772 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT pname!"); 2773 2774 gl.getIntegerv(m_glExtTokens.MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, 2775 &m_gl_max_tess_evaluation_output_components_value); 2776 GLU_EXPECT_NO_ERROR(gl.getError(), 2777 "glGetIntegerv() failed for GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT pname!"); 2778 2779 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, 2780 &m_gl_max_transform_feedback_interleaved_components_value); 2781 GLU_EXPECT_NO_ERROR(gl.getError(), 2782 "glGetIntegerv() failed for GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS pname!"); 2783 2784 /* Sanity checks */ 2785 DE_ASSERT(m_gl_max_vertex_output_components_value != 0); 2786 DE_ASSERT(m_gl_max_tess_control_input_components_value != 0); 2787 DE_ASSERT(m_gl_max_tess_control_output_components_value != 0); 2788 DE_ASSERT(m_gl_max_tess_patch_components_value != 0); 2789 DE_ASSERT(m_gl_max_tess_evaluation_input_components_value != 0); 2790 DE_ASSERT(m_gl_max_tess_evaluation_output_components_value != 0); 2791 DE_ASSERT(m_gl_max_transform_feedback_interleaved_components_value != 0); 2792 2793 /* Make sure it is possible to transfer all components through all the stages. 2794 * If not, the test may fail, so we throw not supported. */ 2795 if (m_gl_max_vertex_output_components_value < m_gl_max_tess_control_input_components_value) 2796 { 2797 m_testCtx.getLog() << tcu::TestLog::Message << "Warning: GL_MAX_VERTEX_OUTPUT_COMPONENTS value:" 2798 << m_gl_max_vertex_output_components_value 2799 << " is less than GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT: " 2800 << m_gl_max_tess_control_input_components_value 2801 << ". It may not be possible to pass all GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT " 2802 "per-vertex components from Vertex Shader to Tessellation Control Shader." 2803 << tcu::TestLog::EndMessage; 2804 throw tcu::NotSupportedError("GL_MAX_VERTEX_OUTPUT_COMPONENTS < GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"); 2805 } 2806 2807 if (m_gl_max_tess_control_output_components_value != m_gl_max_tess_evaluation_input_components_value) 2808 { 2809 m_testCtx.getLog() << tcu::TestLog::Message << "Warning: GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT:" 2810 << m_gl_max_tess_control_output_components_value 2811 << " is not equal to GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT:" 2812 << m_gl_max_tess_evaluation_input_components_value 2813 << ". It may not be possible to pass all GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT " 2814 "per-vertex components from Tessellation Control Shader to Tessellation " 2815 "Evaluation Shader." 2816 << tcu::TestLog::EndMessage; 2817 throw tcu::NotSupportedError("GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS != " 2818 "GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS"); 2819 } 2820 2821 if (m_gl_max_tess_evaluation_output_components_value > m_gl_max_transform_feedback_interleaved_components_value) 2822 { 2823 m_testCtx.getLog() << tcu::TestLog::Message << "Warning: GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT:" 2824 << m_gl_max_tess_evaluation_output_components_value 2825 << " is greater than GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:" 2826 << m_gl_max_transform_feedback_interleaved_components_value 2827 << ". It may not be possible to check all GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT " 2828 "per-vertex components from Tessellation Evaluation Shader." 2829 << tcu::TestLog::EndMessage; 2830 throw tcu::NotSupportedError("GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS > " 2831 "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS"); 2832 } 2833 } 2834 2835 /** Maps buffer object storage bound to GL_TRANSFORM_FEEDBACK_BUFFER binding point into process space 2836 * and verifies the downloaded data matches the user-provided reference data. 2837 * 2838 * Note the function throws exception should an error occur! 2839 * 2840 * @param description Case description; 2841 * @param reference_values Array storing reference data; 2842 * @param n_reference_values Number of vec4s available for reading under @param reference_values; 2843 * 2844 * @return false if the comparison failed, or true otherwise. 2845 **/ 2846 bool TessellationShaderTessellationMaxInOut::compareValues(char const* description, glw::GLfloat* reference_values, 2847 int n_reference_values) 2848 { 2849 /* Retrieve ES entry-points */ 2850 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2851 2852 /* Map the buffer storage into process space. */ 2853 glw::GLint bo_size = static_cast<glw::GLint>(2 /* number of vertices */ * sizeof(glw::GLfloat) * 2854 n_reference_values * 4); /* number of components */ 2855 glw::GLfloat* resultFloats = 2856 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_size, GL_MAP_READ_BIT); 2857 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed"); 2858 2859 /* Verify the data */ 2860 const glw::GLfloat epsilon = (glw::GLfloat)1e-5f; 2861 bool test_passed = true; 2862 2863 for (int i = 0; i < n_reference_values * 4 /* number of components */; i += 4 /* number of components */) 2864 { 2865 if ((de::abs(resultFloats[i] - reference_values[i]) > epsilon) || 2866 (de::abs(resultFloats[i + 1] - reference_values[i + 1]) > epsilon) || 2867 (de::abs(resultFloats[i + 2] - reference_values[i + 2]) > epsilon) || 2868 (de::abs(resultFloats[i + 3] - reference_values[i + 3]) > epsilon)) 2869 { 2870 m_testCtx.getLog() << tcu::TestLog::Message << description << ": captured results " 2871 << "vec4(" << resultFloats[i + 0] << ", " << resultFloats[i + 1] << ", " 2872 << resultFloats[i + 2] << ", " << resultFloats[i + 3] << ") " 2873 << "are different from the expected values " 2874 << "vec4(" << reference_values[i + 0] << ", " << reference_values[i + 1] << ", " 2875 << reference_values[i + 2] << ", " << reference_values[i + 3] << ")." 2876 << tcu::TestLog::EndMessage; 2877 2878 test_passed = false; 2879 break; 2880 } 2881 } 2882 2883 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 2884 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed!"); 2885 2886 return test_passed; 2887 } 2888 2889 } /* namespace glcts */ 2890