• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
GeometryShaderLayeredRendering(Context & context,const ExtParameters & extParams,const char * name,const char * description)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  **/
buildProgramForLRTest(_layered_rendering_test * test)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  **/
iterate(void)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  */
deinit(void)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.bindTexture(GL_TEXTURE_2D, 0 /* texture */);
633 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
634 	gl.bindVertexArray(0);
635 
636 	for (unsigned int n_current_test = 0; n_current_test < sizeof(m_tests) / sizeof(m_tests[0]); ++n_current_test)
637 	{
638 		if (m_tests[n_current_test].po_id != 0)
639 		{
640 			gl.deleteProgram(m_tests[n_current_test].po_id);
641 		}
642 
643 		if (m_tests[n_current_test].fs_id != 0)
644 		{
645 			gl.deleteShader(m_tests[n_current_test].fs_id);
646 		}
647 
648 		if (m_tests[n_current_test].gs_id != 0)
649 		{
650 			gl.deleteShader(m_tests[n_current_test].gs_id);
651 		}
652 
653 		if (m_tests[n_current_test].vs_id != 0)
654 		{
655 			gl.deleteShader(m_tests[n_current_test].vs_id);
656 		}
657 
658 		if (m_tests[n_current_test].to_id != 0)
659 		{
660 			gl.deleteTextures(1, &m_tests[n_current_test].to_id);
661 		}
662 
663 		if (m_tests[n_current_test].fbo_id != 0)
664 		{
665 			gl.deleteFramebuffers(1, &m_tests[n_current_test].fbo_id);
666 		}
667 	} /* for (all tests) */
668 
669 	if (m_vao_id != 0)
670 	{
671 		gl.deleteVertexArrays(1, &m_vao_id);
672 	}
673 
674 	/* Release base class */
675 	TestCaseBase::deinit();
676 }
677 
678 } // namespace glcts
679