[automerger skipped] Merge "DO NOT MERGE: Drop dEQP-VK.image.qualifiers.{coherent...
[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         /* Check if m_gl_max_geometry_image_uniforms_value is less than or equal zero. */
1558         if (m_gl_max_geometry_image_uniforms_ext_value <= 0)
1559         {
1560                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
1561                                                    << "[" << m_gl_max_geometry_image_uniforms_ext_value
1562                                                    << "]"
1563                                                           " is less than or equal zero. Image uniforms in Geometry Shader"
1564                                                           " are not supported."
1565                                                    << tcu::TestLog::EndMessage;
1566
1567                 if (m_gl_max_geometry_image_uniforms_ext_value == 0)
1568                 {
1569                         throw tcu::NotSupportedError("GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT is 0");
1570                 }
1571                 else
1572                 {
1573                         result = false;
1574                         goto end;
1575                 }
1576         }
1577
1578         /* Check if m_gl_max_geometry_texture_image_units_value is less than m_gl_max_geometry_image_uniforms_value. */
1579         if (m_gl_max_geometry_texture_image_units_ext_value < m_gl_max_geometry_image_uniforms_ext_value)
1580         {
1581                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
1582                                                    << "[" << m_gl_max_geometry_image_uniforms_ext_value
1583                                                    << "]"
1584                                                           " is greater than GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT query value "
1585                                                           "["
1586                                                    << m_gl_max_geometry_texture_image_units_ext_value << "]." << tcu::TestLog::EndMessage;
1587
1588                 result = false;
1589                 goto end;
1590         }
1591
1592         /* Create a program object. */
1593         m_po_id = gl.createProgram();
1594         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1595
1596         /* Create shader objects. */
1597         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1598         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1599         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1600
1601         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1602
1603         /* Configure which outputs should be captured by Transform Feedback. */
1604         gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
1605
1606         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
1607
1608         /* Try to link the test program object */
1609         fs_code_specialized             = specializeShader(1, &dummy_fs_code);
1610         fs_code_specialized_raw = fs_code_specialized.c_str();
1611
1612         gs_code_specialized             = getGSCode();
1613         gs_code_specialized_raw = gs_code_specialized.c_str();
1614
1615         vs_code_specialized             = specializeShader(1, &dummy_vs_code);
1616         vs_code_specialized_raw = vs_code_specialized.c_str();
1617
1618         if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,                              /* n_sh1_body_parts */
1619                                                                         &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1620                                                                         &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1621                                                                         &fs_code_specialized_raw, &has_shader_compilation_failed))
1622         {
1623                 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
1624
1625                 result = false;
1626                 goto end;
1627         }
1628
1629         /* Use program. */
1630         gl.useProgram(m_po_id);
1631         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1632
1633         /* Allocate memory for m_max_image_units_value Texture Objects. */
1634         m_texture_ids = new glw::GLuint[m_gl_max_geometry_image_uniforms_ext_value];
1635
1636         /* Generate m_max_image_units_value Texture Objects. */
1637         gl.genTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids);
1638         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
1639
1640         /* Set GL_PACK_ALIGNMENT to 1. */
1641         gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1642         GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname.");
1643
1644         /* Bind integer 2D texture objects of resolution 1x1 to image units. */
1645         for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
1646         {
1647                 glw::GLint texture = m_texture_ids[n_img];
1648                 glw::GLint value   = n_img + 1;
1649
1650                 gl.bindTexture(GL_TEXTURE_2D, texture);
1651                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1652
1653                 gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_R32I, 1 /*width*/, 1 /*height*/);
1654                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1655
1656                 gl.texSubImage2D(GL_TEXTURE_2D, 0 /*level*/, 0 /*xoffset*/, 0 /*yoffset*/, 1 /*width*/, 1 /*height*/,
1657                                                  GL_RED_INTEGER, GL_INT, &value);
1658                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
1659
1660                 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1661                 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
1662
1663                 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1664                 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
1665
1666                 gl.bindImageTexture(n_img, texture, 0 /*level*/, GL_FALSE /*is layered?*/, 0 /*layer*/, GL_READ_ONLY, GL_R32I);
1667                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed.");
1668         }
1669
1670         /* Configure VAO. */
1671         gl.genVertexArrays(1, &m_vao_id);
1672         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1673
1674         gl.bindVertexArray(m_vao_id);
1675         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1676
1677         /* Create a Buffer Object for Transform Feedback's outputs. */
1678         gl.genBuffers(1, &m_tfbo_id);
1679         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1680
1681         gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
1682         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1683
1684         gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, NULL, GL_STATIC_READ);
1685         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1686
1687         /* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
1688         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tfbo_id);
1689         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
1690
1691         /* Disable rasterization and make a draw call. After that, turn on rasterization. */
1692         gl.enable(GL_RASTERIZER_DISCARD);
1693         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
1694
1695         gl.beginTransformFeedback(GL_POINTS);
1696         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
1697
1698         gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
1699         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
1700
1701         gl.endTransformFeedback();
1702         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
1703
1704         gl.disable(GL_RASTERIZER_DISCARD);
1705         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
1706
1707         /* Retrieve value from Transform Feedback. */
1708         counter = 0;
1709         ptr             = (glw::GLfloat*)gl.mapBufferRange(
1710                 GL_ARRAY_BUFFER, 0, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
1711
1712         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
1713
1714         counter = int(ptr[0] + 0.5f);
1715
1716         gl.unmapBuffer(GL_ARRAY_BUFFER);
1717         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
1718
1719         /* Calculate expected value. */
1720         expectedValue = m_gl_max_geometry_image_uniforms_ext_value * (m_gl_max_geometry_image_uniforms_ext_value + 1) / 2;
1721
1722         if (counter != expectedValue)
1723         {
1724                 result = false;
1725         }
1726
1727 end:
1728         if (result)
1729         {
1730                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1731         }
1732         else
1733         {
1734                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1735         }
1736
1737         return STOP;
1738 }
1739
1740 /** Constructor
1741  *
1742  * @param context       Test context
1743  * @param extParams     Not used.
1744  * @param name          Test case's name
1745  * @param description   Test case's description
1746  **/
1747 GeometryShaderMaxShaderStorageBlocksTest::GeometryShaderMaxShaderStorageBlocksTest(Context&                             context,
1748                                                                                                                                                                    const ExtParameters& extParams,
1749                                                                                                                                                                    const char*                  name,
1750                                                                                                                                                                    const char*                  description)
1751         : TestCaseBase(context, extParams, name, description)
1752         , m_fs_id(0)
1753         , m_gl_max_geometry_shader_storage_blocks_ext_value(0)
1754         , m_gs_id(0)
1755         , m_po_id(0)
1756         , m_ssbo_id(0)
1757         , m_tfbo_id(0)
1758         , m_vao_id(0)
1759         , m_vs_id(0)
1760 {
1761 }
1762
1763 /** Deinitializes GLES objects created during the test. */
1764 void GeometryShaderMaxShaderStorageBlocksTest::deinit()
1765 {
1766         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1767
1768         if (m_fs_id != 0)
1769         {
1770                 gl.deleteShader(m_fs_id);
1771                 m_fs_id = 0;
1772         }
1773
1774         if (m_gs_id != 0)
1775         {
1776                 gl.deleteShader(m_gs_id);
1777                 m_gs_id = 0;
1778         }
1779
1780         if (m_po_id != 0)
1781         {
1782                 gl.deleteProgram(m_po_id);
1783                 m_po_id = 0;
1784         }
1785
1786         if (m_ssbo_id != 0)
1787         {
1788                 gl.deleteBuffers(1, &m_ssbo_id);
1789                 m_ssbo_id = 0;
1790         }
1791
1792         if (m_tfbo_id != 0)
1793         {
1794                 gl.deleteBuffers(1, &m_tfbo_id);
1795                 m_tfbo_id = 0;
1796         }
1797
1798         if (m_vao_id != 0)
1799         {
1800                 gl.deleteVertexArrays(1, &m_vao_id);
1801                 m_vao_id = 0;
1802         }
1803
1804         if (m_vs_id != 0)
1805         {
1806                 gl.deleteShader(m_vs_id);
1807                 m_vs_id = 0;
1808         }
1809
1810         /* Release base class */
1811         TestCaseBase::deinit();
1812 }
1813
1814 /* Retrieves test-specific geometry shader source code.
1815  *
1816  * @return Requested string.
1817  */
1818 std::string GeometryShaderMaxShaderStorageBlocksTest::getGSCode()
1819 {
1820         std::stringstream code_sstream;
1821
1822         /* Form the GS */
1823         code_sstream << "${VERSION}\n"
1824                                         "${GEOMETRY_SHADER_REQUIRE}\n"
1825                                         "\n"
1826                                         "layout (points)                   in;\n"
1827                                         "layout (points, max_vertices = 1) out;\n"
1828                                         "\n"
1829                                         "int counter = 0;\n"
1830                                         "\n";
1831
1832         for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
1833         {
1834                 code_sstream << "layout(binding = " << n_ssb << ") buffer ssb" << n_ssb << " \n{\n"
1835                                          << "    int value;\n"
1836                                          << "} S_SSB" << n_ssb << ";\n\n";
1837         }
1838
1839         code_sstream << "\n"
1840                                         "void main()\n"
1841                                         "{\n";
1842
1843         for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
1844         {
1845                 code_sstream << "    counter += S_SSB" << n_ssb << ".value++;\n";
1846         }
1847
1848         code_sstream << "\n"
1849                                         "    gl_Position = vec4(float(counter), 0.0, 0.0, 1.0);\n"
1850                                         "    EmitVertex();\n"
1851                                         "}\n";
1852
1853         /* Form a specialized version of the GS source code */
1854         std::string gs_code                             = code_sstream.str();
1855         const char* gs_code_raw                 = gs_code.c_str();
1856         std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw);
1857
1858         return gs_code_specialized;
1859 }
1860
1861 /** Executes the test.
1862  *
1863  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1864  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1865  *  Note the function throws exception should an error occur!
1866  **/
1867 tcu::TestNode::IterateResult GeometryShaderMaxShaderStorageBlocksTest::iterate()
1868 {
1869         glw::GLint                 counter                                               = 0;
1870         glw::GLint                 expectedValue                                 = 0;
1871         const glw::GLchar* feedbackVaryings[]                    = { "gl_Position" };
1872         bool                       has_shader_compilation_failed = true;
1873         const glw::GLfloat initial_buffer_data[4]                = { 0.0f, 0.0f, 0.0f, 0.0f };
1874         glw::GLint                 int_alignment                                 = 0;
1875         const glw::GLint   int_size                                              = sizeof(glw::GLint);
1876         glw::GLint*                ptrSSBO_data                                  = DE_NULL;
1877         glw::GLfloat*     ptrTF_data                                     = DE_NULL;
1878         bool                       result                                                = true;
1879         glw::GLint                 ssbo_alignment                                = 0;
1880         glw::GLint*                ssbo_data                                     = DE_NULL;
1881         glw::GLint                 ssbo_data_size                                = 0;
1882
1883         std::string fs_code_specialized         = "";
1884         const char* fs_code_specialized_raw = DE_NULL;
1885         std::string gs_code_specialized         = "";
1886         const char* gs_code_specialized_raw = DE_NULL;
1887         std::string vs_code_specialized         = "";
1888         const char* vs_code_specialized_raw = DE_NULL;
1889
1890         /* This test should only run if EXT_geometry_shader is supported. */
1891         if (!m_is_geometry_shader_extension_supported)
1892         {
1893                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1894         }
1895
1896         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1897
1898         /* Retrieve GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname value */
1899         gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
1900                                    &m_gl_max_geometry_shader_storage_blocks_ext_value);
1901         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname");
1902
1903         /* Retrieve GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname value */
1904         glw::GLint m_gl_max_shader_storage_buffer_bindings_value = 0;
1905
1906         gl.getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &m_gl_max_shader_storage_buffer_bindings_value);
1907         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname");
1908
1909         /* Check if m_gl_max_shader_storage_blocks_value is less than or equal zero. */
1910         if (m_gl_max_geometry_shader_storage_blocks_ext_value <= 0)
1911         {
1912                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
1913                                                    << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
1914                                                    << "]"
1915                                                           " is less than or equal zero. Shader Storage Blocks"
1916                                                           " in Geometry Shader are not supported."
1917                                                    << tcu::TestLog::EndMessage;
1918
1919                 if (m_gl_max_geometry_shader_storage_blocks_ext_value == 0)
1920                 {
1921                         throw tcu::NotSupportedError("GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT is 0");
1922                 }
1923                 else
1924                 {
1925                         result = false;
1926                         goto end;
1927                 }
1928         }
1929
1930         /* Check if m_gl_max_shader_storage_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
1931         if (m_gl_max_shader_storage_buffer_bindings_value < m_gl_max_geometry_shader_storage_blocks_ext_value)
1932         {
1933                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
1934                                                    << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
1935                                                    << "]"
1936                                                           " is greater than GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS query value "
1937                                                           "["
1938                                                    << m_gl_max_shader_storage_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
1939
1940                 result = false;
1941                 goto end;
1942         }
1943
1944         /* Create a program object. */
1945         m_po_id = gl.createProgram();
1946         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1947
1948         /* Create shader objects. */
1949         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1950         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1951         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1952
1953         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1954
1955         /* Configure which outputs should be captured by Transform Feedback. */
1956         gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
1957
1958         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
1959
1960         /* Try to link the test program object */
1961         fs_code_specialized             = specializeShader(1, &dummy_fs_code);
1962         fs_code_specialized_raw = fs_code_specialized.c_str();
1963
1964         gs_code_specialized             = getGSCode();
1965         gs_code_specialized_raw = gs_code_specialized.c_str();
1966
1967         vs_code_specialized             = specializeShader(1, &dummy_vs_code);
1968         vs_code_specialized_raw = vs_code_specialized.c_str();
1969
1970         if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,                              /* n_sh1_body_parts */
1971                                                                         &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1972                                                                         &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1973                                                                         &fs_code_specialized_raw, &has_shader_compilation_failed))
1974         {
1975                 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
1976
1977                 result = false;
1978                 goto end;
1979         }
1980
1981         /* Prepare data for Shader Storage Buffer Object. */
1982         gl.getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_alignment);
1983         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
1984
1985         int_alignment  = ssbo_alignment / int_size;
1986         ssbo_data_size = m_gl_max_geometry_shader_storage_blocks_ext_value * ssbo_alignment;
1987         ssbo_data         = new glw::GLint[ssbo_data_size];
1988
1989         if ((ssbo_alignment % int_size) != 0)
1990         {
1991                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT query value "
1992                                                                                                            "["
1993                                                    << ssbo_alignment << "]"
1994                                                                                                 "divide with remainder by the size of GLint "
1995                                                                                                 "["
1996                                                    << int_size << "]" << tcu::TestLog::EndMessage;
1997
1998                 result = false;
1999                 goto end;
2000         }
2001
2002         for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
2003         {
2004                 ssbo_data[i * int_alignment] = i + 1;
2005         }
2006
2007         /* Create Shader Storage Buffer Object. */
2008         gl.genBuffers(1, &m_ssbo_id);
2009         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2010
2011         gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo_id);
2012         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2013
2014         gl.bufferData(GL_SHADER_STORAGE_BUFFER, ssbo_data_size, ssbo_data, GL_DYNAMIC_COPY);
2015         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2016
2017         /* Free unused memory. */
2018         delete[] ssbo_data;
2019         ssbo_data = NULL;
2020
2021         /* Bind specific m_ssbo_id buffer region to a specific Shader Storage Buffer binding point. */
2022         for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
2023         {
2024                 glw::GLuint offset = n_ssb * ssbo_alignment;
2025
2026                 gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, n_ssb /*binding index*/, m_ssbo_id, offset, int_size);
2027                 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2028         }
2029
2030         /* Configure VAO. */
2031         gl.genVertexArrays(1, &m_vao_id);
2032         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2033
2034         gl.bindVertexArray(m_vao_id);
2035         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2036
2037         /* Create a Buffer Object for Transform Feedback's outputs. */
2038         gl.genBuffers(1, &m_tfbo_id);
2039         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2040
2041         gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
2042         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2043
2044         gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, initial_buffer_data,
2045                                   GL_STATIC_READ);
2046         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2047
2048         /* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
2049         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
2050         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
2051
2052         /* Use program. */
2053         gl.useProgram(m_po_id);
2054         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2055
2056         /* Disable rasterization and make a draw call. After that, turn on rasterization. */
2057         gl.enable(GL_RASTERIZER_DISCARD);
2058         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
2059
2060         gl.beginTransformFeedback(GL_POINTS);
2061         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2062
2063         gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
2064         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2065
2066         gl.endTransformFeedback();
2067         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
2068
2069         gl.disable(GL_RASTERIZER_DISCARD);
2070         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
2071
2072         /* Retrieve value from Transform Feedback. */
2073         ptrTF_data = (glw::GLfloat*)gl.mapBufferRange(
2074                 GL_ARRAY_BUFFER, 0 /*offset*/, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
2075         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2076
2077         counter = int(ptrTF_data[0] + 0.5f);
2078
2079         gl.unmapBuffer(GL_ARRAY_BUFFER);
2080         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2081
2082         ptrTF_data = NULL;
2083
2084         /* Retrieve values from Shader Storage Buffer Object. */
2085         ptrSSBO_data =
2086                 (glw::GLint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /*offset*/, ssbo_data_size, GL_MAP_READ_BIT);
2087         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2088
2089         for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
2090         {
2091                 if (ptrSSBO_data[i * int_alignment] != i + 2)
2092                 {
2093                         result = false;
2094
2095                         m_testCtx.getLog() << tcu::TestLog::Message << "Value read from Shader Storage Buffer "
2096                                                                                                                    "["
2097                                                            << ptrSSBO_data[i * int_alignment] << "] "
2098                                                                                                                                          "at index "
2099                                                                                                                                          "["
2100                                                            << i * int_alignment << "]"
2101                                                                                                            "is not equal to expected value "
2102                                                                                                            "["
2103                                                            << i + 2 << "]" << tcu::TestLog::EndMessage;
2104
2105                         break;
2106                 }
2107         }
2108
2109         gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
2110         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2111
2112         ptrSSBO_data = NULL;
2113
2114         /* Calculate expected value. */
2115         expectedValue =
2116                 m_gl_max_geometry_shader_storage_blocks_ext_value * (m_gl_max_geometry_shader_storage_blocks_ext_value + 1) / 2;
2117
2118         if (counter != expectedValue)
2119         {
2120                 result = false;
2121         }
2122
2123 end:
2124         if (result)
2125         {
2126                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2127         }
2128         else
2129         {
2130                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2131         }
2132
2133         return STOP;
2134 }
2135
2136 /** Constructor
2137  *
2138  * @param context       Test context
2139  * @param extParams     Not used.
2140  * @param name          Test case's name
2141  * @param description   Test case's description
2142  **/
2143 GeometryShaderMaxAtomicCountersTest::GeometryShaderMaxAtomicCountersTest(Context&                         context,
2144                                                                                                                                                  const ExtParameters& extParams,
2145                                                                                                                                                  const char* name, const char* description)
2146         : TestCaseBase(context, extParams, name, description)
2147         , m_acbo_id(0)
2148         , m_fs_id(0)
2149         , m_gl_max_geometry_atomic_counters_ext_value(0)
2150         , m_gs_id(0)
2151         , m_po_id(0)
2152         , m_vao_id(0)
2153         , m_vs_id(0)
2154 {
2155 }
2156
2157 /** Deinitializes GLES objects created during the test. */
2158 void GeometryShaderMaxAtomicCountersTest::deinit()
2159 {
2160         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2161
2162         if (m_acbo_id != 0)
2163         {
2164                 gl.deleteBuffers(1, &m_acbo_id);
2165                 m_acbo_id = 0;
2166         }
2167
2168         if (m_fs_id != 0)
2169         {
2170                 gl.deleteShader(m_fs_id);
2171                 m_fs_id = 0;
2172         }
2173
2174         if (m_gs_id != 0)
2175         {
2176                 gl.deleteShader(m_gs_id);
2177                 m_gs_id = 0;
2178         }
2179
2180         if (m_po_id != 0)
2181         {
2182                 gl.deleteProgram(m_po_id);
2183                 m_po_id = 0;
2184         }
2185
2186         if (m_vao_id != 0)
2187         {
2188                 gl.deleteVertexArrays(1, &m_vao_id);
2189                 m_vao_id = 0;
2190         }
2191
2192         if (m_vs_id != 0)
2193         {
2194                 gl.deleteShader(m_vs_id);
2195                 m_vs_id = 0;
2196         }
2197
2198         /* Release base class */
2199         TestCaseBase::deinit();
2200 }
2201
2202 /* Retrieves test-specific geometry shader source code.
2203  *
2204  * @return Requested string.
2205  */
2206 std::string GeometryShaderMaxAtomicCountersTest::getGSCode()
2207 {
2208         std::stringstream code_sstream;
2209
2210         /* Form the GS */
2211         code_sstream << "${VERSION}\n"
2212                                         "${GEOMETRY_SHADER_REQUIRE}\n"
2213                                         "\n"
2214                                         "layout (points)                   in;\n"
2215                                         "layout (points, max_vertices = 1) out;\n"
2216                                         "\n"
2217                                         "uniform int n_loop_iterations;\n"
2218                                         "flat in int vertex_id[];\n"
2219                                         "\n";
2220
2221         code_sstream << "layout(binding = 0) uniform atomic_uint acs[" << m_gl_max_geometry_atomic_counters_ext_value
2222                                  << "];\n"
2223                                  << "\n"
2224                                         "void main()\n"
2225                                         "{\n"
2226                                         "    for (int counter_id = 1;\n"
2227                                         "             counter_id <= n_loop_iterations;\n"
2228                                         "           ++counter_id)\n"
2229                                         "    {\n"
2230                                         "        if ((vertex_id[0] % counter_id) == 0)\n"
2231                                         "        {\n"
2232                                         "            atomicCounterIncrement(acs[counter_id - 1]);\n"
2233                                         "        }\n"
2234                                         "    }\n"
2235                                         "\n"
2236                                         "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2237                                         "    EmitVertex();\n"
2238                                         "}\n";
2239
2240         /* Form a specialized version of the GS source code */
2241         std::string gs_code                             = code_sstream.str();
2242         const char* gs_code_raw                 = gs_code.c_str();
2243         std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
2244
2245         return gs_code_specialized;
2246 }
2247
2248 /** Executes the test.
2249  *
2250  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2251  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2252  *  Note the function throws exception should an error occur!
2253  **/
2254 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCountersTest::iterate()
2255 {
2256         /* Define Vertex Shader's code for the purpose of this test. */
2257         const char* vs_code = "${VERSION}\n"
2258                                                   "\n"
2259                                                   "flat out int vertex_id;\n"
2260                                                   "\n"
2261                                                   "void main()\n"
2262                                                   "{\n"
2263                                                   "    vertex_id    = gl_VertexID;\n"
2264                                                   "    gl_Position  = vec4(1.0, 0.0, 0.0, 1.0);\n"
2265                                                   "}\n";
2266
2267         bool                       has_shader_compilation_failed          = true;
2268         glw::GLuint*       initial_ac_data                                        = DE_NULL;
2269         const unsigned int n_draw_call_vertices                           = 4;
2270         glw::GLint                 n_loop_iterations_uniform_location = -1;
2271         glw::GLuint*       ptrACBO_data                                           = DE_NULL;
2272         bool                       result                                                         = true;
2273
2274         std::string fs_code_specialized         = "";
2275         const char* fs_code_specialized_raw = DE_NULL;
2276         std::string gs_code_specialized         = "";
2277         const char* gs_code_specialized_raw = DE_NULL;
2278         std::string vs_code_specialized         = "";
2279         const char* vs_code_specialized_raw = DE_NULL;
2280
2281         /* This test should only run if EXT_geometry_shader is supported. */
2282         if (!m_is_geometry_shader_extension_supported)
2283         {
2284                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2285         }
2286
2287         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2288
2289         /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname value */
2290         gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTERS, &m_gl_max_geometry_atomic_counters_ext_value);
2291         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname");
2292
2293         /* Check if m_gl_max_atomic_counters_value is less than or equal zero. */
2294         if (m_gl_max_geometry_atomic_counters_ext_value <= 0)
2295         {
2296                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT query value "
2297                                                    << "[" << m_gl_max_geometry_atomic_counters_ext_value
2298                                                    << "]"
2299                                                           " is less than or equal to zero. Atomic Counters"
2300                                                           " in Geometry Shader are not supported."
2301                                                    << tcu::TestLog::EndMessage;
2302
2303                 if (m_gl_max_geometry_atomic_counters_ext_value == 0)
2304                 {
2305                         throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT is 0");
2306                 }
2307                 else
2308                 {
2309                         result = false;
2310                         goto end;
2311                 }
2312         }
2313
2314         /* Create a program object. */
2315         m_po_id = gl.createProgram();
2316         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2317
2318         /* Create shader objects. */
2319         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2320         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2321         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2322
2323         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2324
2325         /* Try to link the test program object */
2326         fs_code_specialized             = specializeShader(1, &dummy_fs_code);
2327         fs_code_specialized_raw = fs_code_specialized.c_str();
2328
2329         gs_code_specialized             = getGSCode();
2330         gs_code_specialized_raw = gs_code_specialized.c_str();
2331
2332         vs_code_specialized             = specializeShader(1, &vs_code);
2333         vs_code_specialized_raw = vs_code_specialized.c_str();
2334
2335         if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,                              /* n_sh1_body_parts */
2336                                                                         &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2337                                                                         &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2338                                                                         &fs_code_specialized_raw, &has_shader_compilation_failed))
2339         {
2340                 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
2341
2342                 result = false;
2343                 goto end;
2344         }
2345
2346         /* Create Atomic Counter Buffer Objects. */
2347         gl.genBuffers(1, &m_acbo_id);
2348         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2349
2350         /* Prepare initial data - zeroes - to fill the Atomic Counter Buffer Object. */
2351         initial_ac_data = new glw::GLuint[m_gl_max_geometry_atomic_counters_ext_value];
2352         memset(initial_ac_data, 0, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value);
2353
2354         gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_id);
2355         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2356
2357         gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value, NULL,
2358                                   GL_DYNAMIC_COPY);
2359         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2360
2361         gl.bufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2362                                          sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
2363                                          initial_ac_data /*initialize with zeroes*/);
2364         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
2365
2366         gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0 /*binding index*/, m_acbo_id /*buffer*/);
2367         GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2368
2369         /* Configure VAO. */
2370         gl.genVertexArrays(1, &m_vao_id);
2371         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2372
2373         gl.bindVertexArray(m_vao_id);
2374         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2375
2376         /* Use program. */
2377         n_loop_iterations_uniform_location = gl.getUniformLocation(m_po_id, "n_loop_iterations");
2378
2379         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
2380         if (n_loop_iterations_uniform_location == -1)
2381         {
2382                 TCU_FAIL("n_loop_iterations uniform is considered inactive");
2383         }
2384         else
2385         {
2386                 gl.useProgram(m_po_id);
2387                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2388
2389                 gl.uniform1i(n_loop_iterations_uniform_location, m_gl_max_geometry_atomic_counters_ext_value);
2390                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
2391         }
2392
2393         /* Issue the draw call */
2394         gl.drawArrays(GL_POINTS, 0, n_draw_call_vertices);
2395         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2396
2397         /* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
2398         ptrACBO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2399                                                                                                    sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
2400                                                                                                    GL_MAP_READ_BIT);
2401         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2402
2403         for (glw::GLint n_ac = 0; n_ac < m_gl_max_geometry_atomic_counters_ext_value; ++n_ac)
2404         {
2405                 unsigned int expected_value = 0;
2406
2407                 for (unsigned int n_draw_call_vertex = 0; n_draw_call_vertex < n_draw_call_vertices; ++n_draw_call_vertex)
2408                 {
2409                         if ((n_draw_call_vertex % (n_ac + 1)) == 0)
2410                         {
2411                                 ++expected_value;
2412                         }
2413                 }
2414
2415                 if (ptrACBO_data[n_ac] != expected_value)
2416                 {
2417                         result = false;
2418                         break;
2419                 }
2420         }
2421
2422         gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2423         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2424
2425         ptrACBO_data = NULL;
2426
2427 end:
2428         if (result)
2429         {
2430                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2431         }
2432         else
2433         {
2434                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2435         }
2436
2437         return STOP;
2438 }
2439
2440 /** Constructor
2441  *
2442  * @param context       Test context
2443  * @param extParams     Not used.
2444  * @param name          Test case's name
2445  * @param description   Test case's description
2446  **/
2447 GeometryShaderMaxAtomicCounterBuffersTest::GeometryShaderMaxAtomicCounterBuffersTest(Context&                     context,
2448                                                                                                                                                                          const ExtParameters& extParams,
2449                                                                                                                                                                          const char*              name,
2450                                                                                                                                                                          const char*              description)
2451         : TestCaseBase(context, extParams, name, description)
2452         , m_acbo_ids(NULL)
2453         , m_fs_id(0)
2454         , m_gl_max_atomic_counter_buffer_bindings_value(0)
2455         , m_gl_max_geometry_atomic_counter_buffers_ext_value(0)
2456         , m_gs_id(0)
2457         , m_po_id(0)
2458         , m_vao_id(0)
2459         , m_vs_id(0)
2460 {
2461 }
2462
2463 /** Deinitializes GLES objects created during the test. */
2464 void GeometryShaderMaxAtomicCounterBuffersTest::deinit()
2465 {
2466         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2467
2468         if (m_acbo_ids != NULL)
2469         {
2470                 if (m_gl_max_geometry_atomic_counter_buffers_ext_value > 0)
2471                 {
2472                         gl.deleteBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
2473
2474                         delete[] m_acbo_ids;
2475                         m_acbo_ids = NULL;
2476                 }
2477         }
2478
2479         if (m_fs_id != 0)
2480         {
2481                 gl.deleteShader(m_fs_id);
2482                 m_fs_id = 0;
2483         }
2484
2485         if (m_gs_id != 0)
2486         {
2487                 gl.deleteShader(m_gs_id);
2488                 m_gs_id = 0;
2489         }
2490
2491         if (m_po_id != 0)
2492         {
2493                 gl.deleteProgram(m_po_id);
2494                 m_po_id = 0;
2495         }
2496
2497         if (m_vao_id != 0)
2498         {
2499                 gl.deleteVertexArrays(1, &m_vao_id);
2500                 m_vao_id = 0;
2501         }
2502
2503         if (m_vs_id != 0)
2504         {
2505                 gl.deleteShader(m_vs_id);
2506                 m_vs_id = 0;
2507         }
2508
2509         /* Release base class */
2510         TestCaseBase::deinit();
2511 }
2512
2513 /* Retrieves test-specific geometry shader source code.
2514  *
2515  * @return Requested string.
2516  */
2517 std::string GeometryShaderMaxAtomicCounterBuffersTest::getGSCode()
2518 {
2519         std::stringstream code_sstream;
2520
2521         /* Form the GS */
2522         code_sstream << "${VERSION}\n"
2523                                         "${GEOMETRY_SHADER_REQUIRE}\n"
2524                                         "\n"
2525                                         "layout (points)                   in;\n"
2526                                         "layout (points, max_vertices = 1) out;\n"
2527                                         "\n"
2528                                         "flat in int vertex_id[];\n"
2529                                         "\n";
2530
2531         for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
2532         {
2533                 code_sstream << "layout(binding = " << n_ac << ") uniform atomic_uint ac" << n_ac << ";\n";
2534         }
2535
2536         code_sstream << "\n"
2537                                         "void main()\n"
2538                                         "{\n"
2539                                         "    for(int counter_id = 1; counter_id <= "
2540                                  << m_gl_max_geometry_atomic_counter_buffers_ext_value
2541                                  << "; ++counter_id)\n"
2542                                         "    {\n"
2543                                         "        if((vertex_id[0] % counter_id) == 0)\n"
2544                                         "        {\n";
2545
2546         for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
2547         {
2548                 code_sstream << "            atomicCounterIncrement(ac" << n_ac << ");\n";
2549         }
2550
2551         code_sstream << "        }\n"
2552                                         "    }\n";
2553
2554         code_sstream << "\n"
2555                                         "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2556                                         "    EmitVertex();\n"
2557                                         "}\n";
2558
2559         /* Form a specialized version of the GS source code */
2560         std::string gs_code                             = code_sstream.str();
2561         const char* gs_code_raw                 = gs_code.c_str();
2562         std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
2563
2564         return gs_code_specialized;
2565 }
2566
2567 /** Executes the test.
2568  *
2569  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2570  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2571  *  Note the function throws exception should an error occur!
2572  **/
2573 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCounterBuffersTest::iterate()
2574 {
2575         /* Define Vertex Shader's code for the purpose of this test. */
2576         const char* vs_code = "${VERSION}\n"
2577                                                   "\n"
2578                                                   "flat out int vertex_id;\n"
2579                                                   "\n"
2580                                                   "void main()\n"
2581                                                   "{\n"
2582                                                   "    vertex_id    = gl_VertexID;\n"
2583                                                   "    gl_Position  = vec4(1.0, 0.0, 0.0, 1.0);\n"
2584                                                   "}\n";
2585
2586         unsigned int              expected_value                                = 0;
2587         const glw::Functions& gl                                                        = m_context.getRenderContext().getFunctions();
2588         bool                              has_shader_compilation_failed = true;
2589         const glw::GLuint        initial_ac_data                                = 0;
2590         const glw::GLuint        number_of_indices                              = 128 * m_gl_max_geometry_atomic_counter_buffers_ext_value;
2591         bool                              result                                                = true;
2592
2593         std::string fs_code_specialized         = "";
2594         const char* fs_code_specialized_raw = DE_NULL;
2595         std::string gs_code_specialized         = "";
2596         const char* gs_code_specialized_raw = DE_NULL;
2597         std::string vs_code_specialized         = "";
2598         const char* vs_code_specialized_raw = DE_NULL;
2599
2600         /* This test should only run if EXT_geometry_shader is supported. */
2601         if (!m_is_geometry_shader_extension_supported)
2602         {
2603                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2604         }
2605
2606         /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname value */
2607         gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS,
2608                                    &m_gl_max_geometry_atomic_counter_buffers_ext_value);
2609         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname");
2610
2611         /* Retrieve GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname value */
2612         gl.getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_gl_max_atomic_counter_buffer_bindings_value);
2613         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname");
2614
2615         /* Check if m_gl_max_geometry_atomic_counter_buffers_ext_value is less than or equal zero. */
2616         if (m_gl_max_geometry_atomic_counter_buffers_ext_value <= 0)
2617         {
2618                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
2619                                                    << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
2620                                                    << "]"
2621                                                           " is less than or equal to zero. Atomic Counter Buffers"
2622                                                           " are not supported."
2623                                                    << tcu::TestLog::EndMessage;
2624
2625                 if (m_gl_max_geometry_atomic_counter_buffers_ext_value == 0)
2626                 {
2627                         throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT is 0");
2628                 }
2629                 else
2630                 {
2631                         result = false;
2632                         goto end;
2633                 }
2634         }
2635
2636         /* Check if m_gl_max_atomic_counter_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
2637         if (m_gl_max_atomic_counter_buffer_bindings_value < m_gl_max_geometry_atomic_counter_buffers_ext_value)
2638         {
2639                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
2640                                                    << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
2641                                                    << "]"
2642                                                           " is greater than GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS query value "
2643                                                           "["
2644                                                    << m_gl_max_atomic_counter_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
2645
2646                 result = false;
2647                 goto end;
2648         }
2649
2650         /* Create a program object. */
2651         m_po_id = gl.createProgram();
2652         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2653
2654         /* Create shader objects. */
2655         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2656         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2657         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2658
2659         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2660
2661         /* Try to link the test program object */
2662         fs_code_specialized             = specializeShader(1, &dummy_fs_code);
2663         fs_code_specialized_raw = fs_code_specialized.c_str();
2664
2665         gs_code_specialized             = getGSCode();
2666         gs_code_specialized_raw = gs_code_specialized.c_str();
2667
2668         vs_code_specialized             = specializeShader(1, &vs_code);
2669         vs_code_specialized_raw = vs_code_specialized.c_str();
2670
2671         if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,                              /* n_sh1_body_parts */
2672                                                                         &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2673                                                                         &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2674                                                                         &fs_code_specialized_raw, &has_shader_compilation_failed))
2675         {
2676                 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
2677
2678                 result = false;
2679                 goto end;
2680         }
2681
2682         /* Create Atomic Counter Buffer Objects. */
2683         m_acbo_ids = new glw::GLuint[m_gl_max_geometry_atomic_counter_buffers_ext_value];
2684
2685         gl.genBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
2686         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2687
2688         for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
2689         {
2690                 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
2691                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2692
2693                 gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint), &initial_ac_data /*initialize with zeroes*/,
2694                                           GL_DYNAMIC_COPY);
2695                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2696
2697                 gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, n_acb /*binding index*/, m_acbo_ids[n_acb] /*buffer*/);
2698                 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2699         }
2700
2701         /* Configure VAO. */
2702         gl.genVertexArrays(1, &m_vao_id);
2703         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2704
2705         gl.bindVertexArray(m_vao_id);
2706         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2707
2708         /* Use program. */
2709         gl.useProgram(m_po_id);
2710         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2711
2712         gl.drawArrays(GL_POINTS, 0 /*starting index*/, number_of_indices);
2713         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2714
2715         /* Calculate expected value. */
2716         /* For each point being processed by Geometry Shader. */
2717         for (glw::GLuint vertex_id = 0; vertex_id < number_of_indices; ++vertex_id)
2718         {
2719                 /* And for each atomic counter ID. */
2720                 for (int atomic_counter_id = 1; atomic_counter_id <= m_gl_max_geometry_atomic_counter_buffers_ext_value;
2721                          ++atomic_counter_id)
2722                 {
2723                         /* Check if (vertex_id % atomic_counter_id) == 0. If it is true, increment expected_value. */
2724                         if (vertex_id % atomic_counter_id == 0)
2725                         {
2726                                 ++expected_value;
2727                         }
2728                 }
2729         }
2730
2731         /* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
2732         for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
2733         {
2734                 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
2735                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2736
2737                 glw::GLuint* ptrABO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2738                                                                                                                                    sizeof(glw::GLuint) /*length*/, GL_MAP_READ_BIT);
2739                 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2740
2741                 if (ptrABO_data[0] != expected_value)
2742                 {
2743                         result = false;
2744                         break;
2745                 }
2746
2747                 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2748                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2749
2750                 ptrABO_data = NULL;
2751         }
2752
2753 end:
2754         if (result)
2755         {
2756                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2757         }
2758         else
2759         {
2760                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2761         }
2762
2763         return STOP;
2764 }
2765
2766 /** Constructor
2767  *
2768  * @param context       Test context
2769  * @param extParams     Not used.
2770  * @param name          Test case's name
2771  * @param description   Test case's description
2772  **/
2773 GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::
2774         GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context& context, const ExtParameters& extParams,
2775                                                                                                                                  const char* name, const char* description)
2776         : TestCaseBase(context, extParams, name, description)
2777         , m_fs_id(0)
2778         , m_fs_po_id(0)
2779         , m_gs_id(0)
2780         , m_gs_po_id(0)
2781         , m_ppo_id(0)
2782         , m_vao_id(0)
2783 {
2784 }
2785
2786 /** Deinitializes GLES objects created during the test. */
2787 void GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::deinit()
2788 {
2789         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2790
2791         if (m_fs_id != 0)
2792         {
2793                 gl.deleteShader(m_fs_id);
2794                 m_fs_id = 0;
2795         }
2796
2797         if (m_fs_po_id != 0)
2798         {
2799                 gl.deleteProgram(m_fs_po_id);
2800                 m_fs_po_id = 0;
2801         }
2802
2803         if (m_gs_id != 0)
2804         {
2805                 gl.deleteShader(m_gs_id);
2806                 m_gs_id = 0;
2807         }
2808
2809         if (m_gs_po_id != 0)
2810         {
2811                 gl.deleteProgram(m_gs_po_id);
2812                 m_gs_po_id = 0;
2813         }
2814
2815         if (m_ppo_id != 0)
2816         {
2817                 gl.deleteProgramPipelines(1, &m_ppo_id);
2818                 m_ppo_id = 0;
2819         }
2820
2821         if (m_vao_id != 0)
2822         {
2823                 gl.deleteVertexArrays(1, &m_vao_id);
2824                 m_vao_id = 0;
2825         }
2826
2827         /* Release base class */
2828         TestCaseBase::deinit();
2829 }
2830
2831 /** Executes the test.
2832  *
2833  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2834  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2835  *  Note the function throws exception should an error occur!
2836  **/
2837 tcu::TestNode::IterateResult GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::iterate()
2838 {
2839         bool            has_shader_compilation_failed = true;
2840         bool            result                                            = true;
2841         glw::GLenum error                                                 = GL_NO_ERROR;
2842
2843         /* This test should only run if EXT_geometry_shader is supported. */
2844         if (!m_is_geometry_shader_extension_supported)
2845         {
2846                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2847         }
2848
2849         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2850
2851         /* Create separable program objects. */
2852         m_fs_po_id = gl.createProgram();
2853         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2854
2855         gl.programParameteri(m_fs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2856         GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
2857
2858         m_gs_po_id = gl.createProgram();
2859         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2860
2861         gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2862         GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
2863
2864         /* Create shader objects. */
2865         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2866         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2867
2868         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2869
2870         /* Try to link the test program object */
2871         std::string fs_code_specialized         = specializeShader(1, &dummy_fs_code);
2872         const char* fs_code_specialized_raw = fs_code_specialized.c_str();
2873         std::string gs_code_specialized         = specializeShader(1, &dummy_gs_code);
2874         const char* gs_code_specialized_raw = gs_code_specialized.c_str();
2875
2876         if (!TestCaseBase::buildProgram(m_fs_po_id, m_fs_id, 1,                 /* n_sh1_body_parts */
2877                                                                         &fs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
2878                                                                         NULL, 0, 0,                                             /* n_sh3_body_parts */
2879                                                                         NULL, &has_shader_compilation_failed))
2880         {
2881                 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment Shader Program object linking failed."
2882                                                    << tcu::TestLog::EndMessage;
2883
2884                 result = false;
2885                 goto end;
2886         }
2887
2888         if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1,                 /* n_sh1_body_parts */
2889                                                                         &gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
2890                                                                         NULL, 0, 0,                                             /* n_sh3_body_parts */
2891                                                                         NULL, &has_shader_compilation_failed))
2892         {
2893                 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
2894                                                    << tcu::TestLog::EndMessage;
2895
2896                 result = false;
2897                 goto end;
2898         }
2899
2900         /* Configure Pipeline Object. */
2901         gl.genProgramPipelines(1, &m_ppo_id);
2902         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
2903
2904         gl.useProgramStages(m_ppo_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
2905         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
2906
2907         gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
2908         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
2909
2910         /* Configure VAO. */
2911         gl.genVertexArrays(1, &m_vao_id);
2912         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2913
2914         gl.bindVertexArray(m_vao_id);
2915         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2916
2917         /* Use Program Pipeline Object. */
2918         gl.bindProgramPipeline(m_ppo_id);
2919         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
2920
2921         gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
2922
2923         error = gl.getError();
2924
2925         /* Check if correct error was generated. */
2926         if (GL_INVALID_OPERATION != error)
2927         {
2928                 result = false;
2929
2930                 m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
2931                                                    << tcu::TestLog::EndMessage;
2932         }
2933
2934 end:
2935         if (result)
2936         {
2937                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2938         }
2939         else
2940         {
2941                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2942         }
2943
2944         return STOP;
2945 }
2946
2947 /** Constructor
2948  *
2949  * @param context       Test context
2950  * @param extParams     Not used.
2951  * @param name          Test case's name
2952  * @param description   Test case's description
2953  **/
2954 GeometryShaderIncompatibleDrawCallModeTest::GeometryShaderIncompatibleDrawCallModeTest(Context&                         context,
2955                                                                                                                                                                            const ExtParameters& extParams,
2956                                                                                                                                                                            const char*                  name,
2957                                                                                                                                                                            const char*                  description)
2958         : TestCaseBase(context, extParams, name, description)
2959         , m_fs_id(0)
2960         , m_gs_ids(NULL)
2961         , m_number_of_gs(5 /*taken from test spec*/)
2962         , m_po_ids(NULL)
2963 {
2964         m_vao_id = 0;
2965         m_vs_id  = 0;
2966 }
2967
2968 /** Deinitializes GLES objects created during the test. */
2969 void GeometryShaderIncompatibleDrawCallModeTest::deinit()
2970 {
2971         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2972
2973         if (m_fs_id != 0)
2974         {
2975                 gl.deleteShader(m_fs_id);
2976                 m_fs_id = 0;
2977         }
2978
2979         if (m_gs_ids != 0)
2980         {
2981                 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2982                 {
2983                         gl.deleteShader(m_gs_ids[i]);
2984                         m_gs_ids[i] = 0;
2985                 }
2986
2987                 delete[] m_gs_ids;
2988                 m_gs_ids = NULL;
2989         }
2990
2991         if (m_po_ids != 0)
2992         {
2993                 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2994                 {
2995                         gl.deleteProgram(m_po_ids[i]);
2996                         m_po_ids[i] = 0;
2997                 }
2998
2999                 delete[] m_po_ids;
3000                 m_po_ids = NULL;
3001         }
3002
3003         if (m_vao_id != 0)
3004         {
3005                 gl.deleteVertexArrays(1, &m_vao_id);
3006                 m_vao_id = 0;
3007         }
3008
3009         if (m_vs_id != 0)
3010         {
3011                 gl.deleteShader(m_vs_id);
3012                 m_vs_id = 0;
3013         }
3014
3015         /* Release base class */
3016         TestCaseBase::deinit();
3017 }
3018
3019 /** Executes the test.
3020  *
3021  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3022  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3023  *  Note the function throws exception should an error occur!
3024  **/
3025 tcu::TestNode::IterateResult GeometryShaderIncompatibleDrawCallModeTest::iterate()
3026 {
3027         /* Define 5 Geometry Shaders for purpose of this test. */
3028         const char* gs_code_points = "${VERSION}\n"
3029                                                                  "${GEOMETRY_SHADER_REQUIRE}\n"
3030                                                                  "\n"
3031                                                                  "layout (points)                   in;\n"
3032                                                                  "layout (points, max_vertices = 1) out;\n"
3033                                                                  "\n"
3034                                                                  "${IN_PER_VERTEX_DECL_ARRAY}"
3035                                                                  "\n"
3036                                                                  "void main()\n"
3037                                                                  "{\n"
3038                                                                  "    gl_Position = gl_in[0].gl_Position;\n"
3039                                                                  "    EmitVertex();\n"
3040                                                                  "}\n";
3041
3042         const char* gs_code_lines = "${VERSION}\n"
3043                                                                 "${GEOMETRY_SHADER_REQUIRE}\n"
3044                                                                 "\n"
3045                                                                 "layout (lines)                    in;\n"
3046                                                                 "layout (points, max_vertices = 1) out;\n"
3047                                                                 "\n"
3048                                                                 "${IN_PER_VERTEX_DECL_ARRAY}"
3049                                                                 "\n"
3050                                                                 "void main()\n"
3051                                                                 "{\n"
3052                                                                 "    gl_Position = gl_in[0].gl_Position;\n"
3053                                                                 "    EmitVertex();\n"
3054                                                                 "}\n";
3055
3056         const char* gs_code_lines_adjacency = "${VERSION}\n"
3057                                                                                   "${GEOMETRY_SHADER_REQUIRE}\n"
3058                                                                                   "\n"
3059                                                                                   "layout (lines_adjacency)          in;\n"
3060                                                                                   "layout (points, max_vertices = 1) out;\n"
3061                                                                                   "\n"
3062                                                                                   "${IN_PER_VERTEX_DECL_ARRAY}"
3063                                                                                   "\n"
3064                                                                                   "void main()\n"
3065                                                                                   "{\n"
3066                                                                                   "    gl_Position = gl_in[0].gl_Position;\n"
3067                                                                                   "    EmitVertex();\n"
3068                                                                                   "}\n";
3069
3070         const char* gs_code_triangles = "${VERSION}\n"
3071                                                                         "${GEOMETRY_SHADER_REQUIRE}\n"
3072                                                                         "\n"
3073                                                                         "layout (triangles)                in;\n"
3074                                                                         "layout (points, max_vertices = 1) out;\n"
3075                                                                         "\n"
3076                                                                         "${IN_PER_VERTEX_DECL_ARRAY}"
3077                                                                         "\n"
3078                                                                         "void main()\n"
3079                                                                         "{\n"
3080                                                                         "    gl_Position = gl_in[0].gl_Position;\n"
3081                                                                         "    EmitVertex();\n"
3082                                                                         "}\n";
3083
3084         const char* gs_code_triangles_adjacency = "${VERSION}\n"
3085                                                                                           "${GEOMETRY_SHADER_REQUIRE}\n"
3086                                                                                           "\n"
3087                                                                                           "layout (triangles_adjacency)      in;\n"
3088                                                                                           "layout (points, max_vertices = 1) out;\n"
3089                                                                                           "\n"
3090                                                                                           "${IN_PER_VERTEX_DECL_ARRAY}"
3091                                                                                           "\n"
3092                                                                                           "void main()\n"
3093                                                                                           "{\n"
3094                                                                                           "    gl_Position = gl_in[0].gl_Position;\n"
3095                                                                                           "    EmitVertex();\n"
3096                                                                                           "}\n";
3097
3098         bool has_shader_compilation_failed = true;
3099         bool result                                                = true;
3100
3101         m_gs_ids = new glw::GLuint[m_number_of_gs];
3102         m_po_ids = new glw::GLuint[m_number_of_gs];
3103
3104         /* This test should only run if EXT_geometry_shader is supported. */
3105         if (!m_is_geometry_shader_extension_supported)
3106         {
3107                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3108         }
3109
3110         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3111
3112         /* Create program objects & geometry shader objects. */
3113         for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3114         {
3115                 m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
3116                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3117
3118                 m_po_ids[i] = gl.createProgram();
3119                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3120         }
3121
3122         /* Create shader object. */
3123         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3124         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3125         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3126
3127         /* Try to link the test program object */
3128         std::string fs_code_specialized         = specializeShader(1, &dummy_fs_code);
3129         const char* fs_code_specialized_raw = fs_code_specialized.c_str();
3130
3131         std::string gs_codes_specialized[] = { specializeShader(1, &gs_code_points), specializeShader(1, &gs_code_lines),
3132                                                                                    specializeShader(1, &gs_code_lines_adjacency),
3133                                                                                    specializeShader(1, &gs_code_triangles),
3134                                                                                    specializeShader(1, &gs_code_triangles_adjacency) };
3135
3136         const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str(),
3137                                                                                            gs_codes_specialized[2].c_str(), gs_codes_specialized[3].c_str(),
3138                                                                                            gs_codes_specialized[4].c_str() };
3139         std::string vs_code_specialized         = specializeShader(1, &dummy_vs_code);
3140         const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3141
3142         for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3143         {
3144                 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,                                  /* n_sh1_body_parts */
3145                                                                                 &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
3146                                                                                 &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
3147                                                                                 &vs_code_specialized_raw, &has_shader_compilation_failed))
3148                 {
3149                         m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
3150                                                            << "[" << i << "]." << tcu::TestLog::EndMessage;
3151
3152                         result = false;
3153                         break;
3154                 }
3155         }
3156
3157         if (result)
3158         {
3159                 /* Configure VAO. */
3160                 gl.genVertexArrays(1, &m_vao_id);
3161                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3162
3163                 gl.bindVertexArray(m_vao_id);
3164                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3165
3166                 for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
3167                 {
3168                         /* Use Program Object. */
3169                         gl.useProgram(m_po_ids[po]);
3170                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3171
3172                         if (po != 0)
3173                         {
3174                                 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
3175
3176                                 if (GL_INVALID_OPERATION != gl.getError())
3177                                 {
3178                                         result = false;
3179
3180                                         m_testCtx.getLog() << tcu::TestLog::Message
3181                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3182                                                                            << tcu::TestLog::EndMessage;
3183
3184                                         break;
3185                                 }
3186                         }
3187
3188                         if (po != 1)
3189                         {
3190                                 gl.drawArrays(GL_LINES, 0 /*starting index*/, 2 /*number of indices*/);
3191
3192                                 if (GL_INVALID_OPERATION != gl.getError())
3193                                 {
3194                                         result = false;
3195
3196                                         m_testCtx.getLog() << tcu::TestLog::Message
3197                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3198                                                                            << tcu::TestLog::EndMessage;
3199
3200                                         break;
3201                                 }
3202
3203                                 gl.drawArrays(GL_LINE_LOOP, 0 /*starting index*/, 2 /*number of indices*/);
3204
3205                                 if (GL_INVALID_OPERATION != gl.getError())
3206                                 {
3207                                         result = false;
3208
3209                                         m_testCtx.getLog() << tcu::TestLog::Message
3210                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3211                                                                            << tcu::TestLog::EndMessage;
3212
3213                                         break;
3214                                 }
3215
3216                                 gl.drawArrays(GL_LINE_STRIP, 0 /*starting index*/, 2 /*number of indices*/);
3217
3218                                 if (GL_INVALID_OPERATION != gl.getError())
3219                                 {
3220                                         result = false;
3221
3222                                         m_testCtx.getLog() << tcu::TestLog::Message
3223                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3224                                                                            << tcu::TestLog::EndMessage;
3225
3226                                         break;
3227                                 }
3228                         }
3229
3230                         if (po != 2)
3231                         {
3232                                 gl.drawArrays(GL_LINES_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
3233
3234                                 if (GL_INVALID_OPERATION != gl.getError())
3235                                 {
3236                                         result = false;
3237
3238                                         m_testCtx.getLog() << tcu::TestLog::Message
3239                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3240                                                                            << tcu::TestLog::EndMessage;
3241
3242                                         break;
3243                                 }
3244
3245                                 gl.drawArrays(GL_LINE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
3246
3247                                 if (GL_INVALID_OPERATION != gl.getError())
3248                                 {
3249                                         result = false;
3250
3251                                         m_testCtx.getLog() << tcu::TestLog::Message
3252                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3253                                                                            << tcu::TestLog::EndMessage;
3254
3255                                         break;
3256                                 }
3257                         }
3258
3259                         if (po != 3)
3260                         {
3261                                 gl.drawArrays(GL_TRIANGLES, 0 /*starting index*/, 3 /*number of indices*/);
3262
3263                                 if (GL_INVALID_OPERATION != gl.getError())
3264                                 {
3265                                         result = false;
3266
3267                                         m_testCtx.getLog() << tcu::TestLog::Message
3268                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3269                                                                            << tcu::TestLog::EndMessage;
3270
3271                                         break;
3272                                 }
3273
3274                                 gl.drawArrays(GL_TRIANGLE_FAN, 0 /*starting index*/, 3 /*number of indices*/);
3275
3276                                 if (GL_INVALID_OPERATION != gl.getError())
3277                                 {
3278                                         result = false;
3279
3280                                         m_testCtx.getLog() << tcu::TestLog::Message
3281                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3282                                                                            << tcu::TestLog::EndMessage;
3283
3284                                         break;
3285                                 }
3286
3287                                 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /*starting index*/, 3 /*number of indices*/);
3288
3289                                 if (GL_INVALID_OPERATION != gl.getError())
3290                                 {
3291                                         result = false;
3292
3293                                         m_testCtx.getLog() << tcu::TestLog::Message
3294                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3295                                                                            << tcu::TestLog::EndMessage;
3296
3297                                         break;
3298                                 }
3299                         }
3300
3301                         if (po != 4)
3302                         {
3303                                 gl.drawArrays(GL_TRIANGLES_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
3304
3305                                 if (GL_INVALID_OPERATION != gl.getError())
3306                                 {
3307                                         result = false;
3308
3309                                         m_testCtx.getLog() << tcu::TestLog::Message
3310                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3311                                                                            << tcu::TestLog::EndMessage;
3312
3313                                         break;
3314                                 }
3315
3316                                 gl.drawArrays(GL_TRIANGLE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
3317
3318                                 if (GL_INVALID_OPERATION != gl.getError())
3319                                 {
3320                                         result = false;
3321
3322                                         m_testCtx.getLog() << tcu::TestLog::Message
3323                                                                            << "Error different than GL_INVALID_OPEARATION was generated."
3324                                                                            << tcu::TestLog::EndMessage;
3325
3326                                         break;
3327                                 }
3328                         }
3329                 }
3330         }
3331
3332         if (result)
3333         {
3334                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3335         }
3336         else
3337         {
3338                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3339         }
3340
3341         return STOP;
3342 }
3343
3344 /** Constructor
3345  *
3346  * @param context       Test context
3347  * @param extParams     Not used.
3348  * @param name          Test case's name
3349  * @param description   Test case's description
3350  **/
3351 GeometryShaderInsufficientEmittedVerticesTest::GeometryShaderInsufficientEmittedVerticesTest(
3352         Context& context, const ExtParameters& extParams, const char* name, const char* description)
3353         : TestCaseBase(context, extParams, name, description)
3354         , m_fbo_id(0)
3355         , m_fs_id(0)
3356         , m_gs_ids(NULL)
3357         , m_number_of_color_components(4)
3358         , m_number_of_gs(2 /*taken from test spec*/)
3359         , m_po_ids(NULL)
3360         , m_texture_height(16)
3361         , m_texture_id(0)
3362         , m_texture_width(16)
3363 {
3364         m_vao_id = 0;
3365         m_vs_id  = 0;
3366
3367         /* Allocate enough memory for glReadPixels() data which is respectively: width, height, RGBA components number. */
3368         m_pixels = new glw::GLubyte[m_texture_height * m_texture_width * m_number_of_color_components];
3369 }
3370
3371 /** Deinitializes GLES objects created during the test. */
3372 void GeometryShaderInsufficientEmittedVerticesTest::deinit()
3373 {
3374         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3375
3376         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
3377
3378         if (m_pixels != NULL)
3379         {
3380                 delete[] m_pixels;
3381                 m_pixels = NULL;
3382         }
3383
3384         if (m_fbo_id != 0)
3385         {
3386                 gl.deleteFramebuffers(1, &m_fbo_id);
3387                 m_fbo_id = 0;
3388         }
3389
3390         if (m_fs_id != 0)
3391         {
3392                 gl.deleteShader(m_fs_id);
3393                 m_fs_id = 0;
3394         }
3395
3396         if (m_gs_ids != 0)
3397         {
3398                 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3399                 {
3400                         gl.deleteShader(m_gs_ids[i]);
3401                         m_gs_ids[i] = 0;
3402                 }
3403
3404                 delete[] m_gs_ids;
3405                 m_gs_ids = NULL;
3406         }
3407
3408         if (m_po_ids != 0)
3409         {
3410                 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3411                 {
3412                         gl.deleteProgram(m_po_ids[i]);
3413                         m_po_ids[i] = 0;
3414                 }
3415
3416                 delete[] m_po_ids;
3417                 m_po_ids = NULL;
3418         }
3419
3420         if (m_texture_id != 0)
3421         {
3422                 gl.deleteTextures(1, &m_texture_id);
3423                 m_texture_id = 0;
3424         }
3425
3426         if (m_vao_id != 0)
3427         {
3428                 gl.deleteVertexArrays(1, &m_vao_id);
3429                 m_vao_id = 0;
3430         }
3431
3432         if (m_vs_id != 0)
3433         {
3434                 gl.deleteShader(m_vs_id);
3435                 m_vs_id = 0;
3436         }
3437
3438         /* Release base class */
3439         TestCaseBase::deinit();
3440 }
3441
3442 /** Executes the test.
3443  *
3444  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3445  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3446  *  Note the function throws exception should an error occur!
3447  **/
3448 tcu::TestNode::IterateResult GeometryShaderInsufficientEmittedVerticesTest::iterate()
3449 {
3450         /* Define Fragment Shader for purpose of this test. */
3451         const char* fs_code = "${VERSION}\n"
3452                                                   "\n"
3453                                                   "precision highp float;\n"
3454                                                   "\n"
3455                                                   "out vec4 result;\n"
3456                                                   "\n"
3457                                                   "void main()\n"
3458                                                   "{\n"
3459                                                   "    result = vec4(1.0, 0.0, 0.0, 0.0);\n"
3460                                                   "}\n";
3461
3462         /* Define 2 Geometry Shaders for purpose of this test. */
3463         const char* gs_line_strip = "${VERSION}\n"
3464                                                                 "${GEOMETRY_SHADER_REQUIRE}\n"
3465                                                                 "\n"
3466                                                                 "layout (points)                       in;\n"
3467                                                                 "layout (line_strip, max_vertices = 2) out;\n"
3468                                                                 "\n"
3469                                                                 "${IN_PER_VERTEX_DECL_ARRAY}"
3470                                                                 "\n"
3471                                                                 "void main()\n"
3472                                                                 "{\n"
3473                                                                 "    gl_Position    = gl_in[0].gl_Position;\n"
3474                                                                 "    gl_Position.zw = vec2(0.0, 1.0);\n"
3475                                                                 "    EmitVertex();\n"
3476                                                                 "}\n";
3477
3478         const char* gs_triangle_strip = "${VERSION}\n"
3479                                                                         "${GEOMETRY_SHADER_REQUIRE}\n"
3480                                                                         "\n"
3481                                                                         "layout (points)                           in;\n"
3482                                                                         "layout (triangle_strip, max_vertices = 3) out;\n"
3483                                                                         "\n"
3484                                                                         "${IN_PER_VERTEX_DECL_ARRAY}"
3485                                                                         "\n"
3486                                                                         "void main()\n"
3487                                                                         "{\n"
3488                                                                         "    gl_Position    = gl_in[0].gl_Position;\n"
3489                                                                         "    gl_Position.zw = vec2(0.0, 1.0);\n"
3490                                                                         "    EmitVertex();\n"
3491
3492                                                                         "    gl_Position    = gl_in[0].gl_Position;\n"
3493                                                                         "    gl_Position.zw = vec2(0.0, 1.0);\n"
3494                                                                         "    EmitVertex();\n"
3495                                                                         "}\n";
3496
3497         bool has_shader_compilation_failed = true;
3498         bool result                                                = true;
3499
3500         m_gs_ids = new glw::GLuint[m_number_of_gs];
3501         m_po_ids = new glw::GLuint[m_number_of_gs];
3502
3503         /* This test should only run if EXT_geometry_shader is supported. */
3504         if (!m_is_geometry_shader_extension_supported)
3505         {
3506                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3507         }
3508
3509         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3510
3511         /* Create program objects & geometry shader objects. */
3512         for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3513         {
3514                 m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
3515                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3516
3517                 m_po_ids[i] = gl.createProgram();
3518                 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3519         }
3520
3521         /* Create shader object. */
3522         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3523         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3524         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3525
3526         /* Try to link the test program object */
3527         std::string fs_code_specialized         = specializeShader(1, &fs_code);
3528         const char* fs_code_specialized_raw = fs_code_specialized.c_str();
3529
3530         std::string gs_codes_specialized[] = { specializeShader(1, &gs_line_strip),
3531                                                                                    specializeShader(1, &gs_triangle_strip) };
3532
3533         const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str() };
3534
3535         std::string vs_code_specialized         = specializeShader(1, &dummy_vs_code);
3536         const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3537
3538         for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3539         {
3540                 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,                                  /* n_sh1_body_parts */
3541                                                                                 &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
3542                                                                                 &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
3543                                                                                 &vs_code_specialized_raw, &has_shader_compilation_failed))
3544                 {
3545                         m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
3546                                                            << "[" << i << "]." << tcu::TestLog::EndMessage;
3547
3548                         result = false;
3549                         break;
3550                 }
3551         }
3552
3553         if (result)
3554         {
3555                 /* Create a 2D texture. */
3556                 gl.genTextures(1, &m_texture_id);
3557                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
3558
3559                 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
3560                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
3561
3562                 gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_RGBA8, 16 /*width taken from spec*/,
3563                                                 16 /*height taken from spec*/);
3564                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
3565
3566                 /* Configure FBO. */
3567                 gl.genFramebuffers(1, &m_fbo_id);
3568                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
3569
3570                 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
3571                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
3572
3573                 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /*level*/);
3574                 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
3575
3576                 /* Configure VAO. */
3577                 gl.genVertexArrays(1, &m_vao_id);
3578                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3579
3580                 gl.bindVertexArray(m_vao_id);
3581                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3582
3583                 gl.clearColor(0.0f, 1.0f, 0.0f, 0.0f);
3584                 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
3585
3586                 for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
3587                 {
3588                         /* Use Program Object. */
3589                         gl.useProgram(m_po_ids[po]);
3590                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3591
3592                         gl.clear(GL_COLOR_BUFFER_BIT);
3593                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
3594
3595                         gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3596                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
3597
3598                         gl.readPixels(0 /*x*/, 0 /*y*/, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
3599                         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
3600
3601                         for (glw::GLuint pixel = 0; pixel < (m_texture_width * m_texture_height * m_number_of_color_components -
3602                                                                                                  m_number_of_color_components);
3603                                  pixel += m_number_of_color_components)
3604                         {
3605                                 if (m_pixels[pixel] != 0 && m_pixels[pixel + 1] != 255 && m_pixels[pixel + 2] != 0 &&
3606                                         m_pixels[pixel + 3] != 0)
3607                                 {
3608                                         result = false;
3609
3610                                         m_testCtx.getLog() << tcu::TestLog::Message << "Pixel [" << pixel << "] has color = ["
3611                                                                            << m_pixels[pixel] << ", " << m_pixels[pixel + 1] << ", " << m_pixels[pixel + 2]
3612                                                                            << ", " << m_pixels[pixel + 3] << "] "
3613                                                                            << "instead of [0, 255, 0, 0]." << tcu::TestLog::EndMessage;
3614
3615                                         break;
3616                                 }
3617                         }
3618                 }
3619         }
3620
3621         if (result)
3622         {
3623                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3624         }
3625         else
3626         {
3627                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3628         }
3629
3630         return STOP;
3631 }
3632
3633 /** Constructor
3634  *
3635  * @param context       Test context
3636  * @param extParams     Not used.
3637  * @param name          Test case's name
3638  * @param description   Test case's description
3639  **/
3640 GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::
3641         GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context&                         context,
3642                                                                                                                                                                         const ExtParameters& extParams,
3643                                                                                                                                                                         const char*                      name,
3644                                                                                                                                                                         const char*                      description)
3645         : TestCaseBase(context, extParams, name, description)
3646         , m_gs_id(0)
3647         , m_gs_po_id(0)
3648         , m_ppo_id(0)
3649         , m_tfbo_id(0)
3650         , m_vao_id(0)
3651         , m_vs_id(0)
3652         , m_vs_po_id(0)
3653 {
3654 }
3655
3656 /** Deinitializes GLES objects created during the test. */
3657 void GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::deinit()
3658 {
3659         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3660
3661         if (m_gs_id != 0)
3662         {
3663                 gl.deleteShader(m_gs_id);
3664                 m_gs_id = 0;
3665         }
3666
3667         if (m_gs_po_id != 0)
3668         {
3669                 gl.deleteProgram(m_gs_po_id);
3670                 m_gs_po_id = 0;
3671         }
3672
3673         if (m_ppo_id != 0)
3674         {
3675                 gl.deleteProgramPipelines(1, &m_ppo_id);
3676                 m_ppo_id = 0;
3677         }
3678
3679         if (m_tfbo_id != 0)
3680         {
3681                 gl.deleteBuffers(1, &m_tfbo_id);
3682                 m_tfbo_id = 0;
3683         }
3684
3685         if (m_vao_id != 0)
3686         {
3687                 gl.deleteVertexArrays(1, &m_vao_id);
3688                 m_vao_id = 0;
3689         }
3690
3691         if (m_vs_id != 0)
3692         {
3693                 gl.deleteShader(m_vs_id);
3694                 m_vs_id = 0;
3695         }
3696
3697         if (m_vs_po_id != 0)
3698         {
3699                 gl.deleteProgram(m_vs_po_id);
3700                 m_vs_po_id = 0;
3701         }
3702
3703         /* Release base class */
3704         TestCaseBase::deinit();
3705 }
3706
3707 /** Executes the test.
3708  *
3709  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3710  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3711  *  Note the function throws exception should an error occur!
3712  **/
3713 tcu::TestNode::IterateResult GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::iterate()
3714 {
3715         /* Define Geometry Shader for purpose of this test. */
3716         const char* gs_code =
3717                 "${VERSION}\n"
3718                 "${GEOMETRY_SHADER_REQUIRE}\n"
3719                 "${IN_PER_VERTEX_DECL_ARRAY}\n"
3720                 "${OUT_PER_VERTEX_DECL}\n"
3721                 "\n"
3722                 "layout (points)                   in;\n"
3723                 "layout (points, max_vertices = 1) out;\n"
3724                 "\n"
3725                 "flat in int   vertexID[];\n"
3726                 "flat in ivec4 out_vs_1[];\n"
3727                 "\n"
3728                 "out vec4 out_gs_1;\n"
3729                 "\n"
3730                 "void main()\n"
3731                 "{\n"
3732                 "    out_gs_1 = vec4(vertexID[0] * 2, vertexID[0] * 2 + 1, vertexID[0] * 2 + 2, vertexID[0] * 2 + 3);\n"
3733                 "    gl_Position = vec4(0, 0, 0, 1);\n"
3734                 "    EmitVertex();\n"
3735                 "}\n";
3736
3737         /* Define Vertex Shader for purpose of this test. */
3738         const char* vs_code = "${VERSION}\n"
3739                                                   "${OUT_PER_VERTEX_DECL}\n"
3740                                                   "\n"
3741                                                   "flat out ivec4 out_vs_1;\n"
3742                                                   "flat out int vertexID;\n"
3743                                                   "\n"
3744                                                   "void main()\n"
3745                                                   "{\n"
3746                                                   "    vertexID = gl_VertexID;\n"
3747                                                   "    out_vs_1 = ivec4(gl_VertexID, gl_VertexID + 1, gl_VertexID + 2, gl_VertexID + 3);\n"
3748                                                   "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3749                                                   "}\n";
3750
3751         bool              has_shader_compilation_failed = true;
3752         bool              result                                                = true;
3753         glw::GLfloat* ptrTF_data_f                                      = NULL;
3754         glw::GLuint*  ptrTF_data_ui                                     = NULL;
3755         glw::GLfloat  expected_geom_results[]           = { 0.0f, 1.0f, 2.0f, 3.0f };
3756         glw::GLuint   expected_vertex_results[]         = { 0, 1, 2, 3 };
3757         glw::GLfloat  epsilon                                           = 1e-5f;
3758
3759         /* This test should only run if EXT_geometry_shader is supported. */
3760         if (!m_is_geometry_shader_extension_supported)
3761         {
3762                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3763         }
3764
3765         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3766
3767         /* Create separable program objects. */
3768         m_gs_po_id = gl.createProgram();
3769         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3770
3771         gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
3772         GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
3773
3774         m_vs_po_id = gl.createProgram();
3775         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3776
3777         gl.programParameteri(m_vs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
3778         GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
3779
3780         /* Create shader objects. */
3781         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
3782         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3783         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3784
3785         /* Try to link the test program object */
3786         std::string gs_code_specialized         = specializeShader(1, &gs_code);
3787         const char* gs_code_specialized_raw = gs_code_specialized.c_str();
3788
3789         std::string vs_code_specialized         = specializeShader(1, &vs_code);
3790         const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3791
3792         /* Specify output variables to be captured. */
3793         const char* tf_varyings[2] = { "out_gs_1", "out_vs_1" };
3794
3795         gl.transformFeedbackVaryings(m_gs_po_id, 1 /*count*/, &tf_varyings[0], GL_INTERLEAVED_ATTRIBS);
3796         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
3797
3798         gl.transformFeedbackVaryings(m_vs_po_id, 1 /*count*/, &tf_varyings[1], GL_INTERLEAVED_ATTRIBS);
3799         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
3800
3801         if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1,                 /* n_sh1_body_parts */
3802                                                                         &gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
3803                                                                         NULL, 0, 0,                                             /* n_sh3_body_parts */
3804                                                                         NULL, &has_shader_compilation_failed))
3805         {
3806                 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
3807                                                    << tcu::TestLog::EndMessage;
3808
3809                 result = false;
3810                 goto end;
3811         }
3812
3813         if (!TestCaseBase::buildProgram(m_vs_po_id, m_vs_id, 1,                 /* n_sh1_body_parts */
3814                                                                         &vs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
3815                                                                         NULL, 0, 0,                                             /* n_sh3_body_parts */
3816                                                                         NULL, &has_shader_compilation_failed))
3817         {
3818                 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
3819                                                    << tcu::TestLog::EndMessage;
3820
3821                 result = false;
3822                 goto end;
3823         }
3824
3825         /* Create and configure Program Pipeline Object. */
3826         gl.genProgramPipelines(1, &m_ppo_id);
3827         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call(s) failed.");
3828
3829         gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
3830         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3831
3832         gl.useProgramStages(m_ppo_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
3833         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3834
3835         /* Create Vertex Array Object. */
3836         gl.genVertexArrays(1, &m_vao_id);
3837         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
3838
3839         gl.bindVertexArray(m_vao_id);
3840         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
3841
3842         /* Create Buffer Object for Transform Feedback data. */
3843         gl.genBuffers(1, &m_tfbo_id);
3844         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
3845
3846         gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
3847         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
3848
3849         gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4, NULL, GL_STREAM_READ);
3850         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
3851
3852         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
3853         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
3854
3855         /* Ensure that there is no program object already bound and bind program pipeline. */
3856         gl.useProgram(0);
3857         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
3858
3859         gl.bindProgramPipeline(m_ppo_id);
3860         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
3861
3862         gl.enable(GL_RASTERIZER_DISCARD);
3863         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
3864
3865         /* First pass - Vertex and Geometry Shaders On. */
3866         gl.beginTransformFeedback(GL_POINTS);
3867         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
3868
3869         gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3870         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
3871
3872         gl.endTransformFeedback();
3873         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
3874
3875         /* Retrieve data and check if it is correct. */
3876         ptrTF_data_f =
3877                 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
3878                                                                                  sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
3879         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3880
3881         for (size_t i = 0; i < 4; ++i)
3882         {
3883                 if (fabs(ptrTF_data_f[i] - expected_geom_results[i]) >= epsilon)
3884                 {
3885                         result = false;
3886                         break;
3887                 }
3888         }
3889
3890         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3891         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3892
3893         ptrTF_data_f = NULL;
3894
3895         if (!result)
3896         {
3897                 goto end;
3898         }
3899
3900         /* Deactivate Geometry Shader Program Object from Program Pipeline Object. */
3901         gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, 0 /* program */);
3902         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3903
3904         /* Second pass - only Vertex Shader Program On. */
3905         gl.beginTransformFeedback(GL_POINTS);
3906         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
3907
3908         gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3909         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
3910
3911         gl.endTransformFeedback();
3912         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
3913
3914         gl.disable(GL_RASTERIZER_DISCARD);
3915         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
3916
3917         /* Retrieve data and check if it is correct. */
3918         ptrTF_data_ui =
3919                 (glw::GLuint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
3920                                                                                 sizeof(glw::GLuint) * 4 /* four float vector components */, GL_MAP_READ_BIT);
3921         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3922
3923         for (size_t i = 0; i < 4; ++i)
3924         {
3925                 if (ptrTF_data_ui[i] != expected_vertex_results[i])
3926                 {
3927                         result = false;
3928                         break;
3929                 }
3930         }
3931
3932         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3933         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3934
3935         ptrTF_data_ui = NULL;
3936
3937 end:
3938         if (result)
3939         {
3940                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3941         }
3942         else
3943         {
3944                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3945         }
3946
3947         return STOP;
3948 }
3949
3950 /** Constructor
3951  *
3952  * @param context       Test context
3953  * @param extParams     Not used.
3954  * @param name          Test case's name
3955  * @param description   Test case's description
3956  **/
3957 GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives(
3958         Context& context, const ExtParameters& extParams, const char* name, const char* description)
3959         : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_tfbo_id(0)
3960 {
3961         m_vao_id = 0;
3962         m_vs_id  = 0;
3963 }
3964
3965 /** Deinitializes GLES objects created during the test. */
3966 void GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::deinit()
3967 {
3968         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3969
3970         if (m_fs_id != 0)
3971         {
3972                 gl.deleteShader(m_fs_id);
3973                 m_fs_id = 0;
3974         }
3975
3976         if (m_gs_id != 0)
3977         {
3978                 gl.deleteShader(m_gs_id);
3979                 m_gs_id = 0;
3980         }
3981
3982         if (m_po_id != 0)
3983         {
3984                 gl.deleteProgram(m_po_id);
3985                 m_po_id = 0;
3986         }
3987
3988         if (m_tfbo_id != 0)
3989         {
3990                 gl.deleteBuffers(1, &m_tfbo_id);
3991                 m_tfbo_id = 0;
3992         }
3993
3994         if (m_vao_id != 0)
3995         {
3996                 gl.deleteVertexArrays(1, &m_vao_id);
3997                 m_vao_id = 0;
3998         }
3999
4000         if (m_vs_id != 0)
4001         {
4002                 gl.deleteShader(m_vs_id);
4003                 m_vs_id = 0;
4004         }
4005
4006         /* Release base class */
4007         TestCaseBase::deinit();
4008 }
4009
4010 /** Executes the test.
4011  *
4012  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4013  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
4014  *  Note the function throws exception should an error occur!
4015  **/
4016 tcu::TestNode::IterateResult GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::iterate()
4017 {
4018         /* Define Geometry Shader for purpose of this test. */
4019         const char* gs_code = "${VERSION}\n"
4020                                                   "${GEOMETRY_SHADER_REQUIRE}\n"
4021                                                   "\n"
4022                                                   "layout (lines)                            in;\n"
4023                                                   "layout (triangle_strip, max_vertices = 3) out;\n"
4024                                                   "\n"
4025                                                   "out vec4 out_gs_1;\n"
4026                                                   "\n"
4027                                                   "void main()\n"
4028                                                   "{\n"
4029                                                   "    out_gs_1 = vec4(4.0, 3.0, 2.0, 1.0);\n"
4030                                                   "\n"
4031                                                   "    gl_Position = vec4(0, 0, 0, 1);\n"
4032                                                   "    EmitVertex();\n"
4033                                                   "\n"
4034                                                   "    gl_Position = vec4(1, 0, 0, 1);\n"
4035                                                   "    EmitVertex();\n"
4036                                                   "\n"
4037                                                   "    gl_Position = vec4(1, 1, 0, 1);\n"
4038                                                   "    EmitVertex();\n"
4039                                                   "\n"
4040                                                   "    EndPrimitive();"
4041                                                   "}\n";
4042
4043         bool            has_shader_compilation_failed = true;
4044         bool            result                                            = true;
4045         glw::GLenum error                                                 = GL_NO_ERROR;
4046
4047         /* This test should only run if EXT_geometry_shader is supported. */
4048         if (!m_is_geometry_shader_extension_supported)
4049         {
4050                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
4051         }
4052
4053         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4054
4055         /* Create program object. */
4056         m_po_id = gl.createProgram();
4057         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
4058
4059         /* Specify output variables to be captured. */
4060         const char* tf_varyings[] = { "out_gs_1" };
4061
4062         gl.transformFeedbackVaryings(m_po_id, 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
4063         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
4064
4065         /* Create shader objects. */
4066         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4067         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4068         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4069         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4070
4071         /* Try to link the test program object */
4072         std::string fs_code_specialized         = specializeShader(1, &dummy_fs_code);
4073         const char* fs_code_specialized_raw = fs_code_specialized.c_str();
4074
4075         std::string gs_code_specialized         = specializeShader(1, &gs_code);
4076         const char* gs_code_specialized_raw = gs_code_specialized.c_str();
4077
4078         std::string vs_code_specialized         = specializeShader(1, &dummy_vs_code);
4079         const char* vs_code_specialized_raw = vs_code_specialized.c_str();
4080
4081         if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1,                              /* n_sh1_body_parts */
4082                                                                         &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
4083                                                                         &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
4084                                                                         &vs_code_specialized_raw, &has_shader_compilation_failed))
4085         {
4086                 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed whereas a success was expected."
4087                                                    << tcu::TestLog::EndMessage;
4088
4089                 result = false;
4090                 goto end;
4091         }
4092
4093         /* Create Vertex Array Object. */
4094         gl.genVertexArrays(1, &m_vao_id);
4095         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
4096
4097         gl.bindVertexArray(m_vao_id);
4098         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
4099
4100         /* Create Buffer Object for Transform Feedback data. */
4101         gl.genBuffers(1, &m_tfbo_id);
4102         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
4103
4104         gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
4105         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4106
4107         gl.bufferData(GL_ARRAY_BUFFER,
4108                                   sizeof(glw::GLfloat) * 4 * 3 /* capture 4 float vector components times 3 triangle vertices */, NULL,
4109                                   GL_STREAM_READ);
4110         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
4111
4112         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
4113         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
4114
4115         /* Turn on program object. */
4116         gl.useProgram(m_po_id);
4117         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
4118
4119         gl.enable(GL_RASTERIZER_DISCARD);
4120         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
4121
4122         gl.beginTransformFeedback(GL_LINES);
4123         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
4124
4125         gl.drawArrays(GL_TRIANGLES, 0 /*first*/, 3 /*count*/);
4126
4127         error = gl.getError();
4128
4129         if (error != GL_INVALID_OPERATION)
4130         {
4131                 result = false;
4132
4133                 m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
4134                                                    << tcu::TestLog::EndMessage;
4135         }
4136
4137         gl.endTransformFeedback();
4138         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
4139
4140         gl.disable(GL_RASTERIZER_DISCARD);
4141         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
4142
4143 end:
4144
4145         if (result)
4146         {
4147                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4148         }
4149         else
4150         {
4151                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4152         }
4153
4154         return STOP;
4155 }
4156
4157 /** Constructor
4158  *
4159  * @param context       Test context
4160  * @param extParams     Not used.
4161  * @param name          Test case's name
4162  * @param description   Test case's description
4163  **/
4164 GeometryShaderDrawCallsWhileTFPaused::GeometryShaderDrawCallsWhileTFPaused(Context&                             context,
4165                                                                                                                                                    const ExtParameters& extParams,
4166                                                                                                                                                    const char* name, const char* description)
4167         : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_tfbo_id(0)
4168 {
4169         m_vao_id = 0;
4170         m_vs_id  = 0;
4171 }
4172
4173 /** Deinitializes GLES objects created during the test. */
4174 void GeometryShaderDrawCallsWhileTFPaused::deinit()
4175 {
4176         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4177
4178         if (m_fs_id != 0)
4179         {
4180                 gl.deleteShader(m_fs_id);
4181                 m_fs_id = 0;
4182         }
4183
4184         if (m_gs_id != 0)
4185         {
4186                 gl.deleteShader(m_gs_id);
4187                 m_gs_id = 0;
4188         }
4189
4190         for (int i = 0; i < 15 /* All combinations of possible inputs and outputs in GS */; ++i)
4191         {
4192                 if (m_po_ids[i] != 0)
4193                 {
4194                         gl.deleteProgram(m_po_ids[i]);
4195                         m_po_ids[i] = 0;
4196                 }
4197         }
4198
4199         if (m_tfbo_id != 0)
4200         {
4201                 gl.deleteBuffers(1, &m_tfbo_id);
4202                 m_tfbo_id = 0;
4203         }
4204
4205         if (m_vao_id != 0)
4206         {
4207                 gl.deleteVertexArrays(1, &m_vao_id);
4208                 m_vao_id = 0;
4209         }
4210
4211         if (m_vs_id != 0)
4212         {
4213                 gl.deleteShader(m_vs_id);
4214                 m_vs_id = 0;
4215         }
4216
4217         /* Release base class */
4218         TestCaseBase::deinit();
4219 }
4220
4221 /** Executes the test.
4222  *
4223  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4224  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
4225  *  Note the function throws exception should an error occur!
4226  **/
4227 tcu::TestNode::IterateResult GeometryShaderDrawCallsWhileTFPaused::iterate()
4228 {
4229         /* Define 15 (all combinations of possible inputs and outputs in geometry shader) Geometry Shaders for purpose of this test. */
4230         const std::string gs_inputs[]  = { "points", "lines", "lines_adjacency", "triangles", "triangles_adjacency" };
4231         const std::string gs_outputs[] = { "points", "line_strip", "triangle_strip" };
4232         const std::string gs_max_output_vertices[] = { "1", "2", "3" };
4233
4234         const unsigned short number_of_combinations =
4235                 (sizeof(gs_inputs) / sizeof(gs_inputs[0]) * (sizeof(gs_outputs) / sizeof(gs_outputs[0])));
4236
4237         std::string gs_codes[number_of_combinations];
4238         glw::GLenum errorCode;
4239
4240         for (size_t i = 0; i < (sizeof(gs_inputs) / sizeof(gs_inputs[0])) /*5 possible GS inputs*/; ++i)
4241         {
4242                 for (size_t j = 0; j < (sizeof(gs_outputs) / sizeof(gs_outputs[0])) /*3 possible GS outputs*/; ++j)
4243                 {
4244                         /* This shader will not emit primitives for anything but points.
4245                          * We do so, because we just need to make sure that, while transform feedback
4246                          * is paused, all draw calls executed with an active program object which
4247                          * includes a geometry shader, are valid.
4248                          */
4249                         gs_codes[j + 3 * i] = "${VERSION}\n"
4250                                                                   "${GEOMETRY_SHADER_REQUIRE}\n"
4251                                                                   "\n"
4252                                                                   "layout (" +
4253                                                                   gs_inputs[i] + ") in;\n"
4254                                                                                                  "layout (" +
4255                                                                   gs_outputs[j] + ", max_vertices = " + gs_max_output_vertices[j] +
4256                                                                   ") out;\n"
4257                                                                   "\n"
4258                                                                   "out vec2 out_gs_1;\n"
4259                                                                   "\n"
4260                                                                   "void main()\n"
4261                                                                   "{\n"
4262                                                                   "    out_gs_1    = vec2(1.0, 2.0);\n"
4263                                                                   "    gl_Position = vec4(0, 0, 0, 1);\n"
4264                                                                   "    EmitVertex();\n"
4265                                                                   "}\n";
4266                 }
4267         }
4268
4269         bool                      has_shader_compilation_failed = true;
4270         bool                      result                                                = true;
4271         const glw::GLuint tf_modes[3]                                   = { GL_POINTS, GL_LINES, GL_TRIANGLES };
4272         const glw::GLuint draw_call_modes[5]                    = { GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES,
4273                                                                                          GL_TRIANGLES_ADJACENCY };
4274
4275         /* This test should only run if EXT_geometry_shader is supported. */
4276         if (!m_is_geometry_shader_extension_supported)
4277         {
4278                 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
4279         }
4280
4281         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4282
4283         /* Create program objects. */
4284         for (int i = 0; i < number_of_combinations; ++i)
4285         {
4286                 m_po_ids[i] = gl.createProgram();
4287         }
4288         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
4289
4290         /* Specify output variables to be captured. */
4291         const char* tf_varyings[] = { "out_gs_1" };
4292
4293         for (int i = 0; i < number_of_combinations; ++i)
4294         {
4295                 gl.transformFeedbackVaryings(m_po_ids[i], 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
4296         }
4297         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
4298
4299         /* Create shader objects. */
4300         m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4301         m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4302         m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4303         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4304
4305         /* Try to link the test program object */
4306         std::string fs_code_specialized         = specializeShader(1, &dummy_fs_code);
4307         const char* fs_code_specialized_raw = fs_code_specialized.c_str();
4308
4309         std::string vs_code_specialized         = specializeShader(1, &dummy_vs_code);
4310         const char* vs_code_specialized_raw = vs_code_specialized.c_str();
4311
4312         for (int i = 0; i < number_of_combinations; ++i)
4313         {
4314                 const char* gs_code                                     = gs_codes[i].c_str();
4315                 std::string gs_code_specialized         = specializeShader(1, &gs_code);
4316                 const char* gs_code_specialized_raw = gs_code_specialized.c_str();
4317
4318                 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,                          /* n_sh1_body_parts */
4319                                                                                 &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
4320                                                                                 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
4321                                                                                 &vs_code_specialized_raw, &has_shader_compilation_failed))
4322                 {
4323                         m_testCtx.getLog() << tcu::TestLog::Message
4324                                                            << "Program object linking failed whereas a success was expected."
4325                                                            << tcu::TestLog::EndMessage;
4326
4327                         result = false;
4328                 }
4329         }
4330
4331         if (!result)
4332         {
4333                 goto end;
4334         }
4335
4336         /* Create Vertex Array Object. */
4337         gl.genVertexArrays(1, &m_vao_id);
4338         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
4339
4340         gl.bindVertexArray(m_vao_id);
4341         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
4342
4343         /* Create Buffer Object for Transform Feedback data. */
4344         gl.genBuffers(1, &m_tfbo_id);
4345         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
4346
4347         gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
4348         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4349
4350         gl.bufferData(GL_ARRAY_BUFFER,
4351                                   sizeof(glw::GLfloat) * 2 * 3 /* capture 2 float vector components times 3 triangle vertices */, NULL,
4352                                   GL_STREAM_READ);
4353         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
4354
4355         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
4356         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
4357
4358         gl.enable(GL_RASTERIZER_DISCARD);
4359         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
4360
4361         for (int i = 0; i < 3 /* number of TF modes */ && result; ++i)
4362         {
4363                 for (int j = 0; j < 5 /*number of draw call modes*/ && result; ++j)
4364                 {
4365                         for (int k = 0; k < 3 /* number of output GS primitive types */; ++k)
4366                         {
4367                                 /* Turn on program object. */
4368                                 gl.useProgram(m_po_ids[k + 3 * j]);
4369                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
4370
4371                                 gl.beginTransformFeedback(tf_modes[i]);
4372                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
4373
4374                                 gl.pauseTransformFeedback();
4375                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback() call(s) failed.");
4376
4377                                 gl.drawArrays(draw_call_modes[j], 0 /*first*/, 3 /*count*/);
4378                                 errorCode = gl.getError();
4379
4380                                 gl.resumeTransformFeedback();
4381                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback() call(s) failed.");
4382
4383                                 gl.endTransformFeedback();
4384                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
4385
4386                                 /* If draw call fails stop test execution. */
4387                                 if (GL_NO_ERROR != errorCode)
4388                                 {
4389                                         m_testCtx.getLog() << tcu::TestLog::Message
4390                                                                            << "glDrawArrays() call generated an error while transform feedback was paused."
4391                                                                            << tcu::TestLog::EndMessage;
4392
4393                                         result = false;
4394                                         break;
4395                                 }
4396                         }
4397                 }
4398         }
4399
4400         gl.disable(GL_RASTERIZER_DISCARD);
4401         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
4402
4403 end:
4404
4405         if (result)
4406         {
4407                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4408         }
4409         else
4410         {
4411                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4412         }
4413
4414         return STOP;
4415 }
4416
4417 } // namespace glcts