1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 #include "esextcTextureCubeMapArrayColorDepthAttachments.hpp" 25 26 #include "gluContextInfo.hpp" 27 #include "glwEnums.hpp" 28 #include "glwFunctions.hpp" 29 #include "tcuTestLog.hpp" 30 31 namespace glcts 32 { 33 /* Shader parts */ 34 const glw::GLchar* const TextureCubeMapArrayColorDepthAttachmentsTest::m_fragment_shader_code = 35 "${VERSION}\n" 36 "/* FS */\n" 37 "\n" 38 "precision highp float;\n" 39 "\n" 40 "in flat int fs_in_color;\n" 41 "\n" 42 "layout(location = 0) out int fs_out_color;\n" 43 "\n" 44 "void main()\n" 45 "{\n" 46 " fs_out_color = fs_in_color;\n" 47 "}\n" 48 "\n"; 49 50 const glw::GLchar* const TextureCubeMapArrayColorDepthAttachmentsTest::m_geometry_shader_code_preamble = 51 "${VERSION}\n" 52 "/* Layered GS */\n" 53 "\n" 54 "${GEOMETRY_SHADER_REQUIRE}\n" 55 "\n" 56 "precision highp float;\n" 57 "\n" 58 "layout(points) in;\n" 59 "layout(triangle_strip, max_vertices=4) out;\n" 60 "\n"; 61 62 const glw::GLchar* const TextureCubeMapArrayColorDepthAttachmentsTest::m_geometry_shader_code_layered = 63 "in flat int vs_out_layer[];\n" 64 "\n" 65 "out flat int fs_in_color;\n" 66 "\n" 67 "void main()\n" 68 "{\n" 69 " int layer = vs_out_layer[0];\n"; 70 71 const glw::GLchar* const TextureCubeMapArrayColorDepthAttachmentsTest::m_geometry_shader_code_non_layered = 72 "uniform int uni_layer;\n" 73 "\n" 74 "out flat int fs_in_color;\n" 75 "\n" 76 "void main()\n" 77 "{\n" 78 " int layer = uni_layer;\n"; 79 80 const glw::GLchar* const TextureCubeMapArrayColorDepthAttachmentsTest::m_geometry_shader_code_body = 81 ";\n" 82 " \n" 83 " // Left-Bottom\n" 84 " gl_Position = vec4(-1.0, -1.0, depth, 1);\n" 85 " gl_Layer = layer;\n" 86 " fs_in_color = layer;\n" 87 " EmitVertex();\n" 88 " \n" 89 " // Left-Top\n" 90 " gl_Position = vec4(-1.0, 1.0, depth, 1);\n" 91 " gl_Layer = layer;\n" 92 " fs_in_color = layer;\n" 93 " EmitVertex();\n" 94 " \n" 95 " // Right-Bottom\n" 96 " gl_Position = vec4( 1.0, -1.0, depth, 1);\n" 97 " gl_Layer = layer;\n" 98 " fs_in_color = layer;\n" 99 " EmitVertex();\n" 100 " \n" 101 " // Right-Top\n" 102 " gl_Position = vec4( 1.0, 1.0, depth, 1);\n" 103 " gl_Layer = layer;\n" 104 " fs_in_color = layer;\n" 105 " EmitVertex();\n" 106 " EndPrimitive();\n" 107 "}\n" 108 "\n"; 109 110 const glw::GLchar* const TextureCubeMapArrayColorDepthAttachmentsTest::m_vertex_shader_code = 111 "${VERSION}\n" 112 "/* VS */\n" 113 "\n" 114 "precision highp float;\n" 115 "\n" 116 "flat out int vs_out_layer;\n" 117 "\n" 118 "void main()\n" 119 "{\n" 120 " gl_PointSize = 1.0f;\n" 121 " vs_out_layer = gl_VertexID;\n" 122 "}\n" 123 "\n"; 124 125 /* Static constants */ 126 const glw::GLenum TextureCubeMapArrayColorDepthAttachmentsTest::m_color_internal_format = GL_R32I; 127 const glw::GLenum TextureCubeMapArrayColorDepthAttachmentsTest::m_color_format = GL_RED_INTEGER; 128 const glw::GLenum TextureCubeMapArrayColorDepthAttachmentsTest::m_color_type = GL_INT; 129 const glw::GLenum TextureCubeMapArrayColorDepthAttachmentsTest::m_depth_format = GL_DEPTH_COMPONENT; 130 131 /** Verifies all texels in user-provided data buffer are equal to user-specified vector value. 132 * 133 * @tparam T Type of image components 134 * @tparam N_Components Number of image components 135 * 136 * @param image_width Width of image 137 * @param image_height Height of image 138 * @param components Amount of components per texel 139 * @param image Image data 140 * 141 * @return true if all texels are found valid, false otherwise. 142 **/ 143 template <typename T, unsigned int N_Components> 144 bool verifyImage(glw::GLuint image_width, glw::GLuint image_height, const T* components, const T* image) 145 { 146 const glw::GLuint line_size = image_width * N_Components; 147 148 for (glw::GLuint y = 0; y < image_height; ++y) 149 { 150 const glw::GLuint line_offset = y * line_size; 151 152 for (glw::GLuint x = 0; x < image_width; ++x) 153 { 154 const glw::GLuint pixel_offset = line_offset + x * N_Components; 155 156 for (glw::GLuint component = 0; component < N_Components; ++component) 157 { 158 if (image[pixel_offset + component] != components[component]) 159 { 160 return false; 161 } 162 } /* for (all components) */ 163 } /* for (all columns) */ 164 } /* for (all rows) */ 165 166 return true; 167 } 168 169 /** Constructor 170 * 171 * @param size Size of texture 172 * @param n_cubemaps Number of cube-maps in array 173 **/ 174 TextureCubeMapArrayColorDepthAttachmentsTest::_texture_size::_texture_size(glw::GLuint size, glw::GLuint n_cubemaps) 175 : m_size(size), m_n_cubemaps(n_cubemaps) 176 { 177 /* Nothing to be done here */ 178 } 179 180 /** Constructor 181 * 182 * @param context Test context 183 * @param name Test case's name 184 * @param description Test case's description 185 **/ 186 TextureCubeMapArrayColorDepthAttachmentsTest::TextureCubeMapArrayColorDepthAttachmentsTest( 187 Context& context, const ExtParameters& extParams, const char* name, const char* description) 188 : TestCaseBase(context, extParams, name, description) 189 , m_vao_id(0) 190 , m_color_texture_id(0) 191 , m_depth_texture_id(0) 192 , m_fragment_shader_id(0) 193 , m_framebuffer_object_id(0) 194 , m_layered_geometry_shader_id(0) 195 , m_layered_program_id(0) 196 , m_non_layered_geometry_shader_id(0) 197 , m_non_layered_program_id(0) 198 , m_non_layered_program_id_uni_layer_uniform_location(0) 199 , m_vertex_shader_id(0) 200 , m_depth_internal_format(0) 201 , m_depth_type(0) 202 , m_n_invalid_color_checks(0) 203 , m_n_invalid_depth_checks(0) 204 { 205 /* Define tested resolutions */ 206 m_resolutions.push_back(_texture_size(8, 8)); 207 m_resolutions.push_back(_texture_size(64, 3)); 208 m_resolutions.push_back(_texture_size(117, 1)); 209 m_resolutions.push_back(_texture_size(256, 1)); 210 m_resolutions.push_back(_texture_size(173, 3)); 211 } 212 213 /** Attaches an user-specified texture object to zeroth color attachment OR depth attachment of 214 * test-maintained FBO in a layered manner. 215 * 216 * @param texture_id Texture object's ID. 217 * @param should_use_as_color_attachment true to attach the texture object to GL_COLOR_ATTACHMENT0 of 218 * the test-maintained FBO; false to use GL_DEPTH_ATTACHMENT 219 * binding point. 220 **/ 221 void TextureCubeMapArrayColorDepthAttachmentsTest::configureLayeredFramebufferAttachment( 222 glw::GLuint texture_id, bool should_use_as_color_attachment) 223 { 224 glw::GLenum attachment = GL_NONE; 225 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 226 227 /* Determine which attachment should be used */ 228 if (true == should_use_as_color_attachment) 229 { 230 attachment = GL_COLOR_ATTACHMENT0; 231 } 232 else 233 { 234 attachment = GL_DEPTH_ATTACHMENT; 235 } 236 237 /* Re-bind the draw framebuffer, just in case. */ 238 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_object_id); 239 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 240 241 /* Update the FBO's attachment */ 242 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, attachment, texture_id, 0 /* level */); 243 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureEXT() call failed."); 244 } 245 246 /** Attaches an user-specified texture object to zeroth color attachment OR depth attachment of 247 * test-maintained FBO in a non-layered manner. 248 * 249 * @param texture_id Texture object's ID. 250 * @param n_layer Layer of the texture to attach. 251 * @param should_use_as_color_attachment true to attach the texture object to GL_COLOR_ATTACHMENT0 of 252 * the test-maintained FBO; false to use GL_DEPTH_ATTACHMENT 253 * binding point. 254 * @param should_update_draw_framebuffer true to bind the test-maintained FBO to GL_DRAW_FRAMEBUFFER 255 * binding point first, false to use GL_READ_FRAMEBUFFER binding 256 * point. 257 **/ 258 void TextureCubeMapArrayColorDepthAttachmentsTest::configureNonLayeredFramebufferAttachment( 259 glw::GLuint texture_id, glw::GLuint n_layer, bool should_use_as_color_attachment, 260 bool should_update_draw_framebuffer) 261 { 262 glw::GLenum attachment_type = GL_NONE; 263 glw::GLenum framebuffer_target = GL_NONE; 264 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 265 266 /* Determine which attachment should be used */ 267 if (true == should_use_as_color_attachment) 268 { 269 attachment_type = GL_COLOR_ATTACHMENT0; 270 } 271 else 272 { 273 attachment_type = GL_DEPTH_ATTACHMENT; 274 } 275 276 /* Determine which framebuffer target should be used */ 277 if (true == should_update_draw_framebuffer) 278 { 279 framebuffer_target = GL_DRAW_FRAMEBUFFER; 280 } 281 else 282 { 283 framebuffer_target = GL_READ_FRAMEBUFFER; 284 } 285 286 /* Re-bind the framebuffer, just in case. */ 287 gl.bindFramebuffer(framebuffer_target, m_framebuffer_object_id); 288 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 289 290 /* Use the specified texture layer as attachment */ 291 gl.framebufferTextureLayer(framebuffer_target, attachment_type, texture_id, 0 /* level */, n_layer); 292 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() call failed."); 293 } 294 295 /* Deinitializes GLES objects created during the test. */ 296 void TextureCubeMapArrayColorDepthAttachmentsTest::deinit() 297 { 298 /* Deinitialize base class */ 299 TestCaseBase::deinit(); 300 301 if (true != m_is_texture_cube_map_array_supported) 302 { 303 return; 304 } 305 if (true != m_is_geometry_shader_extension_supported) 306 { 307 return; 308 } 309 310 /* GL functions */ 311 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 312 313 /* Release texture objects */ 314 releaseAndDetachTextureObject(m_color_texture_id, true /* is_color_attachment */); 315 releaseAndDetachTextureObject(m_depth_texture_id, false /* is_color_attachment */); 316 317 /* Restore default state */ 318 gl.useProgram(0); 319 gl.bindVertexArray(0); 320 321 /* Delete all remaining ES objects the test may have created. */ 322 if (0 != m_fragment_shader_id) 323 { 324 gl.deleteShader(m_fragment_shader_id); 325 326 m_fragment_shader_id = 0; 327 } 328 329 if (0 != m_framebuffer_object_id) 330 { 331 gl.deleteFramebuffers(1, &m_framebuffer_object_id); 332 333 m_framebuffer_object_id = 0; 334 } 335 336 if (0 != m_layered_geometry_shader_id) 337 { 338 gl.deleteShader(m_layered_geometry_shader_id); 339 340 m_layered_geometry_shader_id = 0; 341 } 342 343 if (0 != m_layered_program_id) 344 { 345 gl.deleteProgram(m_layered_program_id); 346 347 m_layered_program_id = 0; 348 } 349 350 if (0 != m_non_layered_geometry_shader_id) 351 { 352 gl.deleteShader(m_non_layered_geometry_shader_id); 353 354 m_non_layered_geometry_shader_id = 0; 355 } 356 357 if (0 != m_non_layered_program_id) 358 { 359 gl.deleteProgram(m_non_layered_program_id); 360 361 m_non_layered_program_id = 0; 362 } 363 364 if (0 != m_vertex_shader_id) 365 { 366 gl.deleteShader(m_vertex_shader_id); 367 368 m_vertex_shader_id = 0; 369 } 370 371 if (m_vao_id != 0) 372 { 373 gl.deleteVertexArrays(1, &m_vao_id); 374 375 m_vao_id = 0; 376 } 377 } 378 379 /* Determines depth internalformat that can be used for a draw framebuffer. 380 * The result is stored in m_depth_internal_format and m_depth_type. 381 **/ 382 void TextureCubeMapArrayColorDepthAttachmentsTest::determineSupportedDepthFormat() 383 { 384 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 385 386 /* Start with 16-bit depth internalformat */ 387 m_depth_internal_format = GL_DEPTH_COMPONENT16; 388 m_depth_type = GL_UNSIGNED_SHORT; 389 390 while (true) 391 { 392 /* Create color and depth texture objectss */ 393 generateAndConfigureTextureObjects(8, /* texture_width */ 394 1, /* n_cubemaps */ 395 false); /* should_generate_mutable_textures */ 396 397 /* Set framebuffer attachments up */ 398 configureNonLayeredFramebufferAttachment(m_color_texture_id, 0 /* layer */, true /* is_color_attachment */, 399 true /* should_update_draw_framebuffer */); 400 configureNonLayeredFramebufferAttachment(m_depth_texture_id, 0 /* layer */, false /* is_color_attachment */, 401 true /* should_update_draw_framebuffer */); 402 403 /* Check framebuffer status */ 404 const glw::GLenum framebuffer_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); 405 406 if (GL_FRAMEBUFFER_COMPLETE == framebuffer_status) 407 { 408 return; 409 } 410 411 /* Current format does not work too well, try another one */ 412 switch (m_depth_internal_format) 413 { 414 case GL_DEPTH_COMPONENT16: 415 { 416 m_depth_internal_format = GL_DEPTH_COMPONENT24; 417 m_depth_type = GL_UNSIGNED_INT; 418 419 break; 420 } 421 422 case GL_DEPTH_COMPONENT24: 423 { 424 m_depth_internal_format = GL_DEPTH_COMPONENT32F; 425 m_depth_type = GL_FLOAT; 426 427 break; 428 } 429 430 case GL_DEPTH_COMPONENT32F: 431 { 432 throw tcu::NotSupportedError("Implementation does not support any known depth format"); 433 } 434 435 default: 436 { 437 TCU_FAIL("Unrecognized depth internalformat"); 438 } 439 } /* switch (m_depth_internal_format) */ 440 } /* while (true) */ 441 } 442 443 /** Execute a draw call that renders (texture_size.m_n_cubemaps * 6) points. 444 * First, the viewport is configured to match the texture resolution and 445 * both color & depth buffers are cleared. 446 * 447 * @param texture_size Render-target resolution. 448 * 449 **/ 450 void TextureCubeMapArrayColorDepthAttachmentsTest::draw(const _texture_size& texture_size) 451 { 452 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 453 454 /* Set up the viewport */ 455 gl.viewport(0, /* x */ 456 0, /* y */ 457 texture_size.m_size, texture_size.m_size); 458 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed."); 459 460 /* Clear color & depth buffers */ 461 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 462 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed."); 463 464 gl.drawArrays(GL_POINTS, 0 /* first */, texture_size.m_n_cubemaps * 6 /* layer-faces per cube-map */); 465 GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays"); 466 } 467 468 /** Releases existing color & depth cube-map texture array objects, generates new 469 * ones and configures them as per user-specified properties. 470 * 471 * @param texture_width Size to use for each layer-face's width and height. 472 * @param n_cubemaps Number of cube-maps to initialize for the cube-map texture arrays. 473 * @param should_generate_mutable_textures true if the texture should be initialized as mutable, false otherwise. 474 **/ 475 void TextureCubeMapArrayColorDepthAttachmentsTest::generateAndConfigureTextureObjects( 476 glw::GLuint texture_width, glw::GLuint n_cubemaps, bool should_generate_mutable_textures) 477 { 478 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 479 480 /* Release any texture objects that may have already been initialized */ 481 releaseAndDetachTextureObject(m_color_texture_id, true /* is_color_attachment */); 482 releaseAndDetachTextureObject(m_depth_texture_id, false /* is_color_attachment */); 483 484 /* Generate texture objects */ 485 gl.genTextures(1, &m_color_texture_id); 486 gl.genTextures(1, &m_depth_texture_id); 487 488 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed"); 489 490 /* Configure new textures' storage */ 491 if (true == should_generate_mutable_textures) 492 { 493 prepareMutableTextureObject(m_color_texture_id, texture_width, n_cubemaps, 494 true /* should_take_color_texture_properties */); 495 prepareMutableTextureObject(m_depth_texture_id, texture_width, n_cubemaps, 496 false /* should_take_color_texture_properties */); 497 } 498 else 499 { 500 prepareImmutableTextureObject(m_color_texture_id, texture_width, n_cubemaps, 501 true /* should_take_color_texture_properties */); 502 prepareImmutableTextureObject(m_depth_texture_id, texture_width, n_cubemaps, 503 false /* should_take_color_texture_properties */); 504 } 505 } 506 507 /* Initializes all ES objects needed to run the test */ 508 void TextureCubeMapArrayColorDepthAttachmentsTest::initTest() 509 { 510 const glw::GLchar* depth_calculation_code = DE_NULL; 511 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 512 513 /* Check if EXT_texture_cube_map_array extension is supported */ 514 if (true != m_is_texture_cube_map_array_supported) 515 { 516 throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED); 517 } 518 519 /* This test should only run if EXT_geometry_shader is supported */ 520 if (true != m_is_geometry_shader_extension_supported) 521 { 522 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED); 523 } 524 525 /* Generate and bind VAO */ 526 gl.genVertexArrays(1, &m_vao_id); 527 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 528 529 gl.bindVertexArray(m_vao_id); 530 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 531 532 /* Create a framebuffer object */ 533 gl.genFramebuffers(1, &m_framebuffer_object_id); 534 GLU_EXPECT_NO_ERROR(gl.getError(), "genFramebuffers"); 535 536 /* Determine which depth format can be used as a depth attachment without 537 * making the FBO incomplete */ 538 determineSupportedDepthFormat(); 539 540 /* Decide which code snippet to use for depth value calculation */ 541 switch (m_depth_internal_format) 542 { 543 case GL_DEPTH_COMPONENT16: 544 { 545 depth_calculation_code = "-1.0 + float(2 * layer) / float(0xffff)"; 546 547 break; 548 } 549 550 case GL_DEPTH_COMPONENT24: 551 { 552 depth_calculation_code = "-1.0 + float(2 * layer) / float(0xffffff)"; 553 554 break; 555 } 556 557 case GL_DEPTH_COMPONENT32F: 558 { 559 depth_calculation_code = "-1.0 + float(2 * layer) / 256.0"; 560 561 break; 562 } 563 564 default: 565 { 566 TCU_FAIL("Unrecognized depth internal format"); 567 } 568 } /* switch (m_depth_internal_format) */ 569 570 /* Create shader objects */ 571 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 572 m_layered_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 573 m_non_layered_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 574 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 575 576 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); 577 578 /* Create program objects */ 579 m_layered_program_id = gl.createProgram(); 580 m_non_layered_program_id = gl.createProgram(); 581 582 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed"); 583 584 /* Build up an array of snippets making up bodies of two geometry shaders 585 * we'll be using for the test. 586 */ 587 const glw::GLchar* const layered_geometry_shader_parts[] = { m_geometry_shader_code_preamble, 588 m_geometry_shader_code_layered, 589 " float depth = ", depth_calculation_code, 590 m_geometry_shader_code_body }; 591 592 const glw::GLchar* const non_layered_geometry_shader_parts[] = { m_geometry_shader_code_preamble, 593 m_geometry_shader_code_non_layered, 594 " float depth = ", depth_calculation_code, 595 m_geometry_shader_code_body }; 596 597 const glw::GLuint n_layered_geometry_shader_parts = 598 sizeof(layered_geometry_shader_parts) / sizeof(layered_geometry_shader_parts[0]); 599 const glw::GLuint n_non_layered_geometry_shader_parts = 600 sizeof(non_layered_geometry_shader_parts) / sizeof(non_layered_geometry_shader_parts[0]); 601 602 /* Build both programs */ 603 if (!buildProgram(m_layered_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, 604 m_layered_geometry_shader_id, n_layered_geometry_shader_parts, layered_geometry_shader_parts, 605 m_vertex_shader_id, 1, &m_vertex_shader_code)) 606 { 607 TCU_FAIL("Could not build layered-case program object"); 608 } 609 610 if (!buildProgram(m_non_layered_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, 611 m_non_layered_geometry_shader_id, n_non_layered_geometry_shader_parts, 612 non_layered_geometry_shader_parts, m_vertex_shader_id, 1, &m_vertex_shader_code)) 613 { 614 TCU_FAIL("Could not build non-layered-case program object"); 615 } 616 617 /* Get location of "uni_layer" uniform */ 618 m_non_layered_program_id_uni_layer_uniform_location = gl.getUniformLocation(m_non_layered_program_id, "uni_layer"); 619 620 if ((-1 == m_non_layered_program_id_uni_layer_uniform_location) || (GL_NO_ERROR != gl.getError())) 621 { 622 TCU_FAIL("Could not retrieve location of uni_layer uniform for non-layered program"); 623 } 624 } 625 626 /** Executes the test. 627 * 628 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 629 * Note the function throws exception should an error occur! 630 * 631 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 632 **/ 633 tcu::TestCase::IterateResult TextureCubeMapArrayColorDepthAttachmentsTest::iterate() 634 { 635 /* GL functions */ 636 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 637 638 /* Initialize all ES objects needed to run the test */ 639 initTest(); 640 641 /* Setup clear values */ 642 gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */); 643 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed."); 644 645 gl.clearDepthf(1.0f /* d */); 646 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearDepthf() call failed."); 647 648 /* Enable depth test */ 649 gl.enable(GL_DEPTH_TEST); 650 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed"); 651 652 /* Execute tests for each resolution */ 653 for (_texture_size_vector::iterator texture_size_iterator = m_resolutions.begin(), 654 end_iterator = m_resolutions.end(); 655 end_iterator != texture_size_iterator; ++texture_size_iterator) 656 { 657 testNonLayeredRendering(*texture_size_iterator, false); 658 testNonLayeredRendering(*texture_size_iterator, true); 659 testLayeredRendering(*texture_size_iterator, false); 660 testLayeredRendering(*texture_size_iterator, true); 661 } 662 663 /* Test passes if there were no errors */ 664 if ((0 != m_n_invalid_color_checks) || (0 != m_n_invalid_depth_checks)) 665 { 666 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 667 } 668 else 669 { 670 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 671 } 672 673 /* Done */ 674 return STOP; 675 } 676 677 /** Takes a texture ID, binds it to GL_TEXTURE_CUBE_MAP_ARRAY texture target and 678 * initializes an immutable texture storage of @param texture_size x @param texture_size 679 * x (@param n_elements * 6) resolution. 680 * 681 * @param texture_id ID to use for the initialization. 682 * @param texture_size Width & height to use for each layer-face. 683 * @param n_cubemaps Amount of cube-maps to initialize. 684 * @param should_take_color_texture_properties true if m_color_internal_format, m_color_format, 685 * m_color_type should be used for texture storage 686 * initialization, false to use relevant m_depth_* 687 * fields. 688 **/ 689 void TextureCubeMapArrayColorDepthAttachmentsTest::prepareImmutableTextureObject( 690 glw::GLuint texture_id, glw::GLuint texture_size, glw::GLuint n_cubemaps, bool should_take_color_texture_properties) 691 { 692 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 693 glw::GLenum internal_format = GL_NONE; 694 695 /* Set internal_format accordingly to requested texture type */ 696 if (true == should_take_color_texture_properties) 697 { 698 internal_format = m_color_internal_format; 699 } 700 else 701 { 702 internal_format = m_depth_internal_format; 703 } 704 705 /* Bind the texture object to GL_TEXTURE_CUBE_MAP_ARRAY texture target. */ 706 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, texture_id); 707 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 708 709 /* Initialize immutable texture storage as per description */ 710 gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, /* n_mipmap_levels */ 711 internal_format, texture_size, texture_size, n_cubemaps * 6 /* layer-faces per cube-map */); 712 713 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed."); 714 } 715 716 /** Takes a texture ID, binds it to GL_TEXTURE_CUBE_MAP_ARRAY texture target and 717 * initializes a mutable texture storage of @param texture_size x @param texture_size 718 * x (@param n_elements * 6) resolution. Finally,the function sets GL_TEXTURE_MAX_LEVEL 719 * of the texture object to 0. 720 * 721 * @param texture_id ID to use for the initialization. 722 * @param texture_size Width & height to use for each layer-face. 723 * @param n_cubemaps Amount of cube-maps to initialize. 724 * @param should_take_color_texture_properties true if m_color_internal_format, m_color_format, 725 * m_color_type should be used for texture storage 726 * initialization, false to use relevant m_depth_* 727 * fields. 728 **/ 729 void TextureCubeMapArrayColorDepthAttachmentsTest::prepareMutableTextureObject( 730 glw::GLuint texture_id, glw::GLuint texture_size, glw::GLuint n_cubemaps, bool should_take_color_texture_properties) 731 { 732 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 733 glw::GLenum format = GL_NONE; 734 glw::GLenum internal_format = GL_NONE; 735 glw::GLenum type = GL_NONE; 736 737 /* Set internal_format, format and type accordingly to requested texture type */ 738 if (true == should_take_color_texture_properties) 739 { 740 internal_format = m_color_internal_format; 741 format = m_color_format; 742 type = m_color_type; 743 } 744 else 745 { 746 internal_format = m_depth_internal_format; 747 format = m_depth_format; 748 type = m_depth_type; 749 } 750 751 /* Bind the texture object to GL_TEXTURE_CUBE_MAP_ARRAY texture target. */ 752 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, texture_id); 753 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed"); 754 755 /* Initialize mutable texture storage as per description */ 756 gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0 /* mipmap_level */, internal_format, texture_size, texture_size, 757 n_cubemaps * 6 /* layer-faces per cube-map */, 0 /* border */, format, type, 758 DE_NULL); /* initial data */ 759 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D() call failed"); 760 761 /* Update GL_TEXTURE_MAX_LEVEL so that the texture is considered complete */ 762 gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAX_LEVEL, 0 /* param */); 763 764 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed"); 765 } 766 767 /** Releases a texture object and detaches it from test-maintained draw framebuffer. 768 * 769 * @param texture_id Id of the texture object; 770 * @param is_color_attachment true if the texture object described by id @param texture_id 771 * is current draw framebuffer's color attachment, false if it's 772 * a depth attachment. 773 **/ 774 void TextureCubeMapArrayColorDepthAttachmentsTest::releaseAndDetachTextureObject(glw::GLuint texture_id, 775 bool is_color_attachment) 776 { 777 glw::GLenum attachment = GL_NONE; 778 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 779 780 if (true == is_color_attachment) 781 { 782 attachment = GL_COLOR_ATTACHMENT0; 783 } 784 else 785 { 786 attachment = GL_DEPTH_ATTACHMENT; 787 } 788 789 /* Update draw framewbuffer binding just in case. */ 790 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_object_id); 791 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 792 793 /* Clean framebuffer's attachment */ 794 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, /* texture */ 795 0); /* level */ 796 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 797 798 /* Unbind the texture object from GL_TEXTURE_CUBE_MAP_ARRAY binding point */ 799 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 800 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 801 802 /* Finally delete the texture object */ 803 gl.deleteTextures(1, &texture_id); 804 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed."); 805 } 806 807 /** Verifies layered rendering works correctly. 808 * 809 * @param texture_size Resolution of texture; 810 * @param should_use_mutable_textures true if mutable textures should be used for the test, 811 * false to use immutable textures. 812 **/ 813 void TextureCubeMapArrayColorDepthAttachmentsTest::testLayeredRendering(const _texture_size& texture_size, 814 bool should_use_mutable_textures) 815 { 816 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 817 818 /* Generate texture objects for the test */ 819 generateAndConfigureTextureObjects(texture_size.m_size, texture_size.m_n_cubemaps, should_use_mutable_textures); 820 821 /* Setup layered framebuffer */ 822 configureLayeredFramebufferAttachment(m_color_texture_id, true /* should_use_as_color_attachment */); 823 configureLayeredFramebufferAttachment(m_depth_texture_id, false /* should_use_as_color_attachment */); 824 825 /* Activate the program object that performs layered rendering */ 826 gl.useProgram(m_layered_program_id); 827 828 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 829 830 /* Issue the draw call. */ 831 draw(texture_size); 832 833 /* Restore default framebuffer attachments */ 834 configureLayeredFramebufferAttachment(0 /* texture_id */, true /* should_use_as_color_attachment */); 835 configureLayeredFramebufferAttachment(0 /* texture_id */, false /* should_use_as_color_attachment */); 836 837 /* Restore draw framebuffer binding */ 838 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 839 840 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 841 842 /* Time to verify the results - update read framebuffer binding first. */ 843 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer_object_id); 844 845 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 846 847 /* Iterate through all layer-faces */ 848 for (glw::GLuint n_layer_face = 0; n_layer_face < texture_size.m_n_cubemaps * 6 /* layer-faces per cube-map */; 849 ++n_layer_face) 850 { 851 /* Configure read framebuffer attachments to point to the layer of our current interest */ 852 configureNonLayeredFramebufferAttachment(m_color_texture_id, n_layer_face, 853 true, /* should_use_as_color_attachment */ 854 false); /* should_update_draw_framebuffer */ 855 configureNonLayeredFramebufferAttachment(m_depth_texture_id, n_layer_face, 856 false, /* should_use_as_color_attachment */ 857 false); /* should_update_draw_framebuffer */ 858 859 /* Verify contents of color and depth attachments */ 860 bool is_color_data_ok = verifyColorData(texture_size, n_layer_face); 861 bool is_depth_data_ok = false; 862 863 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 864 { 865 switch (m_depth_internal_format) 866 { 867 case GL_DEPTH_COMPONENT16: 868 { 869 is_depth_data_ok = verifyDepth16Data(texture_size, n_layer_face); 870 871 break; 872 } 873 874 case GL_DEPTH_COMPONENT24: 875 { 876 is_depth_data_ok = verifyDepth24Data(texture_size, n_layer_face); 877 878 break; 879 } 880 881 case GL_DEPTH_COMPONENT32F: 882 { 883 is_depth_data_ok = verifyDepth32FData(texture_size, n_layer_face); 884 885 break; 886 } 887 888 default: 889 { 890 TCU_FAIL("Unrecognized depth internalformat"); 891 } 892 } /* switch (m_depth_internal_format) */ 893 } 894 else 895 { 896 is_depth_data_ok = true; 897 } 898 899 /* Any errors? Increment relevant counters */ 900 if (false == is_color_data_ok) 901 { 902 m_n_invalid_color_checks++; 903 } 904 905 if (false == is_depth_data_ok) 906 { 907 m_n_invalid_depth_checks++; 908 } 909 } /* for (all layer-faces) */ 910 } 911 912 /** Verifies layered rendering works correctly. 913 * 914 * @param texture_size Resolution of texture 915 * @param should_use_mutable_texture true if an immutable texture should be used for 916 * the invocation; false if mutable. 917 **/ 918 void TextureCubeMapArrayColorDepthAttachmentsTest::testNonLayeredRendering(const _texture_size& texture_size, 919 bool should_use_mutable_texture) 920 { 921 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 922 923 /* Activate a program object that renders in a non-layered fashion */ 924 gl.useProgram(m_non_layered_program_id); 925 926 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 927 928 /* Create relevant textures */ 929 generateAndConfigureTextureObjects(texture_size.m_size, texture_size.m_n_cubemaps, should_use_mutable_texture); 930 931 /* Iterate over all layer-faces */ 932 for (glw::GLuint n_layer_face = 0; n_layer_face < texture_size.m_n_cubemaps * 6 /* layer-faces per cube-map */; 933 ++n_layer_face) 934 { 935 /* Set up non-layered framebuffer attachments */ 936 configureNonLayeredFramebufferAttachment(m_color_texture_id, n_layer_face, true /* is_color_attachment */); 937 configureNonLayeredFramebufferAttachment(m_depth_texture_id, n_layer_face, false /* is_color_attachment */); 938 939 /* Update value assigned to "uni_layer" uniform */ 940 gl.uniform1i(m_non_layered_program_id_uni_layer_uniform_location, n_layer_face); 941 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed."); 942 943 /* Execute a draw call */ 944 draw(texture_size); 945 946 /* Restore default framebuffer attachments */ 947 configureNonLayeredFramebufferAttachment(0 /* texture_id */, 0 /* n_layer */, 948 true /* should_use_as_color_attachment */); 949 configureNonLayeredFramebufferAttachment(0 /* texture_id */, 0 /* n_layer */, 950 false /* should_use_as_color_attachment */); 951 952 /* Remove draw framebuffer binding */ 953 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 954 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 955 956 /* Verify the results. First, make sure the read framebuffer binding is configured 957 * accordingly. 958 */ 959 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer_object_id); 960 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 961 962 /* Configure read framebuffer attachments to point to the layer of our current interest */ 963 configureNonLayeredFramebufferAttachment(m_color_texture_id, n_layer_face, 964 true, /* should_use_as_color_attachment */ 965 false); /* should_update_draw_framebuffer */ 966 configureNonLayeredFramebufferAttachment(m_depth_texture_id, n_layer_face, 967 false, /* should_use_as_color_attachment */ 968 false); /* should_update_draw_framebuffer */ 969 970 /* Verify contents of color and depth attachments */ 971 bool is_color_data_ok = verifyColorData(texture_size, n_layer_face); 972 bool is_depth_data_ok = false; 973 974 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 975 { 976 switch (m_depth_internal_format) 977 { 978 case GL_DEPTH_COMPONENT16: 979 { 980 is_depth_data_ok = verifyDepth16Data(texture_size, n_layer_face); 981 982 break; 983 } 984 985 case GL_DEPTH_COMPONENT24: 986 { 987 is_depth_data_ok = verifyDepth24Data(texture_size, n_layer_face); 988 989 break; 990 } 991 992 case GL_DEPTH_COMPONENT32F: 993 { 994 is_depth_data_ok = verifyDepth32FData(texture_size, n_layer_face); 995 996 break; 997 } 998 999 default: 1000 { 1001 TCU_FAIL("Unrecognized depth internalformat"); 1002 } 1003 } /* switch (m_depth_internal_format) */ 1004 } 1005 else 1006 { 1007 is_depth_data_ok = true; 1008 } 1009 1010 /* Any errors? Increment relevant counters */ 1011 if (false == is_color_data_ok) 1012 { 1013 m_n_invalid_color_checks++; 1014 } 1015 1016 if (false == is_depth_data_ok) 1017 { 1018 m_n_invalid_depth_checks++; 1019 } 1020 } /* for (all layer-faces) */ 1021 } 1022 1023 /** Reads read buffer's color data and verifies its correctness. 1024 * 1025 * @param texture_size Texture size 1026 * @param n_layer Index of the layer to verify. 1027 * 1028 * @return true if the retrieved data was found correct, false otherwise. 1029 **/ 1030 bool TextureCubeMapArrayColorDepthAttachmentsTest::verifyColorData(const _texture_size& texture_size, 1031 glw::GLuint n_layer) 1032 { 1033 /* Allocate buffer for the data we will retrieve from the implementation */ 1034 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1035 bool result = false; 1036 const glw::GLuint result_data_size = texture_size.m_size * texture_size.m_size * 4; 1037 glw::GLuint* result_data = new glw::GLuint[result_data_size]; 1038 1039 DE_ASSERT(result_data != NULL); 1040 1041 /* Read the data */ 1042 gl.readPixels(0, /* x */ 1043 0, /* y */ 1044 texture_size.m_size, texture_size.m_size, GL_RGBA_INTEGER, m_color_type, result_data); 1045 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 1046 1047 glw::GLuint expected[4] = { n_layer, 0, 0, 1 }; 1048 1049 /* Verify image, expected value is layer index */ 1050 result = verifyImage<glw::GLuint, 4>(texture_size.m_size, texture_size.m_size, expected, result_data); 1051 1052 /* Release the buffer */ 1053 if (result_data != NULL) 1054 { 1055 delete[] result_data; 1056 1057 result_data = NULL; 1058 } 1059 1060 return result; 1061 } 1062 1063 /** Reads read buffer's depth data (assuming it's of 16-bit resolution) 1064 * and verifies its correctness. 1065 * 1066 * @param texture_size Texture size 1067 * @param n_layer Index of the layer to verify. 1068 * 1069 * @return true if the retrieved data was found correct, false otherwise. 1070 **/ 1071 bool TextureCubeMapArrayColorDepthAttachmentsTest::verifyDepth16Data(const _texture_size& texture_size, 1072 glw::GLuint n_layer) 1073 { 1074 /* Allocate buffer for the data we will retrieve from the implementation */ 1075 glw::GLushort expected_value = (glw::GLushort)n_layer; 1076 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1077 bool result = false; 1078 const glw::GLuint result_data_size = texture_size.m_size * texture_size.m_size; 1079 glw::GLushort* result_data = new glw::GLushort[result_data_size]; 1080 1081 DE_ASSERT(result_data != NULL); 1082 1083 gl.pixelStorei(GL_PACK_ALIGNMENT, 2); 1084 1085 /* Read the data */ 1086 gl.readPixels(0, /* x */ 1087 0, /* y */ 1088 texture_size.m_size, texture_size.m_size, m_depth_format, m_depth_type, result_data); 1089 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 1090 1091 /* Verify image, expected value is layer index */ 1092 result = verifyImage<glw::GLushort, 1>(texture_size.m_size, texture_size.m_size, &expected_value, result_data); 1093 1094 /* Release the buffer */ 1095 if (result_data != NULL) 1096 { 1097 delete[] result_data; 1098 1099 result_data = NULL; 1100 } 1101 1102 gl.pixelStorei(GL_PACK_ALIGNMENT, 4); 1103 1104 return result; 1105 } 1106 1107 /** Reads read buffer's depth data (assuming it's of 24-bit resolution) 1108 * and verifies its correctness. 1109 * 1110 * @param texture_size Texture size 1111 * @param n_layer Index of the layer to verify. 1112 * 1113 * @return true if the retrieved data was found correct, false otherwise. 1114 **/ 1115 bool TextureCubeMapArrayColorDepthAttachmentsTest::verifyDepth24Data(const _texture_size& texture_size, 1116 glw::GLuint n_layer) 1117 { 1118 /* Allocate buffer for the data we will retrieve from the implementation */ 1119 glw::GLuint expected_value = n_layer << 8; 1120 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1121 bool result = false; 1122 const glw::GLuint result_data_size = texture_size.m_size * texture_size.m_size; 1123 glw::GLuint* result_data = new glw::GLuint[result_data_size]; 1124 1125 DE_ASSERT(result_data != NULL); 1126 1127 /* Read the data */ 1128 gl.readPixels(0, /* x */ 1129 0, /* y */ 1130 texture_size.m_size, texture_size.m_size, m_depth_format, m_depth_type, result_data); 1131 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 1132 1133 /* Verify image, expected value is layer index */ 1134 result = verifyImage<glw::GLuint, 1>(texture_size.m_size, texture_size.m_size, &expected_value, result_data); 1135 1136 /* Release the buffer */ 1137 if (result_data != NULL) 1138 { 1139 delete[] result_data; 1140 1141 result_data = NULL; 1142 } 1143 1144 return result; 1145 } 1146 1147 /** Reads read buffer's depth data (assuming it's of 32-bit FP resolution) 1148 * and verifies its correctness. 1149 * 1150 * @param texture_size Texture size 1151 * @param n_layer Index of the layer to verify. 1152 * 1153 * @return true if the retrieved data was found correct, false otherwise. 1154 **/ 1155 bool TextureCubeMapArrayColorDepthAttachmentsTest::verifyDepth32FData(const _texture_size& texture_size, 1156 glw::GLuint n_layer) 1157 { 1158 /* Allocate buffer for the data we will retrieve from the implementation */ 1159 glw::GLfloat expected_value = (glw::GLfloat)n_layer / 256.0f; 1160 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1161 bool result = false; 1162 const glw::GLuint result_data_size = texture_size.m_size * texture_size.m_size; 1163 glw::GLfloat* result_data = new glw::GLfloat[result_data_size]; 1164 1165 DE_ASSERT(result_data != NULL); 1166 1167 /* Read the data */ 1168 gl.readPixels(0, /* x */ 1169 0, /* y */ 1170 texture_size.m_size, texture_size.m_size, m_depth_format, m_depth_type, result_data); 1171 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 1172 1173 /* Verify image, expected value is layer index */ 1174 result = verifyImage<glw::GLfloat, 1>(texture_size.m_size, texture_size.m_size, &expected_value, result_data); 1175 1176 /* Release the buffer */ 1177 if (result_data != NULL) 1178 { 1179 delete[] result_data; 1180 1181 result_data = NULL; 1182 } 1183 1184 return result; 1185 } 1186 1187 } /* glcts */ 1188