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 "esextcGeometryShaderLayeredRenderingFBONoAttachment.hpp"
25
26 #include "gluDefs.hpp"
27 #include "tcuTestLog.hpp"
28
29 namespace glcts
30 {
31 /* Fragment shader code */
32 const char* GeometryShaderLayeredRenderingFBONoAttachment::m_fs_code =
33 "${VERSION}\n"
34 "\n"
35 "${GEOMETRY_SHADER_REQUIRE}\n"
36 "\n"
37 "precision highp float;\n"
38 "\n"
39 "layout(rgba32i, binding = 0) writeonly uniform highp iimage2DArray array_image;\n"
40 "\n"
41 " in vec2 uv;\n"
42 "flat in int layer_id;\n"
43 "out vec4 color;\n"
44 "\n"
45 "void main()\n"
46 "{\n"
47 " imageStore(array_image, ivec3( int(128.0 * uv.x), int(128.0 * uv.y), layer_id ), ivec4(0, 255, 0, 0) );\n"
48 "}\n";
49
50 /* Geometry shader code */
51 const char* GeometryShaderLayeredRenderingFBONoAttachment::m_gs_code = "${VERSION}\n"
52 "\n"
53 "${GEOMETRY_SHADER_REQUIRE}\n"
54 "\n"
55 "precision highp float;\n"
56 "\n"
57 "layout(points) in;\n"
58 "layout(triangle_strip, max_vertices=16) out;\n"
59 "\n"
60 " out vec2 uv;\n"
61 "flat out int layer_id;\n"
62 "\n"
63 "void main()\n"
64 "{\n"
65 " for (int n = 0; n < 4; ++n)\n"
66 " {\n"
67 " gl_Position = vec4(1, -1, 0, 1);\n"
68 " gl_Layer = n;\n"
69 " layer_id = n;\n"
70 " uv = vec2(1, 0);\n"
71 " EmitVertex();\n"
72 "\n"
73 " gl_Position = vec4(1, 1, 0, 1);\n"
74 " gl_Layer = n;\n"
75 " layer_id = n;\n"
76 " uv = vec2(1, 1);\n"
77 " EmitVertex();\n"
78 "\n"
79 " gl_Position = vec4(-1, -1, 0, 1);\n"
80 " gl_Layer = n;\n"
81 " layer_id = n;\n"
82 " uv = vec2(0, 0);\n"
83 " EmitVertex();\n"
84 "\n"
85 " gl_Position = vec4(-1, 1, 0, 1);\n"
86 " gl_Layer = n;\n"
87 " layer_id = n;\n"
88 " uv = vec2(0, 1);\n"
89 " EmitVertex();\n"
90 "\n"
91 " EndPrimitive();\n"
92 " }\n"
93 "}\n";
94
95 /* Vertex shader code */
96 const char* GeometryShaderLayeredRenderingFBONoAttachment::m_vs_code = "${VERSION}\n"
97 "\n"
98 "${GEOMETRY_SHADER_REQUIRE}\n"
99 "\n"
100 "precision highp float;\n"
101 "\n"
102 "void main()\n"
103 "{\n"
104 "}\n";
105
106 /* Constants */
107 const glw::GLint GeometryShaderLayeredRenderingFBONoAttachment::m_height = 128;
108 const glw::GLint GeometryShaderLayeredRenderingFBONoAttachment::m_width = 128;
109 const int GeometryShaderLayeredRenderingFBONoAttachment::m_n_layers = 4;
110 const glw::GLint GeometryShaderLayeredRenderingFBONoAttachment::m_n_texture_components = 4;
111
112 /** Constructor
113 *
114 * @param context Test context
115 * @param name Test case's name
116 * @param description Test case's description
117 **/
GeometryShaderLayeredRenderingFBONoAttachment(Context & context,const ExtParameters & extParams,const char * name,const char * description)118 GeometryShaderLayeredRenderingFBONoAttachment::GeometryShaderLayeredRenderingFBONoAttachment(
119 Context& context, const ExtParameters& extParams, const char* name, const char* description)
120 : TestCaseBase(context, extParams, name, description)
121 , m_fbo_id(0)
122 , m_fs_id(0)
123 , m_gs_id(0)
124 , m_po_id(0)
125 , m_to_id(0)
126 , m_vao_id(0)
127 , m_vs_id(0)
128 , m_all_layers_data(DE_NULL)
129 , m_layer_data(DE_NULL)
130 {
131 /* Nothing to be done here */
132 }
133
134 /** Deinitializes GLES objects created during the test.
135 *
136 */
deinit(void)137 void GeometryShaderLayeredRenderingFBONoAttachment::deinit(void)
138 {
139 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
140
141 /* Reset OpenGL ES state */
142 gl.useProgram(0);
143 gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0 /* texture */);
144 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
145 gl.bindVertexArray(0);
146
147 if (m_po_id != 0)
148 {
149 gl.deleteProgram(m_po_id);
150 m_po_id = 0;
151 }
152
153 if (m_fs_id != 0)
154 {
155 gl.deleteShader(m_fs_id);
156 m_fs_id = 0;
157 }
158
159 if (m_gs_id != 0)
160 {
161 gl.deleteShader(m_gs_id);
162 m_gs_id = 0;
163 }
164
165 if (m_vs_id != 0)
166 {
167 gl.deleteShader(m_vs_id);
168 m_vs_id = 0;
169 }
170
171 if (m_to_id != 0)
172 {
173 gl.deleteTextures(1, &m_to_id);
174 m_to_id = 0;
175 }
176
177 if (m_fbo_id != 0)
178 {
179 gl.deleteFramebuffers(1, &m_fbo_id);
180 m_fbo_id = 0;
181 }
182
183 if (m_vao_id != 0)
184 {
185 gl.deleteVertexArrays(1, &m_vao_id);
186 m_vao_id = 0;
187 }
188
189 if (m_all_layers_data != DE_NULL)
190 {
191 delete[] m_all_layers_data;
192 m_all_layers_data = DE_NULL;
193 }
194
195 if (m_layer_data != DE_NULL)
196 {
197 delete[] m_layer_data;
198 m_layer_data = DE_NULL;
199 }
200
201 /* Release base class */
202 TestCaseBase::deinit();
203 }
204
205 /** Executes the test.
206 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
207 *
208 * Note the function throws exception should an error occur!
209 *
210 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
211 *
212 **/
iterate(void)213 tcu::TestNode::IterateResult GeometryShaderLayeredRenderingFBONoAttachment::iterate(void)
214 {
215 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
216
217 /* Check if required extensions are supported */
218 if (!m_is_geometry_shader_extension_supported)
219 {
220 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
221 }
222
223 if (!m_is_framebuffer_no_attachments_supported)
224 {
225 throw tcu::NotSupportedError("framebuffer_no_attachment, is not supported", "", __FILE__, __LINE__);
226 }
227
228 if (!m_is_shader_image_load_store_supported)
229 {
230 throw tcu::NotSupportedError("shader_image_load_store, is not supported", "", __FILE__, __LINE__);
231 }
232
233 /* Generate and bind a framebuffer object */
234 gl.genFramebuffers(1, &m_fbo_id);
235 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
236
237 /* Get the default number of layers of a newly created framebuffer object */
238 glw::GLint nLayers = -1;
239
240 gl.getFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, m_glExtTokens.FRAMEBUFFER_DEFAULT_LAYERS, &nLayers);
241
242 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query a framebuffer object for the number of default layers!");
243
244 /* check 14.2 test condition - if default number of layer equals 0 */
245 if (nLayers != 0)
246 {
247 m_testCtx.getLog() << tcu::TestLog::Message << "Number of default layers should be equal to 0 but is "
248 << nLayers << tcu::TestLog::EndMessage;
249
250 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
251 return STOP;
252 }
253
254 /* Set the default resolution to 128x128 */
255 glw::GLint width = 0;
256 glw::GLint height = 0;
257
258 gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, m_width);
259 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set the default framebuffer's width!");
260 gl.getFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, &width);
261 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get the default framebuffer's width!");
262 gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, m_height);
263 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set the default framebuffer's height!");
264 gl.getFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, &height);
265 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get the default framebuffer's height!");
266
267 if (m_width != width || m_height != height)
268 {
269 m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer's default width/height is not equal to" << m_width
270 << "\\" << m_height << " but is " << width << "\\" << height << tcu::TestLog::EndMessage;
271
272 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
273 return STOP;
274 }
275
276 /* Configure program object to be used for functional part of the test */
277 m_po_id = gl.createProgram();
278
279 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
280 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
281 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
282
283 if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &m_fs_code, m_gs_id, 1 /* part */, &m_gs_code, m_vs_id,
284 1 /* part */, &m_vs_code))
285 {
286 TCU_FAIL("Could not create program object from a valid vertex/geometry/fragment shader code!");
287 }
288
289 /* Configure texture objects and fill them with initial data */
290 m_all_layers_data = new glw::GLint[m_n_layers * m_width * m_height * m_n_texture_components];
291
292 for (int n = 0; n < m_n_layers * m_width * m_height; ++n)
293 {
294 m_all_layers_data[n * m_n_texture_components + 0] = 255;
295 m_all_layers_data[n * m_n_texture_components + 1] = 0;
296 m_all_layers_data[n * m_n_texture_components + 2] = 0;
297 m_all_layers_data[n * m_n_texture_components + 3] = 0;
298 }
299
300 gl.genTextures(1, &m_to_id);
301 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_id);
302 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA32I, m_width, m_height, m_n_layers);
303 gl.texParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
304 gl.texParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
305
306 GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating texture objects!");
307
308 /* Activate the test program object */
309 gl.useProgram(m_po_id);
310 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program!");
311
312 /* Bind texture to image unit */
313 gl.bindImageTexture(0, m_to_id, 0 /* level */, GL_TRUE, 0 /* layer */, GL_WRITE_ONLY, GL_RGBA32I);
314 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind texture to image unit!");
315
316 /* Generate & bind a VAO */
317 gl.genVertexArrays(1, &m_vao_id);
318 gl.bindVertexArray(m_vao_id);
319
320 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a vertex array object!");
321
322 /* Set up the viewport */
323 gl.viewport(0 /* x */, 0 /* y */, m_width /* width */, m_height /* height */);
324 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
325
326 /* Test 21.4 adjusts the behavior of the original tests. The test now needs to run
327 * in two iterations:
328 *
329 * a) Original behavior is left intact
330 * b) GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT should be set to 0.
331 */
332 glw::GLboolean test_failed = false;
333
334 m_layer_data = new glw::GLint[m_width * m_height * m_n_texture_components];
335
336 for (unsigned int n_test_iteration = 0; n_test_iteration < 2 && !test_failed; ++n_test_iteration)
337 {
338 const glw::GLint current_n_layers = (n_test_iteration == 1) ? 0 : m_n_layers;
339
340 /* Reset render-target contents */
341 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, /* level */
342 0, /* xoffset */
343 0, /* yoffset */
344 0, /* zoffset */
345 m_width, m_height, m_n_layers, GL_RGBA_INTEGER, GL_INT, m_all_layers_data);
346 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D() call failed.");
347
348 /* Set the default number of layers to m_n_layers */
349 gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, m_glExtTokens.FRAMEBUFFER_DEFAULT_LAYERS, current_n_layers);
350
351 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set the default number of layers of a framebuffer object!");
352
353 gl.getFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, m_glExtTokens.FRAMEBUFFER_DEFAULT_LAYERS, &nLayers);
354
355 /* check if the reported value equals m_n_layers */
356 if (current_n_layers != nLayers)
357 {
358 m_testCtx.getLog() << tcu::TestLog::Message << "FBO's default layers should be equal to " << m_n_layers
359 << "but is " << nLayers << tcu::TestLog::EndMessage;
360
361 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
362 return STOP;
363 }
364
365 /* Render! */
366 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
367
368 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not execute a draw call!");
369
370 /* Verify result texture data */
371 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
372
373 for (int n_layer = 0; n_layer < m_n_layers && !test_failed; ++n_layer)
374 {
375 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */, n_layer);
376
377 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind texture as color attachment to framebuffer!");
378
379 if (gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
380 {
381 TCU_FAIL("Read framebuffer is not complete!");
382 }
383
384 gl.memoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
385
386 gl.readPixels(0 /* x */, 0 /* y */, m_width, m_height, GL_RGBA_INTEGER, GL_INT, m_layer_data);
387
388 GLU_EXPECT_NO_ERROR(gl.getError(),
389 "Could not read back pixels from the texture bound to color attachment!");
390
391 /* Perform the verification */
392 const int referenceColor[4] = { 0, 255, 0, 0 };
393
394 for (int nPx = 0; nPx < m_width * m_height; ++nPx)
395 {
396 if (m_layer_data[nPx * m_n_texture_components + 0] != referenceColor[0] ||
397 m_layer_data[nPx * m_n_texture_components + 1] != referenceColor[1] ||
398 m_layer_data[nPx * m_n_texture_components + 2] != referenceColor[2] ||
399 m_layer_data[nPx * m_n_texture_components + 3] != referenceColor[3])
400 {
401 m_testCtx.getLog() << tcu::TestLog::Message << "The test failed: Pixel " << nPx << " from layer "
402 << n_layer << " is set to [" << m_layer_data[nPx * m_n_texture_components + 0]
403 << "," << m_layer_data[nPx * m_n_texture_components + 1] << ","
404 << m_layer_data[nPx * m_n_texture_components + 2] << ","
405 << m_layer_data[nPx * m_n_texture_components + 3] << "] but should be equal to ["
406 << referenceColor[0] << "," << referenceColor[1] << "," << referenceColor[2]
407 << "," << referenceColor[3] << ","
408 << "]" << tcu::TestLog::EndMessage;
409
410 test_failed = true;
411 break;
412 } /* if (result pixel is invalid) */
413 } /* for (all pixels) */
414 } /* for (all layers) */
415
416 /* Restore the FBO to no-attachment state for the next iteration */
417 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0);
418
419 } /* for (both iterations) */
420
421 if (test_failed)
422 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
423 else
424 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
425
426 return STOP;
427 }
428
429 } // namespace glcts
430