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 33namespace 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 **/ 41GeometryShaderLayeredFramebufferBlending::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. */ 59void 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 **/ 113tcu::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 **/ 382GeometryShaderLayeredFramebufferClear::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 **/ 402tcu::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 float clear_color_float[] = { 0.25f, 0.5f, 1.0f, 32.0f / 255.0f }; 578 const int clear_color_int[] = { 64, 128, 255, 32 }; 579 glw::GLuint fbo_id = 0; 580 int pixel_size = 0; 581 void* slice_1_data = NULL; 582 void* slice_2_data = NULL; 583 void* slice_3_data = NULL; 584 void* slice_4_data = NULL; 585 glw::GLenum to_format = GL_NONE; 586 glw::GLuint to_id = 0; 587 glw::GLenum to_type = GL_NONE; 588 589 switch (static_cast<_clear_type>(current_test)) 590 { 591 case CLEAR_BUFFERFV: 592 case CLEAR_PLAIN: 593 { 594 buffer = buffer_char; 595 fbo_id = m_fbo_char_id; 596 pixel_size = N_TEXTURE_COMPONENTS; 597 slice_1_data = slice_1_data_char; 598 slice_2_data = slice_2_data_char; 599 slice_3_data = slice_3_data_char; 600 slice_4_data = slice_4_data_char; 601 to_format = GL_RGBA; 602 to_id = m_to_rgba8_id; 603 to_type = GL_UNSIGNED_BYTE; 604 605 break; 606 } 607 608 case CLEAR_BUFFERIV: 609 { 610 buffer = (void*)buffer_int; 611 fbo_id = m_fbo_int_id; 612 pixel_size = N_TEXTURE_COMPONENTS * sizeof(int); 613 slice_1_data = slice_1_data_int; 614 slice_2_data = slice_2_data_int; 615 slice_3_data = slice_3_data_int; 616 slice_4_data = slice_4_data_int; 617 to_format = GL_RGBA_INTEGER; 618 to_id = m_to_rgba32i_id; 619 to_type = GL_INT; 620 621 break; 622 } 623 624 case CLEAR_BUFFERUIV: 625 { 626 buffer = (void*)buffer_uint; 627 fbo_id = m_fbo_uint_id; 628 pixel_size = N_TEXTURE_COMPONENTS * sizeof(unsigned int); 629 slice_1_data = slice_1_data_uint; 630 slice_2_data = slice_2_data_uint; 631 slice_3_data = slice_3_data_uint; 632 slice_4_data = slice_4_data_uint; 633 to_format = GL_RGBA_INTEGER; 634 to_id = m_to_rgba32ui_id; 635 to_type = GL_UNSIGNED_INT; 636 637 break; 638 } 639 640 default: 641 { 642 /* This location should never be reached */ 643 TCU_FAIL("Execution flow failure"); 644 } 645 } /* switch (current_test)*/ 646 647 /* Restore layer data just in case */ 648 gl.bindTexture(GL_TEXTURE_3D, to_id); 649 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH, 650 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_1_data); 651 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH, 652 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_2_data); 653 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH, 654 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_3_data); 655 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH, 656 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_4_data); 657 658 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D() call failed."); 659 660 /* Issue requested clear call */ 661 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id); 662 663 switch (current_test) 664 { 665 case CLEAR_PLAIN: 666 { 667 gl.clearColor(clear_color_float[0], clear_color_float[1], clear_color_float[2], clear_color_float[3]); 668 gl.clear(GL_COLOR_BUFFER_BIT); 669 670 break; 671 } 672 673 case CLEAR_BUFFERIV: 674 { 675 gl.clearBufferiv(GL_COLOR, 0 /* draw buffer index */, clear_color_int); 676 677 break; 678 } 679 680 case CLEAR_BUFFERUIV: 681 { 682 gl.clearBufferuiv(GL_COLOR, 0 /* draw buffer index */, (const glw::GLuint*)clear_color_int); 683 684 break; 685 } 686 687 case CLEAR_BUFFERFV: 688 { 689 gl.clearBufferfv(GL_COLOR, 0 /* draw buffer index */, clear_color_float); 690 691 break; 692 } 693 694 default: 695 { 696 /* This location should never be reached */ 697 TCU_FAIL("Execution flow failure"); 698 } 699 } /* switch (current_test) */ 700 701 /* Make sure no error was generated */ 702 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear call failed."); 703 704 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id); 705 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create read framebuffer object!"); 706 707 /* Check the layer data after a clear call */ 708 for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer) 709 { 710 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */, n_layer); 711 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, to_format, to_type, buffer); 712 713 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 714 715 /* If we requested an integer clear, the pixels we obtained should be reset to specific values. 716 * If we asked for a FP-based clear, consider an epsilon. */ 717 for (y = 0; y < TEXTURE_HEIGHT; ++y) 718 { 719 const int row_size = TEXTURE_WIDTH * pixel_size; 720 unsigned char* row = (unsigned char*)buffer + y * row_size; 721 722 for (x = 0; x < TEXTURE_WIDTH; ++x) 723 { 724 if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV) 725 { 726 unsigned int* pixel = (unsigned int*)(row + x * pixel_size); 727 if (memcmp(pixel, clear_color_int, sizeof(clear_color_int)) != 0) 728 { 729 /* Test fails at this point */ 730 m_testCtx.getLog() 731 << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel [" 732 << clear_color_int[0] << ", " << clear_color_int[1] << ", " << clear_color_int[2] 733 << ", " << clear_color_int[3] << "] is different from the one retrieved [" 734 << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", " 735 << (int)pixel[3] << "]" << tcu::TestLog::EndMessage; 736 737 TCU_FAIL("Data comparison failure"); 738 } /* if (memcmp(pixel, clear_color_int, sizeof(clear_color_int) ) != 0) */ 739 } /* if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV) */ 740 else 741 { 742#define EPSILON (1) 743 744 unsigned char* pixel = (unsigned char*)(row + x * pixel_size); 745 746 if (de::abs((int)pixel[0] - clear_color_int[0]) > EPSILON || 747 de::abs((int)pixel[1] - clear_color_int[1]) > EPSILON || 748 de::abs((int)pixel[2] - clear_color_int[2]) > EPSILON || 749 de::abs((int)pixel[3] - clear_color_int[3]) > EPSILON) 750 { 751 /* Test fails at this point */ 752 m_testCtx.getLog() 753 << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel [" 754 << clear_color_int[0] << ", " << clear_color_int[1] << ", " << clear_color_int[2] 755 << ", " << clear_color_int[3] << "] is different from the one retrieved [" 756 << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", " 757 << (int)pixel[3] << "]" << tcu::TestLog::EndMessage; 758 759 TCU_FAIL("Data comparison failure"); 760 } /* if (pixel component has exceeded an allowed epsilon) */ 761 762#undef EPSILON 763 } 764 } /* for (all pixels) */ 765 } /* for (all rows) */ 766 } /* for (all layers) */ 767 } /* for (all clear call types) */ 768 769 /* Done */ 770 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 771 return STOP; 772 773#undef TEXTURE_DEPTH 774#undef TEXTURE_HEIGHT 775#undef TEXTURE_WIDTH 776} 777 778/** Deinitializes GLES objects created during the test. */ 779void GeometryShaderLayeredFramebufferClear::deinit(void) 780{ 781 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 782 783 if (m_fbo_char_id != 0) 784 { 785 gl.deleteFramebuffers(1, &m_fbo_char_id); 786 } 787 788 if (m_fbo_int_id != 0) 789 { 790 gl.deleteFramebuffers(1, &m_fbo_int_id); 791 } 792 793 if (m_fbo_uint_id != 0) 794 { 795 gl.deleteFramebuffers(1, &m_fbo_uint_id); 796 } 797 798 if (m_to_rgba32i_id != 0) 799 { 800 gl.deleteTextures(1, &m_to_rgba32i_id); 801 } 802 803 if (m_to_rgba32ui_id != 0) 804 { 805 gl.deleteTextures(1, &m_to_rgba32ui_id); 806 } 807 808 if (m_to_rgba8_id != 0) 809 { 810 gl.deleteTextures(1, &m_to_rgba8_id); 811 } 812 813 if (m_read_fbo_id != 0) 814 { 815 gl.deleteFramebuffers(1, &m_read_fbo_id); 816 } 817 818 /* Release base class */ 819 TestCaseBase::deinit(); 820} 821 822/** Constructor 823 * 824 * @param context Test context 825 * @param name Test case's name 826 * @param description Test case's desricption 827 **/ 828GeometryShaderLayeredFramebufferDepth::GeometryShaderLayeredFramebufferDepth(Context& context, 829 const ExtParameters& extParams, 830 const char* name, const char* description) 831 : TestCaseBase(context, extParams, name, description) 832 , m_fbo_id(0) 833 , m_fs_id(0) 834 , m_gs_id(0) 835 , m_po_id(0) 836 , m_read_fbo_id(0) 837 , m_to_a_id(0) 838 , m_to_b_id(0) 839 , m_vao_id(0) 840 , m_vs_id(0) 841{ 842 /* Left blank on purpose */ 843} 844 845/** Deinitializes GLES objects created during the test. */ 846void GeometryShaderLayeredFramebufferDepth::deinit(void) 847{ 848 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 849 850 /* Clean up */ 851 if (m_fbo_id != 0) 852 { 853 gl.deleteFramebuffers(1, &m_fbo_id); 854 } 855 856 if (m_fs_id != 0) 857 { 858 gl.deleteShader(m_fs_id); 859 } 860 861 if (m_gs_id != 0) 862 { 863 gl.deleteShader(m_gs_id); 864 } 865 866 if (m_po_id != 0) 867 { 868 gl.deleteProgram(m_po_id); 869 } 870 871 if (m_read_fbo_id != 0) 872 { 873 gl.deleteFramebuffers(1, &m_read_fbo_id); 874 } 875 876 if (m_to_a_id != 0) 877 { 878 gl.deleteTextures(1, &m_to_a_id); 879 } 880 881 if (m_to_b_id != 0) 882 { 883 gl.deleteTextures(1, &m_to_b_id); 884 } 885 886 if (m_vao_id != 0) 887 { 888 gl.deleteVertexArrays(1, &m_vao_id); 889 } 890 891 if (m_vs_id != 0) 892 { 893 gl.deleteShader(m_vs_id); 894 } 895 896 /* Release base class */ 897 TestCaseBase::deinit(); 898} 899 900/** Executes the test. 901 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 902 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 903 * Note the function throws exception should an error occur! 904 **/ 905tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferDepth::iterate(void) 906{ 907 /* General variables */ 908 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 909 unsigned int n = 0; 910 unsigned int x = 0; 911 unsigned int y = 0; 912 913/* Test-wide definitions */ 914#define N_TEXTURE_COMPONENTS (4) 915#define TEXTURE_DEPTH (4) 916#define TEXTURE_HEIGHT (4) 917#define TEXTURE_WIDTH (4) 918 919 /* Fragment shader code */ 920 const char* fs_code = "${VERSION}\n" 921 "\n" 922 "precision highp float;\n" 923 "\n" 924 "out vec4 result;\n" 925 "\n" 926 "void main()\n" 927 "{\n" 928 " result = vec4(1.0);\n" 929 "}\n"; 930 931 const char* gs_code = "${VERSION}\n" 932 "${GEOMETRY_SHADER_REQUIRE}\n" 933 "\n" 934 "layout(points) in;\n" 935 "layout(triangle_strip, max_vertices=64) out;\n" 936 "\n" 937 "void main()\n" 938 "{\n" 939 " for (int n = 0; n < 4; ++n)\n" 940 " {\n" 941 " float depth = -1.0 + float(n) * 0.5;\n" 942 "\n" 943 " gl_Layer = n;\n" 944 " gl_Position = vec4(1, 1, depth, 1);\n" 945 " EmitVertex();\n" 946 "\n" 947 " gl_Layer = n;\n" 948 " gl_Position = vec4(1, -1, depth, 1);\n" 949 " EmitVertex();\n" 950 "\n" 951 " gl_Layer = n;\n" 952 " gl_Position = vec4(-1, 1, depth, 1);\n" 953 " EmitVertex();\n" 954 "\n" 955 " gl_Layer = n;\n" 956 " gl_Position = vec4(-1, -1, depth, 1);\n" 957 " EmitVertex();\n" 958 "\n" 959 " EndPrimitive();\n" 960 " }\n" 961 "}\n"; 962 963 /* This test should only run if EXT_geometry_shader is supported */ 964 if (!m_is_geometry_shader_extension_supported) 965 { 966 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 967 } 968 969 /* Set up texture objects we will be using for the test */ 970 gl.genTextures(1, &m_to_a_id); 971 gl.genTextures(1, &m_to_b_id); 972 973 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id); 974 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH); 975 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id); 976 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_DEPTH_COMPONENT32F, TEXTURE_WIDTH, TEXTURE_HEIGHT, 977 TEXTURE_DEPTH); 978 979 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture objects"); 980 981 /* Set up framebuffer object we will use for the test */ 982 gl.genFramebuffers(1, &m_fbo_id); 983 gl.genFramebuffers(1, &m_read_fbo_id); 984 985 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id); 986 987 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */); 988 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_to_b_id, 0 /* level */); 989 990 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object"); 991 992 if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 993 { 994 m_testCtx.getLog() << tcu::TestLog::Message 995 << "Draw framebuffer is incomplete: " << gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) 996 << tcu::TestLog::EndMessage; 997 998 TCU_FAIL("Draw framebuffer is incomplete."); 999 } 1000 1001 /* Set up shader objects */ 1002 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1003 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 1004 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1005 1006 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize shader objects"); 1007 1008 /* Set up program object */ 1009 m_po_id = gl.createProgram(); 1010 1011 if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */, 1012 &m_boilerplate_vs_code)) 1013 { 1014 TCU_FAIL("Could not build program object"); 1015 } 1016 1017 /* Set up vertex array object */ 1018 gl.genVertexArrays(1, &m_vao_id); 1019 gl.bindVertexArray(m_vao_id); 1020 1021 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind vertex array object"); 1022 1023 /* Clear the depth attachment before we continue */ 1024 gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */); 1025 gl.clearDepthf(0.5f); 1026 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1027 1028 GLU_EXPECT_NO_ERROR(gl.getError(), "Depth buffer clear operation failed"); 1029 1030 /* Render */ 1031 gl.useProgram(m_po_id); 1032 gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT); 1033 1034 gl.enable(GL_DEPTH_TEST); 1035 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 1036 1037 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed"); 1038 1039 /* Verify the output */ 1040 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id); 1041 1042 for (n = 0; n < TEXTURE_DEPTH; ++n) 1043 { 1044 unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]; 1045 unsigned char ref_color[4]; 1046 1047 /* Determine reference color */ 1048 if (n < 2) 1049 { 1050 memset(ref_color, 0xFF, sizeof(ref_color)); 1051 } 1052 else 1053 { 1054 memset(ref_color, 0, sizeof(ref_color)); 1055 } 1056 1057 /* Read the rendered layer data */ 1058 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n); 1059 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 1060 1061 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed"); 1062 1063 /* Compare all pixels against the reference value */ 1064 for (y = 0; y < TEXTURE_HEIGHT; ++y) 1065 { 1066 const unsigned int pixel_size = N_TEXTURE_COMPONENTS; 1067 const unsigned int row_width = TEXTURE_WIDTH * pixel_size; 1068 const unsigned char* row_data = buffer + y * row_width; 1069 1070 for (x = 0; x < TEXTURE_WIDTH; ++x) 1071 { 1072 const unsigned char* result = row_data + x * pixel_size; 1073 1074 if (memcmp(result, ref_color, sizeof(ref_color)) != 0) 1075 { 1076 m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") " 1077 << "Reference value is different than the rendered data: " 1078 << "(" << (unsigned int)ref_color[0] << ", " << (unsigned int)ref_color[1] 1079 << ", " << (unsigned int)ref_color[2] << ", " << (unsigned int)ref_color[3] 1080 << ") vs " 1081 << "(" << (unsigned int)result[0] << ", " << (unsigned int)result[1] << ", " 1082 << (unsigned int)result[2] << ", " << (unsigned int)result[3] << ")." 1083 << tcu::TestLog::EndMessage; 1084 1085 TCU_FAIL("Rendered data mismatch"); 1086 } /* if (memcmp(row_data + x * pixel_size, ref_color, sizeof(ref_color) ) != 0)*/ 1087 } /* for (all pixels in a row) */ 1088 } /* for (all rows) */ 1089 } /* for (all layers) */ 1090 1091 /* Done */ 1092 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1093 return STOP; 1094 1095#undef N_TEXTURE_COMPONENTS 1096#undef TEXTURE_DEPTH 1097#undef TEXTURE_HEIGHT 1098#undef TEXTURE_WIDTH 1099} 1100 1101/** Constructor 1102 * 1103 * @param context Test context 1104 * @param name Test case's name 1105 * @param description Test case's desricption 1106 **/ 1107GeometryShaderLayeredFramebufferStencil::GeometryShaderLayeredFramebufferStencil(Context& context, 1108 const ExtParameters& extParams, 1109 const char* name, 1110 const char* description) 1111 : TestCaseBase(context, extParams, name, description) 1112 , m_fbo_id(0) 1113 , m_fs_id(0) 1114 , m_gs_id(0) 1115 , m_po_id(0) 1116 , m_to_a_id(0) 1117 , m_to_b_id(0) 1118 , m_vao_id(0) 1119 , m_vs_id(0) 1120{ 1121 /* Left blank on purpose */ 1122} 1123 1124/** Deinitializes GLES objects created during the test. */ 1125void GeometryShaderLayeredFramebufferStencil::deinit(void) 1126{ 1127 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1128 1129 /* Clean up */ 1130 if (m_fbo_id != 0) 1131 { 1132 gl.deleteFramebuffers(1, &m_fbo_id); 1133 } 1134 1135 if (m_fs_id != 0) 1136 { 1137 gl.deleteShader(m_fs_id); 1138 } 1139 1140 if (m_gs_id != 0) 1141 { 1142 gl.deleteShader(m_gs_id); 1143 } 1144 1145 if (m_po_id != 0) 1146 { 1147 gl.deleteProgram(m_po_id); 1148 } 1149 1150 if (m_to_a_id != 0) 1151 { 1152 gl.deleteTextures(1, &m_to_a_id); 1153 } 1154 1155 if (m_to_b_id != 0) 1156 { 1157 gl.deleteTextures(1, &m_to_b_id); 1158 } 1159 1160 if (m_vao_id != 0) 1161 { 1162 gl.deleteVertexArrays(1, &m_vao_id); 1163 } 1164 1165 if (m_vs_id != 0) 1166 { 1167 gl.deleteShader(m_vs_id); 1168 } 1169 1170 /* Release base class */ 1171 TestCaseBase::deinit(); 1172} 1173 1174/** Executes the test. 1175 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 1176 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 1177 * Note the function throws exception should an error occur! 1178 **/ 1179tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferStencil::iterate(void) 1180{ 1181 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1182 1183/* Test-wide definitions */ 1184#define N_TEXTURE_COMPONENTS (4) 1185#define TEXTURE_DEPTH (4) 1186#define TEXTURE_HEIGHT (4) 1187#define TEXTURE_WIDTH (8) 1188 1189 /* Fragment shader code */ 1190 const char* fs_code = "${VERSION}\n" 1191 "\n" 1192 "precision highp float;\n" 1193 "\n" 1194 "out vec4 result;\n" 1195 "\n" 1196 "void main()\n" 1197 "{\n" 1198 " result = vec4(1, 1, 1, 1);\n" 1199 "}\n"; 1200 1201 /* Geometry shader code */ 1202 const char* gs_code = "${VERSION}\n" 1203 "${GEOMETRY_SHADER_REQUIRE}\n" 1204 "\n" 1205 "precision highp float;\n" 1206 "\n" 1207 "layout (points) in;\n" 1208 "layout (triangle_strip, max_vertices = 16) out;\n" 1209 "\n" 1210 "void main()\n" 1211 "{\n" 1212 " for (int n = 0; n < 4; ++n)\n" 1213 " {\n" 1214 " gl_Position = vec4(1, -1, 0, 1);\n" 1215 " gl_Layer = n;\n" 1216 " EmitVertex();\n" 1217 "\n" 1218 " gl_Position = vec4(1, 1, 0, 1);\n" 1219 " gl_Layer = n;\n" 1220 " EmitVertex();\n" 1221 "\n" 1222 " gl_Position = vec4(-1, -1, 0, 1);\n" 1223 " gl_Layer = n;\n" 1224 " EmitVertex();\n" 1225 "\n" 1226 " gl_Position = vec4(-1, 1, 0, 1);\n" 1227 " gl_Layer = n;\n" 1228 " EmitVertex();\n" 1229 "\n" 1230 " EndPrimitive();\n" 1231 " }\n" 1232 "\n" 1233 "}\n"; 1234 1235 /* General variables */ 1236 int n = 0; 1237 1238 unsigned char slice_null_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 1 /* byte per texel */] = { 0 }; 1239 unsigned char slice_1_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = { 0 }; 1240 unsigned char slice_2_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = { 0 }; 1241 unsigned char slice_3_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = { 0 }; 1242 unsigned char slice_4_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = { 0 }; 1243 1244 /* This test should only run if EXT_geometry_shader is supported */ 1245 if (!m_is_geometry_shader_extension_supported) 1246 { 1247 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 1248 } 1249 1250 /* Create shader & program objects */ 1251 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 1252 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 1253 m_po_id = gl.createProgram(); 1254 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 1255 1256 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader or program objects"); 1257 1258 /* Build test program object */ 1259 if (!buildProgram(m_po_id, m_fs_id, 1 /* parts */, &fs_code, m_gs_id, 1 /* parts */, &gs_code, m_vs_id, 1260 1 /* parts */, &m_boilerplate_vs_code)) 1261 { 1262 TCU_FAIL("Could not build test program object"); 1263 } 1264 1265 /* Generate and bind a vertex array object */ 1266 gl.genVertexArrays(1, &m_vao_id); 1267 gl.bindVertexArray(m_vao_id); 1268 1269 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create & bind a vertex array object."); 1270 1271 /* Configure slice data */ 1272 for (n = 0; n < TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */; ++n) 1273 { 1274 /* We are okay with depth data being filled with glitch, but need the stencil data to be 1275 * as per test spec. To keep code simple, we do not differentiate between floating-point and 1276 * stencil part. 1277 */ 1278 slice_1_data[n] = 2; 1279 slice_2_data[n] = 1; 1280 1281 /* Slices 3 and 4 should be filled with 0s */ 1282 slice_3_data[n] = 0; 1283 slice_4_data[n] = 0; 1284 } /* for (all pixels making up slices) */ 1285 1286 /* Set up texture objects */ 1287 gl.genTextures(1, &m_to_a_id); 1288 gl.genTextures(1, &m_to_b_id); 1289 1290 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id); 1291 gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, 1292 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 1293 1294 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, 1295 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data); 1296 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* 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 */, 2 /* 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 */, 3 /* zoffset */, 1301 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data); 1302 1303 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object A."); 1304 1305 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id); 1306 gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_DEPTH32F_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 1307 TEXTURE_DEPTH, 0 /* border */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); 1308 1309 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, 1310 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 1311 slice_1_data); 1312 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, 1313 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 1314 slice_2_data); 1315 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, 1316 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 1317 slice_3_data); 1318 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, 1319 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 1320 slice_4_data); 1321 1322 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object B."); 1323 1324 /* Set up depth tests */ 1325 gl.disable(GL_DEPTH_TEST); 1326 1327 /* Set up stencil tests */ 1328 gl.enable(GL_STENCIL_TEST); 1329 gl.stencilFunc(GL_LESS, 0, /* reference value */ 0xFFFFFFFF /* mask */); 1330 1331 /* Set up framebuffer objects */ 1332 gl.genFramebuffers(1, &m_fbo_id); 1333 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id); 1334 1335 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */); 1336 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_to_b_id, 0 /* level */); 1337 1338 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer."); 1339 1340 /* Issue the draw call. */ 1341 gl.useProgram(m_po_id); 1342 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 1343 1344 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed."); 1345 1346 /* Check the results */ 1347 for (n = 0; n < 4 /* layers */; ++n) 1348 { 1349 glw::GLenum fbo_completeness = GL_NONE; 1350 int m = 0; 1351 unsigned char ref_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = { 0 }; 1352 unsigned char result_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = { 0 }; 1353 int x = 0; 1354 int y = 0; 1355 1356 /* Configure the read framebuffer */ 1357 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id); 1358 1359 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n); 1360 gl.framebufferTexture(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0 /* texture */, 0 /* level */); 1361 1362 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer."); 1363 1364 /* Verify read framebuffer is considered complete */ 1365 fbo_completeness = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER); 1366 1367 if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE) 1368 { 1369 m_testCtx.getLog() << tcu::TestLog::Message << "Read FBO is incomplete: " 1370 << "[" << fbo_completeness << "]" << tcu::TestLog::EndMessage; 1371 1372 TCU_FAIL("Read FBO is incomplete."); 1373 } 1374 1375 /* Build reference data */ 1376 for (m = 0; m < TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS; ++m) 1377 { 1378 if (n < 2) 1379 { 1380 ref_data[m] = 255; 1381 } 1382 else 1383 { 1384 ref_data[m] = 0; 1385 } 1386 } /* for (all reference pixels) */ 1387 1388 /* Read the rendered data */ 1389 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result_data); 1390 1391 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed"); 1392 1393 for (y = 0; y < TEXTURE_HEIGHT; ++y) 1394 { 1395 int pixel_size = N_TEXTURE_COMPONENTS; 1396 int row_size = pixel_size * TEXTURE_WIDTH; 1397 unsigned char* ref_row = ref_data + y * row_size; 1398 unsigned char* result_row = result_data + y * row_size; 1399 1400 for (x = 0; x < TEXTURE_WIDTH; ++x) 1401 { 1402 if (memcmp(ref_row, result_row, pixel_size) != 0) 1403 { 1404 m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << "): Rendered data " 1405 << "(" << result_row[0] << ", " << result_row[1] << ", " << result_row[2] << ", " 1406 << result_row[3] << ")" 1407 << " is different from reference data " 1408 << "(" << ref_row[0] << ", " << ref_row[1] << ", " << ref_row[2] << ", " 1409 << ref_row[3] << ")" << tcu::TestLog::EndMessage; 1410 1411 TCU_FAIL("Data comparison failed"); 1412 } /* if (memcmp(ref_row, result_row, pixel_size) != 0) */ 1413 1414 ref_row += pixel_size; 1415 result_row += pixel_size; 1416 } /* for (all pixels in a row) */ 1417 } /* for (all pixels) */ 1418 } /* for (all layers) */ 1419 1420 /* Done */ 1421 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1422 return STOP; 1423 1424#undef N_TEXTURE_COMPONENTS 1425#undef TEXTURE_DEPTH 1426#undef TEXTURE_HEIGHT 1427#undef TEXTURE_WIDTH 1428} 1429 1430} // namespace glcts 1431