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 "esextcGeometryShaderLayeredRendering.hpp" 25 26 #include "gluContextInfo.hpp" 27 #include "gluDefs.hpp" 28 #include "glwEnums.hpp" 29 #include "glwFunctions.hpp" 30 #include "tcuTestLog.hpp" 31 32 #include <algorithm> 33 #include <cstring> 34 #include <string> 35 #include <vector> 36 37 namespace glcts 38 { 39 /* Array holding vector values describing contents of layers 40 * at subsequent indices. 41 * 42 * Contents of this array are directly related to layered_rendering_fs_code. 43 **/ 44 const unsigned char GeometryShaderLayeredRendering::m_layered_rendering_expected_layer_data[6 * 4] = { 45 /* Layer 0 */ 46 255, 0, 0, 0, 47 /* Layer 1 */ 48 0, 255, 0, 0, 49 /* Layer 2 */ 50 0, 0, 255, 0, 51 /* Layer 3 */ 52 0, 0, 0, 255, 53 /* Layer 4 */ 54 255, 255, 0, 0, 55 /* Layer 5 */ 56 255, 0, 255, 0 57 }; 58 59 /* Fragment shader code */ 60 const char* GeometryShaderLayeredRendering::m_layered_rendering_fs_code = 61 "${VERSION}\n" 62 "\n" 63 "precision highp float;\n" 64 "\n" 65 "flat in int layer_id;\n" 66 " out vec4 color;\n" 67 "\n" 68 "void main()\n" 69 "{\n" 70 " switch (layer_id)\n" 71 " {\n" 72 " case 0: color = vec4(1, 0, 0, 0); break;\n" 73 " case 1: color = vec4(0, 1, 0, 0); break;\n" 74 " case 2: color = vec4(0, 0, 1, 0); break;\n" 75 " case 3: color = vec4(0, 0, 0, 1); break;\n" 76 " case 4: color = vec4(1, 1, 0, 0); break;\n" 77 " case 5: color = vec4(1, 0, 1, 0); break;\n" 78 " default: color = vec4(1, 1, 1, 1); break;\n" 79 " }\n" 80 "}\n"; 81 82 /* Geometry shader code parts */ 83 const char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_preamble = "${VERSION}\n" 84 "${GEOMETRY_SHADER_REQUIRE}\n" 85 "\n"; 86 87 const char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_2d_array = "#define MAX_VERTICES 64\n" 88 "#define N_LAYERS 4\n"; 89 90 const char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_2d_marray = "#define MAX_VERTICES 64\n" 91 "#define N_LAYERS 4\n"; 92 93 const char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_3d = "#define MAX_VERTICES 64\n" 94 "#define N_LAYERS 4\n"; 95 96 const char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_cm = "#define MAX_VERTICES 96\n" 97 "#define N_LAYERS 6\n"; 98 99 /* NOTE: provoking_vertex_index holds an integer value which represents platform-reported 100 * GL_LAYER_PROVOKING_VERTEX_EXT value. The meaning is as follows: 101 * 102 * 0: Property carries a GL_UNDEFINED_VERTEX_EXT value. Need to set gl_Layer for all 103 * vertices. 104 * 1: Property carries a GL_FIRST_VERTEX_CONVENTION_EXT value. Need to set gl_Layer for 105 * the first two vertices, since these are a part of the two triangles, emitted 106 * separately for each layer. 107 * 2: Property carries a GL_LAST_VERTEX_CONVENTION_EXT value. Need to set gl_Layer for 108 * the last two vertices, since these are a part of the two triangles, emitted 109 * separately for each layer. 110 */ 111 const char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_main = 112 "layout(points) in;\n" 113 "layout(triangle_strip, max_vertices=MAX_VERTICES) out;\n" 114 "\n" 115 "precision highp float;\n" 116 "\n" 117 "flat out int layer_id;\n" 118 "uniform int provoking_vertex_index;\n" 119 "\n" 120 "void main()\n" 121 "{\n" 122 " for (int n = 0; n < N_LAYERS; ++n)\n" 123 " {\n" 124 " #ifndef SHOULD_NOT_SET_GL_LAYER\n" 125 " if (provoking_vertex_index == 0 || provoking_vertex_index == 1) gl_Layer = n;\n" 126 " #endif\n" 127 "\n" 128 " layer_id = gl_Layer;\n" 129 " gl_Position = vec4(1, 1, 0, 1);\n" 130 " EmitVertex();\n" 131 "\n" 132 " #ifndef SHOULD_NOT_SET_GL_LAYER\n" 133 " if (provoking_vertex_index == 0 || provoking_vertex_index == 1) gl_Layer = n;\n" 134 " #endif\n" 135 "\n" 136 " layer_id = gl_Layer;\n" 137 " gl_Position = vec4(1, -1, 0, 1);\n" 138 " EmitVertex();\n" 139 "\n" 140 " #ifndef SHOULD_NOT_SET_GL_LAYER\n" 141 " if (provoking_vertex_index == 0 || provoking_vertex_index == 2) gl_Layer = n;\n" 142 " #endif\n" 143 "\n" 144 " layer_id = gl_Layer;\n" 145 " gl_Position = vec4(-1, 1, 0, 1);\n" 146 " EmitVertex();\n" 147 "\n" 148 " #ifndef SHOULD_NOT_SET_GL_LAYER\n" 149 " gl_Layer = n;\n" 150 " #endif\n" 151 "\n" 152 " layer_id = gl_Layer;\n" 153 " gl_Position = vec4(-1, -1, 0, 1);\n" 154 " EmitVertex();\n" 155 "\n" 156 " EndPrimitive();\n" 157 " }\n" 158 "}\n"; 159 160 /* Vertex shader */ 161 const char* GeometryShaderLayeredRendering::m_layered_rendering_vs_code = "${VERSION}\n" 162 "\n" 163 "precision highp float;\n" 164 "\n" 165 "flat out int layer_id;\n" 166 "void main()\n" 167 "{\n" 168 " layer_id = 0;\n" 169 "}\n"; 170 171 /* Constants used for various test iterations */ 172 #define TEXTURE_DEPTH (64) 173 #define TEXTURE_HEIGHT (32) 174 #define TEXTURE_N_COMPONENTS (4) 175 #define TEXTURE_WIDTH (32) 176 177 /* Constructor */ 178 GeometryShaderLayeredRendering::GeometryShaderLayeredRendering(Context& context, const ExtParameters& extParams, 179 const char* name, const char* description) 180 : TestCaseBase(context, extParams, name, description), m_vao_id(0) 181 { 182 memset(m_tests, 0, sizeof(m_tests)); 183 } 184 185 /** Builds a GL program specifically for a layer rendering test instance. 186 * 187 * @param test Layered Rendering test to consider. 188 * 189 * @return GTFtrue if successful, false otherwise. 190 **/ 191 bool GeometryShaderLayeredRendering::buildProgramForLRTest(_layered_rendering_test* test) 192 { 193 return buildProgram(test->po_id, test->fs_id, test->n_fs_parts, test->fs_parts, test->gs_id, test->n_gs_parts, 194 test->gs_parts, test->vs_id, test->n_vs_parts, test->vs_parts); 195 } 196 197 /** Executes the test. 198 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 199 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 200 * Note the function throws exception should an error occur! 201 **/ 202 tcu::TestNode::IterateResult GeometryShaderLayeredRendering::iterate(void) 203 { 204 const glu::ContextType& context_type = m_context.getRenderContext().getType(); 205 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 206 207 /* Helper variables to support shader compilation process */ 208 const char* cm_fs_parts[] = { m_layered_rendering_fs_code }; 209 const char* cm_gs_parts[] = { m_layered_rendering_gs_code_preamble, m_layered_rendering_gs_code_cm, 210 m_layered_rendering_gs_code_main }; 211 const char* cm_vs_parts[] = { m_layered_rendering_vs_code }; 212 const char* threedimensional_fs_parts[] = { m_layered_rendering_fs_code }; 213 const char* threedimensional_gs_parts[] = { m_layered_rendering_gs_code_preamble, m_layered_rendering_gs_code_3d, 214 m_layered_rendering_gs_code_main }; 215 const char* threedimensional_vs_parts[] = { m_layered_rendering_vs_code }; 216 const char* twodimensionala_fs_parts[] = { m_layered_rendering_fs_code }; 217 const char* twodimensionala_gs_parts[] = { m_layered_rendering_gs_code_preamble, 218 m_layered_rendering_gs_code_2d_array, m_layered_rendering_gs_code_main }; 219 const char* twodimensionala_vs_parts[] = { m_layered_rendering_vs_code }; 220 const char* twodimensionalma_fs_parts[] = { m_layered_rendering_fs_code }; 221 const char* twodimensionalma_gs_parts[] = { m_layered_rendering_gs_code_preamble, 222 m_layered_rendering_gs_code_2d_marray, 223 m_layered_rendering_gs_code_main }; 224 const char* twodimensionalma_vs_parts[] = { m_layered_rendering_vs_code }; 225 const unsigned int n_cm_fs_parts = sizeof(cm_fs_parts) / sizeof(cm_fs_parts[0]); 226 const unsigned int n_cm_gs_parts = sizeof(cm_gs_parts) / sizeof(cm_gs_parts[0]); 227 const unsigned int n_cm_vs_parts = sizeof(cm_vs_parts) / sizeof(cm_vs_parts[0]); 228 const unsigned int n_threedimensional_fs_parts = 229 sizeof(threedimensional_fs_parts) / sizeof(threedimensional_fs_parts[0]); 230 const unsigned int n_threedimensional_gs_parts = 231 sizeof(threedimensional_gs_parts) / sizeof(threedimensional_gs_parts[0]); 232 const unsigned int n_threedimensional_vs_parts = 233 sizeof(threedimensional_vs_parts) / sizeof(threedimensional_vs_parts[0]); 234 const unsigned int n_twodimensionala_fs_parts = 235 sizeof(twodimensionala_fs_parts) / sizeof(twodimensionala_fs_parts[0]); 236 const unsigned int n_twodimensionala_gs_parts = 237 sizeof(twodimensionala_gs_parts) / sizeof(twodimensionala_gs_parts[0]); 238 const unsigned int n_twodimensionala_vs_parts = 239 sizeof(twodimensionala_vs_parts) / sizeof(twodimensionala_vs_parts[0]); 240 const unsigned int n_twodimensionalma_fs_parts = 241 sizeof(twodimensionalma_fs_parts) / sizeof(twodimensionalma_fs_parts[0]); 242 const unsigned int n_twodimensionalma_gs_parts = 243 sizeof(twodimensionalma_gs_parts) / sizeof(twodimensionalma_gs_parts[0]); 244 const unsigned int n_twodimensionalma_vs_parts = 245 sizeof(twodimensionalma_vs_parts) / sizeof(twodimensionalma_vs_parts[0]); 246 247 /* General-use helper variables */ 248 unsigned int n_current_test = 0; 249 250 /* This test should only run if EXT_geometry_shader is supported */ 251 if (!m_is_geometry_shader_extension_supported) 252 { 253 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 254 } 255 256 /* Configure test descriptors */ 257 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].iteration = LAYERED_RENDERING_TEST_ITERATION_CUBEMAP; 258 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].n_layers = 6; /* faces */ 259 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].fs_parts = cm_fs_parts; 260 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].gs_parts = cm_gs_parts; 261 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].vs_parts = cm_vs_parts; 262 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].n_fs_parts = n_cm_fs_parts; 263 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].n_gs_parts = n_cm_gs_parts; 264 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].n_vs_parts = n_cm_vs_parts; 265 266 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].iteration = LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY; 267 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].n_layers = 4; /* layers */ 268 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].fs_parts = twodimensionala_fs_parts; 269 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].gs_parts = twodimensionala_gs_parts; 270 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].vs_parts = twodimensionala_vs_parts; 271 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].n_fs_parts = n_twodimensionala_fs_parts; 272 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].n_gs_parts = n_twodimensionala_gs_parts; 273 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].n_vs_parts = n_twodimensionala_vs_parts; 274 275 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].iteration = LAYERED_RENDERING_TEST_ITERATION_3D; 276 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].n_layers = 4; /* layers */ 277 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].fs_parts = threedimensional_fs_parts; 278 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].gs_parts = threedimensional_gs_parts; 279 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].vs_parts = threedimensional_vs_parts; 280 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].n_fs_parts = n_threedimensional_fs_parts; 281 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].n_gs_parts = n_threedimensional_gs_parts; 282 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].n_vs_parts = n_threedimensional_vs_parts; 283 284 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].iteration = 285 LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY; 286 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].n_layers = 4; /* layers */ 287 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].fs_parts = twodimensionalma_fs_parts; 288 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].gs_parts = twodimensionalma_gs_parts; 289 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].vs_parts = twodimensionalma_vs_parts; 290 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].n_fs_parts = n_twodimensionalma_fs_parts; 291 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].n_gs_parts = n_twodimensionalma_gs_parts; 292 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].n_vs_parts = n_twodimensionalma_vs_parts; 293 294 /* Create shader objects we'll use for the test */ 295 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].fs_id = gl.createShader(GL_FRAGMENT_SHADER); 296 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 297 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].vs_id = gl.createShader(GL_VERTEX_SHADER); 298 299 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].fs_id = gl.createShader(GL_FRAGMENT_SHADER); 300 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 301 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].vs_id = gl.createShader(GL_VERTEX_SHADER); 302 303 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].fs_id = gl.createShader(GL_FRAGMENT_SHADER); 304 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 305 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].vs_id = gl.createShader(GL_VERTEX_SHADER); 306 307 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].fs_id = gl.createShader(GL_FRAGMENT_SHADER); 308 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].gs_id = 309 gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 310 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].vs_id = gl.createShader(GL_VERTEX_SHADER); 311 312 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shaders!"); 313 314 /* Create program objects as well */ 315 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].po_id = gl.createProgram(); 316 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].po_id = gl.createProgram(); 317 m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].po_id = gl.createProgram(); 318 319 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].po_id = gl.createProgram(); 320 321 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create programs!"); 322 323 /* Build the programs */ 324 if (!buildProgramForLRTest(&m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP]) || 325 !buildProgramForLRTest(&m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY]) || 326 !buildProgramForLRTest(&m_tests[LAYERED_RENDERING_TEST_ITERATION_3D]) || 327 !buildProgramForLRTest(&m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY])) 328 { 329 TCU_FAIL("Could not create a program for cube-map texture layered rendering test!"); 330 } 331 332 /* Set up provoking vertex uniform value, given the GL_LAYER_PROVOKING_VERTEX_EXT value. */ 333 glw::GLint layer_provoking_vertex_gl_value = -1; 334 glw::GLint layer_provoking_vertex_uniform_value = -1; 335 336 gl.getIntegerv(m_glExtTokens.LAYER_PROVOKING_VERTEX, &layer_provoking_vertex_gl_value); 337 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_LAYER_PROVOKING_VERTEX_EXT pname"); 338 339 if (!glu::isContextTypeES(context_type) && ((glw::GLenum)layer_provoking_vertex_gl_value == GL_PROVOKING_VERTEX)) 340 { 341 gl.getIntegerv(GL_PROVOKING_VERTEX, &layer_provoking_vertex_gl_value); 342 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_PROVOKING_VERTEX pname"); 343 } 344 345 if ((glw::GLenum)layer_provoking_vertex_gl_value == m_glExtTokens.FIRST_VERTEX_CONVENTION) 346 { 347 layer_provoking_vertex_uniform_value = 1; /* as per geometry shader implementation */ 348 } 349 else if ((glw::GLenum)layer_provoking_vertex_gl_value == m_glExtTokens.LAST_VERTEX_CONVENTION) 350 { 351 layer_provoking_vertex_uniform_value = 2; /* as per geometry shader implementation */ 352 } 353 else if ((glw::GLenum)layer_provoking_vertex_gl_value == m_glExtTokens.UNDEFINED_VERTEX) 354 { 355 layer_provoking_vertex_uniform_value = 0; /* as per geometry shader implementation */ 356 } 357 else 358 { 359 TCU_FAIL("Unrecognized value returned by glGetIntegerv() for GL_LAYER_PROVOKING_VERTEX_EXT pname."); 360 } 361 362 for (unsigned int test_index = 0; test_index < LAYERED_RENDERING_TEST_ITERATION_LAST; ++test_index) 363 { 364 glw::GLint provoking_vertex_index_uniform_location = 365 gl.getUniformLocation(m_tests[test_index].po_id, "provoking_vertex_index"); 366 367 /* Sanity checks */ 368 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call generated an error"); 369 DE_ASSERT(provoking_vertex_index_uniform_location != -1); 370 371 /* Assign the uniform value */ 372 gl.programUniform1i(m_tests[test_index].po_id, provoking_vertex_index_uniform_location, 373 layer_provoking_vertex_uniform_value); 374 375 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramUniform1i() call failed."); 376 } /* for (all test iterations) */ 377 378 /* Initialize texture objects */ 379 gl.genTextures(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].to_id); 380 gl.genTextures(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].to_id); 381 gl.genTextures(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].to_id); 382 gl.genTextures(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].to_id); 383 384 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create texture object(s)!"); 385 386 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].to_id); 387 gl.texStorage2D(GL_TEXTURE_CUBE_MAP, 1 /* mip-map only */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT); 388 389 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].to_id); 390 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* mip-map only */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH); 391 392 gl.bindTexture(GL_TEXTURE_3D, m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].to_id); 393 gl.texStorage3D(GL_TEXTURE_3D, 1 /* mip-map only */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH); 394 395 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 396 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].to_id); 397 gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 1 /* samples */, GL_RGBA8, TEXTURE_WIDTH, 398 TEXTURE_HEIGHT, TEXTURE_DEPTH, GL_FALSE /* fixed sample locations */); 399 400 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture object(s)!"); 401 402 /* Initialize framebuffer objects */ 403 gl.genFramebuffers(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].fbo_id); 404 gl.genFramebuffers(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].fbo_id); 405 gl.genFramebuffers(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].fbo_id); 406 gl.genFramebuffers(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].fbo_id); 407 408 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer object(s)!"); 409 410 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].fbo_id); 411 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 412 m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].to_id, 0 /* base mip-map */); 413 414 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].fbo_id); 415 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 416 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].to_id, 0 /* base mip-map */); 417 418 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].fbo_id); 419 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].to_id, 420 0 /* base mip-map */); 421 422 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].fbo_id); 423 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 424 m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].to_id, 0 /* base mip-map */); 425 426 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure framebuffer object(s)!"); 427 428 /* Initialize vertex array object. We don't really use any attributes, but ES does not 429 * permit draw calls with an unbound VAO 430 */ 431 gl.genVertexArrays(1, &m_vao_id); 432 gl.bindVertexArray(m_vao_id); 433 434 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind a vertex array object!"); 435 436 /* Execute all iterations */ 437 for (n_current_test = 0; n_current_test < sizeof(m_tests) / sizeof(m_tests[0]); ++n_current_test) 438 { 439 unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * TEXTURE_N_COMPONENTS] = { 0 }; 440 glw::GLuint program_id = 0; 441 unsigned int n_layer = 0; 442 glw::GLuint texture_id = 0; 443 444 /* Bind the iteration-specific framebuffer */ 445 gl.bindFramebuffer(GL_FRAMEBUFFER, m_tests[n_current_test].fbo_id); 446 447 program_id = m_tests[n_current_test].po_id; 448 texture_id = m_tests[n_current_test].to_id; 449 450 /* Clear the color attachment with (1, 1, 1, 1) which is not used for 451 * any layers. 452 */ 453 gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f); 454 gl.clear(GL_COLOR_BUFFER_BIT); 455 456 /* Render a single point. This should result in full-screen quads drawn 457 * for each face/layer of the attachment bound to current FBO */ 458 gl.useProgram(program_id); 459 gl.drawArrays(GL_POINTS, 0 /* first index */, 1 /* n points */); 460 461 GLU_EXPECT_NO_ERROR(gl.getError(), "Error rendering geometry!"); 462 463 /* Read contents of each layer we rendered to and verify the contents */ 464 for (n_layer = 0; n_layer < m_tests[n_current_test].n_layers; ++n_layer) 465 { 466 const unsigned char* expected_data = 467 m_layered_rendering_expected_layer_data + TEXTURE_N_COMPONENTS * n_layer; 468 unsigned int n = 0; 469 bool texture_layered = false; 470 glw::GLenum texture_target = GL_NONE; 471 472 /* What is the source attachment's texture target? */ 473 switch (m_tests[n_current_test].iteration) 474 { 475 case LAYERED_RENDERING_TEST_ITERATION_CUBEMAP: 476 { 477 texture_layered = false; 478 texture_target = (n_layer == 0) ? 479 GL_TEXTURE_CUBE_MAP_POSITIVE_X : 480 (n_layer == 1) ? 481 GL_TEXTURE_CUBE_MAP_NEGATIVE_X : 482 (n_layer == 2) ? GL_TEXTURE_CUBE_MAP_POSITIVE_Y : 483 (n_layer == 3) ? GL_TEXTURE_CUBE_MAP_NEGATIVE_Y : 484 (n_layer == 4) ? GL_TEXTURE_CUBE_MAP_POSITIVE_Z : 485 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; 486 487 break; 488 } 489 490 case LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY: 491 { 492 texture_layered = true; 493 texture_target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES; 494 495 break; 496 } 497 498 case LAYERED_RENDERING_TEST_ITERATION_3D: 499 { 500 texture_layered = true; 501 texture_target = GL_TEXTURE_3D; 502 503 break; 504 } 505 506 case LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY: 507 { 508 texture_layered = true; 509 texture_target = GL_TEXTURE_2D_ARRAY; 510 511 break; 512 } 513 514 default: 515 { 516 TCU_FAIL("This location should never be reached"); 517 } 518 } 519 520 /* Configure the read framebuffer's read buffer, depending on whether the attachment 521 * uses layers or not 522 */ 523 if (texture_layered) 524 { 525 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_id, 0 /* base mip-map */, 526 n_layer); 527 } 528 else 529 { 530 if (texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_X || 531 texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y || 532 texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z || 533 texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X || 534 texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y || 535 texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) 536 { 537 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, texture_id, 538 0 /* base mip-map */); 539 } 540 else 541 { 542 TCU_FAIL("This location should never be reached"); 543 } 544 } 545 546 /* Make sure read framebuffer was configured successfully */ 547 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting read framebuffer!"); 548 549 /* Read the data */ 550 if (m_tests[n_current_test].iteration == LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY) 551 { 552 glw::GLuint new_dst_to = 0; 553 glw::GLuint dst_fbo_id = 0; 554 555 gl.genFramebuffers(1, &dst_fbo_id); 556 557 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_tests[n_current_test].fbo_id); 558 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo_id); 559 560 gl.genTextures(1, &new_dst_to); 561 gl.bindTexture(GL_TEXTURE_2D, new_dst_to); 562 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT); 563 564 GLU_EXPECT_NO_ERROR(gl.getError(), 565 "Could not setup texture object for draw framebuffer color attachment."); 566 567 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, new_dst_to, 0); 568 569 GLU_EXPECT_NO_ERROR(gl.getError(), 570 "Could not attach texture object to draw framebuffer color attachment."); 571 572 gl.blitFramebuffer(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, 573 GL_COLOR_BUFFER_BIT, GL_LINEAR); 574 575 GLU_EXPECT_NO_ERROR(gl.getError(), "Error blitting from read framebuffer to draw framebuffer."); 576 577 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, dst_fbo_id); 578 579 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 580 581 GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading attachment's data!"); 582 583 gl.bindFramebuffer(GL_FRAMEBUFFER, m_tests[n_current_test].fbo_id); 584 585 gl.deleteFramebuffers(1, &dst_fbo_id); 586 gl.deleteTextures(1, &new_dst_to); 587 } 588 else 589 { 590 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 591 592 GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading attachment's data!"); 593 } 594 595 /* Validate it */ 596 for (; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n) 597 { 598 unsigned char* data_ptr = buffer + n * TEXTURE_N_COMPONENTS; 599 600 if (memcmp(data_ptr, expected_data, TEXTURE_N_COMPONENTS) != 0) 601 { 602 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << data_ptr[0] << ", " 603 << data_ptr[1] << ", " << data_ptr[2] << ", " << data_ptr[3] 604 << "] is different from reference data [" 605 << m_layered_rendering_expected_layer_data[0] << ", " 606 << m_layered_rendering_expected_layer_data[1] << ", " 607 << m_layered_rendering_expected_layer_data[2] << ", " 608 << m_layered_rendering_expected_layer_data[3] << "] !" 609 << tcu::TestLog::EndMessage; 610 611 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 612 return STOP; 613 } /* if (data comparison failed) */ 614 } /* for (all pixels) */ 615 } /* for (all layers) */ 616 } /* for (all iterations) */ 617 618 /* Done! */ 619 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 620 return STOP; 621 } 622 623 /** Deinitializes GLES objects created during the test. 624 * 625 */ 626 void GeometryShaderLayeredRendering::deinit(void) 627 { 628 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 629 630 /* Reset OpenGL ES state */ 631 gl.useProgram(0); 632 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture */, 0 /* level */); 633 gl.bindTexture(GL_TEXTURE_2D, 0 /* texture */); 634 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 635 gl.bindVertexArray(0); 636 637 for (unsigned int n_current_test = 0; n_current_test < sizeof(m_tests) / sizeof(m_tests[0]); ++n_current_test) 638 { 639 if (m_tests[n_current_test].po_id != 0) 640 { 641 gl.deleteProgram(m_tests[n_current_test].po_id); 642 } 643 644 if (m_tests[n_current_test].fs_id != 0) 645 { 646 gl.deleteShader(m_tests[n_current_test].fs_id); 647 } 648 649 if (m_tests[n_current_test].gs_id != 0) 650 { 651 gl.deleteShader(m_tests[n_current_test].gs_id); 652 } 653 654 if (m_tests[n_current_test].vs_id != 0) 655 { 656 gl.deleteShader(m_tests[n_current_test].vs_id); 657 } 658 659 if (m_tests[n_current_test].to_id != 0) 660 { 661 gl.deleteTextures(1, &m_tests[n_current_test].to_id); 662 } 663 664 if (m_tests[n_current_test].fbo_id != 0) 665 { 666 gl.deleteFramebuffers(1, &m_tests[n_current_test].fbo_id); 667 } 668 } /* for (all tests) */ 669 670 if (m_vao_id != 0) 671 { 672 gl.deleteVertexArrays(1, &m_vao_id); 673 } 674 675 /* Release base class */ 676 TestCaseBase::deinit(); 677 } 678 679 } // namespace glcts 680