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/** 25 */ /*! 26 * \file es31cTextureStorageMultisampleFunctionalTests.cpp 27 * \brief Implements conformance tests that verify behavior of 28 * multisample texture functionality (ES3.1 only). 29 */ /*-------------------------------------------------------------------*/ 30 31#include "es31cTextureStorageMultisampleFunctionalTests.hpp" 32#include "gluContextInfo.hpp" 33#include "gluDefs.hpp" 34#include "glwEnums.hpp" 35#include "glwFunctions.hpp" 36#include "tcuRenderTarget.hpp" 37#include "tcuTestLog.hpp" 38 39#include <algorithm> 40#include <string.h> 41#include <string> 42#include <vector> 43 44namespace glcts 45{ 46/** Constructor. 47 * 48 * @param context CTS context handle. 49 **/ 50MultisampleTextureFunctionalTestsBlittingTest::MultisampleTextureFunctionalTestsBlittingTest(Context& context) 51 : TestCase(context, "multisampled_fbo_to_singlesampled_fbo_blit", 52 "Verifies that blitting from a multi-sampled framebuffer object " 53 "to a single-sampled framebuffer object does not generate an error.") 54 , dst_fbo_id(0) 55 , dst_to_color_id(0) 56 , dst_to_depth_stencil_id(0) 57 , src_fbo_id(0) 58 , src_to_color_id(0) 59 , src_to_depth_stencil_id(0) 60{ 61 /* Left blank on purpose */ 62} 63 64/** Deinitializes ES objects created during test execution */ 65void MultisampleTextureFunctionalTestsBlittingTest::deinit() 66{ 67 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 68 69 if (dst_fbo_id != 0) 70 { 71 gl.deleteFramebuffers(1, &dst_fbo_id); 72 73 dst_fbo_id = 0; 74 } 75 76 if (src_fbo_id != 0) 77 { 78 gl.deleteFramebuffers(1, &src_fbo_id); 79 80 src_fbo_id = 0; 81 } 82 83 if (dst_to_color_id != 0) 84 { 85 gl.deleteTextures(1, &dst_to_color_id); 86 87 dst_to_color_id = 0; 88 } 89 90 if (dst_to_depth_stencil_id != 0) 91 { 92 gl.deleteTextures(1, &dst_to_depth_stencil_id); 93 94 dst_to_depth_stencil_id = 0; 95 } 96 97 if (src_to_color_id != 0) 98 { 99 gl.deleteTextures(1, &src_to_color_id); 100 101 src_to_color_id = 0; 102 } 103 104 if (src_to_depth_stencil_id != 0) 105 { 106 gl.deleteTextures(1, &src_to_depth_stencil_id); 107 108 src_to_depth_stencil_id = 0; 109 } 110 111 /* Call base class' deinit() */ 112 TestCase::deinit(); 113} 114 115/** Executes test iteration. 116 * 117 * @return Returns STOP when test has finished executing. 118 */ 119tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingTest::iterate() 120{ 121 bool are_2d_ms_array_tos_supported = 122 m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); 123 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 124 125 /* Set up texture objects */ 126 gl.genTextures(1, &dst_to_color_id); 127 gl.genTextures(1, &dst_to_depth_stencil_id); 128 gl.genTextures(1, &src_to_color_id); 129 gl.genTextures(1, &src_to_depth_stencil_id); 130 131 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects"); 132 133 if (are_2d_ms_array_tos_supported) 134 { 135 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, src_to_color_id); 136 gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */ 137 GL_RGBA8, 4, /* width */ 138 4, /* height */ 139 4, /* depth */ 140 GL_TRUE); /* fixedsamplelocations */ 141 GLU_EXPECT_NO_ERROR(gl.getError(), 142 "gltexStorage3DMultisample() call failed for texture object src_to_color_id"); 143 } 144 else 145 { 146 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_color_id); 147 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ 148 GL_RGBA8, 4, /* width */ 149 4, /* height */ 150 GL_TRUE); /* fixedsamplelocations */ 151 152 GLU_EXPECT_NO_ERROR(gl.getError(), 153 "gltexStorage3DMultisample() call failed for texture object src_to_color_id"); 154 } 155 156 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_depth_stencil_id); 157 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ 158 GL_DEPTH32F_STENCIL8, 4, /* width */ 159 4, /* height */ 160 GL_TRUE); /* fixedsamplelocations */ 161 GLU_EXPECT_NO_ERROR(gl.getError(), 162 "glTexStorage2DMultisample() call failed for texture object src_to_depth_stencil_id"); 163 164 gl.bindTexture(GL_TEXTURE_2D, dst_to_color_id); 165 gl.texImage2D(GL_TEXTURE_2D, 0, /* level */ 166 GL_RGBA8, 4, /* width */ 167 4, /* height */ 168 0, /* border */ 169 GL_RGBA, GL_UNSIGNED_BYTE, NULL); /* data */ 170 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() call failed for texture object dst_to_color_id"); 171 172 gl.bindTexture(GL_TEXTURE_2D_ARRAY, dst_to_depth_stencil_id); 173 gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0, /* level */ 174 GL_DEPTH32F_STENCIL8, 4, /* width */ 175 4, /* height */ 176 4, /* depth */ 177 0, /* border */ 178 GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); /* data */ 179 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D9) call failed for texture object dst_to_depth_stencil_id"); 180 181 /* Set up framebuffer objects */ 182 gl.genFramebuffers(1, &dst_fbo_id); 183 gl.genFramebuffers(1, &src_fbo_id); 184 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo_id); 185 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, src_fbo_id); 186 187 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects"); 188 189 /* Set up source FBO attachments. */ 190 glw::GLenum fbo_completeness_status = 0; 191 192 if (are_2d_ms_array_tos_supported) 193 { 194 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, src_to_color_id, 0, /* level */ 195 0); /* layer */ 196 } 197 else 198 { 199 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_color_id, 200 0); /* level */ 201 } 202 203 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, 204 src_to_depth_stencil_id, 0); /* level */ 205 206 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up source framebuffer's attachments"); 207 208 fbo_completeness_status = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER); 209 210 if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE) 211 { 212 m_testCtx.getLog() << tcu::TestLog::Message << "Source FBO completeness status is: " << fbo_completeness_status 213 << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage; 214 215 TCU_FAIL("Source FBO is considered incomplete which is invalid"); 216 } 217 218 /* Set up draw FBO attachments */ 219 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_color_id, 0); /* level */ 220 gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, dst_to_depth_stencil_id, 0, /* level */ 221 0); /* layer */ 222 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer's attachments"); 223 224 fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); 225 226 if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE) 227 { 228 m_testCtx.getLog() << tcu::TestLog::Message << "Draw FBO completeness status is: " << fbo_completeness_status 229 << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage; 230 231 TCU_FAIL("Draw FBO is considered incomplete which is invalid"); 232 } 233 234 /* Perform the blitting operation */ 235 gl.blitFramebuffer(0, /* srcX0 */ 236 0, /* srcY0 */ 237 4, /* srcX1 */ 238 4, /* srcY1 */ 239 0, /* dstX0 */ 240 0, /* dstY0 */ 241 4, /* dstX1 */ 242 4, /* dstY1 */ 243 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 244 GL_NEAREST); /* An INVALID_OPERATION error is generated if ...., and filter is not NEAREST. */ 245 246 /* Make sure no error was generated */ 247 GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed."); 248 249 /* All done */ 250 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 251 252 return STOP; 253} 254 255/** Constructor. 256 * 257 * @param context CTS context handle. 258 **/ 259MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest:: 260 MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest(Context& context) 261 : TestCase(context, "blitting_multisampled_depth_attachment", 262 "Verifies that blitting a multi-sampled depth attachment to " 263 "a single-sampled depth attachment gives valid results") 264 , fbo_dst_id(0) 265 , fbo_src_id(0) 266 , fs_depth_preview_id(0) 267 , fs_id(0) 268 , po_depth_preview_id(0) 269 , po_id(0) 270 , to_dst_preview_id(0) 271 , to_dst_id(0) 272 , to_src_id(0) 273 , vao_id(0) 274 , vs_id(0) 275{ 276 /* Left blank on purpose */ 277} 278 279/** Deinitializes ES objects created during test execution */ 280void MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest::deinit() 281{ 282 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 283 284 if (fbo_dst_id != 0) 285 { 286 gl.deleteFramebuffers(1, &fbo_dst_id); 287 288 fbo_dst_id = 0; 289 } 290 291 if (fbo_src_id != 0) 292 { 293 gl.deleteFramebuffers(1, &fbo_src_id); 294 295 fbo_src_id = 0; 296 } 297 298 if (to_dst_preview_id != 0) 299 { 300 gl.deleteTextures(1, &to_dst_preview_id); 301 302 to_dst_preview_id = 0; 303 } 304 305 if (to_dst_id != 0) 306 { 307 gl.deleteTextures(1, &to_dst_id); 308 309 to_dst_id = 0; 310 } 311 312 if (to_src_id != 0) 313 { 314 gl.deleteTextures(1, &to_src_id); 315 316 to_src_id = 0; 317 } 318 319 if (fs_id != 0) 320 { 321 gl.deleteShader(fs_id); 322 323 fs_id = 0; 324 } 325 326 if (fs_depth_preview_id != 0) 327 { 328 gl.deleteShader(fs_depth_preview_id); 329 330 fs_depth_preview_id = 0; 331 } 332 333 if (po_depth_preview_id != 0) 334 { 335 gl.deleteProgram(po_depth_preview_id); 336 337 po_depth_preview_id = 0; 338 } 339 340 if (po_id != 0) 341 { 342 gl.deleteProgram(po_id); 343 344 po_id = 0; 345 } 346 347 if (vao_id != 0) 348 { 349 gl.deleteVertexArrays(1, &vao_id); 350 351 vao_id = 0; 352 } 353 354 if (vs_id != 0) 355 { 356 gl.deleteShader(vs_id); 357 358 vs_id = 0; 359 } 360 361 /* Call base class' deinit() */ 362 TestCase::deinit(); 363} 364 365/** Executes test iteration. 366 * 367 * @return Returns STOP when test has finished executing. 368 */ 369tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest::iterate() 370{ 371 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 372 373 /* Generate all objects this test will use */ 374 fs_depth_preview_id = gl.createShader(GL_FRAGMENT_SHADER); 375 fs_id = gl.createShader(GL_FRAGMENT_SHADER); 376 vs_id = gl.createShader(GL_VERTEX_SHADER); 377 378 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 379 380 po_depth_preview_id = gl.createProgram(); 381 po_id = gl.createProgram(); 382 383 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 384 385 gl.genTextures(1, &to_src_id); 386 gl.genTextures(1, &to_dst_preview_id); 387 gl.genTextures(1, &to_dst_id); 388 389 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 390 391 gl.genFramebuffers(1, &fbo_src_id); 392 gl.genFramebuffers(1, &fbo_dst_id); 393 394 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed"); 395 396 gl.genVertexArrays(1, &vao_id); 397 398 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed"); 399 400 /* Bind FBOs to relevant FB targets */ 401 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_dst_id); 402 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_src_id); 403 404 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call(s) failed"); 405 406 /* Configure body of vs_id vertex shader */ 407 const glw::GLchar* vs_body = "#version 310 es\n" 408 "\n" 409 "precision highp float;\n" 410 "\n" 411 "out vec2 uv;\n" 412 "\n" 413 "void main()\n" 414 "{\n" 415 " switch(gl_VertexID)\n" 416 " {\n" 417 " case 0: gl_Position = vec4(-1, -1, 0, 1); uv = vec2(0, 0); break;\n" 418 " case 1: gl_Position = vec4(-1, 1, 0, 1); uv = vec2(0, 1); break;\n" 419 " case 2: gl_Position = vec4( 1, 1, 0, 1); uv = vec2(1, 1); break;\n" 420 " case 3: gl_Position = vec4( 1, -1, 0, 1); uv = vec2(1, 0); break;\n" 421 " }\n" 422 "}\n"; 423 424 gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL); 425 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader of vs_id id"); 426 427 /* Configure body of fs_id fragment shader */ 428 const glw::GLchar* fs_body = "#version 310 es\n" 429 "\n" 430 "precision highp float;\n" 431 "\n" 432 "in vec2 uv;\n" 433 "\n" 434 "void main()\n" 435 "{\n" 436 " gl_FragDepth = uv.x * uv.y;\n" 437 "}\n"; 438 439 gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL); 440 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader of fs_id id"); 441 442 /* Configure body of fs_depth_preview_id fragment shader */ 443 const glw::GLchar* fs_depth_preview_body = "#version 310 es\n" 444 "\n" 445 "precision highp int;\n" 446 "precision highp float;\n" 447 "\n" 448 "in vec2 uv;\n" 449 "out uint result;\n" 450 "uniform sampler2D tex;\n" 451 "\n" 452 "void main()\n" 453 "{\n" 454 " result = floatBitsToUint(textureLod(tex, uv, 0.0).x);\n" 455 "}\n"; 456 457 gl.shaderSource(fs_depth_preview_id, 1 /* count */, &fs_depth_preview_body, NULL); 458 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader of fs_depth_preview_id id"); 459 460 /* Compile all the shaders */ 461 const glw::GLuint shader_ids[] = { fs_id, fs_depth_preview_id, vs_id }; 462 const unsigned int n_shader_ids = sizeof(shader_ids) / sizeof(shader_ids[0]); 463 464 for (unsigned int n_shader_id = 0; n_shader_id < n_shader_ids; ++n_shader_id) 465 { 466 glw::GLint compile_status = GL_FALSE; 467 468 gl.compileShader(shader_ids[n_shader_id]); 469 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed"); 470 471 gl.getShaderiv(shader_ids[n_shader_id], GL_COMPILE_STATUS, &compile_status); 472 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed"); 473 474 if (compile_status != GL_TRUE) 475 { 476 TCU_FAIL("Shader compilation failure"); 477 } 478 } /* for (all shader ids) */ 479 480 /* Configure and link both program objects */ 481 const glw::GLuint program_ids[] = { po_depth_preview_id, po_id }; 482 const unsigned int n_program_ids = sizeof(program_ids) / sizeof(program_ids[0]); 483 484 gl.attachShader(po_depth_preview_id, fs_depth_preview_id); 485 gl.attachShader(po_depth_preview_id, vs_id); 486 gl.attachShader(po_id, fs_id); 487 gl.attachShader(po_id, vs_id); 488 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed"); 489 490 for (unsigned int n_program_id = 0; n_program_id < n_program_ids; ++n_program_id) 491 { 492 glw::GLint link_status = GL_FALSE; 493 494 gl.linkProgram(program_ids[n_program_id]); 495 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed"); 496 497 gl.getProgramiv(program_ids[n_program_id], GL_LINK_STATUS, &link_status); 498 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed"); 499 500 if (link_status != GL_TRUE) 501 { 502 TCU_FAIL("Program linking failure"); 503 } 504 } /* for (all program ids) */ 505 506 /* Retrieve maximum amount of samples that can be used for GL_DEPTH_COMPONENT32F internalformat */ 507 glw::GLint n_depth_component32f_max_samples = 0; 508 509 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_DEPTH_COMPONENT32F, GL_SAMPLES, 1, /* bufSize */ 510 &n_depth_component32f_max_samples); 511 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed"); 512 513 /* Configure texture storage for to_src_id */ 514 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_src_id); 515 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, n_depth_component32f_max_samples, GL_DEPTH_COMPONENT32F, 516 64, /* width */ 517 64, /* height */ 518 GL_FALSE); /* fixedsamplelocations */ 519 520 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure texture storage for texture object to_src_id"); 521 522 gl.texParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 523 524 /* When <target> is TEXTURE_2D_MULTISAMPLE or 525 TEXTURE_2D_MULTISAMPLE_ARRAY_XXX, certain texture parameters may not be 526 specified. In this case, an INVALID_ENUM error is generated if the 527 parameter is any sampler state value from table 6.10. */ 528 glw::GLenum error_code = gl.getError(); 529 if (error_code != GL_INVALID_ENUM) 530 { 531 m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameteri() call generated an error " << error_code 532 << " instead of the expected error code " << GL_INVALID_ENUM << tcu::TestLog::EndMessage; 533 534 TCU_FAIL("glTexParameterf() with target GL_TEXTURE_2D_MULTISAMPLE and pname=GL_TEXTURE_MIN_FILTER did not " 535 "generate GL_INVALID_ENUM."); 536 } 537 538 /* Configure texture storage for to_dst_id */ 539 gl.bindTexture(GL_TEXTURE_2D, to_dst_id); 540 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 541 GL_DEPTH_COMPONENT32F, 64, /* width */ 542 64); /* height */ 543 544 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure texture storage for texture object to_dst_id"); 545 546 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 547 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set nearest minification filter for texture object to_dst_id"); 548 549 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 550 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set nearest magnification filter for texture object to_dst_id"); 551 552 /* Configure draw framebuffer */ 553 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, to_src_id, 554 0); /* level */ 555 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure draw framebuffer for depth data rendering"); 556 557 /* Render the test geometry. 558 * 559 * NOTE: Original test spec rendered to fbo_dst_id which would have been invalid, 560 * since fbo_dst_id is the assumed destination for the blitting operation. 561 * Actual FBO management code has been rewritten to improve code clarity. 562 * 563 * NOTE: Original test spec didn't enable the depth tests, which are necessary 564 * for the depth buffer to be updated. 565 **/ 566 gl.viewport(0, 0, 64 /* rt width */, 64 /* rt height */); 567 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed"); 568 569 gl.enable(GL_DEPTH_TEST); 570 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_DEPTH_TEST) failed"); 571 572 gl.depthFunc(GL_ALWAYS); 573 GLU_EXPECT_NO_ERROR(gl.getError(), "gldepthFunc(GL_ALWAYS) failed"); 574 575 gl.useProgram(po_id); 576 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() for program object po_id failed"); 577 578 gl.bindVertexArray(vao_id); 579 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed"); 580 581 gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */); 582 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 583 584 /* Configure FBOs for blitting */ 585 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, to_src_id, 586 0); /* level */ 587 588 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, to_dst_id, 0); /* level */ 589 590 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure FBOs for blitting"); 591 592 /* Blit source FBO to destination FBO */ 593 gl.blitFramebuffer(0, /* srcX0 */ 594 0, /* srcY0 */ 595 64, /* srcX1 */ 596 64, /* srcY1 */ 597 0, /* dstX0 */ 598 0, /* dstY0 */ 599 64, /* dstX1 */ 600 64, /* dstY1 */ 601 GL_DEPTH_BUFFER_BIT, GL_NEAREST); 602 GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() failed"); 603 604 /* Single-sampled depth data is now stored in dst_to_id in GL_DEPTH_COMPONENT32F which may 605 * not work too well with glReadPixels(). 606 * 607 * We will now convert it to GL_R32UI using the other program */ 608 gl.useProgram(po_depth_preview_id); 609 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed for program object po_depth_preview_id"); 610 611 /* Configure texture storage for the destination texture object */ 612 gl.bindTexture(GL_TEXTURE_2D, to_dst_preview_id); 613 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 614 GL_R32UI, 64, /* width */ 615 64); /* height */ 616 617 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texcture storage for texture object to_dst_preview_id"); 618 619 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 620 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed for texture object to_dst_preview_id"); 621 622 /* Update draw framebuffer configuration */ 623 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, /* texture */ 624 0); /* level */ 625 626 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_dst_preview_id, 0); /* level */ 627 628 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed for depth preview pass"); 629 630 /* Render a full-screen quad */ 631 gl.bindTexture(GL_TEXTURE_2D, to_dst_id); 632 633 gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */); 634 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed for depth preview pass"); 635 636 /* to_dst_id now contains the result data. 637 * 638 * Before we do a glReadPixels() call, we need to re-configure the read FBO */ 639 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, /* texture */ 640 0); /* level */ 641 642 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_dst_preview_id, 0); /* level */ 643 644 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed for depth data download pass"); 645 646 /* Read the data */ 647 unsigned int buffer[64 /* width */ * 64 /* height */ * 4 /* components */]; 648 649 gl.readPixels(0, /* x */ 650 0, /* y */ 651 64, /* width */ 652 64, /* height */ 653 GL_RGBA_INTEGER, GL_UNSIGNED_INT, buffer); 654 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed for depth data download pass"); 655 656 /* Verify the rendered data */ 657 const float epsilon = 1.0f / 64.0f + (float)1e-5; 658 659 for (int y = 0; y < 64 /* height */; ++y) 660 { 661 /* NOTE: data_y is used to take the bottom-top orientation of the data downloaded 662 * by glReadPixels() into account. 663 */ 664 const int data_y = (64 /* height */ - y - 1 /* counting starts from 0 */); 665 const int pixel_size = 4; /* components */ 666 const int row_width = 64 /* width */ * pixel_size; 667 float* row_ptr = (float*)buffer + row_width * data_y; 668 669 for (int x = 0; x < 64 /* width */; ++x) 670 { 671 float* data_ptr = row_ptr + x * pixel_size; 672 float depth = data_ptr[0]; 673 float expected_value_max = float(x) * float(data_y) / (64.0f * 64.0f) + epsilon; 674 float expected_value_min = float(x) * float(data_y) / (64.0f * 64.0f) - epsilon; 675 676 if (!(depth >= expected_value_min && depth <= expected_value_max)) 677 { 678 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data rendered at (" << x << ", " << y << "): " 679 << "Expected value from " << expected_value_min << " to " << expected_value_max 680 << ", " 681 << "rendered: " << depth << tcu::TestLog::EndMessage; 682 683 TCU_FAIL("Invalid data rendered"); 684 } 685 } /* for (all x argument values) */ 686 } /* for (all y argument values) */ 687 688 /* All done */ 689 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 690 691 return STOP; 692} 693 694/** Constructor. 695 * 696 * @param context CTS context handle. 697 **/ 698MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest:: 699 MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest(Context& context) 700 : TestCase(context, "blitting_multisampled_integer_attachment", 701 "Verifies that blitting a multi-sampled integer attachment " 702 "to a single-sampled integer attachment gives valid results") 703 , dst_to_id(0) 704 , fbo_draw_id(0) 705 , fbo_read_id(0) 706 , fs_id(0) 707 , po_id(0) 708 , src_to_id(0) 709 , vs_id(0) 710{ 711 /* Left blank on purpose */ 712} 713 714/** Deinitializes ES objects created during test execution */ 715void MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest::deinit() 716{ 717 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 718 719 if (fbo_draw_id != 0) 720 { 721 gl.deleteFramebuffers(1, &fbo_draw_id); 722 723 fbo_draw_id = 0; 724 } 725 726 if (fbo_read_id != 0) 727 { 728 gl.deleteFramebuffers(1, &fbo_read_id); 729 730 fbo_read_id = 0; 731 } 732 733 if (dst_to_id != 0) 734 { 735 gl.deleteTextures(1, &dst_to_id); 736 737 dst_to_id = 0; 738 } 739 740 if (src_to_id != 0) 741 { 742 gl.deleteTextures(1, &src_to_id); 743 744 src_to_id = 0; 745 } 746 747 if (fs_id != 0) 748 { 749 gl.deleteShader(fs_id); 750 751 fs_id = 0; 752 } 753 754 if (po_id != 0) 755 { 756 gl.deleteProgram(po_id); 757 758 po_id = 0; 759 } 760 761 if (vs_id != 0) 762 { 763 gl.deleteShader(vs_id); 764 765 vs_id = 0; 766 } 767 768 /* Call base class' deinit() */ 769 TestCase::deinit(); 770} 771 772/** Executes test iteration. 773 * 774 * @return Returns STOP when test has finished executing. 775 */ 776tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest::iterate() 777{ 778 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 779 780 /* Make sure GL_MAX_INTEGER_SAMPLES is at least 2 */ 781 glw::GLint gl_max_integer_samples_value = 0; 782 783 gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &gl_max_integer_samples_value); 784 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query GL_MAX_INTEGER_SAMPLES pname value"); 785 786 if (gl_max_integer_samples_value < 2) 787 { 788 throw tcu::NotSupportedError("GL_MAX_INTEGER_SAMPLES is lower than 2"); 789 } 790 791 /* Retrieve maximum amount of samples for GL_R16UI internalformat */ 792 glw::GLint r16ui_max_samples = 0; 793 794 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R16UI, GL_SAMPLES, 1 /* bufSize */, &r16ui_max_samples); 795 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() call failed."); 796 797 /* Set up texture objects */ 798 gl.genTextures(1, &dst_to_id); 799 gl.genTextures(1, &src_to_id); 800 801 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects"); 802 803 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_id); 804 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, r16ui_max_samples, GL_R16UI, 16, /* width */ 805 16, /* height */ 806 GL_FALSE); /* fixedsamplelocations */ 807 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed for texture object src_to_id"); 808 809 gl.bindTexture(GL_TEXTURE_2D, dst_to_id); 810 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 811 GL_R16UI, 16, /* width */ 812 16); /* height */ 813 814 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed for texture object dst_to_id"); 815 816 /* Create a program object */ 817 po_id = gl.createProgram(); 818 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed"); 819 820 /* Create two shader objects */ 821 fs_id = gl.createShader(GL_FRAGMENT_SHADER); 822 vs_id = gl.createShader(GL_VERTEX_SHADER); 823 824 GLU_EXPECT_NO_ERROR(gl.getError(), "Either of the glCreateShader() calls failed"); 825 826 /* Set up framebuffer objects */ 827 gl.genFramebuffers(1, &fbo_draw_id); 828 gl.genFramebuffers(1, &fbo_read_id); 829 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_draw_id); 830 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read_id); 831 832 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects"); 833 834 /* Set up draw FBO's color attachment. */ 835 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_id, 836 0); /* level */ 837 838 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed"); 839 840 /* Set up shader objects. 841 * 842 * NOTE: Original test spec specified an invalid case 3 for the vertex shader. 843 * NOTE: Original test case used a float output value. This would not be valid, 844 * as the color buffer's attachment uses GL_R16UI format. 845 */ 846 glw::GLint compile_status = GL_FALSE; 847 static const char* fs_body = "#version 310 es\n" 848 "\n" 849 "precision highp float;\n" 850 "\n" 851 "uniform uint n_sample;\n" 852 "uniform uint n_max_samples;\n" 853 "uniform highp uvec2 x1y1;\n" 854 "out uint result;\n" 855 "\n" 856 "void main()\n" 857 "{\n" 858 " uint row_index = x1y1.y;\n" 859 " uint column_index = x1y1.x;\n" 860 "\n" 861 " if (n_sample < n_max_samples / 2u)\n" 862 " {\n" 863 " result = row_index * 16u + column_index;\n" 864 " }\n" 865 " else\n" 866 " {\n" 867 " result = row_index * 16u + column_index + 1u;\n" 868 " }\n" 869 "}\n"; 870 static const char* vs_body = "#version 310 es\n" 871 "\n" 872 "uniform uvec2 x1y1;\n" 873 "\n" 874 "void main()\n" 875 "{\n" 876 " switch (gl_VertexID)\n" 877 " {\n" 878 " case 0: gl_Position = vec4( (float(x1y1.x) + 0.0 - 8.0)/8.0, (float(x1y1.y) " 879 "+ 0.0 - 8.0)/8.0, 0.0, 1.0); break;\n" 880 " case 1: gl_Position = vec4( (float(x1y1.x) + 1.0 - 8.0)/8.0, (float(x1y1.y) " 881 "+ 0.0 - 8.0)/8.0, 0.0, 1.0); break;\n" 882 " case 2: gl_Position = vec4( (float(x1y1.x) + 1.0 - 8.0)/8.0, (float(x1y1.y) " 883 "+ 1.0 - 8.0)/8.0, 0.0, 1.0); break;\n" 884 " case 3: gl_Position = vec4( (float(x1y1.x) + 0.0 - 8.0)/8.0, (float(x1y1.y) " 885 "+ 1.0 - 8.0)/8.0, 0.0, 1.0); break;\n" 886 " }\n" 887 "}\n"; 888 889 gl.attachShader(po_id, fs_id); 890 gl.attachShader(po_id, vs_id); 891 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 892 893 gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL); 894 gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL); 895 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed."); 896 897 gl.compileShader(fs_id); 898 gl.compileShader(vs_id); 899 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call(s) failed."); 900 901 gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status); 902 if (compile_status != GL_TRUE) 903 { 904 TCU_FAIL("Could not compile fragment shader"); 905 } 906 907 gl.getShaderiv(vs_id, GL_COMPILE_STATUS, &compile_status); 908 if (compile_status != GL_TRUE) 909 { 910 /* Retrieve and dump compilation fail reason */ 911 char infoLog[1024]; 912 glw::GLsizei length = 0; 913 914 gl.getShaderInfoLog(vs_id, 1024, &length, infoLog); 915 916 m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader compilation failed, infoLog: " << infoLog 917 << tcu::TestLog::EndMessage; 918 919 TCU_FAIL("Could not compile vertex shader"); 920 } 921 922 /* Link the program object */ 923 glw::GLint link_status = GL_FALSE; 924 925 gl.linkProgram(po_id); 926 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed"); 927 928 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 929 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed"); 930 931 if (link_status != GL_TRUE) 932 { 933 TCU_FAIL("Could not link program object"); 934 } 935 936 /* Enable GL_SAMPLE_MASK mode */ 937 gl.enable(GL_SAMPLE_MASK); 938 939 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error"); 940 941 /* Prepare for rendering */ 942 glw::GLint n_max_samples_uniform_location = gl.getUniformLocation(po_id, "n_max_samples"); 943 glw::GLint n_sample_uniform_location = gl.getUniformLocation(po_id, "n_sample"); 944 glw::GLint x1y1_uniform_location = gl.getUniformLocation(po_id, "x1y1"); 945 946 if (n_max_samples_uniform_location == -1) 947 { 948 TCU_FAIL("n_max_samples is not considered an active uniform."); 949 } 950 951 if (n_sample_uniform_location == -1) 952 { 953 TCU_FAIL("n_sample is not considered an active uniform."); 954 } 955 956 if (x1y1_uniform_location == -1) 957 { 958 TCU_FAIL("x1y1 is not considered an active uniform."); 959 } 960 961 gl.viewport(0 /* x */, 0 /* y */, 16 /* width */, 16 /* height */); 962 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed"); 963 964 gl.useProgram(po_id); 965 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 966 967 gl.uniform1ui(n_max_samples_uniform_location, r16ui_max_samples); 968 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1ui() call failed"); 969 970 /* Clear color buffer before drawing to it, not strictly neccesary 971 * but helps debugging */ 972 glw::GLuint clear_color_src[] = { 11, 22, 33, 44 }; 973 974 gl.clearBufferuiv(GL_COLOR, 0, clear_color_src); 975 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv() call failed"); 976 977 /* Render */ 978 for (int x = 0; x < 16 /* width */; ++x) 979 { 980 for (int y = 0; y < 16 /* height */; ++y) 981 { 982 for (int n_sample = 0; n_sample < r16ui_max_samples; ++n_sample) 983 { 984 gl.uniform1ui(n_sample_uniform_location, n_sample); 985 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1ui() call failed"); 986 987 gl.uniform2ui(x1y1_uniform_location, x, y); 988 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2f() call failed"); 989 990 gl.sampleMaski(n_sample / 32, 1 << (n_sample % 32)); 991 GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski() call failed."); 992 993 gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */); 994 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 995 } /* for (all n_sample values) */ 996 } /* for (all y values) */ 997 } /* for (all x values) */ 998 999 /* Now, configure the framebuffer binding points for the blitting operation */ 1000 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_id, 0); /* level */ 1001 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_id, 1002 0); /* level */ 1003 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects for the blitting operation"); 1004 1005 /* Clear color buffer before drawing to it, not strictly neccesary 1006 * but helps debugging */ 1007 glw::GLuint clear_color_dst[] = { 55, 66, 77, 88 }; 1008 1009 gl.clearBufferuiv(GL_COLOR, 0, clear_color_dst); 1010 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv() call failed"); 1011 1012 /* Blit the data. 1013 * 1014 * NOTE: Original test spec specified GL_LINEAR filter which would not have worked 1015 * because the read buffer contains integer data. 1016 **/ 1017 gl.blitFramebuffer(0, /* srcX0 */ 1018 0, /* srcY0 */ 1019 16, /* srcX1 */ 1020 16, /* srcY1 */ 1021 0, /* dstX0 */ 1022 0, /* dstY0 */ 1023 16, /* dstX1 */ 1024 16, /* dstY1 */ 1025 GL_COLOR_BUFFER_BIT, GL_NEAREST); 1026 GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed."); 1027 1028 /* Configure the read framebuffer for upcoming glReadPixels() call */ 1029 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_id, 0); /* level */ 1030 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure the read framebuffer"); 1031 1032 /* Allocate a buffer to hold the result data and then download the result texture's 1033 * contents */ 1034 unsigned int* buffer = new unsigned int[16 /* width */ * 16 /* height */ * 4 /* components */]; 1035 1036 gl.readPixels(0, /* x */ 1037 0, /* y */ 1038 16, /* width */ 1039 16, /* height */ 1040 GL_RGBA_INTEGER, GL_UNSIGNED_INT, buffer); 1041 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 1042 1043 /* Verify the downloaded contents */ 1044 int has_test_fail = 0; 1045 int pixel_size = sizeof(unsigned int) * 4 /* components */; 1046 int row_width = pixel_size * 16 /* width */; 1047 1048 for (unsigned int y = 0; y < 16 /* height */; ++y) 1049 { 1050 /* NOTE: Vertical flipping should not be needed, but we cannot confirm this at the moment. 1051 * Should it be the case, please change data_y to 15 - y */ 1052 /* TODO: Remove NOTE above when verified on actual ES3.1 implementation */ 1053 unsigned int data_y = y; 1054 const unsigned int* row_ptr = (unsigned int*)((char*)buffer + data_y * row_width); 1055 1056 for (unsigned int x = 0; x < 16 /* width */; ++x) 1057 { 1058 const unsigned int* data_ptr = (unsigned int*)((char*)row_ptr + x * pixel_size); 1059 const unsigned int r = data_ptr[0]; 1060 const unsigned int g = data_ptr[1]; 1061 const unsigned int b = data_ptr[2]; 1062 const unsigned int a = data_ptr[3]; 1063 bool is_r_valid = (r == (data_y * 16 + x)) || (r == (data_y * 16 + x + 1)); 1064 bool is_g_valid = (g == 0); 1065 bool is_b_valid = (b == 0); 1066 bool is_a_valid = (a == 1); 1067 1068 if (!is_r_valid || !is_g_valid || !is_b_valid || !is_a_valid) 1069 { 1070 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texture data at (" << x << ", " << y << "):" 1071 << " Expected (" << (data_y * 16 + x) << ", 0, 0, 1)" 1072 << " or (" << (data_y * 16 + x + 1) << ", 0, 0, 1)" 1073 << ", found (" << r << ", " << g << ", " << b << ", " << a << ")." 1074 << tcu::TestLog::EndMessage; 1075 1076 has_test_fail++; 1077 } 1078 } /* for (all x values) */ 1079 } /* for (all y values) */ 1080 1081 if (has_test_fail) 1082 { 1083 TCU_FAIL("Invalid texture data"); 1084 } 1085 1086 /* All done */ 1087 if (buffer != NULL) 1088 { 1089 delete[] buffer; 1090 buffer = NULL; 1091 } 1092 1093 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1094 1095 return STOP; 1096} 1097 1098/** Constructor. 1099 * 1100 * @param context CTS context handle. 1101 **/ 1102MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest:: 1103 MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest(Context& context) 1104 : TestCase(context, "blitting_to_multisampled_fbo_is_forbidden", 1105 "Verifies that blitting to a multisampled framebuffer " 1106 "object results in a GL_INVALID_OPERATION error.") 1107 , dst_to_id(0) 1108 , fbo_draw_id(0) 1109 , fbo_read_id(0) 1110 , src_to_id(0) 1111{ 1112 /* Left blank on purpose */ 1113} 1114 1115/** Deinitializes ES objects created during test execution */ 1116void MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest::deinit() 1117{ 1118 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1119 1120 if (fbo_draw_id != 0) 1121 { 1122 gl.deleteFramebuffers(1, &fbo_draw_id); 1123 1124 fbo_draw_id = 0; 1125 } 1126 1127 if (fbo_read_id != 0) 1128 { 1129 gl.deleteFramebuffers(1, &fbo_read_id); 1130 1131 fbo_read_id = 0; 1132 } 1133 1134 if (dst_to_id != 0) 1135 { 1136 gl.deleteTextures(1, &dst_to_id); 1137 1138 dst_to_id = 0; 1139 } 1140 1141 if (src_to_id != 0) 1142 { 1143 gl.deleteTextures(1, &src_to_id); 1144 1145 src_to_id = 0; 1146 } 1147 1148 /* Call base class' deinit() */ 1149 TestCase::deinit(); 1150} 1151 1152/** Executes test iteration. 1153 * 1154 * @return Returns STOP when test has finished executing. 1155 */ 1156tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest::iterate() 1157{ 1158 const std::vector<std::string>& exts = m_context.getContextInfo().getExtensions(); 1159 const bool has_NV_framebuffer_blit = std::find(exts.begin(), exts.end(), "GL_NV_framebuffer_blit") != exts.end(); 1160 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1161 1162 /* Set up texture objects */ 1163 gl.genTextures(1, &dst_to_id); 1164 gl.genTextures(1, &src_to_id); 1165 1166 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, dst_to_id); 1167 gl.bindTexture(GL_TEXTURE_2D, src_to_id); 1168 1169 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects"); 1170 1171 gl.texStorage2D(GL_TEXTURE_2D, 2, /* levels */ 1172 GL_RGB10_A2, 64, /* width */ 1173 64); /* height */ 1174 1175 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed for GL_TEXTURE_2D texture target"); 1176 1177 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ 1178 GL_RGB10_A2, 64, /* width */ 1179 64, /* height */ 1180 GL_FALSE); /* fixedsamplelocations */ 1181 1182 GLU_EXPECT_NO_ERROR(gl.getError(), 1183 "gl.texStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target"); 1184 1185 /* Set up framebuffer objects */ 1186 gl.genFramebuffers(1, &fbo_draw_id); 1187 gl.genFramebuffers(1, &fbo_read_id); 1188 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_draw_id); 1189 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read_id); 1190 1191 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects"); 1192 1193 /* Set up FBO attachments. 1194 * 1195 * NOTE: The draw/read FBO configuration in original test spec was the other 1196 * way around which was wrong. 1197 */ 1198 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_to_id, 0); /* level */ 1199 1200 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer's attachments"); 1201 1202 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, 1203 dst_to_id, /* texture */ 1204 0); /* layer */ 1205 1206 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer's attachments"); 1207 1208 /* Try to perform blitting operations. */ 1209 const glw::GLenum filters[] = { GL_NEAREST, GL_LINEAR }; 1210 const unsigned int n_filters = sizeof(filters) / sizeof(filters[0]); 1211 1212 for (unsigned int n_filter = 0; n_filter < n_filters; ++n_filter) 1213 { 1214 glw::GLenum filter = filters[n_filter]; 1215 1216 // This blit would be supported by NV_framebuffer_blit if sizes match. 1217 // Alter the size of destination if extension is present to make it invalid. 1218 int dstY1 = has_NV_framebuffer_blit ? 63 : 64; 1219 gl.blitFramebuffer(0, /* srcX0 */ 1220 0, /* srcY0 */ 1221 64, /* srcX1 */ 1222 64, /* srcY1 */ 1223 0, /* dstX0 */ 1224 0, /* dstY0 */ 1225 64, /* dstX1 */ 1226 dstY1, /* dstY1 */ 1227 GL_COLOR_BUFFER_BIT, filter); 1228 1229 /* Verify GL_INVALID_OPERATION was returned */ 1230 glw::GLenum error_code = gl.getError(); 1231 1232 if (error_code != GL_INVALID_OPERATION) 1233 { 1234 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid glBlitFramebuffer() call for filter argument [" 1235 << filter << "]" 1236 "should have generated a GL_INVALID_OPERATION error. Instead, " 1237 "[" 1238 << error_code << "] error was reported." << tcu::TestLog::EndMessage; 1239 1240 TCU_FAIL("GL_INVALID_OPERATION was not returned by invalid glBlitFramebuffer() call."); 1241 } 1242 } /* for (all valid filter argument values) */ 1243 1244 /* All done */ 1245 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1246 1247 return STOP; 1248} 1249 1250/** Constructor. 1251 * 1252 * @param context Rendering context handle. 1253 **/ 1254MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest:: 1255 MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest(Context& context) 1256 : TestCase(context, "verify_sample_masking_for_non_integer_color_renderable_internalformats", 1257 "Verifies sample masking mechanism for non-integer color-renderable " 1258 "internalformats used for 2D multisample textures") 1259 , bo_id(0) 1260 , fbo_id(0) 1261 , fs_draw_id(0) 1262 , po_draw_id(0) 1263 , po_verify_id(0) 1264 , tfo_id(0) 1265 , to_2d_multisample_id(0) 1266 , vs_draw_id(0) 1267 , vs_verify_id(0) 1268{ 1269 /* Left blank on purpose */ 1270} 1271 1272/** Deinitializes ES objects created during test execution */ 1273void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::deinit() 1274{ 1275 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1276 1277 /* Unset used program */ 1278 gl.useProgram(0); 1279 1280 /* Unbind transform feedback object bound to GL_TRANSFORM_FEEDBACK target */ 1281 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 1282 1283 /* Unbind buffer object bound to GL_TRANSFORM_FEEDBACK_BUFFER target */ 1284 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 1285 1286 /* Unbind framebuffer object bound to GL_DRAW_FRAMEBUFFER target */ 1287 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 1288 1289 /* Unbind texture object bound to GL_TEXTURE_2D_MULTISAMPLE texture target */ 1290 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 1291 1292 /* Delete a 2D multisample texture object of id to_2d_multisample_id */ 1293 if (to_2d_multisample_id != 0) 1294 { 1295 gl.deleteTextures(1, &to_2d_multisample_id); 1296 1297 to_2d_multisample_id = 0; 1298 } 1299 1300 /* Delete a buffer object of id bo_id */ 1301 if (bo_id != 0) 1302 { 1303 gl.deleteBuffers(1, &bo_id); 1304 1305 bo_id = 0; 1306 } 1307 1308 /* Delete a framebuffer object of id fbo_id */ 1309 if (fbo_id != 0) 1310 { 1311 gl.deleteFramebuffers(1, &fbo_id); 1312 1313 fbo_id = 0; 1314 } 1315 1316 /* Delete a transform feedback object of id tfo_id */ 1317 if (tfo_id != 0) 1318 { 1319 gl.deleteTransformFeedbacks(1, &tfo_id); 1320 1321 tfo_id = 0; 1322 } 1323 1324 /* Delete fs_draw_id shader */ 1325 if (fs_draw_id != 0) 1326 { 1327 gl.deleteShader(fs_draw_id); 1328 1329 fs_draw_id = 0; 1330 } 1331 1332 /* Delete vs_verify_id shader */ 1333 if (vs_verify_id != 0) 1334 { 1335 gl.deleteShader(vs_verify_id); 1336 1337 vs_verify_id = 0; 1338 } 1339 1340 /* Delete vs_draw_id shader */ 1341 if (vs_draw_id != 0) 1342 { 1343 gl.deleteShader(vs_draw_id); 1344 1345 vs_draw_id = 0; 1346 } 1347 1348 /* Delete program objects po_verify_id */ 1349 if (po_verify_id != 0) 1350 { 1351 gl.deleteProgram(po_verify_id); 1352 1353 po_verify_id = 0; 1354 } 1355 1356 /* Delete program objects po_draw_id */ 1357 if (po_draw_id != 0) 1358 { 1359 gl.deleteProgram(po_draw_id); 1360 1361 po_draw_id = 0; 1362 } 1363 1364 /* Call base class' deinit() */ 1365 TestCase::deinit(); 1366} 1367 1368/** Initializes test-specific ES objects */ 1369void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::initInternals() 1370{ 1371 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1372 1373 /* Generate a 2D multisample texture object of id to_2d_multisample_id */ 1374 gl.genTextures(1, &to_2d_multisample_id); 1375 1376 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed"); 1377 1378 if (to_2d_multisample_id == 0) 1379 { 1380 TCU_FAIL("Texture object has not been generated properly"); 1381 } 1382 1383 /* Generate a buffer object of id bo_id */ 1384 gl.genBuffers(1, &bo_id); 1385 1386 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed"); 1387 1388 if (bo_id == 0) 1389 { 1390 TCU_FAIL("Buffer object has not been generated properly"); 1391 } 1392 1393 /* Generate a framebuffer object of id fbo_id */ 1394 gl.genFramebuffers(1, &fbo_id); 1395 1396 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed"); 1397 1398 if (fbo_id == 0) 1399 { 1400 TCU_FAIL("Framebuffer object has not been generated properly"); 1401 } 1402 1403 /* Generate a transform feedback object of id tfo_id */ 1404 gl.genTransformFeedbacks(1, &tfo_id); 1405 1406 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() call failed"); 1407 1408 if (tfo_id == 0) 1409 { 1410 TCU_FAIL("Transform feedback object has not been generated properly"); 1411 } 1412 1413 /* Create a vertex shader vs_draw_id */ 1414 vs_draw_id = gl.createShader(GL_VERTEX_SHADER); 1415 1416 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_draw_id"); 1417 1418 /* Create a vertex shader vs_verify_id */ 1419 vs_verify_id = gl.createShader(GL_VERTEX_SHADER); 1420 1421 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_verify_id"); 1422 1423 /* Create a fragment shader fs_draw_id */ 1424 fs_draw_id = gl.createShader(GL_FRAGMENT_SHADER); 1425 1426 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for fs_draw_id"); 1427 1428 /* Create program objects po_draw_id */ 1429 po_draw_id = gl.createProgram(); 1430 1431 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_draw_id"); 1432 1433 /* Create program objects po_verify_id */ 1434 po_verify_id = gl.createProgram(); 1435 1436 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_verify_id"); 1437} 1438 1439/** Executes test iteration. 1440 * 1441 * @return Always STOP. 1442 */ 1443tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest:: 1444 iterate() 1445{ 1446 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1447 1448 initInternals(); 1449 1450 /* Constants */ 1451 const glw::GLfloat epsilon = 1e-5f; 1452 const glw::GLfloat expected_value = 1.0f; 1453 const glw::GLchar* fs_draw_body = "#version 310 es\n" 1454 "\n" 1455 "precision highp float;\n" 1456 "\n" 1457 "out vec4 out_color;\n" 1458 "\n" 1459 "void main()\n" 1460 "{\n" 1461 " out_color = vec4(1, 1, 1, 1);\n" 1462 "}\n"; 1463 1464 const glw::GLchar* vs_draw_body = "#version 310 es\n" 1465 "\n" 1466 "precision highp float;\n" 1467 "\n" 1468 "void main()\n" 1469 "{\n" 1470 " switch (gl_VertexID)\n" 1471 " {\n" 1472 " case 0: gl_Position = vec4(-1, 1, 0, 1); break;\n" 1473 " case 1: gl_Position = vec4( 1, 1, 0, 1); break;\n" 1474 " case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n" 1475 " case 3: gl_Position = vec4(-1, -1, 0, 1); break;\n" 1476 " }\n" 1477 "}\n"; 1478 1479 const glw::GLchar* vs_verify_body = "#version 310 es\n" 1480 "\n" 1481 "precision highp float;\n" 1482 "\n" 1483 "uniform uint n_bit_on;\n" 1484 "uniform uint n_bits;\n" 1485 "uniform highp sampler2DMS sampler;\n" 1486 "\n" 1487 "out float result;\n" 1488 "\n" 1489 "void main()\n" 1490 "{\n" 1491 " vec4 one = vec4(1);\n" 1492 " vec4 zero = vec4(0.0, 0.0, 0.0, 1.0);\n" 1493 "\n" 1494 " result = 1.0;\n" 1495 "\n" 1496 " for (uint n_current_bit = 0u; n_current_bit < n_bits; n_current_bit++)\n" 1497 " {\n" 1498 " vec4 value = texelFetch(sampler, ivec2(0), int(n_current_bit));\n" 1499 "\n" 1500 " if (n_bit_on == n_current_bit)\n" 1501 " {\n" 1502 " if (any(notEqual(value, one)))\n" 1503 " {\n" 1504 " result = 0.1 + float(n_current_bit)/1000.0;\n" 1505 " break;\n" 1506 " }\n" 1507 " }\n" 1508 " else\n" 1509 " {\n" 1510 " if (any(notEqual(value, zero)))\n" 1511 " {\n" 1512 " result = 0.2 + float(n_current_bit)/1000.0;\n" 1513 " break;\n" 1514 " }\n" 1515 " }\n" 1516 " }\n" 1517 "}\n"; 1518 1519 /* Configure the vertex shader vs_draw_id */ 1520 compileShader(vs_draw_id, vs_draw_body); 1521 1522 /* Configure the vertex shader vs_verify_id */ 1523 compileShader(vs_verify_id, vs_verify_body); 1524 1525 /* Configure the fragment shader fs_draw_id */ 1526 compileShader(fs_draw_id, fs_draw_body); 1527 1528 /* Attach the shaders vs_draw_id and fs_draw_id to program object po_draw_id */ 1529 gl.attachShader(po_draw_id, vs_draw_id); 1530 gl.attachShader(po_draw_id, fs_draw_id); 1531 1532 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_draw_id program object"); 1533 1534 /* Attach the shaders vs_verify_id and fs_draw_id to program object po_verify_id */ 1535 gl.attachShader(po_verify_id, vs_verify_id); 1536 gl.attachShader(po_verify_id, fs_draw_id); 1537 1538 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_verify_id program object"); 1539 1540 /* Configure vs_verify_id for transform feedback - our varying of choice is result and we're happy to use either of the TF modes since we'll be outputting a single float anyway. */ 1541 const glw::GLchar* vs_verify_varying_name = "result"; 1542 1543 gl.transformFeedbackVaryings(po_verify_id, 1, &vs_verify_varying_name, GL_SEPARATE_ATTRIBS); 1544 1545 /* Link the program objects po_draw_id */ 1546 linkProgram(po_draw_id); 1547 1548 /* Link the program objects po_verify_id */ 1549 linkProgram(po_verify_id); 1550 1551 /* Retrieve uniform locations */ 1552 glw::GLuint n_bits_location = gl.getUniformLocation(po_verify_id, "n_bits"); 1553 glw::GLuint n_bit_on_location = gl.getUniformLocation(po_verify_id, "n_bit_on"); 1554 1555 /* Bind the to_2d_multisample_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */ 1556 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id); 1557 1558 /* Bind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */ 1559 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); 1560 1561 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); 1562 1563 /* Bind the bo_id buffer object to GL_TRANSFORM_FEEDBACK_BUFFER generic target */ 1564 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id); 1565 1566 /* Bind the tfo_id transform feedback object go GL_TRANSFORM_FEEDBACK target */ 1567 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id); 1568 1569 /* Bind the bo_id buffer object to zeroth binding point of GL_TRANSFORM_FEEDBACK_BUFFER */ 1570 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id); 1571 1572 /* Initialize buffer object's storage to hold a total of 4 bytes (sizeof(float) );*/ 1573 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW); 1574 1575 /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */ 1576 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id, 1577 0); /* level */ 1578 1579 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment"); 1580 1581 /* Enable GL_SAMPLE_MASK mode */ 1582 gl.enable(GL_SAMPLE_MASK); 1583 1584 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error"); 1585 1586 /* Color-renderable internalformats to test, note that GL_R8 will not work since sampling from 1587 * such format will never return {1,1,1,1} or {0,0,0,1} which current shader uses for sample validation */ 1588 const glw::GLenum internalformat_list[] = { GL_RGBA8, GL_RGB565, GL_SRGB8_ALPHA8 }; 1589 const int internalformat_list_count = sizeof(internalformat_list) / sizeof(internalformat_list[0]); 1590 1591 /* Get GL_MAX_SAMPLES value */ 1592 glw::GLint gl_max_samples_value = 0; 1593 1594 gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value); 1595 1596 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to retrieve GL_MAX_SAMPLES value"); 1597 1598 if (gl_max_samples_value > 32) 1599 { 1600 m_testCtx.getLog() << tcu::TestLog::Message << "The test case checks only first 32 samples out of " 1601 << gl_max_samples_value << " reported by GL_MAX_SAMPLES." << tcu::TestLog::EndMessage; 1602 } 1603 1604 /* Work with no more than 32 bits of mask's first word */ 1605 const glw::GLint mask_bits_to_check = de::min(gl_max_samples_value, 32); 1606 1607 /* Keep the results but continue running all cases */ 1608 bool test_fail = false; 1609 1610 /* Iterate through all internal formats test case should check */ 1611 for (int internalformat_index = 0; internalformat_index < internalformat_list_count; internalformat_index++) 1612 { 1613 /* Configure the texture object storage */ 1614 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, mask_bits_to_check, /* samples */ 1615 internalformat_list[internalformat_index], 1, /* width */ 1616 1, /* height */ 1617 GL_TRUE); /* fixedsamplelocations */ 1618 1619 /* Make sure no errors were reported. The framebuffer should be considered complete at this moment. */ 1620 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed"); 1621 1622 /* Following code does not affect test method. Just checks if FBO is complete 1623 To catch errors earlier */ 1624 1625 glw::GLenum fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); 1626 1627 if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE) 1628 { 1629 m_testCtx.getLog() << tcu::TestLog::Message 1630 << "Draw FBO completeness status is: " << fbo_completeness_status 1631 << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage; 1632 1633 TCU_FAIL("Draw FBO is considered incomplete which is invalid"); 1634 } 1635 1636 /* For all values of n_bit from range <0, GL_MAX_SAMPLES pname value) */ 1637 for (int n_bit = 0; n_bit < mask_bits_to_check; n_bit++) 1638 { 1639 1640 /* We need to clear render buffer, otherwise masked samples will have undefined values */ 1641 glw::GLfloat clear_color_src[] = { 0.0f, 0.0f, 0.0f, 1.0f }; 1642 1643 gl.clearBufferfv(GL_COLOR, 0, clear_color_src); 1644 GLU_EXPECT_NO_ERROR(gl.getError(), "clearBufferfv() call failed"); 1645 1646 /* Use program object po_draw_id */ 1647 gl.useProgram(po_draw_id); 1648 1649 /* Configure sample mask to only render n_bit-th sample using glSampleMaski() function */ 1650 gl.sampleMaski(0, 1 << n_bit); 1651 1652 /* Draw a triangle fan of 4 vertices. This fills to_2d_id with multisampled data. 1653 * However, due to active GL_SAMPLE_MASK and the way we configured it, only one sample should have been rendered. 1654 * The only way we can check if this is the case is by using a special shader, 1655 * because we have no way of downloading multisampled data to process space in ES3.0+. 1656 */ 1657 gl.drawArrays(GL_TRIANGLE_FAN, 0, /* first */ 1658 4 /* count */); 1659 1660 /* Unbind fbo_id before sourcing from the texture attached to it */ 1661 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 1662 1663 /* Enable GL_RASTERIZER_DISCARD mode */ 1664 gl.enable(GL_RASTERIZER_DISCARD); 1665 { 1666 /* Use program object po_verify_id */ 1667 gl.useProgram(po_verify_id); 1668 1669 /* Specify input arguments for vertex shader */ 1670 gl.uniform1ui(n_bits_location, mask_bits_to_check); 1671 gl.uniform1ui(n_bit_on_location, n_bit); 1672 1673 /* Bind to_2d_multisample_id to GL_TEXTURE_2D_MULTISAMPLE texture target. Current texture unit is GL_TEXTURE0 */ 1674 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id); 1675 1676 /* Begin transform feedback (primitiveMode: GL_POINTS) */ 1677 gl.beginTransformFeedback(GL_POINTS); 1678 { 1679 /* Draw a single point. This will fill our transform feedback buffer with result */ 1680 gl.drawArrays(GL_POINTS, 0, 1); 1681 } 1682 /* End transform feedback */ 1683 gl.endTransformFeedback(); 1684 } 1685 /* Disable GL_RASTERIZER_DISCARD mode */ 1686 gl.disable(GL_RASTERIZER_DISCARD); 1687 1688 /* Make sure no errors were generated */ 1689 GLU_EXPECT_NO_ERROR(gl.getError(), "Transform feedback failed"); 1690 1691 /* Rebind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */ 1692 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); 1693 1694 /* Map buffer object bo_id's contents to user-space */ 1695 const glw::GLfloat* mapped_bo = 1696 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 4, GL_MAP_READ_BIT); 1697 1698 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed"); 1699 1700 /* Copy result from buffer */ 1701 glw::GLfloat result = *mapped_bo; 1702 1703 /* Unmap the buffer object */ 1704 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 1705 1706 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed"); 1707 1708 /* Verify the value stored by verification program is not 0. If it is 0, the test has failed. */ 1709 if (de::abs(result - expected_value) > epsilon) 1710 { 1711 m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected value stored by verification program: [" 1712 << result << "]," 1713 << "Format index: " << internalformat_index << ", " 1714 << "Bit to check: [" << n_bit << "." << tcu::TestLog::EndMessage; 1715 /* Notice test failure */ 1716 test_fail = true; 1717 } 1718 } 1719 1720 /* Delete the 2D multisample texture object with glDeleteTextures() call and re-bind the object to a GL_TEXTURE_2D_MULTISAMPLE texture target with a glBindTexture() call */ 1721 gl.deleteTextures(1, &to_2d_multisample_id); 1722 1723 to_2d_multisample_id = 0; 1724 1725 /* Recreate to_2d_multisample_id texture object. */ 1726 /* Generate a 2D multisample texture object of id to_2d_multisample_id */ 1727 gl.genTextures(1, &to_2d_multisample_id); 1728 1729 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed"); 1730 1731 if (to_2d_multisample_id == 0) 1732 { 1733 TCU_FAIL("Texture object has not been generated properly"); 1734 } 1735 1736 /* Bind the to_2d_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */ 1737 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id); 1738 1739 /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */ 1740 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, 1741 to_2d_multisample_id, 0); /* level */ 1742 1743 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment"); 1744 } 1745 1746 if (test_fail) 1747 { 1748 TCU_FAIL("Value stored by verification program is not 1.0. Test has failed."); 1749 } 1750 1751 /* Test case passed */ 1752 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1753 1754 return STOP; 1755} 1756 1757/** Links a program object. Shaders should be attached to program id before call. 1758 * If an error reported throws an exception. 1759 * 1760 * @param id Program id 1761 */ 1762void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::linkProgram(glw::GLuint id) 1763{ 1764 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1765 1766 /* Link the test program object */ 1767 glw::GLint link_status = GL_FALSE; 1768 1769 gl.linkProgram(id); 1770 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed"); 1771 1772 gl.getProgramiv(id, GL_LINK_STATUS, &link_status); 1773 1774 if (link_status != GL_TRUE) 1775 { 1776 TCU_FAIL("Program linking failed"); 1777 } 1778} 1779 1780/** Compiles the shader. Should the shader not compile, a TestError exception will be thrown. 1781 * 1782 * @param id Generated shader id 1783 * @param source NULL-terminated shader source code string 1784 */ 1785void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::compileShader( 1786 glw::GLuint id, const glw::GLchar* source) 1787{ 1788 glw::GLint compile_status = GL_FALSE; 1789 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1790 1791 gl.shaderSource(id, 1, &source, NULL); 1792 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 1793 1794 gl.compileShader(id); 1795 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 1796 1797 gl.getShaderiv(id, GL_COMPILE_STATUS, &compile_status); 1798 1799 if (compile_status != GL_TRUE) 1800 { 1801 /* Retrieve adn dump compliation fail reason */ 1802 char infoLog[1024]; 1803 glw::GLsizei length = 0; 1804 1805 gl.getShaderInfoLog(id, 1024, &length, infoLog); 1806 1807 m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed, shader id=" << id 1808 << ", infoLog: " << infoLog << tcu::TestLog::EndMessage; 1809 1810 TCU_FAIL("Shader compilation failed"); 1811 } 1812} 1813 1814/** Constructor. 1815 * 1816 * @param context Rendering context handle. 1817 **/ 1818MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::MultisampleTextureFunctionalTestsSampleMaskingTexturesTest( 1819 Context& context) 1820 : TestCase(context, "verify_sample_masking_textures", 1821 "Verifies sample masking mechanism for non-integer, integer/unsigned, " 1822 "integer/signed color-renderable internalformats and " 1823 "depth-renderable internalformats. All internalformats " 1824 "are used for 2D multisample textures.") 1825 , bo_id(0) 1826 , fbo_id(0) 1827 , fs_draw_id(0) 1828 , po_draw_id(0) 1829 , po_verify_id(0) 1830 , tfo_id(0) 1831 , to_2d_multisample_id(0) 1832 , vs_draw_id(0) 1833 , vs_verify_id(0) 1834{ 1835 /* Left blank on purpose */ 1836} 1837 1838/** Deinitializes ES objects created during test execution */ 1839void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::deinit() 1840{ 1841 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1842 1843 /* Unset used program */ 1844 gl.useProgram(0); 1845 1846 /* Unbind transform feedback object bound to GL_TRANSFORM_FEEDBACK target */ 1847 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 1848 1849 /* Unbind buffer object bound to GL_TRANSFORM_FEEDBACK_BUFFER target */ 1850 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); 1851 1852 /* Unbind framebuffer object bound to GL_DRAW_FRAMEBUFFER target */ 1853 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 1854 1855 /* Unbind texture object bound to GL_TEXTURE_2D_MULTISAMPLE texture target */ 1856 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 1857 1858 /* Delete a 2D multisample texture object of id to_2d_multisample_id */ 1859 if (to_2d_multisample_id != 0) 1860 { 1861 gl.deleteTextures(1, &to_2d_multisample_id); 1862 1863 to_2d_multisample_id = 0; 1864 } 1865 1866 /* Delete a buffer object of id bo_id */ 1867 if (bo_id != 0) 1868 { 1869 gl.deleteBuffers(1, &bo_id); 1870 1871 bo_id = 0; 1872 } 1873 1874 /* Delete a framebuffer object of id fbo_id */ 1875 if (fbo_id != 0) 1876 { 1877 gl.deleteFramebuffers(1, &fbo_id); 1878 1879 fbo_id = 0; 1880 } 1881 1882 /* Delete a transform feedback object of id tfo_id */ 1883 if (tfo_id != 0) 1884 { 1885 gl.deleteTransformFeedbacks(1, &tfo_id); 1886 1887 tfo_id = 0; 1888 } 1889 1890 /* Delete fs_draw_id shader */ 1891 if (fs_draw_id != 0) 1892 { 1893 gl.deleteShader(fs_draw_id); 1894 1895 fs_draw_id = 0; 1896 } 1897 1898 /* Delete vs_verify_id shader */ 1899 if (vs_verify_id != 0) 1900 { 1901 gl.deleteShader(vs_verify_id); 1902 1903 vs_verify_id = 0; 1904 } 1905 1906 /* Delete vs_draw_id shader */ 1907 if (vs_draw_id != 0) 1908 { 1909 gl.deleteShader(vs_draw_id); 1910 1911 vs_draw_id = 0; 1912 } 1913 1914 /* Delete program objects po_verify_id */ 1915 if (po_verify_id != 0) 1916 { 1917 gl.deleteProgram(po_verify_id); 1918 1919 po_verify_id = 0; 1920 } 1921 1922 /* Delete program objects po_draw_id */ 1923 if (po_draw_id != 0) 1924 { 1925 gl.deleteProgram(po_draw_id); 1926 1927 po_draw_id = 0; 1928 } 1929 1930 /* Call base class' deinit() */ 1931 TestCase::deinit(); 1932} 1933 1934/** Initializes test-specific ES objects */ 1935void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::initInternals() 1936{ 1937 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1938 1939 /* Generate a 2D multisample texture object of id to_2d_multisample_id */ 1940 gl.genTextures(1, &to_2d_multisample_id); 1941 1942 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed"); 1943 1944 if (to_2d_multisample_id == 0) 1945 { 1946 TCU_FAIL("Texture object has not been generated properly"); 1947 } 1948 1949 /* Generate a buffer object of id bo_id */ 1950 gl.genBuffers(1, &bo_id); 1951 1952 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed"); 1953 1954 if (bo_id == 0) 1955 { 1956 TCU_FAIL("Buffer object has not been generated properly"); 1957 } 1958 1959 /* Generate a framebuffer object of id fbo_id */ 1960 gl.genFramebuffers(1, &fbo_id); 1961 1962 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed"); 1963 1964 if (fbo_id == 0) 1965 { 1966 TCU_FAIL("Framebuffer object has not been generated properly"); 1967 } 1968 1969 /* Generate a transform feedback object of id tfo_id */ 1970 gl.genTransformFeedbacks(1, &tfo_id); 1971 1972 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() call failed"); 1973 1974 if (tfo_id == 0) 1975 { 1976 TCU_FAIL("Transform feedback object has not been generated properly"); 1977 } 1978 1979 /* Create a vertex shader vs_draw_id */ 1980 vs_draw_id = gl.createShader(GL_VERTEX_SHADER); 1981 1982 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_draw_id"); 1983 1984 /* Create a vertex shader vs_verify_id */ 1985 vs_verify_id = gl.createShader(GL_VERTEX_SHADER); 1986 1987 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_verify_id"); 1988 1989 /* Create a fragment shader fs_draw_id */ 1990 fs_draw_id = gl.createShader(GL_FRAGMENT_SHADER); 1991 1992 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for fs_draw_id"); 1993 1994 /* Create program objects po_draw_id */ 1995 po_draw_id = gl.createProgram(); 1996 1997 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_draw_id"); 1998 1999 /* Create program objects po_verify_id */ 2000 po_verify_id = gl.createProgram(); 2001 2002 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_verify_id"); 2003} 2004 2005/** Executes test iteration. 2006 * 2007 * @return Always STOP. 2008 */ 2009tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::iterate() 2010{ 2011 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2012 2013 initInternals(); 2014 2015 /* Constants */ 2016 const glw::GLfloat epsilon = 1e-5f; 2017 const glw::GLchar* fs_draw_body = "#version 310 es\n" 2018 "\n" 2019 "out vec4 out_color;\n" 2020 "\n" 2021 "void main()\n" 2022 "{\n" 2023 " out_color = vec4(1, 1, 1, 1);\n" 2024 "}\n"; 2025 2026 const glw::GLchar* vs_draw_body = "#version 310 es\n" 2027 "\n" 2028 "void main()\n" 2029 "{\n" 2030 " switch (gl_VertexID)\n" 2031 " {\n" 2032 " case 0: gl_Position = vec4(-1, 1, 0, 1); break;\n" 2033 " case 1: gl_Position = vec4( 1, 1, 0, 1); break;\n" 2034 " case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n" 2035 " case 3: gl_Position = vec4(-1, -1, 0, 1); break;\n" 2036 " }\n" 2037 "}\n"; 2038 2039 const glw::GLchar* vs_verify_body = "#version 310 es\n" 2040 "\n" 2041 "precision highp float;\n" 2042 "\n" 2043 "uniform uint n_bit_on;\n" 2044 "uniform uint n_bits;\n" 2045 "uniform highp sampler2DMS sampler;\n" 2046 "\n" 2047 "out float result;\n" 2048 "\n" 2049 "void main()\n" 2050 "{\n" 2051 " vec4 one = vec4(1);\n" 2052 " vec4 zero = vec4(0);\n" 2053 "\n" 2054 " result = 1.0;\n" 2055 "\n" 2056 " for (uint n_current_bit = 0u; n_current_bit < n_bits; n_current_bit++)\n" 2057 " {\n" 2058 " vec4 value = texelFetch(sampler, ivec2(0), int(n_current_bit));\n" 2059 "\n" 2060 " if (n_bit_on == n_current_bit)\n" 2061 " {\n" 2062 " if (any(notEqual(value, one)))\n" 2063 " {\n" 2064 " result = 0.0;\n" 2065 " }\n" 2066 " }\n" 2067 " else\n" 2068 " {\n" 2069 " if (any(notEqual(value, zero)))\n" 2070 " {\n" 2071 " result = 0.0;\n" 2072 " }\n" 2073 " }\n" 2074 " }\n" 2075 "}\n"; 2076 2077 /* Configure the vertex shader vs_draw_id */ 2078 compileShader(vs_draw_id, vs_draw_body); 2079 2080 /* Configure the vertex shader vs_verify_id */ 2081 compileShader(vs_verify_id, vs_verify_body); 2082 2083 /* Configure the fragment shader fs_draw_id */ 2084 compileShader(fs_draw_id, fs_draw_body); 2085 2086 /* Attach the shaders vs_draw_id and fs_draw_id to program object po_draw_id */ 2087 gl.attachShader(po_draw_id, vs_draw_id); 2088 gl.attachShader(po_draw_id, fs_draw_id); 2089 2090 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_draw_id program object"); 2091 2092 /* Attach the shaders vs_verify_id and fs_draw_id to program object po_verify_id */ 2093 gl.attachShader(po_verify_id, vs_verify_id); 2094 gl.attachShader(po_verify_id, fs_draw_id); 2095 2096 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_verify_id program object"); 2097 2098 /* Configure vs_verify_id for transform feedback - our varying of choice is result and we're happy to use either of the TF modes since we'll be outputting a single float anyway. */ 2099 const glw::GLchar* vs_verify_varying_name = "result"; 2100 2101 gl.transformFeedbackVaryings(po_verify_id, 1, &vs_verify_varying_name, GL_SEPARATE_ATTRIBS); 2102 2103 /* Link the program objects po_draw_id */ 2104 linkProgram(po_draw_id); 2105 2106 /* Link the program objects po_verify_id */ 2107 linkProgram(po_verify_id); 2108 2109 /* Retrieve uniform locations */ 2110 glw::GLuint n_bits_location = gl.getUniformLocation(po_verify_id, "n_bits"); 2111 glw::GLuint n_bit_on_location = gl.getUniformLocation(po_verify_id, "n_bit_on"); 2112 2113 /* Bind the to_2d_multisample_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */ 2114 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id); 2115 2116 /* Bind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */ 2117 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); 2118 2119 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); 2120 2121 /* Bind the bo_id buffer object to GL_TRANSFORM_FEEDBACK_BUFFER generic target */ 2122 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id); 2123 2124 /* Bind the bo_id buffer object to zeroth binding point of GL_TRANSFORM_FEEDBACK_BUFFER */ 2125 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id); 2126 2127 /* Bind the tfo_id transform feedback object go GL_TRANSFORM_FEEDBACK target */ 2128 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id); 2129 2130 /* Initialize buffer object's storage to hold a total of 4 bytes (sizeof(float) );*/ 2131 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW); 2132 2133 /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */ 2134 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id, 2135 0); /* level */ 2136 2137 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment"); 2138 2139 /* Enable GL_SAMPLE_MASK mode */ 2140 gl.enable(GL_SAMPLE_MASK); 2141 2142 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error"); 2143 2144 /* Iterate through color-normalized-, color-unsigned-integer-, color-signed-integer- and depth-renderable internalformats */ 2145 const glw::GLenum normalized_color_internalformats[] = { GL_R8, GL_RGB565, GL_SRGB8_ALPHA8 }; 2146 const glw::GLenum unsigned_color_internalformats[] = { GL_RGBA32UI, GL_RG16UI }; 2147 const glw::GLenum signed_color_internalformats[] = { GL_RGBA32I, GL_RG16I }; 2148 const glw::GLenum depth_internalformats[] = { GL_DEPTH_COMPONENT32F }; 2149 const unsigned int n_normalized_color_internalformats = 2150 sizeof(normalized_color_internalformats) / sizeof(normalized_color_internalformats[0]); 2151 const unsigned int n_unsigned_color_internalformats = 2152 sizeof(unsigned_color_internalformats) / sizeof(unsigned_color_internalformats[0]); 2153 const unsigned int n_signed_color_internalformats = 2154 sizeof(signed_color_internalformats) / sizeof(signed_color_internalformats[0]); 2155 const unsigned int n_depth_internalformats = sizeof(depth_internalformats) / sizeof(depth_internalformats[0]); 2156 2157 for (unsigned int n_iteration = 0; n_iteration < 4 /* normalized/unsigned/signed/depth */; ++n_iteration) 2158 { 2159 glw::GLenum attachment = 0; 2160 const glw::GLenum* internalformats = NULL; 2161 unsigned int n_internalformats = 0; 2162 2163 switch (n_iteration) 2164 { 2165 case 0: 2166 { 2167 attachment = GL_COLOR_ATTACHMENT0; 2168 internalformats = normalized_color_internalformats; 2169 n_internalformats = n_normalized_color_internalformats; 2170 2171 break; 2172 } 2173 2174 case 1: 2175 { 2176 attachment = GL_COLOR_ATTACHMENT0; 2177 internalformats = unsigned_color_internalformats; 2178 n_internalformats = n_unsigned_color_internalformats; 2179 2180 break; 2181 } 2182 2183 case 2: 2184 { 2185 attachment = GL_COLOR_ATTACHMENT0; 2186 internalformats = signed_color_internalformats; 2187 n_internalformats = n_signed_color_internalformats; 2188 2189 break; 2190 } 2191 2192 case 3: 2193 { 2194 attachment = GL_DEPTH_ATTACHMENT; 2195 internalformats = depth_internalformats; 2196 n_internalformats = n_depth_internalformats; 2197 2198 break; 2199 } 2200 2201 default: 2202 { 2203 TCU_FAIL("Unrecognized iteration index"); 2204 } 2205 } /* switch (n_iteration) */ 2206 2207 /* Iterate through internalformats */ 2208 for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat) 2209 { 2210 glw::GLenum internalformat = internalformats[n_internalformat]; 2211 glw::GLint internalformat_max_samples = 0; 2212 2213 /* Retrieve internalformat-specific GL_MAX_SAMPLES value */ 2214 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, /* target */ 2215 internalformat, GL_SAMPLES, 1, /* bufSize */ 2216 &internalformat_max_samples); 2217 2218 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed"); 2219 2220 if (internalformat_max_samples > 32) 2221 { 2222 m_testCtx.getLog() << tcu::TestLog::Message << "The test case checks only first 32 samples out of " 2223 << internalformat_max_samples 2224 << " reported by GL_SAMPLES reported by getInternalformativ() " 2225 << "for internalformat " << internalformat << "." << tcu::TestLog::EndMessage; 2226 } 2227 2228 /* Work with no more than 32 bits of mask's first word */ 2229 const glw::GLint mask_bits_to_check = de::min(internalformat_max_samples, 32); 2230 2231 /* Recreate to_2d_multisample_id texture object. */ 2232 if (to_2d_multisample_id == 0) 2233 { 2234 /* Generate a 2D multisample texture object of id to_2d_multisample_id */ 2235 gl.genTextures(1, &to_2d_multisample_id); 2236 2237 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed"); 2238 2239 if (to_2d_multisample_id == 0) 2240 { 2241 TCU_FAIL("Texture object has not been generated properly"); 2242 } 2243 2244 /* Bind the to_2d_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */ 2245 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id); 2246 2247 /* Attach the 2D multisample texture object to the framebuffer object's attachment */ 2248 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D_MULTISAMPLE, 2249 to_2d_multisample_id, 0); /* level */ 2250 2251 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up attachment"); 2252 } 2253 2254 /* Configure the texture object storage */ 2255 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, internalformat_max_samples, /* samples */ 2256 internalformat, 1, /* width */ 2257 1, /* height */ 2258 GL_TRUE); /* fixedsamplelocations */ 2259 2260 /* Make sure no errors were reported. The framebuffer should be considered complete at this moment. */ 2261 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed"); 2262 2263 /* For all values of n_bit from range <0, GL_MAX_SAMPLES pname value) */ 2264 for (int n_bit = 0; n_bit < mask_bits_to_check; n_bit++) 2265 { 2266 /* Use program object po_draw_id */ 2267 gl.useProgram(po_draw_id); 2268 2269 /* Configure sample mask to only render n_bit-th sample using glSampleMaski() function */ 2270 gl.sampleMaski(0, 1 << n_bit); 2271 2272 /* Draw a triangle fan of 4 vertices. This fills to_2d_id with multisampled data. 2273 * However, due to active GL_SAMPLE_MASK and the way we configured it, only one sample should have been rendered. 2274 * The only way we can check if this is the case is by using a special shader, 2275 * because we have no way of downloading multisampled data to process space in ES3.0+. 2276 */ 2277 gl.drawArrays(GL_TRIANGLE_FAN, 0, /* first */ 2278 4 /* count */); 2279 2280 /* Enable GL_RASTERIZER_DISCARD mode */ 2281 gl.enable(GL_RASTERIZER_DISCARD); 2282 { 2283 /* Use program object po_verify_id */ 2284 gl.useProgram(po_verify_id); 2285 2286 /* Specify input arguments for vertex shader */ 2287 gl.uniform1i(n_bits_location, mask_bits_to_check); 2288 gl.uniform1i(n_bit_on_location, n_bit); 2289 2290 /* Bind to_2d_multisample_id to GL_TEXTURE_2D_MULTISAMPLE texture target. Current texture unit is GL_TEXTURE0 */ 2291 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id); 2292 2293 /* Begin transform feedback (primitiveMode: GL_POINTS) */ 2294 gl.beginTransformFeedback(GL_POINTS); 2295 { 2296 /* Draw a single point. This will fill our transform feedback buffer with result */ 2297 gl.drawArrays(GL_POINTS, 0, 1); 2298 } 2299 /* End transform feedback */ 2300 gl.endTransformFeedback(); 2301 } 2302 /* Disable GL_RASTERIZER_DISCARD mode */ 2303 gl.disable(GL_RASTERIZER_DISCARD); 2304 2305 /* Make sure no errors were generated */ 2306 GLU_EXPECT_NO_ERROR(gl.getError(), "Transform feedback failed"); 2307 2308 /* Map buffer object bo_id's contents to user-space */ 2309 const glw::GLfloat* mapped_bo = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 2310 2311 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed"); 2312 2313 /* Copy result from buffer */ 2314 glw::GLfloat result = *mapped_bo; 2315 2316 /* Unmap the buffer object */ 2317 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 2318 2319 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed"); 2320 2321 /* Verify the value stored by verification program is not 0. If it is 0, the test has failed. */ 2322 if (de::abs(result) < epsilon) 2323 { 2324 TCU_FAIL("Value stored by verification program is zero. Test has failed."); 2325 } 2326 } 2327 2328 /* Delete the 2D multisample texture object with glDeleteTextures() call and re-bind the object to a GL_TEXTURE_2D_MULTISAMPLE texture target with a glBindTexture() call */ 2329 gl.deleteTextures(1, &to_2d_multisample_id); 2330 2331 to_2d_multisample_id = 0; 2332 } /* for (all renderable internalformats) */ 2333 } /* for (all iterations) */ 2334 2335 /* Test case passed */ 2336 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2337 2338 return STOP; 2339} 2340 2341/** Links a program object. Shaders should be attached to program id before call. 2342 * If an error reported throws an exception. 2343 * 2344 * @param id Program id 2345 */ 2346void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::linkProgram(glw::GLuint id) 2347{ 2348 /* Link the test program object */ 2349 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2350 glw::GLint link_status = GL_FALSE; 2351 2352 gl.linkProgram(id); 2353 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed"); 2354 2355 gl.getProgramiv(id, GL_LINK_STATUS, &link_status); 2356 2357 if (link_status != GL_TRUE) 2358 { 2359 TCU_FAIL("Program linking failed"); 2360 } 2361} 2362 2363/** Compiles the shader. Should the shader not compile, a TestError exception will be thrown. 2364 * 2365 * @param id Generated shader id 2366 * @param source NULL-terminated shader source code string 2367 */ 2368void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::compileShader(glw::GLuint id, 2369 const glw::GLchar* source) 2370{ 2371 glw::GLint compile_status = GL_FALSE; 2372 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2373 2374 gl.shaderSource(id, 1, &source, NULL); 2375 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 2376 2377 gl.compileShader(id); 2378 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); 2379 2380 gl.getShaderiv(id, GL_COMPILE_STATUS, &compile_status); 2381 2382 if (compile_status != GL_TRUE) 2383 { 2384 TCU_FAIL("Shader compilation failed"); 2385 } 2386} 2387 2388/** Constructor. 2389 * 2390 * @param context CTS context handle. 2391 **/ 2392MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest:: 2393 MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest(Context& context) 2394 : TestCase(context, "texture_size_in_fragment_shaders", 2395 "Verifies textureSize() works for multisample textures when used in fragment shaders") 2396 , fbo_id(0) 2397 , fs_id(0) 2398 , po_id(0) 2399 , to_2d_multisample_id(0) 2400 , to_2d_multisample_array_id(0) 2401 , vs_id(0) 2402{ 2403 /* Left blank on purpose */ 2404} 2405 2406/** Deinitializes ES objects created during test execution */ 2407void MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::deinit() 2408{ 2409 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2410 2411 if (fbo_id != 0) 2412 { 2413 gl.deleteFramebuffers(1, &fbo_id); 2414 2415 fbo_id = 0; 2416 } 2417 2418 if (fs_id != 0) 2419 { 2420 gl.deleteShader(fs_id); 2421 2422 fs_id = 0; 2423 } 2424 2425 if (po_id != 0) 2426 { 2427 gl.deleteProgram(po_id); 2428 2429 po_id = 0; 2430 } 2431 2432 if (to_2d_multisample_id != 0) 2433 { 2434 gl.deleteTextures(1, &to_2d_multisample_id); 2435 2436 to_2d_multisample_id = 0; 2437 } 2438 2439 if (to_2d_multisample_array_id != 0) 2440 { 2441 gl.deleteTextures(1, &to_2d_multisample_array_id); 2442 2443 to_2d_multisample_array_id = 0; 2444 } 2445 2446 if (vs_id != 0) 2447 { 2448 gl.deleteShader(vs_id); 2449 2450 vs_id = 0; 2451 } 2452 2453 /* Call base class' deinit() */ 2454 TestCase::deinit(); 2455} 2456 2457/** Executes test iteration. 2458 * 2459 * @return Returns STOP when test has finished executing. 2460 */ 2461tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::iterate() 2462{ 2463 bool are_2d_array_ms_tos_supported = 2464 m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); 2465 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2466 2467 /* Set up texture objects */ 2468 if (are_2d_array_ms_tos_supported) 2469 { 2470 gl.genTextures(1, &to_2d_multisample_array_id); 2471 } 2472 2473 gl.genTextures(1, &to_2d_multisample_id); 2474 2475 if (are_2d_array_ms_tos_supported) 2476 { 2477 gl.activeTexture(GL_TEXTURE0); 2478 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_2d_multisample_array_id); 2479 gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */ 2480 GL_RGBA8, 16, /* width */ 2481 32, /* height */ 2482 8, /* depth */ 2483 GL_TRUE); /* fixedsamplelocations */ 2484 2485 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up 2D multisample array texture storage"); 2486 } 2487 2488 gl.activeTexture(GL_TEXTURE1); 2489 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id); 2490 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ 2491 GL_RGBA8, 16, /* width */ 2492 32, /* height */ 2493 GL_TRUE); 2494 2495 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up 2D multisample texture storage"); 2496 2497 /* Set up a fragment shader */ 2498 static const char* fs_body = 2499 "#version 310 es\n" 2500 "\n" 2501 "#ifdef GL_OES_texture_storage_multisample_2d_array\n" 2502 " #extension GL_OES_texture_storage_multisample_2d_array : enable\n" 2503 "#endif\n" 2504 "\n" 2505 "precision highp float;\n" 2506 "\n" 2507 "uniform highp sampler2DMS sampler_2d;\n" 2508 "\n" 2509 "#ifdef GL_OES_texture_storage_multisample_2d_array\n" 2510 " uniform highp sampler2DMSArray sampler_2d_array;\n" 2511 "#endif" 2512 "\n" 2513 "out vec4 result;\n" 2514 "\n" 2515 "void main()\n" 2516 "{\n" 2517 " #ifdef GL_OES_texture_storage_multisample_2d_array\n" 2518 " ivec3 sampler_2d_array_size = textureSize(sampler_2d_array);\n" 2519 " #else\n" 2520 " ivec3 sampler_2d_array_size = ivec3(16, 32, 8);\n" 2521 " #endif\n" 2522 "\n" 2523 " ivec2 sampler_2d_size = textureSize(sampler_2d);\n" 2524 "\n" 2525 " if (sampler_2d_size.x == 16 && sampler_2d_size.y == 32 &&\n" 2526 " sampler_2d_array_size.x == 16 && sampler_2d_array_size.y == 32 && sampler_2d_array_size.z == 8)\n" 2527 " {\n" 2528 " result = vec4(0, 1, 0, 0);\n" 2529 " }\n" 2530 " else\n" 2531 " {\n" 2532 " result = vec4(1, 0, 0, 0);\n" 2533 " }\n" 2534 "}\n"; 2535 glw::GLint compile_status = GL_FALSE; 2536 2537 fs_id = gl.createShader(GL_FRAGMENT_SHADER); 2538 2539 gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL); 2540 gl.compileShader(fs_id); 2541 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a fragment shader"); 2542 2543 gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status); 2544 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query fragment shader's compile status"); 2545 2546 if (compile_status == GL_FALSE) 2547 { 2548 TCU_FAIL("Could not compile fragment shader"); 2549 } 2550 2551 /* Set up a vertex shader for 2D multisample texture case */ 2552 static const char* vs_body = "#version 310 es\n" 2553 "\n" 2554 "precision highp float;\n" 2555 "\n" 2556 "void main()\n" 2557 "{\n" 2558 " switch (gl_VertexID)\n" 2559 " {\n" 2560 " case 0: gl_Position = vec4(-1, -1, 0, 1); break;\n" 2561 " case 1: gl_Position = vec4(-1, 1, 0, 1); break;\n" 2562 " case 2: gl_Position = vec4( 1, 1, 0, 1); break;\n" 2563 " case 3: gl_Position = vec4( 1, -1, 0, 1); break;\n" 2564 " }\n" 2565 "}\n"; 2566 2567 vs_id = gl.createShader(GL_VERTEX_SHADER); 2568 2569 gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL); 2570 gl.compileShader(vs_id); 2571 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader"); 2572 2573 gl.getShaderiv(vs_id, GL_COMPILE_STATUS, &compile_status); 2574 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query vertex shader's compile status"); 2575 2576 if (compile_status == GL_FALSE) 2577 { 2578 TCU_FAIL("Could not compile vertex shader"); 2579 } 2580 2581 /* Set up a program object */ 2582 po_id = gl.createProgram(); 2583 2584 gl.attachShader(po_id, fs_id); 2585 gl.attachShader(po_id, vs_id); 2586 2587 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a program object"); 2588 2589 /* Link the program object */ 2590 glw::GLint link_status = GL_FALSE; 2591 2592 gl.linkProgram(po_id); 2593 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 2594 2595 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 2596 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 2597 2598 if (link_status != GL_TRUE) 2599 { 2600 TCU_FAIL("Program object linking failed"); 2601 } 2602 2603 /* Set up uniforms */ 2604 glw::GLint sampler_2d_array_location = gl.getUniformLocation(po_id, "sampler_2d_array"); 2605 glw::GLint sampler_2d_location = gl.getUniformLocation(po_id, "sampler_2d"); 2606 2607 if ((sampler_2d_array_location == -1 && are_2d_array_ms_tos_supported) || sampler_2d_location == -1) 2608 { 2609 TCU_FAIL("At least one of the required uniforms is not considered active"); 2610 } 2611 2612 gl.useProgram(po_id); 2613 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2614 2615 gl.uniform1i(sampler_2d_array_location, 0); 2616 gl.uniform1i(sampler_2d_location, 1); 2617 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call(s) failed."); 2618 2619 /* Render a full-screen quad */ 2620 gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */); 2621 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed"); 2622 2623 /* Verify the results */ 2624 const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget(); 2625 2626 unsigned char* buffer = NULL; 2627 unsigned char* data_ptr = NULL; 2628 int rt_bits_alpha = 0; 2629 int rt_bits_blue = 0; 2630 int rt_bits_green = 0; 2631 int rt_bits_red = 0; 2632 int rt_height = rt.getHeight(); 2633 int rt_width = rt.getWidth(); 2634 const int row_width = 4 /* RGBA */ * rt_width; 2635 2636 gl.getIntegerv(GL_ALPHA_BITS, &rt_bits_alpha); 2637 gl.getIntegerv(GL_BLUE_BITS, &rt_bits_blue); 2638 gl.getIntegerv(GL_GREEN_BITS, &rt_bits_green); 2639 gl.getIntegerv(GL_RED_BITS, &rt_bits_red); 2640 2641 buffer = new unsigned char[rt_height * rt_width * 4]; 2642 2643 gl.readPixels(0, 0, rt_width, rt_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 2644 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 2645 2646 data_ptr = buffer + row_width * (rt_height / 2) + rt_width / 2 * 4; 2647 2648 if (((data_ptr[0] != 0) && (rt_bits_red != 0)) || ((data_ptr[1] != 255) && (rt_bits_green != 0)) || 2649 ((data_ptr[2] != 0) && (rt_bits_blue != 0)) || ((data_ptr[3] != 0) && (rt_bits_alpha != 0))) 2650 { 2651 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data rendered: expected:(0, 255, 0, 0) rendered:" 2652 << "(" << data_ptr[0] << ", " << data_ptr[1] << ", " << data_ptr[2] << ", " << data_ptr[3] 2653 << ")" << tcu::TestLog::EndMessage; 2654 2655 delete[] buffer; 2656 buffer = NULL; 2657 2658 TCU_FAIL("Invalid data rendered"); 2659 } 2660 2661 if (buffer != NULL) 2662 { 2663 delete[] buffer; 2664 buffer = NULL; 2665 } 2666 2667 /* All done */ 2668 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2669 2670 return STOP; 2671} 2672 2673/** Constructor. 2674 * 2675 * @param context CTS context handle. 2676 **/ 2677MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest:: 2678 MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest(Context& context) 2679 : TestCase(context, "texture_size_in_vertex_shaders", 2680 "Verifies textureSize() works for multisample textures when used in vertex shaders") 2681 , bo_id(0) 2682 , fbo_id(0) 2683 , fs_id(0) 2684 , po_id(0) 2685 , tfo_id(0) 2686 , to_2d_multisample_id(0) 2687 , to_2d_multisample_array_id(0) 2688 , vs_2d_array_id(0) 2689 , vs_2d_id(0) 2690{ 2691 /* Left blank on purpose */ 2692} 2693 2694/** Deinitializes ES objects created during test execution */ 2695void MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::deinit() 2696{ 2697 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2698 2699 if (bo_id != 0) 2700 { 2701 gl.deleteBuffers(1, &bo_id); 2702 2703 bo_id = 0; 2704 } 2705 2706 if (fbo_id != 0) 2707 { 2708 gl.deleteFramebuffers(1, &fbo_id); 2709 2710 fbo_id = 0; 2711 } 2712 2713 if (fs_id != 0) 2714 { 2715 gl.deleteShader(fs_id); 2716 2717 fs_id = 0; 2718 } 2719 2720 if (po_id != 0) 2721 { 2722 gl.deleteProgram(po_id); 2723 2724 po_id = 0; 2725 } 2726 2727 if (tfo_id != 0) 2728 { 2729 gl.deleteTransformFeedbacks(1, &tfo_id); 2730 2731 tfo_id = 0; 2732 } 2733 2734 if (to_2d_multisample_id != 0) 2735 { 2736 gl.deleteTextures(1, &to_2d_multisample_id); 2737 2738 to_2d_multisample_id = 0; 2739 } 2740 2741 if (to_2d_multisample_array_id != 0) 2742 { 2743 gl.deleteTextures(1, &to_2d_multisample_array_id); 2744 2745 to_2d_multisample_array_id = 0; 2746 } 2747 2748 if (vs_2d_id != 0) 2749 { 2750 gl.deleteShader(vs_2d_id); 2751 2752 vs_2d_id = 0; 2753 } 2754 2755 if (vs_2d_array_id != 0) 2756 { 2757 gl.deleteShader(vs_2d_array_id); 2758 2759 vs_2d_array_id = 0; 2760 } 2761 2762 /* Call base class' deinit() */ 2763 TestCase::deinit(); 2764} 2765 2766/** Executes test iteration. 2767 * 2768 * @return Returns STOP when test has finished executing. 2769 */ 2770tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::iterate() 2771{ 2772 bool are_multisample_2d_array_tos_supported = 2773 m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); 2774 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2775 2776 /* Set up a TFO */ 2777 gl.genTransformFeedbacks(1, &tfo_id); 2778 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id); 2779 2780 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a transform feedback object"); 2781 2782 /* Set up a buffer object */ 2783 gl.genBuffers(1, &bo_id); 2784 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id); 2785 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float), NULL, GL_STATIC_READ); 2786 2787 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a buffer object"); 2788 2789 /* Set up texture objects */ 2790 if (are_multisample_2d_array_tos_supported) 2791 { 2792 gl.genTextures(1, &to_2d_multisample_array_id); 2793 } 2794 2795 gl.genTextures(1, &to_2d_multisample_id); 2796 2797 /* NOTE: Since we're binding the textures to zero texture unit, 2798 * we don't need to do glUniform1i() calls to configure 2799 * the texture samplers in the vertex shaders later on. 2800 */ 2801 if (are_multisample_2d_array_tos_supported) 2802 { 2803 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_2d_multisample_array_id); 2804 } 2805 2806 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id); 2807 2808 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects"); 2809 2810 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ 2811 GL_RGBA8, 16, /* width */ 2812 32, /* height */ 2813 GL_TRUE); 2814 GLU_EXPECT_NO_ERROR(gl.getError(), 2815 "glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target"); 2816 2817 if (are_multisample_2d_array_tos_supported) 2818 { 2819 gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */ 2820 GL_RGBA8, 16, /* width */ 2821 32, /* height */ 2822 8, /* depth */ 2823 GL_TRUE); /* fixedsamplelocations */ 2824 GLU_EXPECT_NO_ERROR( 2825 gl.getError(), 2826 "gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target"); 2827 } 2828 2829 /* Set up a fragment shader */ 2830 glw::GLint compile_status = GL_FALSE; 2831 static const char* fs_body = "#version 310 es\n" 2832 "\n" 2833 "void main()\n" 2834 "{\n" 2835 "}\n"; 2836 2837 fs_id = gl.createShader(GL_FRAGMENT_SHADER); 2838 2839 gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL); 2840 gl.compileShader(fs_id); 2841 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a fragment shader"); 2842 2843 gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status); 2844 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query fragment shader's compile status"); 2845 2846 if (compile_status == GL_FALSE) 2847 { 2848 TCU_FAIL("Could not compile fragment shader"); 2849 } 2850 2851 /* Set up a vertex shader for 2D multisample texture case */ 2852 static const char* vs_2d_body = "#version 310 es\n" 2853 "\n" 2854 "precision highp float;\n" 2855 "\n" 2856 "uniform highp sampler2DMS sampler;\n" 2857 "out float is_size_correct;\n" 2858 "\n" 2859 "void main()\n" 2860 "{\n" 2861 " ivec2 size = textureSize(sampler);\n" 2862 "\n" 2863 " if (size.x == 16 && size.y == 32)\n" 2864 " {\n" 2865 " is_size_correct = 1.0f;\n" 2866 " }\n" 2867 " else\n" 2868 " {\n" 2869 " is_size_correct = 0.0f;\n" 2870 " }\n" 2871 "}\n"; 2872 2873 vs_2d_id = gl.createShader(GL_VERTEX_SHADER); 2874 2875 gl.shaderSource(vs_2d_id, 1 /* count */, &vs_2d_body, NULL); 2876 gl.compileShader(vs_2d_id); 2877 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader for 2D multisample texture case"); 2878 2879 gl.getShaderiv(vs_2d_id, GL_COMPILE_STATUS, &compile_status); 2880 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query 2D multisample texture vertex shader's compile status"); 2881 2882 if (compile_status == GL_FALSE) 2883 { 2884 TCU_FAIL("Could not compile vertex shader for 2D multisample texture"); 2885 } 2886 2887 /* Set up a vertex shader for 2D multisample array texture case */ 2888 if (are_multisample_2d_array_tos_supported) 2889 { 2890 static const char* vs_2d_array_body = "#version 310 es\n" 2891 "\n" 2892 "#extension GL_OES_texture_storage_multisample_2d_array : enable\n" 2893 "precision highp float;\n" 2894 "\n" 2895 "uniform highp sampler2DMSArray sampler;\n" 2896 "out float is_size_correct;\n" 2897 "\n" 2898 "void main()\n" 2899 "{\n" 2900 " ivec3 size = textureSize(sampler);\n" 2901 "\n" 2902 " if (size.x == 16 && size.y == 32 && size.z == 8)\n" 2903 " {\n" 2904 " is_size_correct = 1.0f;\n" 2905 " }\n" 2906 " else\n" 2907 " {\n" 2908 " is_size_correct = 0.0f;\n" 2909 " }\n" 2910 "}\n"; 2911 2912 vs_2d_array_id = gl.createShader(GL_VERTEX_SHADER); 2913 2914 gl.shaderSource(vs_2d_array_id, 1 /* count */, &vs_2d_array_body, NULL); 2915 gl.compileShader(vs_2d_array_id); 2916 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader for 2D multisample array texture case"); 2917 2918 gl.getShaderiv(vs_2d_array_id, GL_COMPILE_STATUS, &compile_status); 2919 GLU_EXPECT_NO_ERROR(gl.getError(), 2920 "Could not query 2D multisample array texture vertex shader's compile status"); 2921 2922 if (compile_status == GL_FALSE) 2923 { 2924 TCU_FAIL("Could not compile vertex shader for 2D multisample array texture"); 2925 } 2926 } 2927 2928 /* Execute two iterations: 2929 * 2930 * a) Create a program object using fs and vs_2d shaders; 2931 * b) Create a program object using fs and vs_2d_array shaders. 2932 * 2933 * Case b) should only be executed if 2D Array MS textures are 2934 * supported. 2935 */ 2936 for (int n_iteration = 0; n_iteration < 2 /* iterations */; ++n_iteration) 2937 { 2938 if (n_iteration == 1 && !are_multisample_2d_array_tos_supported) 2939 { 2940 /* Skip the iteration */ 2941 continue; 2942 } 2943 2944 if (po_id != 0) 2945 { 2946 gl.deleteProgram(po_id); 2947 2948 po_id = 0; 2949 } 2950 2951 po_id = gl.createProgram(); 2952 2953 /* Attach iteration-specific shaders */ 2954 switch (n_iteration) 2955 { 2956 case 0: 2957 { 2958 gl.attachShader(po_id, fs_id); 2959 gl.attachShader(po_id, vs_2d_id); 2960 2961 break; 2962 } 2963 2964 case 1: 2965 { 2966 gl.attachShader(po_id, fs_id); 2967 gl.attachShader(po_id, vs_2d_array_id); 2968 2969 break; 2970 } 2971 2972 default: 2973 TCU_FAIL("Unrecognized iteration index"); 2974 } 2975 2976 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 2977 2978 /* Configure the program object for XFB */ 2979 const char* varying_name = "is_size_correct"; 2980 2981 gl.transformFeedbackVaryings(po_id, 1 /* count */, &varying_name, GL_INTERLEAVED_ATTRIBS); 2982 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed."); 2983 2984 /* Link the program object */ 2985 glw::GLint link_status = GL_FALSE; 2986 2987 gl.linkProgram(po_id); 2988 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 2989 2990 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 2991 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 2992 2993 if (link_status != GL_TRUE) 2994 { 2995 m_testCtx.getLog() << tcu::TestLog::Message << "Linking failed for program object in iteration " 2996 << n_iteration << tcu::TestLog::EndMessage; 2997 2998 TCU_FAIL("Program object linking failed"); 2999 } 3000 3001 /* Render a point using the program */ 3002 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id); 3003 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed"); 3004 3005 gl.useProgram(po_id); 3006 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 3007 3008 gl.beginTransformFeedback(GL_POINTS); 3009 { 3010 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 3011 } 3012 gl.endTransformFeedback(); 3013 3014 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed"); 3015 3016 /* Read the captured data. Reset the contents of the BO before the buffer 3017 * object is unmapped. 3018 */ 3019 void* data_ptr = NULL; 3020 const float epsilon = (float)1e-5; 3021 float result = 0.0f; 3022 3023 data_ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, sizeof(float) /* size */, 3024 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); 3025 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed"); 3026 3027 result = *((const float*)data_ptr); 3028 memset(data_ptr, 0, sizeof(float)); 3029 3030 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3031 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed"); 3032 3033 if (de::abs(result - 1.0f) > epsilon) 3034 { 3035 m_testCtx.getLog() << tcu::TestLog::Message << "Retrieved value: " << result << ", expected: 1.0" 3036 << tcu::TestLog::EndMessage; 3037 3038 TCU_FAIL("Invalid value reported."); 3039 } 3040 } 3041 3042 /* All done */ 3043 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3044 3045 return STOP; 3046} 3047} /* glcts namespace */ 3048