Home | History | Annotate | Download | only in geometry_shader
      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