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 "esextcTessellationShaderMaxPatchVertices.hpp" 25 #include "gluContextInfo.hpp" 26 #include "gluDefs.hpp" 27 #include "glwEnums.hpp" 28 #include "glwFunctions.hpp" 29 #include "tcuTestLog.hpp" 30 #include <cstddef> 31 #include <cstdlib> 32 33 /* The test creates a patch with max patch vertices count size. 34 * The output from the tesselation stage is a single segment (2 vertices). 35 * Use this define when allocating/using the output TF buffer. 36 */ 37 #define OUTPUT_VERTEX_COUNT 2 38 39 namespace glcts 40 { 41 42 /* Vertex Shader code */ 43 const char* TessellationShaderMaxPatchVertices::m_vs_code = "${VERSION}\n" 44 "\n" 45 "${SHADER_IO_BLOCKS_ENABLE}\n" 46 "\n" 47 "precision highp float;\n" 48 "\n" 49 "layout(location = 0) in vec4 in_fv;\n" 50 "layout(location = 1) in ivec4 in_iv;\n" 51 "\n" 52 "out Vertex\n" 53 "{\n" 54 " ivec4 iv;\n" 55 " vec4 fv;\n" 56 "} outVertex;\n" 57 "\n" 58 "void main()\n" 59 "{\n" 60 " gl_Position = in_fv;\n" 61 " outVertex.iv = in_iv;\n" 62 " outVertex.fv = in_fv;\n" 63 "}\n"; 64 65 /* Tessellation Control Shader code (for case with explicit array size) */ 66 const char* TessellationShaderMaxPatchVertices::m_tc_code = 67 "${VERSION}\n" 68 "\n" 69 "${TESSELLATION_SHADER_REQUIRE}\n" 70 "\n" 71 "precision highp float;\n" 72 "\n" 73 "in Vertex\n" 74 "{\n" 75 " ivec4 iv;\n" 76 " vec4 fv;\n" 77 "} inVertex[];\n" 78 "\n" 79 "layout(vertices = 2) out;\n" /* One segment only. */ 80 "\n" 81 "out Vertex\n" 82 "{\n" 83 " ivec4 iv;\n" 84 " vec4 fv;\n" 85 "} outVertex[];\n" 86 "\n" 87 "void main()\n" 88 "{\n" 89 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 90 " outVertex[gl_InvocationID].iv = ivec4(0);\n" 91 " outVertex[gl_InvocationID].fv = vec4(0);\n" 92 "\n" 93 " for (int i = 0; i < gl_PatchVerticesIn; i++)\n" 94 " {\n" 95 " outVertex[gl_InvocationID].iv += inVertex[i].iv;\n" 96 " outVertex[gl_InvocationID].fv += inVertex[i].fv;\n" 97 " }\n" 98 "\n" 99 " gl_TessLevelInner[0] = 1.0;\n" 100 " gl_TessLevelInner[1] = 1.0;\n" 101 " gl_TessLevelOuter[0] = 1.0;\n" 102 " gl_TessLevelOuter[1] = 1.0;\n" 103 " gl_TessLevelOuter[2] = 1.0;\n" 104 " gl_TessLevelOuter[3] = 1.0;\n" 105 "}\n"; 106 107 /* Tessellation Evaluation Shader code (for case */ 108 const char* TessellationShaderMaxPatchVertices::m_te_code = "${VERSION}\n" 109 "\n" 110 "${TESSELLATION_SHADER_REQUIRE}\n" 111 "\n" 112 "precision highp float;\n" 113 "\n" 114 "layout (isolines, point_mode) in;\n" 115 "\n" 116 "in Vertex\n" 117 "{\n" 118 " ivec4 iv;\n" 119 " vec4 fv;\n" 120 "} inVertex[];\n" 121 "\n" 122 "out vec4 result_fv;\n" 123 "out ivec4 result_iv;\n" 124 "\n" 125 "void main()\n" 126 "{\n" 127 " gl_Position = gl_in[0].gl_Position;\n" 128 " result_iv = ivec4(0);\n" 129 " result_fv = vec4(0.0);\n" 130 "\n" 131 " for (int i = 0 ; i < gl_PatchVerticesIn; i++)\n" 132 " {\n" 133 " result_iv += inVertex[i].iv;\n" 134 " result_fv += inVertex[i].fv;\n" 135 " }\n" 136 "}\n"; 137 138 /* Fragment Shader code */ 139 const char* TessellationShaderMaxPatchVertices::m_fs_code = "${VERSION}\n" 140 "\n" 141 "void main()\n" 142 "{\n" 143 "}\n"; 144 145 /* Transform Feedback varyings */ 146 const char* const TessellationShaderMaxPatchVertices::m_tf_varyings[] = { "result_fv", "result_iv" }; 147 148 /** Constructor 149 * 150 * @param context Test context 151 * @param name Test case's name 152 * @param description Test case's description 153 **/ 154 TessellationShaderMaxPatchVertices::TessellationShaderMaxPatchVertices(Context& context, const ExtParameters& extParams) 155 : TestCaseBase(context, extParams, "max_patch_vertices", 156 "Make sure it is possible to use up to gl_MaxPatchVertices vertices." 157 " TCS must be able to correctly access all vertices in an input patch") 158 , m_bo_id_f_1(0) 159 , m_bo_id_f_2(0) 160 , m_bo_id_i_1(0) 161 , m_bo_id_i_2(0) 162 , m_fs_id(0) 163 , m_po_id_1(0) 164 , m_po_id_2(0) 165 , m_tc_id(0) 166 , m_te_id(0) 167 , m_tf_id_1(0) 168 , m_tf_id_2(0) 169 , m_vs_id(0) 170 , m_vao_id(0) 171 , m_gl_max_patch_vertices(0) 172 , m_patch_vertices_bo_f_id(0) 173 , m_patch_vertices_bo_i_id(0) 174 , m_patch_vertices_f(DE_NULL) 175 , m_patch_vertices_i(DE_NULL) 176 { 177 } 178 179 /** Deinitializes all ES objects created for the test. */ 180 void TessellationShaderMaxPatchVertices::deinit(void) 181 { 182 /* Deinitialize parent. */ 183 TestCaseBase::deinit(); 184 185 if (!m_is_tessellation_shader_supported) 186 { 187 return; 188 } 189 190 /* Dealocate input array of patch vertices. */ 191 if (m_patch_vertices_f != DE_NULL) 192 { 193 free(m_patch_vertices_f); 194 195 m_patch_vertices_f = DE_NULL; 196 } 197 198 if (m_patch_vertices_i != DE_NULL) 199 { 200 free(m_patch_vertices_i); 201 202 m_patch_vertices_i = DE_NULL; 203 } 204 205 /* Retrieve ES entry-points. */ 206 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 207 208 /* Set back to default program */ 209 gl.useProgram(0); 210 211 /* Revert GL_PATCH_VERTICES_EXT value to the default setting */ 212 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 213 214 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 215 { 216 /* Revert GL_PATCH_DEFAULT_INNER_LEVEL and GL_PATCH_DEFAULT_OUTER_LEVEL pname 217 * values to the default settings */ 218 const float default_levels[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 219 220 gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, default_levels); 221 gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, default_levels); 222 } 223 224 /* Disable vertex attribute arrays that may have been enabled for the test */ 225 gl.disableVertexAttribArray(0); 226 gl.disableVertexAttribArray(1); 227 228 /* Unbind buffer objects from TF binding points */ 229 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 230 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 231 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1 /* index */, 0 /* buffer */); 232 233 /* Unbind transform feedback object */ 234 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0 /* id */); 235 236 /* Disable GL_RASTERIZER_DISCARD mode */ 237 gl.disable(GL_RASTERIZER_DISCARD); 238 239 /* Unbind vertex array object */ 240 gl.bindVertexArray(0); 241 242 /* Delete OpenGL objects */ 243 if (m_bo_id_f_1 != 0) 244 { 245 gl.deleteBuffers(1, &m_bo_id_f_1); 246 247 m_bo_id_f_1 = 0; 248 } 249 250 if (m_bo_id_f_2 != 0) 251 { 252 gl.deleteBuffers(1, &m_bo_id_f_2); 253 254 m_bo_id_f_2 = 0; 255 } 256 257 if (m_bo_id_i_1 != 0) 258 { 259 gl.deleteBuffers(1, &m_bo_id_i_1); 260 261 m_bo_id_i_1 = 0; 262 } 263 264 if (m_bo_id_i_2 != 0) 265 { 266 gl.deleteBuffers(1, &m_bo_id_i_2); 267 268 m_bo_id_i_2 = 0; 269 } 270 271 if (m_patch_vertices_bo_f_id != 0) 272 { 273 gl.deleteBuffers(1, &m_patch_vertices_bo_f_id); 274 275 m_patch_vertices_bo_f_id = 0; 276 } 277 278 if (m_patch_vertices_bo_i_id != 0) 279 { 280 gl.deleteBuffers(1, &m_patch_vertices_bo_i_id); 281 282 m_patch_vertices_bo_i_id = 0; 283 } 284 285 if (m_vs_id != 0) 286 { 287 gl.deleteShader(m_vs_id); 288 289 m_vs_id = 0; 290 } 291 292 if (m_tc_id != 0) 293 { 294 gl.deleteShader(m_tc_id); 295 296 m_tc_id = 0; 297 } 298 299 if (m_te_id != 0) 300 { 301 gl.deleteShader(m_te_id); 302 303 m_te_id = 0; 304 } 305 306 if (m_fs_id != 0) 307 { 308 gl.deleteShader(m_fs_id); 309 310 m_fs_id = 0; 311 } 312 313 if (m_tf_id_1 != 0) 314 { 315 gl.deleteTransformFeedbacks(1, &m_tf_id_1); 316 317 m_tf_id_1 = 0; 318 } 319 320 if (m_tf_id_2 != 0) 321 { 322 gl.deleteTransformFeedbacks(1, &m_tf_id_2); 323 324 m_tf_id_2 = 0; 325 } 326 327 if (m_po_id_1 != 0) 328 { 329 gl.deleteProgram(m_po_id_1); 330 331 m_po_id_1 = 0; 332 } 333 334 if (m_po_id_2 != 0) 335 { 336 gl.deleteProgram(m_po_id_2); 337 338 m_po_id_2 = 0; 339 } 340 341 if (m_vao_id != 0) 342 { 343 gl.deleteVertexArrays(1, &m_vao_id); 344 345 m_vao_id = 0; 346 } 347 } 348 349 /** Initializes all ES objects and reference values for the test. */ 350 void TessellationShaderMaxPatchVertices::initTest(void) 351 { 352 /* This test runs for two cases: 353 * 354 * 1) The patch size is explicitly defined to be equal to gl_MaxPatchVertices. 355 * (The Tessellation Control Shader gets 32 vertices, then it access them 356 * and it outputs 2 vertices to Tessllation Evaluation Shader. Next Tessllation 357 * Evaluation Shader sends 1 segment of an isoline to the output). 358 * 2) The patch size is implicitly defined to be equal to gl_MaxPatchVertices. 359 * (There is no Tessellation Control Shader. Tessllation Evaluation Shader 360 * gets 32 vertices, then it access them. Next (gl_MaxPatchVertices-1) segments 361 * of the isoline are send to the output.) 362 */ 363 364 /* Retrieve ES entry/state points. */ 365 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 366 367 /* Initialize vertex array object */ 368 gl.genVertexArrays(1, &m_vao_id); 369 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 370 371 gl.bindVertexArray(m_vao_id); 372 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 373 374 /* Query GL_MAX_PATCH_VERTICES_EXT value */ 375 gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices); 376 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_PATCH_VERTICES_EXT pname!"); 377 378 /* Set maximum number of vertices in the patch. */ 379 gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, m_gl_max_patch_vertices); 380 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname!"); 381 382 /* Build programs */ 383 initProgramObjects(); 384 385 /* Initialize tessellation buffers */ 386 initTransformFeedbackBufferObjects(); 387 388 /* Initialize input vertices */ 389 initVertexBufferObjects(); 390 391 /* Reference values setup */ 392 initReferenceValues(); 393 } 394 395 /** Initializes buffer objects for the test. */ 396 void TessellationShaderMaxPatchVertices::initVertexBufferObjects(void) 397 { 398 /* Retrieve ES entry/state points. */ 399 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 400 401 /* Input patch vertices buffer setup. */ 402 m_patch_vertices_f = (glw::GLfloat*)malloc(m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLfloat)); 403 404 if (m_patch_vertices_f == DE_NULL) 405 { 406 TCU_FAIL("Memory allocation failed!"); 407 } 408 409 m_patch_vertices_i = (glw::GLint*)malloc(m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLint)); 410 411 if (m_patch_vertices_i == DE_NULL) 412 { 413 TCU_FAIL("Memory allocation failed!"); 414 } 415 416 for (int i = 0; i < m_gl_max_patch_vertices * 4 /* components */; i += 4 /* components */) 417 { 418 m_patch_vertices_f[i] = 1.0f; 419 m_patch_vertices_f[i + 1] = 2.0f; 420 m_patch_vertices_f[i + 2] = 3.0f; 421 m_patch_vertices_f[i + 3] = 4.0f; 422 423 m_patch_vertices_i[i] = 1; 424 m_patch_vertices_i[i + 1] = 2; 425 m_patch_vertices_i[i + 2] = 3; 426 m_patch_vertices_i[i + 3] = 4; 427 } 428 429 /* Vec4 vertex attribute array setup. */ 430 gl.genBuffers(1, &m_patch_vertices_bo_f_id); 431 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!"); 432 433 gl.bindBuffer(GL_ARRAY_BUFFER, m_patch_vertices_bo_f_id); 434 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 435 436 gl.bufferData(GL_ARRAY_BUFFER, m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLfloat), 437 m_patch_vertices_f, GL_STATIC_DRAW); 438 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed!"); 439 440 gl.vertexAttribPointer(0, /* index */ 441 4, /* size */ 442 GL_FLOAT, /* type */ 443 GL_FALSE, /* normalized */ 444 0, /* stride */ 445 0); /* pointer */ 446 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer(fv) failed!"); 447 448 gl.enableVertexAttribArray(0); 449 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray(fv) failed!"); 450 451 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 452 453 /* Ivec4 vertex attribute array setup. */ 454 gl.genBuffers(1, &m_patch_vertices_bo_i_id); 455 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers(ARRAY_BUFFER) failed!"); 456 457 gl.bindBuffer(GL_ARRAY_BUFFER, m_patch_vertices_bo_i_id); 458 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer(ARRAY_BUFFER) failed!"); 459 460 gl.bufferData(GL_ARRAY_BUFFER, m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLint), 461 m_patch_vertices_i, GL_STATIC_DRAW); 462 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData(ARRAY_BUFFER) failed!"); 463 464 gl.vertexAttribIPointer(1, /* index */ 465 4, /* size */ 466 GL_INT, 0, /* stride */ 467 0); /* pointer */ 468 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer(iv) failed!"); 469 470 gl.enableVertexAttribArray(1); 471 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray(iv) failed!"); 472 473 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 474 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 475 } 476 477 /** Initializes buffer objects for the test. */ 478 void TessellationShaderMaxPatchVertices::initTransformFeedbackBufferObjects(void) 479 { 480 /* Retrieve ES entry/state points. */ 481 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 482 483 /* Creating Transform Feedback buffer objects. */ 484 gl.genBuffers(1, &m_bo_id_f_1); 485 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 486 487 gl.genBuffers(1, &m_bo_id_f_2); 488 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 489 490 gl.genBuffers(1, &m_bo_id_i_1); 491 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 492 493 gl.genBuffers(1, &m_bo_id_i_2); 494 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 495 496 /* Transform feedback buffers for case 1*/ 497 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1); 498 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!"); 499 500 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_1); 501 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 502 503 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 504 ((sizeof(glw::GLfloat)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL, 505 GL_STATIC_DRAW); 506 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 507 508 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_1); 509 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 510 511 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 512 ((sizeof(glw::GLint)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL, 513 GL_STATIC_DRAW); 514 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 515 516 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 517 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback(0) failed"); 518 519 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 520 { 521 /* Transform feedback buffers for case 2*/ 522 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2); 523 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!"); 524 525 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_2); 526 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 527 528 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 529 ((sizeof(glw::GLfloat)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL, 530 GL_STATIC_DRAW); 531 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 532 533 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_2); 534 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 535 536 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 537 ((sizeof(glw::GLint)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL, 538 GL_STATIC_DRAW); 539 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 540 541 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 542 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback(0) failed"); 543 544 gl.transformFeedbackVaryings(m_po_id_2, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS); 545 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!"); 546 } 547 } 548 549 /** Initializes program objects for the test. */ 550 void TessellationShaderMaxPatchVertices::initProgramObjects(void) 551 { 552 /* Retrieve ES entry/state points. */ 553 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 554 555 /* Create and configure shader objects. */ 556 m_po_id_1 = gl.createProgram(); 557 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!"); 558 559 m_po_id_2 = gl.createProgram(); 560 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!"); 561 562 /* Creating Transform Feedback objects. */ 563 gl.genTransformFeedbacks(1, &m_tf_id_1); 564 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() failed!"); 565 566 gl.genTransformFeedbacks(1, &m_tf_id_2); 567 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() failed!"); 568 569 /* Create and configure shader objects. */ 570 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 571 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(VERTEX_SHADER) failed!"); 572 573 m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 574 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!"); 575 576 m_te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 577 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!"); 578 579 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 580 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!"); 581 582 /* Transform Feedback setup case 1 (explicit arrays).*/ 583 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1); 584 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!"); 585 586 gl.transformFeedbackVaryings(m_po_id_1, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS); 587 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!"); 588 589 /* Build the program object case 1 (explicit arrays).*/ 590 if (!buildProgram(m_po_id_1, m_vs_id, 1, &m_vs_code, m_tc_id, 1, &m_tc_code, m_te_id, 1, &m_te_code, m_fs_id, 1, 591 &m_fs_code)) 592 { 593 TCU_FAIL("Program linking failed!"); 594 } 595 596 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 597 { 598 /* Transform Feedback setup case 2 (implicit arrays).*/ 599 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2); 600 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!"); 601 602 gl.transformFeedbackVaryings(m_po_id_2, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS); 603 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!"); 604 605 /* Build the program object case 2 (implicit arrays). */ 606 if (!buildProgram(m_po_id_2, m_vs_id, 1, &m_vs_code, m_te_id, 1, &m_te_code, m_fs_id, 1, &m_fs_code)) 607 { 608 TCU_FAIL("Program linking failed!"); 609 } 610 } 611 } 612 613 /** Initializes reference values for the test. */ 614 void TessellationShaderMaxPatchVertices::initReferenceValues(void) 615 { 616 /* Reference values setup. */ 617 m_ref_fv_case_1[0] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 1.0f); 618 m_ref_fv_case_1[1] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 2.0f); 619 m_ref_fv_case_1[2] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 3.0f); 620 m_ref_fv_case_1[3] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 4.0f); 621 622 m_ref_iv_case_1[0] = (m_gl_max_patch_vertices * 2 * 1); 623 m_ref_iv_case_1[1] = (m_gl_max_patch_vertices * 2 * 2); 624 m_ref_iv_case_1[2] = (m_gl_max_patch_vertices * 2 * 3); 625 m_ref_iv_case_1[3] = (m_gl_max_patch_vertices * 2 * 4); 626 627 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 628 { 629 m_ref_fv_case_2[0] = ((glw::GLfloat)m_gl_max_patch_vertices * 1.0f); 630 m_ref_fv_case_2[1] = ((glw::GLfloat)m_gl_max_patch_vertices * 2.0f); 631 m_ref_fv_case_2[2] = ((glw::GLfloat)m_gl_max_patch_vertices * 3.0f); 632 m_ref_fv_case_2[3] = ((glw::GLfloat)m_gl_max_patch_vertices * 4.0f); 633 634 m_ref_iv_case_2[0] = (m_gl_max_patch_vertices * 1); 635 m_ref_iv_case_2[1] = (m_gl_max_patch_vertices * 2); 636 m_ref_iv_case_2[2] = (m_gl_max_patch_vertices * 3); 637 m_ref_iv_case_2[3] = (m_gl_max_patch_vertices * 4); 638 } 639 } 640 641 /** Compares values of vec4 results with the reference data. 642 * 643 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed. 644 * 645 * Note the function throws exception should an error occur! 646 * 647 * @param description Test case's description. 648 * @param ref_fv Reference value. 649 * 650 * @return true if test passed; 651 * false if test failed. 652 **/ 653 bool TessellationShaderMaxPatchVertices::compareResults(const char* description, glw::GLfloat ref_fv[4]) 654 { 655 /* Retrieve ES entry/state points. */ 656 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 657 const glw::GLfloat* resultFloats = DE_NULL; 658 659 resultFloats = (const glw::GLfloat*)gl.mapBufferRange( 660 GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 661 (sizeof(glw::GLfloat) /* GLfloat size */ * 4 /* components */ * OUTPUT_VERTEX_COUNT), GL_MAP_READ_BIT); 662 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(floats) failed"); 663 664 /* Comparison of vec4. */ 665 const glw::GLfloat epsilon = (glw::GLfloat)1e-5f; 666 bool test_failed = false; 667 668 for (int i = 0; i < 4 /* components */; i++) 669 { 670 if (de::abs(resultFloats[i] - ref_fv[i]) > epsilon) 671 { 672 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 673 674 m_testCtx.getLog() << tcu::TestLog::Message << description << " captured results " 675 << "vec4(" << resultFloats[0] << ", " << resultFloats[1] << ", " << resultFloats[2] 676 << ", " << resultFloats[3] << ") " 677 << "are different from the expected values " 678 << "vec4(" << ref_fv[0] << ", " << ref_fv[1] << ", " << ref_fv[2] << ", " << ref_fv[3] 679 << ")." << tcu::TestLog::EndMessage; 680 681 test_failed = true; 682 break; 683 } 684 } 685 686 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 687 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed!"); 688 689 return !test_failed; 690 } 691 692 /** Compares values of ivec4 results with the reference data. 693 * 694 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed. 695 * 696 * Note the function throws exception should an error occur! 697 * 698 * @param description Test case's description. 699 * @param ref_iv Reference value. 700 * 701 * @return true if test passed. 702 * false if test failed. 703 **/ 704 bool TessellationShaderMaxPatchVertices::compareResults(const char* description, glw::GLint ref_iv[4]) 705 { 706 /* Retrieve ES entry/state points. */ 707 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 708 const glw::GLint* resultInts = DE_NULL; 709 710 resultInts = (const glw::GLint*)gl.mapBufferRange( 711 GL_TRANSFORM_FEEDBACK_BUFFER, 0, 712 (sizeof(glw::GLint) /* GLfloat size */ * 4 /* components */ * OUTPUT_VERTEX_COUNT), GL_MAP_READ_BIT); 713 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(ints) failed"); 714 715 bool test_failed = false; 716 717 /* Comparison of ivec4. */ 718 for (int i = 0; i < 4 /* components */; i++) 719 { 720 if (resultInts[i] != ref_iv[i]) 721 { 722 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 723 724 m_testCtx.getLog() << tcu::TestLog::Message << description << " captured results ivec4(" << resultInts[0] 725 << ", " << resultInts[1] << ", " << resultInts[2] << ", " << resultInts[3] << ") " 726 << "are different from the expected values ivec4(" << ref_iv[0] << ", " << ref_iv[1] 727 << ", " << ref_iv[2] << ", " << ref_iv[3] << ")." << tcu::TestLog::EndMessage; 728 729 test_failed = true; 730 break; 731 } 732 } 733 734 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 735 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed!"); 736 737 return !test_failed; 738 } 739 740 /** Executes the test. 741 * 742 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 743 * 744 * Note the function throws exception should an error occur! 745 * 746 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 747 **/ 748 tcu::TestNode::IterateResult TessellationShaderMaxPatchVertices::iterate(void) 749 { 750 /* Skip if required extensions are not supported. */ 751 if (!m_is_tessellation_shader_supported) 752 { 753 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 754 } 755 756 /* Retrieve ES entry/state points. */ 757 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 758 759 /* Initialization */ 760 initTest(); 761 762 /* Render setup case 1. */ 763 gl.useProgram(m_po_id_1); 764 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!"); 765 766 gl.enable(GL_RASTERIZER_DISCARD); 767 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(RASTERIZER_DISCARD) failed!"); 768 769 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1); 770 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!"); 771 772 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_f_1); 773 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!"); 774 775 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_i_1); 776 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!"); 777 778 /* Rendering case 1 with transform feedback.*/ 779 gl.beginTransformFeedback(GL_POINTS); 780 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed"); 781 782 gl.drawArrays(m_glExtTokens.PATCHES, 0, m_gl_max_patch_vertices); 783 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 784 785 gl.endTransformFeedback(); 786 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed"); 787 788 /* Compare vec4 results from transform feedback for case 1. */ 789 bool test_passed = true; 790 791 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_1); 792 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 793 794 test_passed &= compareResults("Case 1 (explicit arrays)", m_ref_fv_case_1); 795 796 /* Compare ivec4 results from transform feedback for case 2. */ 797 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_1); 798 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 799 800 test_passed &= compareResults("Case 1 (explicit arrays)", m_ref_iv_case_1); 801 802 // Case 2 tests with no TCS (default TCS is expected to be used). 803 // Since this is not allowed by ES 3.1, just skip it. 804 // Leaving the code for Desktop 805 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 806 { 807 /* Set up rendering for case 2. */ 808 gl.useProgram(m_po_id_2); 809 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!"); 810 811 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2); 812 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!"); 813 814 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id_f_2); 815 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!"); 816 817 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1 /* index */, m_bo_id_i_2); 818 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!"); 819 820 /* Tessellation Control Levels setup. */ 821 const glw::GLfloat inner[] = { 1.0, 1.0 }; 822 const glw::GLfloat outer[] = { 1.0, 1.0, 1.0, 1.0 }; 823 824 gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, outer); 825 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() failed!"); 826 827 gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, inner); 828 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() failed!"); 829 830 /* Rendering case 2 with transform feedback. */ 831 gl.beginTransformFeedback(GL_POINTS); 832 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_POINTS) failed"); 833 834 gl.drawArrays(GL_PATCHES, 0, m_gl_max_patch_vertices); 835 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 836 837 gl.endTransformFeedback(); 838 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed"); 839 840 /* Compare vec4 results from transform feedback for case 2. */ 841 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_2); 842 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 843 844 test_passed &= compareResults("Case 2 (implicit arrays)", m_ref_fv_case_2); 845 846 /* Compare ivec4 results from transform feedback for case 2. */ 847 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_2); 848 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!"); 849 850 test_passed &= compareResults("Case 2 (implicit arrays)", m_ref_iv_case_2); 851 } 852 /* All done */ 853 if (test_passed) 854 { 855 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 856 } 857 858 return STOP; 859 } 860 861 } /* namespace glcts */ 862