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