1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-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 #include "esextcGeometryShaderAPI.hpp"
24 
25 #include "gluDefs.hpp"
26 #include "glwEnums.hpp"
27 #include "glwFunctions.hpp"
28 #include "tcuTestLog.hpp"
29 #include <cstring>
30 
31 namespace glcts
32 {
33 
34 static const char *minimal_fs_code = "${VERSION}\n"
35                                      "\n"
36                                      "precision highp float;\n"
37                                      "\n"
38                                      "out vec4 result;\n"
39                                      "\n"
40                                      "void main()\n"
41                                      "{\n"
42                                      "    result = vec4(1.0);\n"
43                                      "}\n";
44 
45 static const char *minimal_gs_code = "${VERSION}\n"
46                                      "${GEOMETRY_SHADER_REQUIRE}\n"
47                                      "\n"
48                                      "layout (points)                   in;\n"
49                                      "layout (points, max_vertices = 1) out;\n"
50                                      "\n"
51                                      "${OUT_PER_VERTEX_DECL}"
52                                      "${IN_DATA_DECL}"
53                                      "void main()\n"
54                                      "{\n"
55                                      "${POSITION_WITH_IN_DATA}"
56                                      "    EmitVertex();\n"
57                                      "}\n";
58 
59 static const char *minimal_vs_code = "${VERSION}\n"
60                                      "\n"
61                                      "${OUT_PER_VERTEX_DECL}"
62                                      "\n"
63                                      "void main()\n"
64                                      "{\n"
65                                      "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
66                                      "}\n";
67 
68 /* createShaderProgramv conformance test shaders */
69 const char *GeometryShaderCreateShaderProgramvTest::fs_code = "${VERSION}\n"
70                                                               "\n"
71                                                               "precision highp float;\n"
72                                                               "\n"
73                                                               "out vec4 result;\n"
74                                                               "\n"
75                                                               "void main()\n"
76                                                               "{\n"
77                                                               "    result = vec4(0.0, 1.0, 0.0, 0.0);\n"
78                                                               "}\n";
79 
80 const char *GeometryShaderCreateShaderProgramvTest::gs_code = "${VERSION}\n"
81                                                               "${GEOMETRY_SHADER_REQUIRE}\n"
82                                                               "\n"
83                                                               "layout (points)                           in;\n"
84                                                               "layout (triangle_strip, max_vertices = 4) out;\n"
85                                                               "\n"
86                                                               "${OUT_PER_VERTEX_DECL}"
87                                                               "\n"
88                                                               "void main()\n"
89                                                               "{\n"
90                                                               "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
91                                                               "    EmitVertex();\n"
92                                                               "\n"
93                                                               "    gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
94                                                               "    EmitVertex();\n"
95                                                               "\n"
96                                                               "    gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
97                                                               "    EmitVertex();\n"
98                                                               "\n"
99                                                               "    gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
100                                                               "    EmitVertex();\n"
101                                                               "    EndPrimitive();\n"
102                                                               "}\n";
103 
104 const char *GeometryShaderCreateShaderProgramvTest::vs_code = "${VERSION}\n"
105                                                               "\n"
106                                                               "${OUT_PER_VERTEX_DECL}"
107                                                               "\n"
108                                                               "void main()\n"
109                                                               "{\n"
110                                                               "    gl_Position = vec4(-10.0, -10.0, -10.0, 0.0);\n"
111                                                               "}\n";
112 
113 const unsigned int GeometryShaderCreateShaderProgramvTest::m_to_height = 4;
114 const unsigned int GeometryShaderCreateShaderProgramvTest::m_to_width  = 4;
115 
116 /** Constructor
117  *
118  * @param context       Test context
119  * @param extParams     Not used.
120  * @param name          Test case's name
121  * @param description   Test case's description
122  **/
GeometryShaderCreateShaderProgramvTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)123 GeometryShaderCreateShaderProgramvTest::GeometryShaderCreateShaderProgramvTest(Context &context,
124                                                                                const ExtParameters &extParams,
125                                                                                const char *name,
126                                                                                const char *description)
127     : TestCaseBase(context, extParams, name, description)
128     , m_fbo_id(0)
129     , m_fs_po_id(0)
130     , m_gs_po_id(0)
131     , m_pipeline_object_id(0)
132     , m_to_id(0)
133     , m_vao_id(0)
134     , m_vs_po_id(0)
135 {
136 }
137 
138 /** Deinitializes GLES objects created during the test. */
deinit()139 void GeometryShaderCreateShaderProgramvTest::deinit()
140 {
141     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
142 
143     if (m_fbo_id != 0)
144     {
145         gl.deleteFramebuffers(1, &m_fbo_id);
146 
147         m_fbo_id = 0;
148     }
149 
150     if (m_fs_po_id != 0)
151     {
152         gl.deleteProgram(m_fs_po_id);
153 
154         m_fs_po_id = 0;
155     }
156 
157     if (m_gs_po_id != 0)
158     {
159         gl.deleteProgram(m_gs_po_id);
160 
161         m_gs_po_id = 0;
162     }
163 
164     if (m_pipeline_object_id != 0)
165     {
166         gl.deleteProgramPipelines(1, &m_pipeline_object_id);
167 
168         m_pipeline_object_id = 0;
169     }
170 
171     if (m_to_id != 0)
172     {
173         gl.deleteTextures(1, &m_to_id);
174 
175         m_to_id = 0;
176     }
177 
178     if (m_vao_id != 0)
179     {
180         gl.deleteVertexArrays(1, &m_vao_id);
181 
182         m_vao_id = 0;
183     }
184 
185     if (m_vs_po_id != 0)
186     {
187         gl.deleteProgram(m_vs_po_id);
188 
189         m_vs_po_id = 0;
190     }
191 
192     /* Release base class */
193     TestCaseBase::deinit();
194 }
195 
196 /** Initializes a framebuffer object used by the conformance test. */
initFBO()197 void GeometryShaderCreateShaderProgramvTest::initFBO()
198 {
199     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
200 
201     /* Generate a FBO */
202     gl.genFramebuffers(1, &m_fbo_id);
203     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
204 
205     /* Generate a TO */
206     gl.genTextures(1, &m_to_id);
207     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
208 
209     /* Set the TO up */
210     gl.bindTexture(GL_TEXTURE_2D, m_to_id);
211     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
212 
213     gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
214                     GL_RGBA8, m_to_width, m_to_height);
215     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
216 
217     /* Set up the FBO */
218     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
219     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
220 
221     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0); /* level */
222     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
223 
224     /* Set up the viewport */
225     gl.viewport(0, /* x */
226                 0, /* y */
227                 m_to_width, m_to_height);
228 
229     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
230 }
231 
232 /* Initializes a pipeline object used by the conformance test */
initPipelineObject()233 void GeometryShaderCreateShaderProgramvTest::initPipelineObject()
234 {
235     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
236 
237     DE_ASSERT(m_fs_po_id != 0 && m_gs_po_id != 0 && m_vs_po_id != 0);
238 
239     gl.genProgramPipelines(1, &m_pipeline_object_id);
240     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
241 
242     gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
243     gl.useProgramStages(m_pipeline_object_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
244     gl.useProgramStages(m_pipeline_object_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
245 
246     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
247 }
248 
249 /** Executes the test.
250  *
251  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
252  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
253  *  Note the function throws exception should an error occur!
254  **/
iterate()255 tcu::TestNode::IterateResult GeometryShaderCreateShaderProgramvTest::iterate()
256 {
257     const glw::Functions &gl       = m_context.getRenderContext().getFunctions();
258     const unsigned int n_so_po_ids = 3;
259     bool result                    = true;
260     glw::GLuint so_po_ids[n_so_po_ids];
261 
262     /* This test should only run if EXT_geometry_shader is supported. */
263     if (!m_is_geometry_shader_extension_supported)
264     {
265         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
266     }
267 
268     /* Initialize off-screen rendering */
269     initFBO();
270 
271     /* Form shader sources */
272     std::string fs_specialized_code     = specializeShader(1,
273                                                            /* parts */ &fs_code);
274     const char *fs_specialized_code_raw = fs_specialized_code.c_str();
275     std::string gs_specialized_code     = specializeShader(1,
276                                                            /* parts */ &gs_code);
277     const char *gs_specialized_code_raw = gs_specialized_code.c_str();
278     std::string vs_specialized_code     = specializeShader(1,
279                                                            /* parts */ &vs_code);
280     const char *vs_specialized_code_raw = vs_specialized_code.c_str();
281 
282     /* Try to create an invalid geometry shader program first */
283     glw::GLint link_status = GL_TRUE;
284 
285     m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
286                                          &gs_code);
287 
288     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
289 
290     if (m_gs_po_id == 0)
291     {
292         m_testCtx.getLog() << tcu::TestLog::Message << "glCreateShaderProgramv() call returned 0."
293                            << tcu::TestLog::EndMessage;
294 
295         result = false;
296         goto end;
297     }
298 
299     gl.getProgramiv(m_gs_po_id, GL_LINK_STATUS, &link_status);
300     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
301 
302     if (link_status != GL_FALSE)
303     {
304         m_testCtx.getLog() << tcu::TestLog::Message << "An invalid shader program was linked successfully."
305                            << tcu::TestLog::EndMessage;
306 
307         result = false;
308         goto end;
309     }
310 
311     gl.deleteProgram(m_gs_po_id);
312     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed.");
313 
314     /* Create shader programs */
315     m_fs_po_id = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, /* count */
316                                          &fs_specialized_code_raw);
317     m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
318                                          &gs_specialized_code_raw);
319     m_vs_po_id = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, /* count */
320                                          &vs_specialized_code_raw);
321 
322     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call(s) failed.");
323 
324     if (m_fs_po_id == 0 || m_gs_po_id == 0 || m_vs_po_id == 0)
325     {
326         m_testCtx.getLog() << tcu::TestLog::Message << "At least one glCreateShaderProgramv() call returned 0."
327                            << tcu::TestLog::EndMessage;
328 
329         result = false;
330         goto end;
331     }
332 
333     /* Make sure all shader programs were linked successfully */
334     so_po_ids[0] = m_fs_po_id;
335     so_po_ids[1] = m_gs_po_id;
336     so_po_ids[2] = m_vs_po_id;
337 
338     for (unsigned int n_po_id = 0; n_po_id != n_so_po_ids; ++n_po_id)
339     {
340         gl.getProgramiv(so_po_ids[n_po_id], GL_LINK_STATUS, &link_status);
341         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
342 
343         if (link_status != GL_TRUE)
344         {
345             m_testCtx.getLog() << tcu::TestLog::Message << "A valid shader program with id [" << so_po_ids[n_po_id]
346                                << "] was not linked successfully." << tcu::TestLog::EndMessage;
347 
348             result = false;
349             goto end;
350         }
351     }
352 
353     /* Set up the vertex array object */
354     gl.genVertexArrays(1, &m_vao_id);
355     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
356 
357     gl.bindVertexArray(m_vao_id);
358     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
359 
360     /* Set up the pipeline object */
361     initPipelineObject();
362 
363     /* Render a full-screen quad */
364     gl.bindProgramPipeline(m_pipeline_object_id);
365     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
366 
367     gl.drawArrays(GL_POINTS, 0, /* first */
368                   1);           /* count */
369     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
370 
371     /* Verify the rendering result */
372     unsigned char result_data[m_to_width * m_to_height * 4 /* rgba */];
373 
374     gl.readPixels(0, /* x */
375                   0, /* y */
376                   m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, result_data);
377     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
378 
379     for (unsigned int y = 0; y < m_to_height; ++y)
380     {
381         unsigned char *traveller_ptr = result_data + 4 * y;
382 
383         for (unsigned int x = 0; x < m_to_width; ++x)
384         {
385             if (traveller_ptr[0] != 0 || traveller_ptr[1] != 255 || traveller_ptr[2] != 0 || traveller_ptr[3] != 0)
386             {
387                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid result texel found at (" << x << ", " << y
388                                    << ")." << tcu::TestLog::EndMessage;
389 
390                 result = false;
391             }
392 
393             traveller_ptr += 4; /* rgba */
394         }
395     }
396 
397 end:
398     if (result)
399     {
400         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
401     }
402     else
403     {
404         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
405     }
406 
407     return STOP;
408 }
409 
410 /** Constructor
411  *
412  * @param context       Test context
413  * @param extParams     Not used.
414  * @param name          Test case's name
415  * @param description   Test case's description
416  **/
GeometryShaderGetShaderivTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)417 GeometryShaderGetShaderivTest::GeometryShaderGetShaderivTest(Context &context, const ExtParameters &extParams,
418                                                              const char *name, const char *description)
419     : TestCaseBase(context, extParams, name, description)
420     , m_gs_id(0)
421 {
422 }
423 
424 /** Deinitializes GLES objects created during the test. */
deinit()425 void GeometryShaderGetShaderivTest::deinit()
426 {
427     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
428 
429     if (m_gs_id != 0)
430     {
431         gl.deleteShader(m_gs_id);
432 
433         m_gs_id = 0;
434     }
435 
436     /* Release base class */
437     TestCaseBase::deinit();
438 }
439 
440 /** Executes the test.
441  *
442  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
443  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
444  *  Note the function throws exception should an error occur!
445  **/
iterate()446 tcu::TestNode::IterateResult GeometryShaderGetShaderivTest::iterate()
447 {
448     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
449     bool result              = true;
450 
451     /* This test should only run if EXT_geometry_shader is supported. */
452     if (!m_is_geometry_shader_extension_supported)
453     {
454         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
455     }
456 
457     /* Create a GS */
458     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
459 
460     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
461 
462     /* Check the type reported for the SO */
463     glw::GLint shader_type = GL_NONE;
464 
465     gl.getShaderiv(m_gs_id, GL_SHADER_TYPE, &shader_type);
466     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
467 
468     if ((glw::GLenum)shader_type != m_glExtTokens.GEOMETRY_SHADER)
469     {
470         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid shader type [" << shader_type
471                            << "] reported for a Geometry Shader" << tcu::TestLog::EndMessage;
472 
473         result = false;
474     }
475 
476     if (result)
477     {
478         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
479     }
480     else
481     {
482         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
483     }
484 
485     return STOP;
486 }
487 
488 /** Constructor
489  *
490  * @param context       Test context
491  * @param extParams     Not used.
492  * @param name          Test case's name
493  * @param description   Test case's description
494  **/
GeometryShaderGetProgramivTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)495 GeometryShaderGetProgramivTest::GeometryShaderGetProgramivTest(Context &context, const ExtParameters &extParams,
496                                                                const char *name, const char *description)
497     : TestCaseBase(context, extParams, name, description)
498     , m_po_id(0)
499 {
500 }
501 
502 /** Deinitializes GLES objects created during the test. */
deinit()503 void GeometryShaderGetProgramivTest::deinit()
504 {
505     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
506 
507     if (m_po_id != 0)
508     {
509         gl.deleteProgram(m_po_id);
510 
511         m_po_id = 0;
512     }
513 
514     /* Release base class */
515     TestCaseBase::deinit();
516 }
517 
518 /** Executes the test.
519  *
520  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
521  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
522  *  Note the function throws exception should an error occur!
523  **/
iterate()524 tcu::TestNode::IterateResult GeometryShaderGetProgramivTest::iterate()
525 {
526     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
527     bool result              = true;
528 
529     /* This test should only run if EXT_geometry_shader is supported. */
530     if (!m_is_geometry_shader_extension_supported)
531     {
532         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
533     }
534 
535     /* Create a program object */
536     m_po_id = gl.createProgram();
537 
538     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
539 
540     /* Verify that GS-specific queries cause a GL_INVALID_OPERATION error */
541     const glw::GLenum pnames[]  = {m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE,
542                                    m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE, m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS};
543     const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
544 
545     for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
546     {
547         glw::GLenum error_code = GL_NO_ERROR;
548         glw::GLenum pname      = pnames[n_pname];
549         glw::GLint rv          = -1;
550 
551         gl.getProgramiv(m_po_id, pname, &rv);
552 
553         error_code = gl.getError();
554 
555         if (error_code != GL_INVALID_OPERATION)
556         {
557             m_testCtx.getLog() << tcu::TestLog::Message << "No error generated by glGetProgramiv() for pname [" << pname
558                                << "]" << tcu::TestLog::EndMessage;
559 
560             result = false;
561         }
562     } /* for (all pnames) */
563 
564     if (result)
565     {
566         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
567     }
568     else
569     {
570         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
571     }
572 
573     return STOP;
574 }
575 
576 /** Constructor
577  *
578  * @param context       Test context
579  * @param extParams     Not used.
580  * @param name          Test case's name
581  * @param description   Test case's description
582  **/
GeometryShaderGetProgramiv2Test(Context & context,const ExtParameters & extParams,const char * name,const char * description)583 GeometryShaderGetProgramiv2Test::GeometryShaderGetProgramiv2Test(Context &context, const ExtParameters &extParams,
584                                                                  const char *name, const char *description)
585     : TestCaseBase(context, extParams, name, description)
586     , m_fs_id(0)
587     , m_po_id(0)
588     , m_vs_id(0)
589 {
590 }
591 
592 /** Deinitializes GLES objects created during the test. */
deinit()593 void GeometryShaderGetProgramiv2Test::deinit()
594 {
595     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
596 
597     if (m_fs_id != 0)
598     {
599         gl.deleteShader(m_fs_id);
600 
601         m_fs_id = 0;
602     }
603 
604     if (m_po_id != 0)
605     {
606         gl.deleteProgram(m_po_id);
607 
608         m_po_id = 0;
609     }
610 
611     if (m_vs_id != 0)
612     {
613         gl.deleteShader(m_vs_id);
614 
615         m_vs_id = 0;
616     }
617 
618     /* Release base class */
619     TestCaseBase::deinit();
620 }
621 
622 /** Executes the test.
623  *
624  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
625  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
626  *  Note the function throws exception should an error occur!
627  **/
iterate()628 tcu::TestNode::IterateResult GeometryShaderGetProgramiv2Test::iterate()
629 {
630     const glw::Functions &gl    = m_context.getRenderContext().getFunctions();
631     const glw::GLenum pnames[]  = {m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE,
632                                    m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE, m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS};
633     const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
634     bool result                 = true;
635 
636     /* This test should only run if EXT_geometry_shader is supported. */
637     if (!m_is_geometry_shader_extension_supported)
638     {
639         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
640     }
641 
642     /* Initialize the program object */
643     std::string specialized_minimal_fs     = specializeShader(1,
644                                                               /* parts */ &minimal_fs_code);
645     const char *specialized_minimal_fs_raw = specialized_minimal_fs.c_str();
646     std::string specialized_minimal_vs     = specializeShader(1,
647                                                               /* parts */ &minimal_vs_code);
648     const char *specialized_minimal_vs_raw = specialized_minimal_vs.c_str();
649 
650     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
651     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
652 
653     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
654 
655     m_po_id = gl.createProgram();
656 
657     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
658 
659     if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1, &specialized_minimal_fs_raw, m_vs_id, 1,
660                                     &specialized_minimal_vs_raw))
661     {
662         m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build a minimal test program object"
663                            << tcu::TestLog::EndMessage;
664 
665         result = false;
666         goto end;
667     }
668 
669     /* Verify that GS-specific queries cause a GL_INVALID_OPERATION error
670      * for a linked PO lacking the GS stage.
671      */
672     for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
673     {
674         glw::GLenum error_code = GL_NO_ERROR;
675         glw::GLenum pname      = pnames[n_pname];
676         glw::GLint rv          = -1;
677 
678         gl.getProgramiv(m_po_id, pname, &rv);
679 
680         error_code = gl.getError();
681 
682         if (error_code != GL_INVALID_OPERATION)
683         {
684             m_testCtx.getLog() << tcu::TestLog::Message << "No error generated by glGetProgramiv() for pname [" << pname
685                                << "]" << tcu::TestLog::EndMessage;
686 
687             result = false;
688         }
689     } /* for (all pnames) */
690 
691 end:
692     if (result)
693     {
694         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
695     }
696     else
697     {
698         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
699     }
700 
701     return STOP;
702 }
703 
704 /** Constructor
705  *
706  * @param context       Test context
707  * @param extParams     Not used.
708  * @param name          Test case's name
709  * @param description   Test case's description
710  **/
GeometryShaderGetProgramiv3Test(Context & context,const ExtParameters & extParams,const char * name,const char * description)711 GeometryShaderGetProgramiv3Test::GeometryShaderGetProgramiv3Test(Context &context, const ExtParameters &extParams,
712                                                                  const char *name, const char *description)
713     : TestCaseBase(context, extParams, name, description)
714     , m_fs_id(0)
715     , m_fs_po_id(0)
716     , m_gs_id(0)
717     , m_gs_po_id(0)
718     , m_pipeline_object_id(0)
719     , m_po_id(0)
720     , m_vs_id(0)
721     , m_vs_po_id(0)
722 {
723 }
724 
725 /* Compiles a shader object using caller-specified data.
726  *
727  * @param so_id   ID of a Shader Object to compile.
728  * @param so_body Body to use for the compilation process.
729  *
730  * @return true if the compilation succeeded, false otherwise */
buildShader(glw::GLuint so_id,const char * so_body)731 bool GeometryShaderGetProgramiv3Test::buildShader(glw::GLuint so_id, const char *so_body)
732 {
733     glw::GLint compile_status = GL_FALSE;
734     const glw::Functions &gl  = m_context.getRenderContext().getFunctions();
735     bool result               = false;
736 
737     gl.shaderSource(so_id, 1,           /* count */
738                     &so_body, DE_NULL); /* length */
739     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
740 
741     gl.compileShader(so_id);
742     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
743 
744     gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
745     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
746 
747     result = (compile_status == GL_TRUE);
748 
749     return result;
750 }
751 
752 /** Builds a single shader program object using caller-specified data.
753  *
754  *  @param out_spo_id Deref will be set to the ID of the created shader program object.
755  *                    Must not be NULL.
756  *  @param spo_bits   Bits to be passed to the glCreateShaderProgramv() call.
757  *  @param spo_body   Body to use for the glCreateShaderProgramv() call.
758  *
759  *  @return true if the shader program object was linked successfully, false otherwise.
760  */
buildShaderProgram(glw::GLuint * out_spo_id,glw::GLenum spo_bits,const char * spo_body)761 bool GeometryShaderGetProgramiv3Test::buildShaderProgram(glw::GLuint *out_spo_id, glw::GLenum spo_bits,
762                                                          const char *spo_body)
763 {
764     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
765     glw::GLint link_status   = GL_FALSE;
766     bool result              = true;
767 
768     *out_spo_id = gl.createShaderProgramv(spo_bits, 1, /* count */
769                                           &spo_body);
770 
771     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
772 
773     gl.getProgramiv(*out_spo_id, GL_LINK_STATUS, &link_status);
774     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
775 
776     result = (link_status == GL_TRUE);
777 
778     return result;
779 }
780 
781 /** Deinitializes GLES objects created during the test. */
deinit()782 void GeometryShaderGetProgramiv3Test::deinit()
783 {
784     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
785 
786     deinitPO();
787     deinitSOs(true);
788     deinitSPOs(true);
789 
790     if (m_pipeline_object_id != 0)
791     {
792         gl.deleteProgramPipelines(1, &m_pipeline_object_id);
793 
794         m_pipeline_object_id = 0;
795     }
796 
797     /* Release base class */
798     TestCaseBase::deinit();
799 }
800 
801 /** Deinitializes a program object created for the conformance test. */
deinitPO()802 void GeometryShaderGetProgramiv3Test::deinitPO()
803 {
804     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
805 
806     if (m_po_id != 0)
807     {
808         gl.deleteProgram(m_po_id);
809 
810         m_po_id = 0;
811     }
812 }
813 
814 /** Deinitializes shader objects created for the conformance test. */
deinitSOs(bool release_all_SOs)815 void GeometryShaderGetProgramiv3Test::deinitSOs(bool release_all_SOs)
816 {
817     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
818 
819     if (m_fs_id != 0 && release_all_SOs)
820     {
821         gl.deleteShader(m_fs_id);
822 
823         m_fs_id = 0;
824     }
825 
826     if (m_gs_id != 0)
827     {
828         gl.deleteShader(m_gs_id);
829 
830         m_gs_id = 0;
831     }
832 
833     if (m_vs_id != 0 && release_all_SOs)
834     {
835         gl.deleteShader(m_vs_id);
836 
837         m_vs_id = 0;
838     }
839 }
840 
841 /** Deinitializes shader program objects created for the conformance test. */
deinitSPOs(bool release_all_SPOs)842 void GeometryShaderGetProgramiv3Test::deinitSPOs(bool release_all_SPOs)
843 {
844     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
845 
846     if (m_fs_po_id != 0 && release_all_SPOs)
847     {
848         gl.deleteProgram(m_fs_po_id);
849 
850         m_fs_po_id = 0;
851     }
852 
853     if (m_gs_po_id != 0)
854     {
855         gl.deleteProgram(m_gs_po_id);
856 
857         m_gs_po_id = 0;
858     }
859 
860     if (m_vs_po_id != 0 && release_all_SPOs)
861     {
862         gl.deleteProgram(m_vs_po_id);
863 
864         m_vs_po_id = 0;
865     }
866 }
867 
868 /** Retrieves ES SL layout qualifier, corresponding to user-specified
869  *  primitive type.
870  *
871  *  @param primitive_type Primitive type (described by a GLenum value)
872  *                        to use for the query.
873  *
874  *  @return Requested layout qualifier.
875  */
getLayoutQualifierForPrimitiveType(glw::GLenum primitive_type)876 std::string GeometryShaderGetProgramiv3Test::getLayoutQualifierForPrimitiveType(glw::GLenum primitive_type)
877 {
878     std::string result;
879 
880     switch (primitive_type)
881     {
882     case GL_LINE_STRIP:
883         result = "line_strip";
884         break;
885     case GL_LINES_ADJACENCY:
886         result = "lines_adjacency";
887         break;
888     case GL_POINTS:
889         result = "points";
890         break;
891     case GL_TRIANGLES:
892         result = "triangles";
893         break;
894     case GL_TRIANGLE_STRIP:
895         result = "triangle_strip";
896         break;
897 
898     default:
899     {
900         DE_ASSERT(0);
901     }
902     } /* switch (primitive_type) */
903 
904     return result;
905 }
906 
907 /** Retrieves body of a geometry shadet to be used for the conformance test.
908  *  The body is generated, according to the properties described by the
909  *  run descriptor passed as an argument.
910  *
911  *  @param run Test run descriptor.
912  *
913  *  @return Requested string.
914  */
getGSCode(const _run & run)915 std::string GeometryShaderGetProgramiv3Test::getGSCode(const _run &run)
916 {
917     std::stringstream code_sstream;
918 
919     code_sstream << "${VERSION}\n"
920                     "${GEOMETRY_SHADER_REQUIRE}\n"
921                     "\n"
922                     "layout("
923                  << getLayoutQualifierForPrimitiveType(run.input_primitive_type)
924                  << ", "
925                     "invocations = "
926                  << run.invocations
927                  << ") in;\n"
928                     "layout("
929                  << getLayoutQualifierForPrimitiveType(run.output_primitive_type)
930                  << ", "
931                     "max_vertices = "
932                  << run.max_vertices
933                  << ") out;\n"
934                     "\n"
935                     "out gl_PerVertex {\n"
936                     "    vec4 gl_Position;\n"
937                     "};\n"
938                     "\n"
939                     "void main()\n"
940                     "{\n"
941                     "    for (int n = 0; n < "
942                  << run.max_vertices
943                  << "; ++n)\n"
944                     "    {\n"
945                     "        gl_Position = vec4(n, 0.0, 0.0, 1.0);\n"
946                     "        EmitVertex();\n"
947                     "    }\n"
948                     "\n"
949                     "    EndPrimitive();\n"
950                     "}\n";
951 
952     return code_sstream.str();
953 }
954 
955 /** Initializes internal _runs member with test iteration settings for all test runs. */
initTestRuns()956 void GeometryShaderGetProgramiv3Test::initTestRuns()
957 {
958     /*                   input primitive type | invocations | max vertices | output primitive type *
959      *----------------------------------------+-------------+--------------+-----------------------*/
960     _runs.push_back(_run(GL_LINES_ADJACENCY, 3, 16, GL_POINTS));
961     _runs.push_back(_run(GL_TRIANGLES, 12, 37, GL_LINE_STRIP));
962     _runs.push_back(_run(GL_POINTS, 31, 75, GL_TRIANGLE_STRIP));
963 }
964 
965 /** Executes the test.
966  *
967  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
968  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
969  *  Note the function throws exception should an error occur!
970  **/
iterate()971 tcu::TestNode::IterateResult GeometryShaderGetProgramiv3Test::iterate()
972 {
973     const glw::Functions &gl             = m_context.getRenderContext().getFunctions();
974     glw::GLint gs_spo_id                 = 0;
975     unsigned int n_run                   = 0;
976     unsigned int n_separable_object_case = 0;
977     bool result                          = true;
978 
979     /* This test should only run if EXT_geometry_shader is supported. */
980     if (!m_is_geometry_shader_extension_supported)
981     {
982         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
983     }
984 
985     /* Prepare specialized versions of minimal fragment & vertex shaders */
986     std::string minimal_fs_specialized     = specializeShader(1,
987                                                               /* parts */ &minimal_fs_code);
988     const char *minimal_fs_specialized_raw = minimal_fs_specialized.c_str();
989     std::string minimal_vs_specialized     = specializeShader(1, &minimal_vs_code);
990     const char *minimal_vs_specialized_raw = minimal_vs_specialized.c_str();
991 
992     /* Set up the fragment & the vertex shaders */
993     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
994     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
995     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
996 
997     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
998 
999     if (!buildShader(m_fs_id, minimal_fs_specialized_raw) || !buildShader(m_vs_id, minimal_vs_specialized_raw))
1000     {
1001         m_testCtx.getLog() << tcu::TestLog::Message << "Either FS or VS failed to build." << tcu::TestLog::EndMessage;
1002 
1003         result = false;
1004         goto end;
1005     }
1006 
1007     /* Set up the test program object */
1008     m_po_id = gl.createProgram();
1009 
1010     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1011 
1012     gl.attachShader(m_po_id, m_fs_id);
1013     gl.attachShader(m_po_id, m_gs_id);
1014     gl.attachShader(m_po_id, m_vs_id);
1015     GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
1016 
1017     /* Set up the fragment & the vertex shader programs */
1018     if (!buildShaderProgram(&m_fs_po_id, GL_FRAGMENT_SHADER, minimal_fs_specialized_raw) ||
1019         !buildShaderProgram(&m_vs_po_id, GL_VERTEX_SHADER, minimal_vs_specialized_raw))
1020     {
1021         m_testCtx.getLog() << tcu::TestLog::Message << "Either FS or VS SPOs failed to build."
1022                            << tcu::TestLog::EndMessage;
1023 
1024         result = false;
1025         goto end;
1026     }
1027 
1028     /* Set up test runs */
1029     initTestRuns();
1030 
1031     /* The test should check both a geometry shader program object and a full-blown PO
1032      * consisting of FS, GS and VS. */
1033     for (n_separable_object_case = 0; n_separable_object_case < 2; /* PO, SPO cases */
1034          ++n_separable_object_case)
1035     {
1036         bool should_use_separable_object = (n_separable_object_case != 0);
1037 
1038         /* Iterate over all test runs */
1039         for (n_run = 0; n_run < _runs.size(); ++n_run)
1040         {
1041             const _run &current_run             = _runs[n_run];
1042             std::string gs_code                 = getGSCode(current_run);
1043             const char *gs_code_raw             = gs_code.c_str();
1044             std::string gs_code_specialized     = specializeShader(1, /* parts */
1045                                                                    &gs_code_raw);
1046             const char *gs_code_specialized_raw = gs_code_specialized.c_str();
1047 
1048             if (should_use_separable_object)
1049             {
1050                 /* Deinitialize any objects that may have been created in previous iterations */
1051                 deinitSPOs(false);
1052 
1053                 /* Set up the geometry shader program object */
1054                 if (!buildShaderProgram(&m_gs_po_id, GL_GEOMETRY_SHADER, gs_code_specialized_raw))
1055                 {
1056                     m_testCtx.getLog() << tcu::TestLog::Message << "Failed to compile a geometry shader program object"
1057                                        << tcu::TestLog::EndMessage;
1058 
1059                     result = false;
1060                     goto end;
1061                 }
1062             } /* if (should_use_pipeline_object) */
1063             else
1064             {
1065                 gl.bindProgramPipeline(0);
1066                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
1067 
1068                 /* Set up the geometry shader object */
1069                 if (!buildShader(m_gs_id, gs_code_specialized_raw))
1070                 {
1071                     m_testCtx.getLog() << tcu::TestLog::Message << "Failed to compile a geometry shader object."
1072                                        << tcu::TestLog::EndMessage;
1073 
1074                     result = false;
1075                     goto end;
1076                 }
1077 
1078                 /* Set up the program object */
1079                 glw::GLint link_status = GL_FALSE;
1080 
1081                 gl.linkProgram(m_po_id);
1082                 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1083 
1084                 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1085 
1086                 if (link_status == GL_FALSE)
1087                 {
1088                     m_testCtx.getLog() << tcu::TestLog::Message << "Test program object failed to link"
1089                                        << tcu::TestLog::EndMessage;
1090 
1091                     result = false;
1092                     goto end;
1093                 }
1094 
1095                 /* Bind the PO to the rendering context */
1096                 gl.useProgram(m_po_id);
1097                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1098             }
1099 
1100             /* Execute the queries */
1101             glw::GLuint po_id                              = (should_use_separable_object) ? m_gs_po_id : m_po_id;
1102             glw::GLint result_geometry_linked_vertices_out = 0;
1103             glw::GLint result_geometry_linked_input_type   = 0;
1104             glw::GLint result_geometry_linked_output_type  = 0;
1105             glw::GLint result_geometry_shader_invocations  = 0;
1106 
1107             gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, &result_geometry_linked_vertices_out);
1108             GLU_EXPECT_NO_ERROR(gl.getError(),
1109                                 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_VERTICES_OUT_EXT query.");
1110 
1111             gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE, &result_geometry_linked_input_type);
1112             GLU_EXPECT_NO_ERROR(gl.getError(),
1113                                 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query.");
1114 
1115             gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE, &result_geometry_linked_output_type);
1116             GLU_EXPECT_NO_ERROR(gl.getError(),
1117                                 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT query.");
1118 
1119             gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS, &result_geometry_shader_invocations);
1120             GLU_EXPECT_NO_ERROR(gl.getError(),
1121                                 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query.");
1122 
1123             if (current_run.input_primitive_type != (glw::GLenum)result_geometry_linked_input_type)
1124             {
1125                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query value "
1126                                    << "[" << result_geometry_linked_input_type
1127                                    << "]"
1128                                       " does not match the test run setting "
1129                                       "["
1130                                    << current_run.input_primitive_type << "]" << tcu::TestLog::EndMessage;
1131 
1132                 result = false;
1133             }
1134 
1135             if (current_run.invocations != result_geometry_shader_invocations)
1136             {
1137                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_SHADER_INVOCATIONS_EXT query value "
1138                                    << "[" << result_geometry_shader_invocations
1139                                    << "]"
1140                                       " does not match the test run setting "
1141                                       "["
1142                                    << current_run.input_primitive_type << "]" << tcu::TestLog::EndMessage;
1143 
1144                 result = false;
1145             }
1146 
1147             if (current_run.max_vertices != result_geometry_linked_vertices_out)
1148             {
1149                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_VERTICES_OUT query value "
1150                                    << "[" << result_geometry_linked_vertices_out
1151                                    << "]"
1152                                       " does not match the test run setting "
1153                                       "["
1154                                    << current_run.max_vertices << "]" << tcu::TestLog::EndMessage;
1155 
1156                 result = false;
1157             }
1158 
1159             if (current_run.output_primitive_type != (glw::GLenum)result_geometry_linked_output_type)
1160             {
1161                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT query value "
1162                                    << "[" << result_geometry_linked_output_type
1163                                    << "]"
1164                                       " does not match the test run setting "
1165                                       "["
1166                                    << current_run.output_primitive_type << "]" << tcu::TestLog::EndMessage;
1167 
1168                 result = false;
1169             }
1170         } /* for (all test runs) */
1171     }     /* for (PO & SPO cases) */
1172 
1173     /* One more check: build a pipeline object which only defines a FS & VS stages,
1174      *                 and check what GS SPO ID the object reports. */
1175     gl.genProgramPipelines(1, &m_pipeline_object_id);
1176     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
1177 
1178     gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
1179     gl.useProgramStages(m_pipeline_object_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
1180     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
1181 
1182     gl.getProgramPipelineiv(m_pipeline_object_id, m_glExtTokens.GEOMETRY_SHADER, &gs_spo_id);
1183     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed.");
1184 
1185     if (gs_spo_id != 0)
1186     {
1187         m_testCtx.getLog() << tcu::TestLog::Message << "Pipeline object reported [" << gs_spo_id << "]"
1188                            << " for GL_GEOMETRY_SHADER_EXT query, even though no GS SPO was bound."
1189                            << tcu::TestLog::EndMessage;
1190 
1191         result = false;
1192     }
1193 
1194 end:
1195     if (result)
1196     {
1197         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1198     }
1199     else
1200     {
1201         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1202     }
1203 
1204     return STOP;
1205 }
1206 
1207 /** Constructor
1208  *
1209  * @param context       Test context
1210  * @param extParams     Not used.
1211  * @param name          Test case's name
1212  * @param description   Test case's description
1213  **/
GeometryShaderDrawCallWithFSAndGS(Context & context,const ExtParameters & extParams,const char * name,const char * description)1214 GeometryShaderDrawCallWithFSAndGS::GeometryShaderDrawCallWithFSAndGS(Context &context, const ExtParameters &extParams,
1215                                                                      const char *name, const char *description)
1216     : TestCaseBase(context, extParams, name, description)
1217     , m_fs_po_id(0)
1218     , m_gs_po_id(0)
1219     , m_pipeline_object_id(0)
1220     , m_vao_id(0)
1221 {
1222 }
1223 
1224 /** Deinitializes GLES objects created during the test. */
deinit()1225 void GeometryShaderDrawCallWithFSAndGS::deinit()
1226 {
1227     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1228 
1229     if (m_fs_po_id != 0)
1230     {
1231         gl.deleteProgram(m_fs_po_id);
1232 
1233         m_fs_po_id = 0;
1234     }
1235 
1236     if (m_gs_po_id != 0)
1237     {
1238         gl.deleteProgram(m_gs_po_id);
1239 
1240         m_gs_po_id = 0;
1241     }
1242 
1243     if (m_pipeline_object_id != 0)
1244     {
1245         gl.deleteProgramPipelines(1, &m_pipeline_object_id);
1246 
1247         m_pipeline_object_id = 0;
1248     }
1249 
1250     if (m_vao_id != 0)
1251     {
1252         gl.deleteVertexArrays(1, &m_vao_id);
1253 
1254         m_vao_id = 0;
1255     }
1256 
1257     /* Release base class */
1258     TestCaseBase::deinit();
1259 }
1260 
1261 /** Executes the test.
1262  *
1263  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1264  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1265  *  Note the function throws exception should an error occur!
1266  **/
iterate()1267 tcu::TestNode::IterateResult GeometryShaderDrawCallWithFSAndGS::iterate()
1268 {
1269     glw::GLenum error_code   = GL_NO_ERROR;
1270     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1271     bool result              = true;
1272 
1273     /* This test should only run if EXT_geometry_shader is supported. */
1274     if (!m_is_geometry_shader_extension_supported)
1275     {
1276         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1277     }
1278 
1279     /* Create & bind a VAO */
1280     gl.genVertexArrays(1, &m_vao_id);
1281     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1282 
1283     gl.bindVertexArray(m_vao_id);
1284     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1285 
1286     /* Create shader program objects */
1287     std::string code_fs_specialized     = specializeShader(1, /* parts */
1288                                                            &minimal_fs_code);
1289     const char *code_fs_specialized_raw = code_fs_specialized.c_str();
1290     std::string code_gs_specialized     = specializeShader(1, /* parts */
1291                                                            &minimal_gs_code);
1292     const char *code_gs_specialized_raw = code_gs_specialized.c_str();
1293     glw::GLint link_status              = GL_FALSE;
1294 
1295     m_fs_po_id = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, /* count */
1296                                          &code_fs_specialized_raw);
1297     m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
1298                                          &code_gs_specialized_raw);
1299 
1300     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call(s) failed.");
1301 
1302     gl.getProgramiv(m_fs_po_id, GL_LINK_STATUS, &link_status);
1303 
1304     if (link_status != GL_TRUE)
1305     {
1306         m_testCtx.getLog() << tcu::TestLog::Message << "Minimal fragment shader program failed to link."
1307                            << tcu::TestLog::EndMessage;
1308 
1309         result = false;
1310         goto end;
1311     }
1312 
1313     gl.getProgramiv(m_gs_po_id, GL_LINK_STATUS, &link_status);
1314 
1315     if (link_status != GL_TRUE)
1316     {
1317         m_testCtx.getLog() << tcu::TestLog::Message << "Minimal geometry shader program failed to link."
1318                            << tcu::TestLog::EndMessage;
1319 
1320         result = false;
1321         goto end;
1322     }
1323 
1324     /* Create & set up a pipeline object */
1325     gl.genProgramPipelines(1, &m_pipeline_object_id);
1326     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
1327 
1328     gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
1329     gl.useProgramStages(m_pipeline_object_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
1330     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
1331 
1332     gl.bindProgramPipeline(m_pipeline_object_id);
1333     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
1334 
1335     /* Try to do a draw call */
1336     gl.drawArrays(GL_POINTS, 0, /* first */
1337                   1);           /* count */
1338 
1339     error_code = gl.getError();
1340     if (error_code != GL_INVALID_OPERATION)
1341     {
1342         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid draw call generated an error code [" << error_code
1343                            << "]"
1344                               " which is different from the expected GL_INVALID_OPERATION."
1345                            << tcu::TestLog::EndMessage;
1346 
1347         result = false;
1348     }
1349 
1350 end:
1351     // m_pipeline_object_id is generated in this function, need to be freed
1352     if (m_pipeline_object_id)
1353     {
1354         gl.deleteProgramPipelines(1, &m_pipeline_object_id);
1355         m_pipeline_object_id = 0;
1356     }
1357 
1358     // m_gs_po_id is generated in this function, need to be freed
1359     if (m_gs_po_id)
1360     {
1361         gl.deleteProgram(m_gs_po_id);
1362         m_gs_po_id = 0;
1363     }
1364 
1365     // m_fs_po_id is generated in this function, need to be freed
1366     if (m_fs_po_id)
1367     {
1368         gl.deleteProgram(m_fs_po_id);
1369         m_fs_po_id = 0;
1370     }
1371 
1372     // m_vao_id is generated in this function, need to be freed
1373     if (m_vao_id)
1374     {
1375         gl.deleteVertexArrays(1, &m_vao_id);
1376         m_vao_id = 0;
1377     }
1378 
1379     /* All done */
1380     if (result)
1381     {
1382         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1383     }
1384     else
1385     {
1386         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1387     }
1388 
1389     return STOP;
1390 }
1391 
1392 /** Constructor
1393  *
1394  * @param context       Test context
1395  * @param extParams     Not used.
1396  * @param name          Test case's name
1397  * @param description   Test case's description
1398  **/
GeometryShaderMaxImageUniformsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1399 GeometryShaderMaxImageUniformsTest::GeometryShaderMaxImageUniformsTest(Context &context, const ExtParameters &extParams,
1400                                                                        const char *name, const char *description)
1401     : TestCaseBase(context, extParams, name, description)
1402     , m_fs_id(0)
1403     , m_gl_max_geometry_image_uniforms_ext_value(0)
1404     , m_gs_id(0)
1405     , m_po_id(0)
1406     , m_texture_ids(NULL)
1407     , m_tfbo_id(0)
1408     , m_vao_id(0)
1409     , m_vs_id(0)
1410 {
1411     //Bug-15063 Only GLSL 4.50 supports opaque types
1412     if (m_glslVersion >= glu::GLSL_VERSION_130)
1413     {
1414         m_glslVersion = glu::GLSL_VERSION_450;
1415     }
1416 }
1417 
1418 /** Deinitializes GLES objects created during the test. */
deinit()1419 void GeometryShaderMaxImageUniformsTest::deinit()
1420 {
1421     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1422 
1423     if (m_fs_id != 0)
1424     {
1425         gl.deleteShader(m_fs_id);
1426 
1427         m_fs_id = 0;
1428     }
1429 
1430     if (m_gs_id != 0)
1431     {
1432         gl.deleteShader(m_gs_id);
1433 
1434         m_gs_id = 0;
1435     }
1436 
1437     if (m_po_id != 0)
1438     {
1439         gl.deleteProgram(m_po_id);
1440 
1441         m_po_id = 0;
1442     }
1443 
1444     if (m_texture_ids != NULL)
1445     {
1446         gl.deleteTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids);
1447 
1448         delete[] m_texture_ids;
1449         m_texture_ids = NULL;
1450     }
1451 
1452     if (m_tfbo_id != 0)
1453     {
1454         gl.deleteBuffers(1, &m_tfbo_id);
1455         m_tfbo_id = 0;
1456     }
1457 
1458     if (m_vao_id != 0)
1459     {
1460         gl.deleteVertexArrays(1, &m_vao_id);
1461         m_vao_id = 0;
1462     }
1463 
1464     if (m_vs_id != 0)
1465     {
1466         gl.deleteShader(m_vs_id);
1467 
1468         m_vs_id = 0;
1469     }
1470 
1471     /* Set GL_PACK_ALIGNMENT to default value. */
1472     gl.pixelStorei(GL_PACK_ALIGNMENT, 4 /*default value taken from specification*/);
1473     GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname.");
1474 
1475     /* Release base class */
1476     TestCaseBase::deinit();
1477 }
1478 
1479 /* Retrieves test-specific geometry shader source code.
1480  *
1481  * @return Requested string.
1482  */
getGSCode()1483 std::string GeometryShaderMaxImageUniformsTest::getGSCode()
1484 {
1485     std::stringstream code_sstream;
1486 
1487     /* Form the GS */
1488     code_sstream << "${VERSION}\n"
1489                     "${GEOMETRY_SHADER_REQUIRE}\n"
1490                     "\n"
1491                     "layout (points)                   in;\n"
1492                     "layout (points, max_vertices = 1) out;\n"
1493                     "\n"
1494                     "precision highp iimage2D;\n"
1495                     "\n"
1496                     "ivec4 counter = ivec4(0);\n"
1497                     "\n";
1498 
1499     for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
1500     {
1501         code_sstream << "layout(binding = " << n_img << ", r32i) uniform iimage2D img" << n_img << ";\n";
1502     }
1503 
1504     code_sstream << "\n"
1505                     "void main()\n"
1506                     "{\n";
1507 
1508     for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
1509     {
1510         code_sstream << "    counter += imageLoad(img" << n_img << ", ivec2(0, 0));\n";
1511     }
1512 
1513     code_sstream << "\n"
1514                     "    gl_Position = vec4(float(counter.x), 0.0, 0.0, 1.0);\n"
1515                     "    EmitVertex();\n"
1516                     "}\n";
1517 
1518     /* Form a specialized version of the GS source code */
1519     std::string gs_code             = code_sstream.str();
1520     const char *gs_code_raw         = gs_code.c_str();
1521     std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw);
1522 
1523     return gs_code_specialized;
1524 }
1525 
1526 /** Executes the test.
1527  *
1528  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1529  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1530  *  Note the function throws exception should an error occur!
1531  **/
iterate()1532 tcu::TestNode::IterateResult GeometryShaderMaxImageUniformsTest::iterate()
1533 {
1534     glw::GLint counter                    = 0;
1535     glw::GLint expectedValue              = 0;
1536     bool has_shader_compilation_failed    = true;
1537     glw::GLfloat *ptr                     = DE_NULL;
1538     bool result                           = true;
1539     const glw::GLchar *feedbackVaryings[] = {"gl_Position"};
1540 
1541     std::string fs_code_specialized     = "";
1542     const char *fs_code_specialized_raw = DE_NULL;
1543     std::string gs_code_specialized     = "";
1544     const char *gs_code_specialized_raw = DE_NULL;
1545     std::string vs_code_specialized     = "";
1546     const char *vs_code_specialized_raw = DE_NULL;
1547 
1548     /* This test should only run if EXT_geometry_shader is supported. */
1549     if (!m_is_geometry_shader_extension_supported)
1550     {
1551         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1552     }
1553 
1554     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1555 
1556     /* Retrieve GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname value */
1557     gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_IMAGE_UNIFORMS, &m_gl_max_geometry_image_uniforms_ext_value);
1558     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname");
1559 
1560     /* Retrieve GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT pname value */
1561     glw::GLint m_gl_max_geometry_texture_image_units_ext_value = 0;
1562     gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &m_gl_max_geometry_texture_image_units_ext_value);
1563     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname");
1564 
1565     /* Retrieve GL_MAX_IMAGE_UNITS pname value */
1566     glw::GLint m_gl_max_image_units_value = 0;
1567     gl.getIntegerv(GL_MAX_IMAGE_UNITS, &m_gl_max_image_units_value);
1568     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_IMAGE_UNITS pname");
1569 
1570     /* Check if m_gl_max_geometry_image_uniforms_value is less than or equal zero. */
1571     if (m_gl_max_geometry_image_uniforms_ext_value <= 0)
1572     {
1573         m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
1574                            << "[" << m_gl_max_geometry_image_uniforms_ext_value
1575                            << "]"
1576                               " is less than or equal zero. Image uniforms in Geometry Shader"
1577                               " are not supported."
1578                            << tcu::TestLog::EndMessage;
1579 
1580         if (m_gl_max_geometry_image_uniforms_ext_value == 0)
1581         {
1582             throw tcu::NotSupportedError("GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT is 0");
1583         }
1584         else
1585         {
1586             result = false;
1587             goto end;
1588         }
1589     }
1590 
1591     /* Check if m_gl_max_image_units_value is less than m_gl_max_geometry_image_uniforms_value. */
1592     if (m_gl_max_image_units_value < m_gl_max_geometry_image_uniforms_ext_value)
1593     {
1594         m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
1595                            << "[" << m_gl_max_geometry_image_uniforms_ext_value
1596                            << "]"
1597                               " is greater than GL_MAX_IMAGE_UNITS query value "
1598                               "["
1599                            << m_gl_max_image_units_value << "]." << tcu::TestLog::EndMessage;
1600 
1601         result = false;
1602         goto end;
1603     }
1604 
1605     /* Create a program object. */
1606     m_po_id = gl.createProgram();
1607     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1608 
1609     /* Create shader objects. */
1610     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1611     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1612     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1613 
1614     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1615 
1616     /* Configure which outputs should be captured by Transform Feedback. */
1617     gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
1618 
1619     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
1620 
1621     /* Try to link the test program object */
1622     fs_code_specialized     = specializeShader(1, &minimal_fs_code);
1623     fs_code_specialized_raw = fs_code_specialized.c_str();
1624 
1625     gs_code_specialized     = getGSCode();
1626     gs_code_specialized_raw = gs_code_specialized.c_str();
1627 
1628     vs_code_specialized     = specializeShader(1, &minimal_vs_code);
1629     vs_code_specialized_raw = vs_code_specialized.c_str();
1630 
1631     if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,                  /* n_sh1_body_parts */
1632                                     &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1633                                     &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1634                                     &fs_code_specialized_raw, &has_shader_compilation_failed))
1635     {
1636         m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
1637 
1638         result = false;
1639         goto end;
1640     }
1641 
1642     /* Use program. */
1643     gl.useProgram(m_po_id);
1644     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1645 
1646     /* Allocate memory for m_max_image_units_value Texture Objects. */
1647     m_texture_ids = new glw::GLuint[m_gl_max_geometry_image_uniforms_ext_value];
1648 
1649     /* Generate m_max_image_units_value Texture Objects. */
1650     gl.genTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids);
1651     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
1652 
1653     /* Set GL_PACK_ALIGNMENT to 1. */
1654     gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1655     GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname.");
1656 
1657     /* Bind integer 2D texture objects of resolution 1x1 to image units. */
1658     for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
1659     {
1660         glw::GLint texture = m_texture_ids[n_img];
1661         glw::GLint value   = n_img + 1;
1662 
1663         gl.bindTexture(GL_TEXTURE_2D, texture);
1664         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1665 
1666         gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_R32I, 1 /*width*/, 1 /*height*/);
1667         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1668 
1669         gl.texSubImage2D(GL_TEXTURE_2D, 0 /*level*/, 0 /*xoffset*/, 0 /*yoffset*/, 1 /*width*/, 1 /*height*/,
1670                          GL_RED_INTEGER, GL_INT, &value);
1671         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
1672 
1673         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1674         GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
1675 
1676         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1677         GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
1678 
1679         gl.bindImageTexture(n_img, texture, 0 /*level*/, GL_FALSE /*is layered?*/, 0 /*layer*/, GL_READ_ONLY, GL_R32I);
1680         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed.");
1681     }
1682 
1683     /* Configure VAO. */
1684     gl.genVertexArrays(1, &m_vao_id);
1685     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1686 
1687     gl.bindVertexArray(m_vao_id);
1688     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1689 
1690     /* Create a Buffer Object for Transform Feedback's outputs. */
1691     gl.genBuffers(1, &m_tfbo_id);
1692     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1693 
1694     gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
1695     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1696 
1697     gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, NULL, GL_STATIC_READ);
1698     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1699 
1700     /* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
1701     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tfbo_id);
1702     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
1703 
1704     /* Disable rasterization and make a draw call. After that, turn on rasterization. */
1705     gl.enable(GL_RASTERIZER_DISCARD);
1706     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
1707 
1708     gl.beginTransformFeedback(GL_POINTS);
1709     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
1710 
1711     gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
1712     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
1713 
1714     gl.endTransformFeedback();
1715     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
1716 
1717     gl.disable(GL_RASTERIZER_DISCARD);
1718     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
1719 
1720     /* Retrieve value from Transform Feedback. */
1721     counter = 0;
1722     ptr     = (glw::GLfloat *)gl.mapBufferRange(
1723         GL_ARRAY_BUFFER, 0, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
1724 
1725     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
1726 
1727     counter = int(ptr[0] + 0.5f);
1728 
1729     gl.unmapBuffer(GL_ARRAY_BUFFER);
1730     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
1731 
1732     /* Calculate expected value. */
1733     expectedValue = m_gl_max_geometry_image_uniforms_ext_value * (m_gl_max_geometry_image_uniforms_ext_value + 1) / 2;
1734 
1735     if (counter != expectedValue)
1736     {
1737         result = false;
1738     }
1739 
1740 end:
1741     if (result)
1742     {
1743         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1744     }
1745     else
1746     {
1747         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1748     }
1749 
1750     return STOP;
1751 }
1752 
1753 /** Constructor
1754  *
1755  * @param context       Test context
1756  * @param extParams     Not used.
1757  * @param name          Test case's name
1758  * @param description   Test case's description
1759  **/
GeometryShaderMaxShaderStorageBlocksTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1760 GeometryShaderMaxShaderStorageBlocksTest::GeometryShaderMaxShaderStorageBlocksTest(Context &context,
1761                                                                                    const ExtParameters &extParams,
1762                                                                                    const char *name,
1763                                                                                    const char *description)
1764     : TestCaseBase(context, extParams, name, description)
1765     , m_fs_id(0)
1766     , m_gl_max_geometry_shader_storage_blocks_ext_value(0)
1767     , m_gs_id(0)
1768     , m_po_id(0)
1769     , m_ssbo_id(0)
1770     , m_tfbo_id(0)
1771     , m_vao_id(0)
1772     , m_vs_id(0)
1773 {
1774 }
1775 
1776 /** Deinitializes GLES objects created during the test. */
deinit()1777 void GeometryShaderMaxShaderStorageBlocksTest::deinit()
1778 {
1779     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1780 
1781     if (m_fs_id != 0)
1782     {
1783         gl.deleteShader(m_fs_id);
1784         m_fs_id = 0;
1785     }
1786 
1787     if (m_gs_id != 0)
1788     {
1789         gl.deleteShader(m_gs_id);
1790         m_gs_id = 0;
1791     }
1792 
1793     if (m_po_id != 0)
1794     {
1795         gl.deleteProgram(m_po_id);
1796         m_po_id = 0;
1797     }
1798 
1799     if (m_ssbo_id != 0)
1800     {
1801         gl.deleteBuffers(1, &m_ssbo_id);
1802         m_ssbo_id = 0;
1803     }
1804 
1805     if (m_tfbo_id != 0)
1806     {
1807         gl.deleteBuffers(1, &m_tfbo_id);
1808         m_tfbo_id = 0;
1809     }
1810 
1811     if (m_vao_id != 0)
1812     {
1813         gl.deleteVertexArrays(1, &m_vao_id);
1814         m_vao_id = 0;
1815     }
1816 
1817     if (m_vs_id != 0)
1818     {
1819         gl.deleteShader(m_vs_id);
1820         m_vs_id = 0;
1821     }
1822 
1823     /* Release base class */
1824     TestCaseBase::deinit();
1825 }
1826 
1827 /* Retrieves test-specific geometry shader source code.
1828  *
1829  * @return Requested string.
1830  */
getGSCode()1831 std::string GeometryShaderMaxShaderStorageBlocksTest::getGSCode()
1832 {
1833     std::stringstream code_sstream;
1834 
1835     /* Form the GS */
1836     code_sstream << "${VERSION}\n"
1837                     "${GEOMETRY_SHADER_REQUIRE}\n"
1838                     "\n"
1839                     "layout (points)                   in;\n"
1840                     "layout (points, max_vertices = 1) out;\n"
1841                     "\n"
1842                     "int counter = 0;\n"
1843                     "\n";
1844 
1845     for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
1846     {
1847         code_sstream << "layout(binding = " << n_ssb << ") buffer ssb" << n_ssb << " \n{\n"
1848                      << "    int value;\n"
1849                      << "} S_SSB" << n_ssb << ";\n\n";
1850     }
1851 
1852     code_sstream << "\n"
1853                     "void main()\n"
1854                     "{\n";
1855 
1856     for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
1857     {
1858         code_sstream << "    counter += S_SSB" << n_ssb << ".value++;\n";
1859     }
1860 
1861     code_sstream << "\n"
1862                     "    gl_Position = vec4(float(counter), 0.0, 0.0, 1.0);\n"
1863                     "    EmitVertex();\n"
1864                     "}\n";
1865 
1866     /* Form a specialized version of the GS source code */
1867     std::string gs_code             = code_sstream.str();
1868     const char *gs_code_raw         = gs_code.c_str();
1869     std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw);
1870 
1871     return gs_code_specialized;
1872 }
1873 
1874 /** Executes the test.
1875  *
1876  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1877  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1878  *  Note the function throws exception should an error occur!
1879  **/
iterate()1880 tcu::TestNode::IterateResult GeometryShaderMaxShaderStorageBlocksTest::iterate()
1881 {
1882     glw::GLint counter                        = 0;
1883     glw::GLint expectedValue                  = 0;
1884     const glw::GLchar *feedbackVaryings[]     = {"gl_Position"};
1885     bool has_shader_compilation_failed        = true;
1886     const glw::GLfloat initial_buffer_data[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1887     glw::GLint int_alignment                  = 0;
1888     const glw::GLint int_size                 = sizeof(glw::GLint);
1889     glw::GLint *ptrSSBO_data                  = DE_NULL;
1890     glw::GLfloat *ptrTF_data                  = DE_NULL;
1891     bool result                               = true;
1892     glw::GLint ssbo_alignment                 = 0;
1893     glw::GLint *ssbo_data                     = DE_NULL;
1894     glw::GLint ssbo_data_size                 = 0;
1895 
1896     std::string fs_code_specialized     = "";
1897     const char *fs_code_specialized_raw = DE_NULL;
1898     std::string gs_code_specialized     = "";
1899     const char *gs_code_specialized_raw = DE_NULL;
1900     std::string vs_code_specialized     = "";
1901     const char *vs_code_specialized_raw = DE_NULL;
1902 
1903     /* This test should only run if EXT_geometry_shader is supported. */
1904     if (!m_is_geometry_shader_extension_supported)
1905     {
1906         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1907     }
1908 
1909     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1910 
1911     /* Retrieve GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname value */
1912     gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
1913                    &m_gl_max_geometry_shader_storage_blocks_ext_value);
1914     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname");
1915 
1916     /* Retrieve GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname value */
1917     glw::GLint m_gl_max_shader_storage_buffer_bindings_value = 0;
1918 
1919     gl.getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &m_gl_max_shader_storage_buffer_bindings_value);
1920     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname");
1921 
1922     /* Check if m_gl_max_shader_storage_blocks_value is less than or equal zero. */
1923     if (m_gl_max_geometry_shader_storage_blocks_ext_value <= 0)
1924     {
1925         m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
1926                            << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
1927                            << "]"
1928                               " is less than or equal zero. Shader Storage Blocks"
1929                               " in Geometry Shader are not supported."
1930                            << tcu::TestLog::EndMessage;
1931 
1932         if (m_gl_max_geometry_shader_storage_blocks_ext_value == 0)
1933         {
1934             throw tcu::NotSupportedError("GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT is 0");
1935         }
1936         else
1937         {
1938             result = false;
1939             goto end;
1940         }
1941     }
1942 
1943     /* Check if m_gl_max_shader_storage_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
1944     if (m_gl_max_shader_storage_buffer_bindings_value < m_gl_max_geometry_shader_storage_blocks_ext_value)
1945     {
1946         m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
1947                            << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
1948                            << "]"
1949                               " is greater than GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS query value "
1950                               "["
1951                            << m_gl_max_shader_storage_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
1952 
1953         result = false;
1954         goto end;
1955     }
1956 
1957     /* Create a program object. */
1958     m_po_id = gl.createProgram();
1959     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1960 
1961     /* Create shader objects. */
1962     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1963     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1964     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1965 
1966     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1967 
1968     /* Configure which outputs should be captured by Transform Feedback. */
1969     gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
1970 
1971     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
1972 
1973     /* Try to link the test program object */
1974     fs_code_specialized     = specializeShader(1, &minimal_fs_code);
1975     fs_code_specialized_raw = fs_code_specialized.c_str();
1976 
1977     gs_code_specialized     = getGSCode();
1978     gs_code_specialized_raw = gs_code_specialized.c_str();
1979 
1980     vs_code_specialized     = specializeShader(1, &minimal_vs_code);
1981     vs_code_specialized_raw = vs_code_specialized.c_str();
1982 
1983     if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,                  /* n_sh1_body_parts */
1984                                     &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1985                                     &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1986                                     &fs_code_specialized_raw, &has_shader_compilation_failed))
1987     {
1988         m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
1989 
1990         result = false;
1991         goto end;
1992     }
1993 
1994     /* Prepare data for Shader Storage Buffer Object. */
1995     gl.getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_alignment);
1996     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
1997 
1998     int_alignment  = ssbo_alignment / int_size;
1999     ssbo_data_size = m_gl_max_geometry_shader_storage_blocks_ext_value * ssbo_alignment;
2000     ssbo_data      = new glw::GLint[ssbo_data_size];
2001 
2002     if ((ssbo_alignment % int_size) != 0)
2003     {
2004         m_testCtx.getLog() << tcu::TestLog::Message
2005                            << "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT query value "
2006                               "["
2007                            << ssbo_alignment
2008                            << "]"
2009                               "divide with remainder by the size of GLint "
2010                               "["
2011                            << int_size << "]" << tcu::TestLog::EndMessage;
2012 
2013         result = false;
2014         goto end;
2015     }
2016 
2017     for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
2018     {
2019         ssbo_data[i * int_alignment] = i + 1;
2020     }
2021 
2022     /* Create Shader Storage Buffer Object. */
2023     gl.genBuffers(1, &m_ssbo_id);
2024     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2025 
2026     gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo_id);
2027     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2028 
2029     gl.bufferData(GL_SHADER_STORAGE_BUFFER, ssbo_data_size, ssbo_data, GL_DYNAMIC_COPY);
2030     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2031 
2032     /* Free unused memory. */
2033     delete[] ssbo_data;
2034     ssbo_data = NULL;
2035 
2036     /* Bind specific m_ssbo_id buffer region to a specific Shader Storage Buffer binding point. */
2037     for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
2038     {
2039         glw::GLuint offset = n_ssb * ssbo_alignment;
2040 
2041         gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, n_ssb /*binding index*/, m_ssbo_id, offset, int_size);
2042         GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2043     }
2044 
2045     /* Configure VAO. */
2046     gl.genVertexArrays(1, &m_vao_id);
2047     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2048 
2049     gl.bindVertexArray(m_vao_id);
2050     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2051 
2052     /* Create a Buffer Object for Transform Feedback's outputs. */
2053     gl.genBuffers(1, &m_tfbo_id);
2054     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2055 
2056     gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
2057     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2058 
2059     gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, initial_buffer_data,
2060                   GL_STATIC_READ);
2061     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2062 
2063     /* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
2064     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
2065     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
2066 
2067     /* Use program. */
2068     gl.useProgram(m_po_id);
2069     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2070 
2071     /* Disable rasterization and make a draw call. After that, turn on rasterization. */
2072     gl.enable(GL_RASTERIZER_DISCARD);
2073     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
2074 
2075     gl.beginTransformFeedback(GL_POINTS);
2076     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2077 
2078     gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
2079     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2080 
2081     gl.endTransformFeedback();
2082     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
2083 
2084     gl.disable(GL_RASTERIZER_DISCARD);
2085     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
2086 
2087     /* Retrieve value from Transform Feedback. */
2088     ptrTF_data = (glw::GLfloat *)gl.mapBufferRange(
2089         GL_ARRAY_BUFFER, 0 /*offset*/, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
2090     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2091 
2092     counter = int(ptrTF_data[0] + 0.5f);
2093 
2094     gl.unmapBuffer(GL_ARRAY_BUFFER);
2095     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2096 
2097     ptrTF_data = NULL;
2098 
2099     /* Retrieve values from Shader Storage Buffer Object. */
2100     ptrSSBO_data =
2101         (glw::GLint *)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /*offset*/, ssbo_data_size, GL_MAP_READ_BIT);
2102     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2103 
2104     for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
2105     {
2106         if (ptrSSBO_data[i * int_alignment] != i + 2)
2107         {
2108             result = false;
2109 
2110             m_testCtx.getLog() << tcu::TestLog::Message
2111                                << "Value read from Shader Storage Buffer "
2112                                   "["
2113                                << ptrSSBO_data[i * int_alignment]
2114                                << "] "
2115                                   "at index "
2116                                   "["
2117                                << i * int_alignment
2118                                << "]"
2119                                   "is not equal to expected value "
2120                                   "["
2121                                << i + 2 << "]" << tcu::TestLog::EndMessage;
2122 
2123             break;
2124         }
2125     }
2126 
2127     gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
2128     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2129 
2130     ptrSSBO_data = NULL;
2131 
2132     /* Calculate expected value. */
2133     expectedValue =
2134         m_gl_max_geometry_shader_storage_blocks_ext_value * (m_gl_max_geometry_shader_storage_blocks_ext_value + 1) / 2;
2135 
2136     if (counter != expectedValue)
2137     {
2138         result = false;
2139     }
2140 
2141 end:
2142     if (result)
2143     {
2144         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2145     }
2146     else
2147     {
2148         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2149     }
2150 
2151     return STOP;
2152 }
2153 
2154 /** Constructor
2155  *
2156  * @param context       Test context
2157  * @param extParams     Not used.
2158  * @param name          Test case's name
2159  * @param description   Test case's description
2160  **/
GeometryShaderMaxAtomicCountersTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2161 GeometryShaderMaxAtomicCountersTest::GeometryShaderMaxAtomicCountersTest(Context &context,
2162                                                                          const ExtParameters &extParams,
2163                                                                          const char *name, const char *description)
2164     : TestCaseBase(context, extParams, name, description)
2165     , m_acbo_id(0)
2166     , m_fs_id(0)
2167     , m_gl_max_geometry_atomic_counters_ext_value(0)
2168     , m_gs_id(0)
2169     , m_po_id(0)
2170     , m_vao_id(0)
2171     , m_vs_id(0)
2172 {
2173 }
2174 
2175 /** Deinitializes GLES objects created during the test. */
deinit()2176 void GeometryShaderMaxAtomicCountersTest::deinit()
2177 {
2178     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2179 
2180     if (m_acbo_id != 0)
2181     {
2182         gl.deleteBuffers(1, &m_acbo_id);
2183         m_acbo_id = 0;
2184     }
2185 
2186     if (m_fs_id != 0)
2187     {
2188         gl.deleteShader(m_fs_id);
2189         m_fs_id = 0;
2190     }
2191 
2192     if (m_gs_id != 0)
2193     {
2194         gl.deleteShader(m_gs_id);
2195         m_gs_id = 0;
2196     }
2197 
2198     if (m_po_id != 0)
2199     {
2200         gl.deleteProgram(m_po_id);
2201         m_po_id = 0;
2202     }
2203 
2204     if (m_vao_id != 0)
2205     {
2206         gl.deleteVertexArrays(1, &m_vao_id);
2207         m_vao_id = 0;
2208     }
2209 
2210     if (m_vs_id != 0)
2211     {
2212         gl.deleteShader(m_vs_id);
2213         m_vs_id = 0;
2214     }
2215 
2216     /* Release base class */
2217     TestCaseBase::deinit();
2218 }
2219 
2220 /* Retrieves test-specific geometry shader source code.
2221  *
2222  * @return Requested string.
2223  */
getGSCode()2224 std::string GeometryShaderMaxAtomicCountersTest::getGSCode()
2225 {
2226     std::stringstream code_sstream;
2227 
2228     /* Form the GS */
2229     code_sstream << "${VERSION}\n"
2230                     "${GEOMETRY_SHADER_REQUIRE}\n"
2231                     "\n"
2232                     "layout (points)                   in;\n"
2233                     "layout (points, max_vertices = 1) out;\n"
2234                     "\n"
2235                     "uniform int n_loop_iterations;\n"
2236                     "flat in int vertex_id[];\n"
2237                     "\n";
2238 
2239     code_sstream << "layout(binding = 0) uniform atomic_uint acs[" << m_gl_max_geometry_atomic_counters_ext_value
2240                  << "];\n"
2241                  << "\n"
2242                     "void main()\n"
2243                     "{\n"
2244                     "    for (int counter_id = 1;\n"
2245                     "             counter_id <= n_loop_iterations;\n"
2246                     "           ++counter_id)\n"
2247                     "    {\n"
2248                     "        if ((vertex_id[0] % counter_id) == 0)\n"
2249                     "        {\n"
2250                     "            atomicCounterIncrement(acs[counter_id - 1]);\n"
2251                     "        }\n"
2252                     "    }\n"
2253                     "\n"
2254                     "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2255                     "    EmitVertex();\n"
2256                     "}\n";
2257 
2258     /* Form a specialized version of the GS source code */
2259     std::string gs_code             = code_sstream.str();
2260     const char *gs_code_raw         = gs_code.c_str();
2261     std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
2262 
2263     return gs_code_specialized;
2264 }
2265 
2266 /** Executes the test.
2267  *
2268  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2269  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2270  *  Note the function throws exception should an error occur!
2271  **/
iterate()2272 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCountersTest::iterate()
2273 {
2274     /* Define Vertex Shader's code for the purpose of this test. */
2275     const char *vs_code = "${VERSION}\n"
2276                           "\n"
2277                           "flat out int vertex_id;\n"
2278                           "\n"
2279                           "void main()\n"
2280                           "{\n"
2281                           "    vertex_id    = gl_VertexID;\n"
2282                           "    gl_Position  = vec4(1.0, 0.0, 0.0, 1.0);\n"
2283                           "}\n";
2284 
2285     bool has_shader_compilation_failed            = true;
2286     glw::GLuint *initial_ac_data                  = DE_NULL;
2287     const unsigned int n_draw_call_vertices       = 4;
2288     glw::GLint n_loop_iterations_uniform_location = -1;
2289     glw::GLuint *ptrACBO_data                     = DE_NULL;
2290     bool result                                   = true;
2291 
2292     std::string fs_code_specialized     = "";
2293     const char *fs_code_specialized_raw = DE_NULL;
2294     std::string gs_code_specialized     = "";
2295     const char *gs_code_specialized_raw = DE_NULL;
2296     std::string vs_code_specialized     = "";
2297     const char *vs_code_specialized_raw = DE_NULL;
2298 
2299     /* This test should only run if EXT_geometry_shader is supported. */
2300     if (!m_is_geometry_shader_extension_supported)
2301     {
2302         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2303     }
2304 
2305     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2306 
2307     /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname value */
2308     gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTERS, &m_gl_max_geometry_atomic_counters_ext_value);
2309     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname");
2310 
2311     /* Check if m_gl_max_atomic_counters_value is less than or equal zero. */
2312     if (m_gl_max_geometry_atomic_counters_ext_value <= 0)
2313     {
2314         m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT query value "
2315                            << "[" << m_gl_max_geometry_atomic_counters_ext_value
2316                            << "]"
2317                               " is less than or equal to zero. Atomic Counters"
2318                               " in Geometry Shader are not supported."
2319                            << tcu::TestLog::EndMessage;
2320 
2321         if (m_gl_max_geometry_atomic_counters_ext_value == 0)
2322         {
2323             throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT is 0");
2324         }
2325         else
2326         {
2327             result = false;
2328             goto end;
2329         }
2330     }
2331 
2332     /* Create a program object. */
2333     m_po_id = gl.createProgram();
2334     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2335 
2336     /* Create shader objects. */
2337     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2338     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2339     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2340 
2341     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2342 
2343     /* Try to link the test program object */
2344     fs_code_specialized     = specializeShader(1, &minimal_fs_code);
2345     fs_code_specialized_raw = fs_code_specialized.c_str();
2346 
2347     gs_code_specialized     = getGSCode();
2348     gs_code_specialized_raw = gs_code_specialized.c_str();
2349 
2350     vs_code_specialized     = specializeShader(1, &vs_code);
2351     vs_code_specialized_raw = vs_code_specialized.c_str();
2352 
2353     if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,                  /* n_sh1_body_parts */
2354                                     &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2355                                     &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2356                                     &fs_code_specialized_raw, &has_shader_compilation_failed))
2357     {
2358         m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
2359 
2360         result = false;
2361         goto end;
2362     }
2363 
2364     /* Create Atomic Counter Buffer Objects. */
2365     gl.genBuffers(1, &m_acbo_id);
2366     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2367 
2368     /* Prepare initial data - zeroes - to fill the Atomic Counter Buffer Object. */
2369     initial_ac_data = new glw::GLuint[m_gl_max_geometry_atomic_counters_ext_value];
2370     memset(initial_ac_data, 0, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value);
2371 
2372     gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_id);
2373     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2374 
2375     gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value, NULL,
2376                   GL_DYNAMIC_COPY);
2377     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2378 
2379     gl.bufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2380                      sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
2381                      initial_ac_data /*initialize with zeroes*/);
2382     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
2383 
2384     gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0 /*binding index*/, m_acbo_id /*buffer*/);
2385     GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2386 
2387     /* Configure VAO. */
2388     gl.genVertexArrays(1, &m_vao_id);
2389     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2390 
2391     gl.bindVertexArray(m_vao_id);
2392     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2393 
2394     /* Use program. */
2395     n_loop_iterations_uniform_location = gl.getUniformLocation(m_po_id, "n_loop_iterations");
2396 
2397     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
2398     if (n_loop_iterations_uniform_location == -1)
2399     {
2400         TCU_FAIL("n_loop_iterations uniform is considered inactive");
2401     }
2402     else
2403     {
2404         gl.useProgram(m_po_id);
2405         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2406 
2407         gl.uniform1i(n_loop_iterations_uniform_location, m_gl_max_geometry_atomic_counters_ext_value);
2408         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
2409     }
2410 
2411     /* Issue the draw call */
2412     gl.drawArrays(GL_POINTS, 0, n_draw_call_vertices);
2413     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2414 
2415     /* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
2416     ptrACBO_data = (glw::GLuint *)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2417                                                     sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
2418                                                     GL_MAP_READ_BIT);
2419     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2420 
2421     for (glw::GLint n_ac = 0; n_ac < m_gl_max_geometry_atomic_counters_ext_value; ++n_ac)
2422     {
2423         unsigned int expected_value = 0;
2424 
2425         for (unsigned int n_draw_call_vertex = 0; n_draw_call_vertex < n_draw_call_vertices; ++n_draw_call_vertex)
2426         {
2427             if ((n_draw_call_vertex % (n_ac + 1)) == 0)
2428             {
2429                 ++expected_value;
2430             }
2431         }
2432 
2433         if (ptrACBO_data[n_ac] != expected_value)
2434         {
2435             result = false;
2436             break;
2437         }
2438     }
2439 
2440     gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2441     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2442 
2443     ptrACBO_data = NULL;
2444 
2445 end:
2446     if (result)
2447     {
2448         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2449     }
2450     else
2451     {
2452         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2453     }
2454 
2455     return STOP;
2456 }
2457 
2458 /** Constructor
2459  *
2460  * @param context       Test context
2461  * @param extParams     Not used.
2462  * @param name          Test case's name
2463  * @param description   Test case's description
2464  **/
GeometryShaderMaxAtomicCounterBuffersTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2465 GeometryShaderMaxAtomicCounterBuffersTest::GeometryShaderMaxAtomicCounterBuffersTest(Context &context,
2466                                                                                      const ExtParameters &extParams,
2467                                                                                      const char *name,
2468                                                                                      const char *description)
2469     : TestCaseBase(context, extParams, name, description)
2470     , m_acbo_ids(NULL)
2471     , m_fs_id(0)
2472     , m_gl_max_atomic_counter_buffer_bindings_value(0)
2473     , m_gl_max_geometry_atomic_counter_buffers_ext_value(0)
2474     , m_gs_id(0)
2475     , m_po_id(0)
2476     , m_vao_id(0)
2477     , m_vs_id(0)
2478 {
2479 }
2480 
2481 /** Deinitializes GLES objects created during the test. */
deinit()2482 void GeometryShaderMaxAtomicCounterBuffersTest::deinit()
2483 {
2484     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2485 
2486     if (m_acbo_ids != NULL)
2487     {
2488         if (m_gl_max_geometry_atomic_counter_buffers_ext_value > 0)
2489         {
2490             gl.deleteBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
2491 
2492             delete[] m_acbo_ids;
2493             m_acbo_ids = NULL;
2494         }
2495     }
2496 
2497     if (m_fs_id != 0)
2498     {
2499         gl.deleteShader(m_fs_id);
2500         m_fs_id = 0;
2501     }
2502 
2503     if (m_gs_id != 0)
2504     {
2505         gl.deleteShader(m_gs_id);
2506         m_gs_id = 0;
2507     }
2508 
2509     if (m_po_id != 0)
2510     {
2511         gl.deleteProgram(m_po_id);
2512         m_po_id = 0;
2513     }
2514 
2515     if (m_vao_id != 0)
2516     {
2517         gl.deleteVertexArrays(1, &m_vao_id);
2518         m_vao_id = 0;
2519     }
2520 
2521     if (m_vs_id != 0)
2522     {
2523         gl.deleteShader(m_vs_id);
2524         m_vs_id = 0;
2525     }
2526 
2527     /* Release base class */
2528     TestCaseBase::deinit();
2529 }
2530 
2531 /* Retrieves test-specific geometry shader source code.
2532  *
2533  * @return Requested string.
2534  */
getGSCode()2535 std::string GeometryShaderMaxAtomicCounterBuffersTest::getGSCode()
2536 {
2537     std::stringstream code_sstream;
2538 
2539     /* Form the GS */
2540     code_sstream << "${VERSION}\n"
2541                     "${GEOMETRY_SHADER_REQUIRE}\n"
2542                     "\n"
2543                     "layout (points)                   in;\n"
2544                     "layout (points, max_vertices = 1) out;\n"
2545                     "\n"
2546                     "flat in int vertex_id[];\n"
2547                     "\n";
2548 
2549     for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
2550     {
2551         code_sstream << "layout(binding = " << n_ac << ") uniform atomic_uint ac" << n_ac << ";\n";
2552     }
2553 
2554     code_sstream << "\n"
2555                     "void main()\n"
2556                     "{\n"
2557                     "    for(int counter_id = 1; counter_id <= "
2558                  << m_gl_max_geometry_atomic_counter_buffers_ext_value
2559                  << "; ++counter_id)\n"
2560                     "    {\n"
2561                     "        if((vertex_id[0] % counter_id) == 0)\n"
2562                     "        {\n";
2563 
2564     for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
2565     {
2566         code_sstream << "            atomicCounterIncrement(ac" << n_ac << ");\n";
2567     }
2568 
2569     code_sstream << "        }\n"
2570                     "    }\n";
2571 
2572     code_sstream << "\n"
2573                     "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2574                     "    EmitVertex();\n"
2575                     "}\n";
2576 
2577     /* Form a specialized version of the GS source code */
2578     std::string gs_code             = code_sstream.str();
2579     const char *gs_code_raw         = gs_code.c_str();
2580     std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
2581 
2582     return gs_code_specialized;
2583 }
2584 
2585 /** Executes the test.
2586  *
2587  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2588  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2589  *  Note the function throws exception should an error occur!
2590  **/
iterate()2591 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCounterBuffersTest::iterate()
2592 {
2593     /* Define Vertex Shader's code for the purpose of this test. */
2594     const char *vs_code = "${VERSION}\n"
2595                           "\n"
2596                           "flat out int vertex_id;\n"
2597                           "\n"
2598                           "void main()\n"
2599                           "{\n"
2600                           "    vertex_id    = gl_VertexID;\n"
2601                           "    gl_Position  = vec4(1.0, 0.0, 0.0, 1.0);\n"
2602                           "}\n";
2603 
2604     unsigned int expected_value         = 0;
2605     const glw::Functions &gl            = m_context.getRenderContext().getFunctions();
2606     bool has_shader_compilation_failed  = true;
2607     const glw::GLuint initial_ac_data   = 0;
2608     const glw::GLuint number_of_indices = 128 * m_gl_max_geometry_atomic_counter_buffers_ext_value;
2609     bool result                         = true;
2610 
2611     std::string fs_code_specialized     = "";
2612     const char *fs_code_specialized_raw = DE_NULL;
2613     std::string gs_code_specialized     = "";
2614     const char *gs_code_specialized_raw = DE_NULL;
2615     std::string vs_code_specialized     = "";
2616     const char *vs_code_specialized_raw = DE_NULL;
2617 
2618     /* This test should only run if EXT_geometry_shader is supported. */
2619     if (!m_is_geometry_shader_extension_supported)
2620     {
2621         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2622     }
2623 
2624     /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname value */
2625     gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS,
2626                    &m_gl_max_geometry_atomic_counter_buffers_ext_value);
2627     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname");
2628 
2629     /* Retrieve GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname value */
2630     gl.getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_gl_max_atomic_counter_buffer_bindings_value);
2631     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname");
2632 
2633     /* Check if m_gl_max_geometry_atomic_counter_buffers_ext_value is less than or equal zero. */
2634     if (m_gl_max_geometry_atomic_counter_buffers_ext_value <= 0)
2635     {
2636         m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
2637                            << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
2638                            << "]"
2639                               " is less than or equal to zero. Atomic Counter Buffers"
2640                               " are not supported."
2641                            << tcu::TestLog::EndMessage;
2642 
2643         if (m_gl_max_geometry_atomic_counter_buffers_ext_value == 0)
2644         {
2645             throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT is 0");
2646         }
2647         else
2648         {
2649             result = false;
2650             goto end;
2651         }
2652     }
2653 
2654     /* Check if m_gl_max_atomic_counter_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
2655     if (m_gl_max_atomic_counter_buffer_bindings_value < m_gl_max_geometry_atomic_counter_buffers_ext_value)
2656     {
2657         m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
2658                            << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
2659                            << "]"
2660                               " is greater than GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS query value "
2661                               "["
2662                            << m_gl_max_atomic_counter_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
2663 
2664         result = false;
2665         goto end;
2666     }
2667 
2668     /* Create a program object. */
2669     m_po_id = gl.createProgram();
2670     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2671 
2672     /* Create shader objects. */
2673     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2674     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2675     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2676 
2677     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2678 
2679     /* Try to link the test program object */
2680     fs_code_specialized     = specializeShader(1, &minimal_fs_code);
2681     fs_code_specialized_raw = fs_code_specialized.c_str();
2682 
2683     gs_code_specialized     = getGSCode();
2684     gs_code_specialized_raw = gs_code_specialized.c_str();
2685 
2686     vs_code_specialized     = specializeShader(1, &vs_code);
2687     vs_code_specialized_raw = vs_code_specialized.c_str();
2688 
2689     if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,                  /* n_sh1_body_parts */
2690                                     &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2691                                     &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2692                                     &fs_code_specialized_raw, &has_shader_compilation_failed))
2693     {
2694         m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
2695 
2696         result = false;
2697         goto end;
2698     }
2699 
2700     /* Create Atomic Counter Buffer Objects. */
2701     m_acbo_ids = new glw::GLuint[m_gl_max_geometry_atomic_counter_buffers_ext_value];
2702 
2703     gl.genBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
2704     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2705 
2706     for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
2707     {
2708         gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
2709         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2710 
2711         gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint), &initial_ac_data /*initialize with zeroes*/,
2712                       GL_DYNAMIC_COPY);
2713         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2714 
2715         gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, n_acb /*binding index*/, m_acbo_ids[n_acb] /*buffer*/);
2716         GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2717     }
2718 
2719     /* Configure VAO. */
2720     gl.genVertexArrays(1, &m_vao_id);
2721     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2722 
2723     gl.bindVertexArray(m_vao_id);
2724     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2725 
2726     /* Use program. */
2727     gl.useProgram(m_po_id);
2728     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2729 
2730     gl.drawArrays(GL_POINTS, 0 /*starting index*/, number_of_indices);
2731     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2732 
2733     /* Calculate expected value. */
2734     /* For each point being processed by Geometry Shader. */
2735     for (glw::GLuint vertex_id = 0; vertex_id < number_of_indices; ++vertex_id)
2736     {
2737         /* And for each atomic counter ID. */
2738         for (int atomic_counter_id = 1; atomic_counter_id <= m_gl_max_geometry_atomic_counter_buffers_ext_value;
2739              ++atomic_counter_id)
2740         {
2741             /* Check if (vertex_id % atomic_counter_id) == 0. If it is true, increment expected_value. */
2742             if (vertex_id % atomic_counter_id == 0)
2743             {
2744                 ++expected_value;
2745             }
2746         }
2747     }
2748 
2749     /* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
2750     for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
2751     {
2752         gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
2753         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2754 
2755         glw::GLuint *ptrABO_data = (glw::GLuint *)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2756                                                                     sizeof(glw::GLuint) /*length*/, GL_MAP_READ_BIT);
2757         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2758 
2759         if (ptrABO_data[0] != expected_value)
2760         {
2761             result = false;
2762             break;
2763         }
2764 
2765         gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2766         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2767 
2768         ptrABO_data = NULL;
2769     }
2770 
2771 end:
2772     if (result)
2773     {
2774         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2775     }
2776     else
2777     {
2778         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2779     }
2780 
2781     return STOP;
2782 }
2783 
2784 /** Constructor
2785  *
2786  * @param context       Test context
2787  * @param extParams     Not used.
2788  * @param name          Test case's name
2789  * @param description   Test case's description
2790  **/
2791 GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::
GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2792     GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context &context, const ExtParameters &extParams,
2793                                                                  const char *name, const char *description)
2794     : TestCaseBase(context, extParams, name, description)
2795     , m_fs_id(0)
2796     , m_fs_po_id(0)
2797     , m_gs_id(0)
2798     , m_gs_po_id(0)
2799     , m_ppo_id(0)
2800     , m_vao_id(0)
2801 {
2802 }
2803 
2804 /** Deinitializes GLES objects created during the test. */
deinit()2805 void GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::deinit()
2806 {
2807     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2808 
2809     if (m_fs_id != 0)
2810     {
2811         gl.deleteShader(m_fs_id);
2812         m_fs_id = 0;
2813     }
2814 
2815     if (m_fs_po_id != 0)
2816     {
2817         gl.deleteProgram(m_fs_po_id);
2818         m_fs_po_id = 0;
2819     }
2820 
2821     if (m_gs_id != 0)
2822     {
2823         gl.deleteShader(m_gs_id);
2824         m_gs_id = 0;
2825     }
2826 
2827     if (m_gs_po_id != 0)
2828     {
2829         gl.deleteProgram(m_gs_po_id);
2830         m_gs_po_id = 0;
2831     }
2832 
2833     if (m_ppo_id != 0)
2834     {
2835         gl.deleteProgramPipelines(1, &m_ppo_id);
2836         m_ppo_id = 0;
2837     }
2838 
2839     if (m_vao_id != 0)
2840     {
2841         gl.deleteVertexArrays(1, &m_vao_id);
2842         m_vao_id = 0;
2843     }
2844 
2845     /* Release base class */
2846     TestCaseBase::deinit();
2847 }
2848 
2849 /** Executes the test.
2850  *
2851  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2852  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2853  *  Note the function throws exception should an error occur!
2854  **/
iterate()2855 tcu::TestNode::IterateResult GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::iterate()
2856 {
2857     bool has_shader_compilation_failed = true;
2858     bool result                        = true;
2859     glw::GLenum error                  = GL_NO_ERROR;
2860 
2861     /* This test should only run if EXT_geometry_shader is supported. */
2862     if (!m_is_geometry_shader_extension_supported)
2863     {
2864         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2865     }
2866 
2867     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2868 
2869     /* Create separable program objects. */
2870     m_fs_po_id = gl.createProgram();
2871     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2872 
2873     gl.programParameteri(m_fs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2874     GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
2875 
2876     m_gs_po_id = gl.createProgram();
2877     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2878 
2879     gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2880     GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
2881 
2882     /* Create shader objects. */
2883     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2884     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2885 
2886     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2887 
2888     /* Try to link the test program object */
2889     std::string fs_code_specialized     = specializeShader(1, &minimal_fs_code);
2890     const char *fs_code_specialized_raw = fs_code_specialized.c_str();
2891     std::string gs_code_specialized     = specializeShader(1, &minimal_gs_code);
2892     const char *gs_code_specialized_raw = gs_code_specialized.c_str();
2893 
2894     if (!TestCaseBase::buildProgram(m_fs_po_id, m_fs_id, 1,         /* n_sh1_body_parts */
2895                                     &fs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
2896                                     NULL, 0, 0,                     /* n_sh3_body_parts */
2897                                     NULL, &has_shader_compilation_failed))
2898     {
2899         m_testCtx.getLog() << tcu::TestLog::Message << "Fragment Shader Program object linking failed."
2900                            << tcu::TestLog::EndMessage;
2901 
2902         result = false;
2903         goto end;
2904     }
2905 
2906     if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1,         /* n_sh1_body_parts */
2907                                     &gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
2908                                     NULL, 0, 0,                     /* n_sh3_body_parts */
2909                                     NULL, &has_shader_compilation_failed))
2910     {
2911         m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
2912                            << tcu::TestLog::EndMessage;
2913 
2914         result = false;
2915         goto end;
2916     }
2917 
2918     /* Configure Pipeline Object. */
2919     gl.genProgramPipelines(1, &m_ppo_id);
2920     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
2921 
2922     gl.useProgramStages(m_ppo_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
2923     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
2924 
2925     gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
2926     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
2927 
2928     /* Configure VAO. */
2929     gl.genVertexArrays(1, &m_vao_id);
2930     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2931 
2932     gl.bindVertexArray(m_vao_id);
2933     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2934 
2935     /* Use Program Pipeline Object. */
2936     gl.bindProgramPipeline(m_ppo_id);
2937     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
2938 
2939     gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
2940 
2941     error = gl.getError();
2942 
2943     /* Check if correct error was generated. */
2944     if (GL_INVALID_OPERATION != error)
2945     {
2946         result = false;
2947 
2948         m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
2949                            << tcu::TestLog::EndMessage;
2950     }
2951 
2952 end:
2953     if (result)
2954     {
2955         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2956     }
2957     else
2958     {
2959         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2960     }
2961 
2962     return STOP;
2963 }
2964 
2965 /** Constructor
2966  *
2967  * @param context       Test context
2968  * @param extParams     Not used.
2969  * @param name          Test case's name
2970  * @param description   Test case's description
2971  **/
GeometryShaderIncompatibleDrawCallModeTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2972 GeometryShaderIncompatibleDrawCallModeTest::GeometryShaderIncompatibleDrawCallModeTest(Context &context,
2973                                                                                        const ExtParameters &extParams,
2974                                                                                        const char *name,
2975                                                                                        const char *description)
2976     : TestCaseBase(context, extParams, name, description)
2977     , m_fs_id(0)
2978     , m_gs_ids(NULL)
2979     , m_number_of_gs(5 /*taken from test spec*/)
2980     , m_po_ids(NULL)
2981 {
2982     m_vao_id = 0;
2983     m_vs_id  = 0;
2984 }
2985 
2986 /** Deinitializes GLES objects created during the test. */
deinit()2987 void GeometryShaderIncompatibleDrawCallModeTest::deinit()
2988 {
2989     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2990 
2991     if (m_fs_id != 0)
2992     {
2993         gl.deleteShader(m_fs_id);
2994         m_fs_id = 0;
2995     }
2996 
2997     if (m_gs_ids != 0)
2998     {
2999         for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3000         {
3001             gl.deleteShader(m_gs_ids[i]);
3002             m_gs_ids[i] = 0;
3003         }
3004 
3005         delete[] m_gs_ids;
3006         m_gs_ids = NULL;
3007     }
3008 
3009     if (m_po_ids != 0)
3010     {
3011         for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3012         {
3013             gl.deleteProgram(m_po_ids[i]);
3014             m_po_ids[i] = 0;
3015         }
3016 
3017         delete[] m_po_ids;
3018         m_po_ids = NULL;
3019     }
3020 
3021     if (m_vao_id != 0)
3022     {
3023         gl.deleteVertexArrays(1, &m_vao_id);
3024         m_vao_id = 0;
3025     }
3026 
3027     if (m_vs_id != 0)
3028     {
3029         gl.deleteShader(m_vs_id);
3030         m_vs_id = 0;
3031     }
3032 
3033     /* Release base class */
3034     TestCaseBase::deinit();
3035 }
3036 
3037 /** Executes the test.
3038  *
3039  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3040  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3041  *  Note the function throws exception should an error occur!
3042  **/
iterate()3043 tcu::TestNode::IterateResult GeometryShaderIncompatibleDrawCallModeTest::iterate()
3044 {
3045     /* Define 5 Geometry Shaders for purpose of this test. */
3046     const char *gs_code_points = "${VERSION}\n"
3047                                  "${GEOMETRY_SHADER_REQUIRE}\n"
3048                                  "\n"
3049                                  "layout (points)                   in;\n"
3050                                  "layout (points, max_vertices = 1) out;\n"
3051                                  "\n"
3052                                  "${IN_PER_VERTEX_DECL_ARRAY}"
3053                                  "\n"
3054                                  "void main()\n"
3055                                  "{\n"
3056                                  "    gl_Position = gl_in[0].gl_Position;\n"
3057                                  "    EmitVertex();\n"
3058                                  "}\n";
3059 
3060     const char *gs_code_lines = "${VERSION}\n"
3061                                 "${GEOMETRY_SHADER_REQUIRE}\n"
3062                                 "\n"
3063                                 "layout (lines)                    in;\n"
3064                                 "layout (points, max_vertices = 1) out;\n"
3065                                 "\n"
3066                                 "${IN_PER_VERTEX_DECL_ARRAY}"
3067                                 "\n"
3068                                 "void main()\n"
3069                                 "{\n"
3070                                 "    gl_Position = gl_in[0].gl_Position;\n"
3071                                 "    EmitVertex();\n"
3072                                 "}\n";
3073 
3074     const char *gs_code_lines_adjacency = "${VERSION}\n"
3075                                           "${GEOMETRY_SHADER_REQUIRE}\n"
3076                                           "\n"
3077                                           "layout (lines_adjacency)          in;\n"
3078                                           "layout (points, max_vertices = 1) out;\n"
3079                                           "\n"
3080                                           "${IN_PER_VERTEX_DECL_ARRAY}"
3081                                           "\n"
3082                                           "void main()\n"
3083                                           "{\n"
3084                                           "    gl_Position = gl_in[0].gl_Position;\n"
3085                                           "    EmitVertex();\n"
3086                                           "}\n";
3087 
3088     const char *gs_code_triangles = "${VERSION}\n"
3089                                     "${GEOMETRY_SHADER_REQUIRE}\n"
3090                                     "\n"
3091                                     "layout (triangles)                in;\n"
3092                                     "layout (points, max_vertices = 1) out;\n"
3093                                     "\n"
3094                                     "${IN_PER_VERTEX_DECL_ARRAY}"
3095                                     "\n"
3096                                     "void main()\n"
3097                                     "{\n"
3098                                     "    gl_Position = gl_in[0].gl_Position;\n"
3099                                     "    EmitVertex();\n"
3100                                     "}\n";
3101 
3102     const char *gs_code_triangles_adjacency = "${VERSION}\n"
3103                                               "${GEOMETRY_SHADER_REQUIRE}\n"
3104                                               "\n"
3105                                               "layout (triangles_adjacency)      in;\n"
3106                                               "layout (points, max_vertices = 1) out;\n"
3107                                               "\n"
3108                                               "${IN_PER_VERTEX_DECL_ARRAY}"
3109                                               "\n"
3110                                               "void main()\n"
3111                                               "{\n"
3112                                               "    gl_Position = gl_in[0].gl_Position;\n"
3113                                               "    EmitVertex();\n"
3114                                               "}\n";
3115 
3116     bool has_shader_compilation_failed = true;
3117     bool result                        = true;
3118 
3119     m_gs_ids = new glw::GLuint[m_number_of_gs];
3120     m_po_ids = new glw::GLuint[m_number_of_gs];
3121 
3122     /* This test should only run if EXT_geometry_shader is supported. */
3123     if (!m_is_geometry_shader_extension_supported)
3124     {
3125         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3126     }
3127 
3128     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3129 
3130     /* Create program objects & geometry shader objects. */
3131     for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3132     {
3133         m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
3134         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3135 
3136         m_po_ids[i] = gl.createProgram();
3137         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3138     }
3139 
3140     /* Create shader object. */
3141     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3142     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3143     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3144 
3145     /* Try to link the test program object */
3146     std::string fs_code_specialized     = specializeShader(1, &minimal_fs_code);
3147     const char *fs_code_specialized_raw = fs_code_specialized.c_str();
3148 
3149     std::string gs_codes_specialized[] = {specializeShader(1, &gs_code_points), specializeShader(1, &gs_code_lines),
3150                                           specializeShader(1, &gs_code_lines_adjacency),
3151                                           specializeShader(1, &gs_code_triangles),
3152                                           specializeShader(1, &gs_code_triangles_adjacency)};
3153 
3154     const char *gs_codes_specialized_raw[] = {gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str(),
3155                                               gs_codes_specialized[2].c_str(), gs_codes_specialized[3].c_str(),
3156                                               gs_codes_specialized[4].c_str()};
3157     std::string vs_code_specialized        = specializeShader(1, &minimal_vs_code);
3158     const char *vs_code_specialized_raw    = vs_code_specialized.c_str();
3159 
3160     for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3161     {
3162         if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,                  /* n_sh1_body_parts */
3163                                         &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
3164                                         &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
3165                                         &vs_code_specialized_raw, &has_shader_compilation_failed))
3166         {
3167             m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
3168                                << "[" << i << "]." << tcu::TestLog::EndMessage;
3169 
3170             result = false;
3171             break;
3172         }
3173     }
3174 
3175     if (result)
3176     {
3177         /* Configure VAO. */
3178         gl.genVertexArrays(1, &m_vao_id);
3179         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3180 
3181         gl.bindVertexArray(m_vao_id);
3182         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3183 
3184         for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
3185         {
3186             /* Use Program Object. */
3187             gl.useProgram(m_po_ids[po]);
3188             GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3189 
3190             if (po != 0)
3191             {
3192                 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
3193 
3194                 if (GL_INVALID_OPERATION != gl.getError())
3195                 {
3196                     result = false;
3197 
3198                     m_testCtx.getLog() << tcu::TestLog::Message
3199                                        << "Error different than GL_INVALID_OPEARATION was generated."
3200                                        << tcu::TestLog::EndMessage;
3201 
3202                     break;
3203                 }
3204             }
3205 
3206             if (po != 1)
3207             {
3208                 gl.drawArrays(GL_LINES, 0 /*starting index*/, 2 /*number of indices*/);
3209 
3210                 if (GL_INVALID_OPERATION != gl.getError())
3211                 {
3212                     result = false;
3213 
3214                     m_testCtx.getLog() << tcu::TestLog::Message
3215                                        << "Error different than GL_INVALID_OPEARATION was generated."
3216                                        << tcu::TestLog::EndMessage;
3217 
3218                     break;
3219                 }
3220 
3221                 gl.drawArrays(GL_LINE_LOOP, 0 /*starting index*/, 2 /*number of indices*/);
3222 
3223                 if (GL_INVALID_OPERATION != gl.getError())
3224                 {
3225                     result = false;
3226 
3227                     m_testCtx.getLog() << tcu::TestLog::Message
3228                                        << "Error different than GL_INVALID_OPEARATION was generated."
3229                                        << tcu::TestLog::EndMessage;
3230 
3231                     break;
3232                 }
3233 
3234                 gl.drawArrays(GL_LINE_STRIP, 0 /*starting index*/, 2 /*number of indices*/);
3235 
3236                 if (GL_INVALID_OPERATION != gl.getError())
3237                 {
3238                     result = false;
3239 
3240                     m_testCtx.getLog() << tcu::TestLog::Message
3241                                        << "Error different than GL_INVALID_OPEARATION was generated."
3242                                        << tcu::TestLog::EndMessage;
3243 
3244                     break;
3245                 }
3246             }
3247 
3248             if (po != 2)
3249             {
3250                 gl.drawArrays(GL_LINES_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
3251 
3252                 if (GL_INVALID_OPERATION != gl.getError())
3253                 {
3254                     result = false;
3255 
3256                     m_testCtx.getLog() << tcu::TestLog::Message
3257                                        << "Error different than GL_INVALID_OPEARATION was generated."
3258                                        << tcu::TestLog::EndMessage;
3259 
3260                     break;
3261                 }
3262 
3263                 gl.drawArrays(GL_LINE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
3264 
3265                 if (GL_INVALID_OPERATION != gl.getError())
3266                 {
3267                     result = false;
3268 
3269                     m_testCtx.getLog() << tcu::TestLog::Message
3270                                        << "Error different than GL_INVALID_OPEARATION was generated."
3271                                        << tcu::TestLog::EndMessage;
3272 
3273                     break;
3274                 }
3275             }
3276 
3277             if (po != 3)
3278             {
3279                 gl.drawArrays(GL_TRIANGLES, 0 /*starting index*/, 3 /*number of indices*/);
3280 
3281                 if (GL_INVALID_OPERATION != gl.getError())
3282                 {
3283                     result = false;
3284 
3285                     m_testCtx.getLog() << tcu::TestLog::Message
3286                                        << "Error different than GL_INVALID_OPEARATION was generated."
3287                                        << tcu::TestLog::EndMessage;
3288 
3289                     break;
3290                 }
3291 
3292                 gl.drawArrays(GL_TRIANGLE_FAN, 0 /*starting index*/, 3 /*number of indices*/);
3293 
3294                 if (GL_INVALID_OPERATION != gl.getError())
3295                 {
3296                     result = false;
3297 
3298                     m_testCtx.getLog() << tcu::TestLog::Message
3299                                        << "Error different than GL_INVALID_OPEARATION was generated."
3300                                        << tcu::TestLog::EndMessage;
3301 
3302                     break;
3303                 }
3304 
3305                 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /*starting index*/, 3 /*number of indices*/);
3306 
3307                 if (GL_INVALID_OPERATION != gl.getError())
3308                 {
3309                     result = false;
3310 
3311                     m_testCtx.getLog() << tcu::TestLog::Message
3312                                        << "Error different than GL_INVALID_OPEARATION was generated."
3313                                        << tcu::TestLog::EndMessage;
3314 
3315                     break;
3316                 }
3317             }
3318 
3319             if (po != 4)
3320             {
3321                 gl.drawArrays(GL_TRIANGLES_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
3322 
3323                 if (GL_INVALID_OPERATION != gl.getError())
3324                 {
3325                     result = false;
3326 
3327                     m_testCtx.getLog() << tcu::TestLog::Message
3328                                        << "Error different than GL_INVALID_OPEARATION was generated."
3329                                        << tcu::TestLog::EndMessage;
3330 
3331                     break;
3332                 }
3333 
3334                 gl.drawArrays(GL_TRIANGLE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
3335 
3336                 if (GL_INVALID_OPERATION != gl.getError())
3337                 {
3338                     result = false;
3339 
3340                     m_testCtx.getLog() << tcu::TestLog::Message
3341                                        << "Error different than GL_INVALID_OPEARATION was generated."
3342                                        << tcu::TestLog::EndMessage;
3343 
3344                     break;
3345                 }
3346             }
3347         }
3348     }
3349 
3350     if (result)
3351     {
3352         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3353     }
3354     else
3355     {
3356         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3357     }
3358 
3359     return STOP;
3360 }
3361 
3362 /** Constructor
3363  *
3364  * @param context       Test context
3365  * @param extParams     Not used.
3366  * @param name          Test case's name
3367  * @param description   Test case's description
3368  **/
GeometryShaderInsufficientEmittedVerticesTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)3369 GeometryShaderInsufficientEmittedVerticesTest::GeometryShaderInsufficientEmittedVerticesTest(
3370     Context &context, const ExtParameters &extParams, const char *name, const char *description)
3371     : TestCaseBase(context, extParams, name, description)
3372     , m_fbo_id(0)
3373     , m_fs_id(0)
3374     , m_gs_ids(NULL)
3375     , m_number_of_color_components(4)
3376     , m_number_of_gs(2 /*taken from test spec*/)
3377     , m_po_ids(NULL)
3378     , m_texture_height(16)
3379     , m_texture_id(0)
3380     , m_texture_width(16)
3381 {
3382     m_vao_id = 0;
3383     m_vs_id  = 0;
3384 
3385     /* Allocate enough memory for glReadPixels() data which is respectively: width, height, RGBA components number. */
3386     m_pixels = new glw::GLubyte[m_texture_height * m_texture_width * m_number_of_color_components];
3387 }
3388 
3389 /** Deinitializes GLES objects created during the test. */
deinit()3390 void GeometryShaderInsufficientEmittedVerticesTest::deinit()
3391 {
3392     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3393 
3394     gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
3395 
3396     if (m_pixels != NULL)
3397     {
3398         delete[] m_pixels;
3399         m_pixels = NULL;
3400     }
3401 
3402     if (m_fbo_id != 0)
3403     {
3404         gl.deleteFramebuffers(1, &m_fbo_id);
3405         m_fbo_id = 0;
3406     }
3407 
3408     if (m_fs_id != 0)
3409     {
3410         gl.deleteShader(m_fs_id);
3411         m_fs_id = 0;
3412     }
3413 
3414     if (m_gs_ids != 0)
3415     {
3416         for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3417         {
3418             gl.deleteShader(m_gs_ids[i]);
3419             m_gs_ids[i] = 0;
3420         }
3421 
3422         delete[] m_gs_ids;
3423         m_gs_ids = NULL;
3424     }
3425 
3426     if (m_po_ids != 0)
3427     {
3428         for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3429         {
3430             gl.deleteProgram(m_po_ids[i]);
3431             m_po_ids[i] = 0;
3432         }
3433 
3434         delete[] m_po_ids;
3435         m_po_ids = NULL;
3436     }
3437 
3438     if (m_texture_id != 0)
3439     {
3440         gl.deleteTextures(1, &m_texture_id);
3441         m_texture_id = 0;
3442     }
3443 
3444     if (m_vao_id != 0)
3445     {
3446         gl.deleteVertexArrays(1, &m_vao_id);
3447         m_vao_id = 0;
3448     }
3449 
3450     if (m_vs_id != 0)
3451     {
3452         gl.deleteShader(m_vs_id);
3453         m_vs_id = 0;
3454     }
3455 
3456     /* Release base class */
3457     TestCaseBase::deinit();
3458 }
3459 
3460 /** Executes the test.
3461  *
3462  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3463  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3464  *  Note the function throws exception should an error occur!
3465  **/
iterate()3466 tcu::TestNode::IterateResult GeometryShaderInsufficientEmittedVerticesTest::iterate()
3467 {
3468     /* Define Fragment Shader for purpose of this test. */
3469     const char *fs_code = "${VERSION}\n"
3470                           "\n"
3471                           "precision highp float;\n"
3472                           "\n"
3473                           "out vec4 result;\n"
3474                           "\n"
3475                           "void main()\n"
3476                           "{\n"
3477                           "    result = vec4(1.0, 0.0, 0.0, 0.0);\n"
3478                           "}\n";
3479 
3480     /* Define 2 Geometry Shaders for purpose of this test. */
3481     const char *gs_line_strip = "${VERSION}\n"
3482                                 "${GEOMETRY_SHADER_REQUIRE}\n"
3483                                 "\n"
3484                                 "layout (points)                       in;\n"
3485                                 "layout (line_strip, max_vertices = 2) out;\n"
3486                                 "\n"
3487                                 "${IN_PER_VERTEX_DECL_ARRAY}"
3488                                 "\n"
3489                                 "void main()\n"
3490                                 "{\n"
3491                                 "    gl_Position    = gl_in[0].gl_Position;\n"
3492                                 "    gl_Position.zw = vec2(0.0, 1.0);\n"
3493                                 "    EmitVertex();\n"
3494                                 "}\n";
3495 
3496     const char *gs_triangle_strip = "${VERSION}\n"
3497                                     "${GEOMETRY_SHADER_REQUIRE}\n"
3498                                     "\n"
3499                                     "layout (points)                           in;\n"
3500                                     "layout (triangle_strip, max_vertices = 3) out;\n"
3501                                     "\n"
3502                                     "${IN_PER_VERTEX_DECL_ARRAY}"
3503                                     "\n"
3504                                     "void main()\n"
3505                                     "{\n"
3506                                     "    gl_Position    = gl_in[0].gl_Position;\n"
3507                                     "    gl_Position.zw = vec2(0.0, 1.0);\n"
3508                                     "    EmitVertex();\n"
3509 
3510                                     "    gl_Position    = gl_in[0].gl_Position;\n"
3511                                     "    gl_Position.zw = vec2(0.0, 1.0);\n"
3512                                     "    EmitVertex();\n"
3513                                     "}\n";
3514 
3515     bool has_shader_compilation_failed = true;
3516     bool result                        = true;
3517 
3518     m_gs_ids = new glw::GLuint[m_number_of_gs];
3519     m_po_ids = new glw::GLuint[m_number_of_gs];
3520 
3521     /* This test should only run if EXT_geometry_shader is supported. */
3522     if (!m_is_geometry_shader_extension_supported)
3523     {
3524         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3525     }
3526 
3527     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3528 
3529     /* Create program objects & geometry shader objects. */
3530     for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3531     {
3532         m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
3533         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3534 
3535         m_po_ids[i] = gl.createProgram();
3536         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3537     }
3538 
3539     /* Create shader object. */
3540     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3541     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3542     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3543 
3544     /* Try to link the test program object */
3545     std::string fs_code_specialized     = specializeShader(1, &fs_code);
3546     const char *fs_code_specialized_raw = fs_code_specialized.c_str();
3547 
3548     std::string gs_codes_specialized[] = {specializeShader(1, &gs_line_strip), specializeShader(1, &gs_triangle_strip)};
3549 
3550     const char *gs_codes_specialized_raw[] = {gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str()};
3551 
3552     std::string vs_code_specialized     = specializeShader(1, &minimal_vs_code);
3553     const char *vs_code_specialized_raw = vs_code_specialized.c_str();
3554 
3555     for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3556     {
3557         if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,                  /* n_sh1_body_parts */
3558                                         &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
3559                                         &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
3560                                         &vs_code_specialized_raw, &has_shader_compilation_failed))
3561         {
3562             m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
3563                                << "[" << i << "]." << tcu::TestLog::EndMessage;
3564 
3565             result = false;
3566             break;
3567         }
3568     }
3569 
3570     if (result)
3571     {
3572         /* Create a 2D texture. */
3573         gl.genTextures(1, &m_texture_id);
3574         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
3575 
3576         gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
3577         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
3578 
3579         gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_RGBA8, 16 /*width taken from spec*/,
3580                         16 /*height taken from spec*/);
3581         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
3582 
3583         /* Configure FBO. */
3584         gl.genFramebuffers(1, &m_fbo_id);
3585         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
3586 
3587         gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
3588         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
3589 
3590         gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /*level*/);
3591         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
3592 
3593         /* Configure VAO. */
3594         gl.genVertexArrays(1, &m_vao_id);
3595         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3596 
3597         gl.bindVertexArray(m_vao_id);
3598         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3599 
3600         gl.clearColor(0.0f, 1.0f, 0.0f, 0.0f);
3601         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
3602 
3603         for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
3604         {
3605             /* Use Program Object. */
3606             gl.useProgram(m_po_ids[po]);
3607             GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3608 
3609             gl.clear(GL_COLOR_BUFFER_BIT);
3610             GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
3611 
3612             gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3613             GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
3614 
3615             gl.readPixels(0 /*x*/, 0 /*y*/, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
3616             GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
3617 
3618             for (glw::GLuint pixel = 0; pixel < (m_texture_width * m_texture_height * m_number_of_color_components -
3619                                                  m_number_of_color_components);
3620                  pixel += m_number_of_color_components)
3621             {
3622                 if (m_pixels[pixel] != 0 && m_pixels[pixel + 1] != 255 && m_pixels[pixel + 2] != 0 &&
3623                     m_pixels[pixel + 3] != 0)
3624                 {
3625                     result = false;
3626 
3627                     m_testCtx.getLog() << tcu::TestLog::Message << "Pixel [" << pixel << "] has color = ["
3628                                        << m_pixels[pixel] << ", " << m_pixels[pixel + 1] << ", " << m_pixels[pixel + 2]
3629                                        << ", " << m_pixels[pixel + 3] << "] "
3630                                        << "instead of [0, 255, 0, 0]." << tcu::TestLog::EndMessage;
3631 
3632                     break;
3633                 }
3634             }
3635         }
3636     }
3637 
3638     if (result)
3639     {
3640         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3641     }
3642     else
3643     {
3644         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3645     }
3646 
3647     return STOP;
3648 }
3649 
3650 /** Constructor
3651  *
3652  * @param context       Test context
3653  * @param extParams     Not used.
3654  * @param name          Test case's name
3655  * @param description   Test case's description
3656  **/
3657 GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::
GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)3658     GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context &context,
3659                                                                                     const ExtParameters &extParams,
3660                                                                                     const char *name,
3661                                                                                     const char *description)
3662     : TestCaseBase(context, extParams, name, description)
3663     , m_gs_id(0)
3664     , m_gs_po_id(0)
3665     , m_ppo_id(0)
3666     , m_tfbo_id(0)
3667     , m_vao_id(0)
3668     , m_vs_id(0)
3669     , m_vs_po_id(0)
3670 {
3671 }
3672 
3673 /** Deinitializes GLES objects created during the test. */
deinit()3674 void GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::deinit()
3675 {
3676     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3677 
3678     if (m_gs_id != 0)
3679     {
3680         gl.deleteShader(m_gs_id);
3681         m_gs_id = 0;
3682     }
3683 
3684     if (m_gs_po_id != 0)
3685     {
3686         gl.deleteProgram(m_gs_po_id);
3687         m_gs_po_id = 0;
3688     }
3689 
3690     if (m_ppo_id != 0)
3691     {
3692         gl.deleteProgramPipelines(1, &m_ppo_id);
3693         m_ppo_id = 0;
3694     }
3695 
3696     if (m_tfbo_id != 0)
3697     {
3698         gl.deleteBuffers(1, &m_tfbo_id);
3699         m_tfbo_id = 0;
3700     }
3701 
3702     if (m_vao_id != 0)
3703     {
3704         gl.deleteVertexArrays(1, &m_vao_id);
3705         m_vao_id = 0;
3706     }
3707 
3708     if (m_vs_id != 0)
3709     {
3710         gl.deleteShader(m_vs_id);
3711         m_vs_id = 0;
3712     }
3713 
3714     if (m_vs_po_id != 0)
3715     {
3716         gl.deleteProgram(m_vs_po_id);
3717         m_vs_po_id = 0;
3718     }
3719 
3720     /* Release base class */
3721     TestCaseBase::deinit();
3722 }
3723 
3724 /** Executes the test.
3725  *
3726  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3727  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3728  *  Note the function throws exception should an error occur!
3729  **/
iterate()3730 tcu::TestNode::IterateResult GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::iterate()
3731 {
3732     /* Define Geometry Shader for purpose of this test. */
3733     const char *gs_code =
3734         "${VERSION}\n"
3735         "${GEOMETRY_SHADER_REQUIRE}\n"
3736         "${IN_PER_VERTEX_DECL_ARRAY}\n"
3737         "${OUT_PER_VERTEX_DECL}\n"
3738         "\n"
3739         "layout (points)                   in;\n"
3740         "layout (points, max_vertices = 1) out;\n"
3741         "\n"
3742         "flat in int   vertexID[];\n"
3743         "flat in ivec4 out_vs_1[];\n"
3744         "\n"
3745         "out vec4 out_gs_1;\n"
3746         "\n"
3747         "void main()\n"
3748         "{\n"
3749         "    out_gs_1 = vec4(vertexID[0] * 2, vertexID[0] * 2 + 1, vertexID[0] * 2 + 2, vertexID[0] * 2 + 3);\n"
3750         "    gl_Position = vec4(0, 0, 0, 1);\n"
3751         "    EmitVertex();\n"
3752         "}\n";
3753 
3754     /* Define Vertex Shader for purpose of this test. */
3755     const char *vs_code = "${VERSION}\n"
3756                           "${OUT_PER_VERTEX_DECL}\n"
3757                           "\n"
3758                           "flat out ivec4 out_vs_1;\n"
3759                           "flat out int vertexID;\n"
3760                           "\n"
3761                           "void main()\n"
3762                           "{\n"
3763                           "    vertexID = gl_VertexID;\n"
3764                           "    out_vs_1 = ivec4(gl_VertexID, gl_VertexID + 1, gl_VertexID + 2, gl_VertexID + 3);\n"
3765                           "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3766                           "}\n";
3767 
3768     bool has_shader_compilation_failed    = true;
3769     bool result                           = true;
3770     glw::GLfloat *ptrTF_data_f            = NULL;
3771     glw::GLuint *ptrTF_data_ui            = NULL;
3772     glw::GLfloat expected_geom_results[]  = {0.0f, 1.0f, 2.0f, 3.0f};
3773     glw::GLuint expected_vertex_results[] = {0, 1, 2, 3};
3774     glw::GLfloat epsilon                  = 1e-5f;
3775 
3776     /* This test should only run if EXT_geometry_shader is supported. */
3777     if (!m_is_geometry_shader_extension_supported)
3778     {
3779         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3780     }
3781 
3782     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3783 
3784     /* Create separable program objects. */
3785     m_gs_po_id = gl.createProgram();
3786     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3787 
3788     gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
3789     GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
3790 
3791     m_vs_po_id = gl.createProgram();
3792     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3793 
3794     gl.programParameteri(m_vs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
3795     GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
3796 
3797     /* Create shader objects. */
3798     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
3799     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3800     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3801 
3802     /* Try to link the test program object */
3803     std::string gs_code_specialized     = specializeShader(1, &gs_code);
3804     const char *gs_code_specialized_raw = gs_code_specialized.c_str();
3805 
3806     std::string vs_code_specialized     = specializeShader(1, &vs_code);
3807     const char *vs_code_specialized_raw = vs_code_specialized.c_str();
3808 
3809     /* Specify output variables to be captured. */
3810     const char *tf_varyings[2] = {"out_gs_1", "out_vs_1"};
3811 
3812     gl.transformFeedbackVaryings(m_gs_po_id, 1 /*count*/, &tf_varyings[0], GL_INTERLEAVED_ATTRIBS);
3813     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
3814 
3815     gl.transformFeedbackVaryings(m_vs_po_id, 1 /*count*/, &tf_varyings[1], GL_INTERLEAVED_ATTRIBS);
3816     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
3817 
3818     if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1,         /* n_sh1_body_parts */
3819                                     &gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
3820                                     NULL, 0, 0,                     /* n_sh3_body_parts */
3821                                     NULL, &has_shader_compilation_failed))
3822     {
3823         m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
3824                            << tcu::TestLog::EndMessage;
3825 
3826         result = false;
3827         goto end;
3828     }
3829 
3830     if (!TestCaseBase::buildProgram(m_vs_po_id, m_vs_id, 1,         /* n_sh1_body_parts */
3831                                     &vs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
3832                                     NULL, 0, 0,                     /* n_sh3_body_parts */
3833                                     NULL, &has_shader_compilation_failed))
3834     {
3835         m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
3836                            << tcu::TestLog::EndMessage;
3837 
3838         result = false;
3839         goto end;
3840     }
3841 
3842     /* Create and configure Program Pipeline Object. */
3843     gl.genProgramPipelines(1, &m_ppo_id);
3844     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call(s) failed.");
3845 
3846     gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
3847     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3848 
3849     gl.useProgramStages(m_ppo_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
3850     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3851 
3852     /* Create Vertex Array Object. */
3853     gl.genVertexArrays(1, &m_vao_id);
3854     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
3855 
3856     gl.bindVertexArray(m_vao_id);
3857     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
3858 
3859     /* Create Buffer Object for Transform Feedback data. */
3860     gl.genBuffers(1, &m_tfbo_id);
3861     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
3862 
3863     gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
3864     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
3865 
3866     gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4, NULL, GL_STREAM_READ);
3867     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
3868 
3869     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
3870     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
3871 
3872     /* Ensure that there is no program object already bound and bind program pipeline. */
3873     gl.useProgram(0);
3874     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
3875 
3876     gl.bindProgramPipeline(m_ppo_id);
3877     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
3878 
3879     gl.enable(GL_RASTERIZER_DISCARD);
3880     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
3881 
3882     /* First pass - Vertex and Geometry Shaders On. */
3883     gl.beginTransformFeedback(GL_POINTS);
3884     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
3885 
3886     gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3887     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
3888 
3889     gl.endTransformFeedback();
3890     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
3891 
3892     /* Retrieve data and check if it is correct. */
3893     ptrTF_data_f =
3894         (glw::GLfloat *)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
3895                                           sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
3896     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3897 
3898     for (size_t i = 0; i < 4; ++i)
3899     {
3900         if (fabs(ptrTF_data_f[i] - expected_geom_results[i]) >= epsilon)
3901         {
3902             result = false;
3903             break;
3904         }
3905     }
3906 
3907     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3908     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3909 
3910     ptrTF_data_f = NULL;
3911 
3912     if (!result)
3913     {
3914         goto end;
3915     }
3916 
3917     /* Deactivate Geometry Shader Program Object from Program Pipeline Object. */
3918     gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, 0 /* program */);
3919     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3920 
3921     /* Second pass - only Vertex Shader Program On. */
3922     gl.beginTransformFeedback(GL_POINTS);
3923     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
3924 
3925     gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3926     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
3927 
3928     gl.endTransformFeedback();
3929     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
3930 
3931     gl.disable(GL_RASTERIZER_DISCARD);
3932     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
3933 
3934     /* Retrieve data and check if it is correct. */
3935     ptrTF_data_ui =
3936         (glw::GLuint *)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
3937                                          sizeof(glw::GLuint) * 4 /* four float vector components */, GL_MAP_READ_BIT);
3938     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3939 
3940     for (size_t i = 0; i < 4; ++i)
3941     {
3942         if (ptrTF_data_ui[i] != expected_vertex_results[i])
3943         {
3944             result = false;
3945             break;
3946         }
3947     }
3948 
3949     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3950     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3951 
3952     ptrTF_data_ui = NULL;
3953 
3954 end:
3955     if (result)
3956     {
3957         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3958     }
3959     else
3960     {
3961         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3962     }
3963 
3964     return STOP;
3965 }
3966 
3967 /** Constructor
3968  *
3969  * @param context       Test context
3970  * @param extParams     Not used.
3971  * @param name          Test case's name
3972  * @param description   Test case's description
3973  **/
GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives(Context & context,const ExtParameters & extParams,const char * name,const char * description)3974 GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives(
3975     Context &context, const ExtParameters &extParams, const char *name, const char *description)
3976     : TestCaseBase(context, extParams, name, description)
3977     , m_fs_id(0)
3978     , m_gs_id(0)
3979     , m_po_id(0)
3980     , m_tfbo_id(0)
3981 {
3982     m_vao_id = 0;
3983     m_vs_id  = 0;
3984 }
3985 
3986 /** Deinitializes GLES objects created during the test. */
deinit()3987 void GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::deinit()
3988 {
3989     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3990 
3991     if (m_fs_id != 0)
3992     {
3993         gl.deleteShader(m_fs_id);
3994         m_fs_id = 0;
3995     }
3996 
3997     if (m_gs_id != 0)
3998     {
3999         gl.deleteShader(m_gs_id);
4000         m_gs_id = 0;
4001     }
4002 
4003     if (m_po_id != 0)
4004     {
4005         gl.deleteProgram(m_po_id);
4006         m_po_id = 0;
4007     }
4008 
4009     if (m_tfbo_id != 0)
4010     {
4011         gl.deleteBuffers(1, &m_tfbo_id);
4012         m_tfbo_id = 0;
4013     }
4014 
4015     if (m_vao_id != 0)
4016     {
4017         gl.deleteVertexArrays(1, &m_vao_id);
4018         m_vao_id = 0;
4019     }
4020 
4021     if (m_vs_id != 0)
4022     {
4023         gl.deleteShader(m_vs_id);
4024         m_vs_id = 0;
4025     }
4026 
4027     /* Release base class */
4028     TestCaseBase::deinit();
4029 }
4030 
4031 /** Executes the test.
4032  *
4033  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4034  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
4035  *  Note the function throws exception should an error occur!
4036  **/
iterate()4037 tcu::TestNode::IterateResult GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::iterate()
4038 {
4039     /* Define Geometry Shader for purpose of this test. */
4040     const char *gs_code = "${VERSION}\n"
4041                           "${GEOMETRY_SHADER_REQUIRE}\n"
4042                           "\n"
4043                           "layout (lines)                            in;\n"
4044                           "layout (triangle_strip, max_vertices = 3) out;\n"
4045                           "\n"
4046                           "out vec4 out_gs_1;\n"
4047                           "\n"
4048                           "void main()\n"
4049                           "{\n"
4050                           "    out_gs_1 = vec4(4.0, 3.0, 2.0, 1.0);\n"
4051                           "\n"
4052                           "    gl_Position = vec4(0, 0, 0, 1);\n"
4053                           "    EmitVertex();\n"
4054                           "\n"
4055                           "    gl_Position = vec4(1, 0, 0, 1);\n"
4056                           "    EmitVertex();\n"
4057                           "\n"
4058                           "    gl_Position = vec4(1, 1, 0, 1);\n"
4059                           "    EmitVertex();\n"
4060                           "\n"
4061                           "    EndPrimitive();"
4062                           "}\n";
4063 
4064     bool has_shader_compilation_failed = true;
4065     bool result                        = true;
4066     glw::GLenum error                  = GL_NO_ERROR;
4067 
4068     /* This test should only run if EXT_geometry_shader is supported. */
4069     if (!m_is_geometry_shader_extension_supported)
4070     {
4071         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
4072     }
4073 
4074     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4075 
4076     /* Create program object. */
4077     m_po_id = gl.createProgram();
4078     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
4079 
4080     /* Specify output variables to be captured. */
4081     const char *tf_varyings[] = {"out_gs_1"};
4082 
4083     gl.transformFeedbackVaryings(m_po_id, 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
4084     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
4085 
4086     /* Create shader objects. */
4087     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4088     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4089     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4090     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4091 
4092     /* Try to link the test program object */
4093     std::string fs_code_specialized     = specializeShader(1, &minimal_fs_code);
4094     const char *fs_code_specialized_raw = fs_code_specialized.c_str();
4095 
4096     std::string gs_code_specialized     = specializeShader(1, &gs_code);
4097     const char *gs_code_specialized_raw = gs_code_specialized.c_str();
4098 
4099     std::string vs_code_specialized     = specializeShader(1, &minimal_vs_code);
4100     const char *vs_code_specialized_raw = vs_code_specialized.c_str();
4101 
4102     if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1,                  /* n_sh1_body_parts */
4103                                     &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
4104                                     &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
4105                                     &vs_code_specialized_raw, &has_shader_compilation_failed))
4106     {
4107         m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed whereas a success was expected."
4108                            << tcu::TestLog::EndMessage;
4109 
4110         result = false;
4111         goto end;
4112     }
4113 
4114     /* Create Vertex Array Object. */
4115     gl.genVertexArrays(1, &m_vao_id);
4116     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
4117 
4118     gl.bindVertexArray(m_vao_id);
4119     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
4120 
4121     /* Create Buffer Object for Transform Feedback data. */
4122     gl.genBuffers(1, &m_tfbo_id);
4123     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
4124 
4125     gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
4126     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4127 
4128     gl.bufferData(GL_ARRAY_BUFFER,
4129                   sizeof(glw::GLfloat) * 4 * 3 /* capture 4 float vector components times 3 triangle vertices */, NULL,
4130                   GL_STREAM_READ);
4131     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
4132 
4133     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
4134     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
4135 
4136     /* Turn on program object. */
4137     gl.useProgram(m_po_id);
4138     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
4139 
4140     gl.enable(GL_RASTERIZER_DISCARD);
4141     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
4142 
4143     gl.beginTransformFeedback(GL_LINES);
4144     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
4145 
4146     gl.drawArrays(GL_TRIANGLES, 0 /*first*/, 3 /*count*/);
4147 
4148     error = gl.getError();
4149 
4150     if (error != GL_INVALID_OPERATION)
4151     {
4152         result = false;
4153 
4154         m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
4155                            << tcu::TestLog::EndMessage;
4156     }
4157 
4158     gl.endTransformFeedback();
4159     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
4160 
4161     gl.disable(GL_RASTERIZER_DISCARD);
4162     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
4163 
4164 end:
4165 
4166     if (result)
4167     {
4168         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4169     }
4170     else
4171     {
4172         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4173     }
4174 
4175     return STOP;
4176 }
4177 
4178 /** Constructor
4179  *
4180  * @param context       Test context
4181  * @param extParams     Not used.
4182  * @param name          Test case's name
4183  * @param description   Test case's description
4184  **/
GeometryShaderDrawCallsWhileTFPaused(Context & context,const ExtParameters & extParams,const char * name,const char * description)4185 GeometryShaderDrawCallsWhileTFPaused::GeometryShaderDrawCallsWhileTFPaused(Context &context,
4186                                                                            const ExtParameters &extParams,
4187                                                                            const char *name, const char *description)
4188     : TestCaseBase(context, extParams, name, description)
4189     , m_fs_id(0)
4190     , m_gs_id(0)
4191     , m_tfbo_id(0)
4192 {
4193     m_vao_id = 0;
4194     m_vs_id  = 0;
4195 }
4196 
4197 /** Deinitializes GLES objects created during the test. */
deinit()4198 void GeometryShaderDrawCallsWhileTFPaused::deinit()
4199 {
4200     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4201 
4202     if (m_fs_id != 0)
4203     {
4204         gl.deleteShader(m_fs_id);
4205         m_fs_id = 0;
4206     }
4207 
4208     if (m_gs_id != 0)
4209     {
4210         gl.deleteShader(m_gs_id);
4211         m_gs_id = 0;
4212     }
4213 
4214     for (int i = 0; i < 15 /* All combinations of possible inputs and outputs in GS */; ++i)
4215     {
4216         if (m_po_ids[i] != 0)
4217         {
4218             gl.deleteProgram(m_po_ids[i]);
4219             m_po_ids[i] = 0;
4220         }
4221     }
4222 
4223     if (m_tfbo_id != 0)
4224     {
4225         gl.deleteBuffers(1, &m_tfbo_id);
4226         m_tfbo_id = 0;
4227     }
4228 
4229     if (m_vao_id != 0)
4230     {
4231         gl.deleteVertexArrays(1, &m_vao_id);
4232         m_vao_id = 0;
4233     }
4234 
4235     if (m_vs_id != 0)
4236     {
4237         gl.deleteShader(m_vs_id);
4238         m_vs_id = 0;
4239     }
4240 
4241     /* Release base class */
4242     TestCaseBase::deinit();
4243 }
4244 
4245 /** Executes the test.
4246  *
4247  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4248  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
4249  *  Note the function throws exception should an error occur!
4250  **/
iterate()4251 tcu::TestNode::IterateResult GeometryShaderDrawCallsWhileTFPaused::iterate()
4252 {
4253     /* Define 15 (all combinations of possible inputs and outputs in geometry shader) Geometry Shaders for purpose of this test. */
4254     const std::string gs_inputs[]  = {"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"};
4255     const std::string gs_outputs[] = {"points", "line_strip", "triangle_strip"};
4256     const std::string gs_max_output_vertices[] = {"1", "2", "3"};
4257 
4258     const unsigned short number_of_combinations =
4259         (sizeof(gs_inputs) / sizeof(gs_inputs[0]) * (sizeof(gs_outputs) / sizeof(gs_outputs[0])));
4260 
4261     std::string gs_codes[number_of_combinations];
4262     glw::GLenum errorCode;
4263 
4264     for (size_t i = 0; i < (sizeof(gs_inputs) / sizeof(gs_inputs[0])) /*5 possible GS inputs*/; ++i)
4265     {
4266         for (size_t j = 0; j < (sizeof(gs_outputs) / sizeof(gs_outputs[0])) /*3 possible GS outputs*/; ++j)
4267         {
4268             /* This shader will not emit primitives for anything but points.
4269              * We do so, because we just need to make sure that, while transform feedback
4270              * is paused, all draw calls executed with an active program object which
4271              * includes a geometry shader, are valid.
4272              */
4273             gs_codes[j + 3 * i] = "${VERSION}\n"
4274                                   "${GEOMETRY_SHADER_REQUIRE}\n"
4275                                   "\n"
4276                                   "layout (" +
4277                                   gs_inputs[i] +
4278                                   ") in;\n"
4279                                   "layout (" +
4280                                   gs_outputs[j] + ", max_vertices = " + gs_max_output_vertices[j] +
4281                                   ") out;\n"
4282                                   "\n"
4283                                   "out vec2 out_gs_1;\n"
4284                                   "\n"
4285                                   "void main()\n"
4286                                   "{\n"
4287                                   "    out_gs_1    = vec2(1.0, 2.0);\n"
4288                                   "    gl_Position = vec4(0, 0, 0, 1);\n"
4289                                   "    EmitVertex();\n"
4290                                   "}\n";
4291         }
4292     }
4293 
4294     bool has_shader_compilation_failed   = true;
4295     bool result                          = true;
4296     const glw::GLuint tf_modes[3]        = {GL_POINTS, GL_LINES, GL_TRIANGLES};
4297     const glw::GLuint draw_call_modes[5] = {GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES,
4298                                             GL_TRIANGLES_ADJACENCY};
4299 
4300     /* This test should only run if EXT_geometry_shader is supported. */
4301     if (!m_is_geometry_shader_extension_supported)
4302     {
4303         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
4304     }
4305 
4306     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4307 
4308     /* Create program objects. */
4309     for (int i = 0; i < number_of_combinations; ++i)
4310     {
4311         m_po_ids[i] = gl.createProgram();
4312     }
4313     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
4314 
4315     /* Specify output variables to be captured. */
4316     const char *tf_varyings[] = {"out_gs_1"};
4317 
4318     for (int i = 0; i < number_of_combinations; ++i)
4319     {
4320         gl.transformFeedbackVaryings(m_po_ids[i], 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
4321     }
4322     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
4323 
4324     /* Create shader objects. */
4325     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4326     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4327     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4328     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4329 
4330     /* Try to link the test program object */
4331     std::string fs_code_specialized     = specializeShader(1, &minimal_fs_code);
4332     const char *fs_code_specialized_raw = fs_code_specialized.c_str();
4333 
4334     std::string vs_code_specialized     = specializeShader(1, &minimal_vs_code);
4335     const char *vs_code_specialized_raw = vs_code_specialized.c_str();
4336 
4337     for (int i = 0; i < number_of_combinations; ++i)
4338     {
4339         const char *gs_code                 = gs_codes[i].c_str();
4340         std::string gs_code_specialized     = specializeShader(1, &gs_code);
4341         const char *gs_code_specialized_raw = gs_code_specialized.c_str();
4342 
4343         if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,              /* n_sh1_body_parts */
4344                                         &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
4345                                         &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
4346                                         &vs_code_specialized_raw, &has_shader_compilation_failed))
4347         {
4348             m_testCtx.getLog() << tcu::TestLog::Message
4349                                << "Program object linking failed whereas a success was expected."
4350                                << tcu::TestLog::EndMessage;
4351 
4352             result = false;
4353         }
4354     }
4355 
4356     if (!result)
4357     {
4358         goto end;
4359     }
4360 
4361     /* Create Vertex Array Object. */
4362     gl.genVertexArrays(1, &m_vao_id);
4363     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
4364 
4365     gl.bindVertexArray(m_vao_id);
4366     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
4367 
4368     /* Create Buffer Object for Transform Feedback data. */
4369     gl.genBuffers(1, &m_tfbo_id);
4370     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
4371 
4372     gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
4373     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4374 
4375     gl.bufferData(GL_ARRAY_BUFFER,
4376                   sizeof(glw::GLfloat) * 2 * 3 /* capture 2 float vector components times 3 triangle vertices */, NULL,
4377                   GL_STREAM_READ);
4378     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
4379 
4380     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
4381     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
4382 
4383     gl.enable(GL_RASTERIZER_DISCARD);
4384     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
4385 
4386     for (int i = 0; i < 3 /* number of TF modes */ && result; ++i)
4387     {
4388         for (int j = 0; j < 5 /*number of draw call modes*/ && result; ++j)
4389         {
4390             for (int k = 0; k < 3 /* number of output GS primitive types */; ++k)
4391             {
4392                 /* Turn on program object. */
4393                 gl.useProgram(m_po_ids[k + 3 * j]);
4394                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
4395 
4396                 gl.beginTransformFeedback(tf_modes[i]);
4397                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
4398 
4399                 gl.pauseTransformFeedback();
4400                 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback() call(s) failed.");
4401 
4402                 gl.drawArrays(draw_call_modes[j], 0 /*first*/, 3 /*count*/);
4403                 errorCode = gl.getError();
4404 
4405                 gl.resumeTransformFeedback();
4406                 GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback() call(s) failed.");
4407 
4408                 gl.endTransformFeedback();
4409                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
4410 
4411                 /* If draw call fails stop test execution. */
4412                 if (GL_NO_ERROR != errorCode)
4413                 {
4414                     m_testCtx.getLog() << tcu::TestLog::Message
4415                                        << "glDrawArrays() call generated an error while transform feedback was paused."
4416                                        << tcu::TestLog::EndMessage;
4417 
4418                     result = false;
4419                     break;
4420                 }
4421             }
4422         }
4423     }
4424 
4425     gl.disable(GL_RASTERIZER_DISCARD);
4426     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
4427 
4428 end:
4429 
4430     if (result)
4431     {
4432         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4433     }
4434     else
4435     {
4436         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4437     }
4438 
4439     return STOP;
4440 }
4441 
4442 } // namespace glcts
4443