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