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