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