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