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 "esextcGeometryShaderNonarrayInput.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 <string>
34 #include <vector>
35 
36 namespace glcts
37 {
38 
39 /* Fragment shader code */
40 const char *GeometryShaderNonarrayInputCase::m_fs_code = "${VERSION}\n"
41                                                          "\n"
42                                                          "precision highp float;\n"
43                                                          "\n"
44                                                          "out vec4 color;\n"
45                                                          "\n"
46                                                          "void main()\n"
47                                                          "{\n"
48                                                          "    color = vec4(0, 1, 0, 1);\n"
49                                                          "}\n";
50 
51 /* Geometry shader body parts */
52 const char *GeometryShaderNonarrayInputCase::m_gs_code_preamble = "${VERSION}\n"
53                                                                   "${GEOMETRY_SHADER_REQUIRE}\n"
54                                                                   "\n";
55 
56 const char *GeometryShaderNonarrayInputCase::m_gs_code_body = "layout(points)                         in;\n"
57                                                               "layout(triangle_strip, max_vertices=4) out;\n"
58                                                               "\n"
59                                                               "#ifndef USE_BLOCK\n"
60                                                               "    #define V1 v1[0]\n"
61                                                               "    #define V2 v2[0]\n"
62                                                               "    #define V3 v3[0]\n"
63                                                               "\n"
64                                                               "    in vec4 v1[];\n"
65                                                               "    in vec4 v2[];\n"
66                                                               "    in vec4 v3[];\n"
67                                                               "    \n"
68                                                               "    #ifdef CORRUPT\n"
69                                                               "        #define V4 v4\n"
70                                                               "        in vec4 v4;\n"
71                                                               "    #else\n"
72                                                               "        #define V4 v4[0]\n"
73                                                               "        in vec4 v4[];\n"
74                                                               "    #endif\n"
75                                                               "#else\n"
76                                                               "    in VS_GS\n"
77                                                               "    {\n"
78                                                               "        in vec4 v1;\n"
79                                                               "        in vec4 v2;\n"
80                                                               "        in vec4 v3;\n"
81                                                               "        in vec4 v4;\n"
82                                                               "    #ifdef CORRUPT\n"
83                                                               "        } interface_block;\n"
84                                                               "\n"
85                                                               "        #define V1 interface_block.v1\n"
86                                                               "        #define V2 interface_block.v2\n"
87                                                               "        #define V3 interface_block.v3\n"
88                                                               "        #define V4 interface_block.v4\n"
89                                                               "    #else\n"
90                                                               "        } interface_block[];\n"
91                                                               "\n"
92                                                               "        #define V1 interface_block[0].v1\n"
93                                                               "        #define V2 interface_block[0].v2\n"
94                                                               "        #define V3 interface_block[0].v3\n"
95                                                               "        #define V4 interface_block[0].v4\n"
96                                                               "    #endif\n"
97                                                               "#endif\n"
98                                                               "\n"
99                                                               "void main()\n"
100                                                               "{\n"
101                                                               "    gl_Position = V1;\n"
102                                                               "    EmitVertex();\n"
103                                                               "    gl_Position = V2;\n"
104                                                               "    EmitVertex();\n"
105                                                               "    gl_Position = V3;\n"
106                                                               "    EmitVertex();\n"
107                                                               "    gl_Position = V4;\n"
108                                                               "    EmitVertex();\n"
109                                                               "    EndPrimitive();\n"
110                                                               "}\n";
111 
112 /* Vertex shader body parts */
113 const char *GeometryShaderNonarrayInputCase::m_vs_code_preamble = "${VERSION}\n"
114                                                                   "\n";
115 
116 const char *GeometryShaderNonarrayInputCase::m_vs_code_body = "#ifndef USE_BLOCK\n"
117                                                               "    #define V1 v1\n"
118                                                               "    #define V2 v2\n"
119                                                               "    #define V3 v3\n"
120                                                               "    #define V4 v4\n"
121                                                               "\n"
122                                                               "    out vec4 v1;\n"
123                                                               "    out vec4 v2;\n"
124                                                               "    out vec4 v3;\n"
125                                                               "    out vec4 v4;\n"
126                                                               "#else\n"
127                                                               "    ${SHADER_IO_BLOCKS_ENABLE}\n"
128                                                               "    #define V1 interface_block.v1\n"
129                                                               "    #define V2 interface_block.v2\n"
130                                                               "    #define V3 interface_block.v3\n"
131                                                               "    #define V4 interface_block.v4\n"
132                                                               "\n"
133                                                               "    out VS_GS\n"
134                                                               "    {\n"
135                                                               "        vec4 v1;\n"
136                                                               "        vec4 v2;\n"
137                                                               "        vec4 v3;\n"
138                                                               "        vec4 v4;\n"
139                                                               "    } interface_block;\n"
140                                                               "#endif\n"
141                                                               "\n"
142                                                               "void main()\n"
143                                                               "{\n"
144                                                               "    V1 = vec4(-1, -1, 0, 1);\n"
145                                                               "    V2 = vec4(-1,  1, 0, 1);\n"
146                                                               "    V3 = vec4( 1, -1, 0, 1);\n"
147                                                               "    V4 = vec4( 1,  1, 0, 1);\n"
148                                                               "}\n";
149 
150 /* Definitions */
151 #define TEXTURE_HEIGHT (4)
152 #define TEXTURE_WIDTH (4)
153 
154 /** Constructor
155  *
156  * @param context       Test context
157  * @param name          Test case's name
158  * @param description   Test case's desricption
159  **/
GeometryShaderNonarrayInputCase(Context & context,const ExtParameters & extParams,const char * name,const char * description)160 GeometryShaderNonarrayInputCase::GeometryShaderNonarrayInputCase(Context &context, const ExtParameters &extParams,
161                                                                  const char *name, const char *description)
162     : TestCaseBase(context, extParams, name, description)
163     , m_fbo_id(0)
164     , m_fs(0)
165     , m_gs_invalid_non_ib(0)
166     , m_gs_invalid_ib(0)
167     , m_gs_valid_non_ib(0)
168     , m_gs_valid_ib(0)
169     , m_po_a_invalid(0)
170     , m_po_b_invalid(0)
171     , m_po_a_valid(0)
172     , m_po_b_valid(0)
173     , m_to_id(0)
174     , m_vao_id(0)
175     , m_vs_valid_ib(0)
176     , m_vs_valid_non_ib(0)
177 {
178 }
179 
180 /** Executes the test.
181  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
182  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
183  *  Note the function throws exception should an error occur!
184  **/
iterate(void)185 tcu::TestNode::IterateResult GeometryShaderNonarrayInputCase::iterate(void)
186 {
187     glw::GLint compile_status = GL_FALSE;
188     const glw::Functions &gl  = m_context.getRenderContext().getFunctions();
189     glw::GLint link_status    = GL_FALSE;
190     unsigned int m            = 0;
191     unsigned int n            = 0;
192 
193     /* Form the shaders */
194     const char *fs_parts[]                = {m_fs_code};
195     const char *gs_invalid_non_ib_parts[] = {m_gs_code_preamble, "#define CORRUPT\n", m_gs_code_body};
196     const char *gs_invalid_ib_parts[]   = {m_gs_code_preamble, "#define CORRUPT\n#define USE_BLOCK\n", m_gs_code_body};
197     const char *gs_valid_non_ib_parts[] = {m_gs_code_preamble, m_gs_code_body};
198     const char *gs_valid_ib_parts[]     = {m_gs_code_preamble, "#define USE_BLOCK\n", m_gs_code_body};
199     const char *vs_valid_non_ib_parts[] = {m_vs_code_preamble, m_vs_code_body};
200     const char *vs_valid_ib_parts[]     = {m_vs_code_preamble, "#define USE_BLOCK\n", m_vs_code_body};
201 
202     /* This test should only run if EXT_geometry_shader is supported.
203      * Note that EXT_shader_io_blocks support is implied. */
204     if (!m_is_geometry_shader_extension_supported)
205     {
206         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
207     }
208 
209     /* Create program objects */
210     m_po_a_invalid = gl.createProgram();
211     m_po_b_invalid = gl.createProgram();
212 
213     /* Create shader objects */
214     m_fs                = gl.createShader(GL_FRAGMENT_SHADER);
215     m_gs_invalid_non_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
216     m_gs_invalid_ib     = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
217     m_gs_valid_non_ib   = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
218     m_gs_valid_ib       = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
219     m_vs_valid_non_ib   = gl.createShader(GL_VERTEX_SHADER);
220     m_vs_valid_ib       = gl.createShader(GL_VERTEX_SHADER);
221 
222     shaderSourceSpecialized(m_fs, DE_LENGTH_OF_ARRAY(fs_parts), fs_parts);
223     shaderSourceSpecialized(m_gs_invalid_non_ib, DE_LENGTH_OF_ARRAY(gs_invalid_non_ib_parts), gs_invalid_non_ib_parts);
224     shaderSourceSpecialized(m_gs_invalid_ib, DE_LENGTH_OF_ARRAY(gs_invalid_ib_parts), gs_invalid_ib_parts);
225     shaderSourceSpecialized(m_gs_valid_non_ib, DE_LENGTH_OF_ARRAY(gs_valid_non_ib_parts), gs_valid_non_ib_parts);
226     shaderSourceSpecialized(m_gs_valid_ib, DE_LENGTH_OF_ARRAY(gs_valid_ib_parts), gs_valid_ib_parts);
227     shaderSourceSpecialized(m_vs_valid_non_ib, DE_LENGTH_OF_ARRAY(vs_valid_non_ib_parts), vs_valid_non_ib_parts);
228     shaderSourceSpecialized(m_vs_valid_ib, DE_LENGTH_OF_ARRAY(vs_valid_ib_parts), vs_valid_ib_parts);
229 
230     /* Create and form invalid programs */
231     gl.attachShader(m_po_a_invalid, m_fs);
232     gl.attachShader(m_po_a_invalid, m_gs_invalid_non_ib);
233     gl.attachShader(m_po_a_invalid, m_vs_valid_non_ib);
234 
235     gl.attachShader(m_po_b_invalid, m_fs);
236     gl.attachShader(m_po_b_invalid, m_gs_invalid_ib);
237     gl.attachShader(m_po_b_invalid, m_vs_valid_ib);
238 
239     /* Try to compile the shaders. Do not check GL_COMPILE_STATUS - we expect a linking failure */
240     gl.compileShader(m_fs);
241     gl.compileShader(m_gs_invalid_non_ib);
242     gl.compileShader(m_gs_invalid_ib);
243     gl.compileShader(m_vs_valid_non_ib);
244     gl.compileShader(m_vs_valid_ib);
245 
246     /* Try to link the programs */
247     gl.linkProgram(m_po_a_invalid);
248     gl.getProgramiv(m_po_a_invalid, GL_LINK_STATUS, &link_status);
249 
250     if (link_status != GL_FALSE)
251     {
252         m_testCtx.getLog() << tcu::TestLog::Message
253                            << "Program linked sucessfully although it shouldn't because geometry shaders are not "
254                               "expected to support non-array input attributes."
255                            << tcu::TestLog::EndMessage;
256 
257         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
258         return STOP;
259     }
260 
261     gl.linkProgram(m_po_b_invalid);
262     gl.getProgramiv(m_po_b_invalid, GL_LINK_STATUS, &link_status);
263 
264     if (link_status != GL_FALSE)
265     {
266         m_testCtx.getLog() << tcu::TestLog::Message
267                            << "Program linked sucessfully although it shouldn't because geometry shaders are not "
268                               "expected to support non-array block input attributes."
269                            << tcu::TestLog::EndMessage;
270 
271         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
272         return STOP;
273     }
274 
275     /* Release the programs before we continue */
276     gl.deleteProgram(m_po_a_invalid);
277     gl.deleteProgram(m_po_b_invalid);
278 
279     m_po_a_invalid = 0;
280     m_po_b_invalid = 0;
281 
282     /* Release the invalid geometry shaders */
283     gl.deleteShader(m_gs_invalid_non_ib);
284     gl.deleteShader(m_gs_invalid_ib);
285 
286     m_gs_invalid_non_ib = 0;
287     m_gs_invalid_ib     = 0;
288 
289     /* Create and form valid programs */
290     m_po_a_valid = gl.createProgram();
291     m_po_b_valid = gl.createProgram();
292 
293     gl.attachShader(m_po_a_valid, m_fs);
294     gl.attachShader(m_po_a_valid, m_gs_valid_non_ib);
295     gl.attachShader(m_po_a_valid, m_vs_valid_non_ib);
296 
297     gl.attachShader(m_po_b_valid, m_fs);
298     gl.attachShader(m_po_b_valid, m_gs_valid_ib);
299     gl.attachShader(m_po_b_valid, m_vs_valid_ib);
300 
301     gl.compileShader(m_gs_valid_non_ib);
302     gl.compileShader(m_gs_valid_ib);
303 
304     gl.getShaderiv(m_gs_valid_non_ib, GL_COMPILE_STATUS, &compile_status);
305 
306     if (compile_status != GL_TRUE)
307     {
308         std::string log = getCompilationInfoLog(m_gs_valid_non_ib);
309 
310         m_testCtx.getLog() << tcu::TestLog::Message << "Valid geometry shader didn't compile. Error message: " << log
311                            << tcu::TestLog::EndMessage;
312 
313         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
314         return STOP;
315     }
316 
317     gl.getShaderiv(m_gs_valid_ib, GL_COMPILE_STATUS, &compile_status);
318 
319     if (compile_status != GL_TRUE)
320     {
321         std::string log = getCompilationInfoLog(m_gs_valid_ib);
322 
323         m_testCtx.getLog() << tcu::TestLog::Message << "Valid geometry shader didn't compile. Error message: " << log
324                            << tcu::TestLog::EndMessage;
325 
326         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
327         return STOP;
328     }
329 
330     gl.linkProgram(m_po_a_valid);
331     gl.getProgramiv(m_po_a_valid, GL_LINK_STATUS, &link_status);
332 
333     if (link_status != GL_TRUE)
334     {
335         std::string log = getLinkingInfoLog(m_po_a_valid);
336 
337         m_testCtx.getLog() << tcu::TestLog::Message
338                            << "Program failed to link although it was expected to link successfully. Error message: "
339                            << log << tcu::TestLog::EndMessage;
340 
341         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
342         return STOP;
343     }
344 
345     gl.linkProgram(m_po_b_valid);
346     gl.getProgramiv(m_po_b_valid, GL_LINK_STATUS, &link_status);
347 
348     if (link_status != GL_TRUE)
349     {
350         std::string log = getLinkingInfoLog(m_po_b_valid);
351 
352         m_testCtx.getLog() << tcu::TestLog::Message
353                            << "Program failed to link although it was expected to link successfully. Error message: "
354                            << log << tcu::TestLog::EndMessage;
355 
356         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
357         return STOP;
358     }
359 
360     /* Set up a FBO */
361     gl.genFramebuffers(1, &m_fbo_id);
362     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
363 
364     gl.genTextures(1, &m_to_id);
365     gl.bindTexture(GL_TEXTURE_2D, m_to_id);
366     gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
367     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
368 
369     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up a framebuffer object");
370 
371     gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
372 
373     /* Generate and bind a VAO */
374     gl.genVertexArrays(1, &m_vao_id);
375     gl.bindVertexArray(m_vao_id);
376 
377     /* Set up clear color */
378     gl.clearColor(1.0f, 0, 0, 0);
379 
380     /* Use both program objects and verify they work correctly */
381     for (m = 0; m < 2 /* programs */; ++m)
382     {
383         glw::GLuint program = (m == 0) ? m_po_a_valid : m_po_b_valid;
384         unsigned char result[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4 /*components */];
385 
386         /* Clear the color attachment before we continue */
387         gl.clear(GL_COLOR_BUFFER_BIT);
388 
389         /* Render! */
390         gl.useProgram(program);
391         gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
392 
393         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
394 
395         /* Read back the result */
396         gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result);
397 
398         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color attachment 0");
399 
400         /* Verify the result data is correct */
401         for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
402         {
403             if (result[n * 4 + 0] != 0 || result[n * 4 + 1] != 255 || result[n * 4 + 2] != 0 ||
404                 result[n * 4 + 3] != 255)
405             {
406                 m_testCtx.getLog() << tcu::TestLog::Message
407                                    << "Pixel data isn't correct. All pixels should have green color. Pixel at: "
408                                    << "[" << n / 4 << ", " << n % 4 << "] "
409                                    << "has color: "
410                                    << "[" << result[n * 4 + 0] << ", " << result[n * 4 + 1] << ", " << result[n * 4 + 2]
411                                    << ", " << result[n * 4 + 3] << "]" << tcu::TestLog::EndMessage;
412 
413                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
414                 return STOP;
415             } /* if (result data is invalid) */
416         }     /* for (all pixels) */
417     }         /* for (all programs) */
418 
419     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
420     return STOP;
421 }
422 
423 /** Deinitializes GLES objects created during the test.
424  *
425  */
deinit(void)426 void GeometryShaderNonarrayInputCase::deinit(void)
427 {
428     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
429 
430     /* Reset OpenGL ES state */
431     gl.useProgram(0);
432     gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
433     gl.bindVertexArray(0);
434 
435     if (m_po_a_valid != 0)
436     {
437         gl.deleteProgram(m_po_a_valid);
438     }
439 
440     if (m_po_b_valid != 0)
441     {
442         gl.deleteProgram(m_po_b_valid);
443     }
444 
445     if (m_fs != 0)
446     {
447         gl.deleteShader(m_fs);
448     }
449 
450     if (m_gs_invalid_ib != 0)
451     {
452         gl.deleteShader(m_gs_invalid_ib);
453     }
454 
455     if (m_gs_invalid_non_ib != 0)
456     {
457         gl.deleteShader(m_gs_invalid_non_ib);
458     }
459 
460     if (m_gs_valid_ib != 0)
461     {
462         gl.deleteShader(m_gs_valid_ib);
463     }
464 
465     if (m_gs_valid_non_ib != 0)
466     {
467         gl.deleteShader(m_gs_valid_non_ib);
468     }
469 
470     if (m_vs_valid_ib != 0)
471     {
472         gl.deleteShader(m_vs_valid_ib);
473     }
474 
475     if (m_vs_valid_non_ib != 0)
476     {
477         gl.deleteShader(m_vs_valid_non_ib);
478     }
479 
480     if (m_to_id != 0)
481     {
482         gl.deleteTextures(1, &m_to_id);
483     }
484 
485     if (m_fbo_id != 0)
486     {
487         gl.deleteFramebuffers(1, &m_fbo_id);
488     }
489 
490     if (m_vao_id != 0)
491     {
492         gl.deleteVertexArrays(1, &m_vao_id);
493     }
494 
495     /* Release base class */
496     TestCaseBase::deinit();
497 }
498 
499 } // namespace glcts
500