1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2015-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 #include "esextcGeometryShaderAPI.hpp" 24 25 #include "gluDefs.hpp" 26 #include "glwEnums.hpp" 27 #include "glwFunctions.hpp" 28 #include "tcuTestLog.hpp" 29 #include <cstring> 30 31 namespace glcts 32 { 33 34 static const char* dummy_fs_code = "${VERSION}\n" 35 "\n" 36 "precision highp float;\n" 37 "\n" 38 "out vec4 result;\n" 39 "\n" 40 "void main()\n" 41 "{\n" 42 " result = vec4(1.0);\n" 43 "}\n"; 44 45 static const char* dummy_gs_code = "${VERSION}\n" 46 "${GEOMETRY_SHADER_REQUIRE}\n" 47 "\n" 48 "layout (points) in;\n" 49 "layout (points, max_vertices = 1) out;\n" 50 "\n" 51 "${OUT_PER_VERTEX_DECL}" 52 "${IN_DATA_DECL}" 53 "void main()\n" 54 "{\n" 55 "${POSITION_WITH_IN_DATA}" 56 " EmitVertex();\n" 57 "}\n"; 58 59 static const char* dummy_vs_code = "${VERSION}\n" 60 "\n" 61 "${OUT_PER_VERTEX_DECL}" 62 "\n" 63 "void main()\n" 64 "{\n" 65 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" 66 "}\n"; 67 68 /* createShaderProgramv conformance test shaders */ 69 const char* GeometryShaderCreateShaderProgramvTest::fs_code = "${VERSION}\n" 70 "\n" 71 "precision highp float;\n" 72 "\n" 73 "out vec4 result;\n" 74 "\n" 75 "void main()\n" 76 "{\n" 77 " result = vec4(0.0, 1.0, 0.0, 0.0);\n" 78 "}\n"; 79 80 const char* GeometryShaderCreateShaderProgramvTest::gs_code = "${VERSION}\n" 81 "${GEOMETRY_SHADER_REQUIRE}\n" 82 "\n" 83 "layout (points) in;\n" 84 "layout (triangle_strip, max_vertices = 4) out;\n" 85 "\n" 86 "${OUT_PER_VERTEX_DECL}" 87 "\n" 88 "void main()\n" 89 "{\n" 90 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 91 " EmitVertex();\n" 92 "\n" 93 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 94 " EmitVertex();\n" 95 "\n" 96 " gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n" 97 " EmitVertex();\n" 98 "\n" 99 " gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n" 100 " EmitVertex();\n" 101 " EndPrimitive();\n" 102 "}\n"; 103 104 const char* GeometryShaderCreateShaderProgramvTest::vs_code = "${VERSION}\n" 105 "\n" 106 "${OUT_PER_VERTEX_DECL}" 107 "\n" 108 "void main()\n" 109 "{\n" 110 " gl_Position = vec4(-10.0, -10.0, -10.0, 0.0);\n" 111 "}\n"; 112 113 const unsigned int GeometryShaderCreateShaderProgramvTest::m_to_height = 4; 114 const unsigned int GeometryShaderCreateShaderProgramvTest::m_to_width = 4; 115 116 /** Constructor 117 * 118 * @param context Test context 119 * @param extParams Not used. 120 * @param name Test case's name 121 * @param description Test case's description 122 **/ 123 GeometryShaderCreateShaderProgramvTest::GeometryShaderCreateShaderProgramvTest(Context& context, 124 const ExtParameters& extParams, 125 const char* name, 126 const char* description) 127 : TestCaseBase(context, extParams, name, description) 128 , m_fbo_id(0) 129 , m_fs_po_id(0) 130 , m_gs_po_id(0) 131 , m_pipeline_object_id(0) 132 , m_to_id(0) 133 , m_vao_id(0) 134 , m_vs_po_id(0) 135 { 136 } 137 138 /** Deinitializes GLES objects created during the test. */ 139 void GeometryShaderCreateShaderProgramvTest::deinit() 140 { 141 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 142 143 if (m_fbo_id != 0) 144 { 145 gl.deleteFramebuffers(1, &m_fbo_id); 146 147 m_fbo_id = 0; 148 } 149 150 if (m_fs_po_id != 0) 151 { 152 gl.deleteProgram(m_fs_po_id); 153 154 m_fs_po_id = 0; 155 } 156 157 if (m_gs_po_id != 0) 158 { 159 gl.deleteProgram(m_gs_po_id); 160 161 m_gs_po_id = 0; 162 } 163 164 if (m_pipeline_object_id != 0) 165 { 166 gl.deleteProgramPipelines(1, &m_pipeline_object_id); 167 168 m_pipeline_object_id = 0; 169 } 170 171 if (m_to_id != 0) 172 { 173 gl.deleteTextures(1, &m_to_id); 174 175 m_to_id = 0; 176 } 177 178 if (m_vao_id != 0) 179 { 180 gl.deleteVertexArrays(1, &m_vao_id); 181 182 m_vao_id = 0; 183 } 184 185 if (m_vs_po_id != 0) 186 { 187 gl.deleteProgram(m_vs_po_id); 188 189 m_vs_po_id = 0; 190 } 191 192 /* Release base class */ 193 TestCaseBase::deinit(); 194 } 195 196 /** Initializes a framebuffer object used by the conformance test. */ 197 void GeometryShaderCreateShaderProgramvTest::initFBO() 198 { 199 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 200 201 /* Generate a FBO */ 202 gl.genFramebuffers(1, &m_fbo_id); 203 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed."); 204 205 /* Generate a TO */ 206 gl.genTextures(1, &m_to_id); 207 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 208 209 /* Set the TO up */ 210 gl.bindTexture(GL_TEXTURE_2D, m_to_id); 211 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 212 213 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 214 GL_RGBA8, m_to_width, m_to_height); 215 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed."); 216 217 /* Set up the FBO */ 218 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 219 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 220 221 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0); /* level */ 222 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 223 224 /* Set up the viewport */ 225 gl.viewport(0, /* x */ 226 0, /* y */ 227 m_to_width, m_to_height); 228 229 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed."); 230 } 231 232 /* Initializes a pipeline object used by the conformance test */ 233 void GeometryShaderCreateShaderProgramvTest::initPipelineObject() 234 { 235 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 236 237 DE_ASSERT(m_fs_po_id != 0 && m_gs_po_id != 0 && m_vs_po_id != 0); 238 239 gl.genProgramPipelines(1, &m_pipeline_object_id); 240 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); 241 242 gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id); 243 gl.useProgramStages(m_pipeline_object_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id); 244 gl.useProgramStages(m_pipeline_object_id, GL_VERTEX_SHADER_BIT, m_vs_po_id); 245 246 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed."); 247 } 248 249 /** Executes the test. 250 * 251 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 252 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 253 * Note the function throws exception should an error occur! 254 **/ 255 tcu::TestNode::IterateResult GeometryShaderCreateShaderProgramvTest::iterate() 256 { 257 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 258 const unsigned int n_so_po_ids = 3; 259 bool result = true; 260 glw::GLuint so_po_ids[n_so_po_ids]; 261 262 /* This test should only run if EXT_geometry_shader is supported. */ 263 if (!m_is_geometry_shader_extension_supported) 264 { 265 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 266 } 267 268 /* Initialize off-screen rendering */ 269 initFBO(); 270 271 /* Form shader sources */ 272 std::string fs_specialized_code = specializeShader(1, 273 /* parts */ &fs_code); 274 const char* fs_specialized_code_raw = fs_specialized_code.c_str(); 275 std::string gs_specialized_code = specializeShader(1, 276 /* parts */ &gs_code); 277 const char* gs_specialized_code_raw = gs_specialized_code.c_str(); 278 std::string vs_specialized_code = specializeShader(1, 279 /* parts */ &vs_code); 280 const char* vs_specialized_code_raw = vs_specialized_code.c_str(); 281 282 /* Try to create an invalid geometry shader program first */ 283 glw::GLint link_status = GL_TRUE; 284 285 m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */ 286 &gs_code); 287 288 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 289 290 if (m_gs_po_id == 0) 291 { 292 m_testCtx.getLog() << tcu::TestLog::Message << "glCreateShaderProgramv() call returned 0." 293 << tcu::TestLog::EndMessage; 294 295 result = false; 296 goto end; 297 } 298 299 gl.getProgramiv(m_gs_po_id, GL_LINK_STATUS, &link_status); 300 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 301 302 if (link_status != GL_FALSE) 303 { 304 m_testCtx.getLog() << tcu::TestLog::Message << "An invalid shader program was linked successfully." 305 << tcu::TestLog::EndMessage; 306 307 result = false; 308 goto end; 309 } 310 311 gl.deleteProgram(m_gs_po_id); 312 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed."); 313 314 /* Create shader programs */ 315 m_fs_po_id = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, /* count */ 316 &fs_specialized_code_raw); 317 m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */ 318 &gs_specialized_code_raw); 319 m_vs_po_id = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, /* count */ 320 &vs_specialized_code_raw); 321 322 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call(s) failed."); 323 324 if (m_fs_po_id == 0 || m_gs_po_id == 0 || m_vs_po_id == 0) 325 { 326 m_testCtx.getLog() << tcu::TestLog::Message << "At least one glCreateShaderProgramv() call returned 0." 327 << tcu::TestLog::EndMessage; 328 329 result = false; 330 goto end; 331 } 332 333 /* Make sure all shader programs were linked successfully */ 334 so_po_ids[0] = m_fs_po_id; 335 so_po_ids[1] = m_gs_po_id; 336 so_po_ids[2] = m_vs_po_id; 337 338 for (unsigned int n_po_id = 0; n_po_id != n_so_po_ids; ++n_po_id) 339 { 340 gl.getProgramiv(so_po_ids[n_po_id], GL_LINK_STATUS, &link_status); 341 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 342 343 if (link_status != GL_TRUE) 344 { 345 m_testCtx.getLog() << tcu::TestLog::Message << "A valid shader program with id [" << so_po_ids[n_po_id] 346 << "] was not linked successfully." << tcu::TestLog::EndMessage; 347 348 result = false; 349 goto end; 350 } 351 } 352 353 /* Set up the vertex array object */ 354 gl.genVertexArrays(1, &m_vao_id); 355 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 356 357 gl.bindVertexArray(m_vao_id); 358 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 359 360 /* Set up the pipeline object */ 361 initPipelineObject(); 362 363 /* Render a full-screen quad */ 364 gl.bindProgramPipeline(m_pipeline_object_id); 365 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 366 367 gl.drawArrays(GL_POINTS, 0, /* first */ 368 1); /* count */ 369 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 370 371 /* Verify the rendering result */ 372 unsigned char result_data[m_to_width * m_to_height * 4 /* rgba */]; 373 374 gl.readPixels(0, /* x */ 375 0, /* y */ 376 m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, result_data); 377 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 378 379 for (unsigned int y = 0; y < m_to_height; ++y) 380 { 381 unsigned char* traveller_ptr = result_data + 4 * y; 382 383 for (unsigned int x = 0; x < m_to_width; ++x) 384 { 385 if (traveller_ptr[0] != 0 || traveller_ptr[1] != 255 || traveller_ptr[2] != 0 || traveller_ptr[3] != 0) 386 { 387 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid result texel found at (" << x << ", " << y 388 << ")." << tcu::TestLog::EndMessage; 389 390 result = false; 391 } 392 393 traveller_ptr += 4; /* rgba */ 394 } 395 } 396 397 end: 398 if (result) 399 { 400 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 401 } 402 else 403 { 404 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 405 } 406 407 return STOP; 408 } 409 410 /** Constructor 411 * 412 * @param context Test context 413 * @param extParams Not used. 414 * @param name Test case's name 415 * @param description Test case's description 416 **/ 417 GeometryShaderGetShaderivTest::GeometryShaderGetShaderivTest(Context& context, const ExtParameters& extParams, 418 const char* name, const char* description) 419 : TestCaseBase(context, extParams, name, description), m_gs_id(0) 420 { 421 } 422 423 /** Deinitializes GLES objects created during the test. */ 424 void GeometryShaderGetShaderivTest::deinit() 425 { 426 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 427 428 if (m_gs_id != 0) 429 { 430 gl.deleteShader(m_gs_id); 431 432 m_gs_id = 0; 433 } 434 435 /* Release base class */ 436 TestCaseBase::deinit(); 437 } 438 439 /** Executes the test. 440 * 441 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 442 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 443 * Note the function throws exception should an error occur! 444 **/ 445 tcu::TestNode::IterateResult GeometryShaderGetShaderivTest::iterate() 446 { 447 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 448 bool result = true; 449 450 /* This test should only run if EXT_geometry_shader is supported. */ 451 if (!m_is_geometry_shader_extension_supported) 452 { 453 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 454 } 455 456 /* Create a GS */ 457 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 458 459 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); 460 461 /* Check the type reported for the SO */ 462 glw::GLint shader_type = GL_NONE; 463 464 gl.getShaderiv(m_gs_id, GL_SHADER_TYPE, &shader_type); 465 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 466 467 if ((glw::GLenum)shader_type != m_glExtTokens.GEOMETRY_SHADER) 468 { 469 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid shader type [" << shader_type 470 << "] reported for a Geometry Shader" << tcu::TestLog::EndMessage; 471 472 result = false; 473 } 474 475 if (result) 476 { 477 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 478 } 479 else 480 { 481 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 482 } 483 484 return STOP; 485 } 486 487 /** Constructor 488 * 489 * @param context Test context 490 * @param extParams Not used. 491 * @param name Test case's name 492 * @param description Test case's description 493 **/ 494 GeometryShaderGetProgramivTest::GeometryShaderGetProgramivTest(Context& context, const ExtParameters& extParams, 495 const char* name, const char* description) 496 : TestCaseBase(context, extParams, name, description), m_po_id(0) 497 { 498 } 499 500 /** Deinitializes GLES objects created during the test. */ 501 void GeometryShaderGetProgramivTest::deinit() 502 { 503 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 504 505 if (m_po_id != 0) 506 { 507 gl.deleteProgram(m_po_id); 508 509 m_po_id = 0; 510 } 511 512 /* Release base class */ 513 TestCaseBase::deinit(); 514 } 515 516 /** Executes the test. 517 * 518 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 519 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 520 * Note the function throws exception should an error occur! 521 **/ 522 tcu::TestNode::IterateResult GeometryShaderGetProgramivTest::iterate() 523 { 524 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 525 bool result = true; 526 527 /* This test should only run if EXT_geometry_shader is supported. */ 528 if (!m_is_geometry_shader_extension_supported) 529 { 530 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 531 } 532 533 /* Create a program object */ 534 m_po_id = gl.createProgram(); 535 536 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 537 538 /* Verify that GS-specific queries cause a GL_INVALID_OPERATION error */ 539 const glw::GLenum pnames[] = { m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE, 540 m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE, 541 m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS }; 542 const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]); 543 544 for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname) 545 { 546 glw::GLenum error_code = GL_NO_ERROR; 547 glw::GLenum pname = pnames[n_pname]; 548 glw::GLint rv = -1; 549 550 gl.getProgramiv(m_po_id, pname, &rv); 551 552 error_code = gl.getError(); 553 554 if (error_code != GL_INVALID_OPERATION) 555 { 556 m_testCtx.getLog() << tcu::TestLog::Message << "No error generated by glGetProgramiv() for pname [" << pname 557 << "]" << tcu::TestLog::EndMessage; 558 559 result = false; 560 } 561 } /* for (all pnames) */ 562 563 if (result) 564 { 565 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 566 } 567 else 568 { 569 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 570 } 571 572 return STOP; 573 } 574 575 /** Constructor 576 * 577 * @param context Test context 578 * @param extParams Not used. 579 * @param name Test case's name 580 * @param description Test case's description 581 **/ 582 GeometryShaderGetProgramiv2Test::GeometryShaderGetProgramiv2Test(Context& context, const ExtParameters& extParams, 583 const char* name, const char* description) 584 : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_po_id(0), m_vs_id(0) 585 { 586 } 587 588 /** Deinitializes GLES objects created during the test. */ 589 void GeometryShaderGetProgramiv2Test::deinit() 590 { 591 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 592 593 if (m_fs_id != 0) 594 { 595 gl.deleteShader(m_fs_id); 596 597 m_fs_id = 0; 598 } 599 600 if (m_po_id != 0) 601 { 602 gl.deleteProgram(m_po_id); 603 604 m_po_id = 0; 605 } 606 607 if (m_vs_id != 0) 608 { 609 gl.deleteShader(m_vs_id); 610 611 m_vs_id = 0; 612 } 613 614 /* Release base class */ 615 TestCaseBase::deinit(); 616 } 617 618 /** Executes the test. 619 * 620 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 621 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 622 * Note the function throws exception should an error occur! 623 **/ 624 tcu::TestNode::IterateResult GeometryShaderGetProgramiv2Test::iterate() 625 { 626 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 627 const glw::GLenum pnames[] = { m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE, 628 m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE, 629 m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS }; 630 const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]); 631 bool result = true; 632 633 /* This test should only run if EXT_geometry_shader is supported. */ 634 if (!m_is_geometry_shader_extension_supported) 635 { 636 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 637 } 638 639 /* Initialize the program object */ 640 std::string specialized_dummy_fs = specializeShader(1, 641 /* parts */ &dummy_fs_code); 642 const char* specialized_dummy_fs_raw = specialized_dummy_fs.c_str(); 643 std::string specialized_dummy_vs = specializeShader(1, 644 /* parts */ &dummy_vs_code); 645 const char* specialized_dummy_vs_raw = specialized_dummy_vs.c_str(); 646 647 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 648 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 649 650 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 651 652 m_po_id = gl.createProgram(); 653 654 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 655 656 if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1, &specialized_dummy_fs_raw, m_vs_id, 1, 657 &specialized_dummy_vs_raw)) 658 { 659 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build a dummy test program object" 660 << tcu::TestLog::EndMessage; 661 662 result = false; 663 goto end; 664 } 665 666 /* Verify that GS-specific queries cause a GL_INVALID_OPERATION error 667 * for a linked PO lacking the GS stage. 668 */ 669 for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname) 670 { 671 glw::GLenum error_code = GL_NO_ERROR; 672 glw::GLenum pname = pnames[n_pname]; 673 glw::GLint rv = -1; 674 675 gl.getProgramiv(m_po_id, pname, &rv); 676 677 error_code = gl.getError(); 678 679 if (error_code != GL_INVALID_OPERATION) 680 { 681 m_testCtx.getLog() << tcu::TestLog::Message << "No error generated by glGetProgramiv() for pname [" << pname 682 << "]" << tcu::TestLog::EndMessage; 683 684 result = false; 685 } 686 } /* for (all pnames) */ 687 688 end: 689 if (result) 690 { 691 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 692 } 693 else 694 { 695 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 696 } 697 698 return STOP; 699 } 700 701 /** Constructor 702 * 703 * @param context Test context 704 * @param extParams Not used. 705 * @param name Test case's name 706 * @param description Test case's description 707 **/ 708 GeometryShaderGetProgramiv3Test::GeometryShaderGetProgramiv3Test(Context& context, const ExtParameters& extParams, 709 const char* name, const char* description) 710 : TestCaseBase(context, extParams, name, description) 711 , m_fs_id(0) 712 , m_fs_po_id(0) 713 , m_gs_id(0) 714 , m_gs_po_id(0) 715 , m_pipeline_object_id(0) 716 , m_po_id(0) 717 , m_vs_id(0) 718 , m_vs_po_id(0) 719 { 720 } 721 722 /* Compiles a shader object using caller-specified data. 723 * 724 * @param so_id ID of a Shader Object to compile. 725 * @param so_body Body to use for the compilation process. 726 * 727 * @return true if the compilation succeeded, false otherwise */ 728 bool GeometryShaderGetProgramiv3Test::buildShader(glw::GLuint so_id, const char* so_body) 729 { 730 glw::GLint compile_status = GL_FALSE; 731 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 732 bool result = false; 733 734 gl.shaderSource(so_id, 1, /* count */ 735 &so_body, DE_NULL); /* length */ 736 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 737 738 gl.compileShader(so_id); 739 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 740 741 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); 742 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 743 744 result = (compile_status == GL_TRUE); 745 746 return result; 747 } 748 749 /** Builds a single shader program object using caller-specified data. 750 * 751 * @param out_spo_id Deref will be set to the ID of the created shader program object. 752 * Must not be NULL. 753 * @param spo_bits Bits to be passed to the glCreateShaderProgramv() call. 754 * @param spo_body Body to use for the glCreateShaderProgramv() call. 755 * 756 * @return true if the shader program object was linked successfully, false otherwise. 757 */ 758 bool GeometryShaderGetProgramiv3Test::buildShaderProgram(glw::GLuint* out_spo_id, glw::GLenum spo_bits, 759 const char* spo_body) 760 { 761 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 762 glw::GLint link_status = GL_FALSE; 763 bool result = true; 764 765 *out_spo_id = gl.createShaderProgramv(spo_bits, 1, /* count */ 766 &spo_body); 767 768 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); 769 770 gl.getProgramiv(*out_spo_id, GL_LINK_STATUS, &link_status); 771 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 772 773 result = (link_status == GL_TRUE); 774 775 return result; 776 } 777 778 /** Deinitializes GLES objects created during the test. */ 779 void GeometryShaderGetProgramiv3Test::deinit() 780 { 781 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 782 783 deinitPO(); 784 deinitSOs(true); 785 deinitSPOs(true); 786 787 if (m_pipeline_object_id != 0) 788 { 789 gl.deleteProgramPipelines(1, &m_pipeline_object_id); 790 791 m_pipeline_object_id = 0; 792 } 793 794 /* Release base class */ 795 TestCaseBase::deinit(); 796 } 797 798 /** Deinitializes a program object created for the conformance test. */ 799 void GeometryShaderGetProgramiv3Test::deinitPO() 800 { 801 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 802 803 if (m_po_id != 0) 804 { 805 gl.deleteProgram(m_po_id); 806 807 m_po_id = 0; 808 } 809 } 810 811 /** Deinitializes shader objects created for the conformance test. */ 812 void GeometryShaderGetProgramiv3Test::deinitSOs(bool release_all_SOs) 813 { 814 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 815 816 if (m_fs_id != 0 && release_all_SOs) 817 { 818 gl.deleteShader(m_fs_id); 819 820 m_fs_id = 0; 821 } 822 823 if (m_gs_id != 0) 824 { 825 gl.deleteShader(m_gs_id); 826 827 m_gs_id = 0; 828 } 829 830 if (m_vs_id != 0 && release_all_SOs) 831 { 832 gl.deleteShader(m_vs_id); 833 834 m_vs_id = 0; 835 } 836 } 837 838 /** Deinitializes shader program objects created for the conformance test. */ 839 void GeometryShaderGetProgramiv3Test::deinitSPOs(bool release_all_SPOs) 840 { 841 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 842 843 if (m_fs_po_id != 0 && release_all_SPOs) 844 { 845 gl.deleteProgram(m_fs_po_id); 846 847 m_fs_po_id = 0; 848 } 849 850 if (m_gs_po_id != 0) 851 { 852 gl.deleteProgram(m_gs_po_id); 853 854 m_gs_po_id = 0; 855 } 856 857 if (m_vs_po_id != 0 && release_all_SPOs) 858 { 859 gl.deleteProgram(m_vs_po_id); 860 861 m_vs_po_id = 0; 862 } 863 } 864 865 /** Retrieves ES SL layout qualifier, corresponding to user-specified 866 * primitive type. 867 * 868 * @param primitive_type Primitive type (described by a GLenum value) 869 * to use for the query. 870 * 871 * @return Requested layout qualifier. 872 */ 873 std::string GeometryShaderGetProgramiv3Test::getLayoutQualifierForPrimitiveType(glw::GLenum primitive_type) 874 { 875 std::string result; 876 877 switch (primitive_type) 878 { 879 case GL_LINE_STRIP: 880 result = "line_strip"; 881 break; 882 case GL_LINES_ADJACENCY: 883 result = "lines_adjacency"; 884 break; 885 case GL_POINTS: 886 result = "points"; 887 break; 888 case GL_TRIANGLES: 889 result = "triangles"; 890 break; 891 case GL_TRIANGLE_STRIP: 892 result = "triangle_strip"; 893 break; 894 895 default: 896 { 897 DE_ASSERT(0); 898 } 899 } /* switch (primitive_type) */ 900 901 return result; 902 } 903 904 /** Retrieves body of a geometry shadet to be used for the conformance test. 905 * The body is generated, according to the properties described by the 906 * run descriptor passed as an argument. 907 * 908 * @param run Test run descriptor. 909 * 910 * @return Requested string. 911 */ 912 std::string GeometryShaderGetProgramiv3Test::getGSCode(const _run& run) 913 { 914 std::stringstream code_sstream; 915 916 code_sstream << "${VERSION}\n" 917 "${GEOMETRY_SHADER_REQUIRE}\n" 918 "\n" 919 "layout(" 920 << getLayoutQualifierForPrimitiveType(run.input_primitive_type) << ", " 921 "invocations = " 922 << run.invocations << ") in;\n" 923 "layout(" 924 << getLayoutQualifierForPrimitiveType(run.output_primitive_type) << ", " 925 "max_vertices = " 926 << run.max_vertices << ") out;\n" 927 "\n" 928 "out gl_PerVertex {\n" 929 " vec4 gl_Position;\n" 930 "};\n" 931 "\n" 932 "void main()\n" 933 "{\n" 934 " for (int n = 0; n < " 935 << run.max_vertices << "; ++n)\n" 936 " {\n" 937 " gl_Position = vec4(n, 0.0, 0.0, 1.0);\n" 938 " EmitVertex();\n" 939 " }\n" 940 "\n" 941 " EndPrimitive();\n" 942 "}\n"; 943 944 return code_sstream.str(); 945 } 946 947 /** Initializes internal _runs member with test iteration settings for all test runs. */ 948 void GeometryShaderGetProgramiv3Test::initTestRuns() 949 { 950 /* input primitive type | invocations | max vertices | output primitive type * 951 *----------------------------------------+-------------+--------------+-----------------------*/ 952 _runs.push_back(_run(GL_LINES_ADJACENCY, 3, 16, GL_POINTS)); 953 _runs.push_back(_run(GL_TRIANGLES, 12, 37, GL_LINE_STRIP)); 954 _runs.push_back(_run(GL_POINTS, 31, 75, GL_TRIANGLE_STRIP)); 955 } 956 957 /** Executes the test. 958 * 959 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 960 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 961 * Note the function throws exception should an error occur! 962 **/ 963 tcu::TestNode::IterateResult GeometryShaderGetProgramiv3Test::iterate() 964 { 965 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 966 glw::GLint gs_spo_id = 0; 967 unsigned int n_run = 0; 968 unsigned int n_separable_object_case = 0; 969 bool result = true; 970 971 /* This test should only run if EXT_geometry_shader is supported. */ 972 if (!m_is_geometry_shader_extension_supported) 973 { 974 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 975 } 976 977 /* Prepare specialized versions of dummy fragment & vertex shaders */ 978 std::string dummy_fs_specialized = specializeShader(1, 979 /* parts */ &dummy_fs_code); 980 const char* dummy_fs_specialized_raw = dummy_fs_specialized.c_str(); 981 std::string dummy_vs_specialized = specializeShader(1, &dummy_vs_code); 982 const char* dummy_vs_specialized_raw = dummy_vs_specialized.c_str(); 983 984 /* Set up the fragment & the vertex shaders */ 985 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 986 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 987 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 988 989 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 990 991 if (!buildShader(m_fs_id, dummy_fs_specialized_raw) || !buildShader(m_vs_id, dummy_vs_specialized_raw)) 992 { 993 m_testCtx.getLog() << tcu::TestLog::Message << "Either FS or VS failed to build." << tcu::TestLog::EndMessage; 994 995 result = false; 996 goto end; 997 } 998 999 /* Set up the test program object */ 1000 m_po_id = gl.createProgram(); 1001 1002 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 1003 1004 gl.attachShader(m_po_id, m_fs_id); 1005 gl.attachShader(m_po_id, m_gs_id); 1006 gl.attachShader(m_po_id, m_vs_id); 1007 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 1008 1009 /* Set up the fragment & the vertex shader programs */ 1010 if (!buildShaderProgram(&m_fs_po_id, GL_FRAGMENT_SHADER, dummy_fs_specialized_raw) || 1011 !buildShaderProgram(&m_vs_po_id, GL_VERTEX_SHADER, dummy_vs_specialized_raw)) 1012 { 1013 m_testCtx.getLog() << tcu::TestLog::Message << "Either FS or VS SPOs failed to build." 1014 << tcu::TestLog::EndMessage; 1015 1016 result = false; 1017 goto end; 1018 } 1019 1020 /* Set up test runs */ 1021 initTestRuns(); 1022 1023 /* The test should check both a geometry shader program object and a full-blown PO 1024 * consisting of FS, GS and VS. */ 1025 for (n_separable_object_case = 0; n_separable_object_case < 2; /* PO, SPO cases */ 1026 ++n_separable_object_case) 1027 { 1028 bool should_use_separable_object = (n_separable_object_case != 0); 1029 1030 /* Iterate over all test runs */ 1031 for (n_run = 0; n_run < _runs.size(); ++n_run) 1032 { 1033 const _run& current_run = _runs[n_run]; 1034 std::string gs_code = getGSCode(current_run); 1035 const char* gs_code_raw = gs_code.c_str(); 1036 std::string gs_code_specialized = specializeShader(1, /* parts */ 1037 &gs_code_raw); 1038 const char* gs_code_specialized_raw = gs_code_specialized.c_str(); 1039 1040 if (should_use_separable_object) 1041 { 1042 /* Deinitialize any objects that may have been created in previous iterations */ 1043 deinitSPOs(false); 1044 1045 /* Set up the geometry shader program object */ 1046 if (!buildShaderProgram(&m_gs_po_id, GL_GEOMETRY_SHADER, gs_code_specialized_raw)) 1047 { 1048 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to compile a geometry shader program object" 1049 << tcu::TestLog::EndMessage; 1050 1051 result = false; 1052 goto end; 1053 } 1054 } /* if (should_use_pipeline_object) */ 1055 else 1056 { 1057 gl.bindProgramPipeline(0); 1058 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 1059 1060 /* Set up the geometry shader object */ 1061 if (!buildShader(m_gs_id, gs_code_specialized_raw)) 1062 { 1063 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to compile a geometry shader object." 1064 << tcu::TestLog::EndMessage; 1065 1066 result = false; 1067 goto end; 1068 } 1069 1070 /* Set up the program object */ 1071 glw::GLint link_status = GL_FALSE; 1072 1073 gl.linkProgram(m_po_id); 1074 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 1075 1076 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 1077 1078 if (link_status == GL_FALSE) 1079 { 1080 m_testCtx.getLog() << tcu::TestLog::Message << "Test program object failed to link" 1081 << tcu::TestLog::EndMessage; 1082 1083 result = false; 1084 goto end; 1085 } 1086 1087 /* Bind the PO to the rendering context */ 1088 gl.useProgram(m_po_id); 1089 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 1090 } 1091 1092 /* Execute the queries */ 1093 glw::GLuint po_id = (should_use_separable_object) ? m_gs_po_id : m_po_id; 1094 glw::GLint result_geometry_linked_vertices_out = 0; 1095 glw::GLint result_geometry_linked_input_type = 0; 1096 glw::GLint result_geometry_linked_output_type = 0; 1097 glw::GLint result_geometry_shader_invocations = 0; 1098 1099 gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, &result_geometry_linked_vertices_out); 1100 GLU_EXPECT_NO_ERROR(gl.getError(), 1101 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_VERTICES_OUT_EXT query."); 1102 1103 gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE, &result_geometry_linked_input_type); 1104 GLU_EXPECT_NO_ERROR(gl.getError(), 1105 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query."); 1106 1107 gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE, &result_geometry_linked_output_type); 1108 GLU_EXPECT_NO_ERROR(gl.getError(), 1109 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT query."); 1110 1111 gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS, &result_geometry_shader_invocations); 1112 GLU_EXPECT_NO_ERROR(gl.getError(), 1113 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query."); 1114 1115 if (current_run.input_primitive_type != (glw::GLenum)result_geometry_linked_input_type) 1116 { 1117 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query value " 1118 << "[" << result_geometry_linked_input_type 1119 << "]" 1120 " does not match the test run setting " 1121 "[" 1122 << current_run.input_primitive_type << "]" << tcu::TestLog::EndMessage; 1123 1124 result = false; 1125 } 1126 1127 if (current_run.invocations != result_geometry_shader_invocations) 1128 { 1129 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_SHADER_INVOCATIONS_EXT query value " 1130 << "[" << result_geometry_shader_invocations 1131 << "]" 1132 " does not match the test run setting " 1133 "[" 1134 << current_run.input_primitive_type << "]" << tcu::TestLog::EndMessage; 1135 1136 result = false; 1137 } 1138 1139 if (current_run.max_vertices != result_geometry_linked_vertices_out) 1140 { 1141 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_VERTICES_OUT query value " 1142 << "[" << result_geometry_linked_vertices_out 1143 << "]" 1144 " does not match the test run setting " 1145 "[" 1146 << current_run.max_vertices << "]" << tcu::TestLog::EndMessage; 1147 1148 result = false; 1149 } 1150 1151 if (current_run.output_primitive_type != (glw::GLenum)result_geometry_linked_output_type) 1152 { 1153 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT query value " 1154 << "[" << result_geometry_linked_output_type 1155 << "]" 1156 " does not match the test run setting " 1157 "[" 1158 << current_run.output_primitive_type << "]" << tcu::TestLog::EndMessage; 1159 1160 result = false; 1161 } 1162 } /* for (all test runs) */ 1163 } /* for (PO & SPO cases) */ 1164 1165 /* One more check: build a pipeline object which only defines a FS & VS stages, 1166 * and check what GS SPO ID the object reports. */ 1167 gl.genProgramPipelines(1, &m_pipeline_object_id); 1168 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); 1169 1170 gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id); 1171 gl.useProgramStages(m_pipeline_object_id, GL_VERTEX_SHADER_BIT, m_vs_po_id); 1172 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 1173 1174 gl.getProgramPipelineiv(m_pipeline_object_id, m_glExtTokens.GEOMETRY_SHADER, &gs_spo_id); 1175 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed."); 1176 1177 if (gs_spo_id != 0) 1178 { 1179 m_testCtx.getLog() << tcu::TestLog::Message << "Pipeline object reported [" << gs_spo_id << "]" 1180 << " for GL_GEOMETRY_SHADER_EXT query, even though no GS SPO was bound." 1181 << tcu::TestLog::EndMessage; 1182 1183 result = false; 1184 } 1185 1186 end: 1187 if (result) 1188 { 1189 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1190 } 1191 else 1192 { 1193 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1194 } 1195 1196 return STOP; 1197 } 1198 1199 /** Constructor 1200 * 1201 * @param context Test context 1202 * @param extParams Not used. 1203 * @param name Test case's name 1204 * @param description Test case's description 1205 **/ 1206 GeometryShaderDrawCallWithFSAndGS::GeometryShaderDrawCallWithFSAndGS(Context& context, const ExtParameters& extParams, 1207 const char* name, const char* description) 1208 : TestCaseBase(context, extParams, name, description) 1209 , m_fs_po_id(0) 1210 , m_gs_po_id(0) 1211 , m_pipeline_object_id(0) 1212 , m_vao_id(0) 1213 { 1214 } 1215 1216 /** Deinitializes GLES objects created during the test. */ 1217 void GeometryShaderDrawCallWithFSAndGS::deinit() 1218 { 1219 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1220 1221 if (m_fs_po_id != 0) 1222 { 1223 gl.deleteProgram(m_fs_po_id); 1224 1225 m_fs_po_id = 0; 1226 } 1227 1228 if (m_gs_po_id != 0) 1229 { 1230 gl.deleteProgram(m_gs_po_id); 1231 1232 m_gs_po_id = 0; 1233 } 1234 1235 if (m_pipeline_object_id != 0) 1236 { 1237 gl.deleteProgramPipelines(1, &m_pipeline_object_id); 1238 1239 m_pipeline_object_id = 0; 1240 } 1241 1242 if (m_vao_id != 0) 1243 { 1244 gl.deleteVertexArrays(1, &m_vao_id); 1245 1246 m_vao_id = 0; 1247 } 1248 1249 /* Release base class */ 1250 TestCaseBase::deinit(); 1251 } 1252 1253 /** Executes the test. 1254 * 1255 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 1256 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 1257 * Note the function throws exception should an error occur! 1258 **/ 1259 tcu::TestNode::IterateResult GeometryShaderDrawCallWithFSAndGS::iterate() 1260 { 1261 glw::GLenum error_code = GL_NO_ERROR; 1262 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1263 bool result = true; 1264 1265 /* This test should only run if EXT_geometry_shader is supported. */ 1266 if (!m_is_geometry_shader_extension_supported) 1267 { 1268 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 1269 } 1270 1271 /* Create & bind a VAO */ 1272 gl.genVertexArrays(1, &m_vao_id); 1273 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 1274 1275 gl.bindVertexArray(m_vao_id); 1276 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 1277 1278 /* Create shader program objects */ 1279 std::string code_fs_specialized = specializeShader(1, /* parts */ 1280 &dummy_fs_code); 1281 const char* code_fs_specialized_raw = code_fs_specialized.c_str(); 1282 std::string code_gs_specialized = specializeShader(1, /* parts */ 1283 &dummy_gs_code); 1284 const char* code_gs_specialized_raw = code_gs_specialized.c_str(); 1285 glw::GLint link_status = GL_FALSE; 1286 1287 m_fs_po_id = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, /* count */ 1288 &code_fs_specialized_raw); 1289 m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */ 1290 &code_gs_specialized_raw); 1291 1292 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call(s) failed."); 1293 1294 gl.getProgramiv(m_fs_po_id, GL_LINK_STATUS, &link_status); 1295 1296 if (link_status != GL_TRUE) 1297 { 1298 m_testCtx.getLog() << tcu::TestLog::Message << "Dummy fragment shader program failed to link." 1299 << tcu::TestLog::EndMessage; 1300 1301 result = false; 1302 goto end; 1303 } 1304 1305 gl.getProgramiv(m_gs_po_id, GL_LINK_STATUS, &link_status); 1306 1307 if (link_status != GL_TRUE) 1308 { 1309 m_testCtx.getLog() << tcu::TestLog::Message << "Dummy geometry shader program failed to link." 1310 << tcu::TestLog::EndMessage; 1311 1312 result = false; 1313 goto end; 1314 } 1315 1316 /* Create & set up a pipeline object */ 1317 gl.genProgramPipelines(1, &m_pipeline_object_id); 1318 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); 1319 1320 gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id); 1321 gl.useProgramStages(m_pipeline_object_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id); 1322 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed."); 1323 1324 gl.bindProgramPipeline(m_pipeline_object_id); 1325 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 1326 1327 /* Try to do a draw call */ 1328 gl.drawArrays(GL_POINTS, 0, /* first */ 1329 1); /* count */ 1330 1331 error_code = gl.getError(); 1332 if (error_code != GL_INVALID_OPERATION) 1333 { 1334 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid draw call generated an error code [" << error_code 1335 << "]" 1336 " which is different from the expected GL_INVALID_OPERATION." 1337 << tcu::TestLog::EndMessage; 1338 1339 result = false; 1340 } 1341 1342 end: 1343 // m_pipeline_object_id is generated in this function, need to be freed 1344 if (m_pipeline_object_id) 1345 { 1346 gl.deleteProgramPipelines(1, &m_pipeline_object_id); 1347 m_pipeline_object_id = 0; 1348 } 1349 1350 // m_gs_po_id is generated in this function, need to be freed 1351 if (m_gs_po_id) 1352 { 1353 gl.deleteProgram(m_gs_po_id); 1354 m_gs_po_id = 0; 1355 } 1356 1357 // m_fs_po_id is generated in this function, need to be freed 1358 if (m_fs_po_id) 1359 { 1360 gl.deleteProgram(m_fs_po_id); 1361 m_fs_po_id = 0; 1362 } 1363 1364 // m_vao_id is generated in this function, need to be freed 1365 if (m_vao_id) 1366 { 1367 gl.deleteVertexArrays(1, &m_vao_id); 1368 m_vao_id = 0; 1369 } 1370 1371 /* All done */ 1372 if (result) 1373 { 1374 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1375 } 1376 else 1377 { 1378 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1379 } 1380 1381 return STOP; 1382 } 1383 1384 /** Constructor 1385 * 1386 * @param context Test context 1387 * @param extParams Not used. 1388 * @param name Test case's name 1389 * @param description Test case's description 1390 **/ 1391 GeometryShaderMaxImageUniformsTest::GeometryShaderMaxImageUniformsTest(Context& context, const ExtParameters& extParams, 1392 const char* name, const char* description) 1393 : TestCaseBase(context, extParams, name, description) 1394 , m_fs_id(0) 1395 , m_gl_max_geometry_image_uniforms_ext_value(0) 1396 , m_gs_id(0) 1397 , m_po_id(0) 1398 , m_texture_ids(NULL) 1399 , m_tfbo_id(0) 1400 , m_vao_id(0) 1401 , m_vs_id(0) 1402 { 1403 //Bug-15063 Only GLSL 4.50 supports opaque types 1404 if (m_glslVersion >= glu::GLSL_VERSION_130) 1405 { 1406 m_glslVersion = glu::GLSL_VERSION_450; 1407 } 1408 } 1409 1410 /** Deinitializes GLES objects created during the test. */ 1411 void GeometryShaderMaxImageUniformsTest::deinit() 1412 { 1413 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1414 1415 if (m_fs_id != 0) 1416 { 1417 gl.deleteShader(m_fs_id); 1418 1419 m_fs_id = 0; 1420 } 1421 1422 if (m_gs_id != 0) 1423 { 1424 gl.deleteShader(m_gs_id); 1425 1426 m_gs_id = 0; 1427 } 1428 1429 if (m_po_id != 0) 1430 { 1431 gl.deleteProgram(m_po_id); 1432 1433 m_po_id = 0; 1434 } 1435 1436 if (m_texture_ids != NULL) 1437 { 1438 gl.deleteTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids); 1439 1440 delete[] m_texture_ids; 1441 m_texture_ids = NULL; 1442 } 1443 1444 if (m_tfbo_id != 0) 1445 { 1446 gl.deleteBuffers(1, &m_tfbo_id); 1447 m_tfbo_id = 0; 1448 } 1449 1450 if (m_vao_id != 0) 1451 { 1452 gl.deleteVertexArrays(1, &m_vao_id); 1453 m_vao_id = 0; 1454 } 1455 1456 if (m_vs_id != 0) 1457 { 1458 gl.deleteShader(m_vs_id); 1459 1460 m_vs_id = 0; 1461 } 1462 1463 /* Set GL_PACK_ALIGNMENT to default value. */ 1464 gl.pixelStorei(GL_PACK_ALIGNMENT, 4 /*default value taken from specification*/); 1465 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname."); 1466 1467 /* Release base class */ 1468 TestCaseBase::deinit(); 1469 } 1470 1471 /* Retrieves test-specific geometry shader source code. 1472 * 1473 * @return Requested string. 1474 */ 1475 std::string GeometryShaderMaxImageUniformsTest::getGSCode() 1476 { 1477 std::stringstream code_sstream; 1478 1479 /* Form the GS */ 1480 code_sstream << "${VERSION}\n" 1481 "${GEOMETRY_SHADER_REQUIRE}\n" 1482 "\n" 1483 "layout (points) in;\n" 1484 "layout (points, max_vertices = 1) out;\n" 1485 "\n" 1486 "precision highp iimage2D;\n" 1487 "\n" 1488 "ivec4 counter = ivec4(0);\n" 1489 "\n"; 1490 1491 for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img) 1492 { 1493 code_sstream << "layout(binding = " << n_img << ", r32i) uniform iimage2D img" << n_img << ";\n"; 1494 } 1495 1496 code_sstream << "\n" 1497 "void main()\n" 1498 "{\n"; 1499 1500 for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img) 1501 { 1502 code_sstream << " counter += imageLoad(img" << n_img << ", ivec2(0, 0));\n"; 1503 } 1504 1505 code_sstream << "\n" 1506 " gl_Position = vec4(float(counter.x), 0.0, 0.0, 1.0);\n" 1507 " EmitVertex();\n" 1508 "}\n"; 1509 1510 /* Form a specialized version of the GS source code */ 1511 std::string gs_code = code_sstream.str(); 1512 const char* gs_code_raw = gs_code.c_str(); 1513 std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw); 1514 1515 return gs_code_specialized; 1516 } 1517 1518 /** Executes the test. 1519 * 1520 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 1521 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 1522 * Note the function throws exception should an error occur! 1523 **/ 1524 tcu::TestNode::IterateResult GeometryShaderMaxImageUniformsTest::iterate() 1525 { 1526 glw::GLint counter = 0; 1527 glw::GLint expectedValue = 0; 1528 bool has_shader_compilation_failed = true; 1529 glw::GLfloat* ptr = DE_NULL; 1530 bool result = true; 1531 const glw::GLchar* feedbackVaryings[] = { "gl_Position" }; 1532 1533 std::string fs_code_specialized = ""; 1534 const char* fs_code_specialized_raw = DE_NULL; 1535 std::string gs_code_specialized = ""; 1536 const char* gs_code_specialized_raw = DE_NULL; 1537 std::string vs_code_specialized = ""; 1538 const char* vs_code_specialized_raw = DE_NULL; 1539 1540 /* This test should only run if EXT_geometry_shader is supported. */ 1541 if (!m_is_geometry_shader_extension_supported) 1542 { 1543 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 1544 } 1545 1546 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1547 1548 /* Retrieve GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname value */ 1549 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_IMAGE_UNIFORMS, &m_gl_max_geometry_image_uniforms_ext_value); 1550 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname"); 1551 1552 /* Retrieve GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT pname value */ 1553 glw::GLint m_gl_max_geometry_texture_image_units_ext_value = 0; 1554 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &m_gl_max_geometry_texture_image_units_ext_value); 1555 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname"); 1556 1557 /* Check if m_gl_max_geometry_image_uniforms_value is less than or equal zero. */ 1558 if (m_gl_max_geometry_image_uniforms_ext_value <= 0) 1559 { 1560 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value " 1561 << "[" << m_gl_max_geometry_image_uniforms_ext_value 1562 << "]" 1563 " is less than or equal zero. Image uniforms in Geometry Shader" 1564 " are not supported." 1565 << tcu::TestLog::EndMessage; 1566 1567 if (m_gl_max_geometry_image_uniforms_ext_value == 0) 1568 { 1569 throw tcu::NotSupportedError("GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT is 0"); 1570 } 1571 else 1572 { 1573 result = false; 1574 goto end; 1575 } 1576 } 1577 1578 /* Check if m_gl_max_geometry_texture_image_units_value is less than m_gl_max_geometry_image_uniforms_value. */ 1579 if (m_gl_max_geometry_texture_image_units_ext_value < m_gl_max_geometry_image_uniforms_ext_value) 1580 { 1581 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value " 1582 << "[" << m_gl_max_geometry_image_uniforms_ext_value 1583 << "]" 1584 " is greater than GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT query value " 1585 "[" 1586 << m_gl_max_geometry_texture_image_units_ext_value << "]." << tcu::TestLog::EndMessage; 1587 1588 result = false; 1589 goto end; 1590 } 1591 1592 /* Create a program object. */ 1593 m_po_id = gl.createProgram(); 1594 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 1595 1596 /* Create shader objects. */ 1597 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1598 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 1599 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1600 1601 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 1602 1603 /* Configure which outputs should be captured by Transform Feedback. */ 1604 gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS); 1605 1606 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed."); 1607 1608 /* Try to link the test program object */ 1609 fs_code_specialized = specializeShader(1, &dummy_fs_code); 1610 fs_code_specialized_raw = fs_code_specialized.c_str(); 1611 1612 gs_code_specialized = getGSCode(); 1613 gs_code_specialized_raw = gs_code_specialized.c_str(); 1614 1615 vs_code_specialized = specializeShader(1, &dummy_vs_code); 1616 vs_code_specialized_raw = vs_code_specialized.c_str(); 1617 1618 if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ 1619 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ 1620 &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ 1621 &fs_code_specialized_raw, &has_shader_compilation_failed)) 1622 { 1623 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage; 1624 1625 result = false; 1626 goto end; 1627 } 1628 1629 /* Use program. */ 1630 gl.useProgram(m_po_id); 1631 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 1632 1633 /* Allocate memory for m_max_image_units_value Texture Objects. */ 1634 m_texture_ids = new glw::GLuint[m_gl_max_geometry_image_uniforms_ext_value]; 1635 1636 /* Generate m_max_image_units_value Texture Objects. */ 1637 gl.genTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids); 1638 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 1639 1640 /* Set GL_PACK_ALIGNMENT to 1. */ 1641 gl.pixelStorei(GL_PACK_ALIGNMENT, 1); 1642 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname."); 1643 1644 /* Bind integer 2D texture objects of resolution 1x1 to image units. */ 1645 for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img) 1646 { 1647 glw::GLint texture = m_texture_ids[n_img]; 1648 glw::GLint value = n_img + 1; 1649 1650 gl.bindTexture(GL_TEXTURE_2D, texture); 1651 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 1652 1653 gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_R32I, 1 /*width*/, 1 /*height*/); 1654 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed."); 1655 1656 gl.texSubImage2D(GL_TEXTURE_2D, 0 /*level*/, 0 /*xoffset*/, 0 /*yoffset*/, 1 /*width*/, 1 /*height*/, 1657 GL_RED_INTEGER, GL_INT, &value); 1658 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed."); 1659 1660 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1661 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed."); 1662 1663 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1664 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed."); 1665 1666 gl.bindImageTexture(n_img, texture, 0 /*level*/, GL_FALSE /*is layered?*/, 0 /*layer*/, GL_READ_ONLY, GL_R32I); 1667 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed."); 1668 } 1669 1670 /* Configure VAO. */ 1671 gl.genVertexArrays(1, &m_vao_id); 1672 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 1673 1674 gl.bindVertexArray(m_vao_id); 1675 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 1676 1677 /* Create a Buffer Object for Transform Feedback's outputs. */ 1678 gl.genBuffers(1, &m_tfbo_id); 1679 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 1680 1681 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id); 1682 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 1683 1684 gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, NULL, GL_STATIC_READ); 1685 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 1686 1687 /* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */ 1688 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tfbo_id); 1689 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 1690 1691 /* Disable rasterization and make a draw call. After that, turn on rasterization. */ 1692 gl.enable(GL_RASTERIZER_DISCARD); 1693 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname."); 1694 1695 gl.beginTransformFeedback(GL_POINTS); 1696 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 1697 1698 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/); 1699 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname."); 1700 1701 gl.endTransformFeedback(); 1702 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 1703 1704 gl.disable(GL_RASTERIZER_DISCARD); 1705 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname."); 1706 1707 /* Retrieve value from Transform Feedback. */ 1708 counter = 0; 1709 ptr = (glw::GLfloat*)gl.mapBufferRange( 1710 GL_ARRAY_BUFFER, 0, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT); 1711 1712 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 1713 1714 counter = int(ptr[0] + 0.5f); 1715 1716 gl.unmapBuffer(GL_ARRAY_BUFFER); 1717 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 1718 1719 /* Calculate expected value. */ 1720 expectedValue = m_gl_max_geometry_image_uniforms_ext_value * (m_gl_max_geometry_image_uniforms_ext_value + 1) / 2; 1721 1722 if (counter != expectedValue) 1723 { 1724 result = false; 1725 } 1726 1727 end: 1728 if (result) 1729 { 1730 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1731 } 1732 else 1733 { 1734 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1735 } 1736 1737 return STOP; 1738 } 1739 1740 /** Constructor 1741 * 1742 * @param context Test context 1743 * @param extParams Not used. 1744 * @param name Test case's name 1745 * @param description Test case's description 1746 **/ 1747 GeometryShaderMaxShaderStorageBlocksTest::GeometryShaderMaxShaderStorageBlocksTest(Context& context, 1748 const ExtParameters& extParams, 1749 const char* name, 1750 const char* description) 1751 : TestCaseBase(context, extParams, name, description) 1752 , m_fs_id(0) 1753 , m_gl_max_geometry_shader_storage_blocks_ext_value(0) 1754 , m_gs_id(0) 1755 , m_po_id(0) 1756 , m_ssbo_id(0) 1757 , m_tfbo_id(0) 1758 , m_vao_id(0) 1759 , m_vs_id(0) 1760 { 1761 } 1762 1763 /** Deinitializes GLES objects created during the test. */ 1764 void GeometryShaderMaxShaderStorageBlocksTest::deinit() 1765 { 1766 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1767 1768 if (m_fs_id != 0) 1769 { 1770 gl.deleteShader(m_fs_id); 1771 m_fs_id = 0; 1772 } 1773 1774 if (m_gs_id != 0) 1775 { 1776 gl.deleteShader(m_gs_id); 1777 m_gs_id = 0; 1778 } 1779 1780 if (m_po_id != 0) 1781 { 1782 gl.deleteProgram(m_po_id); 1783 m_po_id = 0; 1784 } 1785 1786 if (m_ssbo_id != 0) 1787 { 1788 gl.deleteBuffers(1, &m_ssbo_id); 1789 m_ssbo_id = 0; 1790 } 1791 1792 if (m_tfbo_id != 0) 1793 { 1794 gl.deleteBuffers(1, &m_tfbo_id); 1795 m_tfbo_id = 0; 1796 } 1797 1798 if (m_vao_id != 0) 1799 { 1800 gl.deleteVertexArrays(1, &m_vao_id); 1801 m_vao_id = 0; 1802 } 1803 1804 if (m_vs_id != 0) 1805 { 1806 gl.deleteShader(m_vs_id); 1807 m_vs_id = 0; 1808 } 1809 1810 /* Release base class */ 1811 TestCaseBase::deinit(); 1812 } 1813 1814 /* Retrieves test-specific geometry shader source code. 1815 * 1816 * @return Requested string. 1817 */ 1818 std::string GeometryShaderMaxShaderStorageBlocksTest::getGSCode() 1819 { 1820 std::stringstream code_sstream; 1821 1822 /* Form the GS */ 1823 code_sstream << "${VERSION}\n" 1824 "${GEOMETRY_SHADER_REQUIRE}\n" 1825 "\n" 1826 "layout (points) in;\n" 1827 "layout (points, max_vertices = 1) out;\n" 1828 "\n" 1829 "int counter = 0;\n" 1830 "\n"; 1831 1832 for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb) 1833 { 1834 code_sstream << "layout(binding = " << n_ssb << ") buffer ssb" << n_ssb << " \n{\n" 1835 << " int value;\n" 1836 << "} S_SSB" << n_ssb << ";\n\n"; 1837 } 1838 1839 code_sstream << "\n" 1840 "void main()\n" 1841 "{\n"; 1842 1843 for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb) 1844 { 1845 code_sstream << " counter += S_SSB" << n_ssb << ".value++;\n"; 1846 } 1847 1848 code_sstream << "\n" 1849 " gl_Position = vec4(float(counter), 0.0, 0.0, 1.0);\n" 1850 " EmitVertex();\n" 1851 "}\n"; 1852 1853 /* Form a specialized version of the GS source code */ 1854 std::string gs_code = code_sstream.str(); 1855 const char* gs_code_raw = gs_code.c_str(); 1856 std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw); 1857 1858 return gs_code_specialized; 1859 } 1860 1861 /** Executes the test. 1862 * 1863 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 1864 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 1865 * Note the function throws exception should an error occur! 1866 **/ 1867 tcu::TestNode::IterateResult GeometryShaderMaxShaderStorageBlocksTest::iterate() 1868 { 1869 glw::GLint counter = 0; 1870 glw::GLint expectedValue = 0; 1871 const glw::GLchar* feedbackVaryings[] = { "gl_Position" }; 1872 bool has_shader_compilation_failed = true; 1873 const glw::GLfloat initial_buffer_data[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 1874 glw::GLint int_alignment = 0; 1875 const glw::GLint int_size = sizeof(glw::GLint); 1876 glw::GLint* ptrSSBO_data = DE_NULL; 1877 glw::GLfloat* ptrTF_data = DE_NULL; 1878 bool result = true; 1879 glw::GLint ssbo_alignment = 0; 1880 glw::GLint* ssbo_data = DE_NULL; 1881 glw::GLint ssbo_data_size = 0; 1882 1883 std::string fs_code_specialized = ""; 1884 const char* fs_code_specialized_raw = DE_NULL; 1885 std::string gs_code_specialized = ""; 1886 const char* gs_code_specialized_raw = DE_NULL; 1887 std::string vs_code_specialized = ""; 1888 const char* vs_code_specialized_raw = DE_NULL; 1889 1890 /* This test should only run if EXT_geometry_shader is supported. */ 1891 if (!m_is_geometry_shader_extension_supported) 1892 { 1893 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 1894 } 1895 1896 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1897 1898 /* Retrieve GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname value */ 1899 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, 1900 &m_gl_max_geometry_shader_storage_blocks_ext_value); 1901 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname"); 1902 1903 /* Retrieve GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname value */ 1904 glw::GLint m_gl_max_shader_storage_buffer_bindings_value = 0; 1905 1906 gl.getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &m_gl_max_shader_storage_buffer_bindings_value); 1907 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname"); 1908 1909 /* Check if m_gl_max_shader_storage_blocks_value is less than or equal zero. */ 1910 if (m_gl_max_geometry_shader_storage_blocks_ext_value <= 0) 1911 { 1912 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value " 1913 << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value 1914 << "]" 1915 " is less than or equal zero. Shader Storage Blocks" 1916 " in Geometry Shader are not supported." 1917 << tcu::TestLog::EndMessage; 1918 1919 if (m_gl_max_geometry_shader_storage_blocks_ext_value == 0) 1920 { 1921 throw tcu::NotSupportedError("GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT is 0"); 1922 } 1923 else 1924 { 1925 result = false; 1926 goto end; 1927 } 1928 } 1929 1930 /* Check if m_gl_max_shader_storage_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */ 1931 if (m_gl_max_shader_storage_buffer_bindings_value < m_gl_max_geometry_shader_storage_blocks_ext_value) 1932 { 1933 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value " 1934 << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value 1935 << "]" 1936 " is greater than GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS query value " 1937 "[" 1938 << m_gl_max_shader_storage_buffer_bindings_value << "]." << tcu::TestLog::EndMessage; 1939 1940 result = false; 1941 goto end; 1942 } 1943 1944 /* Create a program object. */ 1945 m_po_id = gl.createProgram(); 1946 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 1947 1948 /* Create shader objects. */ 1949 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1950 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 1951 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1952 1953 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 1954 1955 /* Configure which outputs should be captured by Transform Feedback. */ 1956 gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS); 1957 1958 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed."); 1959 1960 /* Try to link the test program object */ 1961 fs_code_specialized = specializeShader(1, &dummy_fs_code); 1962 fs_code_specialized_raw = fs_code_specialized.c_str(); 1963 1964 gs_code_specialized = getGSCode(); 1965 gs_code_specialized_raw = gs_code_specialized.c_str(); 1966 1967 vs_code_specialized = specializeShader(1, &dummy_vs_code); 1968 vs_code_specialized_raw = vs_code_specialized.c_str(); 1969 1970 if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ 1971 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ 1972 &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ 1973 &fs_code_specialized_raw, &has_shader_compilation_failed)) 1974 { 1975 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage; 1976 1977 result = false; 1978 goto end; 1979 } 1980 1981 /* Prepare data for Shader Storage Buffer Object. */ 1982 gl.getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_alignment); 1983 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed."); 1984 1985 int_alignment = ssbo_alignment / int_size; 1986 ssbo_data_size = m_gl_max_geometry_shader_storage_blocks_ext_value * ssbo_alignment; 1987 ssbo_data = new glw::GLint[ssbo_data_size]; 1988 1989 if ((ssbo_alignment % int_size) != 0) 1990 { 1991 m_testCtx.getLog() << tcu::TestLog::Message << "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT query value " 1992 "[" 1993 << ssbo_alignment << "]" 1994 "divide with remainder by the size of GLint " 1995 "[" 1996 << int_size << "]" << tcu::TestLog::EndMessage; 1997 1998 result = false; 1999 goto end; 2000 } 2001 2002 for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i) 2003 { 2004 ssbo_data[i * int_alignment] = i + 1; 2005 } 2006 2007 /* Create Shader Storage Buffer Object. */ 2008 gl.genBuffers(1, &m_ssbo_id); 2009 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 2010 2011 gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo_id); 2012 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname."); 2013 2014 gl.bufferData(GL_SHADER_STORAGE_BUFFER, ssbo_data_size, ssbo_data, GL_DYNAMIC_COPY); 2015 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 2016 2017 /* Free unused memory. */ 2018 delete[] ssbo_data; 2019 ssbo_data = NULL; 2020 2021 /* Bind specific m_ssbo_id buffer region to a specific Shader Storage Buffer binding point. */ 2022 for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb) 2023 { 2024 glw::GLuint offset = n_ssb * ssbo_alignment; 2025 2026 gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, n_ssb /*binding index*/, m_ssbo_id, offset, int_size); 2027 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed."); 2028 } 2029 2030 /* Configure VAO. */ 2031 gl.genVertexArrays(1, &m_vao_id); 2032 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 2033 2034 gl.bindVertexArray(m_vao_id); 2035 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 2036 2037 /* Create a Buffer Object for Transform Feedback's outputs. */ 2038 gl.genBuffers(1, &m_tfbo_id); 2039 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 2040 2041 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id); 2042 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 2043 2044 gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, initial_buffer_data, 2045 GL_STATIC_READ); 2046 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 2047 2048 /* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */ 2049 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id); 2050 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed."); 2051 2052 /* Use program. */ 2053 gl.useProgram(m_po_id); 2054 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2055 2056 /* Disable rasterization and make a draw call. After that, turn on rasterization. */ 2057 gl.enable(GL_RASTERIZER_DISCARD); 2058 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname."); 2059 2060 gl.beginTransformFeedback(GL_POINTS); 2061 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 2062 2063 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/); 2064 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname."); 2065 2066 gl.endTransformFeedback(); 2067 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 2068 2069 gl.disable(GL_RASTERIZER_DISCARD); 2070 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname."); 2071 2072 /* Retrieve value from Transform Feedback. */ 2073 ptrTF_data = (glw::GLfloat*)gl.mapBufferRange( 2074 GL_ARRAY_BUFFER, 0 /*offset*/, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT); 2075 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 2076 2077 counter = int(ptrTF_data[0] + 0.5f); 2078 2079 gl.unmapBuffer(GL_ARRAY_BUFFER); 2080 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 2081 2082 ptrTF_data = NULL; 2083 2084 /* Retrieve values from Shader Storage Buffer Object. */ 2085 ptrSSBO_data = 2086 (glw::GLint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /*offset*/, ssbo_data_size, GL_MAP_READ_BIT); 2087 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 2088 2089 for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i) 2090 { 2091 if (ptrSSBO_data[i * int_alignment] != i + 2) 2092 { 2093 result = false; 2094 2095 m_testCtx.getLog() << tcu::TestLog::Message << "Value read from Shader Storage Buffer " 2096 "[" 2097 << ptrSSBO_data[i * int_alignment] << "] " 2098 "at index " 2099 "[" 2100 << i * int_alignment << "]" 2101 "is not equal to expected value " 2102 "[" 2103 << i + 2 << "]" << tcu::TestLog::EndMessage; 2104 2105 break; 2106 } 2107 } 2108 2109 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 2110 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 2111 2112 ptrSSBO_data = NULL; 2113 2114 /* Calculate expected value. */ 2115 expectedValue = 2116 m_gl_max_geometry_shader_storage_blocks_ext_value * (m_gl_max_geometry_shader_storage_blocks_ext_value + 1) / 2; 2117 2118 if (counter != expectedValue) 2119 { 2120 result = false; 2121 } 2122 2123 end: 2124 if (result) 2125 { 2126 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2127 } 2128 else 2129 { 2130 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2131 } 2132 2133 return STOP; 2134 } 2135 2136 /** Constructor 2137 * 2138 * @param context Test context 2139 * @param extParams Not used. 2140 * @param name Test case's name 2141 * @param description Test case's description 2142 **/ 2143 GeometryShaderMaxAtomicCountersTest::GeometryShaderMaxAtomicCountersTest(Context& context, 2144 const ExtParameters& extParams, 2145 const char* name, const char* description) 2146 : TestCaseBase(context, extParams, name, description) 2147 , m_acbo_id(0) 2148 , m_fs_id(0) 2149 , m_gl_max_geometry_atomic_counters_ext_value(0) 2150 , m_gs_id(0) 2151 , m_po_id(0) 2152 , m_vao_id(0) 2153 , m_vs_id(0) 2154 { 2155 } 2156 2157 /** Deinitializes GLES objects created during the test. */ 2158 void GeometryShaderMaxAtomicCountersTest::deinit() 2159 { 2160 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2161 2162 if (m_acbo_id != 0) 2163 { 2164 gl.deleteBuffers(1, &m_acbo_id); 2165 m_acbo_id = 0; 2166 } 2167 2168 if (m_fs_id != 0) 2169 { 2170 gl.deleteShader(m_fs_id); 2171 m_fs_id = 0; 2172 } 2173 2174 if (m_gs_id != 0) 2175 { 2176 gl.deleteShader(m_gs_id); 2177 m_gs_id = 0; 2178 } 2179 2180 if (m_po_id != 0) 2181 { 2182 gl.deleteProgram(m_po_id); 2183 m_po_id = 0; 2184 } 2185 2186 if (m_vao_id != 0) 2187 { 2188 gl.deleteVertexArrays(1, &m_vao_id); 2189 m_vao_id = 0; 2190 } 2191 2192 if (m_vs_id != 0) 2193 { 2194 gl.deleteShader(m_vs_id); 2195 m_vs_id = 0; 2196 } 2197 2198 /* Release base class */ 2199 TestCaseBase::deinit(); 2200 } 2201 2202 /* Retrieves test-specific geometry shader source code. 2203 * 2204 * @return Requested string. 2205 */ 2206 std::string GeometryShaderMaxAtomicCountersTest::getGSCode() 2207 { 2208 std::stringstream code_sstream; 2209 2210 /* Form the GS */ 2211 code_sstream << "${VERSION}\n" 2212 "${GEOMETRY_SHADER_REQUIRE}\n" 2213 "\n" 2214 "layout (points) in;\n" 2215 "layout (points, max_vertices = 1) out;\n" 2216 "\n" 2217 "uniform int n_loop_iterations;\n" 2218 "flat in int vertex_id[];\n" 2219 "\n"; 2220 2221 code_sstream << "layout(binding = 0) uniform atomic_uint acs[" << m_gl_max_geometry_atomic_counters_ext_value 2222 << "];\n" 2223 << "\n" 2224 "void main()\n" 2225 "{\n" 2226 " for (int counter_id = 1;\n" 2227 " counter_id <= n_loop_iterations;\n" 2228 " ++counter_id)\n" 2229 " {\n" 2230 " if ((vertex_id[0] % counter_id) == 0)\n" 2231 " {\n" 2232 " atomicCounterIncrement(acs[counter_id - 1]);\n" 2233 " }\n" 2234 " }\n" 2235 "\n" 2236 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" 2237 " EmitVertex();\n" 2238 "}\n"; 2239 2240 /* Form a specialized version of the GS source code */ 2241 std::string gs_code = code_sstream.str(); 2242 const char* gs_code_raw = gs_code.c_str(); 2243 std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw); 2244 2245 return gs_code_specialized; 2246 } 2247 2248 /** Executes the test. 2249 * 2250 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 2251 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 2252 * Note the function throws exception should an error occur! 2253 **/ 2254 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCountersTest::iterate() 2255 { 2256 /* Define Vertex Shader's code for the purpose of this test. */ 2257 const char* vs_code = "${VERSION}\n" 2258 "\n" 2259 "flat out int vertex_id;\n" 2260 "\n" 2261 "void main()\n" 2262 "{\n" 2263 " vertex_id = gl_VertexID;\n" 2264 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" 2265 "}\n"; 2266 2267 bool has_shader_compilation_failed = true; 2268 glw::GLuint* initial_ac_data = DE_NULL; 2269 const unsigned int n_draw_call_vertices = 4; 2270 glw::GLint n_loop_iterations_uniform_location = -1; 2271 glw::GLuint* ptrACBO_data = DE_NULL; 2272 bool result = true; 2273 2274 std::string fs_code_specialized = ""; 2275 const char* fs_code_specialized_raw = DE_NULL; 2276 std::string gs_code_specialized = ""; 2277 const char* gs_code_specialized_raw = DE_NULL; 2278 std::string vs_code_specialized = ""; 2279 const char* vs_code_specialized_raw = DE_NULL; 2280 2281 /* This test should only run if EXT_geometry_shader is supported. */ 2282 if (!m_is_geometry_shader_extension_supported) 2283 { 2284 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 2285 } 2286 2287 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2288 2289 /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname value */ 2290 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTERS, &m_gl_max_geometry_atomic_counters_ext_value); 2291 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname"); 2292 2293 /* Check if m_gl_max_atomic_counters_value is less than or equal zero. */ 2294 if (m_gl_max_geometry_atomic_counters_ext_value <= 0) 2295 { 2296 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT query value " 2297 << "[" << m_gl_max_geometry_atomic_counters_ext_value 2298 << "]" 2299 " is less than or equal to zero. Atomic Counters" 2300 " in Geometry Shader are not supported." 2301 << tcu::TestLog::EndMessage; 2302 2303 if (m_gl_max_geometry_atomic_counters_ext_value == 0) 2304 { 2305 throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT is 0"); 2306 } 2307 else 2308 { 2309 result = false; 2310 goto end; 2311 } 2312 } 2313 2314 /* Create a program object. */ 2315 m_po_id = gl.createProgram(); 2316 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 2317 2318 /* Create shader objects. */ 2319 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 2320 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 2321 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 2322 2323 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 2324 2325 /* Try to link the test program object */ 2326 fs_code_specialized = specializeShader(1, &dummy_fs_code); 2327 fs_code_specialized_raw = fs_code_specialized.c_str(); 2328 2329 gs_code_specialized = getGSCode(); 2330 gs_code_specialized_raw = gs_code_specialized.c_str(); 2331 2332 vs_code_specialized = specializeShader(1, &vs_code); 2333 vs_code_specialized_raw = vs_code_specialized.c_str(); 2334 2335 if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ 2336 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ 2337 &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ 2338 &fs_code_specialized_raw, &has_shader_compilation_failed)) 2339 { 2340 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage; 2341 2342 result = false; 2343 goto end; 2344 } 2345 2346 /* Create Atomic Counter Buffer Objects. */ 2347 gl.genBuffers(1, &m_acbo_id); 2348 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 2349 2350 /* Prepare initial data - zeroes - to fill the Atomic Counter Buffer Object. */ 2351 initial_ac_data = new glw::GLuint[m_gl_max_geometry_atomic_counters_ext_value]; 2352 memset(initial_ac_data, 0, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value); 2353 2354 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_id); 2355 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname."); 2356 2357 gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value, NULL, 2358 GL_DYNAMIC_COPY); 2359 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 2360 2361 gl.bufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/, 2362 sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value, 2363 initial_ac_data /*initialize with zeroes*/); 2364 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed."); 2365 2366 gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0 /*binding index*/, m_acbo_id /*buffer*/); 2367 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed."); 2368 2369 /* Configure VAO. */ 2370 gl.genVertexArrays(1, &m_vao_id); 2371 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 2372 2373 gl.bindVertexArray(m_vao_id); 2374 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 2375 2376 /* Use program. */ 2377 n_loop_iterations_uniform_location = gl.getUniformLocation(m_po_id, "n_loop_iterations"); 2378 2379 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed."); 2380 if (n_loop_iterations_uniform_location == -1) 2381 { 2382 TCU_FAIL("n_loop_iterations uniform is considered inactive"); 2383 } 2384 else 2385 { 2386 gl.useProgram(m_po_id); 2387 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2388 2389 gl.uniform1i(n_loop_iterations_uniform_location, m_gl_max_geometry_atomic_counters_ext_value); 2390 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed."); 2391 } 2392 2393 /* Issue the draw call */ 2394 gl.drawArrays(GL_POINTS, 0, n_draw_call_vertices); 2395 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname."); 2396 2397 /* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */ 2398 ptrACBO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/, 2399 sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value, 2400 GL_MAP_READ_BIT); 2401 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 2402 2403 for (glw::GLint n_ac = 0; n_ac < m_gl_max_geometry_atomic_counters_ext_value; ++n_ac) 2404 { 2405 unsigned int expected_value = 0; 2406 2407 for (unsigned int n_draw_call_vertex = 0; n_draw_call_vertex < n_draw_call_vertices; ++n_draw_call_vertex) 2408 { 2409 if ((n_draw_call_vertex % (n_ac + 1)) == 0) 2410 { 2411 ++expected_value; 2412 } 2413 } 2414 2415 if (ptrACBO_data[n_ac] != expected_value) 2416 { 2417 result = false; 2418 break; 2419 } 2420 } 2421 2422 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 2423 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 2424 2425 ptrACBO_data = NULL; 2426 2427 end: 2428 if (result) 2429 { 2430 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2431 } 2432 else 2433 { 2434 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2435 } 2436 2437 return STOP; 2438 } 2439 2440 /** Constructor 2441 * 2442 * @param context Test context 2443 * @param extParams Not used. 2444 * @param name Test case's name 2445 * @param description Test case's description 2446 **/ 2447 GeometryShaderMaxAtomicCounterBuffersTest::GeometryShaderMaxAtomicCounterBuffersTest(Context& context, 2448 const ExtParameters& extParams, 2449 const char* name, 2450 const char* description) 2451 : TestCaseBase(context, extParams, name, description) 2452 , m_acbo_ids(NULL) 2453 , m_fs_id(0) 2454 , m_gl_max_atomic_counter_buffer_bindings_value(0) 2455 , m_gl_max_geometry_atomic_counter_buffers_ext_value(0) 2456 , m_gs_id(0) 2457 , m_po_id(0) 2458 , m_vao_id(0) 2459 , m_vs_id(0) 2460 { 2461 } 2462 2463 /** Deinitializes GLES objects created during the test. */ 2464 void GeometryShaderMaxAtomicCounterBuffersTest::deinit() 2465 { 2466 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2467 2468 if (m_acbo_ids != NULL) 2469 { 2470 if (m_gl_max_geometry_atomic_counter_buffers_ext_value > 0) 2471 { 2472 gl.deleteBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids); 2473 2474 delete[] m_acbo_ids; 2475 m_acbo_ids = NULL; 2476 } 2477 } 2478 2479 if (m_fs_id != 0) 2480 { 2481 gl.deleteShader(m_fs_id); 2482 m_fs_id = 0; 2483 } 2484 2485 if (m_gs_id != 0) 2486 { 2487 gl.deleteShader(m_gs_id); 2488 m_gs_id = 0; 2489 } 2490 2491 if (m_po_id != 0) 2492 { 2493 gl.deleteProgram(m_po_id); 2494 m_po_id = 0; 2495 } 2496 2497 if (m_vao_id != 0) 2498 { 2499 gl.deleteVertexArrays(1, &m_vao_id); 2500 m_vao_id = 0; 2501 } 2502 2503 if (m_vs_id != 0) 2504 { 2505 gl.deleteShader(m_vs_id); 2506 m_vs_id = 0; 2507 } 2508 2509 /* Release base class */ 2510 TestCaseBase::deinit(); 2511 } 2512 2513 /* Retrieves test-specific geometry shader source code. 2514 * 2515 * @return Requested string. 2516 */ 2517 std::string GeometryShaderMaxAtomicCounterBuffersTest::getGSCode() 2518 { 2519 std::stringstream code_sstream; 2520 2521 /* Form the GS */ 2522 code_sstream << "${VERSION}\n" 2523 "${GEOMETRY_SHADER_REQUIRE}\n" 2524 "\n" 2525 "layout (points) in;\n" 2526 "layout (points, max_vertices = 1) out;\n" 2527 "\n" 2528 "flat in int vertex_id[];\n" 2529 "\n"; 2530 2531 for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac) 2532 { 2533 code_sstream << "layout(binding = " << n_ac << ") uniform atomic_uint ac" << n_ac << ";\n"; 2534 } 2535 2536 code_sstream << "\n" 2537 "void main()\n" 2538 "{\n" 2539 " for(int counter_id = 1; counter_id <= " 2540 << m_gl_max_geometry_atomic_counter_buffers_ext_value 2541 << "; ++counter_id)\n" 2542 " {\n" 2543 " if((vertex_id[0] % counter_id) == 0)\n" 2544 " {\n"; 2545 2546 for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac) 2547 { 2548 code_sstream << " atomicCounterIncrement(ac" << n_ac << ");\n"; 2549 } 2550 2551 code_sstream << " }\n" 2552 " }\n"; 2553 2554 code_sstream << "\n" 2555 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" 2556 " EmitVertex();\n" 2557 "}\n"; 2558 2559 /* Form a specialized version of the GS source code */ 2560 std::string gs_code = code_sstream.str(); 2561 const char* gs_code_raw = gs_code.c_str(); 2562 std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw); 2563 2564 return gs_code_specialized; 2565 } 2566 2567 /** Executes the test. 2568 * 2569 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 2570 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 2571 * Note the function throws exception should an error occur! 2572 **/ 2573 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCounterBuffersTest::iterate() 2574 { 2575 /* Define Vertex Shader's code for the purpose of this test. */ 2576 const char* vs_code = "${VERSION}\n" 2577 "\n" 2578 "flat out int vertex_id;\n" 2579 "\n" 2580 "void main()\n" 2581 "{\n" 2582 " vertex_id = gl_VertexID;\n" 2583 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" 2584 "}\n"; 2585 2586 unsigned int expected_value = 0; 2587 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2588 bool has_shader_compilation_failed = true; 2589 const glw::GLuint initial_ac_data = 0; 2590 const glw::GLuint number_of_indices = 128 * m_gl_max_geometry_atomic_counter_buffers_ext_value; 2591 bool result = true; 2592 2593 std::string fs_code_specialized = ""; 2594 const char* fs_code_specialized_raw = DE_NULL; 2595 std::string gs_code_specialized = ""; 2596 const char* gs_code_specialized_raw = DE_NULL; 2597 std::string vs_code_specialized = ""; 2598 const char* vs_code_specialized_raw = DE_NULL; 2599 2600 /* This test should only run if EXT_geometry_shader is supported. */ 2601 if (!m_is_geometry_shader_extension_supported) 2602 { 2603 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 2604 } 2605 2606 /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname value */ 2607 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, 2608 &m_gl_max_geometry_atomic_counter_buffers_ext_value); 2609 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname"); 2610 2611 /* Retrieve GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname value */ 2612 gl.getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_gl_max_atomic_counter_buffer_bindings_value); 2613 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname"); 2614 2615 /* Check if m_gl_max_geometry_atomic_counter_buffers_ext_value is less than or equal zero. */ 2616 if (m_gl_max_geometry_atomic_counter_buffers_ext_value <= 0) 2617 { 2618 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value " 2619 << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value 2620 << "]" 2621 " is less than or equal to zero. Atomic Counter Buffers" 2622 " are not supported." 2623 << tcu::TestLog::EndMessage; 2624 2625 if (m_gl_max_geometry_atomic_counter_buffers_ext_value == 0) 2626 { 2627 throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT is 0"); 2628 } 2629 else 2630 { 2631 result = false; 2632 goto end; 2633 } 2634 } 2635 2636 /* Check if m_gl_max_atomic_counter_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */ 2637 if (m_gl_max_atomic_counter_buffer_bindings_value < m_gl_max_geometry_atomic_counter_buffers_ext_value) 2638 { 2639 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value " 2640 << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value 2641 << "]" 2642 " is greater than GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS query value " 2643 "[" 2644 << m_gl_max_atomic_counter_buffer_bindings_value << "]." << tcu::TestLog::EndMessage; 2645 2646 result = false; 2647 goto end; 2648 } 2649 2650 /* Create a program object. */ 2651 m_po_id = gl.createProgram(); 2652 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 2653 2654 /* Create shader objects. */ 2655 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 2656 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 2657 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 2658 2659 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 2660 2661 /* Try to link the test program object */ 2662 fs_code_specialized = specializeShader(1, &dummy_fs_code); 2663 fs_code_specialized_raw = fs_code_specialized.c_str(); 2664 2665 gs_code_specialized = getGSCode(); 2666 gs_code_specialized_raw = gs_code_specialized.c_str(); 2667 2668 vs_code_specialized = specializeShader(1, &vs_code); 2669 vs_code_specialized_raw = vs_code_specialized.c_str(); 2670 2671 if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ 2672 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ 2673 &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ 2674 &fs_code_specialized_raw, &has_shader_compilation_failed)) 2675 { 2676 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage; 2677 2678 result = false; 2679 goto end; 2680 } 2681 2682 /* Create Atomic Counter Buffer Objects. */ 2683 m_acbo_ids = new glw::GLuint[m_gl_max_geometry_atomic_counter_buffers_ext_value]; 2684 2685 gl.genBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids); 2686 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 2687 2688 for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb) 2689 { 2690 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]); 2691 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname."); 2692 2693 gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint), &initial_ac_data /*initialize with zeroes*/, 2694 GL_DYNAMIC_COPY); 2695 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 2696 2697 gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, n_acb /*binding index*/, m_acbo_ids[n_acb] /*buffer*/); 2698 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed."); 2699 } 2700 2701 /* Configure VAO. */ 2702 gl.genVertexArrays(1, &m_vao_id); 2703 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 2704 2705 gl.bindVertexArray(m_vao_id); 2706 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 2707 2708 /* Use program. */ 2709 gl.useProgram(m_po_id); 2710 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2711 2712 gl.drawArrays(GL_POINTS, 0 /*starting index*/, number_of_indices); 2713 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname."); 2714 2715 /* Calculate expected value. */ 2716 /* For each point being processed by Geometry Shader. */ 2717 for (glw::GLuint vertex_id = 0; vertex_id < number_of_indices; ++vertex_id) 2718 { 2719 /* And for each atomic counter ID. */ 2720 for (int atomic_counter_id = 1; atomic_counter_id <= m_gl_max_geometry_atomic_counter_buffers_ext_value; 2721 ++atomic_counter_id) 2722 { 2723 /* Check if (vertex_id % atomic_counter_id) == 0. If it is true, increment expected_value. */ 2724 if (vertex_id % atomic_counter_id == 0) 2725 { 2726 ++expected_value; 2727 } 2728 } 2729 } 2730 2731 /* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */ 2732 for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb) 2733 { 2734 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]); 2735 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 2736 2737 glw::GLuint* ptrABO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/, 2738 sizeof(glw::GLuint) /*length*/, GL_MAP_READ_BIT); 2739 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 2740 2741 if (ptrABO_data[0] != expected_value) 2742 { 2743 result = false; 2744 break; 2745 } 2746 2747 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); 2748 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 2749 2750 ptrABO_data = NULL; 2751 } 2752 2753 end: 2754 if (result) 2755 { 2756 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2757 } 2758 else 2759 { 2760 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2761 } 2762 2763 return STOP; 2764 } 2765 2766 /** Constructor 2767 * 2768 * @param context Test context 2769 * @param extParams Not used. 2770 * @param name Test case's name 2771 * @param description Test case's description 2772 **/ 2773 GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest:: 2774 GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context& context, const ExtParameters& extParams, 2775 const char* name, const char* description) 2776 : TestCaseBase(context, extParams, name, description) 2777 , m_fs_id(0) 2778 , m_fs_po_id(0) 2779 , m_gs_id(0) 2780 , m_gs_po_id(0) 2781 , m_ppo_id(0) 2782 , m_vao_id(0) 2783 { 2784 } 2785 2786 /** Deinitializes GLES objects created during the test. */ 2787 void GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::deinit() 2788 { 2789 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2790 2791 if (m_fs_id != 0) 2792 { 2793 gl.deleteShader(m_fs_id); 2794 m_fs_id = 0; 2795 } 2796 2797 if (m_fs_po_id != 0) 2798 { 2799 gl.deleteProgram(m_fs_po_id); 2800 m_fs_po_id = 0; 2801 } 2802 2803 if (m_gs_id != 0) 2804 { 2805 gl.deleteShader(m_gs_id); 2806 m_gs_id = 0; 2807 } 2808 2809 if (m_gs_po_id != 0) 2810 { 2811 gl.deleteProgram(m_gs_po_id); 2812 m_gs_po_id = 0; 2813 } 2814 2815 if (m_ppo_id != 0) 2816 { 2817 gl.deleteProgramPipelines(1, &m_ppo_id); 2818 m_ppo_id = 0; 2819 } 2820 2821 if (m_vao_id != 0) 2822 { 2823 gl.deleteVertexArrays(1, &m_vao_id); 2824 m_vao_id = 0; 2825 } 2826 2827 /* Release base class */ 2828 TestCaseBase::deinit(); 2829 } 2830 2831 /** Executes the test. 2832 * 2833 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 2834 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 2835 * Note the function throws exception should an error occur! 2836 **/ 2837 tcu::TestNode::IterateResult GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::iterate() 2838 { 2839 bool has_shader_compilation_failed = true; 2840 bool result = true; 2841 glw::GLenum error = GL_NO_ERROR; 2842 2843 /* This test should only run if EXT_geometry_shader is supported. */ 2844 if (!m_is_geometry_shader_extension_supported) 2845 { 2846 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 2847 } 2848 2849 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2850 2851 /* Create separable program objects. */ 2852 m_fs_po_id = gl.createProgram(); 2853 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 2854 2855 gl.programParameteri(m_fs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE); 2856 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed."); 2857 2858 m_gs_po_id = gl.createProgram(); 2859 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 2860 2861 gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE); 2862 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed."); 2863 2864 /* Create shader objects. */ 2865 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 2866 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 2867 2868 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 2869 2870 /* Try to link the test program object */ 2871 std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); 2872 const char* fs_code_specialized_raw = fs_code_specialized.c_str(); 2873 std::string gs_code_specialized = specializeShader(1, &dummy_gs_code); 2874 const char* gs_code_specialized_raw = gs_code_specialized.c_str(); 2875 2876 if (!TestCaseBase::buildProgram(m_fs_po_id, m_fs_id, 1, /* n_sh1_body_parts */ 2877 &fs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */ 2878 NULL, 0, 0, /* n_sh3_body_parts */ 2879 NULL, &has_shader_compilation_failed)) 2880 { 2881 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment Shader Program object linking failed." 2882 << tcu::TestLog::EndMessage; 2883 2884 result = false; 2885 goto end; 2886 } 2887 2888 if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1, /* n_sh1_body_parts */ 2889 &gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */ 2890 NULL, 0, 0, /* n_sh3_body_parts */ 2891 NULL, &has_shader_compilation_failed)) 2892 { 2893 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed." 2894 << tcu::TestLog::EndMessage; 2895 2896 result = false; 2897 goto end; 2898 } 2899 2900 /* Configure Pipeline Object. */ 2901 gl.genProgramPipelines(1, &m_ppo_id); 2902 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); 2903 2904 gl.useProgramStages(m_ppo_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id); 2905 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 2906 2907 gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id); 2908 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); 2909 2910 /* Configure VAO. */ 2911 gl.genVertexArrays(1, &m_vao_id); 2912 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 2913 2914 gl.bindVertexArray(m_vao_id); 2915 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 2916 2917 /* Use Program Pipeline Object. */ 2918 gl.bindProgramPipeline(m_ppo_id); 2919 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); 2920 2921 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/); 2922 2923 error = gl.getError(); 2924 2925 /* Check if correct error was generated. */ 2926 if (GL_INVALID_OPERATION != error) 2927 { 2928 result = false; 2929 2930 m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated." 2931 << tcu::TestLog::EndMessage; 2932 } 2933 2934 end: 2935 if (result) 2936 { 2937 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2938 } 2939 else 2940 { 2941 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2942 } 2943 2944 return STOP; 2945 } 2946 2947 /** Constructor 2948 * 2949 * @param context Test context 2950 * @param extParams Not used. 2951 * @param name Test case's name 2952 * @param description Test case's description 2953 **/ 2954 GeometryShaderIncompatibleDrawCallModeTest::GeometryShaderIncompatibleDrawCallModeTest(Context& context, 2955 const ExtParameters& extParams, 2956 const char* name, 2957 const char* description) 2958 : TestCaseBase(context, extParams, name, description) 2959 , m_fs_id(0) 2960 , m_gs_ids(NULL) 2961 , m_number_of_gs(5 /*taken from test spec*/) 2962 , m_po_ids(NULL) 2963 { 2964 m_vao_id = 0; 2965 m_vs_id = 0; 2966 } 2967 2968 /** Deinitializes GLES objects created during the test. */ 2969 void GeometryShaderIncompatibleDrawCallModeTest::deinit() 2970 { 2971 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2972 2973 if (m_fs_id != 0) 2974 { 2975 gl.deleteShader(m_fs_id); 2976 m_fs_id = 0; 2977 } 2978 2979 if (m_gs_ids != 0) 2980 { 2981 for (glw::GLuint i = 0; i < m_number_of_gs; ++i) 2982 { 2983 gl.deleteShader(m_gs_ids[i]); 2984 m_gs_ids[i] = 0; 2985 } 2986 2987 delete[] m_gs_ids; 2988 m_gs_ids = NULL; 2989 } 2990 2991 if (m_po_ids != 0) 2992 { 2993 for (glw::GLuint i = 0; i < m_number_of_gs; ++i) 2994 { 2995 gl.deleteProgram(m_po_ids[i]); 2996 m_po_ids[i] = 0; 2997 } 2998 2999 delete[] m_po_ids; 3000 m_po_ids = NULL; 3001 } 3002 3003 if (m_vao_id != 0) 3004 { 3005 gl.deleteVertexArrays(1, &m_vao_id); 3006 m_vao_id = 0; 3007 } 3008 3009 if (m_vs_id != 0) 3010 { 3011 gl.deleteShader(m_vs_id); 3012 m_vs_id = 0; 3013 } 3014 3015 /* Release base class */ 3016 TestCaseBase::deinit(); 3017 } 3018 3019 /** Executes the test. 3020 * 3021 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 3022 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 3023 * Note the function throws exception should an error occur! 3024 **/ 3025 tcu::TestNode::IterateResult GeometryShaderIncompatibleDrawCallModeTest::iterate() 3026 { 3027 /* Define 5 Geometry Shaders for purpose of this test. */ 3028 const char* gs_code_points = "${VERSION}\n" 3029 "${GEOMETRY_SHADER_REQUIRE}\n" 3030 "\n" 3031 "layout (points) in;\n" 3032 "layout (points, max_vertices = 1) out;\n" 3033 "\n" 3034 "${IN_PER_VERTEX_DECL_ARRAY}" 3035 "\n" 3036 "void main()\n" 3037 "{\n" 3038 " gl_Position = gl_in[0].gl_Position;\n" 3039 " EmitVertex();\n" 3040 "}\n"; 3041 3042 const char* gs_code_lines = "${VERSION}\n" 3043 "${GEOMETRY_SHADER_REQUIRE}\n" 3044 "\n" 3045 "layout (lines) in;\n" 3046 "layout (points, max_vertices = 1) out;\n" 3047 "\n" 3048 "${IN_PER_VERTEX_DECL_ARRAY}" 3049 "\n" 3050 "void main()\n" 3051 "{\n" 3052 " gl_Position = gl_in[0].gl_Position;\n" 3053 " EmitVertex();\n" 3054 "}\n"; 3055 3056 const char* gs_code_lines_adjacency = "${VERSION}\n" 3057 "${GEOMETRY_SHADER_REQUIRE}\n" 3058 "\n" 3059 "layout (lines_adjacency) in;\n" 3060 "layout (points, max_vertices = 1) out;\n" 3061 "\n" 3062 "${IN_PER_VERTEX_DECL_ARRAY}" 3063 "\n" 3064 "void main()\n" 3065 "{\n" 3066 " gl_Position = gl_in[0].gl_Position;\n" 3067 " EmitVertex();\n" 3068 "}\n"; 3069 3070 const char* gs_code_triangles = "${VERSION}\n" 3071 "${GEOMETRY_SHADER_REQUIRE}\n" 3072 "\n" 3073 "layout (triangles) in;\n" 3074 "layout (points, max_vertices = 1) out;\n" 3075 "\n" 3076 "${IN_PER_VERTEX_DECL_ARRAY}" 3077 "\n" 3078 "void main()\n" 3079 "{\n" 3080 " gl_Position = gl_in[0].gl_Position;\n" 3081 " EmitVertex();\n" 3082 "}\n"; 3083 3084 const char* gs_code_triangles_adjacency = "${VERSION}\n" 3085 "${GEOMETRY_SHADER_REQUIRE}\n" 3086 "\n" 3087 "layout (triangles_adjacency) in;\n" 3088 "layout (points, max_vertices = 1) out;\n" 3089 "\n" 3090 "${IN_PER_VERTEX_DECL_ARRAY}" 3091 "\n" 3092 "void main()\n" 3093 "{\n" 3094 " gl_Position = gl_in[0].gl_Position;\n" 3095 " EmitVertex();\n" 3096 "}\n"; 3097 3098 bool has_shader_compilation_failed = true; 3099 bool result = true; 3100 3101 m_gs_ids = new glw::GLuint[m_number_of_gs]; 3102 m_po_ids = new glw::GLuint[m_number_of_gs]; 3103 3104 /* This test should only run if EXT_geometry_shader is supported. */ 3105 if (!m_is_geometry_shader_extension_supported) 3106 { 3107 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 3108 } 3109 3110 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3111 3112 /* Create program objects & geometry shader objects. */ 3113 for (glw::GLuint i = 0; i < m_number_of_gs; ++i) 3114 { 3115 m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER); 3116 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 3117 3118 m_po_ids[i] = gl.createProgram(); 3119 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 3120 } 3121 3122 /* Create shader object. */ 3123 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 3124 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 3125 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 3126 3127 /* Try to link the test program object */ 3128 std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); 3129 const char* fs_code_specialized_raw = fs_code_specialized.c_str(); 3130 3131 std::string gs_codes_specialized[] = { specializeShader(1, &gs_code_points), specializeShader(1, &gs_code_lines), 3132 specializeShader(1, &gs_code_lines_adjacency), 3133 specializeShader(1, &gs_code_triangles), 3134 specializeShader(1, &gs_code_triangles_adjacency) }; 3135 3136 const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str(), 3137 gs_codes_specialized[2].c_str(), gs_codes_specialized[3].c_str(), 3138 gs_codes_specialized[4].c_str() }; 3139 std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); 3140 const char* vs_code_specialized_raw = vs_code_specialized.c_str(); 3141 3142 for (glw::GLuint i = 0; i < m_number_of_gs; ++i) 3143 { 3144 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1, /* n_sh1_body_parts */ 3145 &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */ 3146 &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */ 3147 &vs_code_specialized_raw, &has_shader_compilation_failed)) 3148 { 3149 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = " 3150 << "[" << i << "]." << tcu::TestLog::EndMessage; 3151 3152 result = false; 3153 break; 3154 } 3155 } 3156 3157 if (result) 3158 { 3159 /* Configure VAO. */ 3160 gl.genVertexArrays(1, &m_vao_id); 3161 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 3162 3163 gl.bindVertexArray(m_vao_id); 3164 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 3165 3166 for (glw::GLuint po = 0; po < m_number_of_gs; ++po) 3167 { 3168 /* Use Program Object. */ 3169 gl.useProgram(m_po_ids[po]); 3170 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 3171 3172 if (po != 0) 3173 { 3174 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/); 3175 3176 if (GL_INVALID_OPERATION != gl.getError()) 3177 { 3178 result = false; 3179 3180 m_testCtx.getLog() << tcu::TestLog::Message 3181 << "Error different than GL_INVALID_OPEARATION was generated." 3182 << tcu::TestLog::EndMessage; 3183 3184 break; 3185 } 3186 } 3187 3188 if (po != 1) 3189 { 3190 gl.drawArrays(GL_LINES, 0 /*starting index*/, 2 /*number of indices*/); 3191 3192 if (GL_INVALID_OPERATION != gl.getError()) 3193 { 3194 result = false; 3195 3196 m_testCtx.getLog() << tcu::TestLog::Message 3197 << "Error different than GL_INVALID_OPEARATION was generated." 3198 << tcu::TestLog::EndMessage; 3199 3200 break; 3201 } 3202 3203 gl.drawArrays(GL_LINE_LOOP, 0 /*starting index*/, 2 /*number of indices*/); 3204 3205 if (GL_INVALID_OPERATION != gl.getError()) 3206 { 3207 result = false; 3208 3209 m_testCtx.getLog() << tcu::TestLog::Message 3210 << "Error different than GL_INVALID_OPEARATION was generated." 3211 << tcu::TestLog::EndMessage; 3212 3213 break; 3214 } 3215 3216 gl.drawArrays(GL_LINE_STRIP, 0 /*starting index*/, 2 /*number of indices*/); 3217 3218 if (GL_INVALID_OPERATION != gl.getError()) 3219 { 3220 result = false; 3221 3222 m_testCtx.getLog() << tcu::TestLog::Message 3223 << "Error different than GL_INVALID_OPEARATION was generated." 3224 << tcu::TestLog::EndMessage; 3225 3226 break; 3227 } 3228 } 3229 3230 if (po != 2) 3231 { 3232 gl.drawArrays(GL_LINES_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/); 3233 3234 if (GL_INVALID_OPERATION != gl.getError()) 3235 { 3236 result = false; 3237 3238 m_testCtx.getLog() << tcu::TestLog::Message 3239 << "Error different than GL_INVALID_OPEARATION was generated." 3240 << tcu::TestLog::EndMessage; 3241 3242 break; 3243 } 3244 3245 gl.drawArrays(GL_LINE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/); 3246 3247 if (GL_INVALID_OPERATION != gl.getError()) 3248 { 3249 result = false; 3250 3251 m_testCtx.getLog() << tcu::TestLog::Message 3252 << "Error different than GL_INVALID_OPEARATION was generated." 3253 << tcu::TestLog::EndMessage; 3254 3255 break; 3256 } 3257 } 3258 3259 if (po != 3) 3260 { 3261 gl.drawArrays(GL_TRIANGLES, 0 /*starting index*/, 3 /*number of indices*/); 3262 3263 if (GL_INVALID_OPERATION != gl.getError()) 3264 { 3265 result = false; 3266 3267 m_testCtx.getLog() << tcu::TestLog::Message 3268 << "Error different than GL_INVALID_OPEARATION was generated." 3269 << tcu::TestLog::EndMessage; 3270 3271 break; 3272 } 3273 3274 gl.drawArrays(GL_TRIANGLE_FAN, 0 /*starting index*/, 3 /*number of indices*/); 3275 3276 if (GL_INVALID_OPERATION != gl.getError()) 3277 { 3278 result = false; 3279 3280 m_testCtx.getLog() << tcu::TestLog::Message 3281 << "Error different than GL_INVALID_OPEARATION was generated." 3282 << tcu::TestLog::EndMessage; 3283 3284 break; 3285 } 3286 3287 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /*starting index*/, 3 /*number of indices*/); 3288 3289 if (GL_INVALID_OPERATION != gl.getError()) 3290 { 3291 result = false; 3292 3293 m_testCtx.getLog() << tcu::TestLog::Message 3294 << "Error different than GL_INVALID_OPEARATION was generated." 3295 << tcu::TestLog::EndMessage; 3296 3297 break; 3298 } 3299 } 3300 3301 if (po != 4) 3302 { 3303 gl.drawArrays(GL_TRIANGLES_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/); 3304 3305 if (GL_INVALID_OPERATION != gl.getError()) 3306 { 3307 result = false; 3308 3309 m_testCtx.getLog() << tcu::TestLog::Message 3310 << "Error different than GL_INVALID_OPEARATION was generated." 3311 << tcu::TestLog::EndMessage; 3312 3313 break; 3314 } 3315 3316 gl.drawArrays(GL_TRIANGLE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/); 3317 3318 if (GL_INVALID_OPERATION != gl.getError()) 3319 { 3320 result = false; 3321 3322 m_testCtx.getLog() << tcu::TestLog::Message 3323 << "Error different than GL_INVALID_OPEARATION was generated." 3324 << tcu::TestLog::EndMessage; 3325 3326 break; 3327 } 3328 } 3329 } 3330 } 3331 3332 if (result) 3333 { 3334 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3335 } 3336 else 3337 { 3338 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3339 } 3340 3341 return STOP; 3342 } 3343 3344 /** Constructor 3345 * 3346 * @param context Test context 3347 * @param extParams Not used. 3348 * @param name Test case's name 3349 * @param description Test case's description 3350 **/ 3351 GeometryShaderInsufficientEmittedVerticesTest::GeometryShaderInsufficientEmittedVerticesTest( 3352 Context& context, const ExtParameters& extParams, const char* name, const char* description) 3353 : TestCaseBase(context, extParams, name, description) 3354 , m_fbo_id(0) 3355 , m_fs_id(0) 3356 , m_gs_ids(NULL) 3357 , m_number_of_color_components(4) 3358 , m_number_of_gs(2 /*taken from test spec*/) 3359 , m_po_ids(NULL) 3360 , m_texture_height(16) 3361 , m_texture_id(0) 3362 , m_texture_width(16) 3363 { 3364 m_vao_id = 0; 3365 m_vs_id = 0; 3366 3367 /* Allocate enough memory for glReadPixels() data which is respectively: width, height, RGBA components number. */ 3368 m_pixels = new glw::GLubyte[m_texture_height * m_texture_width * m_number_of_color_components]; 3369 } 3370 3371 /** Deinitializes GLES objects created during the test. */ 3372 void GeometryShaderInsufficientEmittedVerticesTest::deinit() 3373 { 3374 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3375 3376 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 3377 3378 if (m_pixels != NULL) 3379 { 3380 delete[] m_pixels; 3381 m_pixels = NULL; 3382 } 3383 3384 if (m_fbo_id != 0) 3385 { 3386 gl.deleteFramebuffers(1, &m_fbo_id); 3387 m_fbo_id = 0; 3388 } 3389 3390 if (m_fs_id != 0) 3391 { 3392 gl.deleteShader(m_fs_id); 3393 m_fs_id = 0; 3394 } 3395 3396 if (m_gs_ids != 0) 3397 { 3398 for (glw::GLuint i = 0; i < m_number_of_gs; ++i) 3399 { 3400 gl.deleteShader(m_gs_ids[i]); 3401 m_gs_ids[i] = 0; 3402 } 3403 3404 delete[] m_gs_ids; 3405 m_gs_ids = NULL; 3406 } 3407 3408 if (m_po_ids != 0) 3409 { 3410 for (glw::GLuint i = 0; i < m_number_of_gs; ++i) 3411 { 3412 gl.deleteProgram(m_po_ids[i]); 3413 m_po_ids[i] = 0; 3414 } 3415 3416 delete[] m_po_ids; 3417 m_po_ids = NULL; 3418 } 3419 3420 if (m_texture_id != 0) 3421 { 3422 gl.deleteTextures(1, &m_texture_id); 3423 m_texture_id = 0; 3424 } 3425 3426 if (m_vao_id != 0) 3427 { 3428 gl.deleteVertexArrays(1, &m_vao_id); 3429 m_vao_id = 0; 3430 } 3431 3432 if (m_vs_id != 0) 3433 { 3434 gl.deleteShader(m_vs_id); 3435 m_vs_id = 0; 3436 } 3437 3438 /* Release base class */ 3439 TestCaseBase::deinit(); 3440 } 3441 3442 /** Executes the test. 3443 * 3444 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 3445 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 3446 * Note the function throws exception should an error occur! 3447 **/ 3448 tcu::TestNode::IterateResult GeometryShaderInsufficientEmittedVerticesTest::iterate() 3449 { 3450 /* Define Fragment Shader for purpose of this test. */ 3451 const char* fs_code = "${VERSION}\n" 3452 "\n" 3453 "precision highp float;\n" 3454 "\n" 3455 "out vec4 result;\n" 3456 "\n" 3457 "void main()\n" 3458 "{\n" 3459 " result = vec4(1.0, 0.0, 0.0, 0.0);\n" 3460 "}\n"; 3461 3462 /* Define 2 Geometry Shaders for purpose of this test. */ 3463 const char* gs_line_strip = "${VERSION}\n" 3464 "${GEOMETRY_SHADER_REQUIRE}\n" 3465 "\n" 3466 "layout (points) in;\n" 3467 "layout (line_strip, max_vertices = 2) out;\n" 3468 "\n" 3469 "${IN_PER_VERTEX_DECL_ARRAY}" 3470 "\n" 3471 "void main()\n" 3472 "{\n" 3473 " gl_Position = gl_in[0].gl_Position;\n" 3474 " gl_Position.zw = vec2(0.0, 1.0);\n" 3475 " EmitVertex();\n" 3476 "}\n"; 3477 3478 const char* gs_triangle_strip = "${VERSION}\n" 3479 "${GEOMETRY_SHADER_REQUIRE}\n" 3480 "\n" 3481 "layout (points) in;\n" 3482 "layout (triangle_strip, max_vertices = 3) out;\n" 3483 "\n" 3484 "${IN_PER_VERTEX_DECL_ARRAY}" 3485 "\n" 3486 "void main()\n" 3487 "{\n" 3488 " gl_Position = gl_in[0].gl_Position;\n" 3489 " gl_Position.zw = vec2(0.0, 1.0);\n" 3490 " EmitVertex();\n" 3491 3492 " gl_Position = gl_in[0].gl_Position;\n" 3493 " gl_Position.zw = vec2(0.0, 1.0);\n" 3494 " EmitVertex();\n" 3495 "}\n"; 3496 3497 bool has_shader_compilation_failed = true; 3498 bool result = true; 3499 3500 m_gs_ids = new glw::GLuint[m_number_of_gs]; 3501 m_po_ids = new glw::GLuint[m_number_of_gs]; 3502 3503 /* This test should only run if EXT_geometry_shader is supported. */ 3504 if (!m_is_geometry_shader_extension_supported) 3505 { 3506 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 3507 } 3508 3509 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3510 3511 /* Create program objects & geometry shader objects. */ 3512 for (glw::GLuint i = 0; i < m_number_of_gs; ++i) 3513 { 3514 m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER); 3515 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 3516 3517 m_po_ids[i] = gl.createProgram(); 3518 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 3519 } 3520 3521 /* Create shader object. */ 3522 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 3523 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 3524 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 3525 3526 /* Try to link the test program object */ 3527 std::string fs_code_specialized = specializeShader(1, &fs_code); 3528 const char* fs_code_specialized_raw = fs_code_specialized.c_str(); 3529 3530 std::string gs_codes_specialized[] = { specializeShader(1, &gs_line_strip), 3531 specializeShader(1, &gs_triangle_strip) }; 3532 3533 const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str() }; 3534 3535 std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); 3536 const char* vs_code_specialized_raw = vs_code_specialized.c_str(); 3537 3538 for (glw::GLuint i = 0; i < m_number_of_gs; ++i) 3539 { 3540 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1, /* n_sh1_body_parts */ 3541 &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */ 3542 &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */ 3543 &vs_code_specialized_raw, &has_shader_compilation_failed)) 3544 { 3545 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = " 3546 << "[" << i << "]." << tcu::TestLog::EndMessage; 3547 3548 result = false; 3549 break; 3550 } 3551 } 3552 3553 if (result) 3554 { 3555 /* Create a 2D texture. */ 3556 gl.genTextures(1, &m_texture_id); 3557 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 3558 3559 gl.bindTexture(GL_TEXTURE_2D, m_texture_id); 3560 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 3561 3562 gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_RGBA8, 16 /*width taken from spec*/, 3563 16 /*height taken from spec*/); 3564 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed."); 3565 3566 /* Configure FBO. */ 3567 gl.genFramebuffers(1, &m_fbo_id); 3568 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed."); 3569 3570 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 3571 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 3572 3573 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /*level*/); 3574 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 3575 3576 /* Configure VAO. */ 3577 gl.genVertexArrays(1, &m_vao_id); 3578 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 3579 3580 gl.bindVertexArray(m_vao_id); 3581 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 3582 3583 gl.clearColor(0.0f, 1.0f, 0.0f, 0.0f); 3584 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed."); 3585 3586 for (glw::GLuint po = 0; po < m_number_of_gs; ++po) 3587 { 3588 /* Use Program Object. */ 3589 gl.useProgram(m_po_ids[po]); 3590 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 3591 3592 gl.clear(GL_COLOR_BUFFER_BIT); 3593 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed."); 3594 3595 gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/); 3596 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname."); 3597 3598 gl.readPixels(0 /*x*/, 0 /*y*/, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels); 3599 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 3600 3601 for (glw::GLuint pixel = 0; pixel < (m_texture_width * m_texture_height * m_number_of_color_components - 3602 m_number_of_color_components); 3603 pixel += m_number_of_color_components) 3604 { 3605 if (m_pixels[pixel] != 0 && m_pixels[pixel + 1] != 255 && m_pixels[pixel + 2] != 0 && 3606 m_pixels[pixel + 3] != 0) 3607 { 3608 result = false; 3609 3610 m_testCtx.getLog() << tcu::TestLog::Message << "Pixel [" << pixel << "] has color = [" 3611 << m_pixels[pixel] << ", " << m_pixels[pixel + 1] << ", " << m_pixels[pixel + 2] 3612 << ", " << m_pixels[pixel + 3] << "] " 3613 << "instead of [0, 255, 0, 0]." << tcu::TestLog::EndMessage; 3614 3615 break; 3616 } 3617 } 3618 } 3619 } 3620 3621 if (result) 3622 { 3623 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3624 } 3625 else 3626 { 3627 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3628 } 3629 3630 return STOP; 3631 } 3632 3633 /** Constructor 3634 * 3635 * @param context Test context 3636 * @param extParams Not used. 3637 * @param name Test case's name 3638 * @param description Test case's description 3639 **/ 3640 GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest:: 3641 GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context& context, 3642 const ExtParameters& extParams, 3643 const char* name, 3644 const char* description) 3645 : TestCaseBase(context, extParams, name, description) 3646 , m_gs_id(0) 3647 , m_gs_po_id(0) 3648 , m_ppo_id(0) 3649 , m_tfbo_id(0) 3650 , m_vao_id(0) 3651 , m_vs_id(0) 3652 , m_vs_po_id(0) 3653 { 3654 } 3655 3656 /** Deinitializes GLES objects created during the test. */ 3657 void GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::deinit() 3658 { 3659 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3660 3661 if (m_gs_id != 0) 3662 { 3663 gl.deleteShader(m_gs_id); 3664 m_gs_id = 0; 3665 } 3666 3667 if (m_gs_po_id != 0) 3668 { 3669 gl.deleteProgram(m_gs_po_id); 3670 m_gs_po_id = 0; 3671 } 3672 3673 if (m_ppo_id != 0) 3674 { 3675 gl.deleteProgramPipelines(1, &m_ppo_id); 3676 m_ppo_id = 0; 3677 } 3678 3679 if (m_tfbo_id != 0) 3680 { 3681 gl.deleteBuffers(1, &m_tfbo_id); 3682 m_tfbo_id = 0; 3683 } 3684 3685 if (m_vao_id != 0) 3686 { 3687 gl.deleteVertexArrays(1, &m_vao_id); 3688 m_vao_id = 0; 3689 } 3690 3691 if (m_vs_id != 0) 3692 { 3693 gl.deleteShader(m_vs_id); 3694 m_vs_id = 0; 3695 } 3696 3697 if (m_vs_po_id != 0) 3698 { 3699 gl.deleteProgram(m_vs_po_id); 3700 m_vs_po_id = 0; 3701 } 3702 3703 /* Release base class */ 3704 TestCaseBase::deinit(); 3705 } 3706 3707 /** Executes the test. 3708 * 3709 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 3710 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 3711 * Note the function throws exception should an error occur! 3712 **/ 3713 tcu::TestNode::IterateResult GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::iterate() 3714 { 3715 /* Define Geometry Shader for purpose of this test. */ 3716 const char* gs_code = 3717 "${VERSION}\n" 3718 "${GEOMETRY_SHADER_REQUIRE}\n" 3719 "${IN_PER_VERTEX_DECL_ARRAY}\n" 3720 "${OUT_PER_VERTEX_DECL}\n" 3721 "\n" 3722 "layout (points) in;\n" 3723 "layout (points, max_vertices = 1) out;\n" 3724 "\n" 3725 "flat in int vertexID[];\n" 3726 "flat in ivec4 out_vs_1[];\n" 3727 "\n" 3728 "out vec4 out_gs_1;\n" 3729 "\n" 3730 "void main()\n" 3731 "{\n" 3732 " out_gs_1 = vec4(vertexID[0] * 2, vertexID[0] * 2 + 1, vertexID[0] * 2 + 2, vertexID[0] * 2 + 3);\n" 3733 " gl_Position = vec4(0, 0, 0, 1);\n" 3734 " EmitVertex();\n" 3735 "}\n"; 3736 3737 /* Define Vertex Shader for purpose of this test. */ 3738 const char* vs_code = "${VERSION}\n" 3739 "${OUT_PER_VERTEX_DECL}\n" 3740 "\n" 3741 "flat out ivec4 out_vs_1;\n" 3742 "flat out int vertexID;\n" 3743 "\n" 3744 "void main()\n" 3745 "{\n" 3746 " vertexID = gl_VertexID;\n" 3747 " out_vs_1 = ivec4(gl_VertexID, gl_VertexID + 1, gl_VertexID + 2, gl_VertexID + 3);\n" 3748 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" 3749 "}\n"; 3750 3751 bool has_shader_compilation_failed = true; 3752 bool result = true; 3753 glw::GLfloat* ptrTF_data_f = NULL; 3754 glw::GLuint* ptrTF_data_ui = NULL; 3755 glw::GLfloat expected_geom_results[] = { 0.0f, 1.0f, 2.0f, 3.0f }; 3756 glw::GLuint expected_vertex_results[] = { 0, 1, 2, 3 }; 3757 glw::GLfloat epsilon = 1e-5f; 3758 3759 /* This test should only run if EXT_geometry_shader is supported. */ 3760 if (!m_is_geometry_shader_extension_supported) 3761 { 3762 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 3763 } 3764 3765 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3766 3767 /* Create separable program objects. */ 3768 m_gs_po_id = gl.createProgram(); 3769 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 3770 3771 gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE); 3772 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed."); 3773 3774 m_vs_po_id = gl.createProgram(); 3775 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 3776 3777 gl.programParameteri(m_vs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE); 3778 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed."); 3779 3780 /* Create shader objects. */ 3781 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 3782 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 3783 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 3784 3785 /* Try to link the test program object */ 3786 std::string gs_code_specialized = specializeShader(1, &gs_code); 3787 const char* gs_code_specialized_raw = gs_code_specialized.c_str(); 3788 3789 std::string vs_code_specialized = specializeShader(1, &vs_code); 3790 const char* vs_code_specialized_raw = vs_code_specialized.c_str(); 3791 3792 /* Specify output variables to be captured. */ 3793 const char* tf_varyings[2] = { "out_gs_1", "out_vs_1" }; 3794 3795 gl.transformFeedbackVaryings(m_gs_po_id, 1 /*count*/, &tf_varyings[0], GL_INTERLEAVED_ATTRIBS); 3796 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed."); 3797 3798 gl.transformFeedbackVaryings(m_vs_po_id, 1 /*count*/, &tf_varyings[1], GL_INTERLEAVED_ATTRIBS); 3799 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed."); 3800 3801 if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1, /* n_sh1_body_parts */ 3802 &gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */ 3803 NULL, 0, 0, /* n_sh3_body_parts */ 3804 NULL, &has_shader_compilation_failed)) 3805 { 3806 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed." 3807 << tcu::TestLog::EndMessage; 3808 3809 result = false; 3810 goto end; 3811 } 3812 3813 if (!TestCaseBase::buildProgram(m_vs_po_id, m_vs_id, 1, /* n_sh1_body_parts */ 3814 &vs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */ 3815 NULL, 0, 0, /* n_sh3_body_parts */ 3816 NULL, &has_shader_compilation_failed)) 3817 { 3818 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed." 3819 << tcu::TestLog::EndMessage; 3820 3821 result = false; 3822 goto end; 3823 } 3824 3825 /* Create and configure Program Pipeline Object. */ 3826 gl.genProgramPipelines(1, &m_ppo_id); 3827 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call(s) failed."); 3828 3829 gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id); 3830 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed."); 3831 3832 gl.useProgramStages(m_ppo_id, GL_VERTEX_SHADER_BIT, m_vs_po_id); 3833 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed."); 3834 3835 /* Create Vertex Array Object. */ 3836 gl.genVertexArrays(1, &m_vao_id); 3837 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed."); 3838 3839 gl.bindVertexArray(m_vao_id); 3840 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed."); 3841 3842 /* Create Buffer Object for Transform Feedback data. */ 3843 gl.genBuffers(1, &m_tfbo_id); 3844 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed."); 3845 3846 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id); 3847 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed."); 3848 3849 gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4, NULL, GL_STREAM_READ); 3850 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed."); 3851 3852 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id); 3853 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed."); 3854 3855 /* Ensure that there is no program object already bound and bind program pipeline. */ 3856 gl.useProgram(0); 3857 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed."); 3858 3859 gl.bindProgramPipeline(m_ppo_id); 3860 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed."); 3861 3862 gl.enable(GL_RASTERIZER_DISCARD); 3863 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed."); 3864 3865 /* First pass - Vertex and Geometry Shaders On. */ 3866 gl.beginTransformFeedback(GL_POINTS); 3867 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed."); 3868 3869 gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/); 3870 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed."); 3871 3872 gl.endTransformFeedback(); 3873 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed."); 3874 3875 /* Retrieve data and check if it is correct. */ 3876 ptrTF_data_f = 3877 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/, 3878 sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT); 3879 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 3880 3881 for (size_t i = 0; i < 4; ++i) 3882 { 3883 if (fabs(ptrTF_data_f[i] - expected_geom_results[i]) >= epsilon) 3884 { 3885 result = false; 3886 break; 3887 } 3888 } 3889 3890 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3891 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 3892 3893 ptrTF_data_f = NULL; 3894 3895 if (!result) 3896 { 3897 goto end; 3898 } 3899 3900 /* Deactivate Geometry Shader Program Object from Program Pipeline Object. */ 3901 gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, 0 /* program */); 3902 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed."); 3903 3904 /* Second pass - only Vertex Shader Program On. */ 3905 gl.beginTransformFeedback(GL_POINTS); 3906 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed."); 3907 3908 gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/); 3909 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed."); 3910 3911 gl.endTransformFeedback(); 3912 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed."); 3913 3914 gl.disable(GL_RASTERIZER_DISCARD); 3915 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed."); 3916 3917 /* Retrieve data and check if it is correct. */ 3918 ptrTF_data_ui = 3919 (glw::GLuint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/, 3920 sizeof(glw::GLuint) * 4 /* four float vector components */, GL_MAP_READ_BIT); 3921 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 3922 3923 for (size_t i = 0; i < 4; ++i) 3924 { 3925 if (ptrTF_data_ui[i] != expected_vertex_results[i]) 3926 { 3927 result = false; 3928 break; 3929 } 3930 } 3931 3932 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3933 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 3934 3935 ptrTF_data_ui = NULL; 3936 3937 end: 3938 if (result) 3939 { 3940 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3941 } 3942 else 3943 { 3944 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3945 } 3946 3947 return STOP; 3948 } 3949 3950 /** Constructor 3951 * 3952 * @param context Test context 3953 * @param extParams Not used. 3954 * @param name Test case's name 3955 * @param description Test case's description 3956 **/ 3957 GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives( 3958 Context& context, const ExtParameters& extParams, const char* name, const char* description) 3959 : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_tfbo_id(0) 3960 { 3961 m_vao_id = 0; 3962 m_vs_id = 0; 3963 } 3964 3965 /** Deinitializes GLES objects created during the test. */ 3966 void GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::deinit() 3967 { 3968 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3969 3970 if (m_fs_id != 0) 3971 { 3972 gl.deleteShader(m_fs_id); 3973 m_fs_id = 0; 3974 } 3975 3976 if (m_gs_id != 0) 3977 { 3978 gl.deleteShader(m_gs_id); 3979 m_gs_id = 0; 3980 } 3981 3982 if (m_po_id != 0) 3983 { 3984 gl.deleteProgram(m_po_id); 3985 m_po_id = 0; 3986 } 3987 3988 if (m_tfbo_id != 0) 3989 { 3990 gl.deleteBuffers(1, &m_tfbo_id); 3991 m_tfbo_id = 0; 3992 } 3993 3994 if (m_vao_id != 0) 3995 { 3996 gl.deleteVertexArrays(1, &m_vao_id); 3997 m_vao_id = 0; 3998 } 3999 4000 if (m_vs_id != 0) 4001 { 4002 gl.deleteShader(m_vs_id); 4003 m_vs_id = 0; 4004 } 4005 4006 /* Release base class */ 4007 TestCaseBase::deinit(); 4008 } 4009 4010 /** Executes the test. 4011 * 4012 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 4013 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 4014 * Note the function throws exception should an error occur! 4015 **/ 4016 tcu::TestNode::IterateResult GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::iterate() 4017 { 4018 /* Define Geometry Shader for purpose of this test. */ 4019 const char* gs_code = "${VERSION}\n" 4020 "${GEOMETRY_SHADER_REQUIRE}\n" 4021 "\n" 4022 "layout (lines) in;\n" 4023 "layout (triangle_strip, max_vertices = 3) out;\n" 4024 "\n" 4025 "out vec4 out_gs_1;\n" 4026 "\n" 4027 "void main()\n" 4028 "{\n" 4029 " out_gs_1 = vec4(4.0, 3.0, 2.0, 1.0);\n" 4030 "\n" 4031 " gl_Position = vec4(0, 0, 0, 1);\n" 4032 " EmitVertex();\n" 4033 "\n" 4034 " gl_Position = vec4(1, 0, 0, 1);\n" 4035 " EmitVertex();\n" 4036 "\n" 4037 " gl_Position = vec4(1, 1, 0, 1);\n" 4038 " EmitVertex();\n" 4039 "\n" 4040 " EndPrimitive();" 4041 "}\n"; 4042 4043 bool has_shader_compilation_failed = true; 4044 bool result = true; 4045 glw::GLenum error = GL_NO_ERROR; 4046 4047 /* This test should only run if EXT_geometry_shader is supported. */ 4048 if (!m_is_geometry_shader_extension_supported) 4049 { 4050 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 4051 } 4052 4053 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4054 4055 /* Create program object. */ 4056 m_po_id = gl.createProgram(); 4057 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 4058 4059 /* Specify output variables to be captured. */ 4060 const char* tf_varyings[] = { "out_gs_1" }; 4061 4062 gl.transformFeedbackVaryings(m_po_id, 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS); 4063 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed."); 4064 4065 /* Create shader objects. */ 4066 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 4067 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 4068 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 4069 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 4070 4071 /* Try to link the test program object */ 4072 std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); 4073 const char* fs_code_specialized_raw = fs_code_specialized.c_str(); 4074 4075 std::string gs_code_specialized = specializeShader(1, &gs_code); 4076 const char* gs_code_specialized_raw = gs_code_specialized.c_str(); 4077 4078 std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); 4079 const char* vs_code_specialized_raw = vs_code_specialized.c_str(); 4080 4081 if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1, /* n_sh1_body_parts */ 4082 &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */ 4083 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */ 4084 &vs_code_specialized_raw, &has_shader_compilation_failed)) 4085 { 4086 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed whereas a success was expected." 4087 << tcu::TestLog::EndMessage; 4088 4089 result = false; 4090 goto end; 4091 } 4092 4093 /* Create Vertex Array Object. */ 4094 gl.genVertexArrays(1, &m_vao_id); 4095 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed."); 4096 4097 gl.bindVertexArray(m_vao_id); 4098 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed."); 4099 4100 /* Create Buffer Object for Transform Feedback data. */ 4101 gl.genBuffers(1, &m_tfbo_id); 4102 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed."); 4103 4104 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id); 4105 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed."); 4106 4107 gl.bufferData(GL_ARRAY_BUFFER, 4108 sizeof(glw::GLfloat) * 4 * 3 /* capture 4 float vector components times 3 triangle vertices */, NULL, 4109 GL_STREAM_READ); 4110 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed."); 4111 4112 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id); 4113 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed."); 4114 4115 /* Turn on program object. */ 4116 gl.useProgram(m_po_id); 4117 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed."); 4118 4119 gl.enable(GL_RASTERIZER_DISCARD); 4120 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed."); 4121 4122 gl.beginTransformFeedback(GL_LINES); 4123 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed."); 4124 4125 gl.drawArrays(GL_TRIANGLES, 0 /*first*/, 3 /*count*/); 4126 4127 error = gl.getError(); 4128 4129 if (error != GL_INVALID_OPERATION) 4130 { 4131 result = false; 4132 4133 m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated." 4134 << tcu::TestLog::EndMessage; 4135 } 4136 4137 gl.endTransformFeedback(); 4138 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed."); 4139 4140 gl.disable(GL_RASTERIZER_DISCARD); 4141 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed."); 4142 4143 end: 4144 4145 if (result) 4146 { 4147 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4148 } 4149 else 4150 { 4151 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4152 } 4153 4154 return STOP; 4155 } 4156 4157 /** Constructor 4158 * 4159 * @param context Test context 4160 * @param extParams Not used. 4161 * @param name Test case's name 4162 * @param description Test case's description 4163 **/ 4164 GeometryShaderDrawCallsWhileTFPaused::GeometryShaderDrawCallsWhileTFPaused(Context& context, 4165 const ExtParameters& extParams, 4166 const char* name, const char* description) 4167 : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_tfbo_id(0) 4168 { 4169 m_vao_id = 0; 4170 m_vs_id = 0; 4171 } 4172 4173 /** Deinitializes GLES objects created during the test. */ 4174 void GeometryShaderDrawCallsWhileTFPaused::deinit() 4175 { 4176 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4177 4178 if (m_fs_id != 0) 4179 { 4180 gl.deleteShader(m_fs_id); 4181 m_fs_id = 0; 4182 } 4183 4184 if (m_gs_id != 0) 4185 { 4186 gl.deleteShader(m_gs_id); 4187 m_gs_id = 0; 4188 } 4189 4190 for (int i = 0; i < 15 /* All combinations of possible inputs and outputs in GS */; ++i) 4191 { 4192 if (m_po_ids[i] != 0) 4193 { 4194 gl.deleteProgram(m_po_ids[i]); 4195 m_po_ids[i] = 0; 4196 } 4197 } 4198 4199 if (m_tfbo_id != 0) 4200 { 4201 gl.deleteBuffers(1, &m_tfbo_id); 4202 m_tfbo_id = 0; 4203 } 4204 4205 if (m_vao_id != 0) 4206 { 4207 gl.deleteVertexArrays(1, &m_vao_id); 4208 m_vao_id = 0; 4209 } 4210 4211 if (m_vs_id != 0) 4212 { 4213 gl.deleteShader(m_vs_id); 4214 m_vs_id = 0; 4215 } 4216 4217 /* Release base class */ 4218 TestCaseBase::deinit(); 4219 } 4220 4221 /** Executes the test. 4222 * 4223 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 4224 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 4225 * Note the function throws exception should an error occur! 4226 **/ 4227 tcu::TestNode::IterateResult GeometryShaderDrawCallsWhileTFPaused::iterate() 4228 { 4229 /* Define 15 (all combinations of possible inputs and outputs in geometry shader) Geometry Shaders for purpose of this test. */ 4230 const std::string gs_inputs[] = { "points", "lines", "lines_adjacency", "triangles", "triangles_adjacency" }; 4231 const std::string gs_outputs[] = { "points", "line_strip", "triangle_strip" }; 4232 const std::string gs_max_output_vertices[] = { "1", "2", "3" }; 4233 4234 const unsigned short number_of_combinations = 4235 (sizeof(gs_inputs) / sizeof(gs_inputs[0]) * (sizeof(gs_outputs) / sizeof(gs_outputs[0]))); 4236 4237 std::string gs_codes[number_of_combinations]; 4238 glw::GLenum errorCode; 4239 4240 for (size_t i = 0; i < (sizeof(gs_inputs) / sizeof(gs_inputs[0])) /*5 possible GS inputs*/; ++i) 4241 { 4242 for (size_t j = 0; j < (sizeof(gs_outputs) / sizeof(gs_outputs[0])) /*3 possible GS outputs*/; ++j) 4243 { 4244 /* This shader will not emit primitives for anything but points. 4245 * We do so, because we just need to make sure that, while transform feedback 4246 * is paused, all draw calls executed with an active program object which 4247 * includes a geometry shader, are valid. 4248 */ 4249 gs_codes[j + 3 * i] = "${VERSION}\n" 4250 "${GEOMETRY_SHADER_REQUIRE}\n" 4251 "\n" 4252 "layout (" + 4253 gs_inputs[i] + ") in;\n" 4254 "layout (" + 4255 gs_outputs[j] + ", max_vertices = " + gs_max_output_vertices[j] + 4256 ") out;\n" 4257 "\n" 4258 "out vec2 out_gs_1;\n" 4259 "\n" 4260 "void main()\n" 4261 "{\n" 4262 " out_gs_1 = vec2(1.0, 2.0);\n" 4263 " gl_Position = vec4(0, 0, 0, 1);\n" 4264 " EmitVertex();\n" 4265 "}\n"; 4266 } 4267 } 4268 4269 bool has_shader_compilation_failed = true; 4270 bool result = true; 4271 const glw::GLuint tf_modes[3] = { GL_POINTS, GL_LINES, GL_TRIANGLES }; 4272 const glw::GLuint draw_call_modes[5] = { GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES, 4273 GL_TRIANGLES_ADJACENCY }; 4274 4275 /* This test should only run if EXT_geometry_shader is supported. */ 4276 if (!m_is_geometry_shader_extension_supported) 4277 { 4278 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 4279 } 4280 4281 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4282 4283 /* Create program objects. */ 4284 for (int i = 0; i < number_of_combinations; ++i) 4285 { 4286 m_po_ids[i] = gl.createProgram(); 4287 } 4288 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed."); 4289 4290 /* Specify output variables to be captured. */ 4291 const char* tf_varyings[] = { "out_gs_1" }; 4292 4293 for (int i = 0; i < number_of_combinations; ++i) 4294 { 4295 gl.transformFeedbackVaryings(m_po_ids[i], 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS); 4296 } 4297 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed."); 4298 4299 /* Create shader objects. */ 4300 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 4301 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); 4302 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 4303 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 4304 4305 /* Try to link the test program object */ 4306 std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); 4307 const char* fs_code_specialized_raw = fs_code_specialized.c_str(); 4308 4309 std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); 4310 const char* vs_code_specialized_raw = vs_code_specialized.c_str(); 4311 4312 for (int i = 0; i < number_of_combinations; ++i) 4313 { 4314 const char* gs_code = gs_codes[i].c_str(); 4315 std::string gs_code_specialized = specializeShader(1, &gs_code); 4316 const char* gs_code_specialized_raw = gs_code_specialized.c_str(); 4317 4318 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1, /* n_sh1_body_parts */ 4319 &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */ 4320 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */ 4321 &vs_code_specialized_raw, &has_shader_compilation_failed)) 4322 { 4323 m_testCtx.getLog() << tcu::TestLog::Message 4324 << "Program object linking failed whereas a success was expected." 4325 << tcu::TestLog::EndMessage; 4326 4327 result = false; 4328 } 4329 } 4330 4331 if (!result) 4332 { 4333 goto end; 4334 } 4335 4336 /* Create Vertex Array Object. */ 4337 gl.genVertexArrays(1, &m_vao_id); 4338 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed."); 4339 4340 gl.bindVertexArray(m_vao_id); 4341 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed."); 4342 4343 /* Create Buffer Object for Transform Feedback data. */ 4344 gl.genBuffers(1, &m_tfbo_id); 4345 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed."); 4346 4347 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id); 4348 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed."); 4349 4350 gl.bufferData(GL_ARRAY_BUFFER, 4351 sizeof(glw::GLfloat) * 2 * 3 /* capture 2 float vector components times 3 triangle vertices */, NULL, 4352 GL_STREAM_READ); 4353 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed."); 4354 4355 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id); 4356 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed."); 4357 4358 gl.enable(GL_RASTERIZER_DISCARD); 4359 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed."); 4360 4361 for (int i = 0; i < 3 /* number of TF modes */ && result; ++i) 4362 { 4363 for (int j = 0; j < 5 /*number of draw call modes*/ && result; ++j) 4364 { 4365 for (int k = 0; k < 3 /* number of output GS primitive types */; ++k) 4366 { 4367 /* Turn on program object. */ 4368 gl.useProgram(m_po_ids[k + 3 * j]); 4369 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed."); 4370 4371 gl.beginTransformFeedback(tf_modes[i]); 4372 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed."); 4373 4374 gl.pauseTransformFeedback(); 4375 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback() call(s) failed."); 4376 4377 gl.drawArrays(draw_call_modes[j], 0 /*first*/, 3 /*count*/); 4378 errorCode = gl.getError(); 4379 4380 gl.resumeTransformFeedback(); 4381 GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback() call(s) failed."); 4382 4383 gl.endTransformFeedback(); 4384 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed."); 4385 4386 /* If draw call fails stop test execution. */ 4387 if (GL_NO_ERROR != errorCode) 4388 { 4389 m_testCtx.getLog() << tcu::TestLog::Message 4390 << "glDrawArrays() call generated an error while transform feedback was paused." 4391 << tcu::TestLog::EndMessage; 4392 4393 result = false; 4394 break; 4395 } 4396 } 4397 } 4398 } 4399 4400 gl.disable(GL_RASTERIZER_DISCARD); 4401 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed."); 4402 4403 end: 4404 4405 if (result) 4406 { 4407 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4408 } 4409 else 4410 { 4411 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4412 } 4413 4414 return STOP; 4415 } 4416 4417 } // namespace glcts 4418