1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 #include "esextcGeometryShaderLayeredFramebuffer.hpp" 25 26 #include "gluContextInfo.hpp" 27 #include "gluDefs.hpp" 28 #include "glwEnums.hpp" 29 #include "glwFunctions.hpp" 30 #include "tcuTestLog.hpp" 31 #include <cstring> 32 33 namespace glcts 34 { 35 /** Constructor 36 * 37 * @param context Test context 38 * @param name Test case's name 39 * @param description Test case's desricption 40 **/ 41 GeometryShaderLayeredFramebufferBlending::GeometryShaderLayeredFramebufferBlending(Context& context, 42 const ExtParameters& extParams, 43 const char* name, 44 const char* description) 45 : TestCaseBase(context, extParams, name, description) 46 , m_fbo_id(0) 47 , m_fs_id(0) 48 , m_gs_id(0) 49 , m_po_id(0) 50 , m_read_fbo_id(0) 51 , m_to_id(0) 52 , m_vao_id(0) 53 , m_vs_id(0) 54 { 55 /* Left blank on purpose */ 56 } 57 58 /** Deinitializes GLES objects created during the test. */ 59 void GeometryShaderLayeredFramebufferBlending::deinit(void) 60 { 61 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 62 63 /* Clean up */ 64 if (m_fbo_id != 0) 65 { 66 gl.deleteFramebuffers(1, &m_fbo_id); 67 } 68 69 if (m_fs_id != 0) 70 { 71 gl.deleteShader(m_fs_id); 72 } 73 74 if (m_gs_id != 0) 75 { 76 gl.deleteShader(m_gs_id); 77 } 78 79 if (m_po_id != 0) 80 { 81 gl.deleteProgram(m_po_id); 82 } 83 84 if (m_read_fbo_id != 0) 85 { 86 gl.deleteFramebuffers(1, &m_read_fbo_id); 87 } 88 89 if (m_to_id != 0) 90 { 91 gl.deleteTextures(1, &m_to_id); 92 } 93 94 if (m_vao_id != 0) 95 { 96 gl.deleteVertexArrays(1, &m_vao_id); 97 } 98 99 if (m_vs_id != 0) 100 { 101 gl.deleteShader(m_vs_id); 102 } 103 104 /* Release base class */ 105 TestCaseBase::deinit(); 106 } 107 108 /** Executes the test. 109 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 110 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 111 * Note the function throws exception should an error occur! 112 **/ 113 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferBlending::iterate(void) 114 { 115 /* Test-wide constants */ 116 #define N_TEXTURE_COMPONENTS (4) 117 #define TEXTURE_DEPTH (4) 118 #define TEXTURE_HEIGHT (4) 119 #define TEXTURE_WIDTH (4) 120 121 /* Fragment shader code */ 122 const char* fs_code = "${VERSION}\n" 123 "\n" 124 "precision highp float;\n" 125 "\n" 126 "out vec4 result;\n" 127 "\n" 128 "void main()\n" 129 "{\n" 130 " result = vec4(0.2);\n" 131 "}\n"; 132 133 /* Geometry shader code */ 134 const char* gs_code = "${VERSION}\n" 135 "${GEOMETRY_SHADER_REQUIRE}\n" 136 "\n" 137 "layout(points) in;\n" 138 "layout(triangle_strip, max_vertices=64) out;\n" 139 "\n" 140 "void main()\n" 141 "{\n" 142 " for (int n = 0; n < 4; ++n)\n" 143 " {\n" 144 " gl_Layer = n;\n" 145 " gl_Position = vec4(1, 1, 0, 1);\n" 146 " EmitVertex();\n" 147 "\n" 148 " gl_Layer = n;\n" 149 " gl_Position = vec4(1, -1, 0, 1);\n" 150 " EmitVertex();\n" 151 "\n" 152 " gl_Layer = n;\n" 153 " gl_Position = vec4(-1, 1, 0, 1);\n" 154 " EmitVertex();\n" 155 "\n" 156 " gl_Layer = n;\n" 157 " gl_Position = vec4(-1, -1, 0, 1);\n" 158 " EmitVertex();\n" 159 "\n" 160 " EndPrimitive();\n" 161 " }\n" 162 "}\n"; 163 164 /* General variables */ 165 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 166 unsigned int n = 0; 167 unsigned int n_component = 0; 168 unsigned int n_layer = 0; 169 unsigned int n_slice = 0; 170 unsigned int x = 0; 171 unsigned int y = 0; 172 173 unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 174 unsigned char buffer_slice1[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 175 unsigned char buffer_slice2[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 176 unsigned char buffer_slice3[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 177 unsigned char buffer_slice4[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 178 unsigned char ref_buffer_slice1[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 179 unsigned char ref_buffer_slice2[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 180 unsigned char ref_buffer_slice3[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 181 unsigned char ref_buffer_slice4[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 182 183 if (!m_is_geometry_shader_extension_supported) 184 { 185 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 186 } 187 188 /* Set up shader objects */ 189 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 190 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 191 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 192 193 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate shader objects"); 194 195 /* Set up program objects */ 196 m_po_id = gl.createProgram(); 197 198 if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */, 199 &m_boilerplate_vs_code)) 200 { 201 TCU_FAIL("Could not build program object"); 202 } 203 204 /* Prepare texture data we will use for each slice */ 205 for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n) 206 { 207 unsigned char* slice_pixels_ptr[] = { buffer_slice1 + n * N_TEXTURE_COMPONENTS, 208 buffer_slice2 + n * N_TEXTURE_COMPONENTS, 209 buffer_slice3 + n * N_TEXTURE_COMPONENTS, 210 buffer_slice4 + n * N_TEXTURE_COMPONENTS }; 211 212 for (n_slice = 0; n_slice < sizeof(slice_pixels_ptr) / sizeof(slice_pixels_ptr[0]); ++n_slice) 213 { 214 slice_pixels_ptr[n_slice][0] = 0; 215 slice_pixels_ptr[n_slice][1] = (unsigned char)(n_slice * 255 / 4); 216 slice_pixels_ptr[n_slice][2] = (unsigned char)(n_slice * 255 / 8); 217 slice_pixels_ptr[n_slice][3] = (unsigned char)(n_slice * 255 / 12); 218 } /* for (all slices) */ 219 } /* for (all pixels) */ 220 221 /* Calculate reference texture data we will later use when verifying the rendered data */ 222 for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n) 223 { 224 unsigned char* ref_slice_pixels_ptr[] = { ref_buffer_slice1 + n * N_TEXTURE_COMPONENTS, 225 ref_buffer_slice2 + n * N_TEXTURE_COMPONENTS, 226 ref_buffer_slice3 + n * N_TEXTURE_COMPONENTS, 227 ref_buffer_slice4 + n * N_TEXTURE_COMPONENTS }; 228 229 unsigned char* slice_pixels_ptr[] = { buffer_slice1 + n * N_TEXTURE_COMPONENTS, 230 buffer_slice2 + n * N_TEXTURE_COMPONENTS, 231 buffer_slice3 + n * N_TEXTURE_COMPONENTS, 232 buffer_slice4 + n * N_TEXTURE_COMPONENTS }; 233 234 for (n_slice = 0; n_slice < sizeof(slice_pixels_ptr) / sizeof(slice_pixels_ptr[0]); ++n_slice) 235 { 236 unsigned char* ref_slice_ptr = ref_slice_pixels_ptr[n_slice]; 237 unsigned char* slice_ptr = slice_pixels_ptr[n_slice]; 238 float slice_rgba[] = { 239 float(slice_ptr[0]) / 255.0f, /* convert to FP representation */ 240 float(slice_ptr[1]) / 255.0f, /* convert to FP representation */ 241 float(slice_ptr[2]) / 255.0f, /* convert to FP representation */ 242 float(slice_ptr[3]) / 255.0f /* convert to FP representation */ 243 }; 244 245 for (n_component = 0; n_component < N_TEXTURE_COMPONENTS; ++n_component) 246 { 247 float temp_component = slice_rgba[n_component] /* dst_color */ * slice_rgba[n_component] /* dst_color */ 248 + 0.8f /* 1-src_color */ * 0.2f /* src_color */; 249 250 /* Clamp if necessary */ 251 if (temp_component < 0) 252 { 253 temp_component = 0.0f; 254 } 255 else if (temp_component > 1) 256 { 257 temp_component = 1.0f; 258 } 259 260 /* Convert back to GL_RGBA8 */ 261 ref_slice_ptr[n_component] = (unsigned char)(temp_component * 255.0f); 262 } /* for (all components) */ 263 } /* for (all slices) */ 264 } /* for (all pixels) */ 265 266 /* Set up texture object used for the test */ 267 gl.genTextures(1, &m_to_id); 268 gl.bindTexture(GL_TEXTURE_3D, m_to_id); 269 gl.texStorage3D(GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH); 270 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH, 271 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice1); 272 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH, 273 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice2); 274 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH, 275 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice3); 276 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH, 277 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice4); 278 279 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object"); 280 281 /* Set up framebuffer object used for the test */ 282 gl.genFramebuffers(1, &m_fbo_id); 283 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id); 284 285 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */); 286 287 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer"); 288 289 /* Generate and bind a vertex array object */ 290 gl.genVertexArrays(1, &m_vao_id); 291 gl.bindVertexArray(m_vao_id); 292 293 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up vertex array object"); 294 295 /* Set up blending */ 296 gl.blendFunc(GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR); 297 gl.enable(GL_BLEND); 298 299 /* Render */ 300 gl.useProgram(m_po_id); 301 gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT); 302 303 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 304 305 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed"); 306 307 /* Verify rendered data in the layers */ 308 gl.genFramebuffers(1, &m_read_fbo_id); 309 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id); 310 311 for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer) 312 { 313 bool has_layer_failed = false; 314 315 const unsigned char* ref_buffer = 316 (n_layer == 0) ? 317 ref_buffer_slice1 : 318 (n_layer == 1) ? ref_buffer_slice2 : (n_layer == 2) ? ref_buffer_slice3 : ref_buffer_slice4; 319 320 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */, n_layer); 321 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 322 323 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixel data!"); 324 325 for (y = 0; y < TEXTURE_HEIGHT; ++y) 326 { 327 const unsigned int pixel_size = N_TEXTURE_COMPONENTS; 328 const unsigned char* ref_row = ref_buffer + y * pixel_size; 329 const unsigned char* row = buffer + y * pixel_size; 330 331 for (x = 0; x < TEXTURE_WIDTH; ++x) 332 { 333 #define EPSILON (1) 334 335 const unsigned char* data = row + x * pixel_size; 336 const unsigned char* ref_data = ref_row + x * pixel_size; 337 338 if (de::abs((int)data[0] - (int)ref_data[0]) > EPSILON || 339 de::abs((int)data[1] - (int)ref_data[1]) > EPSILON || 340 de::abs((int)data[2] - (int)ref_data[2]) > EPSILON || 341 de::abs((int)data[3] - (int)ref_data[3]) > EPSILON) 342 { 343 m_testCtx.getLog() << tcu::TestLog::Message << "(layer=" << n_layer << " x=" << x << " y=" << y 344 << ") " 345 << "Reference value is different than the rendered data (epsilon > " << EPSILON 346 << "): " 347 << "(" << (unsigned int)ref_data[0] << ", " << (unsigned int)ref_data[1] << ", " 348 << (unsigned int)ref_data[2] << ", " << (unsigned int)ref_data[3] << ") vs " 349 << "(" << (unsigned int)data[0] << ", " << (unsigned int)data[1] << ", " 350 << (unsigned int)data[2] << ", " << (unsigned int)data[3] << ")." 351 << tcu::TestLog::EndMessage; 352 353 has_layer_failed = true; 354 } /* if (regions are different) */ 355 356 #undef EPSILON 357 } /* for (all pixels in a row) */ 358 } /* for (all rows) */ 359 360 if (has_layer_failed) 361 { 362 TCU_FAIL("Pixel data comparison failed"); 363 } 364 } /* for (all layers) */ 365 366 /* Done */ 367 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 368 return STOP; 369 370 #undef N_TEXTURE_COMPONENTS 371 #undef TEXTURE_DEPTH 372 #undef TEXTURE_HEIGHT 373 #undef TEXTURE_WIDTH 374 } 375 376 /** Constructor 377 * 378 * @param context Test context 379 * @param name Test case's name 380 * @param description Test case's description 381 **/ 382 GeometryShaderLayeredFramebufferClear::GeometryShaderLayeredFramebufferClear(Context& context, 383 const ExtParameters& extParams, 384 const char* name, const char* description) 385 : TestCaseBase(context, extParams, name, description) 386 , m_fbo_char_id(0) 387 , m_fbo_int_id(0) 388 , m_fbo_uint_id(0) 389 , m_read_fbo_id(0) 390 , m_to_rgba32i_id(0) 391 , m_to_rgba32ui_id(0) 392 , m_to_rgba8_id(0) 393 { 394 /* Left blank on purpose */ 395 } 396 397 /** Executes the test. 398 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 399 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 400 * Note the function throws exception should an error occur! 401 **/ 402 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferClear::iterate(void) 403 { 404 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 405 406 /* Test-wide definitions */ 407 #define N_TEXTURE_COMPONENTS (4) 408 #define TEXTURE_DEPTH (4) 409 #define TEXTURE_HEIGHT (4) 410 #define TEXTURE_WIDTH (4) 411 412 /* Type definitions */ 413 typedef enum { 414 /* Always first */ 415 CLEAR_FIRST = 0, 416 417 /* glClear() */ 418 CLEAR_PLAIN = CLEAR_FIRST, 419 /* glClearBufferfv() */ 420 CLEAR_BUFFERFV, 421 /* glClearBufferiv() */ 422 CLEAR_BUFFERIV, 423 /* glClearBufferuiv() */ 424 CLEAR_BUFFERUIV, 425 426 /* Always last */ 427 CLEAR_COUNT 428 } _clear_type; 429 430 /* General variables */ 431 const glw::GLenum fbo_draw_buffer = GL_COLOR_ATTACHMENT0; 432 433 int n = 0; 434 int n_layer = 0; 435 int x = 0; 436 int y = 0; 437 438 unsigned char buffer_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 439 int buffer_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 440 unsigned int buffer_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 441 unsigned char slice_1_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 442 int slice_1_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 443 unsigned int slice_1_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 444 unsigned char slice_2_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 445 int slice_2_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 446 unsigned int slice_2_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 447 unsigned char slice_3_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 448 int slice_3_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 449 unsigned int slice_3_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 450 unsigned char slice_4_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 451 int slice_4_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 452 unsigned int slice_4_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 453 454 /* Only carry on if geometry shaders are supported */ 455 if (!m_is_geometry_shader_extension_supported) 456 { 457 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 458 } 459 460 /* Set up slice data */ 461 memset(slice_1_data_char, 0, sizeof(slice_1_data_char)); 462 memset(slice_1_data_int, 0, sizeof(slice_1_data_int)); 463 memset(slice_1_data_uint, 0, sizeof(slice_1_data_uint)); 464 memset(slice_2_data_char, 0, sizeof(slice_2_data_char)); 465 memset(slice_2_data_int, 0, sizeof(slice_2_data_int)); 466 memset(slice_2_data_uint, 0, sizeof(slice_2_data_uint)); 467 memset(slice_3_data_char, 0, sizeof(slice_3_data_char)); 468 memset(slice_3_data_int, 0, sizeof(slice_3_data_int)); 469 memset(slice_3_data_uint, 0, sizeof(slice_3_data_uint)); 470 memset(slice_4_data_char, 0, sizeof(slice_4_data_char)); 471 memset(slice_4_data_int, 0, sizeof(slice_4_data_int)); 472 memset(slice_4_data_uint, 0, sizeof(slice_4_data_uint)); 473 474 for (n = 0; n < 4 /* width */ * 4 /* height */; ++n) 475 { 476 slice_1_data_char[4 * n + 0] = 255; 477 slice_1_data_int[4 * n + 0] = 255; 478 slice_1_data_uint[4 * n + 0] = 255; 479 480 slice_2_data_char[4 * n + 1] = 255; 481 slice_2_data_int[4 * n + 1] = 255; 482 slice_2_data_uint[4 * n + 1] = 255; 483 484 slice_3_data_char[4 * n + 2] = 255; 485 slice_3_data_int[4 * n + 2] = 255; 486 slice_3_data_uint[4 * n + 2] = 255; 487 488 slice_4_data_char[4 * n + 0] = 255; 489 slice_4_data_char[4 * n + 1] = 255; 490 slice_4_data_int[4 * n + 0] = 255; 491 slice_4_data_int[4 * n + 1] = 255; 492 slice_4_data_uint[4 * n + 0] = 255; 493 slice_4_data_uint[4 * n + 1] = 255; 494 } /* for (all pixels) */ 495 496 /* Set up texture objects */ 497 gl.genTextures(1, &m_to_rgba8_id); 498 gl.genTextures(1, &m_to_rgba32i_id); 499 gl.genTextures(1, &m_to_rgba32ui_id); 500 501 for (n = 0; n < 3 /* textures */; ++n) 502 { 503 void* to_data_1 = 504 (n == 0) ? (void*)slice_1_data_char : (n == 1) ? (void*)slice_1_data_int : (void*)slice_1_data_uint; 505 506 void* to_data_2 = 507 (n == 0) ? (void*)slice_2_data_char : (n == 1) ? (void*)slice_2_data_int : (void*)slice_2_data_uint; 508 509 void* to_data_3 = 510 (n == 0) ? (void*)slice_3_data_char : (n == 1) ? (void*)slice_3_data_int : (void*)slice_3_data_uint; 511 512 void* to_data_4 = 513 (n == 0) ? (void*)slice_4_data_char : (n == 1) ? (void*)slice_4_data_int : (void*)slice_4_data_uint; 514 515 glw::GLenum to_format = (n == 0) ? GL_RGBA : (n == 1) ? GL_RGBA_INTEGER : GL_RGBA_INTEGER; 516 517 glw::GLenum to_internalformat = (n == 0) ? GL_RGBA8 : (n == 1) ? GL_RGBA32I : GL_RGBA32UI; 518 519 glw::GLuint to_id = (n == 0) ? m_to_rgba8_id : (n == 1) ? m_to_rgba32i_id : m_to_rgba32ui_id; 520 521 glw::GLenum to_type = (n == 0) ? GL_UNSIGNED_BYTE : (n == 1) ? GL_INT : GL_UNSIGNED_INT; 522 523 gl.bindTexture(GL_TEXTURE_3D, to_id); 524 525 gl.texStorage3D(GL_TEXTURE_3D, 1 /* levels */, to_internalformat, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH); 526 527 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH, 528 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_1); 529 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH, 530 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_2); 531 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH, 532 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_3); 533 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH, 534 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_4); 535 536 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0); 537 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0); 538 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 539 540 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture object"); 541 } /* for (all texture objects) */ 542 543 /* Set up framebuffer object */ 544 gl.genFramebuffers(1, &m_fbo_char_id); 545 gl.genFramebuffers(1, &m_fbo_int_id); 546 gl.genFramebuffers(1, &m_fbo_uint_id); 547 gl.genFramebuffers(1, &m_read_fbo_id); 548 549 for (n = 0; n < 3 /* framebuffers */; ++n) 550 { 551 glw::GLuint fbo_id = (n == 0) ? m_fbo_char_id : (n == 1) ? m_fbo_int_id : m_fbo_uint_id; 552 553 glw::GLuint to_id = (n == 0) ? m_to_rgba8_id : (n == 1) ? m_to_rgba32i_id : m_to_rgba32ui_id; 554 555 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); 556 gl.drawBuffers(1, &fbo_draw_buffer); 557 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */); 558 559 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object"); 560 } /* for (all framebuffers) */ 561 562 /* Try reading from the layered framebuffer. */ 563 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_char_id); 564 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer_char); 565 566 /* Is the returned data an exact copy of what we've uploaded for layer zero? */ 567 if (memcmp(buffer_char, slice_1_data_char, sizeof(slice_1_data_char)) != 0) 568 { 569 TCU_FAIL("Retrieved data is different from data uploaded for layer 0 of a layered framebuffer."); 570 } 571 572 /* Iterate through all clear calls supported */ 573 574 for (int current_test = static_cast<int>(CLEAR_FIRST); current_test < static_cast<int>(CLEAR_COUNT); current_test++) 575 { 576 void* buffer = NULL; 577 const unsigned char clear_color_byte[] = { 64, 128, 255, 32 }; 578 const float clear_color_float[] = { 0.25f, 0.5f, 1.0f, 32.0f / 255.0f }; 579 const int clear_color_int[] = { 64, 128, 255, 32 }; 580 glw::GLuint fbo_id = 0; 581 int pixel_size = 0; 582 void* slice_1_data = NULL; 583 void* slice_2_data = NULL; 584 void* slice_3_data = NULL; 585 void* slice_4_data = NULL; 586 glw::GLenum to_format = GL_NONE; 587 glw::GLuint to_id = 0; 588 glw::GLenum to_type = GL_NONE; 589 590 switch (static_cast<_clear_type>(current_test)) 591 { 592 case CLEAR_BUFFERFV: 593 case CLEAR_PLAIN: 594 { 595 buffer = buffer_char; 596 fbo_id = m_fbo_char_id; 597 pixel_size = N_TEXTURE_COMPONENTS; 598 slice_1_data = slice_1_data_char; 599 slice_2_data = slice_2_data_char; 600 slice_3_data = slice_3_data_char; 601 slice_4_data = slice_4_data_char; 602 to_format = GL_RGBA; 603 to_id = m_to_rgba8_id; 604 to_type = GL_UNSIGNED_BYTE; 605 606 break; 607 } 608 609 case CLEAR_BUFFERIV: 610 { 611 buffer = (void*)buffer_int; 612 fbo_id = m_fbo_int_id; 613 pixel_size = N_TEXTURE_COMPONENTS * sizeof(int); 614 slice_1_data = slice_1_data_int; 615 slice_2_data = slice_2_data_int; 616 slice_3_data = slice_3_data_int; 617 slice_4_data = slice_4_data_int; 618 to_format = GL_RGBA_INTEGER; 619 to_id = m_to_rgba32i_id; 620 to_type = GL_INT; 621 622 break; 623 } 624 625 case CLEAR_BUFFERUIV: 626 { 627 buffer = (void*)buffer_uint; 628 fbo_id = m_fbo_uint_id; 629 pixel_size = N_TEXTURE_COMPONENTS * sizeof(unsigned int); 630 slice_1_data = slice_1_data_uint; 631 slice_2_data = slice_2_data_uint; 632 slice_3_data = slice_3_data_uint; 633 slice_4_data = slice_4_data_uint; 634 to_format = GL_RGBA_INTEGER; 635 to_id = m_to_rgba32ui_id; 636 to_type = GL_UNSIGNED_INT; 637 638 break; 639 } 640 641 default: 642 { 643 /* This location should never be reached */ 644 TCU_FAIL("Execution flow failure"); 645 } 646 } /* switch (current_test)*/ 647 648 /* Restore layer data just in case */ 649 gl.bindTexture(GL_TEXTURE_3D, to_id); 650 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH, 651 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_1_data); 652 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH, 653 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_2_data); 654 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH, 655 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_3_data); 656 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH, 657 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_4_data); 658 659 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D() call failed."); 660 661 /* Issue requested clear call */ 662 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id); 663 664 switch (current_test) 665 { 666 case CLEAR_PLAIN: 667 { 668 gl.clearColor(clear_color_float[0], clear_color_float[1], clear_color_float[2], clear_color_float[3]); 669 gl.clear(GL_COLOR_BUFFER_BIT); 670 671 break; 672 } 673 674 case CLEAR_BUFFERIV: 675 { 676 gl.clearBufferiv(GL_COLOR, 0 /* draw buffer index */, clear_color_int); 677 678 break; 679 } 680 681 case CLEAR_BUFFERUIV: 682 { 683 gl.clearBufferuiv(GL_COLOR, 0 /* draw buffer index */, (const glw::GLuint*)clear_color_int); 684 685 break; 686 } 687 688 case CLEAR_BUFFERFV: 689 { 690 gl.clearBufferfv(GL_COLOR, 0 /* draw buffer index */, clear_color_float); 691 692 break; 693 } 694 695 default: 696 { 697 /* This location should never be reached */ 698 TCU_FAIL("Execution flow failure"); 699 } 700 } /* switch (current_test) */ 701 702 /* Make sure no error was generated */ 703 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear call failed."); 704 705 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id); 706 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create read framebuffer object!"); 707 708 /* Check the layer data after a clear call */ 709 for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer) 710 { 711 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */, n_layer); 712 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, to_format, to_type, buffer); 713 714 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 715 716 /* If we requested an integer clear, the pixels we obtained should be reset to specific values. 717 * If we asked for a FP-based clear, consider an epsilon. */ 718 for (y = 0; y < TEXTURE_HEIGHT; ++y) 719 { 720 const int row_size = TEXTURE_WIDTH * pixel_size; 721 unsigned char* row = (unsigned char*)buffer + y * row_size; 722 723 for (x = 0; x < TEXTURE_WIDTH; ++x) 724 { 725 if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV) 726 { 727 unsigned int* pixel = (unsigned int*)(row + x * pixel_size); 728 729 if (memcmp(pixel, clear_color_int, sizeof(clear_color_int)) != 0) 730 { 731 /* Test fails at this point */ 732 m_testCtx.getLog() 733 << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel [" 734 << clear_color_byte[0] << ", " << clear_color_byte[1] << ", " << clear_color_byte[2] 735 << ", " << clear_color_byte[3] << "] is different from the one retrieved [" 736 << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", " 737 << (int)pixel[3] << "]" << tcu::TestLog::EndMessage; 738 739 TCU_FAIL("Data comparison failure"); 740 } /* if (memcmp(pixel, clear_color_byte, sizeof(clear_color_byte) ) != 0) */ 741 } /* if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV) */ 742 else 743 { 744 #define EPSILON (1) 745 746 unsigned char* pixel = (unsigned char*)(row + x * pixel_size); 747 748 if (de::abs((int)pixel[0] - clear_color_int[0]) > EPSILON || 749 de::abs((int)pixel[1] - clear_color_int[1]) > EPSILON || 750 de::abs((int)pixel[2] - clear_color_int[2]) > EPSILON || 751 de::abs((int)pixel[3] - clear_color_int[3]) > EPSILON) 752 { 753 /* Test fails at this point */ 754 m_testCtx.getLog() 755 << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel [" 756 << clear_color_byte[0] << ", " << clear_color_byte[1] << ", " << clear_color_byte[2] 757 << ", " << clear_color_byte[3] << "] is different from the one retrieved [" 758 << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", " 759 << (int)pixel[3] << "]" << tcu::TestLog::EndMessage; 760 761 TCU_FAIL("Data comparison failure"); 762 } /* if (pixel component has exceeded an allowed epsilon) */ 763 764 #undef EPSILON 765 } 766 } /* for (all pixels) */ 767 } /* for (all rows) */ 768 } /* for (all layers) */ 769 } /* for (all clear call types) */ 770 771 /* Done */ 772 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 773 return STOP; 774 775 #undef TEXTURE_DEPTH 776 #undef TEXTURE_HEIGHT 777 #undef TEXTURE_WIDTH 778 } 779 780 /** Deinitializes GLES objects created during the test. */ 781 void GeometryShaderLayeredFramebufferClear::deinit(void) 782 { 783 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 784 785 if (m_fbo_char_id != 0) 786 { 787 gl.deleteFramebuffers(1, &m_fbo_char_id); 788 } 789 790 if (m_fbo_int_id != 0) 791 { 792 gl.deleteFramebuffers(1, &m_fbo_int_id); 793 } 794 795 if (m_fbo_uint_id != 0) 796 { 797 gl.deleteFramebuffers(1, &m_fbo_uint_id); 798 } 799 800 if (m_to_rgba32i_id != 0) 801 { 802 gl.deleteTextures(1, &m_to_rgba32i_id); 803 } 804 805 if (m_to_rgba32ui_id != 0) 806 { 807 gl.deleteTextures(1, &m_to_rgba32ui_id); 808 } 809 810 if (m_to_rgba8_id != 0) 811 { 812 gl.deleteTextures(1, &m_to_rgba8_id); 813 } 814 815 if (m_read_fbo_id != 0) 816 { 817 gl.deleteFramebuffers(1, &m_read_fbo_id); 818 } 819 820 /* Release base class */ 821 TestCaseBase::deinit(); 822 } 823 824 /** Constructor 825 * 826 * @param context Test context 827 * @param name Test case's name 828 * @param description Test case's desricption 829 **/ 830 GeometryShaderLayeredFramebufferDepth::GeometryShaderLayeredFramebufferDepth(Context& context, 831 const ExtParameters& extParams, 832 const char* name, const char* description) 833 : TestCaseBase(context, extParams, name, description) 834 , m_fbo_id(0) 835 , m_fs_id(0) 836 , m_gs_id(0) 837 , m_po_id(0) 838 , m_read_fbo_id(0) 839 , m_to_a_id(0) 840 , m_to_b_id(0) 841 , m_vao_id(0) 842 , m_vs_id(0) 843 { 844 /* Left blank on purpose */ 845 } 846 847 /** Deinitializes GLES objects created during the test. */ 848 void GeometryShaderLayeredFramebufferDepth::deinit(void) 849 { 850 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 851 852 /* Clean up */ 853 if (m_fbo_id != 0) 854 { 855 gl.deleteFramebuffers(1, &m_fbo_id); 856 } 857 858 if (m_fs_id != 0) 859 { 860 gl.deleteShader(m_fs_id); 861 } 862 863 if (m_gs_id != 0) 864 { 865 gl.deleteShader(m_gs_id); 866 } 867 868 if (m_po_id != 0) 869 { 870 gl.deleteProgram(m_po_id); 871 } 872 873 if (m_read_fbo_id != 0) 874 { 875 gl.deleteFramebuffers(1, &m_read_fbo_id); 876 } 877 878 if (m_to_a_id != 0) 879 { 880 gl.deleteTextures(1, &m_to_a_id); 881 } 882 883 if (m_to_b_id != 0) 884 { 885 gl.deleteTextures(1, &m_to_b_id); 886 } 887 888 if (m_vao_id != 0) 889 { 890 gl.deleteVertexArrays(1, &m_vao_id); 891 } 892 893 if (m_vs_id != 0) 894 { 895 gl.deleteShader(m_vs_id); 896 } 897 898 /* Release base class */ 899 TestCaseBase::deinit(); 900 } 901 902 /** Executes the test. 903 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 904 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 905 * Note the function throws exception should an error occur! 906 **/ 907 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferDepth::iterate(void) 908 { 909 /* General variables */ 910 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 911 unsigned int n = 0; 912 unsigned int x = 0; 913 unsigned int y = 0; 914 915 /* Test-wide definitions */ 916 #define N_TEXTURE_COMPONENTS (4) 917 #define TEXTURE_DEPTH (4) 918 #define TEXTURE_HEIGHT (4) 919 #define TEXTURE_WIDTH (4) 920 921 /* Fragment shader code */ 922 const char* fs_code = "${VERSION}\n" 923 "\n" 924 "precision highp float;\n" 925 "\n" 926 "out vec4 result;\n" 927 "\n" 928 "void main()\n" 929 "{\n" 930 " result = vec4(1.0);\n" 931 "}\n"; 932 933 const char* gs_code = "${VERSION}\n" 934 "${GEOMETRY_SHADER_REQUIRE}\n" 935 "\n" 936 "layout(points) in;\n" 937 "layout(triangle_strip, max_vertices=64) out;\n" 938 "\n" 939 "void main()\n" 940 "{\n" 941 " for (int n = 0; n < 4; ++n)\n" 942 " {\n" 943 " float depth = -1.0 + float(n) * 0.5;\n" 944 "\n" 945 " gl_Layer = n;\n" 946 " gl_Position = vec4(1, 1, depth, 1);\n" 947 " EmitVertex();\n" 948 "\n" 949 " gl_Layer = n;\n" 950 " gl_Position = vec4(1, -1, depth, 1);\n" 951 " EmitVertex();\n" 952 "\n" 953 " gl_Layer = n;\n" 954 " gl_Position = vec4(-1, 1, depth, 1);\n" 955 " EmitVertex();\n" 956 "\n" 957 " gl_Layer = n;\n" 958 " gl_Position = vec4(-1, -1, depth, 1);\n" 959 " EmitVertex();\n" 960 "\n" 961 " EndPrimitive();\n" 962 " }\n" 963 "}\n"; 964 965 /* This test should only run if EXT_geometry_shader is supported */ 966 if (!m_is_geometry_shader_extension_supported) 967 { 968 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 969 } 970 971 /* Set up texture objects we will be using for the test */ 972 gl.genTextures(1, &m_to_a_id); 973 gl.genTextures(1, &m_to_b_id); 974 975 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id); 976 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH); 977 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id); 978 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_DEPTH_COMPONENT32F, TEXTURE_WIDTH, TEXTURE_HEIGHT, 979 TEXTURE_DEPTH); 980 981 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture objects"); 982 983 /* Set up framebuffer object we will use for the test */ 984 gl.genFramebuffers(1, &m_fbo_id); 985 gl.genFramebuffers(1, &m_read_fbo_id); 986 987 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id); 988 989 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */); 990 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_to_b_id, 0 /* level */); 991 992 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object"); 993 994 if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 995 { 996 m_testCtx.getLog() << tcu::TestLog::Message 997 << "Draw framebuffer is incomplete: " << gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) 998 << tcu::TestLog::EndMessage; 999 1000 TCU_FAIL("Draw framebuffer is incomplete."); 1001 } 1002 1003 /* Set up shader objects */ 1004 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1005 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 1006 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1007 1008 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize shader objects"); 1009 1010 /* Set up program object */ 1011 m_po_id = gl.createProgram(); 1012 1013 if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */, 1014 &m_boilerplate_vs_code)) 1015 { 1016 TCU_FAIL("Could not build program object"); 1017 } 1018 1019 /* Set up vertex array object */ 1020 gl.genVertexArrays(1, &m_vao_id); 1021 gl.bindVertexArray(m_vao_id); 1022 1023 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind vertex array object"); 1024 1025 /* Clear the depth attachment before we continue */ 1026 gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */); 1027 gl.clearDepthf(0.5f); 1028 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1029 1030 GLU_EXPECT_NO_ERROR(gl.getError(), "Depth buffer clear operation failed"); 1031 1032 /* Render */ 1033 gl.useProgram(m_po_id); 1034 gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT); 1035 1036 gl.enable(GL_DEPTH_TEST); 1037 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 1038 1039 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed"); 1040 1041 /* Verify the output */ 1042 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id); 1043 1044 for (n = 0; n < TEXTURE_DEPTH; ++n) 1045 { 1046 unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 1047 unsigned char ref_color[4]; 1048 1049 /* Determine reference color */ 1050 if (n < 2) 1051 { 1052 memset(ref_color, 0xFF, sizeof(ref_color)); 1053 } 1054 else 1055 { 1056 memset(ref_color, 0, sizeof(ref_color)); 1057 } 1058 1059 /* Read the rendered layer data */ 1060 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n); 1061 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 1062 1063 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 1064 1065 /* Compare all pixels against the reference value */ 1066 for (y = 0; y < TEXTURE_HEIGHT; ++y) 1067 { 1068 const unsigned int pixel_size = N_TEXTURE_COMPONENTS; 1069 const unsigned int row_width = TEXTURE_WIDTH * pixel_size; 1070 const unsigned char* row_data = buffer + y * row_width; 1071 1072 for (x = 0; x < TEXTURE_WIDTH; ++x) 1073 { 1074 const unsigned char* result = row_data + x * pixel_size; 1075 1076 if (memcmp(result, ref_color, sizeof(ref_color)) != 0) 1077 { 1078 m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") " 1079 << "Reference value is different than the rendered data: " 1080 << "(" << (unsigned int)ref_color[0] << ", " << (unsigned int)ref_color[1] 1081 << ", " << (unsigned int)ref_color[2] << ", " << (unsigned int)ref_color[3] 1082 << ") vs " 1083 << "(" << (unsigned int)result[0] << ", " << (unsigned int)result[1] << ", " 1084 << (unsigned int)result[2] << ", " << (unsigned int)result[3] << ")." 1085 << tcu::TestLog::EndMessage; 1086 1087 TCU_FAIL("Rendered data mismatch"); 1088 } /* if (memcmp(row_data + x * pixel_size, ref_color, sizeof(ref_color) ) != 0)*/ 1089 } /* for (all pixels in a row) */ 1090 } /* for (all rows) */ 1091 } /* for (all layers) */ 1092 1093 /* Done */ 1094 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1095 return STOP; 1096 1097 #undef N_TEXTURE_COMPONENTS 1098 #undef TEXTURE_DEPTH 1099 #undef TEXTURE_HEIGHT 1100 #undef TEXTURE_WIDTH 1101 } 1102 1103 /** Constructor 1104 * 1105 * @param context Test context 1106 * @param name Test case's name 1107 * @param description Test case's desricption 1108 **/ 1109 GeometryShaderLayeredFramebufferStencil::GeometryShaderLayeredFramebufferStencil(Context& context, 1110 const ExtParameters& extParams, 1111 const char* name, 1112 const char* description) 1113 : TestCaseBase(context, extParams, name, description) 1114 , m_fbo_id(0) 1115 , m_fs_id(0) 1116 , m_gs_id(0) 1117 , m_po_id(0) 1118 , m_to_a_id(0) 1119 , m_to_b_id(0) 1120 , m_vao_id(0) 1121 , m_vs_id(0) 1122 { 1123 /* Left blank on purpose */ 1124 } 1125 1126 /** Deinitializes GLES objects created during the test. */ 1127 void GeometryShaderLayeredFramebufferStencil::deinit(void) 1128 { 1129 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1130 1131 /* Clean up */ 1132 if (m_fbo_id != 0) 1133 { 1134 gl.deleteFramebuffers(1, &m_fbo_id); 1135 } 1136 1137 if (m_fs_id != 0) 1138 { 1139 gl.deleteShader(m_fs_id); 1140 } 1141 1142 if (m_gs_id != 0) 1143 { 1144 gl.deleteShader(m_gs_id); 1145 } 1146 1147 if (m_po_id != 0) 1148 { 1149 gl.deleteProgram(m_po_id); 1150 } 1151 1152 if (m_to_a_id != 0) 1153 { 1154 gl.deleteTextures(1, &m_to_a_id); 1155 } 1156 1157 if (m_to_b_id != 0) 1158 { 1159 gl.deleteTextures(1, &m_to_b_id); 1160 } 1161 1162 if (m_vao_id != 0) 1163 { 1164 gl.deleteVertexArrays(1, &m_vao_id); 1165 } 1166 1167 if (m_vs_id != 0) 1168 { 1169 gl.deleteShader(m_vs_id); 1170 } 1171 1172 /* Release base class */ 1173 TestCaseBase::deinit(); 1174 } 1175 1176 /** Executes the test. 1177 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 1178 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 1179 * Note the function throws exception should an error occur! 1180 **/ 1181 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferStencil::iterate(void) 1182 { 1183 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1184 1185 /* Test-wide definitions */ 1186 #define N_TEXTURE_COMPONENTS (4) 1187 #define TEXTURE_DEPTH (4) 1188 #define TEXTURE_HEIGHT (4) 1189 #define TEXTURE_WIDTH (8) 1190 1191 /* Fragment shader code */ 1192 const char* fs_code = "${VERSION}\n" 1193 "\n" 1194 "precision highp float;\n" 1195 "\n" 1196 "out vec4 result;\n" 1197 "\n" 1198 "void main()\n" 1199 "{\n" 1200 " result = vec4(1, 1, 1, 1);\n" 1201 "}\n"; 1202 1203 /* Geometry shader code */ 1204 const char* gs_code = "${VERSION}\n" 1205 "${GEOMETRY_SHADER_REQUIRE}\n" 1206 "\n" 1207 "precision highp float;\n" 1208 "\n" 1209 "layout (points) in;\n" 1210 "layout (triangle_strip, max_vertices = 16) out;\n" 1211 "\n" 1212 "void main()\n" 1213 "{\n" 1214 " for (int n = 0; n < 4; ++n)\n" 1215 " {\n" 1216 " gl_Position = vec4(1, -1, 0, 1);\n" 1217 " gl_Layer = n;\n" 1218 " EmitVertex();\n" 1219 "\n" 1220 " gl_Position = vec4(1, 1, 0, 1);\n" 1221 " gl_Layer = n;\n" 1222 " EmitVertex();\n" 1223 "\n" 1224 " gl_Position = vec4(-1, -1, 0, 1);\n" 1225 " gl_Layer = n;\n" 1226 " EmitVertex();\n" 1227 "\n" 1228 " gl_Position = vec4(-1, 1, 0, 1);\n" 1229 " gl_Layer = n;\n" 1230 " EmitVertex();\n" 1231 "\n" 1232 " EndPrimitive();\n" 1233 " }\n" 1234 "\n" 1235 "}\n"; 1236 1237 /* General variables */ 1238 int n = 0; 1239 1240 unsigned char slice_null_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 1 /* byte per texel */] = { 0 }; 1241 unsigned char slice_1_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = { 0 }; 1242 unsigned char slice_2_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = { 0 }; 1243 unsigned char slice_3_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = { 0 }; 1244 unsigned char slice_4_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = { 0 }; 1245 1246 /* This test should only run if EXT_geometry_shader is supported */ 1247 if (!m_is_geometry_shader_extension_supported) 1248 { 1249 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 1250 } 1251 1252 /* Create shader & program objects */ 1253 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1254 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 1255 m_po_id = gl.createProgram(); 1256 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1257 1258 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader or program objects"); 1259 1260 /* Build test program object */ 1261 if (!buildProgram(m_po_id, m_fs_id, 1 /* parts */, &fs_code, m_gs_id, 1 /* parts */, &gs_code, m_vs_id, 1262 1 /* parts */, &m_boilerplate_vs_code)) 1263 { 1264 TCU_FAIL("Could not build test program object"); 1265 } 1266 1267 /* Generate and bind a vertex array object */ 1268 gl.genVertexArrays(1, &m_vao_id); 1269 gl.bindVertexArray(m_vao_id); 1270 1271 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create & bind a vertex array object."); 1272 1273 /* Configure slice data */ 1274 for (n = 0; n < TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */; ++n) 1275 { 1276 /* We are okay with depth data being filled with glitch, but need the stencil data to be 1277 * as per test spec. To keep code simple, we do not differentiate between floating-point and 1278 * stencil part. 1279 */ 1280 slice_1_data[n] = 2; 1281 slice_2_data[n] = 1; 1282 1283 /* Slices 3 and 4 should be filled with 0s */ 1284 slice_3_data[n] = 0; 1285 slice_4_data[n] = 0; 1286 } /* for (all pixels making up slices) */ 1287 1288 /* Set up texture objects */ 1289 gl.genTextures(1, &m_to_a_id); 1290 gl.genTextures(1, &m_to_b_id); 1291 1292 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id); 1293 gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, 1294 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 1295 1296 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, 1297 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data); 1298 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, 1299 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data); 1300 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, 1301 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data); 1302 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, 1303 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data); 1304 1305 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object A."); 1306 1307 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id); 1308 gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_DEPTH32F_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 1309 TEXTURE_DEPTH, 0 /* border */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); 1310 1311 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, 1312 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 1313 slice_1_data); 1314 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, 1315 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 1316 slice_2_data); 1317 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, 1318 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 1319 slice_3_data); 1320 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, 1321 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 1322 slice_4_data); 1323 1324 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object B."); 1325 1326 /* Set up depth tests */ 1327 gl.disable(GL_DEPTH_TEST); 1328 1329 /* Set up stencil tests */ 1330 gl.enable(GL_STENCIL_TEST); 1331 gl.stencilFunc(GL_LESS, 0, /* reference value */ 0xFFFFFFFF /* mask */); 1332 1333 /* Set up framebuffer objects */ 1334 gl.genFramebuffers(1, &m_fbo_id); 1335 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id); 1336 1337 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */); 1338 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_to_b_id, 0 /* level */); 1339 1340 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer."); 1341 1342 /* Issue the draw call. */ 1343 gl.useProgram(m_po_id); 1344 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 1345 1346 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed."); 1347 1348 /* Check the results */ 1349 for (n = 0; n < 4 /* layers */; ++n) 1350 { 1351 glw::GLenum fbo_completeness = GL_NONE; 1352 int m = 0; 1353 unsigned char ref_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = { 0 }; 1354 unsigned char result_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = { 0 }; 1355 int x = 0; 1356 int y = 0; 1357 1358 /* Configure the read framebuffer */ 1359 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id); 1360 1361 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n); 1362 gl.framebufferTexture(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0 /* texture */, 0 /* level */); 1363 1364 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer."); 1365 1366 /* Verify read framebuffer is considered complete */ 1367 fbo_completeness = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER); 1368 1369 if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE) 1370 { 1371 m_testCtx.getLog() << tcu::TestLog::Message << "Read FBO is incomplete: " 1372 << "[" << fbo_completeness << "]" << tcu::TestLog::EndMessage; 1373 1374 TCU_FAIL("Read FBO is incomplete."); 1375 } 1376 1377 /* Build reference data */ 1378 for (m = 0; m < TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS; ++m) 1379 { 1380 if (n < 2) 1381 { 1382 ref_data[m] = 255; 1383 } 1384 else 1385 { 1386 ref_data[m] = 0; 1387 } 1388 } /* for (all reference pixels) */ 1389 1390 /* Read the rendered data */ 1391 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result_data); 1392 1393 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed"); 1394 1395 for (y = 0; y < TEXTURE_HEIGHT; ++y) 1396 { 1397 int pixel_size = N_TEXTURE_COMPONENTS; 1398 int row_size = pixel_size * TEXTURE_WIDTH; 1399 unsigned char* ref_row = ref_data + y * row_size; 1400 unsigned char* result_row = result_data + y * row_size; 1401 1402 for (x = 0; x < TEXTURE_WIDTH; ++x) 1403 { 1404 if (memcmp(ref_row, result_row, pixel_size) != 0) 1405 { 1406 m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << "): Rendered data " 1407 << "(" << result_row[0] << ", " << result_row[1] << ", " << result_row[2] << ", " 1408 << result_row[3] << ")" 1409 << " is different from reference data " 1410 << "(" << ref_row[0] << ", " << ref_row[1] << ", " << ref_row[2] << ", " 1411 << ref_row[3] << ")" << tcu::TestLog::EndMessage; 1412 1413 TCU_FAIL("Data comparison failed"); 1414 } /* if (memcmp(ref_row, result_row, pixel_size) != 0) */ 1415 1416 ref_row += pixel_size; 1417 result_row += pixel_size; 1418 } /* for (all pixels in a row) */ 1419 } /* for (all pixels) */ 1420 } /* for (all layers) */ 1421 1422 /* Done */ 1423 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1424 return STOP; 1425 1426 #undef N_TEXTURE_COMPONENTS 1427 #undef TEXTURE_DEPTH 1428 #undef TEXTURE_HEIGHT 1429 #undef TEXTURE_WIDTH 1430 } 1431 1432 } // namespace glcts 1433