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