am b0f812a1: (-s ours) am dafc0617: Remove negative tests for sliced 3D ASTC texture...
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fGeometryShaderTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
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 Geometry shader tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fGeometryShaderTests.hpp"
25
26 #include "gluRenderContext.hpp"
27 #include "gluTextureUtil.hpp"
28 #include "gluObjectWrapper.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluCallLogWrapper.hpp"
32 #include "tcuRenderTarget.hpp"
33 #include "tcuTestLog.hpp"
34 #include "tcuVectorUtil.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "glsStateQueryUtil.hpp"
38
39 #include "gluStrUtil.hpp"
40 #include "deStringUtil.hpp"
41 #include "deUniquePtr.hpp"
42 #include "deMemory.h"
43
44 #include "sglrContext.hpp"
45 #include "sglrReferenceContext.hpp"
46 #include "sglrGLContext.hpp"
47 #include "sglrReferenceUtils.hpp"
48
49 #include "glwDefs.hpp"
50 #include "glwEnums.hpp"
51 #include "glwFunctions.hpp"
52
53 #include <algorithm>
54
55 using namespace glw;
56
57 namespace deqp
58 {
59 namespace gles31
60 {
61 namespace Functional
62 {
63 namespace
64 {
65
66 using namespace gls::StateQueryUtil;
67
68 const int TEST_CANVAS_SIZE = 256;
69
70 static const char* const s_commonShaderSourceVertex =           "#version 310 es\n"
71                                                                                                                         "in highp vec4 a_position;\n"
72                                                                                                                         "in highp vec4 a_color;\n"
73                                                                                                                         "out highp vec4 v_geom_FragColor;\n"
74                                                                                                                         "void main (void)\n"
75                                                                                                                         "{\n"
76                                                                                                                         "       gl_Position = a_position;\n"
77                                                                                                                         "       gl_PointSize = 1.0;\n"
78                                                                                                                         "       v_geom_FragColor = a_color;\n"
79                                                                                                                         "}\n";
80 static const char* const s_commonShaderSourceFragment =         "#version 310 es\n"
81                                                                                                                         "layout(location = 0) out mediump vec4 fragColor;\n"
82                                                                                                                         "in mediump vec4 v_frag_FragColor;\n"
83                                                                                                                         "void main (void)\n"
84                                                                                                                         "{\n"
85                                                                                                                         "       fragColor = v_frag_FragColor;\n"
86                                                                                                                         "}\n";
87 static const char* const s_expandShaderSourceGeometryBody =     "in highp vec4 v_geom_FragColor[];\n"
88                                                                                                                         "out highp vec4 v_frag_FragColor;\n"
89                                                                                                                         "\n"
90                                                                                                                         "void main (void)\n"
91                                                                                                                         "{\n"
92                                                                                                                         "       const highp vec4 offset0 = vec4(-0.07, -0.01, 0.0, 0.0);\n"
93                                                                                                                         "       const highp vec4 offset1 = vec4( 0.03, -0.03, 0.0, 0.0);\n"
94                                                                                                                         "       const highp vec4 offset2 = vec4(-0.01,  0.08, 0.0, 0.0);\n"
95                                                                                                                         "             highp vec4 yoffset = float(gl_PrimitiveIDIn) * vec4(0.02, 0.1, 0.0, 0.0);\n"
96                                                                                                                         "\n"
97                                                                                                                         "       for (highp int ndx = 0; ndx < gl_in.length(); ndx++)\n"
98                                                                                                                         "       {\n"
99                                                                                                                         "               gl_Position = gl_in[ndx].gl_Position + offset0 + yoffset;\n"
100                                                                                                                         "               gl_PrimitiveID = gl_PrimitiveIDIn;\n"
101                                                                                                                         "               v_frag_FragColor = v_geom_FragColor[ndx];\n"
102                                                                                                                         "               EmitVertex();\n"
103                                                                                                                         "\n"
104                                                                                                                         "               gl_Position = gl_in[ndx].gl_Position + offset1 + yoffset;\n"
105                                                                                                                         "               gl_PrimitiveID = gl_PrimitiveIDIn;\n"
106                                                                                                                         "               v_frag_FragColor = v_geom_FragColor[ndx];\n"
107                                                                                                                         "               EmitVertex();\n"
108                                                                                                                         "\n"
109                                                                                                                         "               gl_Position = gl_in[ndx].gl_Position + offset2 + yoffset;\n"
110                                                                                                                         "               gl_PrimitiveID = gl_PrimitiveIDIn;\n"
111                                                                                                                         "               v_frag_FragColor = v_geom_FragColor[ndx];\n"
112                                                                                                                         "               EmitVertex();\n"
113                                                                                                                         "               EndPrimitive();\n"
114                                                                                                                         "       }\n"
115                                                                                                                         "}\n";
116
117 std::string inputTypeToGLString (rr::GeometryShaderInputType inputType)
118 {
119         switch (inputType)
120         {
121                 case rr::GEOMETRYSHADERINPUTTYPE_POINTS:                                return "points";
122                 case rr::GEOMETRYSHADERINPUTTYPE_LINES:                                 return "lines";
123                 case rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY:               return "lines_adjacency";
124                 case rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES:                             return "triangles";
125                 case rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY:   return "triangles_adjacency";
126                 default:
127                         DE_ASSERT(DE_FALSE);
128                         return "error";
129         }
130 }
131
132 std::string outputTypeToGLString (rr::GeometryShaderOutputType outputType)
133 {
134         switch (outputType)
135         {
136                 case rr::GEOMETRYSHADEROUTPUTTYPE_POINTS:                               return "points";
137                 case rr::GEOMETRYSHADEROUTPUTTYPE_LINE_STRIP:                   return "line_strip";
138                 case rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP:               return "triangle_strip";
139                 default:
140                         DE_ASSERT(DE_FALSE);
141                         return "error";
142         }
143 }
144
145 std::string primitiveTypeToString(GLenum primitive)
146 {
147         switch (primitive)
148         {
149                 case GL_POINTS:                                          return "points";
150                 case GL_LINES:                                           return "lines";
151                 case GL_LINE_LOOP:                                       return "line_loop";
152                 case GL_LINE_STRIP:                                      return "line_strip";
153                 case GL_LINES_ADJACENCY:                         return "lines_adjacency";
154                 case GL_LINE_STRIP_ADJACENCY:            return "line_strip_adjacency";
155                 case GL_TRIANGLES:                                       return "triangles";
156                 case GL_TRIANGLE_STRIP:                          return "triangle_strip";
157                 case GL_TRIANGLE_FAN:                            return "triangle_fan";
158                 case GL_TRIANGLES_ADJACENCY:             return "triangles_adjacency";
159                 case GL_TRIANGLE_STRIP_ADJACENCY:        return "triangle_strip_adjacency";
160                 default:
161                         DE_ASSERT(DE_FALSE);
162                         return "error";
163         }
164 }
165
166 struct OutputCountPatternSpec
167 {
168                                                 OutputCountPatternSpec (int count);
169                                                 OutputCountPatternSpec (int count0, int count1);
170
171         std::vector<int>        pattern;
172 };
173
174 OutputCountPatternSpec::OutputCountPatternSpec (int count)
175 {
176         pattern.push_back(count);
177 }
178
179 OutputCountPatternSpec::OutputCountPatternSpec (int count0, int count1)
180 {
181         pattern.push_back(count0);
182         pattern.push_back(count1);
183 }
184
185 class VertexExpanderShader : public sglr::ShaderProgram
186 {
187 public:
188                                 VertexExpanderShader    (rr::GeometryShaderInputType inputType, rr::GeometryShaderOutputType outputType);
189
190         void            shadeVertices                   (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
191         void            shadeFragments                  (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
192         void            shadePrimitives                 (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const;
193
194 private:
195         size_t          calcOutputVertices              (rr::GeometryShaderInputType inputType) const;
196         std::string     genGeometrySource               (rr::GeometryShaderInputType inputType, rr::GeometryShaderOutputType outputType) const;
197 };
198
199 VertexExpanderShader::VertexExpanderShader (rr::GeometryShaderInputType inputType, rr::GeometryShaderOutputType outputType)
200         : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
201                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
202                                                         << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
203                                                         << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT)
204                                                         << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
205                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
206                                                         << sglr::pdec::VertexSource(s_commonShaderSourceVertex)
207                                                         << sglr::pdec::FragmentSource(s_commonShaderSourceFragment)
208                                                         << sglr::pdec::GeometryShaderDeclaration(inputType, outputType, calcOutputVertices(inputType))
209                                                         << sglr::pdec::GeometrySource(genGeometrySource(inputType, outputType).c_str()))
210 {
211 }
212
213 void VertexExpanderShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
214 {
215         for (int ndx = 0; ndx < numPackets; ++ndx)
216         {
217                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
218                 packets[ndx]->pointSize = 1.0f;
219                 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
220         }
221 }
222
223 void VertexExpanderShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
224 {
225         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
226         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
227                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx));
228 }
229
230 void VertexExpanderShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
231 {
232         DE_UNREF(invocationID);
233
234         for (int ndx = 0; ndx < numPackets; ++ndx)
235         for (int verticeNdx = 0; verticeNdx < verticesIn; ++verticeNdx)
236         {
237                 const tcu::Vec4 offsets[] =
238                 {
239                         tcu::Vec4(-0.07f, -0.01f, 0.0f, 0.0f),
240                         tcu::Vec4( 0.03f, -0.03f, 0.0f, 0.0f),
241                         tcu::Vec4(-0.01f,  0.08f, 0.0f, 0.0f)
242                 };
243                 const tcu::Vec4 yoffset = float(packets[ndx].primitiveIDIn) * tcu::Vec4(0.02f, 0.1f, 0, 0);
244
245                 // Create new primitive at every input vertice
246                 const rr::VertexPacket* vertex = packets[ndx].vertices[verticeNdx];
247
248                 output.EmitVertex(vertex->position + offsets[0] + yoffset, vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn);
249                 output.EmitVertex(vertex->position + offsets[1] + yoffset, vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn);
250                 output.EmitVertex(vertex->position + offsets[2] + yoffset, vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn);
251                 output.EndPrimitive();
252         }
253 }
254
255 size_t VertexExpanderShader::calcOutputVertices (rr::GeometryShaderInputType inputType) const
256 {
257         switch (inputType)
258         {
259                 case rr::GEOMETRYSHADERINPUTTYPE_POINTS:                                return 1 * 3;
260                 case rr::GEOMETRYSHADERINPUTTYPE_LINES:                                 return 2 * 3;
261                 case rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY:               return 4 * 3;
262                 case rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES:                             return 3 * 3;
263                 case rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY:   return 6 * 3;
264                 default:
265                         DE_ASSERT(DE_FALSE);
266                         return 0;
267         }
268 }
269
270 std::string     VertexExpanderShader::genGeometrySource (rr::GeometryShaderInputType inputType, rr::GeometryShaderOutputType outputType) const
271 {
272         std::ostringstream str;
273
274         str << "#version 310 es\n";
275         str << "#extension GL_EXT_geometry_shader : require\n";
276         str << "layout(" << inputTypeToGLString(inputType) << ") in;\n";
277         str << "layout(" << outputTypeToGLString(outputType) << ", max_vertices = " << calcOutputVertices(inputType) << ") out;";
278         str << "\n";
279         str << s_expandShaderSourceGeometryBody;
280
281         return str.str();
282 }
283
284 class VertexEmitterShader : public sglr::ShaderProgram
285 {
286 public:
287                                 VertexEmitterShader             (int emitCountA, int endCountA, int emitCountB, int endCountB, rr::GeometryShaderOutputType outputType);
288
289         void            shadeVertices                   (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
290         void            shadeFragments                  (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
291         void            shadePrimitives                 (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const;
292
293 private:
294         std::string     genGeometrySource               (int emitCountA, int endCountA, int emitCountB, int endCountB, rr::GeometryShaderOutputType outputType) const;
295
296         int                     m_emitCountA;
297         int                     m_endCountA;
298         int                     m_emitCountB;
299         int                     m_endCountB;
300 };
301
302 VertexEmitterShader::VertexEmitterShader (int emitCountA, int endCountA, int emitCountB, int endCountB, rr::GeometryShaderOutputType outputType)
303         : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
304                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
305                                                         << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
306                                                         << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT)
307                                                         << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
308                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
309                                                         << sglr::pdec::VertexSource(s_commonShaderSourceVertex)
310                                                         << sglr::pdec::FragmentSource(s_commonShaderSourceFragment)
311                                                         << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS, outputType, emitCountA + emitCountB)
312                                                         << sglr::pdec::GeometrySource(genGeometrySource(emitCountA, endCountA, emitCountB, endCountB, outputType).c_str()))
313         , m_emitCountA          (emitCountA)
314         , m_endCountA           (endCountA)
315         , m_emitCountB          (emitCountB)
316         , m_endCountB           (endCountB)
317 {
318 }
319
320 void VertexEmitterShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
321 {
322         for (int ndx = 0; ndx < numPackets; ++ndx)
323         {
324                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
325                 packets[ndx]->pointSize = 1.0f;
326                 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
327         }
328 }
329
330 void VertexEmitterShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
331 {
332         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
333         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
334                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx));
335 }
336
337 void VertexEmitterShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
338 {
339         DE_UNREF(verticesIn);
340         DE_UNREF(invocationID);
341
342         for (int ndx = 0; ndx < numPackets; ++ndx)
343         {
344                 const tcu::Vec4 positions[] =
345                 {
346                         tcu::Vec4(-0.5f,   0.5f, 0.0f, 0.0f),
347                         tcu::Vec4( 0.0f,   0.1f, 0.0f, 0.0f),
348                         tcu::Vec4( 0.5f,   0.5f, 0.0f, 0.0f),
349                         tcu::Vec4( 0.7f,  -0.2f, 0.0f, 0.0f),
350                         tcu::Vec4( 0.2f,   0.2f, 0.0f, 0.0f),
351                         tcu::Vec4( 0.4f,  -0.3f, 0.0f, 0.0f),
352                 };
353
354                 // Create new primitive at this point
355                 const rr::VertexPacket* vertex = packets[ndx].vertices[0];
356
357                 for (int i = 0; i < m_emitCountA; ++i)
358                         output.EmitVertex(vertex->position + positions[i], vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn);
359
360                 for (int i = 0; i < m_endCountA; ++i)
361                         output.EndPrimitive();
362
363                 for (int i = 0; i < m_emitCountB; ++i)
364                         output.EmitVertex(vertex->position + positions[m_emitCountA + i], vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn);
365
366                 for (int i = 0; i < m_endCountB; ++i)
367                         output.EndPrimitive();
368         }
369 }
370
371 std::string     VertexEmitterShader::genGeometrySource (int emitCountA, int endCountA, int emitCountB, int endCountB, rr::GeometryShaderOutputType outputType) const
372 {
373         std::ostringstream str;
374
375         str << "#version 310 es\n";
376         str << "#extension GL_EXT_geometry_shader : require\n";
377         str << "layout(points) in;\n";
378         str << "layout(" << outputTypeToGLString(outputType) << ", max_vertices = " << (emitCountA+emitCountB) << ") out;";
379         str << "\n";
380
381         str <<  "in highp vec4 v_geom_FragColor[];\n"
382                         "out highp vec4 v_frag_FragColor;\n"
383                         "\n"
384                         "void main (void)\n"
385                         "{\n"
386                         "       const highp vec4 position0 = vec4(-0.5,  0.5, 0.0, 0.0);\n"
387                         "       const highp vec4 position1 = vec4( 0.0,  0.1, 0.0, 0.0);\n"
388                         "       const highp vec4 position2 = vec4( 0.5,  0.5, 0.0, 0.0);\n"
389                         "       const highp vec4 position3 = vec4( 0.7, -0.2, 0.0, 0.0);\n"
390                         "       const highp vec4 position4 = vec4( 0.2,  0.2, 0.0, 0.0);\n"
391                         "       const highp vec4 position5 = vec4( 0.4, -0.3, 0.0, 0.0);\n"
392                         "\n";
393
394         for (int i = 0; i < emitCountA; ++i)
395                 str <<  "       gl_Position = gl_in[0].gl_Position + position" << i << ";\n"
396                                 "       gl_PrimitiveID = gl_PrimitiveIDIn;\n"
397                                 "       v_frag_FragColor = v_geom_FragColor[0];\n"
398                                 "       EmitVertex();\n"
399                                 "\n";
400
401         for (int i = 0; i < endCountA; ++i)
402                 str << "        EndPrimitive();\n";
403
404         for (int i = 0; i < emitCountB; ++i)
405                 str <<  "       gl_Position = gl_in[0].gl_Position + position" << (emitCountA + i) << ";\n"
406                                 "       gl_PrimitiveID = gl_PrimitiveIDIn;\n"
407                                 "       v_frag_FragColor = v_geom_FragColor[0];\n"
408                                 "       EmitVertex();\n"
409                                 "\n";
410
411         for (int i = 0; i < endCountB; ++i)
412                 str << "        EndPrimitive();\n";
413
414
415         str << "}\n";
416
417         return str.str();
418 }
419
420 class VertexVaryingShader : public sglr::ShaderProgram
421 {
422 public:
423                                                                                                 VertexVaryingShader             (int vertexOut, int geometryOut);
424
425         void                                                                            shadeVertices                   (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
426         void                                                                            shadeFragments                  (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
427         void                                                                            shadePrimitives                 (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const;
428
429 private:
430         static sglr::pdec::ShaderProgramDeclaration genProgramDeclaration       (int vertexOut, int geometryOut);
431
432         const int                                                                       m_vertexOut;
433         const int                                                                       m_geometryOut;
434 };
435
436 VertexVaryingShader::VertexVaryingShader (int vertexOut, int geometryOut)
437         : sglr::ShaderProgram   (genProgramDeclaration(vertexOut, geometryOut))
438         , m_vertexOut                   (vertexOut)
439         , m_geometryOut                 (geometryOut)
440 {
441 }
442
443 void VertexVaryingShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
444 {
445         // vertex shader is no-op
446         if (m_vertexOut == -1)
447                 return;
448
449         for (int ndx = 0; ndx < numPackets; ++ndx)
450         {
451                 const tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
452
453                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
454                 packets[ndx]->pointSize = 1.0f;
455
456                 switch (m_vertexOut)
457                 {
458                         case 0:
459                                 break;
460
461                         case 1:
462                                 packets[ndx]->outputs[0] = color;
463                                 break;
464
465                         case 2:
466                                 packets[ndx]->outputs[0] = color * 0.5f;
467                                 packets[ndx]->outputs[1] = color.swizzle(2,1,0,3) * 0.5f;
468                                 break;
469
470                         default:
471                                 DE_ASSERT(DE_FALSE);
472                 }
473         }
474 }
475
476 void VertexVaryingShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
477 {
478         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
479         {
480                 switch (m_geometryOut)
481                 {
482                         case 0:
483                                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
484                                         rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
485                                 break;
486
487                         case 1:
488                                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
489                                         rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx));
490                                 break;
491
492                         case 2:
493                                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
494                                         rr::writeFragmentOutput(context, packetNdx, fragNdx, 0,   rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx)
495                                                                                                 + rr::readTriangleVarying<float>(packets[packetNdx], context, 1, fragNdx).swizzle(1, 0, 2, 3));
496                                 break;
497
498                         default:
499                                 DE_ASSERT(DE_FALSE);
500                 }
501         }
502 }
503
504 void VertexVaryingShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
505 {
506         DE_UNREF(invocationID);
507
508         const tcu::Vec4 vertexOffset(-0.2f, -0.2f, 0, 0);
509
510         if (m_vertexOut == -1)
511         {
512                 // vertex is a no-op
513                 const tcu::Vec4 inputColor = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
514                 rr::GenericVec4 outputs[2];
515
516                 // output color
517                 switch (m_geometryOut)
518                 {
519                         case 0:
520                                 break;
521
522                         case 1:
523                                 outputs[0] = inputColor;
524                                 break;
525
526                         case 2:
527                                 outputs[0] = inputColor * 0.5f;
528                                 outputs[1] = inputColor.swizzle(1, 0, 2, 3) * 0.5f;
529                                 break;
530
531                         default:
532                                 DE_ASSERT(DE_FALSE);
533                 }
534
535                 for (int ndx = 0; ndx < numPackets; ++ndx)
536                 {
537                         output.EmitVertex(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) + vertexOffset, 1.0f, outputs, packets[ndx].primitiveIDIn);
538                         output.EmitVertex(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f) + vertexOffset, 1.0f, outputs, packets[ndx].primitiveIDIn);
539                         output.EmitVertex(tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f) + vertexOffset, 1.0f, outputs, packets[ndx].primitiveIDIn);
540                         output.EndPrimitive();
541                 }
542         }
543         else
544         {
545                 // vertex is not a no-op
546                 for (int ndx = 0; ndx < numPackets; ++ndx)
547                 {
548                         for (int verticeNdx = 0; verticeNdx < verticesIn; ++verticeNdx)
549                         {
550                                 tcu::Vec4               inputColor;
551                                 rr::GenericVec4 outputs[2];
552
553                                 // input color
554                                 switch (m_vertexOut)
555                                 {
556                                         case 0:
557                                                 inputColor = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
558                                                 break;
559
560                                         case 1:
561                                                 inputColor = packets[ndx].vertices[verticeNdx]->outputs[0].get<float>();
562                                                 break;
563
564                                         case 2:
565                                                 inputColor = (packets[ndx].vertices[verticeNdx]->outputs[0].get<float>() * 0.5f)
566                                                                    + (packets[ndx].vertices[verticeNdx]->outputs[1].get<float>().swizzle(2, 1, 0, 3) * 0.5f);
567                                                 break;
568
569                                         default:
570                                                 DE_ASSERT(DE_FALSE);
571                                 }
572
573                                 // output color
574                                 switch (m_geometryOut)
575                                 {
576                                         case 0:
577                                                 break;
578
579                                         case 1:
580                                                 outputs[0] = inputColor;
581                                                 break;
582
583                                         case 2:
584                                                 outputs[0] = inputColor * 0.5f;
585                                                 outputs[1] = inputColor.swizzle(1, 0, 2, 3) * 0.5f;
586                                                 break;
587
588                                         default:
589                                                 DE_ASSERT(DE_FALSE);
590                                 }
591
592                                 output.EmitVertex(packets[ndx].vertices[verticeNdx]->position + vertexOffset, packets[ndx].vertices[verticeNdx]->pointSize, outputs, packets[ndx].primitiveIDIn);
593                         }
594                         output.EndPrimitive();
595                 }
596         }
597 }
598
599 sglr::pdec::ShaderProgramDeclaration VertexVaryingShader::genProgramDeclaration (int vertexOut, int geometryOut)
600 {
601         sglr::pdec::ShaderProgramDeclaration    decl;
602         std::ostringstream                                              vertexSource;
603         std::ostringstream                                              fragmentSource;
604         std::ostringstream                                              geometrySource;
605
606         decl
607                 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
608                 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT);
609
610         for (int i = 0; i < vertexOut; ++i)
611                 decl << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT);
612         for (int i = 0; i < geometryOut; ++i)
613                 decl << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
614
615         decl
616                 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
617                 << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES, rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP, 3);
618
619         // vertexSource
620
621         vertexSource << "#version 310 es\n"
622                                         "in highp vec4 a_position;\n"
623                                         "in highp vec4 a_color;\n";
624
625         // no-op case?
626         if (vertexOut == -1)
627         {
628                 vertexSource << "void main (void)\n"
629                                                 "{\n"
630                                                 "}\n";
631         }
632         else
633         {
634                 for (int i = 0; i < vertexOut; ++i)
635                         vertexSource << "out highp vec4 v_geom_" << i << ";\n";
636
637                 vertexSource << "void main (void)\n"
638                                                 "{\n"
639                                                 "\tgl_Position = a_position;\n"
640                                                 "\tgl_PointSize = 1.0;\n";
641                 switch (vertexOut)
642                 {
643                         case 0:
644                                 break;
645
646                         case 1:
647                                 vertexSource << "\tv_geom_0 = a_color;\n";
648                                 break;
649
650                         case 2:
651                                 vertexSource << "\tv_geom_0 = a_color * 0.5;\n";
652                                 vertexSource << "\tv_geom_1 = a_color.zyxw * 0.5;\n";
653                                 break;
654
655                         default:
656                                 DE_ASSERT(DE_FALSE);
657                 }
658                 vertexSource << "}\n";
659         }
660
661         // fragmentSource
662
663         fragmentSource <<       "#version 310 es\n"
664                                                 "layout(location = 0) out mediump vec4 fragColor;\n";
665
666         for (int i = 0; i < geometryOut; ++i)
667                 fragmentSource << "in mediump vec4 v_frag_" << i << ";\n";
668
669         fragmentSource <<       "void main (void)\n"
670                                                 "{\n";
671         switch (geometryOut)
672         {
673                 case 0:
674                         fragmentSource << "\tfragColor = vec4(1.0, 0.0, 0.0, 1.0);\n";
675                         break;
676
677                 case 1:
678                         fragmentSource << "\tfragColor = v_frag_0;\n";
679                         break;
680
681                 case 2:
682                         fragmentSource << "\tfragColor = v_frag_0 + v_frag_1.yxzw;\n";
683                         break;
684
685                 default:
686                         DE_ASSERT(DE_FALSE);
687         }
688         fragmentSource << "}\n";
689
690         // geometrySource
691
692         geometrySource <<       "#version 310 es\n"
693                                                 "#extension GL_EXT_geometry_shader : require\n"
694                                                 "layout(triangles) in;\n"
695                                                 "layout(triangle_strip, max_vertices = 3) out;\n";
696
697         for (int i = 0; i < vertexOut; ++i)
698                 geometrySource << "in highp vec4 v_geom_" << i << "[];\n";
699         for (int i = 0; i < geometryOut; ++i)
700                 geometrySource << "out highp vec4 v_frag_" << i << ";\n";
701
702         geometrySource <<       "void main (void)\n"
703                                                 "{\n"
704                                                 "\thighp vec4 offset = vec4(-0.2, -0.2, 0.0, 0.0);\n"
705                                                 "\thighp vec4 inputColor;\n\n";
706
707         for (int vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
708         {
709                 if (vertexOut == -1)
710                 {
711                         // vertex is a no-op
712                         geometrySource <<       "\tinputColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
713                                                                 "\tgl_Position = vec4(" << ((vertexNdx==0) ? ("0.0, 0.0") : ((vertexNdx==1) ? ("1.0, 0.0") : ("1.0, 1.0"))) << ", 0.0, 1.0) + offset;\n"
714                                                                 "\tgl_PrimitiveID = gl_PrimitiveIDIn;\n";
715                 }
716                 else
717                 {
718                         switch (vertexOut)
719                         {
720                                 case 0:
721                                         geometrySource << "\tinputColor = vec4(1.0, 0.0, 0.0, 1.0);\n";
722                                         break;
723
724                                 case 1:
725                                         geometrySource << "\tinputColor = v_geom_0[" << vertexNdx << "];\n";
726                                         break;
727
728                                 case 2:
729                                         geometrySource << "\tinputColor = v_geom_0[" << vertexNdx << "] * 0.5 + v_geom_1[" << vertexNdx << "].zyxw * 0.5;\n";
730                                         break;
731
732                                 default:
733                                         DE_ASSERT(DE_FALSE);
734                         }
735                         geometrySource <<       "\tgl_Position = gl_in[" << vertexNdx << "].gl_Position + offset;\n"
736                                                                 "\tgl_PrimitiveID = gl_PrimitiveIDIn;\n";
737                 }
738
739                 switch (geometryOut)
740                 {
741                         case 0:
742                                 break;
743
744                         case 1:
745                                 geometrySource << "\tv_frag_0 = inputColor;\n";
746                                 break;
747
748                         case 2:
749                                 geometrySource << "\tv_frag_0 = inputColor * 0.5;\n";
750                                 geometrySource << "\tv_frag_1 = inputColor.yxzw * 0.5;\n";
751                                 break;
752
753                         default:
754                                 DE_ASSERT(DE_FALSE);
755                 }
756
757                 geometrySource << "\tEmitVertex();\n\n";
758         }
759
760         geometrySource <<       "\tEndPrimitive();\n"
761                                                 "}\n";
762
763         decl
764                 << sglr::pdec::VertexSource(vertexSource.str().c_str())
765                 << sglr::pdec::FragmentSource(fragmentSource.str().c_str())
766                 << sglr::pdec::GeometrySource(geometrySource.str().c_str());
767         return decl;
768 }
769
770 class OutputCountShader : public sglr::ShaderProgram
771 {
772 public:
773                                                                         OutputCountShader               (const OutputCountPatternSpec& spec);
774
775         void                                                    shadeVertices                   (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
776         void                                                    shadeFragments                  (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
777         void                                                    shadePrimitives                 (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const;
778
779 private:
780         std::string                                             genGeometrySource               (const OutputCountPatternSpec& spec) const;
781         size_t                                                  getPatternEmitCount             (const OutputCountPatternSpec& spec) const;
782
783         const int                                               m_patternLength;
784         const int                                               m_patternMaxEmitCount;
785         const OutputCountPatternSpec    m_spec;
786 };
787
788 OutputCountShader::OutputCountShader (const OutputCountPatternSpec& spec)
789         : sglr::ShaderProgram   (sglr::pdec::ShaderProgramDeclaration()
790                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
791                                                         << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
792                                                         << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT)
793                                                         << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
794                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
795                                                         << sglr::pdec::VertexSource(s_commonShaderSourceVertex)
796                                                         << sglr::pdec::FragmentSource(s_commonShaderSourceFragment)
797                                                         << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS, rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP, getPatternEmitCount(spec))
798                                                         << sglr::pdec::GeometrySource(genGeometrySource(spec).c_str()))
799         , m_patternLength               ((int)spec.pattern.size())
800         , m_patternMaxEmitCount ((int)getPatternEmitCount(spec))
801         , m_spec                                (spec)
802 {
803 }
804
805 void OutputCountShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
806 {
807         for (int ndx = 0; ndx < numPackets; ++ndx)
808         {
809                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
810                 packets[ndx]->pointSize = 1.0f;
811                 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
812         }
813 }
814
815 void OutputCountShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
816 {
817         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
818         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
819                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx));
820 }
821
822 void OutputCountShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
823 {
824         DE_UNREF(verticesIn);
825         DE_UNREF(invocationID);
826
827         const float rowHeight   = 2.0f / (float)m_patternLength;
828         const float colWidth    = 2.0f / (float)m_patternMaxEmitCount;
829
830         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
831         {
832                 // Create triangle strip at this point
833                 const rr::VertexPacket* vertex          = packets[packetNdx].vertices[0];
834                 const int                               emitCount       = m_spec.pattern[packets[packetNdx].primitiveIDIn];
835
836                 for (int ndx = 0; ndx < emitCount / 2; ++ndx)
837                 {
838                         output.EmitVertex(vertex->position + tcu::Vec4(2 * (float)ndx * colWidth, 0.0,       0.0, 0.0), vertex->pointSize, vertex->outputs, packets[packetNdx].primitiveIDIn);
839                         output.EmitVertex(vertex->position + tcu::Vec4(2 * (float)ndx * colWidth, rowHeight, 0.0, 0.0), vertex->pointSize, vertex->outputs, packets[packetNdx].primitiveIDIn);
840                 }
841                 output.EndPrimitive();
842         }
843 }
844
845 std::string     OutputCountShader::genGeometrySource (const OutputCountPatternSpec& spec) const
846 {
847         std::ostringstream str;
848
849         // draw row with a triangle strip, always make rectangles
850         for (int ndx = 0; ndx < (int)spec.pattern.size(); ++ndx)
851                 DE_ASSERT(spec.pattern[ndx] % 2 == 0);
852
853         str << "#version 310 es\n";
854         str << "#extension GL_EXT_geometry_shader : require\n";
855         str << "layout(points) in;\n";
856         str << "layout(triangle_strip, max_vertices = " << getPatternEmitCount(spec) << ") out;";
857         str << "\n";
858
859         str <<  "in highp vec4 v_geom_FragColor[];\n"
860                         "out highp vec4 v_frag_FragColor;\n"
861                         "\n"
862                         "void main (void)\n"
863                         "{\n"
864                         "       const highp float rowHeight = 2.0 / float(" << spec.pattern.size() << ");\n"
865                         "       const highp float colWidth = 2.0 / float(" << getPatternEmitCount(spec) << ");\n"
866                         "\n";
867
868         str <<  "       highp int emitCount = ";
869         for (int ndx = 0; ndx < (int)spec.pattern.size() - 1; ++ndx)
870                 str << "(gl_PrimitiveIDIn == " << ndx << ") ? (" << spec.pattern[ndx] << ") : (";
871         str <<  spec.pattern[(int)spec.pattern.size() - 1]
872                 <<      ((spec.pattern.size() == 1) ? ("") : (")"))
873                 <<      ";\n";
874
875         str <<  "       for (highp int ndx = 0; ndx < emitCount / 2; ndx++)\n"
876                         "       {\n"
877                         "               gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, 0.0, 0.0, 0.0);\n"
878                         "               v_frag_FragColor = v_geom_FragColor[0];\n"
879                         "               EmitVertex();\n"
880                         "\n"
881                         "               gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, rowHeight, 0.0, 0.0);\n"
882                         "               v_frag_FragColor = v_geom_FragColor[0];\n"
883                         "               EmitVertex();\n"
884                         "       }\n"
885                         "}\n";
886
887         return str.str();
888 }
889
890 size_t OutputCountShader::getPatternEmitCount (const OutputCountPatternSpec& spec) const
891 {
892         return *std::max_element(spec.pattern.begin(), spec.pattern.end());
893 }
894
895 class BuiltinVariableShader : public sglr::ShaderProgram
896 {
897 public:
898         enum VariableTest
899         {
900                 TEST_POINT_SIZE = 0,
901                 TEST_PRIMITIVE_ID_IN,
902                 TEST_PRIMITIVE_ID,
903
904                 TEST_LAST
905         };
906
907                                                 BuiltinVariableShader   (VariableTest test);
908
909         void                            shadeVertices                   (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
910         void                            shadeFragments                  (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
911         void                            shadePrimitives                 (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const;
912
913         static const char*      getTestAttributeName    (VariableTest test);
914
915 private:
916         std::string                     genGeometrySource               (VariableTest test) const;
917         std::string                     genVertexSource                 (VariableTest test) const;
918         std::string                     genFragmentSource               (VariableTest test) const;
919
920         const VariableTest      m_test;
921 };
922
923 BuiltinVariableShader::BuiltinVariableShader (VariableTest test)
924         : sglr::ShaderProgram   (sglr::pdec::ShaderProgramDeclaration()
925                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
926                                                         << sglr::pdec::VertexAttribute(getTestAttributeName(test), rr::GENERICVECTYPE_FLOAT)
927                                                         << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT)
928                                                         << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
929                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
930                                                         << sglr::pdec::VertexSource(genVertexSource(test))
931                                                         << sglr::pdec::FragmentSource(genFragmentSource(test))
932                                                         << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS,
933                                                                                                                                          ((test == TEST_POINT_SIZE) ? (rr::GEOMETRYSHADEROUTPUTTYPE_POINTS) : (rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP)),
934                                                                                                                                          ((test == TEST_POINT_SIZE) ? (1) : (3)))
935                                                         << sglr::pdec::GeometrySource(genGeometrySource(test).c_str()))
936         , m_test                                (test)
937 {
938 }
939
940 void BuiltinVariableShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
941 {
942         for (int ndx = 0; ndx < numPackets; ++ndx)
943         {
944                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
945                 packets[ndx]->pointSize = 1.0f;
946                 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
947         }
948 }
949
950 void BuiltinVariableShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
951 {
952         const tcu::Vec4 red                     = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
953         const tcu::Vec4 green           = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
954         const tcu::Vec4 blue            = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
955         const tcu::Vec4 yellow          = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
956         const tcu::Vec4 colors[4]       = { yellow, red, green, blue };
957
958         if (m_test == TEST_POINT_SIZE || m_test == TEST_PRIMITIVE_ID_IN)
959         {
960                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
961                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
962                         rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx));
963         }
964         else if (m_test == TEST_PRIMITIVE_ID)
965         {
966                 const tcu::Vec4 color = colors[context.primitiveID % 4];
967
968                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
969                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
970                         rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
971         }
972         else
973                 DE_ASSERT(DE_FALSE);
974 }
975
976 void BuiltinVariableShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
977 {
978         DE_UNREF(verticesIn);
979         DE_UNREF(invocationID);
980
981         const tcu::Vec4 red                     = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
982         const tcu::Vec4 green           = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
983         const tcu::Vec4 blue            = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
984         const tcu::Vec4 yellow          = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
985         const tcu::Vec4 colors[4]       = { red, green, blue, yellow };
986
987         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
988         {
989                 const rr::VertexPacket* vertex = packets[packetNdx].vertices[0];
990
991                 if (m_test == TEST_POINT_SIZE)
992                 {
993                         rr::GenericVec4 fragColor;
994                         const float             pointSize = vertex->outputs[0].get<float>().x() + 1.0f;
995
996                         fragColor = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
997                         output.EmitVertex(vertex->position, pointSize, &fragColor, packets[packetNdx].primitiveIDIn);
998                 }
999                 else if (m_test == TEST_PRIMITIVE_ID_IN)
1000                 {
1001                         rr::GenericVec4 fragColor;
1002                         fragColor = colors[packets[packetNdx].primitiveIDIn % 4];
1003
1004                         output.EmitVertex(vertex->position + tcu::Vec4(0.05f, 0.0f,  0.0f, 0.0f), 1.0f, &fragColor, packets[packetNdx].primitiveIDIn);
1005                         output.EmitVertex(vertex->position - tcu::Vec4(0.05f, 0.0f,  0.0f, 0.0f), 1.0f, &fragColor, packets[packetNdx].primitiveIDIn);
1006                         output.EmitVertex(vertex->position + tcu::Vec4(0.0f,  0.05f, 0.0f, 0.0f), 1.0f, &fragColor, packets[packetNdx].primitiveIDIn);
1007                 }
1008                 else if (m_test == TEST_PRIMITIVE_ID)
1009                 {
1010                         const int primitiveID = (int)deFloatFloor(vertex->outputs[0].get<float>().x()) + 3;
1011
1012                         output.EmitVertex(vertex->position + tcu::Vec4(0.05f, 0.0f,  0.0f, 0.0f), 1.0f, vertex->outputs, primitiveID);
1013                         output.EmitVertex(vertex->position - tcu::Vec4(0.05f, 0.0f,  0.0f, 0.0f), 1.0f, vertex->outputs, primitiveID);
1014                         output.EmitVertex(vertex->position + tcu::Vec4(0.0f,  0.05f, 0.0f, 0.0f), 1.0f, vertex->outputs, primitiveID);
1015                 }
1016                 else
1017                         DE_ASSERT(DE_FALSE);
1018
1019                 output.EndPrimitive();
1020         }
1021 }
1022
1023 const char* BuiltinVariableShader::getTestAttributeName (VariableTest test)
1024 {
1025         switch (test)
1026         {
1027                 case TEST_POINT_SIZE:                   return "a_pointSize";
1028                 case TEST_PRIMITIVE_ID_IN:              return "";
1029                 case TEST_PRIMITIVE_ID:                 return "a_primitiveID";
1030                 default:
1031                         DE_ASSERT(DE_FALSE);
1032                         return "";
1033         }
1034 }
1035
1036 std::string BuiltinVariableShader::genGeometrySource (VariableTest test) const
1037 {
1038         std::ostringstream buf;
1039
1040         buf <<  "#version 310 es\n"
1041                         "#extension GL_EXT_geometry_shader : require\n";
1042
1043         if (test == TEST_POINT_SIZE)
1044                 buf << "#extension GL_EXT_geometry_point_size : require\n";
1045
1046         buf << "layout(points) in;\n";
1047
1048         if (test == TEST_POINT_SIZE)
1049                 buf << "layout(points, max_vertices = 1) out;\n";
1050         else
1051                 buf << "layout(triangle_strip, max_vertices = 3) out;\n";
1052
1053         if (test == TEST_POINT_SIZE)
1054                 buf << "in highp vec4 v_geom_pointSize[];\n";
1055         else if (test == TEST_PRIMITIVE_ID)
1056                 buf << "in highp vec4 v_geom_primitiveID[];\n";
1057
1058         if (test != TEST_PRIMITIVE_ID)
1059                 buf << "out highp vec4 v_frag_FragColor;\n";
1060
1061         buf <<  "\n"
1062                         "void main (void)\n"
1063                         "{\n";
1064
1065         if (test == TEST_POINT_SIZE)
1066         {
1067                 buf <<  "       gl_Position = gl_in[0].gl_Position;\n"
1068                                 "       gl_PointSize = v_geom_pointSize[0].x + 1.0;\n"
1069                                 "       v_frag_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
1070                                 "       EmitVertex();\n";
1071         }
1072         else if (test == TEST_PRIMITIVE_ID_IN)
1073         {
1074                 buf <<  "       const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
1075                                 "       const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
1076                                 "       const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
1077                                 "       const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
1078                                 "       const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n"
1079                                 "\n"
1080                                 "       gl_Position = gl_in[0].gl_Position + vec4(0.05, 0.0, 0.0, 0.0);\n"
1081                                 "       v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n"
1082                                 "       EmitVertex();\n"
1083                                 "\n"
1084                                 "       gl_Position = gl_in[0].gl_Position - vec4(0.05, 0.0, 0.0, 0.0);\n"
1085                                 "       v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n"
1086                                 "       EmitVertex();\n"
1087                                 "\n"
1088                                 "       gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.05, 0.0, 0.0);\n"
1089                                 "       v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n"
1090                                 "       EmitVertex();\n";
1091         }
1092         else if (test == TEST_PRIMITIVE_ID)
1093         {
1094                 buf <<  "       gl_Position = gl_in[0].gl_Position + vec4(0.05, 0.0, 0.0, 0.0);\n"
1095                                 "       gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
1096                                 "       EmitVertex();\n"
1097                                 "\n"
1098                                 "       gl_Position = gl_in[0].gl_Position - vec4(0.05, 0.0, 0.0, 0.0);\n"
1099                                 "       gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
1100                                 "       EmitVertex();\n"
1101                                 "\n"
1102                                 "       gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.05, 0.0, 0.0);\n"
1103                                 "       gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
1104                                 "       EmitVertex();\n"
1105                                 "\n";
1106         }
1107         else
1108                 DE_ASSERT(DE_FALSE);
1109
1110         buf << "}\n";
1111
1112         return buf.str();
1113 }
1114
1115 std::string BuiltinVariableShader::genVertexSource (VariableTest test) const
1116 {
1117         std::ostringstream buf;
1118
1119         buf <<  "#version 310 es\n"
1120                         "in highp vec4 a_position;\n";
1121
1122         if (test == TEST_POINT_SIZE)
1123                 buf << "in highp vec4 a_pointSize;\n";
1124         else if (test == TEST_PRIMITIVE_ID)
1125                 buf << "in highp vec4 a_primitiveID;\n";
1126
1127         if (test == TEST_POINT_SIZE)
1128                 buf << "out highp vec4 v_geom_pointSize;\n";
1129         else if (test == TEST_PRIMITIVE_ID)
1130                 buf << "out highp vec4 v_geom_primitiveID;\n";
1131
1132         buf <<  "void main (void)\n"
1133                         "{\n"
1134                         "       gl_Position = a_position;\n"
1135                         "       gl_PointSize = 1.0;\n";
1136
1137         if (test == TEST_POINT_SIZE)
1138                 buf << "        v_geom_pointSize = a_pointSize;\n";
1139         else if (test == TEST_PRIMITIVE_ID)
1140                 buf << "        v_geom_primitiveID = a_primitiveID;\n";
1141
1142         buf <<  "}\n";
1143
1144         return buf.str();
1145 }
1146
1147 std::string BuiltinVariableShader::genFragmentSource (VariableTest test) const
1148 {
1149         if (test == TEST_POINT_SIZE || test == TEST_PRIMITIVE_ID_IN)
1150                 return s_commonShaderSourceFragment;
1151         else if (test == TEST_PRIMITIVE_ID)
1152         {
1153                 return  "#version 310 es\n"
1154                                 "#extension GL_EXT_geometry_shader : require\n"
1155                                 "layout(location = 0) out mediump vec4 fragColor;\n"
1156                                 "void main (void)\n"
1157                                 "{\n"
1158                                 "       const mediump vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
1159                                 "       const mediump vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
1160                                 "       const mediump vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
1161                                 "       const mediump vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
1162                                 "       const mediump vec4 colors[4] = vec4[4](yellow, red, green, blue);\n"
1163                                 "       fragColor = colors[gl_PrimitiveID % 4];\n"
1164                                 "}\n";
1165         }
1166         else
1167         {
1168                 DE_ASSERT(DE_FALSE);
1169                 return DE_NULL;
1170         }
1171 }
1172
1173 class VaryingOutputCountShader : public sglr::ShaderProgram
1174 {
1175 public:
1176         enum VaryingSource
1177         {
1178                 READ_ATTRIBUTE = 0,
1179                 READ_UNIFORM,
1180                 READ_TEXTURE,
1181
1182                 READ_LAST
1183         };
1184
1185         enum
1186         {
1187                 EMIT_COUNT_VERTEX_0 = 6,
1188                 EMIT_COUNT_VERTEX_1 = 0,
1189                 EMIT_COUNT_VERTEX_2 = -1,
1190                 EMIT_COUNT_VERTEX_3 = 10,
1191         };
1192
1193                                                                 VaryingOutputCountShader        (VaryingSource source, int maxEmitCount, bool instanced);
1194
1195         void                                            shadeVertices                           (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
1196         void                                            shadeFragments                          (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
1197         void                                            shadePrimitives                         (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const;
1198
1199         static const char*                      getAttributeName                        (VaryingSource test);
1200
1201 private:
1202         static std::string                      genGeometrySource                       (VaryingSource test, int maxEmitCount, bool instanced);
1203         static std::string                      genVertexSource                         (VaryingSource test);
1204
1205         const VaryingSource                     m_test;
1206         const sglr::UniformSlot&        m_sampler;
1207         const sglr::UniformSlot&        m_emitCount;
1208         const int                                       m_maxEmitCount;
1209         const bool                                      m_instanced;
1210 };
1211
1212 VaryingOutputCountShader::VaryingOutputCountShader (VaryingSource source, int maxEmitCount, bool instanced)
1213         : sglr::ShaderProgram   (sglr::pdec::ShaderProgramDeclaration()
1214                                                         << sglr::pdec::Uniform("u_sampler", glu::TYPE_SAMPLER_2D)
1215                                                         << sglr::pdec::Uniform("u_emitCount", glu::TYPE_INT_VEC4)
1216                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
1217                                                         << sglr::pdec::VertexAttribute(getAttributeName(source), rr::GENERICVECTYPE_FLOAT)
1218                                                         << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT)
1219                                                         << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
1220                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
1221                                                         << sglr::pdec::VertexSource(genVertexSource(source))
1222                                                         << sglr::pdec::FragmentSource(s_commonShaderSourceFragment)
1223                                                         << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS,
1224                                                                                                                                          rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP,
1225                                                                                                                                          maxEmitCount,
1226                                                                                                                                          (instanced) ? (4) : (1))
1227                                                         << sglr::pdec::GeometrySource(genGeometrySource(source, maxEmitCount, instanced).c_str()))
1228         , m_test                                (source)
1229         , m_sampler                             (getUniformByName("u_sampler"))
1230         , m_emitCount                   (getUniformByName("u_emitCount"))
1231         , m_maxEmitCount                (maxEmitCount)
1232         , m_instanced                   (instanced)
1233 {
1234 }
1235
1236 void VaryingOutputCountShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
1237 {
1238         for (int ndx = 0; ndx < numPackets; ++ndx)
1239         {
1240                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
1241                 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
1242         }
1243 }
1244
1245 void VaryingOutputCountShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
1246 {
1247         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1248         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
1249                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx));
1250 }
1251
1252 void VaryingOutputCountShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
1253 {
1254         DE_UNREF(verticesIn);
1255
1256         const tcu::Vec4 red                     = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1257         const tcu::Vec4 green           = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1258         const tcu::Vec4 blue            = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
1259         const tcu::Vec4 yellow          = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
1260         const tcu::Vec4 colors[4]       = { red, green, blue, yellow };
1261
1262         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1263         {
1264                 const rr::VertexPacket* vertex          = packets[packetNdx].vertices[0];
1265                 int                                             emitCount       = 0;
1266                 tcu::Vec4                               color           = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
1267
1268                 if (m_test == READ_ATTRIBUTE)
1269                 {
1270                         emitCount = (int)vertex->outputs[0].get<float>()[(m_instanced) ? (invocationID) : (0)];
1271                         color = tcu::Vec4((emitCount < 10) ? (0.0f) : (1.0f), (emitCount > 10) ? (0.0f) : (1.0f), 1.0f, 1.0f);
1272                 }
1273                 else if (m_test == READ_UNIFORM)
1274                 {
1275                         const int primitiveNdx = (m_instanced) ? (invocationID) : ((int)vertex->outputs[0].get<float>().x());
1276
1277                         DE_ASSERT(primitiveNdx >= 0);
1278                         DE_ASSERT(primitiveNdx < 4);
1279
1280                         emitCount = m_emitCount.value.i4[primitiveNdx];
1281                         color = colors[primitiveNdx];
1282                 }
1283                 else if (m_test == READ_TEXTURE)
1284                 {
1285                         const int                       primitiveNdx    = (m_instanced) ? (invocationID) : ((int)vertex->outputs[0].get<float>().x());
1286                         const tcu::Vec2         texCoord                = tcu::Vec2(1.0f / 8.0f + (float)primitiveNdx / 4.0f, 0.5f);
1287                         const tcu::Vec4         texColor                = m_sampler.sampler.tex2D->sample(texCoord.x(), texCoord.y(), 0.0f);
1288
1289                         DE_ASSERT(primitiveNdx >= 0);
1290                         DE_ASSERT(primitiveNdx < 4);
1291
1292                         color = colors[primitiveNdx];
1293                         emitCount = 0;
1294
1295                         if (texColor.x() > 0.0f)
1296                                 emitCount += (EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_0);
1297                         if (texColor.y() > 0.0f)
1298                                 emitCount += (EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_1);
1299                         if (texColor.z() > 0.0f)
1300                                 emitCount += (EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_2);
1301                         if (texColor.w() > 0.0f)
1302                                 emitCount += (EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_3);
1303                 }
1304                 else
1305                         DE_ASSERT(DE_FALSE);
1306
1307                 for (int ndx = 0; ndx < (int)emitCount / 2; ++ndx)
1308                 {
1309                         const float             angle                   = (float(ndx) + 0.5f) / float(emitCount / 2) * 3.142f;
1310                         const tcu::Vec4 basePosition    = (m_instanced) ?
1311                                                                                                 (vertex->position + tcu::Vec4(deFloatCos(float(invocationID)), deFloatSin(float(invocationID)), 0.0f, 0.0f) * 0.5f) :
1312                                                                                                 (vertex->position);
1313                         const tcu::Vec4 position0               = basePosition + tcu::Vec4(deFloatCos(angle),  deFloatSin(angle), 0.0f, 0.0f) * 0.15f;
1314                         const tcu::Vec4 position1               = basePosition + tcu::Vec4(deFloatCos(angle), -deFloatSin(angle), 0.0f, 0.0f) * 0.15f;
1315                         rr::GenericVec4 fragColor;
1316
1317                         fragColor = color;
1318
1319                         output.EmitVertex(position0, 0.0f, &fragColor, packets[packetNdx].primitiveIDIn);
1320                         output.EmitVertex(position1, 0.0f, &fragColor, packets[packetNdx].primitiveIDIn);
1321                 }
1322
1323                 output.EndPrimitive();
1324         }
1325 }
1326
1327 const char* VaryingOutputCountShader::getAttributeName (VaryingSource test)
1328 {
1329         switch (test)
1330         {
1331                 case READ_ATTRIBUTE:    return "a_emitCount";
1332                 case READ_UNIFORM:              return "a_vertexNdx";
1333                 case READ_TEXTURE:              return "a_vertexNdx";
1334                 default:
1335                         DE_ASSERT(DE_FALSE);
1336                         return "";
1337         }
1338 }
1339
1340 std::string VaryingOutputCountShader::genGeometrySource (VaryingSource test, int maxEmitCount, bool instanced)
1341 {
1342         std::ostringstream buf;
1343
1344         buf <<  "#version 310 es\n"
1345                         "#extension GL_EXT_geometry_shader : require\n"
1346                         "layout(points" << ((instanced) ? (",invocations=4") : ("")) << ") in;\n"
1347                         "layout(triangle_strip, max_vertices = " << maxEmitCount << ") out;\n";
1348
1349         if (test == READ_ATTRIBUTE)
1350                 buf <<  "in highp vec4 v_geom_emitCount[];\n";
1351         else if (test == READ_UNIFORM)
1352                 buf <<  "in highp vec4 v_geom_vertexNdx[];\n"
1353                                 "uniform highp ivec4 u_emitCount;\n";
1354         else
1355                 buf <<  "in highp vec4 v_geom_vertexNdx[];\n"
1356                                 "uniform highp sampler2D u_sampler;\n";
1357
1358         buf <<  "out highp vec4 v_frag_FragColor;\n"
1359                         "\n"
1360                         "void main (void)\n"
1361                         "{\n";
1362
1363         // emit count
1364
1365         if (test == READ_ATTRIBUTE)
1366         {
1367                 buf <<  "       highp vec4 attrEmitCounts = v_geom_emitCount[0];\n"
1368                                 "       mediump int emitCount = int(attrEmitCounts[" << ((instanced) ? ("gl_InvocationID") : ("0")) << "]);\n";
1369         }
1370         else if (test == READ_UNIFORM)
1371         {
1372                 buf <<  "       mediump int primitiveNdx = " << ((instanced) ? ("gl_InvocationID") : ("int(v_geom_vertexNdx[0].x)")) << ";\n"
1373                                 "       mediump int emitCount = u_emitCount[primitiveNdx];\n";
1374         }
1375         else if (test == READ_TEXTURE)
1376         {
1377                 buf <<  "       highp float primitiveNdx = " << ((instanced) ? ("float(gl_InvocationID)") : ("v_geom_vertexNdx[0].x")) << ";\n"
1378                                 "       highp vec2 texCoord = vec2(1.0 / 8.0 + primitiveNdx / 4.0, 0.5);\n"
1379                                 "       highp vec4 texColor = texture(u_sampler, texCoord);\n"
1380                                 "       mediump int emitCount = 0;\n"
1381                                 "       if (texColor.x > 0.0)\n"
1382                                 "               emitCount += " << ((EMIT_COUNT_VERTEX_0 == -1) ? (maxEmitCount) : (EMIT_COUNT_VERTEX_0)) << ";\n"
1383                                 "       if (texColor.y > 0.0)\n"
1384                                 "               emitCount += " << ((EMIT_COUNT_VERTEX_1 == -1) ? (maxEmitCount) : (EMIT_COUNT_VERTEX_1)) << ";\n"
1385                                 "       if (texColor.z > 0.0)\n"
1386                                 "               emitCount += " << ((EMIT_COUNT_VERTEX_2 == -1) ? (maxEmitCount) : (EMIT_COUNT_VERTEX_2)) << ";\n"
1387                                 "       if (texColor.w > 0.0)\n"
1388                                 "               emitCount += " << ((EMIT_COUNT_VERTEX_3 == -1) ? (maxEmitCount) : (EMIT_COUNT_VERTEX_3)) << ";\n";
1389         }
1390         else
1391                 DE_ASSERT(DE_FALSE);
1392
1393         // color
1394
1395         if (test == READ_ATTRIBUTE)
1396         {
1397                 // We don't want color to be compile time constant
1398                 buf <<  "       highp vec4 color = vec4((emitCount < 10) ? (0.0) : (1.0), (emitCount > 10) ? (0.0) : (1.0), 1.0, 1.0);\n";
1399         }
1400         else if (test == READ_UNIFORM || test == READ_TEXTURE)
1401         {
1402                 buf <<  "\n"
1403                                 "       const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
1404                                 "       const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
1405                                 "       const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
1406                                 "       const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
1407                                 "       const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n"
1408                                 "       highp vec4 color = colors[int(primitiveNdx)];\n";
1409         }
1410         else
1411                 DE_ASSERT(DE_FALSE);
1412
1413         buf <<  "\n"
1414                         "       highp vec4 basePos = " << ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n"
1415                         "       for (mediump int i = 0; i < emitCount / 2; i++)\n"
1416                         "       {\n"
1417                         "               highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n"
1418                         "               gl_Position = basePos + vec4(cos(angle),  sin(angle), 0.0, 0.0) * 0.15;\n"
1419                         "               v_frag_FragColor = color;\n"
1420                         "               EmitVertex();\n"
1421                         "               gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n"
1422                         "               v_frag_FragColor = color;\n"
1423                         "               EmitVertex();\n"
1424                         "       }"
1425                         "}\n";
1426
1427         return buf.str();
1428 }
1429
1430 std::string VaryingOutputCountShader::genVertexSource (VaryingSource test)
1431 {
1432         std::ostringstream buf;
1433
1434         buf <<  "#version 310 es\n"
1435                         "in highp vec4 a_position;\n";
1436
1437         if (test == READ_ATTRIBUTE)
1438         {
1439                 buf << "in highp vec4 a_emitCount;\n";
1440                 buf << "out highp vec4 v_geom_emitCount;\n";
1441         }
1442         else if (test == READ_UNIFORM || test == READ_TEXTURE)
1443         {
1444                 buf << "in highp vec4 a_vertexNdx;\n";
1445                 buf << "out highp vec4 v_geom_vertexNdx;\n";
1446         }
1447
1448         buf <<  "void main (void)\n"
1449                         "{\n"
1450                         "       gl_Position = a_position;\n";
1451
1452         if (test == READ_ATTRIBUTE)
1453                 buf << "        v_geom_emitCount = a_emitCount;\n";
1454         else if (test == READ_UNIFORM || test == READ_TEXTURE)
1455                 buf << "        v_geom_vertexNdx = a_vertexNdx;\n";
1456
1457         buf <<  "}\n";
1458
1459         return buf.str();
1460 }
1461
1462 class InvocationCountShader : public sglr::ShaderProgram
1463 {
1464 public:
1465         enum OutputCase
1466         {
1467                 CASE_FIXED_OUTPUT_COUNTS = 0,
1468                 CASE_DIFFERENT_OUTPUT_COUNTS,
1469
1470                 CASE_LAST
1471         };
1472
1473                                                 InvocationCountShader            (int numInvocations, OutputCase testCase);
1474
1475 private:
1476         void                            shadeVertices                           (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
1477         void                            shadeFragments                          (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
1478         void                            shadePrimitives                         (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const;
1479
1480         static std::string      genGeometrySource                       (int numInvocations, OutputCase testCase);
1481         static size_t           getNumVertices                          (int numInvocations, OutputCase testCase);
1482
1483         const int                       m_numInvocations;
1484         const OutputCase        m_testCase;
1485 };
1486
1487 InvocationCountShader::InvocationCountShader (int numInvocations, OutputCase testCase)
1488         : sglr::ShaderProgram   (sglr::pdec::ShaderProgramDeclaration()
1489                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
1490                                                         << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
1491                                                         << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT)
1492                                                         << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
1493                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
1494                                                         << sglr::pdec::VertexSource(s_commonShaderSourceVertex)
1495                                                         << sglr::pdec::FragmentSource(s_commonShaderSourceFragment)
1496                                                         << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS,
1497                                                                                                                                          rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP,
1498                                                                                                                                          getNumVertices(numInvocations, testCase),
1499                                                                                                                                          numInvocations)
1500                                                         << sglr::pdec::GeometrySource(genGeometrySource(numInvocations, testCase).c_str()))
1501         , m_numInvocations              (numInvocations)
1502         , m_testCase                    (testCase)
1503 {
1504 }
1505
1506 void InvocationCountShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
1507 {
1508         for (int ndx = 0; ndx < numPackets; ++ndx)
1509         {
1510                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
1511                 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
1512         }
1513 }
1514
1515 void InvocationCountShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
1516 {
1517         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1518         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
1519                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx));
1520 }
1521
1522 void InvocationCountShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
1523 {
1524         DE_UNREF(verticesIn);
1525
1526         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1527         {
1528                 const float                             l_angle         = float(invocationID) / float(m_numInvocations) * 5.5f;
1529                 const float                             l_radius        = 0.6f;
1530
1531                 const rr::VertexPacket* vertex          = packets[packetNdx].vertices[0];
1532
1533                 if (m_testCase == CASE_FIXED_OUTPUT_COUNTS)
1534                 {
1535                         const tcu::Vec4                 position0       = vertex->position + tcu::Vec4(deFloatCos(l_angle)      * (l_radius - 0.1f), deFloatSin(l_angle)      * (l_radius - 0.1f), 0.0f, 0.0f);
1536                         const tcu::Vec4                 position1       = vertex->position + tcu::Vec4(deFloatCos(l_angle+0.1f) * l_radius,          deFloatSin(l_angle+0.1f) * l_radius,          0.0f, 0.0f);
1537                         const tcu::Vec4                 position2       = vertex->position + tcu::Vec4(deFloatCos(l_angle-0.1f) * l_radius,          deFloatSin(l_angle-0.1f) * l_radius,          0.0f, 0.0f);
1538
1539                         rr::GenericVec4                 tipColor;
1540                         rr::GenericVec4                 baseColor;
1541
1542                         tipColor  = tcu::Vec4(1.0, 1.0, 0.0, 1.0) * packets[packetNdx].vertices[0]->outputs[0].get<float>();
1543                         baseColor = tcu::Vec4(1.0, 0.0, 0.0, 1.0) * packets[packetNdx].vertices[0]->outputs[0].get<float>();
1544
1545                         output.EmitVertex(position0, 0.0f, &tipColor, packets[packetNdx].primitiveIDIn);
1546                         output.EmitVertex(position1, 0.0f, &baseColor, packets[packetNdx].primitiveIDIn);
1547                         output.EmitVertex(position2, 0.0f, &baseColor, packets[packetNdx].primitiveIDIn);
1548                         output.EndPrimitive();
1549                 }
1550                 else if (m_testCase == CASE_DIFFERENT_OUTPUT_COUNTS)
1551                 {
1552                         const tcu::Vec4 color                   = tcu::Vec4(float(invocationID % 2), (((invocationID / 2) % 2) == 0) ? (1.0f) : (0.0f), 1.0f, 1.0f);
1553                         const tcu::Vec4 basePosition    = vertex->position + tcu::Vec4(deFloatCos(l_angle) * l_radius, deFloatSin(l_angle) * l_radius, 0.0f, 0.0f);
1554                         const int               numNgonVtx              = invocationID + 3;
1555
1556                         rr::GenericVec4 outColor;
1557                         outColor = color;
1558
1559                         for (int ndx = 0; ndx + 1 < numNgonVtx; ndx += 2)
1560                         {
1561                                 const float subAngle = (float(ndx) + 1.0f) / float(numNgonVtx) * 3.141f;
1562
1563                                 output.EmitVertex(basePosition + tcu::Vec4(deFloatCos(subAngle) * 0.1f, deFloatSin(subAngle) *  0.1f, 0.0f, 0.0f), 0.0f, &outColor, packets[packetNdx].primitiveIDIn);
1564                                 output.EmitVertex(basePosition + tcu::Vec4(deFloatCos(subAngle) * 0.1f, deFloatSin(subAngle) * -0.1f, 0.0f, 0.0f), 0.0f, &outColor, packets[packetNdx].primitiveIDIn);
1565                         }
1566
1567                         if ((numNgonVtx % 2) == 1)
1568                                 output.EmitVertex(basePosition + tcu::Vec4(-0.1f, 0.0f, 0.0f, 0.0f), 0.0f, &outColor, packets[packetNdx].primitiveIDIn);
1569
1570                         output.EndPrimitive();
1571                 }
1572         }
1573 }
1574
1575 std::string InvocationCountShader::genGeometrySource (int numInvocations, OutputCase testCase)
1576 {
1577         const int                       maxVertices = (int)getNumVertices(numInvocations, testCase);
1578         std::ostringstream      buf;
1579
1580         buf     <<      "#version 310 es\n"
1581                         "#extension GL_EXT_geometry_shader : require\n"
1582                         "layout(points, invocations = " << numInvocations << ") in;\n"
1583                         "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
1584                         "\n"
1585                         "in highp vec4 v_geom_FragColor[];\n"
1586                         "out highp vec4 v_frag_FragColor;\n"
1587                         "\n"
1588                         "void main ()\n"
1589                         "{\n"
1590                         "       highp float l_angle = float(gl_InvocationID) / float(" << numInvocations << ") * 5.5;\n"
1591                         "       highp float l_radius = 0.6;\n"
1592                         "\n";
1593
1594         if (testCase == CASE_FIXED_OUTPUT_COUNTS)
1595         {
1596                 buf <<  "       v_frag_FragColor = vec4(1.0, 1.0, 0.0, 1.0) * v_geom_FragColor[0];\n"
1597                                 "       gl_Position = gl_in[0].gl_Position + vec4(cos(l_angle) * (l_radius - 0.1), sin(l_angle) * (l_radius - 0.1), 0.0, 0.0);\n"
1598                                 "       EmitVertex();\n"
1599                                 "\n"
1600                                 "       v_frag_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * v_geom_FragColor[0];\n"
1601                                 "       gl_Position = gl_in[0].gl_Position + vec4(cos(l_angle+0.1) * l_radius, sin(l_angle+0.1) * l_radius, 0.0, 0.0);\n"
1602                                 "       EmitVertex();\n"
1603                                 "\n"
1604                                 "       v_frag_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * v_geom_FragColor[0];\n"
1605                                 "       gl_Position = gl_in[0].gl_Position + vec4(cos(l_angle-0.1) * l_radius, sin(l_angle-0.1) * l_radius, 0.0, 0.0);\n"
1606                                 "       EmitVertex();\n";
1607         }
1608         else if (testCase == CASE_DIFFERENT_OUTPUT_COUNTS)
1609         {
1610                 buf <<  "       highp vec4 l_color = vec4(float(gl_InvocationID % 2), (((gl_InvocationID / 2) % 2) == 0) ? (1.0) : (0.0), 1.0, 1.0);\n"
1611                                 "       highp vec4 basePosition = gl_in[0].gl_Position + vec4(cos(l_angle) * l_radius, sin(l_angle) * l_radius, 0.0, 0.0);\n"
1612                                 "       mediump int numNgonVtx = gl_InvocationID + 3;\n"
1613                                 "\n"
1614                                 "       for (int ndx = 0; ndx + 1 < numNgonVtx; ndx += 2)\n"
1615                                 "       {\n"
1616                                 "               highp float sub_angle = (float(ndx) + 1.0) / float(numNgonVtx) * 3.141;\n"
1617                                 "\n"
1618                                 "               v_frag_FragColor = l_color;\n"
1619                                 "               gl_Position = basePosition + vec4(cos(sub_angle) * 0.1, sin(sub_angle) * 0.1, 0.0, 0.0);\n"
1620                                 "               EmitVertex();\n"
1621                                 "\n"
1622                                 "               v_frag_FragColor = l_color;\n"
1623                                 "               gl_Position = basePosition + vec4(cos(sub_angle) * 0.1, sin(sub_angle) * -0.1, 0.0, 0.0);\n"
1624                                 "               EmitVertex();\n"
1625                                 "       }\n"
1626                                 "       if ((numNgonVtx % 2) == 1)\n"
1627                                 "       {\n"
1628                                 "               v_frag_FragColor = l_color;\n"
1629                                 "               gl_Position = basePosition + vec4(-0.1, 0.0, 0.0, 0.0);\n"
1630                                 "               EmitVertex();\n"
1631                                 "       }\n";
1632         }
1633         else
1634                 DE_ASSERT(false);
1635
1636         buf <<  "}\n";
1637
1638         return buf.str();
1639 }
1640
1641 size_t InvocationCountShader::getNumVertices (int numInvocations, OutputCase testCase)
1642 {
1643         switch (testCase)
1644         {
1645                 case CASE_FIXED_OUTPUT_COUNTS:                  return 3;
1646                 case CASE_DIFFERENT_OUTPUT_COUNTS:              return (size_t)(2 + numInvocations);
1647                 default:
1648                         DE_ASSERT(false);
1649                         return 0;
1650         }
1651 }
1652
1653 class InstancedExpansionShader : public sglr::ShaderProgram
1654 {
1655 public:
1656                                                 InstancedExpansionShader        (int numInvocations);
1657
1658 private:
1659         void                            shadeVertices                           (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
1660         void                            shadeFragments                          (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
1661         void                            shadePrimitives                         (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const;
1662
1663         static std::string      genVertexSource                         (void);
1664         static std::string      genFragmentSource                       (void);
1665         static std::string      genGeometrySource                       (int numInvocations);
1666
1667         const int                       m_numInvocations;
1668 };
1669
1670 InstancedExpansionShader::InstancedExpansionShader (int numInvocations)
1671         : sglr::ShaderProgram   (sglr::pdec::ShaderProgramDeclaration()
1672                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
1673                                                         << sglr::pdec::VertexAttribute("a_offset", rr::GENERICVECTYPE_FLOAT)
1674                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
1675                                                         << sglr::pdec::VertexSource(genVertexSource())
1676                                                         << sglr::pdec::FragmentSource(genFragmentSource())
1677                                                         << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS,
1678                                                                                                                                          rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP,
1679                                                                                                                                          4,
1680                                                                                                                                          numInvocations)
1681                                                         << sglr::pdec::GeometrySource(genGeometrySource(numInvocations).c_str()))
1682         , m_numInvocations              (numInvocations)
1683 {
1684 }
1685
1686 void InstancedExpansionShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
1687 {
1688         for (int ndx = 0; ndx < numPackets; ++ndx)
1689         {
1690                 packets[ndx]->position =        rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx) +
1691                                                                         rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
1692         }
1693 }
1694
1695 void InstancedExpansionShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
1696 {
1697         DE_UNREF(packets);
1698
1699         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1700         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
1701                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1702 }
1703
1704 void InstancedExpansionShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const
1705 {
1706         DE_UNREF(verticesIn);
1707
1708         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1709         {
1710                 const rr::VertexPacket* vertex                  = packets[packetNdx].vertices[0];
1711                 const tcu::Vec4                 basePosition    = vertex->position;
1712                 const float                             phase                   = float(invocationID) / float(m_numInvocations) * 6.3f;
1713                 const tcu::Vec4                 centerPosition  = basePosition + tcu::Vec4(deFloatCos(phase), deFloatSin(phase), 0.0f, 0.0f) * 0.1f;
1714
1715                 output.EmitVertex(centerPosition + tcu::Vec4( 0.0f,  -0.1f, 0.0f, 0.0f), 0.0f, DE_NULL, packets[packetNdx].primitiveIDIn);
1716                 output.EmitVertex(centerPosition + tcu::Vec4(-0.05f,  0.0f, 0.0f, 0.0f), 0.0f, DE_NULL, packets[packetNdx].primitiveIDIn);
1717                 output.EmitVertex(centerPosition + tcu::Vec4( 0.05f,  0.0f, 0.0f, 0.0f), 0.0f, DE_NULL, packets[packetNdx].primitiveIDIn);
1718                 output.EndPrimitive();
1719         }
1720 }
1721
1722 std::string InstancedExpansionShader::genVertexSource (void)
1723 {
1724         return  "#version 310 es\n"
1725                         "in highp vec4 a_position;\n"
1726                         "in highp vec4 a_offset;\n"
1727                         "void main (void)\n"
1728                         "{\n"
1729                         "       gl_Position = a_position + a_offset;\n"
1730                         "}\n";
1731 }
1732
1733 std::string InstancedExpansionShader::genFragmentSource (void)
1734 {
1735         return  "#version 310 es\n"
1736                         "layout(location = 0) out mediump vec4 fragColor;\n"
1737                         "void main (void)\n"
1738                         "{\n"
1739                         "       fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
1740                         "}\n";
1741 }
1742
1743 std::string InstancedExpansionShader::genGeometrySource (int numInvocations)
1744 {
1745         std::ostringstream buf;
1746
1747         buf <<  "#version 310 es\n"
1748                         "#extension GL_EXT_geometry_shader : require\n"
1749                         "layout(points,invocations=" << numInvocations << ") in;\n"
1750                         "layout(triangle_strip, max_vertices = 3) out;\n"
1751                         "\n"
1752                         "void main (void)\n"
1753                         "{\n"
1754                         "       highp vec4 basePosition = gl_in[0].gl_Position;\n"
1755                         "       highp float phase = float(gl_InvocationID) / float(" << numInvocations << ") * 6.3;\n"
1756                         "       highp vec4 centerPosition = basePosition + 0.1 * vec4(cos(phase), sin(phase), 0.0, 0.0);\n"
1757                         "\n"
1758                         "       gl_Position = centerPosition + vec4( 0.00, -0.1, 0.0, 0.0);\n"
1759                         "       EmitVertex();\n"
1760                         "       gl_Position = centerPosition + vec4(-0.05,  0.0, 0.0, 0.0);\n"
1761                         "       EmitVertex();\n"
1762                         "       gl_Position = centerPosition + vec4( 0.05,  0.0, 0.0, 0.0);\n"
1763                         "       EmitVertex();\n"
1764                         "}\n";
1765
1766         return buf.str();
1767 }
1768
1769 class GeometryShaderRenderTest : public TestCase
1770 {
1771 public:
1772         enum Flag
1773         {
1774                 FLAG_DRAW_INSTANCED             = 1,
1775                 FLAG_USE_INDICES                = 2,
1776                 FLAG_USE_RESTART_INDEX  = 4,
1777         };
1778
1779                                                                         GeometryShaderRenderTest        (Context& context, const char* name, const char* desc, GLenum inputPrimitives, GLenum outputPrimitives, const char* dataAttributeName, int flags = 0);
1780         virtual                                                 ~GeometryShaderRenderTest       (void);
1781
1782         void                                                    init                                            (void);
1783         void                                                    deinit                                          (void);
1784
1785         IterateResult                                   iterate                                         (void);
1786         bool                                                    compare                                         (void);
1787
1788         virtual sglr::ShaderProgram&    getProgram                                      (void) = 0;
1789
1790 protected:
1791         virtual void                                    genVertexAttribData                     (void);
1792         void                                                    renderWithContext                       (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dstSurface);
1793         virtual void                                    preRender                                       (sglr::Context& ctx, GLuint programID);
1794         virtual void                                    postRender                                      (sglr::Context& ctx, GLuint programID);
1795
1796         int                                                             m_numDrawVertices;
1797         int                                                             m_numDrawInstances;
1798         int                                                             m_vertexAttrDivisor;
1799
1800         const GLenum                                    m_inputPrimitives;
1801         const GLenum                                    m_outputPrimitives;
1802         const char* const                               m_dataAttributeName;
1803         const int                                               m_flags;
1804
1805         tcu::IVec2                                              m_viewportSize;
1806         int                                                             m_interationCount;
1807
1808         tcu::Surface*                                   m_glResult;
1809         tcu::Surface*                                   m_refResult;
1810
1811         sglr::ReferenceContextBuffers*  m_refBuffers;
1812         sglr::ReferenceContext*                 m_refContext;
1813         sglr::Context*                                  m_glContext;
1814
1815         std::vector<tcu::Vec4>                  m_vertexPosData;
1816         std::vector<tcu::Vec4>                  m_vertexAttrData;
1817         std::vector<deUint16>                   m_indices;
1818 };
1819
1820 GeometryShaderRenderTest::GeometryShaderRenderTest (Context& context, const char* name, const char* desc, GLenum inputPrimitives, GLenum outputPrimitives, const char* dataAttributeName, int flags)
1821         : TestCase                              (context, name, desc)
1822         , m_numDrawVertices             (0)
1823         , m_numDrawInstances    (0)
1824         , m_vertexAttrDivisor   (0)
1825         , m_inputPrimitives             (inputPrimitives)
1826         , m_outputPrimitives    (outputPrimitives)
1827         , m_dataAttributeName   (dataAttributeName)
1828         , m_flags                               (flags)
1829         , m_viewportSize                (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE)
1830         , m_interationCount             (0)
1831         , m_glResult                    (DE_NULL)
1832         , m_refResult                   (DE_NULL)
1833         , m_refBuffers                  (DE_NULL)
1834         , m_refContext                  (DE_NULL)
1835         , m_glContext                   (DE_NULL)
1836 {
1837         // Disallow instanced drawElements
1838         DE_ASSERT(((m_flags & FLAG_DRAW_INSTANCED) == 0) || ((m_flags & FLAG_USE_INDICES) == 0));
1839         // Disallow restart without indices
1840         DE_ASSERT(!(((m_flags & FLAG_USE_RESTART_INDEX) != 0) && ((m_flags & FLAG_USE_INDICES) == 0)));
1841 }
1842
1843 GeometryShaderRenderTest::~GeometryShaderRenderTest (void)
1844 {
1845         deinit();
1846 }
1847
1848 void GeometryShaderRenderTest::init (void)
1849 {
1850         // requirements
1851         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
1852                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
1853
1854         // gen resources
1855         {
1856                 sglr::ReferenceContextLimits limits;
1857
1858                 m_glResult              = new tcu::Surface(m_viewportSize.x(), m_viewportSize.y());
1859                 m_refResult             = new tcu::Surface(m_viewportSize.x(), m_viewportSize.y());
1860
1861                 m_refBuffers    = new sglr::ReferenceContextBuffers(m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, m_viewportSize.x(), m_viewportSize.y());
1862                 m_refContext    = new sglr::ReferenceContext(limits, m_refBuffers->getColorbuffer(), m_refBuffers->getDepthbuffer(), m_refBuffers->getStencilbuffer());
1863                 m_glContext             = new sglr::GLContext(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, m_viewportSize.x(), m_viewportSize.y()));
1864         }
1865 }
1866
1867 void GeometryShaderRenderTest::deinit (void)
1868 {
1869         delete m_glResult;
1870         delete m_refResult;
1871
1872         m_glResult = DE_NULL;
1873         m_refResult = DE_NULL;
1874
1875         delete m_refContext;
1876         delete m_glContext;
1877         delete m_refBuffers;
1878
1879         m_refBuffers = DE_NULL;
1880         m_refContext = DE_NULL;
1881         m_glContext = DE_NULL;
1882 }
1883
1884 tcu::TestCase::IterateResult GeometryShaderRenderTest::iterate (void)
1885 {
1886         // init() must be called
1887         DE_ASSERT(m_glContext);
1888         DE_ASSERT(m_refContext);
1889
1890         const int iteration = m_interationCount++;
1891
1892         if (iteration == 0)
1893         {
1894                 // Check requirements
1895                 const int width  = m_context.getRenderTarget().getWidth();
1896                 const int height = m_context.getRenderTarget().getHeight();
1897
1898                 if (width < m_viewportSize.x() || height < m_viewportSize.y())
1899                         throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(m_viewportSize.x()) + "x" + de::toString(m_viewportSize.y()));
1900
1901                 // Gen data
1902                 genVertexAttribData();
1903
1904                 return CONTINUE;
1905         }
1906         else if (iteration == 1)
1907         {
1908                 // Render
1909                 sglr::ShaderProgram& program = getProgram();
1910
1911                 renderWithContext(*m_glContext, program, *m_glResult);
1912                 renderWithContext(*m_refContext, program, *m_refResult);
1913
1914                 return CONTINUE;
1915         }
1916         else
1917         {
1918                 if (compare())
1919                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1920                 else
1921                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
1922
1923                 return STOP;
1924         }
1925 }
1926
1927 bool GeometryShaderRenderTest::compare (void)
1928 {
1929         using tcu::TestLog;
1930
1931         if (m_context.getRenderTarget().getNumSamples() > 1)
1932         {
1933                 return tcu::fuzzyCompare(m_testCtx.getLog(), "Compare Results", "Compare Results", m_refResult->getAccess(), m_glResult->getAccess(), 0.02f, tcu::COMPARE_LOG_RESULT);
1934         }
1935         else
1936         {
1937                 tcu::Surface    errorMask                               (m_viewportSize.x(), m_viewportSize.y());
1938                 const tcu::RGBA green                                   (0, 255, 0, 255);
1939                 const tcu::RGBA red                                             (255, 0, 0, 255);
1940                 const int               colorComponentThreshold = 20;
1941                 bool                    testResult                              = true;
1942
1943                 for (int x = 0; x < m_viewportSize.x(); ++x)
1944                 for (int y = 0; y < m_viewportSize.y(); ++y)
1945                 {
1946                         if (x == 0 || y == 0 || x + 1 == m_viewportSize.x() || y + 1 == m_viewportSize.y())
1947                         {
1948                                 // Mark edge pixels as correct since their neighbourhood is undefined
1949                                 errorMask.setPixel(x, y, green);
1950                         }
1951                         else
1952                         {
1953                                 const tcu::RGBA refcolor        = m_refResult->getPixel(x, y);
1954                                 bool                    found           = false;
1955
1956                                 // Got to find similar pixel near this pixel (3x3 kernel)
1957                                 for (int dx = -1; dx <= 1; ++dx)
1958                                 for (int dy = -1; dy <= 1; ++dy)
1959                                 {
1960                                         const tcu::RGBA         testColor       = m_glResult->getPixel(x + dx, y + dy);
1961                                         const tcu::IVec4        colDiff         = tcu::abs(testColor.toIVec() - refcolor.toIVec());
1962
1963                                         const int                       maxColDiff      = de::max(de::max(colDiff.x(), colDiff.y()), colDiff.z()); // check RGB channels
1964
1965                                         if (maxColDiff <= colorComponentThreshold)
1966                                                 found = true;
1967                                 }
1968
1969                                 if (!found)
1970                                         testResult = false;
1971
1972                                 errorMask.setPixel(x, y, (found) ? (green) : (red));
1973                         }
1974                 }
1975
1976                 if (testResult)
1977                 {
1978                         m_testCtx.getLog()      << TestLog::ImageSet("Compare result", "Result of rendering")
1979                                                                 << TestLog::Image("Result", "Result", *m_glResult)
1980                                                                 << TestLog::EndImageSet;
1981                         m_testCtx.getLog() << TestLog::Message << "Image compare ok." << TestLog::EndMessage;
1982                 }
1983                 else
1984                 {
1985                         m_testCtx.getLog()      << TestLog::ImageSet("Compare result", "Result of rendering")
1986                                                                 << TestLog::Image("Result",             "Result",               *m_glResult)
1987                                                                 << TestLog::Image("Reference",  "Reference",    *m_refResult)
1988                                                                 << TestLog::Image("ErrorMask",  "Error mask",   errorMask)
1989                                                                 << TestLog::EndImageSet;
1990                         m_testCtx.getLog() << TestLog::Message << "Image compare failed." << TestLog::EndMessage;
1991                 }
1992
1993                 return testResult;
1994         }
1995 }
1996
1997 void GeometryShaderRenderTest::genVertexAttribData (void)
1998 {
1999         // Create 1 X 2 grid in triangle strip adjacent - order
2000         const float scale = 0.3f;
2001         const tcu::Vec4 offset(-0.5f, -0.2f, 0.0f, 1.0f);
2002
2003         m_vertexPosData.resize(12);
2004         m_vertexPosData[ 0] = tcu::Vec4( 0,  0, 0.0f, 0.0f) * scale + offset;
2005         m_vertexPosData[ 1] = tcu::Vec4(-1, -1, 0.0f, 0.0f) * scale + offset;
2006         m_vertexPosData[ 2] = tcu::Vec4( 0, -1, 0.0f, 0.0f) * scale + offset;
2007         m_vertexPosData[ 3] = tcu::Vec4( 1,  1, 0.0f, 0.0f) * scale + offset;
2008         m_vertexPosData[ 4] = tcu::Vec4( 1,  0, 0.0f, 0.0f) * scale + offset;
2009         m_vertexPosData[ 5] = tcu::Vec4( 0, -2, 0.0f, 0.0f) * scale + offset;
2010         m_vertexPosData[ 6] = tcu::Vec4( 1, -1, 0.0f, 0.0f) * scale + offset;
2011         m_vertexPosData[ 7] = tcu::Vec4( 2,  1, 0.0f, 0.0f) * scale + offset;
2012         m_vertexPosData[ 8] = tcu::Vec4( 2,  0, 0.0f, 0.0f) * scale + offset;
2013         m_vertexPosData[ 9] = tcu::Vec4( 1, -2, 0.0f, 0.0f) * scale + offset;
2014         m_vertexPosData[10] = tcu::Vec4( 2, -1, 0.0f, 0.0f) * scale + offset;
2015         m_vertexPosData[11] = tcu::Vec4( 3,  0, 0.0f, 0.0f) * scale + offset;
2016
2017         // Red and white
2018         m_vertexAttrData.resize(12);
2019         for (int i = 0; i < 12; ++i)
2020                 m_vertexAttrData[i] = (i % 2 == 0) ? tcu::Vec4(1, 1, 1, 1) : tcu::Vec4(1, 0, 0, 1);
2021
2022         m_numDrawVertices = 12;
2023 }
2024
2025 void GeometryShaderRenderTest::renderWithContext (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dstSurface)
2026 {
2027 #define CHECK_GL_CTX_ERRORS() glu::checkError(ctx.getError(), DE_NULL, __FILE__, __LINE__)
2028
2029         const GLuint    programId               = ctx.createProgram(&program);
2030         const GLint             attrPosLoc              = ctx.getAttribLocation(programId, "a_position");
2031         const GLint             attrColLoc              = ctx.getAttribLocation(programId, m_dataAttributeName);
2032         GLuint                  vaoId                   = 0;
2033         GLuint                  vertexPosBuf    = 0;
2034         GLuint                  vertexAttrBuf   = 0;
2035         GLuint                  elementArrayBuf = 0;
2036
2037         ctx.genVertexArrays(1, &vaoId);
2038         ctx.bindVertexArray(vaoId);
2039
2040         if (attrPosLoc != -1)
2041         {
2042                 ctx.genBuffers(1, &vertexPosBuf);
2043                 ctx.bindBuffer(GL_ARRAY_BUFFER, vertexPosBuf);
2044                 ctx.bufferData(GL_ARRAY_BUFFER, m_vertexPosData.size() * sizeof(tcu::Vec4), &m_vertexPosData[0], GL_STATIC_DRAW);
2045                 ctx.vertexAttribPointer(attrPosLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2046                 ctx.enableVertexAttribArray(attrPosLoc);
2047         }
2048
2049         if (attrColLoc != -1)
2050         {
2051                 ctx.genBuffers(1, &vertexAttrBuf);
2052                 ctx.bindBuffer(GL_ARRAY_BUFFER, vertexAttrBuf);
2053                 ctx.bufferData(GL_ARRAY_BUFFER, m_vertexAttrData.size() * sizeof(tcu::Vec4), &m_vertexAttrData[0], GL_STATIC_DRAW);
2054                 ctx.vertexAttribPointer(attrColLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2055                 ctx.enableVertexAttribArray(attrColLoc);
2056
2057                 if (m_vertexAttrDivisor)
2058                         ctx.vertexAttribDivisor(attrColLoc, m_vertexAttrDivisor);
2059         }
2060
2061         if (m_flags & FLAG_USE_INDICES)
2062         {
2063                 ctx.genBuffers(1, &elementArrayBuf);
2064                 ctx.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuf);
2065                 ctx.bufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof(deUint16), &m_indices[0], GL_STATIC_DRAW);
2066         }
2067
2068         ctx.clearColor(0, 0, 0, 1);
2069         ctx.clear(GL_COLOR_BUFFER_BIT);
2070
2071         ctx.viewport(0, 0, m_viewportSize.x(), m_viewportSize.y());
2072         CHECK_GL_CTX_ERRORS();
2073
2074         ctx.useProgram(programId);
2075         CHECK_GL_CTX_ERRORS();
2076
2077         preRender(ctx, programId);
2078         CHECK_GL_CTX_ERRORS();
2079
2080         if (m_flags & FLAG_USE_RESTART_INDEX)
2081         {
2082                 ctx.enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
2083                 CHECK_GL_CTX_ERRORS();
2084         }
2085
2086         if (m_flags & FLAG_USE_INDICES)
2087                 ctx.drawElements(m_inputPrimitives, m_numDrawVertices, GL_UNSIGNED_SHORT, DE_NULL);
2088         else if (m_flags & FLAG_DRAW_INSTANCED)
2089                 ctx.drawArraysInstanced(m_inputPrimitives, 0, m_numDrawVertices, m_numDrawInstances);
2090         else
2091                 ctx.drawArrays(m_inputPrimitives, 0, m_numDrawVertices);
2092
2093         CHECK_GL_CTX_ERRORS();
2094
2095         if (m_flags & FLAG_USE_RESTART_INDEX)
2096         {
2097                 ctx.disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
2098                 CHECK_GL_CTX_ERRORS();
2099         }
2100
2101         postRender(ctx, programId);
2102         CHECK_GL_CTX_ERRORS();
2103
2104         ctx.useProgram(0);
2105
2106         if (attrPosLoc != -1)
2107                 ctx.disableVertexAttribArray(attrPosLoc);
2108         if (attrColLoc != -1)
2109                 ctx.disableVertexAttribArray(attrColLoc);
2110
2111         if (vertexPosBuf)
2112                 ctx.deleteBuffers(1, &vertexPosBuf);
2113         if (vertexAttrBuf)
2114                 ctx.deleteBuffers(1, &vertexAttrBuf);
2115         if (elementArrayBuf)
2116                 ctx.deleteBuffers(1, &elementArrayBuf);
2117
2118         ctx.deleteVertexArrays(1, &vaoId);
2119
2120         CHECK_GL_CTX_ERRORS();
2121
2122         ctx.finish();
2123         ctx.readPixels(dstSurface, 0, 0, m_viewportSize.x(), m_viewportSize.y());
2124
2125 #undef CHECK_GL_CTX_ERRORS
2126 }
2127
2128 void GeometryShaderRenderTest::preRender (sglr::Context& ctx, GLuint programID)
2129 {
2130         DE_UNREF(ctx);
2131         DE_UNREF(programID);
2132 }
2133
2134 void GeometryShaderRenderTest::postRender (sglr::Context& ctx, GLuint programID)
2135 {
2136         DE_UNREF(ctx);
2137         DE_UNREF(programID);
2138 }
2139
2140 class GeometryExpanderRenderTest : public GeometryShaderRenderTest
2141 {
2142 public:
2143                                                                         GeometryExpanderRenderTest      (Context& context, const char* name, const char* desc, GLenum inputPrimitives, GLenum outputPrimitives);
2144         virtual                                                 ~GeometryExpanderRenderTest     (void);
2145
2146         sglr::ShaderProgram&                    getProgram                                      (void);
2147
2148 private:
2149         VertexExpanderShader                    m_program;
2150 };
2151
2152 GeometryExpanderRenderTest::GeometryExpanderRenderTest (Context& context, const char* name, const char* desc, GLenum inputPrimitives, GLenum outputPrimitives)
2153         : GeometryShaderRenderTest      (context, name, desc, inputPrimitives, outputPrimitives, "a_color")
2154         , m_program                                     (sglr::rr_util::mapGLGeometryShaderInputType(inputPrimitives), sglr::rr_util::mapGLGeometryShaderOutputType(outputPrimitives))
2155 {
2156 }
2157
2158 GeometryExpanderRenderTest::~GeometryExpanderRenderTest (void)
2159 {
2160 }
2161
2162 sglr::ShaderProgram& GeometryExpanderRenderTest::getProgram (void)
2163 {
2164         return m_program;
2165 }
2166
2167 class EmitTest : public GeometryShaderRenderTest
2168 {
2169 public:
2170                                                         EmitTest                                (Context& context, const char* name, const char* desc, int emitCountA, int endCountA, int emitCountB, int endCountB, GLenum outputType);
2171
2172         sglr::ShaderProgram&    getProgram                              (void);
2173 private:
2174         void                                    genVertexAttribData             (void);
2175
2176         VertexEmitterShader             m_program;
2177 };
2178
2179 EmitTest::EmitTest (Context& context, const char* name, const char* desc, int emitCountA, int endCountA, int emitCountB, int endCountB, GLenum outputType)
2180         : GeometryShaderRenderTest      (context, name, desc, GL_POINTS, outputType, "a_color")
2181         , m_program                                     (emitCountA, endCountA, emitCountB, endCountB, sglr::rr_util::mapGLGeometryShaderOutputType(outputType))
2182 {
2183 }
2184
2185 sglr::ShaderProgram& EmitTest::getProgram (void)
2186 {
2187         return m_program;
2188 }
2189
2190 void EmitTest::genVertexAttribData (void)
2191 {
2192         m_vertexPosData.resize(1);
2193         m_vertexPosData[0] = tcu::Vec4(0, 0, 0, 1);
2194
2195         m_vertexAttrData.resize(1);
2196         m_vertexAttrData[0] = tcu::Vec4(1, 1, 1, 1);
2197
2198         m_numDrawVertices = 1;
2199 }
2200
2201 class VaryingTest : public GeometryShaderRenderTest
2202 {
2203 public:
2204                                                         VaryingTest                             (Context& context, const char* name, const char* desc, int vertexOut, int geometryOut);
2205
2206         sglr::ShaderProgram&    getProgram                              (void);
2207 private:
2208         void                                    genVertexAttribData             (void);
2209
2210         VertexVaryingShader             m_program;
2211 };
2212
2213 VaryingTest::VaryingTest (Context& context, const char* name, const char* desc, int vertexOut, int geometryOut)
2214         : GeometryShaderRenderTest      (context, name, desc, GL_TRIANGLES, GL_TRIANGLE_STRIP, "a_color")
2215         , m_program                                     (vertexOut, geometryOut)
2216 {
2217 }
2218
2219 sglr::ShaderProgram& VaryingTest::getProgram (void)
2220 {
2221         return m_program;
2222 }
2223
2224 void VaryingTest::genVertexAttribData (void)
2225 {
2226         m_vertexPosData.resize(3);
2227         m_vertexPosData[0] = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f);
2228         m_vertexPosData[1] = tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f);
2229         m_vertexPosData[2] = tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f);
2230
2231         m_vertexAttrData.resize(3);
2232         m_vertexAttrData[0] = tcu::Vec4(0.7f, 0.4f, 0.6f, 1.0f);
2233         m_vertexAttrData[1] = tcu::Vec4(0.9f, 0.2f, 0.5f, 1.0f);
2234         m_vertexAttrData[2] = tcu::Vec4(0.1f, 0.8f, 0.3f, 1.0f);
2235
2236         m_numDrawVertices = 3;
2237 }
2238
2239 class TriangleStripAdjacencyVertexCountTest : public GeometryExpanderRenderTest
2240 {
2241 public:
2242                                 TriangleStripAdjacencyVertexCountTest   (Context& context, const char* name, const char* desc, int numInputVertices);
2243
2244 private:
2245         void            genVertexAttribData                                             (void);
2246
2247         int                     m_numInputVertices;
2248 };
2249
2250 TriangleStripAdjacencyVertexCountTest::TriangleStripAdjacencyVertexCountTest (Context& context, const char* name, const char* desc, int numInputVertices)
2251         : GeometryExpanderRenderTest    (context, name, desc, GL_TRIANGLE_STRIP_ADJACENCY, GL_TRIANGLE_STRIP)
2252         , m_numInputVertices                    (numInputVertices)
2253 {
2254 }
2255
2256 void TriangleStripAdjacencyVertexCountTest::genVertexAttribData (void)
2257 {
2258         this->GeometryShaderRenderTest::genVertexAttribData();
2259         m_numDrawVertices = m_numInputVertices;
2260 }
2261
2262 class NegativeDrawCase : public TestCase
2263 {
2264 public:
2265                                                         NegativeDrawCase        (Context& context, const char* name, const char* desc, GLenum inputType, GLenum inputPrimitives);
2266                                                         ~NegativeDrawCase       (void);
2267
2268         void                                    init                            (void);
2269         void                                    deinit                          (void);
2270
2271         IterateResult                   iterate                         (void);
2272
2273 private:
2274         sglr::Context*                  m_ctx;
2275         VertexExpanderShader*   m_program;
2276         GLenum                                  m_inputType;
2277         GLenum                                  m_inputPrimitives;
2278 };
2279
2280 NegativeDrawCase::NegativeDrawCase (Context& context, const char* name, const char* desc, GLenum inputType, GLenum inputPrimitives)
2281         : TestCase                      (context, name, desc)
2282         , m_ctx                         (DE_NULL)
2283         , m_program                     (DE_NULL)
2284         , m_inputType           (inputType)
2285         , m_inputPrimitives     (inputPrimitives)
2286 {
2287 }
2288
2289 NegativeDrawCase::~NegativeDrawCase (void)
2290 {
2291         deinit();
2292 }
2293
2294 void NegativeDrawCase::init (void)
2295 {
2296         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
2297                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
2298
2299         m_ctx           = new sglr::GLContext(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, 1, 1));
2300         m_program       = new VertexExpanderShader(sglr::rr_util::mapGLGeometryShaderInputType(m_inputType), rr::GEOMETRYSHADEROUTPUTTYPE_POINTS);
2301 }
2302
2303 void NegativeDrawCase::deinit (void)
2304 {
2305         delete m_ctx;
2306         delete m_program;
2307
2308         m_ctx = NULL;
2309         m_program = DE_NULL;
2310 }
2311
2312 NegativeDrawCase::IterateResult NegativeDrawCase::iterate (void)
2313 {
2314         const GLuint    programId               = m_ctx->createProgram(m_program);
2315         const GLint             attrPosLoc              = m_ctx->getAttribLocation(programId, "a_position");
2316         const tcu::Vec4 vertexPosData   (0, 0, 0, 1);
2317
2318         GLuint vaoId            = 0;
2319         GLuint vertexPosBuf = 0;
2320         GLenum errorCode        = 0;
2321
2322         m_ctx->genVertexArrays(1, &vaoId);
2323         m_ctx->bindVertexArray(vaoId);
2324
2325         m_ctx->genBuffers(1, &vertexPosBuf);
2326         m_ctx->bindBuffer(GL_ARRAY_BUFFER, vertexPosBuf);
2327         m_ctx->bufferData(GL_ARRAY_BUFFER, sizeof(tcu::Vec4), vertexPosData.m_data, GL_STATIC_DRAW);
2328         m_ctx->vertexAttribPointer(attrPosLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2329         m_ctx->enableVertexAttribArray(attrPosLoc);
2330
2331         m_ctx->clearColor(0, 0, 0, 1);
2332         m_ctx->clear(GL_COLOR_BUFFER_BIT);
2333
2334         m_ctx->viewport(0, 0, 1, 1);
2335
2336         m_ctx->useProgram(programId);
2337
2338         // no errors before
2339         glu::checkError(m_ctx->getError(), "", __FILE__, __LINE__);
2340
2341         m_ctx->drawArrays(m_inputPrimitives, 0, 1);
2342
2343         errorCode = m_ctx->getError();
2344         if (errorCode != GL_INVALID_OPERATION)
2345         {
2346                 m_testCtx.getLog() << tcu::TestLog::Message << "Expected GL_INVALID_OPERATION, got " << glu::getErrorStr(errorCode) << tcu::TestLog::EndMessage;
2347                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got wrong error code");
2348         }
2349         else
2350         {
2351                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2352         }
2353
2354         m_ctx->useProgram(0);
2355
2356         m_ctx->disableVertexAttribArray(attrPosLoc);
2357         m_ctx->deleteBuffers(1, &vertexPosBuf);
2358
2359         m_ctx->deleteVertexArrays(1, &vaoId);
2360
2361         return STOP;
2362 }
2363
2364 class OutputCountCase : public GeometryShaderRenderTest
2365 {
2366 public:
2367                                                                         OutputCountCase                 (Context& context, const char* name, const char* desc, const OutputCountPatternSpec&);
2368 private:
2369         void                                                    init                                    (void);
2370         void                                                    deinit                                  (void);
2371
2372         sglr::ShaderProgram&                    getProgram                              (void);
2373         void                                                    genVertexAttribData             (void);
2374
2375         const int                                               m_primitiveCount;
2376         OutputCountShader*                              m_program;
2377         OutputCountPatternSpec                  m_spec;
2378 };
2379
2380 OutputCountCase::OutputCountCase (Context& context, const char* name, const char* desc, const OutputCountPatternSpec& spec)
2381         : GeometryShaderRenderTest      (context, name, desc, GL_POINTS, GL_TRIANGLE_STRIP, "a_color")
2382         , m_primitiveCount                      ((int)spec.pattern.size())
2383         , m_program                                     (DE_NULL)
2384         , m_spec                                        (spec)
2385 {
2386 }
2387
2388 void OutputCountCase::init (void)
2389 {
2390         // Check requirements and adapt to them
2391         {
2392                 const int       componentsPerVertex     = 4 + 4; // vec4 pos, vec4 color
2393                 const int       testVertices            = *std::max_element(m_spec.pattern.begin(), m_spec.pattern.end());
2394                 glw::GLint      maxVertices                     = 0;
2395                 glw::GLint      maxComponents           = 0;
2396
2397                 // check the extension before querying anything
2398                 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
2399                         throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
2400
2401                 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &maxVertices);
2402                 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &maxComponents);
2403
2404                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_OUTPUT_VERTICES = " << maxVertices << tcu::TestLog::EndMessage;
2405                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = " << maxComponents << tcu::TestLog::EndMessage;
2406                 m_testCtx.getLog() << tcu::TestLog::Message << "Components per vertex = " << componentsPerVertex << tcu::TestLog::EndMessage;
2407
2408                 if (testVertices == -1)
2409                 {
2410                         // "max vertices"-case
2411                         DE_ASSERT((int)m_spec.pattern.size() == 1);
2412                         m_spec.pattern[0] = de::min(maxVertices, maxComponents / componentsPerVertex);
2413
2414                         // make sure size is dividable by 2, as OutputShader requires
2415                         m_spec.pattern[0] = m_spec.pattern[0] & ~0x00000001;
2416
2417                         if (m_spec.pattern[0] == 0)
2418                                 throw tcu::InternalError("Pattern size is invalid.");
2419                 }
2420                 else
2421                 {
2422                         // normal case
2423                         if (testVertices > maxVertices)
2424                                 throw tcu::NotSupportedError(de::toString(testVertices) + " output vertices required.");
2425                         if (testVertices * componentsPerVertex > maxComponents)
2426                                 throw tcu::NotSupportedError(de::toString(testVertices * componentsPerVertex) + " output components required.");
2427                 }
2428         }
2429
2430         // Log what the test tries to do
2431
2432         m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << (int)m_spec.pattern.size() << " row(s).\nOne geometry shader invocation generates one row.\nRow sizes:" << tcu::TestLog::EndMessage;
2433         for (int ndx = 0; ndx < (int)m_spec.pattern.size(); ++ndx)
2434                 m_testCtx.getLog() << tcu::TestLog::Message << "Row " << ndx << ": " << m_spec.pattern[ndx] << " vertices." << tcu::TestLog::EndMessage;
2435
2436         // Gen shader
2437         DE_ASSERT(!m_program);
2438         m_program = new OutputCountShader(m_spec);
2439
2440         // Case init
2441         GeometryShaderRenderTest::init();
2442 }
2443
2444 void OutputCountCase::deinit (void)
2445 {
2446         if (m_program)
2447         {
2448                 delete m_program;
2449                 m_program = DE_NULL;
2450         }
2451
2452         GeometryShaderRenderTest::deinit();
2453 }
2454
2455 sglr::ShaderProgram& OutputCountCase::getProgram (void)
2456 {
2457         return *m_program;
2458 }
2459
2460 void OutputCountCase::genVertexAttribData (void)
2461 {
2462         m_vertexPosData.resize(m_primitiveCount);
2463         m_vertexAttrData.resize(m_primitiveCount);
2464
2465         for (int ndx = 0; ndx < m_primitiveCount; ++ndx)
2466         {
2467                 m_vertexPosData[ndx] = tcu::Vec4(-1.0f, ((float)ndx) / (float)m_primitiveCount * 2.0f - 1.0f, 0.0f, 1.0f);
2468                 m_vertexAttrData[ndx] = (ndx % 2 == 0) ? tcu::Vec4(1, 1, 1, 1) : tcu::Vec4(1, 0, 0, 1);
2469         }
2470
2471         m_numDrawVertices = m_primitiveCount;
2472 }
2473
2474 class BuiltinVariableRenderTest : public GeometryShaderRenderTest
2475 {
2476 public:
2477                                                                                                 BuiltinVariableRenderTest       (Context& context, const char* name, const char* desc, BuiltinVariableShader::VariableTest test, int flags = 0);
2478
2479 private:
2480         void                                                                            init                                            (void);
2481
2482         sglr::ShaderProgram&                                            getProgram                                      (void);
2483         void                                                                            genVertexAttribData                     (void);
2484
2485         BuiltinVariableShader                                           m_program;
2486         const BuiltinVariableShader::VariableTest       m_test;
2487 };
2488
2489 BuiltinVariableRenderTest::BuiltinVariableRenderTest (Context& context, const char* name, const char* desc, BuiltinVariableShader::VariableTest test, int flags)
2490         : GeometryShaderRenderTest      (context, name, desc, GL_POINTS, GL_POINTS, BuiltinVariableShader::getTestAttributeName(test), flags)
2491         , m_program                                     (test)
2492         , m_test                                        (test)
2493 {
2494 }
2495
2496 void BuiltinVariableRenderTest::init (void)
2497 {
2498         // Requirements
2499         if (m_test == BuiltinVariableShader::TEST_POINT_SIZE)
2500         {
2501                 const float requiredPointSize = 5.0f;
2502
2503                 tcu::Vec2 range = tcu::Vec2(1.0f, 1.0f);
2504
2505                 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_point_size"))
2506                         throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_point_size extension");
2507
2508                 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range.getPtr());
2509                 if (range.y() < requiredPointSize)
2510                         throw tcu::NotSupportedError("Test case requires point size " + de::toString(requiredPointSize));
2511         }
2512
2513         // Shader init
2514         GeometryShaderRenderTest::init();
2515 }
2516
2517 sglr::ShaderProgram& BuiltinVariableRenderTest::getProgram (void)
2518 {
2519         return m_program;
2520 }
2521
2522 void BuiltinVariableRenderTest::genVertexAttribData (void)
2523 {
2524         m_vertexPosData.resize(4);
2525         m_vertexPosData[0] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 1.0f);
2526         m_vertexPosData[1] = tcu::Vec4( 0.0f,  0.5f, 0.0f, 1.0f);
2527         m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f);
2528         m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f);
2529
2530         m_vertexAttrData.resize(4);
2531         m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
2532         m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
2533         m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f);
2534         m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f);
2535
2536         // Only used by primitive ID restart test
2537         m_indices.resize(4);
2538         m_indices[0] = 3;
2539         m_indices[1] = 2;
2540         m_indices[2] = 0xFFFF; // restart
2541         m_indices[3] = 1;
2542
2543         m_numDrawVertices = 4;
2544 }
2545
2546 class LayeredRenderCase : public TestCase
2547 {
2548 public:
2549         enum LayeredRenderTargetType
2550         {
2551                 TARGET_CUBE = 0,
2552                 TARGET_3D,
2553                 TARGET_1D_ARRAY,
2554                 TARGET_2D_ARRAY,
2555                 TARGET_2D_MS_ARRAY,
2556
2557                 TARGET_LAST
2558         };
2559         enum TestType
2560         {
2561                 TEST_DEFAULT_LAYER,                                             // !< draw to default layer
2562                 TEST_SINGLE_LAYER,                                              // !< draw to single layer
2563                 TEST_ALL_LAYERS,                                                // !< draw all layers
2564                 TEST_DIFFERENT_LAYERS,                                  // !< draw different content to different layers
2565                 TEST_INVOCATION_PER_LAYER,                              // !< draw to all layers, one invocation per layer
2566                 TEST_MULTIPLE_LAYERS_PER_INVOCATION,    // !< draw to all layers, multiple invocations write to multiple layers
2567                 TEST_LAYER_ID,                                                  // !< draw to all layers, verify gl_Layer fragment input
2568                 TEST_LAYER_PROVOKING_VERTEX,                    // !< draw primitive with vertices in different layers, check which layer it was drawn to
2569
2570                 TEST_LAST
2571         };
2572                                                                                 LayeredRenderCase                       (Context& context, const char* name, const char* desc, LayeredRenderTargetType target, TestType test);
2573                                                                                 ~LayeredRenderCase                      (void);
2574
2575         void                                                            init                                            (void);
2576         void                                                            deinit                                          (void);
2577         IterateResult                                           iterate                                         (void);
2578
2579 private:
2580         void                                                            initTexture                                     (void);
2581         void                                                            initFbo                                         (void);
2582         void                                                            initRenderShader                        (void);
2583         void                                                            initSamplerShader                       (void);
2584
2585         std::string                                                     genFragmentSource                       (void) const;
2586         std::string                                                     genGeometrySource                       (void) const;
2587         std::string                                                     genSamplerFragmentSource        (void) const;
2588
2589         void                                                            renderToTexture                         (void);
2590         void                                                            sampleTextureLayer                      (tcu::Surface& dst, int layer);
2591         bool                                                            verifyLayerContent                      (const tcu::Surface& layer, int layerNdx);
2592         bool                                                            verifyImageSingleColoredRow (const tcu::Surface& layer, float rowWidthRatio, const tcu::Vec4& color, bool logging = true);
2593         bool                                                            verifyEmptyImage                        (const tcu::Surface& layer, bool logging = true);
2594         bool                                                            verifyProvokingVertexLayers     (const tcu::Surface& layer0, const tcu::Surface& layer1);
2595
2596         static int                                                      getTargetLayers                         (LayeredRenderTargetType target);
2597         static glw::GLenum                                      getTargetTextureTarget          (LayeredRenderTargetType target);
2598         static tcu::IVec3                                       getTargetDimensions                     (LayeredRenderTargetType target);
2599         static tcu::IVec2                                       getResolveDimensions            (LayeredRenderTargetType target);
2600
2601         const LayeredRenderTargetType           m_target;
2602         const TestType                                          m_test;
2603         const int                                                       m_numLayers;
2604         const int                                                       m_targetLayer;
2605         const tcu::IVec2                                        m_resolveDimensions;
2606
2607         int                                                                     m_iteration;
2608         bool                                                            m_allLayersOk;
2609
2610         glw::GLuint                                                     m_texture;
2611         glw::GLuint                                                     m_fbo;
2612         glu::ShaderProgram*                                     m_renderShader;
2613         glu::ShaderProgram*                                     m_samplerShader;
2614
2615         glw::GLint                                                      m_samplerSamplerLoc;
2616         glw::GLint                                                      m_samplerLayerLoc;
2617
2618         glw::GLenum                                                     m_provokingVertex;
2619 };
2620
2621 LayeredRenderCase::LayeredRenderCase (Context& context, const char* name, const char* desc, LayeredRenderTargetType target, TestType test)
2622         : TestCase                              (context, name, desc)
2623         , m_target                              (target)
2624         , m_test                                (test)
2625         , m_numLayers                   (getTargetLayers(target))
2626         , m_targetLayer                 (m_numLayers / 2)
2627         , m_resolveDimensions   (getResolveDimensions(target))
2628         , m_iteration                   (0)
2629         , m_allLayersOk                 (true)
2630         , m_texture                             (0)
2631         , m_fbo                                 (0)
2632         , m_renderShader                (DE_NULL)
2633         , m_samplerShader               (DE_NULL)
2634         , m_samplerSamplerLoc   (-1)
2635         , m_samplerLayerLoc             (-1)
2636         , m_provokingVertex             (0)
2637 {
2638 }
2639
2640 LayeredRenderCase::~LayeredRenderCase (void)
2641 {
2642         deinit();
2643 }
2644
2645 void LayeredRenderCase::init (void)
2646 {
2647         // Requirements
2648
2649         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
2650                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
2651
2652         if (m_target == TARGET_2D_MS_ARRAY && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
2653                 throw tcu::NotSupportedError("Test requires OES_texture_storage_multisample_2d_array extension");
2654
2655         if (m_context.getRenderTarget().getWidth() < m_resolveDimensions.x() || m_context.getRenderTarget().getHeight() < m_resolveDimensions.y())
2656                 throw tcu::NotSupportedError("Render target size must be at least " + de::toString(m_resolveDimensions.x()) + "x" + de::toString(m_resolveDimensions.y()));
2657
2658         // log what the test tries to do
2659
2660         if (m_test == TEST_DEFAULT_LAYER)
2661                 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to the default layer." << tcu::TestLog::EndMessage;
2662         else if (m_test == TEST_SINGLE_LAYER)
2663                 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to a single layer." << tcu::TestLog::EndMessage;
2664         else if (m_test == TEST_ALL_LAYERS)
2665                 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to all layers." << tcu::TestLog::EndMessage;
2666         else if (m_test == TEST_DIFFERENT_LAYERS)
2667                 m_testCtx.getLog() << tcu::TestLog::Message << "Outputting different number of vertices to each layer." << tcu::TestLog::EndMessage;
2668         else if (m_test == TEST_INVOCATION_PER_LAYER)
2669                 m_testCtx.getLog() << tcu::TestLog::Message << "Using a different invocation to output to each layer." << tcu::TestLog::EndMessage;
2670         else if (m_test == TEST_MULTIPLE_LAYERS_PER_INVOCATION)
2671                 m_testCtx.getLog() << tcu::TestLog::Message << "Outputting to each layer from multiple invocations." << tcu::TestLog::EndMessage;
2672         else if (m_test == TEST_LAYER_ID)
2673                 m_testCtx.getLog() << tcu::TestLog::Message << "Using gl_Layer in fragment shader." << tcu::TestLog::EndMessage;
2674         else if (m_test == TEST_LAYER_PROVOKING_VERTEX)
2675                 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying LAYER_PROVOKING_VERTEX." << tcu::TestLog::EndMessage;
2676         else
2677                 DE_ASSERT(false);
2678
2679         // init resources
2680
2681         initTexture();
2682         initFbo();
2683         initRenderShader();
2684         initSamplerShader();
2685 }
2686
2687 void LayeredRenderCase::deinit (void)
2688 {
2689         if (m_texture)
2690         {
2691                 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture);
2692                 m_texture = 0;
2693         }
2694
2695         if (m_fbo)
2696         {
2697                 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_fbo);
2698                 m_fbo = 0;
2699         }
2700
2701         delete m_renderShader;
2702         delete m_samplerShader;
2703
2704         m_renderShader = DE_NULL;
2705         m_samplerShader = DE_NULL;
2706 }
2707
2708 LayeredRenderCase::IterateResult LayeredRenderCase::iterate (void)
2709 {
2710         ++m_iteration;
2711
2712         if (m_iteration == 1)
2713         {
2714                 if (m_test == TEST_LAYER_PROVOKING_VERTEX)
2715                 {
2716                         // which layer the implementation claims to render to
2717
2718                         gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state;
2719
2720                         m_context.getRenderContext().getFunctions().getIntegerv(GL_LAYER_PROVOKING_VERTEX, &state);
2721                         GLU_EXPECT_NO_ERROR(m_context.getRenderContext().getFunctions().getError(), "getInteger(GL_LAYER_PROVOKING_VERTEX)");
2722
2723                         if (!state.verifyValidity(m_testCtx))
2724                                 return STOP;
2725
2726                         m_testCtx.getLog() << tcu::TestLog::Message << "GL_LAYER_PROVOKING_VERTEX = " << glu::getProvokingVertexStr(state) << tcu::TestLog::EndMessage;
2727
2728                         if (state != GL_FIRST_VERTEX_CONVENTION &&
2729                                 state != GL_LAST_VERTEX_CONVENTION &&
2730                                 state != GL_UNDEFINED_VERTEX)
2731                         {
2732                                 m_testCtx.getLog() << tcu::TestLog::Message << "getInteger(GL_LAYER_PROVOKING_VERTEX) returned illegal value. Got " << state << tcu::TestLog::EndMessage;
2733                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected provoking vertex value");
2734                                 return STOP;
2735                         }
2736
2737                         m_provokingVertex = (glw::GLenum)state;
2738                 }
2739
2740                 // render to texture
2741                 {
2742                         const tcu::ScopedLogSection section(m_testCtx.getLog(), "RenderToTexture", "Render to layered texture");
2743
2744                         // render to layered texture with the geometry shader
2745                         renderToTexture();
2746                 }
2747
2748                 return CONTINUE;
2749         }
2750         else if (m_test == TEST_LAYER_PROVOKING_VERTEX && m_provokingVertex == GL_UNDEFINED_VERTEX)
2751         {
2752                 // Verification requires information from another layers, layers not independent
2753                 {
2754                         const tcu::ScopedLogSection     section         (m_testCtx.getLog(), "VerifyLayers", "Verify layers 0 and 1");
2755                         tcu::Surface                            layer0          (m_resolveDimensions.x(), m_resolveDimensions.y());
2756                         tcu::Surface                            layer1          (m_resolveDimensions.x(), m_resolveDimensions.y());
2757
2758                         // sample layer to frame buffer
2759                         sampleTextureLayer(layer0, 0);
2760                         sampleTextureLayer(layer1, 1);
2761
2762                         m_allLayersOk &= verifyProvokingVertexLayers(layer0, layer1);
2763                 }
2764
2765                 // Other layers empty
2766                 for (int layerNdx = 2; layerNdx < m_numLayers; ++layerNdx)
2767                 {
2768                         const tcu::ScopedLogSection     section         (m_testCtx.getLog(), "VerifyLayer", "Verify layer " + de::toString(layerNdx));
2769                         tcu::Surface                            layer           (m_resolveDimensions.x(), m_resolveDimensions.y());
2770
2771                         // sample layer to frame buffer
2772                         sampleTextureLayer(layer, layerNdx);
2773
2774                         // verify
2775                         m_allLayersOk &= verifyEmptyImage(layer);
2776                 }
2777         }
2778         else
2779         {
2780                 // Layers independent
2781
2782                 const int                                       layerNdx        = m_iteration - 2;
2783                 const tcu::ScopedLogSection     section         (m_testCtx.getLog(), "VerifyLayer", "Verify layer " + de::toString(layerNdx));
2784                 tcu::Surface                            layer           (m_resolveDimensions.x(), m_resolveDimensions.y());
2785
2786                 // sample layer to frame buffer
2787                 sampleTextureLayer(layer, layerNdx);
2788
2789                 // verify
2790                 m_allLayersOk &= verifyLayerContent(layer, layerNdx);
2791
2792                 if (layerNdx < m_numLayers-1)
2793                         return CONTINUE;
2794         }
2795
2796         // last iteration
2797         if (m_allLayersOk)
2798                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2799         else
2800                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Detected invalid layer content");
2801
2802         return STOP;
2803 }
2804
2805 void LayeredRenderCase::initTexture (void)
2806 {
2807         DE_ASSERT(!m_texture);
2808
2809         const glw::Functions&           gl                              = m_context.getRenderContext().getFunctions();
2810         const tcu::IVec3                        texSize                 = getTargetDimensions(m_target);
2811         const tcu::TextureFormat        texFormat               = glu::mapGLInternalFormat(GL_RGBA8);
2812         const glu::TransferFormat       transferFormat  = glu::getTransferFormat(texFormat);
2813
2814         gl.genTextures(1, &m_texture);
2815         GLU_EXPECT_NO_ERROR(gl.getError(), "gen texture");
2816
2817         switch (m_target)
2818         {
2819                 case TARGET_CUBE:
2820                         m_testCtx.getLog() << tcu::TestLog::Message << "Creating cubemap texture, size = " << texSize.x() << "x" << texSize.y() << tcu::TestLog::EndMessage;
2821                         gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture);
2822                         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2823                         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2824                         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2825                         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2826                         gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2827                         gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2828                         break;
2829
2830                 case TARGET_3D:
2831                         m_testCtx.getLog() << tcu::TestLog::Message << "Creating 3d texture, size = " << texSize.x() << "x" << texSize.y() << "x" << texSize.z() << tcu::TestLog::EndMessage;
2832                         gl.bindTexture(GL_TEXTURE_3D, m_texture);
2833                         gl.texImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, texSize.x(), texSize.y(), texSize.z(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2834                         break;
2835
2836                 case TARGET_1D_ARRAY:
2837                         m_testCtx.getLog() << tcu::TestLog::Message << "Creating 1d texture array, size = " << texSize.x() << ", layers = " << texSize.y() << tcu::TestLog::EndMessage;
2838                         gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_texture);
2839                         gl.texImage2D(GL_TEXTURE_1D_ARRAY, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2840                         break;
2841
2842                 case TARGET_2D_ARRAY:
2843                         m_testCtx.getLog() << tcu::TestLog::Message << "Creating 2d texture array, size = " << texSize.x() << "x" << texSize.y() << ", layers = " << texSize.z() << tcu::TestLog::EndMessage;
2844                         gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
2845                         gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, texSize.x(), texSize.y(), texSize.z(), 0, transferFormat.format, transferFormat.dataType, DE_NULL);
2846                         break;
2847
2848                 case TARGET_2D_MS_ARRAY:
2849                 {
2850                         const int numSamples = 2;
2851
2852                         int maxSamples = 0;
2853                         gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxSamples);
2854
2855                         m_testCtx.getLog() << tcu::TestLog::Message << "Creating 2d multisample texture array, size = " << texSize.x() << "x" << texSize.y() << ", layers = " << texSize.z() << ", samples = " << numSamples << tcu::TestLog::EndMessage;
2856
2857                         if (numSamples > maxSamples)
2858                                 throw tcu::NotSupportedError("Test requires " + de::toString(numSamples) + " color texture samples." );
2859
2860                         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, m_texture);
2861                         gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, numSamples, GL_RGBA8, texSize.x(), texSize.y(), texSize.z(), GL_TRUE);
2862                         break;
2863                 }
2864
2865                 default:
2866                         DE_ASSERT(DE_FALSE);
2867         }
2868         GLU_EXPECT_NO_ERROR(gl.getError(), "tex image");
2869
2870         // Multisample textures don't use filters
2871         if (getTargetTextureTarget(m_target) != GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
2872         {
2873                 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2874                 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2875                 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_WRAP_S, GL_REPEAT);
2876                 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_WRAP_T, GL_REPEAT);
2877                 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_WRAP_R, GL_REPEAT);
2878                 GLU_EXPECT_NO_ERROR(gl.getError(), "tex filter");
2879         }
2880 }
2881
2882 void LayeredRenderCase::initFbo (void)
2883 {
2884         DE_ASSERT(!m_fbo);
2885
2886         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2887
2888         m_testCtx.getLog() << tcu::TestLog::Message << "Creating FBO" << tcu::TestLog::EndMessage;
2889
2890         gl.genFramebuffers(1, &m_fbo);
2891         gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
2892         gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture, 0);
2893         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
2894
2895         GLU_EXPECT_NO_ERROR(gl.getError(), "setup fbo");
2896 }
2897
2898 void LayeredRenderCase::initRenderShader (void)
2899 {
2900         const tcu::ScopedLogSection section(m_testCtx.getLog(), "RenderToTextureShader", "Create layered rendering shader program");
2901
2902         static const char* const positionVertex =       "#version 310 es\n"
2903                                                                                                 "void main (void)\n"
2904                                                                                                 "{\n"
2905                                                                                                 "       gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
2906                                                                                                 "}\n";
2907
2908         m_renderShader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(positionVertex) << glu::FragmentSource(genFragmentSource()) << glu::GeometrySource(genGeometrySource()));
2909         m_testCtx.getLog() << *m_renderShader;
2910
2911         if (!m_renderShader->isOk())
2912                 throw tcu::TestError("failed to build render shader");
2913 }
2914
2915 void LayeredRenderCase::initSamplerShader (void)
2916 {
2917         const tcu::ScopedLogSection section(m_testCtx.getLog(), "TextureSamplerShader", "Create shader sampler program");
2918
2919         static const char* const positionVertex =       "#version 310 es\n"
2920                                                                                                 "in highp vec4 a_position;\n"
2921                                                                                                 "void main (void)\n"
2922                                                                                                 "{\n"
2923                                                                                                 "       gl_Position = a_position;\n"
2924                                                                                                 "}\n";
2925
2926         m_samplerShader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
2927                                                                                                                                                         << glu::VertexSource(positionVertex)
2928                                                                                                                                                         << glu::FragmentSource(genSamplerFragmentSource()));
2929
2930         m_testCtx.getLog() << *m_samplerShader;
2931
2932         if (!m_samplerShader->isOk())
2933                 throw tcu::TestError("failed to build sampler shader");
2934
2935         m_samplerSamplerLoc = m_context.getRenderContext().getFunctions().getUniformLocation(m_samplerShader->getProgram(), "u_sampler");
2936         if (m_samplerSamplerLoc == -1)
2937                 throw tcu::TestError("u_sampler uniform location = -1");
2938
2939         m_samplerLayerLoc = m_context.getRenderContext().getFunctions().getUniformLocation(m_samplerShader->getProgram(), "u_layer");
2940         if (m_samplerLayerLoc == -1)
2941                 throw tcu::TestError("u_layer uniform location = -1");
2942 }
2943
2944 std::string LayeredRenderCase::genFragmentSource (void) const
2945 {
2946         static const char* const fragmentLayerIdShader =        "#version 310 es\n"
2947                                                                                                                 "#extension GL_EXT_geometry_shader : require\n"
2948                                                                                                                 "layout(location = 0) out mediump vec4 fragColor;\n"
2949                                                                                                                 "void main (void)\n"
2950                                                                                                                 "{\n"
2951                                                                                                                 "       fragColor = vec4(((gl_Layer % 2) == 1) ? 1.0 : 0.5,\n"
2952                                                                                                                 "                        (((gl_Layer / 2) % 2) == 1) ? 1.0 : 0.5,\n"
2953                                                                                                                 "                        (gl_Layer == 0) ? 1.0 : 0.0,\n"
2954                                                                                                                 "                        1.0);\n"
2955                                                                                                                 "}\n";
2956
2957         if (m_test != TEST_LAYER_ID)
2958                 return std::string(s_commonShaderSourceFragment);
2959         else
2960                 return std::string(fragmentLayerIdShader);
2961 }
2962
2963 std::string LayeredRenderCase::genGeometrySource (void) const
2964 {
2965         // TEST_DIFFERENT_LAYERS:                               draw 0 quad to first layer, 1 to second, etc.
2966         // TEST_ALL_LAYERS:                                             draw 1 quad to all layers
2967         // TEST_MULTIPLE_LAYERS_PER_INVOCATION: draw 1 triangle to "current layer" and 1 triangle to another layer
2968         // else:                                                                draw 1 quad to some single layer
2969         const int                       maxVertices =           (m_test == TEST_DIFFERENT_LAYERS) ? ((2 + m_numLayers-1) * m_numLayers) :
2970                                                                                         (m_test == TEST_ALL_LAYERS || m_test == TEST_LAYER_ID) ? (m_numLayers * 4) :
2971                                                                                         (m_test == TEST_MULTIPLE_LAYERS_PER_INVOCATION) ? (6) :
2972                                                                                         (m_test == TEST_LAYER_PROVOKING_VERTEX) ? (6) :
2973                                                                                         (4);
2974         std::ostringstream      buf;
2975
2976         buf <<  "#version 310 es\n"
2977                         "#extension GL_EXT_geometry_shader : require\n";
2978
2979         if (m_test == TEST_INVOCATION_PER_LAYER || m_test == TEST_MULTIPLE_LAYERS_PER_INVOCATION)
2980                 buf << "layout(points, invocations=" << m_numLayers << ") in;\n";
2981         else
2982                 buf << "layout(points) in;\n";
2983
2984         buf <<  "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
2985                         "out highp vec4 v_frag_FragColor;\n"
2986                         "\n"
2987                         "void main (void)\n"
2988                         "{\n";
2989
2990         if (m_test == TEST_DEFAULT_LAYER)
2991         {
2992                 buf <<  "       const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n\n"
2993                                 "       gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
2994                                 "       v_frag_FragColor = white;\n"
2995                                 "       EmitVertex();\n\n"
2996                                 "       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
2997                                 "       v_frag_FragColor = white;\n"
2998                                 "       EmitVertex();\n\n"
2999                                 "       gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
3000                                 "       v_frag_FragColor = white;\n"
3001                                 "       EmitVertex();\n\n"
3002                                 "       gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
3003                                 "       v_frag_FragColor = white;\n"
3004                                 "       EmitVertex();\n";
3005         }
3006         else if (m_test == TEST_SINGLE_LAYER)
3007         {
3008                 buf <<  "       const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n\n"
3009                                 "       gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
3010                                 "       gl_Layer = " << m_targetLayer << ";\n"
3011                                 "       v_frag_FragColor = white;\n"
3012                                 "       EmitVertex();\n\n"
3013                                 "       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
3014                                 "       gl_Layer = " << m_targetLayer << ";\n"
3015                                 "       v_frag_FragColor = white;\n"
3016                                 "       EmitVertex();\n\n"
3017                                 "       gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
3018                                 "       gl_Layer = " << m_targetLayer << ";\n"
3019                                 "       v_frag_FragColor = white;\n"
3020                                 "       EmitVertex();\n\n"
3021                                 "       gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
3022                                 "       gl_Layer = " << m_targetLayer << ";\n"
3023                                 "       v_frag_FragColor = white;\n"
3024                                 "       EmitVertex();\n";
3025         }
3026         else if (m_test == TEST_ALL_LAYERS || m_test == TEST_LAYER_ID)
3027         {
3028                 DE_ASSERT(m_numLayers <= 6);
3029
3030                 buf <<  "       const highp vec4 white   = vec4(1.0, 1.0, 1.0, 1.0);\n"
3031                                 "       const highp vec4 red     = vec4(1.0, 0.0, 0.0, 1.0);\n"
3032                                 "       const highp vec4 green   = vec4(0.0, 1.0, 0.0, 1.0);\n"
3033                                 "       const highp vec4 blue    = vec4(0.0, 0.0, 1.0, 1.0);\n"
3034                                 "       const highp vec4 yellow  = vec4(1.0, 1.0, 0.0, 1.0);\n"
3035                                 "       const highp vec4 magenta = vec4(1.0, 0.0, 1.0, 1.0);\n"
3036                                 "       const highp vec4 colors[6] = vec4[6](white, red, green, blue, yellow, magenta);\n\n"
3037                                 "       for (mediump int layerNdx = 0; layerNdx < " << m_numLayers << "; ++layerNdx)\n"
3038                                 "       {\n"
3039                                 "               gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
3040                                 "               gl_Layer = layerNdx;\n"
3041                                 "               v_frag_FragColor = colors[layerNdx];\n"
3042                                 "               EmitVertex();\n\n"
3043                                 "               gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
3044                                 "               gl_Layer = layerNdx;\n"
3045                                 "               v_frag_FragColor = colors[layerNdx];\n"
3046                                 "               EmitVertex();\n\n"
3047                                 "               gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
3048                                 "               gl_Layer = layerNdx;\n"
3049                                 "               v_frag_FragColor = colors[layerNdx];\n"
3050                                 "               EmitVertex();\n\n"
3051                                 "               gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
3052                                 "               gl_Layer = layerNdx;\n"
3053                                 "               v_frag_FragColor = colors[layerNdx];\n"
3054                                 "               EmitVertex();\n"
3055                                 "               EndPrimitive();\n"
3056                                 "       }\n";
3057         }
3058         else if (m_test == TEST_DIFFERENT_LAYERS)
3059         {
3060                 DE_ASSERT(m_numLayers <= 6);
3061
3062                 buf <<  "       const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n\n"
3063                                 "       for (mediump int layerNdx = 0; layerNdx < " << m_numLayers << "; ++layerNdx)\n"
3064                                 "       {\n"
3065                                 "               for (mediump int colNdx = 0; colNdx <= layerNdx; ++colNdx)\n"
3066                                 "               {\n"
3067                                 "                       highp float posX = float(colNdx) / float(" << m_numLayers << ") * 2.0 - 1.0;\n\n"
3068                                 "                       gl_Position = vec4(posX,  1.0, 0.0, 1.0);\n"
3069                                 "                       gl_Layer = layerNdx;\n"
3070                                 "                       v_frag_FragColor = white;\n"
3071                                 "                       EmitVertex();\n\n"
3072                                 "                       gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
3073                                 "                       gl_Layer = layerNdx;\n"
3074                                 "                       v_frag_FragColor = white;\n"
3075                                 "                       EmitVertex();\n"
3076                                 "               }\n"
3077                                 "               EndPrimitive();\n"
3078                                 "       }\n";
3079         }
3080         else if (m_test == TEST_INVOCATION_PER_LAYER)
3081         {
3082                 buf <<  "       const highp vec4 white   = vec4(1.0, 1.0, 1.0, 1.0);\n"
3083                                 "       const highp vec4 red     = vec4(1.0, 0.0, 0.0, 1.0);\n"
3084                                 "       const highp vec4 green   = vec4(0.0, 1.0, 0.0, 1.0);\n"
3085                                 "       const highp vec4 blue    = vec4(0.0, 0.0, 1.0, 1.0);\n"
3086                                 "       const highp vec4 yellow  = vec4(1.0, 1.0, 0.0, 1.0);\n"
3087                                 "       const highp vec4 magenta = vec4(1.0, 0.0, 1.0, 1.0);\n"
3088                                 "       const highp vec4 colors[6] = vec4[6](white, red, green, blue, yellow, magenta);\n"
3089                                 "\n"
3090                                 "       gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
3091                                 "       gl_Layer = gl_InvocationID;\n"
3092                                 "       v_frag_FragColor = colors[gl_InvocationID];\n"
3093                                 "       EmitVertex();\n\n"
3094                                 "       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
3095                                 "       gl_Layer = gl_InvocationID;\n"
3096                                 "       v_frag_FragColor = colors[gl_InvocationID];\n"
3097                                 "       EmitVertex();\n\n"
3098                                 "       gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
3099                                 "       gl_Layer = gl_InvocationID;\n"
3100                                 "       v_frag_FragColor = colors[gl_InvocationID];\n"
3101                                 "       EmitVertex();\n\n"
3102                                 "       gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
3103                                 "       gl_Layer = gl_InvocationID;\n"
3104                                 "       v_frag_FragColor = colors[gl_InvocationID];\n"
3105                                 "       EmitVertex();\n"
3106                                 "       EndPrimitive();\n";
3107         }
3108         else if (m_test == TEST_MULTIPLE_LAYERS_PER_INVOCATION)
3109         {
3110                 buf <<  "       const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n"
3111                                 "\n"
3112                                 "       mediump int layerA = gl_InvocationID;\n"
3113                                 "       mediump int layerB = (gl_InvocationID + 1) % " << m_numLayers << ";\n"
3114                                 "       highp float aEnd = float(layerA) / float(" << m_numLayers << ") * 2.0 - 1.0;\n"
3115                                 "       highp float bEnd = float(layerB) / float(" << m_numLayers << ") * 2.0 - 1.0;\n"
3116                                 "\n"
3117                                 "       gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
3118                                 "       gl_Layer = layerA;\n"
3119                                 "       v_frag_FragColor = white;\n"
3120                                 "       EmitVertex();\n\n"
3121                                 "       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
3122                                 "       gl_Layer = layerA;\n"
3123                                 "       v_frag_FragColor = white;\n"
3124                                 "       EmitVertex();\n\n"
3125                                 "       gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
3126                                 "       gl_Layer = layerA;\n"
3127                                 "       v_frag_FragColor = white;\n"
3128                                 "       EmitVertex();\n\n"
3129                                 "       EndPrimitive();\n"
3130                                 "\n"
3131                                 "       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
3132                                 "       gl_Layer = layerB;\n"
3133                                 "       v_frag_FragColor = white;\n"
3134                                 "       EmitVertex();\n\n"
3135                                 "       gl_Position = vec4(bEnd,  1.0, 0.0, 1.0);\n"
3136                                 "       gl_Layer = layerB;\n"
3137                                 "       v_frag_FragColor = white;\n"
3138                                 "       EmitVertex();\n\n"
3139                                 "       gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
3140                                 "       gl_Layer = layerB;\n"
3141                                 "       v_frag_FragColor = white;\n"
3142                                 "       EmitVertex();\n\n"
3143                                 "       EndPrimitive();\n";
3144         }
3145         else if (m_test == TEST_LAYER_PROVOKING_VERTEX)
3146         {
3147                 buf <<  "       const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n\n"
3148                                 "       gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
3149                                 "       gl_Layer = 0;\n"
3150                                 "       v_frag_FragColor = white;\n"
3151                                 "       EmitVertex();\n\n"
3152                                 "       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
3153                                 "       gl_Layer = 1;\n"
3154                                 "       v_frag_FragColor = white;\n"
3155                                 "       EmitVertex();\n\n"
3156                                 "       gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
3157                                 "       gl_Layer = 1;\n"
3158                                 "       v_frag_FragColor = white;\n"
3159                                 "       EmitVertex();\n\n"
3160                                 "       EndPrimitive();\n\n"
3161                                 "       gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
3162                                 "       gl_Layer = 0;\n"
3163                                 "       v_frag_FragColor = white;\n"
3164                                 "       EmitVertex();\n\n"
3165                                 "       gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
3166                                 "       gl_Layer = 1;\n"
3167                                 "       v_frag_FragColor = white;\n"
3168                                 "       EmitVertex();\n\n"
3169                                 "       gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
3170                                 "       gl_Layer = 1;\n"
3171                                 "       v_frag_FragColor = white;\n"
3172                                 "       EmitVertex();\n";
3173         }
3174         else
3175                 DE_ASSERT(DE_FALSE);
3176
3177         buf <<  "}\n";
3178
3179         return buf.str();
3180 }
3181
3182 std::string LayeredRenderCase::genSamplerFragmentSource (void) const
3183 {
3184         std::ostringstream buf;
3185
3186         buf << "#version 310 es\n";
3187         if (m_target == TARGET_2D_MS_ARRAY)
3188                 buf << "#extension GL_OES_texture_storage_multisample_2d_array : require\n";
3189         buf << "layout(location = 0) out mediump vec4 fragColor;\n";
3190
3191         switch (m_target)
3192         {
3193                 case TARGET_CUBE:                       buf << "uniform highp samplerCube u_sampler;\n";                break;
3194                 case TARGET_3D:                         buf << "uniform highp sampler3D u_sampler;\n";                  break;
3195                 case TARGET_2D_ARRAY:           buf << "uniform highp sampler2DArray u_sampler;\n";             break;
3196                 case TARGET_1D_ARRAY:           buf << "uniform highp sampler1DArray u_sampler;\n";             break;
3197                 case TARGET_2D_MS_ARRAY:        buf << "uniform highp sampler2DMSArray u_sampler;\n";   break;
3198                 default:
3199                         DE_ASSERT(DE_FALSE);
3200         }
3201
3202         buf <<  "uniform highp int u_layer;\n"
3203                         "void main (void)\n"
3204                         "{\n";
3205
3206         switch (m_target)
3207         {
3208                 case TARGET_CUBE:
3209                         buf <<  "       highp vec2 facepos = 2.0 * gl_FragCoord.xy / vec2(ivec2(" << m_resolveDimensions.x() << ", " << m_resolveDimensions.y() << ")) - vec2(1.0, 1.0);\n"
3210                                         "       if (u_layer == 0)\n"
3211                                         "               fragColor = textureLod(u_sampler, vec3(1.0, -facepos.y, -facepos.x), 0.0);\n"
3212                                         "       else if (u_layer == 1)\n"
3213                                         "               fragColor = textureLod(u_sampler, vec3(-1.0, -facepos.y, facepos.x), 0.0);\n"
3214                                         "       else if (u_layer == 2)\n"
3215                                         "               fragColor = textureLod(u_sampler, vec3(facepos.x, 1.0, facepos.y), 0.0);\n"
3216                                         "       else if (u_layer == 3)\n"
3217                                         "               fragColor = textureLod(u_sampler, vec3(facepos.x, -1.0, -facepos.y), 0.0);\n"
3218                                         "       else if (u_layer == 4)\n"
3219                                         "               fragColor = textureLod(u_sampler, vec3(facepos.x, -facepos.y, 1.0), 0.0);\n"
3220                                         "       else if (u_layer == 5)\n"
3221                                         "               fragColor = textureLod(u_sampler, vec3(-facepos.x, -facepos.y, -1.0), 0.0);\n"
3222                                         "       else\n"
3223                                         "               fragColor = vec4(1.0, 0.0, 1.0, 1.0);\n";
3224                         break;
3225
3226                 case TARGET_3D:
3227                 case TARGET_2D_ARRAY:
3228                 case TARGET_2D_MS_ARRAY:
3229                         buf <<  "       highp ivec2 screenpos = ivec2(floor(gl_FragCoord.xy));\n"
3230                                         "       fragColor = texelFetch(u_sampler, ivec3(screenpos, u_layer), 0);\n";
3231                         break;
3232
3233                 case TARGET_1D_ARRAY:
3234                         buf <<  "       highp ivec2 screenpos = ivec2(floor(gl_FragCoord.xy));\n"
3235                                         "       fragColor = texelFetch(u_sampler, ivec2(screenpos.x, u_layer), 0);\n";
3236                         break;
3237
3238                 default:
3239                         DE_ASSERT(DE_FALSE);
3240         }
3241         buf <<  "}\n";
3242         return buf.str();
3243 }
3244
3245 void LayeredRenderCase::renderToTexture (void)
3246 {
3247         const tcu::IVec3                texSize         = getTargetDimensions(m_target);
3248         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
3249         glu::VertexArray                vao                     (m_context.getRenderContext());
3250
3251         m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to texture" << tcu::TestLog::EndMessage;
3252
3253         gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
3254         gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
3255         gl.clear(GL_COLOR_BUFFER_BIT);
3256         gl.viewport(0, 0, texSize.x(), texSize.y());
3257         gl.clear(GL_COLOR_BUFFER_BIT);
3258
3259         gl.bindVertexArray(*vao);
3260         gl.useProgram(m_renderShader->getProgram());
3261         gl.drawArrays(GL_POINTS, 0, 1);
3262         gl.useProgram(0);
3263         gl.bindVertexArray(0);
3264         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
3265
3266         GLU_EXPECT_NO_ERROR(gl.getError(), "render");
3267 }
3268
3269 void LayeredRenderCase::sampleTextureLayer (tcu::Surface& dst, int layer)
3270 {
3271         DE_ASSERT(dst.getWidth() == m_resolveDimensions.x());
3272         DE_ASSERT(dst.getHeight() == m_resolveDimensions.y());
3273
3274         static const tcu::Vec4 fullscreenQuad[4] =
3275         {
3276                 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
3277                 tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
3278                 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
3279                 tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
3280         };
3281
3282         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
3283         const int                               positionLoc     = gl.getAttribLocation(m_samplerShader->getProgram(), "a_position");
3284         glu::VertexArray                vao                     (m_context.getRenderContext());
3285         glu::Buffer                             buf                     (m_context.getRenderContext());
3286
3287         m_testCtx.getLog() << tcu::TestLog::Message << "Sampling from texture layer " << layer << tcu::TestLog::EndMessage;
3288
3289         gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
3290         gl.clear(GL_COLOR_BUFFER_BIT);
3291         gl.viewport(0, 0, m_resolveDimensions.x(), m_resolveDimensions.y());
3292         GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
3293
3294         gl.bindBuffer(GL_ARRAY_BUFFER, *buf);
3295         gl.bufferData(GL_ARRAY_BUFFER, sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW);
3296         GLU_EXPECT_NO_ERROR(gl.getError(), "buf");
3297
3298         gl.bindVertexArray(*vao);
3299         gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
3300         gl.enableVertexAttribArray(positionLoc);
3301         GLU_EXPECT_NO_ERROR(gl.getError(), "setup attribs");
3302
3303         gl.activeTexture(GL_TEXTURE0);
3304         gl.bindTexture(getTargetTextureTarget(m_target), m_texture);
3305         GLU_EXPECT_NO_ERROR(gl.getError(), "bind texture");
3306
3307         gl.useProgram(m_samplerShader->getProgram());
3308         gl.uniform1i(m_samplerLayerLoc, layer);
3309         gl.uniform1i(m_samplerSamplerLoc, 0);
3310         GLU_EXPECT_NO_ERROR(gl.getError(), "setup program");
3311
3312         gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
3313         GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
3314
3315         gl.useProgram(0);
3316         gl.bindVertexArray(0);
3317         GLU_EXPECT_NO_ERROR(gl.getError(), "clean");
3318
3319         glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
3320 }
3321
3322 bool LayeredRenderCase::verifyLayerContent (const tcu::Surface& layer, int layerNdx)
3323 {
3324         const tcu::Vec4 white   = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
3325         const tcu::Vec4 red     = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
3326         const tcu::Vec4 green   = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
3327         const tcu::Vec4 blue    = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
3328         const tcu::Vec4 yellow  = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
3329         const tcu::Vec4 magenta = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f);
3330         const tcu::Vec4 colors[6] = { white, red, green, blue, yellow, magenta };
3331
3332         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying layer contents" << tcu::TestLog::EndMessage;
3333
3334         switch (m_test)
3335         {
3336                 case TEST_DEFAULT_LAYER:
3337                         if (layerNdx == 0)
3338                                 return verifyImageSingleColoredRow(layer, 0.5f, white);
3339                         else
3340                                 return verifyEmptyImage(layer);
3341
3342                 case TEST_SINGLE_LAYER:
3343                         if (layerNdx == m_targetLayer)
3344                                 return verifyImageSingleColoredRow(layer, 0.5f, white);
3345                         else
3346                                 return verifyEmptyImage(layer);
3347
3348                 case TEST_ALL_LAYERS:
3349                 case TEST_INVOCATION_PER_LAYER:
3350                         return verifyImageSingleColoredRow(layer, 0.5f, colors[layerNdx]);
3351
3352                 case TEST_DIFFERENT_LAYERS:
3353                 case TEST_MULTIPLE_LAYERS_PER_INVOCATION:
3354                         if (layerNdx == 0)
3355                                 return verifyEmptyImage(layer);
3356                         else
3357                                 return verifyImageSingleColoredRow(layer, (float)layerNdx / (float)m_numLayers, white);
3358
3359                 case TEST_LAYER_ID:
3360                 {
3361                         const tcu::Vec4 layerColor((layerNdx % 2 == 1) ? (1.0f) : (0.5f),
3362                                                                            ((layerNdx/2) % 2 == 1) ? (1.0f) : (0.5f),
3363                                                                            (layerNdx == 0) ? (1.0f) : (0.0f),
3364                                                                            1.0f);
3365                         return verifyImageSingleColoredRow(layer, 0.5f, layerColor);
3366                 }
3367
3368                 case TEST_LAYER_PROVOKING_VERTEX:
3369                         if (m_provokingVertex == GL_FIRST_VERTEX_CONVENTION)
3370                         {
3371                                 if (layerNdx == 0)
3372                                         return verifyImageSingleColoredRow(layer, 0.5f, white);
3373                                 else
3374                                         return verifyEmptyImage(layer);
3375                         }
3376                         else if (m_provokingVertex == GL_LAST_VERTEX_CONVENTION)
3377                         {
3378                                 if (layerNdx == 1)
3379                                         return verifyImageSingleColoredRow(layer, 0.5f, white);
3380                                 else
3381                                         return verifyEmptyImage(layer);
3382                         }
3383                         else
3384                         {
3385                                 DE_ASSERT(false);
3386                                 return false;
3387                         }
3388
3389                 default:
3390                         DE_ASSERT(DE_FALSE);
3391                         return false;
3392         };
3393 }
3394
3395 bool LayeredRenderCase::verifyImageSingleColoredRow (const tcu::Surface& layer, float rowWidthRatio, const tcu::Vec4& barColor, bool logging)
3396 {
3397         DE_ASSERT(rowWidthRatio > 0.0f);
3398
3399         const int               barLength                       = (int)(rowWidthRatio * (float)layer.getWidth());
3400         const int               barLengthThreshold      = 1;
3401         tcu::Surface    errorMask                       (layer.getWidth(), layer.getHeight());
3402         bool                    allPixelsOk                     = true;
3403
3404         if (logging)
3405                 m_testCtx.getLog() << tcu::TestLog::Message << "Expecting all pixels with distance less or equal to (about) " << barLength << " pixels from left border to be of color " << barColor.swizzle(0,1,2) << "." << tcu::TestLog::EndMessage;
3406
3407         tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
3408
3409         for (int y = 0; y < layer.getHeight(); ++y)
3410         for (int x = 0; x < layer.getWidth(); ++x)
3411         {
3412                 const tcu::RGBA color           = layer.getPixel(x, y);
3413                 const tcu::RGBA refColor        = tcu::RGBA(barColor);
3414                 const int               threshold       = 8;
3415                 const bool              isBlack         = color.getRed() <= threshold || color.getGreen() <= threshold || color.getBlue() <= threshold;
3416                 const bool              isColor         = tcu::allEqual(tcu::lessThan(tcu::abs(color.toIVec().swizzle(0, 1, 2) - refColor.toIVec().swizzle(0, 1, 2)), tcu::IVec3(threshold, threshold, threshold)), tcu::BVec3(true, true, true));
3417
3418                 bool                    isOk;
3419
3420                 if (x <= barLength - barLengthThreshold)
3421                         isOk = isColor;
3422                 else if (x >= barLength + barLengthThreshold)
3423                         isOk = isBlack;
3424                 else
3425                         isOk = isColor || isBlack;
3426
3427                 allPixelsOk &= isOk;
3428
3429                 if (!isOk)
3430                         errorMask.setPixel(x, y, tcu::RGBA::red());
3431         }
3432
3433         if (allPixelsOk)
3434         {
3435                 if (logging)
3436                         m_testCtx.getLog()      << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
3437                                                                 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
3438                                                                 << tcu::TestLog::Image("Layer", "Layer", layer)
3439                                                                 << tcu::TestLog::EndImageSet;
3440                 return true;
3441         }
3442         else
3443         {
3444                 if (logging)
3445                         m_testCtx.getLog()      << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
3446                                                                 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
3447                                                                 << tcu::TestLog::Image("Layer",         "Layer",        layer)
3448                                                                 << tcu::TestLog::Image("ErrorMask",     "Errors",       errorMask)
3449                                                                 << tcu::TestLog::EndImageSet;
3450                 return false;
3451         }
3452
3453         if (logging)
3454                 m_testCtx.getLog() << tcu::TestLog::Image("LayerContent", "Layer content", layer);
3455
3456         return allPixelsOk;
3457 }
3458
3459 bool LayeredRenderCase::verifyEmptyImage (const tcu::Surface& layer, bool logging)
3460 {
3461         // Expect black
3462         if (logging)
3463                 m_testCtx.getLog() << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
3464
3465         for (int y = 0; y < layer.getHeight(); ++y)
3466         for (int x = 0; x < layer.getWidth(); ++x)
3467         {
3468                 const tcu::RGBA color           = layer.getPixel(x, y);
3469                 const int               threshold       = 8;
3470                 const bool              isBlack         = color.getRed() <= threshold || color.getGreen() <= threshold || color.getBlue() <= threshold;
3471
3472                 if (!isBlack)
3473                 {
3474                         if (logging)
3475                                 m_testCtx.getLog()      << tcu::TestLog::Message
3476                                                                         << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
3477                                                                         << tcu::TestLog::EndMessage
3478                                                                         << tcu::TestLog::ImageSet("LayerContent", "Layer content")
3479                                                                         << tcu::TestLog::Image("Layer", "Layer", layer)
3480                                                                         << tcu::TestLog::EndImageSet;
3481                         return false;
3482                 }
3483         }
3484
3485         if (logging)
3486                 m_testCtx.getLog() << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
3487
3488         return true;
3489 }
3490
3491 bool LayeredRenderCase::verifyProvokingVertexLayers (const tcu::Surface& layer0, const tcu::Surface& layer1)
3492 {
3493         const bool              layer0Empty             = verifyEmptyImage(layer0, false);
3494         const bool              layer1Empty             = verifyEmptyImage(layer1, false);
3495         bool                    error                   = false;
3496
3497         // Both images could contain something if the quad triangles get assigned to different layers
3498         m_testCtx.getLog() << tcu::TestLog::Message << "Expecting non-empty layers, or non-empty layer." << tcu::TestLog::EndMessage;
3499
3500         if (layer0Empty == true && layer1Empty == true)
3501         {
3502                 m_testCtx.getLog() << tcu::TestLog::Message << "Got empty images." << tcu::TestLog::EndMessage;
3503                 error = true;
3504         }
3505
3506         // log images always
3507         m_testCtx.getLog()
3508                 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
3509                 << tcu::TestLog::Image("Layer", "Layer0", layer0)
3510                 << tcu::TestLog::Image("Layer", "Layer1", layer1)
3511                 << tcu::TestLog::EndImageSet;
3512
3513         if (error)
3514                 m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage;
3515         else
3516                 m_testCtx.getLog() << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage;
3517
3518         return !error;
3519 }
3520
3521 int LayeredRenderCase::getTargetLayers (LayeredRenderTargetType target)
3522 {
3523         switch (target)
3524         {
3525                 case TARGET_CUBE:                       return 6;
3526                 case TARGET_3D:                         return 4;
3527                 case TARGET_1D_ARRAY:           return 4;
3528                 case TARGET_2D_ARRAY:           return 4;
3529                 case TARGET_2D_MS_ARRAY:        return 2;
3530                 default:
3531                         DE_ASSERT(DE_FALSE);
3532                         return 0;
3533         }
3534 }
3535
3536 glw::GLenum LayeredRenderCase::getTargetTextureTarget (LayeredRenderTargetType target)
3537 {
3538         switch (target)
3539         {
3540                 case TARGET_CUBE:                       return GL_TEXTURE_CUBE_MAP;
3541                 case TARGET_3D:                         return GL_TEXTURE_3D;
3542                 case TARGET_1D_ARRAY:           return GL_TEXTURE_1D_ARRAY;
3543                 case TARGET_2D_ARRAY:           return GL_TEXTURE_2D_ARRAY;
3544                 case TARGET_2D_MS_ARRAY:        return GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
3545                 default:
3546                         DE_ASSERT(DE_FALSE);
3547                         return 0;
3548         }
3549 }
3550
3551 tcu::IVec3 LayeredRenderCase::getTargetDimensions (LayeredRenderTargetType target)
3552 {
3553         switch (target)
3554         {
3555                 case TARGET_CUBE:                       return tcu::IVec3(64, 64, 0);
3556                 case TARGET_3D:                         return tcu::IVec3(64, 64, 4);
3557                 case TARGET_1D_ARRAY:           return tcu::IVec3(64, 4, 0);
3558                 case TARGET_2D_ARRAY:           return tcu::IVec3(64, 64, 4);
3559                 case TARGET_2D_MS_ARRAY:        return tcu::IVec3(64, 64, 2);
3560                 default:
3561                         DE_ASSERT(DE_FALSE);
3562                         return tcu::IVec3(0, 0, 0);
3563         }
3564 }
3565
3566 tcu::IVec2 LayeredRenderCase::getResolveDimensions (LayeredRenderTargetType target)
3567 {
3568         switch (target)
3569         {
3570                 case TARGET_CUBE:                       return tcu::IVec2(64, 64);
3571                 case TARGET_3D:                         return tcu::IVec2(64, 64);
3572                 case TARGET_1D_ARRAY:           return tcu::IVec2(64, 1);
3573                 case TARGET_2D_ARRAY:           return tcu::IVec2(64, 64);
3574                 case TARGET_2D_MS_ARRAY:        return tcu::IVec2(64, 64);
3575                 default:
3576                         DE_ASSERT(DE_FALSE);
3577                         return tcu::IVec2(0, 0);
3578         }
3579 }
3580
3581 class VaryingOutputCountCase : public GeometryShaderRenderTest
3582 {
3583 public:
3584         enum ShaderInstancingMode
3585         {
3586                 MODE_WITHOUT_INSTANCING = 0,
3587                 MODE_WITH_INSTANCING,
3588
3589                 MODE_LAST
3590         };
3591                                                                                                         VaryingOutputCountCase                  (Context& context, const char* name, const char* desc, VaryingOutputCountShader::VaryingSource test, ShaderInstancingMode mode);
3592 private:
3593         void                                                                                    init                                                    (void);
3594         void                                                                                    deinit                                                  (void);
3595         void                                                                                    preRender                                               (sglr::Context& ctx, GLuint programID);
3596
3597         sglr::ShaderProgram&                                                    getProgram                                              (void);
3598         void                                                                                    genVertexAttribData                             (void);
3599         void                                                                                    genVertexDataWithoutInstancing  (void);
3600         void                                                                                    genVertexDataWithInstancing             (void);
3601
3602         VaryingOutputCountShader*                                               m_program;
3603         const VaryingOutputCountShader::VaryingSource   m_test;
3604         const ShaderInstancingMode                                              m_mode;
3605         int                                                                                             m_maxEmitCount;
3606 };
3607
3608 VaryingOutputCountCase::VaryingOutputCountCase (Context& context, const char* name, const char* desc, VaryingOutputCountShader::VaryingSource test, ShaderInstancingMode mode)
3609         : GeometryShaderRenderTest      (context, name, desc, GL_POINTS, GL_TRIANGLE_STRIP, VaryingOutputCountShader::getAttributeName(test))
3610         , m_program                                     (DE_NULL)
3611         , m_test                                        (test)
3612         , m_mode                                        (mode)
3613         , m_maxEmitCount                        (0)
3614 {
3615         DE_ASSERT(mode < MODE_LAST);
3616 }
3617
3618 void VaryingOutputCountCase::init (void)
3619 {
3620         // Check requirements
3621
3622         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
3623                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
3624
3625         if (m_test == VaryingOutputCountShader::READ_TEXTURE)
3626         {
3627                 glw::GLint maxTextures = 0;
3628
3629                 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &maxTextures);
3630
3631                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS = " << maxTextures << tcu::TestLog::EndMessage;
3632
3633                 if (maxTextures < 1)
3634                         throw tcu::NotSupportedError("Geometry shader texture units required");
3635         }
3636
3637         // Get max emit count
3638         {
3639                 const int       componentsPerVertex     = 4 + 4; // vec4 pos, vec4 color
3640                 glw::GLint      maxVertices                     = 0;
3641                 glw::GLint      maxComponents           = 0;
3642
3643                 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &maxVertices);
3644                 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &maxComponents);
3645
3646                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_OUTPUT_VERTICES = " << maxVertices << tcu::TestLog::EndMessage;
3647                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = " << maxComponents << tcu::TestLog::EndMessage;
3648                 m_testCtx.getLog() << tcu::TestLog::Message << "Components per vertex = " << componentsPerVertex << tcu::TestLog::EndMessage;
3649
3650                 if (maxVertices < 256)
3651                         throw tcu::TestError("MAX_GEOMETRY_OUTPUT_VERTICES was less than minimum required (256)");
3652                 if (maxComponents < 1024)
3653                         throw tcu::TestError("MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS was less than minimum required (1024)");
3654
3655                 m_maxEmitCount = de::min(maxVertices, maxComponents / componentsPerVertex);
3656         }
3657
3658         // Log what the test tries to do
3659
3660         m_testCtx.getLog()
3661                 << tcu::TestLog::Message
3662                 << "Rendering 4 n-gons with n = "
3663                 << ((VaryingOutputCountShader::EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_0)) << ", "
3664                 << ((VaryingOutputCountShader::EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_1)) << ", "
3665                 << ((VaryingOutputCountShader::EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_2)) << ", and "
3666                 << ((VaryingOutputCountShader::EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_3)) << ".\n"
3667                 << "N is supplied to the geomery shader with "
3668                 << ((m_test == VaryingOutputCountShader::READ_ATTRIBUTE) ? ("attribute") : (m_test == VaryingOutputCountShader::READ_UNIFORM) ? ("uniform") : ("texture"))
3669                 << tcu::TestLog::EndMessage;
3670
3671         // Gen shader
3672         {
3673                 const bool instanced = (m_mode == MODE_WITH_INSTANCING);
3674
3675                 DE_ASSERT(!m_program);
3676                 m_program = new VaryingOutputCountShader(m_test, m_maxEmitCount, instanced);
3677         }
3678
3679         // Case init
3680         GeometryShaderRenderTest::init();
3681 }
3682
3683 void VaryingOutputCountCase::deinit (void)
3684 {
3685         if (m_program)
3686         {
3687                 delete m_program;
3688                 m_program = DE_NULL;
3689         }
3690
3691         GeometryShaderRenderTest::deinit();
3692 }
3693
3694 void VaryingOutputCountCase::preRender (sglr::Context& ctx, GLuint programID)
3695 {
3696         if (m_test == VaryingOutputCountShader::READ_UNIFORM)
3697         {
3698                 const int               location                = ctx.getUniformLocation(programID, "u_emitCount");
3699                 const deInt32   emitCount[4]    = { 6, 0, m_maxEmitCount, 10 };
3700
3701                 if (location == -1)
3702                         throw tcu::TestError("uniform location of u_emitCount was -1.");
3703
3704                 ctx.uniform4iv(location, 1, emitCount);
3705         }
3706         else if (m_test == VaryingOutputCountShader::READ_TEXTURE)
3707         {
3708                 const deUint8 data[4*4] =
3709                 {
3710                         255,   0,   0,   0,
3711                           0, 255,   0,   0,
3712                           0,   0, 255,   0,
3713                           0,   0,   0, 255,
3714                 };
3715                 const int       location        = ctx.getUniformLocation(programID, "u_sampler");
3716                 GLuint          texID           = 0;
3717
3718                 if (location == -1)
3719                         throw tcu::TestError("uniform location of u_sampler was -1.");
3720                 ctx.uniform1i(location, 0);
3721
3722                 // \note we don't need to explicitly delete the texture, the sglr context will delete it
3723                 ctx.genTextures(1, &texID);
3724                 ctx.bindTexture(GL_TEXTURE_2D, texID);
3725                 ctx.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
3726                 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3727                 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3728         }
3729 }
3730
3731 sglr::ShaderProgram& VaryingOutputCountCase::getProgram (void)
3732 {
3733         return *m_program;
3734 }
3735
3736 void VaryingOutputCountCase::genVertexAttribData (void)
3737 {
3738         if (m_mode == MODE_WITHOUT_INSTANCING)
3739                 genVertexDataWithoutInstancing();
3740         else if (m_mode == MODE_WITH_INSTANCING)
3741                 genVertexDataWithInstancing();
3742         else
3743                 DE_ASSERT(false);
3744 }
3745
3746 void VaryingOutputCountCase::genVertexDataWithoutInstancing (void)
3747 {
3748         m_numDrawVertices = 4;
3749
3750         m_vertexPosData.resize(4);
3751         m_vertexAttrData.resize(4);
3752
3753         m_vertexPosData[0] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 1.0f);
3754         m_vertexPosData[1] = tcu::Vec4( 0.0f,  0.5f, 0.0f, 1.0f);
3755         m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f);
3756         m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f);
3757
3758         if (m_test == VaryingOutputCountShader::READ_ATTRIBUTE)
3759         {
3760                 m_vertexAttrData[0] = tcu::Vec4(((VaryingOutputCountShader::EMIT_COUNT_VERTEX_0 == -1) ? ((float)m_maxEmitCount) : ((float)VaryingOutputCountShader::EMIT_COUNT_VERTEX_0)), 0.0f, 0.0f, 0.0f);
3761                 m_vertexAttrData[1] = tcu::Vec4(((VaryingOutputCountShader::EMIT_COUNT_VERTEX_1 == -1) ? ((float)m_maxEmitCount) : ((float)VaryingOutputCountShader::EMIT_COUNT_VERTEX_1)), 0.0f, 0.0f, 0.0f);
3762                 m_vertexAttrData[2] = tcu::Vec4(((VaryingOutputCountShader::EMIT_COUNT_VERTEX_2 == -1) ? ((float)m_maxEmitCount) : ((float)VaryingOutputCountShader::EMIT_COUNT_VERTEX_2)), 0.0f, 0.0f, 0.0f);
3763                 m_vertexAttrData[3] = tcu::Vec4(((VaryingOutputCountShader::EMIT_COUNT_VERTEX_3 == -1) ? ((float)m_maxEmitCount) : ((float)VaryingOutputCountShader::EMIT_COUNT_VERTEX_3)), 0.0f, 0.0f, 0.0f);
3764         }
3765         else
3766         {
3767                 m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
3768                 m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
3769                 m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f);
3770                 m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f);
3771         }
3772 }
3773
3774 void VaryingOutputCountCase::genVertexDataWithInstancing (void)
3775 {
3776         m_numDrawVertices = 1;
3777
3778         m_vertexPosData.resize(1);
3779         m_vertexAttrData.resize(1);
3780
3781         m_vertexPosData[0] = tcu::Vec4(0.0f,  0.0f, 0.0f, 1.0f);
3782
3783         if (m_test == VaryingOutputCountShader::READ_ATTRIBUTE)
3784         {
3785                 const int emitCounts[] =
3786                 {
3787                         (VaryingOutputCountShader::EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_0),
3788                         (VaryingOutputCountShader::EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_1),
3789                         (VaryingOutputCountShader::EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_2),
3790                         (VaryingOutputCountShader::EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_3),
3791                 };
3792
3793                 m_vertexAttrData[0] = tcu::Vec4((float)emitCounts[0], (float)emitCounts[1], (float)emitCounts[2], (float)emitCounts[3]);
3794         }
3795         else
3796         {
3797                 // not used
3798                 m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
3799         }
3800 }
3801
3802 class GeometryProgramQueryCase : public TestCase
3803 {
3804 public:
3805         struct ProgramCase
3806         {
3807                 const char*     description;
3808                 const char*     header;
3809                 int                     value;
3810         };
3811
3812                                                 GeometryProgramQueryCase                        (Context& context, const char* name, const char* description, glw::GLenum target);
3813
3814         void                            init                                                            (void);
3815         IterateResult           iterate                                                         (void);
3816
3817 private:
3818         void                            expectProgramValue                                      (deUint32 program, int value);
3819         void                            expectQueryError                                        (deUint32 program);
3820
3821         const glw::GLenum       m_target;
3822
3823 protected:
3824         std::vector<ProgramCase> m_cases;
3825 };
3826
3827 GeometryProgramQueryCase::GeometryProgramQueryCase (Context& context, const char* name, const char* description, glw::GLenum target)
3828         : TestCase      (context, name, description)
3829         , m_target      (target)
3830 {
3831 }
3832
3833 void GeometryProgramQueryCase::init (void)
3834 {
3835         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
3836                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
3837 }
3838
3839 GeometryProgramQueryCase::IterateResult GeometryProgramQueryCase::iterate (void)
3840 {
3841         static const char* const s_vertexSource =                       "#version 310 es\n"
3842                                                                                                                 "void main ()\n"
3843                                                                                                                 "{\n"
3844                                                                                                                 "       gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
3845                                                                                                                 "}\n";
3846         static const char* const s_fragmentSource =                     "#version 310 es\n"
3847                                                                                                                 "layout(location = 0) out mediump vec4 fragColor;\n"
3848                                                                                                                 "void main ()\n"
3849                                                                                                                 "{\n"
3850                                                                                                                 "       fragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
3851                                                                                                                 "}\n";
3852         static const char* const s_geometryBody =                       "void main ()\n"
3853                                                                                                                 "{\n"
3854                                                                                                                 "       gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
3855                                                                                                                 "       EmitVertex();\n"
3856                                                                                                                 "}\n";
3857
3858         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3859
3860         // default cases
3861         for (int ndx = 0; ndx < (int)m_cases.size(); ++ndx)
3862         {
3863                 const tcu::ScopedLogSection section                     (m_testCtx.getLog(), "Case", m_cases[ndx].description);
3864                 const std::string                       geometrySource  = m_cases[ndx].header + std::string(s_geometryBody);
3865                 const glu::ShaderProgram        program                 (m_context.getRenderContext(),
3866                                                                                                         glu::ProgramSources()
3867                                                                                                                 << glu::VertexSource(s_vertexSource)
3868                                                                                                                 << glu::FragmentSource(s_fragmentSource)
3869                                                                                                                 << glu::GeometrySource(geometrySource));
3870
3871                 m_testCtx.getLog() << program;
3872                 expectProgramValue(program.getProgram(), m_cases[ndx].value);
3873         }
3874
3875         // no geometry shader -case (INVALID OP)
3876         {
3877                 const tcu::ScopedLogSection section                     (m_testCtx.getLog(), "NoGeometryShader", "No geometry shader");
3878                 const glu::ShaderProgram        program                 (m_context.getRenderContext(),
3879                                                                                                         glu::ProgramSources()
3880                                                                                                                 << glu::VertexSource(s_vertexSource)
3881                                                                                                                 << glu::FragmentSource(s_fragmentSource));
3882
3883                 m_testCtx.getLog() << program;
3884                 expectQueryError(program.getProgram());
3885         }
3886
3887         // not linked -case (INVALID OP)
3888         {
3889                 const tcu::ScopedLogSection section                     (m_testCtx.getLog(), "NotLinkedProgram", "Shader program not linked");
3890                 const std::string                       geometrySource  = "#version 310 es\n"
3891                                                                                                           "#extension GL_EXT_geometry_shader : require\n"
3892                                                                                                           "layout (triangles) in;\n"
3893                                                                                                           "layout (points, max_vertices = 3) out;\n"
3894                                                                                                           + std::string(s_geometryBody);
3895
3896
3897                 glu::Shader                                     vertexShader    (m_context.getRenderContext(), glu::SHADERTYPE_VERTEX);
3898                 glu::Shader                                     fragmentShader  (m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
3899                 glu::Shader                                     geometryShader  (m_context.getRenderContext(), glu::SHADERTYPE_GEOMETRY);
3900                 glu::Program                            program                 (m_context.getRenderContext());
3901
3902                 const char* const                       geometrySourceArray[1] = { geometrySource.c_str() };
3903
3904                 vertexShader.setSources(1, &s_vertexSource, DE_NULL);
3905                 fragmentShader.setSources(1, &s_fragmentSource, DE_NULL);
3906                 geometryShader.setSources(1, geometrySourceArray, DE_NULL);
3907
3908                 vertexShader.compile();
3909                 fragmentShader.compile();
3910                 geometryShader.compile();
3911
3912                 if (!vertexShader.getCompileStatus()   ||
3913                         !fragmentShader.getCompileStatus() ||
3914                         !geometryShader.getCompileStatus())
3915                         throw tcu::TestError("Failed to compile shader");
3916
3917                 program.attachShader(vertexShader.getShader());
3918                 program.attachShader(fragmentShader.getShader());
3919                 program.attachShader(geometryShader.getShader());
3920
3921                 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a program with geometry shader, but not linking it" << tcu::TestLog::EndMessage;
3922
3923                 expectQueryError(program.getProgram());
3924         }
3925
3926         return STOP;
3927 }
3928
3929 void GeometryProgramQueryCase::expectProgramValue (deUint32 program, int value)
3930 {
3931         const glw::Functions&                                                                           gl              = m_context.getRenderContext().getFunctions();
3932         gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>     state;
3933
3934         gl.getProgramiv(program, m_target, &state);
3935         GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
3936
3937         m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramParamStr(m_target) << " = " << state << tcu::TestLog::EndMessage;
3938
3939         if (state != value)
3940         {
3941                 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << value << ", got " << state << tcu::TestLog::EndMessage;
3942
3943                 // don't overwrite error
3944                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
3945                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
3946         }
3947 }
3948
3949 void GeometryProgramQueryCase::expectQueryError (deUint32 program)
3950 {
3951         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
3952         glw::GLint                              dummy;
3953         glw::GLenum                             errorCode;
3954
3955         m_testCtx.getLog() << tcu::TestLog::Message << "Querying " << glu::getProgramParamStr(m_target) << ", expecting INVALID_OPERATION" << tcu::TestLog::EndMessage;
3956         gl.getProgramiv(program, m_target, &dummy);
3957
3958         errorCode = gl.getError();
3959
3960         if (errorCode != GL_INVALID_OPERATION)
3961         {
3962                 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected INVALID_OPERATION, got " << glu::getErrorStr(errorCode) << tcu::TestLog::EndMessage;
3963
3964                 // don't overwrite error
3965                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
3966                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected error code");
3967         }
3968 }
3969
3970 class GeometryShaderInvocationsQueryCase : public GeometryProgramQueryCase
3971 {
3972 public:
3973         GeometryShaderInvocationsQueryCase(Context& context, const char* name, const char* description);
3974 };
3975
3976 GeometryShaderInvocationsQueryCase::GeometryShaderInvocationsQueryCase(Context& context, const char* name, const char* description)
3977         : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_SHADER_INVOCATIONS)
3978 {
3979         // 2 normal cases
3980         m_cases.resize(2);
3981
3982         m_cases[0].description  = "Default value";
3983         m_cases[0].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n";
3984         m_cases[0].value                = 1;
3985
3986         m_cases[1].description  = "Value declared";
3987         m_cases[1].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles, invocations=2) in;\nlayout (points, max_vertices = 3) out;\n";
3988         m_cases[1].value                = 2;
3989 }
3990
3991 class GeometryShaderVerticesQueryCase : public GeometryProgramQueryCase
3992 {
3993 public:
3994         GeometryShaderVerticesQueryCase(Context& context, const char* name, const char* description);
3995 };
3996
3997 GeometryShaderVerticesQueryCase::GeometryShaderVerticesQueryCase(Context& context, const char* name, const char* description)
3998         : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_VERTICES_OUT_EXT)
3999 {
4000         m_cases.resize(1);
4001
4002         m_cases[0].description  = "max_vertices = 1";
4003         m_cases[0].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 1) out;\n";
4004         m_cases[0].value                = 1;
4005 }
4006
4007 class GeometryShaderInputQueryCase : public GeometryProgramQueryCase
4008 {
4009 public:
4010         GeometryShaderInputQueryCase(Context& context, const char* name, const char* description);
4011 };
4012
4013 GeometryShaderInputQueryCase::GeometryShaderInputQueryCase(Context& context, const char* name, const char* description)
4014         : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_INPUT_TYPE_EXT)
4015 {
4016         m_cases.resize(3);
4017
4018         m_cases[0].description  = "Triangles";
4019         m_cases[0].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n";
4020         m_cases[0].value                = GL_TRIANGLES;
4021
4022         m_cases[1].description  = "Lines";
4023         m_cases[1].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (lines) in;\nlayout (points, max_vertices = 3) out;\n";
4024         m_cases[1].value                = GL_LINES;
4025
4026         m_cases[2].description  = "Points";
4027         m_cases[2].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (points) in;\nlayout (points, max_vertices = 3) out;\n";
4028         m_cases[2].value                = GL_POINTS;
4029 }
4030
4031 class GeometryShaderOutputQueryCase : public GeometryProgramQueryCase
4032 {
4033 public:
4034         GeometryShaderOutputQueryCase(Context& context, const char* name, const char* description);
4035 };
4036
4037 GeometryShaderOutputQueryCase::GeometryShaderOutputQueryCase(Context& context, const char* name, const char* description)
4038         : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT)
4039 {
4040         m_cases.resize(3);
4041
4042         m_cases[0].description  = "Triangle strip";
4043         m_cases[0].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (triangle_strip, max_vertices = 3) out;\n";
4044         m_cases[0].value                = GL_TRIANGLE_STRIP;
4045
4046         m_cases[1].description  = "Lines";
4047         m_cases[1].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (line_strip, max_vertices = 3) out;\n";
4048         m_cases[1].value                = GL_LINE_STRIP;
4049
4050         m_cases[2].description  = "Points";
4051         m_cases[2].header               = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n";
4052         m_cases[2].value                = GL_POINTS;
4053 }
4054
4055 class ImplementationLimitCase : public TestCase
4056 {
4057 public:
4058                                                 ImplementationLimitCase (Context& context, const char* name, const char* description, glw::GLenum target, int minValue);
4059
4060         void                            init                                    (void);
4061         IterateResult           iterate                                 (void);
4062
4063         const glw::GLenum       m_target;
4064         const int                       m_minValue;
4065 };
4066
4067 ImplementationLimitCase::ImplementationLimitCase (Context& context, const char* name, const char* description, glw::GLenum target, int minValue)
4068         : TestCase              (context, name, description)
4069         , m_target              (target)
4070         , m_minValue    (minValue)
4071 {
4072 }
4073
4074 void ImplementationLimitCase::init (void)
4075 {
4076         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
4077                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
4078 }
4079
4080 ImplementationLimitCase::IterateResult ImplementationLimitCase::iterate (void)
4081 {
4082         glu::CallLogWrapper             gl              (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
4083         tcu::ResultCollector    result  (m_testCtx.getLog(), " // ERROR: ");
4084
4085         gl.enableLogging(true);
4086         verifyStateIntegerMin(result, gl, m_target, m_minValue, QUERY_INTEGER);
4087
4088         {
4089                 const tcu::ScopedLogSection     section(m_testCtx.getLog(), "Types", "Alternative queries");
4090                 verifyStateIntegerMin(result, gl, m_target, m_minValue, QUERY_BOOLEAN);
4091                 verifyStateIntegerMin(result, gl, m_target, m_minValue, QUERY_INTEGER64);
4092                 verifyStateIntegerMin(result, gl, m_target, m_minValue, QUERY_FLOAT);
4093         }
4094
4095         result.setTestContextResult(m_testCtx);
4096         return STOP;
4097 }
4098
4099 class LayerProvokingVertexQueryCase : public TestCase
4100 {
4101 public:
4102                                         LayerProvokingVertexQueryCase   (Context& context, const char* name, const char* description);
4103
4104         void                    init                                                    (void);
4105         IterateResult   iterate                                                 (void);
4106 };
4107
4108 LayerProvokingVertexQueryCase::LayerProvokingVertexQueryCase(Context& context, const char* name, const char* description)
4109         : TestCase(context, name, description)
4110 {
4111 }
4112
4113 void LayerProvokingVertexQueryCase::init (void)
4114 {
4115         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
4116                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
4117 }
4118
4119 LayerProvokingVertexQueryCase::IterateResult LayerProvokingVertexQueryCase::iterate (void)
4120 {
4121         glu::CallLogWrapper             gl              (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
4122         tcu::ResultCollector    result  (m_testCtx.getLog(), " // ERROR: ");
4123         QueriedState                    state;
4124
4125         gl.enableLogging(true);
4126         queryState(result, gl, QUERY_INTEGER, GL_LAYER_PROVOKING_VERTEX, state);
4127
4128         if (!state.isUndefined())
4129         {
4130                 m_testCtx.getLog() << tcu::TestLog::Message << "LAYER_PROVOKING_VERTEX = " << glu::getProvokingVertexStr(state.getIntAccess()) << tcu::TestLog::EndMessage;
4131
4132                 if (state.getIntAccess() != GL_FIRST_VERTEX_CONVENTION &&
4133                         state.getIntAccess() != GL_LAST_VERTEX_CONVENTION &&
4134                         state.getIntAccess() != GL_UNDEFINED_VERTEX)
4135                 {
4136                         m_testCtx.getLog()
4137                                 << tcu::TestLog::Message
4138                                 << "getInteger(GL_LAYER_PROVOKING_VERTEX) returned illegal value. Got "
4139                                 << state.getIntAccess() << "\n"
4140                                 << "Expected any of {FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, UNDEFINED_VERTEX}."
4141                                 << tcu::TestLog::EndMessage;
4142
4143                         result.fail("got unexpected provoking vertex value");
4144                 }
4145
4146                 {
4147                         const tcu::ScopedLogSection     section(m_testCtx.getLog(), "Types", "Alternative queries");
4148                         verifyStateInteger(result, gl, GL_LAYER_PROVOKING_VERTEX, state.getIntAccess(), QUERY_BOOLEAN);
4149                         verifyStateInteger(result, gl, GL_LAYER_PROVOKING_VERTEX, state.getIntAccess(), QUERY_INTEGER64);
4150                         verifyStateInteger(result, gl, GL_LAYER_PROVOKING_VERTEX, state.getIntAccess(), QUERY_FLOAT);
4151                 }
4152         }
4153
4154         result.setTestContextResult(m_testCtx);
4155         return STOP;
4156 }
4157
4158 class GeometryInvocationCase : public GeometryShaderRenderTest
4159 {
4160 public:
4161         enum OutputCase
4162         {
4163                 CASE_FIXED_OUTPUT_COUNTS = 0,
4164                 CASE_DIFFERENT_OUTPUT_COUNTS,
4165
4166                 CASE_LAST
4167         };
4168
4169                                                                 GeometryInvocationCase  (Context& context, const char* name, const char* description, int numInvocations, OutputCase testCase);
4170                                                                 ~GeometryInvocationCase (void);
4171
4172         void                                            init                                    (void);
4173         void                                            deinit                                  (void);
4174
4175 private:
4176         sglr::ShaderProgram&            getProgram                              (void);
4177         void                                            genVertexAttribData             (void);
4178
4179         static InvocationCountShader::OutputCase mapToShaderCaseType (OutputCase testCase);
4180
4181         const OutputCase                        m_testCase;
4182         int                                                     m_numInvocations;
4183         InvocationCountShader*          m_program;
4184 };
4185
4186 GeometryInvocationCase::GeometryInvocationCase (Context& context, const char* name, const char* description, int numInvocations, OutputCase testCase)
4187         : GeometryShaderRenderTest      (context, name, description, GL_POINTS, GL_TRIANGLE_STRIP, "a_color")
4188         , m_testCase                            (testCase)
4189         , m_numInvocations                      (numInvocations)
4190         , m_program                                     (DE_NULL)
4191 {
4192         DE_ASSERT(m_testCase < CASE_LAST);
4193 }
4194
4195 GeometryInvocationCase::~GeometryInvocationCase (void)
4196 {
4197         deinit();
4198 }
4199
4200 void GeometryInvocationCase::init (void)
4201 {
4202         const glw::Functions&   gl                                                              = m_context.getRenderContext().getFunctions();
4203         int                                             maxGeometryShaderInvocations    = 0;
4204         int                                             maxComponents                                   = 0;
4205
4206         // requirements
4207
4208         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
4209                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
4210
4211         gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS, &maxGeometryShaderInvocations);
4212         GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS)");
4213
4214         gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &maxComponents);
4215         GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS)");
4216
4217         m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_INVOCATIONS = " << maxGeometryShaderInvocations << tcu::TestLog::EndMessage;
4218
4219         // set target num invocations
4220
4221         if (m_numInvocations == -1)
4222                 m_numInvocations = maxGeometryShaderInvocations;
4223         else if (maxGeometryShaderInvocations < m_numInvocations)
4224                 throw tcu::NotSupportedError("Test requires larger GL_MAX_GEOMETRY_SHADER_INVOCATIONS");
4225
4226         if (m_testCase == CASE_DIFFERENT_OUTPUT_COUNTS)
4227         {
4228                 const int maxEmitCount  = m_numInvocations + 2;
4229                 const int numComponents = 8; // pos + color
4230                 if (maxEmitCount * numComponents > maxComponents)
4231                         throw tcu::NotSupportedError("Test requires larger GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS");
4232         }
4233
4234         // Log what the test tries to do
4235
4236         if (m_testCase == CASE_FIXED_OUTPUT_COUNTS)
4237         {
4238                 m_testCtx.getLog()
4239                         << tcu::TestLog::Message
4240                         << "Rendering triangles in a partial circle formation with a geometry shader. Each triangle is generated by a separate invocation.\n"
4241                         << "Drawing 2 points, each generating " << m_numInvocations << " triangles."
4242                         << tcu::TestLog::EndMessage;
4243         }
4244         else if (m_testCase == CASE_DIFFERENT_OUTPUT_COUNTS)
4245         {
4246                 m_testCtx.getLog()
4247                         << tcu::TestLog::Message
4248                         << "Rendering n-gons in a partial circle formation with a geometry shader. Each n-gon is generated by a separate invocation.\n"
4249                         << "Drawing 2 points, each generating " << m_numInvocations << " n-gons."
4250                         << tcu::TestLog::EndMessage;
4251         }
4252         else
4253                 DE_ASSERT(false);
4254
4255         // resources
4256
4257         m_program = new InvocationCountShader(m_numInvocations, mapToShaderCaseType(m_testCase));
4258
4259         GeometryShaderRenderTest::init();
4260 }
4261
4262 void GeometryInvocationCase::deinit (void)
4263 {
4264         if (m_program)
4265         {
4266                 delete m_program;
4267                 m_program = DE_NULL;
4268         }
4269
4270         GeometryShaderRenderTest::deinit();
4271 }
4272
4273 sglr::ShaderProgram& GeometryInvocationCase::getProgram (void)
4274 {
4275         return *m_program;
4276 }
4277
4278 void GeometryInvocationCase::genVertexAttribData (void)
4279 {
4280         m_vertexPosData.resize(2);
4281         m_vertexPosData[0] = tcu::Vec4(0.0f,-0.3f, 0.0f, 1.0f);
4282         m_vertexPosData[1] = tcu::Vec4(0.2f, 0.3f, 0.0f, 1.0f);
4283
4284         m_vertexAttrData.resize(2);
4285         m_vertexAttrData[0] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
4286         m_vertexAttrData[1] = tcu::Vec4(0.8f, 0.8f, 0.8f, 1.0f);
4287         m_numDrawVertices = 2;
4288 }
4289
4290 InvocationCountShader::OutputCase GeometryInvocationCase::mapToShaderCaseType (OutputCase testCase)
4291 {
4292         switch (testCase)
4293         {
4294                 case CASE_FIXED_OUTPUT_COUNTS:                  return InvocationCountShader::CASE_FIXED_OUTPUT_COUNTS;
4295                 case CASE_DIFFERENT_OUTPUT_COUNTS:              return InvocationCountShader::CASE_DIFFERENT_OUTPUT_COUNTS;
4296                 default:
4297                         DE_ASSERT(false);
4298                         return InvocationCountShader::CASE_LAST;
4299         }
4300 }
4301
4302 class DrawInstancedGeometryInstancedCase : public GeometryShaderRenderTest
4303 {
4304 public:
4305                                                                 DrawInstancedGeometryInstancedCase      (Context& context, const char* name, const char* description, int numInstances, int numInvocations);
4306                                                                 ~DrawInstancedGeometryInstancedCase     (void);
4307
4308 private:
4309         void                                            init                                                            (void);
4310         sglr::ShaderProgram&            getProgram                                                      (void);
4311         void                                            genVertexAttribData                                     (void);
4312
4313         const int                                       m_numInstances;
4314         const int                                       m_numInvocations;
4315         InstancedExpansionShader        m_program;
4316 };
4317
4318 DrawInstancedGeometryInstancedCase::DrawInstancedGeometryInstancedCase (Context& context, const char* name, const char* description, int numInstances, int numInvocations)
4319         : GeometryShaderRenderTest      (context, name, description, GL_POINTS, GL_TRIANGLE_STRIP, "a_offset", FLAG_DRAW_INSTANCED)
4320         , m_numInstances                        (numInstances)
4321         , m_numInvocations                      (numInvocations)
4322         , m_program                                     (numInvocations)
4323 {
4324 }
4325
4326 DrawInstancedGeometryInstancedCase::~DrawInstancedGeometryInstancedCase (void)
4327 {
4328 }
4329
4330 void DrawInstancedGeometryInstancedCase::init (void)
4331 {
4332         m_testCtx.getLog()
4333                 << tcu::TestLog::Message
4334                 << "Rendering a single point with " << m_numInstances << " instances. "
4335                 << "Each geometry shader is invoked " << m_numInvocations << " times for each primitive. "
4336                 << tcu::TestLog::EndMessage;
4337
4338         GeometryShaderRenderTest::init();
4339 }
4340
4341 sglr::ShaderProgram& DrawInstancedGeometryInstancedCase::getProgram (void)
4342 {
4343         return m_program;
4344 }
4345
4346 void DrawInstancedGeometryInstancedCase::genVertexAttribData (void)
4347 {
4348         m_numDrawVertices = 1;
4349         m_numDrawInstances = m_numInstances;
4350         m_vertexAttrDivisor = 1;
4351
4352         m_vertexPosData.resize(1);
4353         m_vertexAttrData.resize(8);
4354
4355         m_vertexPosData[0] = tcu::Vec4( 0.0f,  0.0f, 0.0f, 1.0f);
4356
4357         m_vertexAttrData[0] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 0.0f);
4358         m_vertexAttrData[1] = tcu::Vec4( 0.0f,  0.5f, 0.0f, 0.0f);
4359         m_vertexAttrData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 0.0f);
4360         m_vertexAttrData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 0.0f);
4361         m_vertexAttrData[4] = tcu::Vec4(-0.8f, -0.7f, 0.0f, 0.0f);
4362         m_vertexAttrData[5] = tcu::Vec4(-0.9f,  0.6f, 0.0f, 0.0f);
4363         m_vertexAttrData[6] = tcu::Vec4(-0.8f,  0.3f, 0.0f, 0.0f);
4364         m_vertexAttrData[7] = tcu::Vec4(-0.1f,  0.1f, 0.0f, 0.0f);
4365
4366         DE_ASSERT(m_numInstances <= (int)m_vertexAttrData.size());
4367 }
4368
4369 class GeometryProgramLimitCase : public TestCase
4370 {
4371 public:
4372                                                 GeometryProgramLimitCase        (Context& context, const char* name, const char* description, glw::GLenum apiName, const std::string& glslName, int limit);
4373
4374 private:
4375         void                            init                                            (void);
4376         IterateResult           iterate                                         (void);
4377
4378         const glw::GLenum       m_apiName;
4379         const std::string       m_glslName;
4380         const int                       m_limit;
4381 };
4382
4383 GeometryProgramLimitCase::GeometryProgramLimitCase (Context& context, const char* name, const char* description, glw::GLenum apiName, const std::string& glslName, int limit)
4384         : TestCase              (context, name, description)
4385         , m_apiName             (apiName)
4386         , m_glslName    (glslName)
4387         , m_limit               (limit)
4388 {
4389 }
4390
4391 void GeometryProgramLimitCase::init (void)
4392 {
4393         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
4394                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
4395 }
4396
4397 GeometryProgramLimitCase::IterateResult GeometryProgramLimitCase::iterate (void)
4398 {
4399         tcu::ResultCollector    result  (m_testCtx.getLog(), " // ERROR: ");
4400         int                                             limit;
4401
4402         // query limit
4403         {
4404                 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>     state;
4405                 glu::CallLogWrapper                                                                                     gl              (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
4406
4407                 gl.enableLogging(true);
4408                 gl.glGetIntegerv(m_apiName, &state);
4409                 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getIntegerv()");
4410
4411                 m_testCtx.getLog() << tcu::TestLog::Message << glu::getGettableStateStr(m_apiName) << " = " << state << tcu::TestLog::EndMessage;
4412
4413                 if (!state.verifyValidity(result))
4414                 {
4415                         result.setTestContextResult(m_testCtx);
4416                         return STOP;
4417                 }
4418
4419                 if (state < m_limit)
4420                 {
4421                         result.fail("Minimum value = " + de::toString(m_limit) + ", got " + de::toString(state.get()));
4422                         result.setTestContextResult(m_testCtx);
4423                         return STOP;
4424                 }
4425
4426                 limit = state;
4427
4428                 // verify other getters
4429                 {
4430                         const tcu::ScopedLogSection     section(m_testCtx.getLog(), "Types", "Alternative queries");
4431                         verifyStateInteger(result, gl, m_apiName, limit, QUERY_BOOLEAN);
4432                         verifyStateInteger(result, gl, m_apiName, limit, QUERY_INTEGER64);
4433                         verifyStateInteger(result, gl, m_apiName, limit, QUERY_FLOAT);
4434                 }
4435         }
4436
4437         // verify limit is the same in GLSL
4438         {
4439                 static const char* const vertexSource =         "#version 310 es\n"
4440                                                                                                         "void main ()\n"
4441                                                                                                         "{\n"
4442                                                                                                         "       gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
4443                                                                                                         "}\n";
4444                 static const char* const fragmentSource =       "#version 310 es\n"
4445                                                                                                         "layout(location = 0) out mediump vec4 fragColor;\n"
4446                                                                                                         "void main ()\n"
4447                                                                                                         "{\n"
4448                                                                                                         "       fragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
4449                                                                                                         "}\n";
4450                 const std::string geometrySource =                      "#version 310 es\n"
4451                                                                                                         "#extension GL_EXT_geometry_shader : require\n"
4452                                                                                                         "layout(points) in;\n"
4453                                                                                                         "layout(points, max_vertices = 1) out;\n"
4454                                                                                                         "void main ()\n"
4455                                                                                                         "{\n"
4456                                                                                                         "       // Building the shader will fail if the constant value is not the expected\n"
4457                                                                                                         "       const mediump int cArraySize = (gl_" + m_glslName + " == " + de::toString(limit) + ") ? (1) : (-1);\n"
4458                                                                                                         "       float[cArraySize] fArray;\n"
4459                                                                                                         "       fArray[0] = 0.0f;\n"
4460                                                                                                         "       gl_Position = vec4(0.0, 0.0, 0.0, fArray[0]);\n"
4461                                                                                                         "       EmitVertex();\n"
4462                                                                                                         "}\n";
4463
4464                 const de::UniquePtr<glu::ShaderProgram> program(new glu::ShaderProgram(m_context.getRenderContext(),
4465                                                                                                                                                            glu::ProgramSources()
4466                                                                                                                                                                 << glu::VertexSource(vertexSource)
4467                                                                                                                                                                 << glu::FragmentSource(fragmentSource)
4468                                                                                                                                                                 << glu::GeometrySource(geometrySource)));
4469
4470                 m_testCtx.getLog() << tcu::TestLog::Message << "Building a test shader to verify GLSL constant " << m_glslName << " value." << tcu::TestLog::EndMessage;
4471                 m_testCtx.getLog() << *program;
4472
4473                 if (!program->isOk())
4474                 {
4475                         // compile failed, assume static assert failed
4476                         result.fail("Shader build failed");
4477                         result.setTestContextResult(m_testCtx);
4478                         return STOP;
4479                 }
4480
4481                 m_testCtx.getLog() << tcu::TestLog::Message << "Build ok" << tcu::TestLog::EndMessage;
4482         }
4483
4484         result.setTestContextResult(m_testCtx);
4485         return STOP;
4486 }
4487
4488 class PrimitivesGeneratedQueryCase : public TestCase
4489 {
4490 public:
4491         enum QueryTest
4492         {
4493                 TEST_NO_GEOMETRY                        = 0,
4494                 TEST_NO_AMPLIFICATION,
4495                 TEST_AMPLIFICATION,
4496                 TEST_PARTIAL_PRIMITIVES,
4497                 TEST_INSTANCED,
4498
4499                 TEST_LAST
4500         };
4501
4502                                                 PrimitivesGeneratedQueryCase    (Context& context, const char* name, const char* description, QueryTest test);
4503                                                 ~PrimitivesGeneratedQueryCase   (void);
4504
4505 private:
4506         void                            init                                                    (void);
4507         void                            deinit                                                  (void);
4508         IterateResult           iterate                                                 (void);
4509
4510         glu::ShaderProgram*     genProgram                                              (void);
4511
4512         const QueryTest         m_test;
4513         glu::ShaderProgram*     m_program;
4514 };
4515
4516 PrimitivesGeneratedQueryCase::PrimitivesGeneratedQueryCase (Context& context, const char* name, const char* description, QueryTest test)
4517         : TestCase      (context, name, description)
4518         , m_test        (test)
4519         , m_program     (DE_NULL)
4520 {
4521         DE_ASSERT(m_test < TEST_LAST);
4522 }
4523
4524 PrimitivesGeneratedQueryCase::~PrimitivesGeneratedQueryCase (void)
4525 {
4526         deinit();
4527 }
4528
4529 void PrimitivesGeneratedQueryCase::init (void)
4530 {
4531         // requirements
4532
4533         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
4534                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
4535
4536         // log what test tries to do
4537
4538         if (m_test == TEST_NO_GEOMETRY)
4539                 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering without a geometry shader." << tcu::TestLog::EndMessage;
4540         else if (m_test == TEST_NO_AMPLIFICATION)
4541                 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a non-amplifying geometry shader." << tcu::TestLog::EndMessage;
4542         else if (m_test == TEST_AMPLIFICATION)
4543                 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a (3x) amplifying geometry shader." << tcu::TestLog::EndMessage;
4544         else if (m_test == TEST_PARTIAL_PRIMITIVES)
4545                 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a geometry shader that emits also partial primitives." << tcu::TestLog::EndMessage;
4546         else if (m_test == TEST_INSTANCED)
4547                 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a instanced geometry shader." << tcu::TestLog::EndMessage;
4548         else
4549                 DE_ASSERT(false);
4550
4551         // resources
4552
4553         m_program = genProgram();
4554         m_testCtx.getLog() << *m_program;
4555
4556         if (!m_program->isOk())
4557                 throw tcu::TestError("could not build program");
4558 }
4559
4560 void PrimitivesGeneratedQueryCase::deinit (void)
4561 {
4562         delete m_program;
4563         m_program = DE_NULL;
4564 }
4565
4566 PrimitivesGeneratedQueryCase::IterateResult PrimitivesGeneratedQueryCase::iterate (void)
4567 {
4568         glw::GLuint primitivesGenerated = 0xDEBADBAD;
4569
4570         m_testCtx.getLog()
4571                 << tcu::TestLog::Message
4572                 << "Drawing 8 points, setting a_one for each to value (1.0, 1.0, 1.0, 1.0)"
4573                 << tcu::TestLog::EndMessage;
4574
4575         {
4576                 static const tcu::Vec4 vertexData[8*2] =
4577                 {
4578                         tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),      tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
4579                         tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f),      tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
4580                         tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f),      tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
4581                         tcu::Vec4(0.3f, 0.0f, 0.0f, 1.0f),      tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
4582                         tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f),      tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
4583                         tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f),      tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
4584                         tcu::Vec4(0.6f, 0.0f, 0.0f, 1.0f),      tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
4585                         tcu::Vec4(0.7f, 0.0f, 0.0f, 1.0f),      tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
4586                 };
4587
4588                 const glw::Functions&   gl                                      = m_context.getRenderContext().getFunctions();
4589                 const glu::VertexArray  vao                                     (m_context.getRenderContext());
4590                 const glu::Buffer               buffer                          (m_context.getRenderContext());
4591                 const glu::Query                query                           (m_context.getRenderContext());
4592                 const int                               positionLocation        = gl.getAttribLocation(m_program->getProgram(), "a_position");
4593                 const int                               oneLocation                     = gl.getAttribLocation(m_program->getProgram(), "a_one");
4594
4595                 gl.bindVertexArray(*vao);
4596
4597                 gl.bindBuffer(GL_ARRAY_BUFFER, *buffer);
4598                 gl.bufferData(GL_ARRAY_BUFFER, (int)sizeof(vertexData), vertexData, GL_STATIC_DRAW);
4599
4600                 gl.vertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 2 * (int)sizeof(tcu::Vec4), DE_NULL);
4601                 gl.enableVertexAttribArray(positionLocation);
4602
4603                 if (oneLocation != -1)
4604                 {
4605                         gl.vertexAttribPointer(oneLocation, 4, GL_FLOAT, GL_FALSE, 2 * (int)sizeof(tcu::Vec4), (const tcu::Vec4*)DE_NULL + 1);
4606                         gl.enableVertexAttribArray(oneLocation);
4607                 }
4608
4609                 gl.useProgram(m_program->getProgram());
4610
4611                 GLU_EXPECT_NO_ERROR(gl.getError(), "setup render");
4612
4613                 gl.beginQuery(GL_PRIMITIVES_GENERATED, *query);
4614                 gl.drawArrays(GL_POINTS, 0, 8);
4615                 gl.endQuery(GL_PRIMITIVES_GENERATED);
4616
4617                 GLU_EXPECT_NO_ERROR(gl.getError(), "render and query");
4618
4619                 gl.getQueryObjectuiv(*query, GL_QUERY_RESULT, &primitivesGenerated);
4620                 GLU_EXPECT_NO_ERROR(gl.getError(), "get query result");
4621         }
4622
4623         m_testCtx.getLog()
4624                 << tcu::TestLog::Message
4625                 << "GL_PRIMITIVES_GENERATED = " << primitivesGenerated
4626                 << tcu::TestLog::EndMessage;
4627
4628         {
4629                 const deUint32 expectedGenerated = (m_test == TEST_AMPLIFICATION) ? (3*8) : (m_test == TEST_INSTANCED) ? (8*(3+1)) : (8);
4630
4631                 if (expectedGenerated == primitivesGenerated)
4632                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4633                 else
4634                 {
4635                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong result for GL_PRIMITIVES_GENERATED");
4636                         m_testCtx.getLog()
4637                                 << tcu::TestLog::Message
4638                                 << "Got unexpected result for GL_PRIMITIVES_GENERATED. Expected " << expectedGenerated << ", got " << primitivesGenerated
4639                                 << tcu::TestLog::EndMessage;
4640                 }
4641         }
4642
4643         return STOP;
4644 }
4645
4646 glu::ShaderProgram* PrimitivesGeneratedQueryCase::genProgram (void)
4647 {
4648         static const char* const vertexSource =         "#version 310 es\n"
4649                                                                                                 "in highp vec4 a_position;\n"
4650                                                                                                 "in highp vec4 a_one;\n"
4651                                                                                                 "out highp vec4 v_one;\n"
4652                                                                                                 "void main (void)\n"
4653                                                                                                 "{\n"
4654                                                                                                 "       gl_Position = a_position;\n"
4655                                                                                                 "       v_one = a_one;\n"
4656                                                                                                 "}\n";
4657         static const char* const fragmentSource =       "#version 310 es\n"
4658                                                                                                 "layout(location = 0) out mediump vec4 fragColor;\n"
4659                                                                                                 "void main (void)\n"
4660                                                                                                 "{\n"
4661                                                                                                 "       fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
4662                                                                                                 "}\n";
4663         std::ostringstream geometrySource;
4664         glu::ProgramSources sources;
4665
4666         if (m_test != TEST_NO_GEOMETRY)
4667         {
4668                 geometrySource <<       "#version 310 es\n"
4669                                                         "#extension GL_EXT_geometry_shader : require\n"
4670                                                         "layout(points" << ((m_test == TEST_INSTANCED) ? (", invocations = 3") : ("")) << ") in;\n"
4671                                                         "layout(triangle_strip, max_vertices = 7) out;\n"
4672                                                         "in highp vec4 v_one[];\n"
4673                                                         "void main (void)\n"
4674                                                         "{\n"
4675                                                         "       // always taken\n"
4676                                                         "       if (v_one[0].x != 0.0)\n"
4677                                                         "       {\n"
4678                                                         "               gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n"
4679                                                         "               EmitVertex();\n"
4680                                                         "               gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n"
4681                                                         "               EmitVertex();\n"
4682                                                         "               gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n"
4683                                                         "               EmitVertex();\n"
4684                                                         "               EndPrimitive();\n"
4685                                                         "       }\n";
4686
4687                 if (m_test == TEST_AMPLIFICATION)
4688                 {
4689                         geometrySource <<       "\n"
4690                                                                 "       // always taken\n"
4691                                                                 "       if (v_one[0].y != 0.0)\n"
4692                                                                 "       {\n"
4693                                                                 "               gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n"
4694                                                                 "               EmitVertex();\n"
4695                                                                 "               gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n"
4696                                                                 "               EmitVertex();\n"
4697                                                                 "               gl_Position = gl_in[0].gl_Position - vec4(0.0, 0.1, 0.0, 0.0);\n"
4698                                                                 "               EmitVertex();\n"
4699                                                                 "               gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n"
4700                                                                 "               EmitVertex();\n"
4701                                                                 "       }\n";
4702                 }
4703                 else if (m_test == TEST_PARTIAL_PRIMITIVES)
4704                 {
4705                         geometrySource <<       "\n"
4706                                                                 "       // always taken\n"
4707                                                                 "       if (v_one[0].y != 0.0)\n"
4708                                                                 "       {\n"
4709                                                                 "               gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n"
4710                                                                 "               EmitVertex();\n"
4711                                                                 "               gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n"
4712                                                                 "               EmitVertex();\n"
4713                                                                 "\n"
4714                                                                 "               // never taken\n"
4715                                                                 "               if (v_one[0].z < 0.0)\n"
4716                                                                 "               {\n"
4717                                                                 "                       gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n"
4718                                                                 "                       EmitVertex();\n"
4719                                                                 "               }\n"
4720                                                                 "       }\n";
4721                 }
4722                 else if (m_test == TEST_INSTANCED)
4723                 {
4724                         geometrySource <<       "\n"
4725                                                                 "       // taken once\n"
4726                                                                 "       if (v_one[0].y > float(gl_InvocationID) + 0.5)\n"
4727                                                                 "       {\n"
4728                                                                 "               gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n"
4729                                                                 "               EmitVertex();\n"
4730                                                                 "               gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n"
4731                                                                 "               EmitVertex();\n"
4732                                                                 "               gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n"
4733                                                                 "               EmitVertex();\n"
4734                                                                 "       }\n";
4735                 }
4736
4737                 geometrySource <<       "}\n";
4738         }
4739
4740         sources << glu::VertexSource(vertexSource);
4741         sources << glu::FragmentSource(fragmentSource);
4742
4743         if (!geometrySource.str().empty())
4744                 sources << glu::GeometrySource(geometrySource.str());
4745
4746         return new glu::ShaderProgram(m_context.getRenderContext(), sources);
4747 }
4748
4749 class PrimitivesGeneratedQueryObjectQueryCase : public TestCase
4750 {
4751 public:
4752                                         PrimitivesGeneratedQueryObjectQueryCase (Context& context, const char* name, const char* description);
4753
4754         void                    init                                                                    (void);
4755         IterateResult   iterate                                                                 (void);
4756 };
4757
4758 PrimitivesGeneratedQueryObjectQueryCase::PrimitivesGeneratedQueryObjectQueryCase (Context& context, const char* name, const char* description)
4759         : TestCase(context, name, description)
4760 {
4761 }
4762
4763 void PrimitivesGeneratedQueryObjectQueryCase::init (void)
4764 {
4765         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
4766                 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension");
4767 }
4768
4769 PrimitivesGeneratedQueryObjectQueryCase::IterateResult PrimitivesGeneratedQueryObjectQueryCase::iterate (void)
4770 {
4771         glu::CallLogWrapper     gl              (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
4772         tcu::ResultCollector    result  (m_testCtx.getLog(), " // ERROR: ");
4773
4774         gl.enableLogging(true);
4775
4776         {
4777                 glw::GLuint query = 0;
4778
4779                 verifyStateQueryInteger(result, gl, GL_PRIMITIVES_GENERATED, GL_CURRENT_QUERY, 0, QUERY_QUERY);
4780
4781                 gl.glGenQueries(1, &query);
4782                 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenQueries");
4783
4784                 gl.glBeginQuery(GL_PRIMITIVES_GENERATED, query);
4785                 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "beginQuery");
4786
4787                 verifyStateQueryInteger(result, gl, GL_PRIMITIVES_GENERATED, GL_CURRENT_QUERY, (int)query, QUERY_QUERY);
4788
4789                 gl.glEndQuery(GL_PRIMITIVES_GENERATED);
4790                 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "endQuery");
4791         }
4792
4793         result.setTestContextResult(m_testCtx);
4794         return STOP;
4795 }
4796
4797 class GeometryShaderFeartureTestCase : public TestCase
4798 {
4799 public:
4800                                         GeometryShaderFeartureTestCase  (Context& context, const char* name, const char* description);
4801
4802         void                    init                                                    (void);
4803 };
4804
4805 GeometryShaderFeartureTestCase::GeometryShaderFeartureTestCase (Context& context, const char* name, const char* description)
4806         : TestCase(context, name, description)
4807 {
4808 }
4809
4810 void GeometryShaderFeartureTestCase::init (void)
4811 {
4812         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
4813                 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension");
4814 }
4815
4816 class FramebufferDefaultLayersCase : public GeometryShaderFeartureTestCase
4817 {
4818 public:
4819                                         FramebufferDefaultLayersCase    (Context& context, const char* name, const char* description);
4820         IterateResult   iterate                                                 (void);
4821 };
4822
4823 FramebufferDefaultLayersCase::FramebufferDefaultLayersCase (Context& context, const char* name, const char* description)
4824         : GeometryShaderFeartureTestCase(context, name, description)
4825 {
4826 }
4827
4828 FramebufferDefaultLayersCase::IterateResult FramebufferDefaultLayersCase::iterate (void)
4829 {
4830         glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
4831
4832         gl.enableLogging(true);
4833
4834         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4835
4836         {
4837                 const tcu::ScopedLogSection section                     (m_testCtx.getLog(), "Default", "Default value");
4838                 const glu::Framebuffer          fbo                             (m_context.getRenderContext());
4839                 glw::GLint                                      defaultLayers   = -1;
4840
4841                 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo);
4842                 gl.glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, &defaultLayers);
4843                 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv");
4844
4845                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_DEFAULT_LAYERS = " << defaultLayers << tcu::TestLog::EndMessage;
4846
4847                 if (defaultLayers != 0)
4848                 {
4849                         m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected 0, got " << defaultLayers << tcu::TestLog::EndMessage;
4850                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count");
4851                 }
4852         }
4853
4854         {
4855                 const tcu::ScopedLogSection section                     (m_testCtx.getLog(), "SetTo12", "Set default layers to 12");
4856                 const glu::Framebuffer          fbo                             (m_context.getRenderContext());
4857                 glw::GLint                                      defaultLayers   = -1;
4858
4859                 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo);
4860                 gl.glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, 12);
4861                 gl.glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, &defaultLayers);
4862                 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv");
4863
4864                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_DEFAULT_LAYERS = " << defaultLayers << tcu::TestLog::EndMessage;
4865
4866                 if (defaultLayers != 12)
4867                 {
4868                         m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected 12, got " << defaultLayers << tcu::TestLog::EndMessage;
4869                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count");
4870                 }
4871         }
4872
4873         return STOP;
4874 }
4875
4876 class FramebufferAttachmentLayeredCase : public GeometryShaderFeartureTestCase
4877 {
4878 public:
4879                                         FramebufferAttachmentLayeredCase        (Context& context, const char* name, const char* description);
4880         IterateResult   iterate                                                         (void);
4881 };
4882
4883 FramebufferAttachmentLayeredCase::FramebufferAttachmentLayeredCase (Context& context, const char* name, const char* description)
4884         : GeometryShaderFeartureTestCase(context, name, description)
4885 {
4886 }
4887
4888 FramebufferAttachmentLayeredCase::IterateResult FramebufferAttachmentLayeredCase::iterate (void)
4889 {
4890         enum CaseType
4891         {
4892                 TEXTURE_3D,
4893                 TEXTURE_2D_ARRAY,
4894                 TEXTURE_CUBE,
4895                 TEXTURE_2D_MS_ARRAY,
4896                 TEXTURE_3D_LAYER,
4897                 TEXTURE_2D_ARRAY_LAYER,
4898         };
4899
4900         static const struct TextureType
4901         {
4902                 const char*     name;
4903                 const char*     description;
4904                 bool            layered;
4905                 CaseType        type;
4906         } textureTypes[] =
4907         {
4908                 { "3D",                         "3D texture",                   true,   TEXTURE_3D                              },
4909                 { "2DArray",            "2D array",                             true,   TEXTURE_2D_ARRAY                },
4910                 { "Cube",                       "Cube map",                             true,   TEXTURE_CUBE                    },
4911                 { "2DMSArray",          "2D multisample array", true,   TEXTURE_2D_MS_ARRAY             },
4912                 { "3DLayer",            "3D texture layer ",    false,  TEXTURE_3D_LAYER                },
4913                 { "2DArrayLayer",       "2D array layer ",              false,  TEXTURE_2D_ARRAY_LAYER  },
4914         };
4915
4916         glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
4917         gl.enableLogging(true);
4918
4919         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4920
4921         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureTypes); ++ndx)
4922         {
4923                 const tcu::ScopedLogSection section                     (m_testCtx.getLog(), textureTypes[ndx].name, textureTypes[ndx].description);
4924                 const glu::Framebuffer          fbo                             (m_context.getRenderContext());
4925                 const glu::Texture                      texture                 (m_context.getRenderContext());
4926                 glw::GLint                                      layered                 = -1;
4927
4928                 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo);
4929
4930                 if (textureTypes[ndx].type == TEXTURE_3D || textureTypes[ndx].type == TEXTURE_3D_LAYER)
4931                 {
4932                         gl.glBindTexture(GL_TEXTURE_3D, *texture);
4933                         gl.glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
4934                         gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4935                         gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4936
4937                         if (textureTypes[ndx].type == TEXTURE_3D)
4938                                 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0);
4939                         else
4940                                 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0, 2);
4941                 }
4942                 else if (textureTypes[ndx].type == TEXTURE_2D_ARRAY || textureTypes[ndx].type == TEXTURE_2D_ARRAY_LAYER)
4943                 {
4944                         gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture);
4945                         gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
4946                         gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4947                         gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4948
4949                         if (textureTypes[ndx].type == TEXTURE_2D_ARRAY)
4950                                 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0);
4951                         else
4952                                 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0, 3);
4953                 }
4954                 else if (textureTypes[ndx].type == TEXTURE_CUBE)
4955                 {
4956                         gl.glBindTexture(GL_TEXTURE_CUBE_MAP, *texture);
4957                         for (int face = 0; face < 6; ++face)
4958                                 gl.glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA8, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
4959                         gl.glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4960                         gl.glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4961                         gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0);
4962                 }
4963                 else if (textureTypes[ndx].type == TEXTURE_2D_MS_ARRAY)
4964                 {
4965                         // check extension
4966                         if (!m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
4967                         {
4968                                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_OES_texture_storage_multisample_2d_array not supported, skipping." << tcu::TestLog::EndMessage;
4969                                 continue;
4970                         }
4971
4972                         gl.glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, *texture);
4973                         gl.glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 1, GL_RGBA8, 32, 32, 32, GL_FALSE);
4974                         gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0);
4975                 }
4976
4977                 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup attachment");
4978
4979                 gl.glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_LAYERED, &layered);
4980                 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv");
4981
4982                 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_ATTACHMENT_LAYERED = " << glu::getBooleanStr(layered) << tcu::TestLog::EndMessage;
4983
4984                 if (layered != GL_TRUE && layered != GL_FALSE)
4985                 {
4986                         m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected boolean, got " << layered << tcu::TestLog::EndMessage;
4987                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid boolean");
4988                 }
4989                 else if ((layered == GL_TRUE) != textureTypes[ndx].layered)
4990                 {
4991                         m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected " << ((textureTypes[ndx].layered) ? ("GL_TRUE") : ("GL_FALSE")) << ", got " << glu::getBooleanStr(layered) << tcu::TestLog::EndMessage;
4992                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count");
4993                 }
4994         }
4995
4996         return STOP;
4997 }
4998
4999 class FramebufferIncompleteLayereTargetsCase : public GeometryShaderFeartureTestCase
5000 {
5001 public:
5002                                         FramebufferIncompleteLayereTargetsCase  (Context& context, const char* name, const char* description);
5003         IterateResult   iterate                                                                 (void);
5004 };
5005
5006 FramebufferIncompleteLayereTargetsCase::FramebufferIncompleteLayereTargetsCase (Context& context, const char* name, const char* description)
5007         : GeometryShaderFeartureTestCase(context, name, description)
5008 {
5009 }
5010
5011 FramebufferIncompleteLayereTargetsCase::IterateResult FramebufferIncompleteLayereTargetsCase::iterate (void)
5012 {
5013         glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
5014         gl.enableLogging(true);
5015
5016         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5017
5018         {
5019                 const tcu::ScopedLogSection section                     (m_testCtx.getLog(), "LayerAndNonLayer", "Layered and non-layered");
5020                 const glu::Framebuffer          fbo                             (m_context.getRenderContext());
5021                 const glu::Texture                      texture0                (m_context.getRenderContext());
5022                 const glu::Texture                      texture1                (m_context.getRenderContext());
5023
5024                 glw::GLint                                      fboStatus;
5025
5026                 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture0);
5027                 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
5028                 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5029                 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5030
5031                 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture1);
5032                 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
5033                 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5034                 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5035
5036                 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo);
5037                 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture0, 0);
5038                 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, *texture1, 0, 0);
5039
5040                 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup fbo");
5041
5042                 fboStatus = gl.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
5043                 m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer status: " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage;
5044
5045                 if (fboStatus != GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS)
5046                 {
5047                         m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS, got " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage;
5048                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count");
5049                 }
5050         }
5051
5052         {
5053                 const tcu::ScopedLogSection section                     (m_testCtx.getLog(), "DifferentTarget", "Different target");
5054                 const glu::Framebuffer          fbo                             (m_context.getRenderContext());
5055                 const glu::Texture                      texture0                (m_context.getRenderContext());
5056                 const glu::Texture                      texture1                (m_context.getRenderContext());
5057
5058                 glw::GLint                                      fboStatus;
5059
5060                 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture0);
5061                 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
5062                 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5063                 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5064
5065                 gl.glBindTexture(GL_TEXTURE_3D, *texture1);
5066                 gl.glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
5067                 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5068                 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5069
5070                 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo);
5071                 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture0, 0);
5072                 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, *texture1, 0);
5073
5074                 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup fbo");
5075
5076                 fboStatus = gl.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
5077                 m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer status: " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage;
5078
5079                 if (fboStatus != GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS)
5080                 {
5081                         m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS, got " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage;
5082                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count");
5083                 }
5084         }
5085
5086         return STOP;
5087 }
5088
5089 class ReferencedByGeometryShaderCase : public GeometryShaderFeartureTestCase
5090 {
5091 public:
5092                                         ReferencedByGeometryShaderCase  (Context& context, const char* name, const char* description);
5093         IterateResult   iterate                                                 (void);
5094 };
5095
5096 ReferencedByGeometryShaderCase::ReferencedByGeometryShaderCase (Context& context, const char* name, const char* description)
5097         : GeometryShaderFeartureTestCase(context, name, description)
5098 {
5099 }
5100
5101 ReferencedByGeometryShaderCase::IterateResult ReferencedByGeometryShaderCase::iterate (void)
5102 {
5103         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5104
5105         {
5106                 static const char* const vertexSource =         "#version 310 es\n"
5107                                                                                                         "uniform highp vec4 u_position;\n"
5108                                                                                                         "void main (void)\n"
5109                                                                                                         "{\n"
5110                                                                                                         "       gl_Position = u_position;\n"
5111                                                                                                         "}\n";
5112                 static const char* const fragmentSource =       "#version 310 es\n"
5113                                                                                                         "layout(location = 0) out mediump vec4 fragColor;\n"
5114                                                                                                         "void main (void)\n"
5115                                                                                                         "{\n"
5116                                                                                                         "       fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
5117                                                                                                         "}\n";
5118                 static const char* const geometrySource =       "#version 310 es\n"
5119                                                                                                         "#extension GL_EXT_geometry_shader : require\n"
5120                                                                                                         "layout(points) in;\n"
5121                                                                                                         "layout(points, max_vertices=1) out;\n"
5122                                                                                                         "uniform highp vec4 u_offset;\n"
5123                                                                                                         "void main (void)\n"
5124                                                                                                         "{\n"
5125                                                                                                         "       gl_Position = gl_in[0].gl_Position + u_offset;\n"
5126                                                                                                         "       EmitVertex();\n"
5127                                                                                                         "}\n";
5128
5129                 const glu::ShaderProgram program(m_context.getRenderContext(), glu::ProgramSources()
5130                                                                                                                                                 << glu::VertexSource(vertexSource)
5131                                                                                                                                                 << glu::FragmentSource(fragmentSource)
5132                                                                                                                                                 << glu::GeometrySource(geometrySource));
5133                 m_testCtx.getLog() << program;
5134
5135                 {
5136                         const tcu::ScopedLogSection section             (m_testCtx.getLog(), "UnreferencedUniform", "Unreferenced uniform u_position");
5137                         glu::CallLogWrapper                     gl                      (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
5138                         const deUint32                          props[1]        = { GL_REFERENCED_BY_GEOMETRY_SHADER };
5139                         deUint32                                        resourcePos;
5140                         glw::GLsizei                            length          = 0;
5141                         glw::GLint                                      referenced      = 0;
5142
5143                         gl.enableLogging(true);
5144
5145                         resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_position");
5146                         m_testCtx.getLog() << tcu::TestLog::Message << "u_position resource index: " << resourcePos << tcu::TestLog::EndMessage;
5147
5148                         gl.glGetProgramResourceiv(program.getProgram(), GL_UNIFORM, resourcePos, 1, props, 1, &length, &referenced);
5149                         m_testCtx.getLog() << tcu::TestLog::Message << "Query GL_REFERENCED_BY_GEOMETRY_SHADER, got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced) << tcu::TestLog::EndMessage;
5150
5151                         GLU_EXPECT_NO_ERROR(gl.glGetError(), "query resource");
5152
5153                         if (length == 0 || referenced != GL_FALSE)
5154                         {
5155                                 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FALSE." << tcu::TestLog::EndMessage;
5156                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected value");
5157                         }
5158                 }
5159
5160                 {
5161                         const tcu::ScopedLogSection section             (m_testCtx.getLog(), "ReferencedUniform", "Referenced uniform u_offset");
5162                         glu::CallLogWrapper                     gl                      (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
5163                         const deUint32                          props[1]        = { GL_REFERENCED_BY_GEOMETRY_SHADER };
5164                         deUint32                                        resourcePos;
5165                         glw::GLsizei                            length          = 0;
5166                         glw::GLint                                      referenced      = 0;
5167
5168                         gl.enableLogging(true);
5169
5170                         resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_offset");
5171                         m_testCtx.getLog() << tcu::TestLog::Message << "u_offset resource index: " << resourcePos << tcu::TestLog::EndMessage;
5172
5173                         gl.glGetProgramResourceiv(program.getProgram(), GL_UNIFORM, resourcePos, 1, props, 1, &length, &referenced);
5174                         m_testCtx.getLog() << tcu::TestLog::Message << "Query GL_REFERENCED_BY_GEOMETRY_SHADER, got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced) << tcu::TestLog::EndMessage;
5175
5176                         GLU_EXPECT_NO_ERROR(gl.glGetError(), "query resource");
5177
5178                         if (length == 0 || referenced != GL_TRUE)
5179                         {
5180                                 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_TRUE." << tcu::TestLog::EndMessage;
5181                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected value");
5182                         }
5183                 }
5184         }
5185
5186         return STOP;
5187 }
5188
5189 class CombinedGeometryUniformLimitCase : public GeometryShaderFeartureTestCase
5190 {
5191 public:
5192                                                 CombinedGeometryUniformLimitCase        (Context& context, const char* name, const char* desc);
5193 private:
5194         IterateResult           iterate                                                         (void);
5195 };
5196
5197 CombinedGeometryUniformLimitCase::CombinedGeometryUniformLimitCase (Context& context, const char* name, const char* desc)
5198         : GeometryShaderFeartureTestCase(context, name, desc)
5199 {
5200 }
5201
5202 CombinedGeometryUniformLimitCase::IterateResult CombinedGeometryUniformLimitCase::iterate (void)
5203 {
5204         glu::CallLogWrapper             gl              (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
5205         tcu::ResultCollector    result  (m_testCtx.getLog(), " // ERROR: ");
5206
5207         gl.enableLogging(true);
5208
5209         m_testCtx.getLog()      << tcu::TestLog::Message
5210                                                 << "The minimum value of MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS is MAX_GEOMETRY_UNIFORM_BLOCKS x MAX_UNIFORM_BLOCK_SIZE / 4 + MAX_GEOMETRY_UNIFORM_COMPONENTS"
5211                                                 << tcu::TestLog::EndMessage;
5212
5213         StateQueryMemoryWriteGuard<glw::GLint> maxUniformBlocks;
5214         gl.glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &maxUniformBlocks);
5215         GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGetIntegerv");
5216
5217         StateQueryMemoryWriteGuard<glw::GLint> maxUniformBlockSize;
5218         gl.glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
5219         GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGetIntegerv");
5220
5221         StateQueryMemoryWriteGuard<glw::GLint> maxUniformComponents;
5222         gl.glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, &maxUniformComponents);
5223         GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGetIntegerv");
5224
5225         if (maxUniformBlocks.verifyValidity(result) && maxUniformBlockSize.verifyValidity(result) && maxUniformComponents.verifyValidity(result))
5226         {
5227                 const int limit = ((int)maxUniformBlocks) * ((int)maxUniformBlockSize) / 4 + (int)maxUniformComponents;
5228                 verifyStateIntegerMin(result, gl, GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS, limit, QUERY_INTEGER);
5229
5230                 {
5231                         const tcu::ScopedLogSection     section(m_testCtx.getLog(), "Types", "Alternative queries");
5232                         verifyStateIntegerMin(result, gl, GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS, limit, QUERY_BOOLEAN);
5233                         verifyStateIntegerMin(result, gl, GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS, limit, QUERY_INTEGER64);
5234                         verifyStateIntegerMin(result, gl, GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS, limit, QUERY_FLOAT);
5235                 }
5236         }
5237
5238         result.setTestContextResult(m_testCtx);
5239         return STOP;
5240 }
5241
5242 class VertexFeedbackCase : public TestCase
5243 {
5244 public:
5245         enum DrawMethod
5246         {
5247                 METHOD_DRAW_ARRAYS = 0,
5248                 METHOD_DRAW_ARRAYS_INSTANCED,
5249                 METHOD_DRAW_ARRAYS_INDIRECT,
5250                 METHOD_DRAW_ELEMENTS,
5251                 METHOD_DRAW_ELEMENTS_INSTANCED,
5252                 METHOD_DRAW_ELEMENTS_INDIRECT,
5253
5254                 METHOD_LAST
5255         };
5256         enum PrimitiveType
5257         {
5258                 PRIMITIVE_LINE_LOOP = 0,
5259                 PRIMITIVE_LINE_STRIP,
5260                 PRIMITIVE_TRIANGLE_STRIP,
5261                 PRIMITIVE_TRIANGLE_FAN,
5262                 PRIMITIVE_POINTS,
5263
5264                 PRIMITIVE_LAST
5265         };
5266
5267                                                 VertexFeedbackCase      (Context& context, const char* name, const char* description, DrawMethod method, PrimitiveType output);
5268                                                 ~VertexFeedbackCase     (void);
5269 private:
5270         void                            init                            (void);
5271         void                            deinit                          (void);
5272         IterateResult           iterate                         (void);
5273
5274         glu::ShaderProgram*     genProgram                      (void);
5275         deUint32                        getOutputPrimitive      (void);
5276         deUint32                        getBasePrimitive        (void);
5277
5278         const DrawMethod        m_method;
5279         const PrimitiveType     m_output;
5280
5281         deUint32                        m_elementBuf;
5282         deUint32                        m_arrayBuf;
5283         deUint32                        m_offsetBuf;
5284         deUint32                        m_feedbackBuf;
5285         deUint32                        m_indirectBuffer;
5286         glu::ShaderProgram*     m_program;
5287         glu::VertexArray*       m_vao;
5288 };
5289
5290 VertexFeedbackCase::VertexFeedbackCase (Context& context, const char* name, const char* description, DrawMethod method, PrimitiveType output)
5291         : TestCase                      (context, name, description)
5292         , m_method                      (method)
5293         , m_output                      (output)
5294         , m_elementBuf          (0)
5295         , m_arrayBuf            (0)
5296         , m_offsetBuf           (0)
5297         , m_feedbackBuf         (0)
5298         , m_indirectBuffer      (0)
5299         , m_program                     (DE_NULL)
5300         , m_vao                         (DE_NULL)
5301 {
5302         DE_ASSERT(method < METHOD_LAST);
5303         DE_ASSERT(output < PRIMITIVE_LAST);
5304 }
5305
5306 VertexFeedbackCase::~VertexFeedbackCase (void)
5307 {
5308         deinit();
5309 }
5310
5311 void VertexFeedbackCase::init (void)
5312 {
5313         // requirements
5314
5315         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
5316                 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension");
5317
5318         // log what test tries to do
5319
5320         m_testCtx.getLog()
5321                 << tcu::TestLog::Message
5322                 << "Testing GL_EXT_geometry_shader transform feedback relaxations.\n"
5323                 << "Capturing vertex shader varying, no geometry shader. Invoke with:"
5324                 << tcu::TestLog::EndMessage;
5325
5326         switch (m_method)
5327         {
5328                 case METHOD_DRAW_ARRAYS:                                m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArrays"                        << tcu::TestLog::EndMessage;    break;
5329                 case METHOD_DRAW_ARRAYS_INSTANCED:              m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArraysInstanced"       << tcu::TestLog::EndMessage;    break;
5330                 case METHOD_DRAW_ARRAYS_INDIRECT:               m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArraysIndirect"        << tcu::TestLog::EndMessage;    break;
5331                 case METHOD_DRAW_ELEMENTS:                              m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElements"                      << tcu::TestLog::EndMessage;    break;
5332                 case METHOD_DRAW_ELEMENTS_INSTANCED:    m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElementsInstanced" << tcu::TestLog::EndMessage;        break;
5333                 case METHOD_DRAW_ELEMENTS_INDIRECT:             m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElementsIndirect"      << tcu::TestLog::EndMessage;    break;
5334                 default:
5335                         DE_ASSERT(false);
5336         }
5337         switch (m_output)
5338         {
5339                 case PRIMITIVE_LINE_LOOP:                               m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: line loop"                      << tcu::TestLog::EndMessage;    break;
5340                 case PRIMITIVE_LINE_STRIP:                              m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: line strip"                     << tcu::TestLog::EndMessage;    break;
5341                 case PRIMITIVE_TRIANGLE_STRIP:                  m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: triangle strip"         << tcu::TestLog::EndMessage;    break;
5342                 case PRIMITIVE_TRIANGLE_FAN:                    m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: triangle fan"           << tcu::TestLog::EndMessage;    break;
5343                 case PRIMITIVE_POINTS:                                  m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: points"                         << tcu::TestLog::EndMessage;    break;
5344                 default:
5345                         DE_ASSERT(false);
5346         }
5347
5348         // resources
5349
5350         {
5351                 static const deUint16 elementData[] =
5352                 {
5353                         0, 1, 2, 3,
5354                 };
5355                 static const tcu::Vec4 arrayData[] =
5356                 {
5357                         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
5358                         tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
5359                         tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f),
5360                         tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f),
5361                 };
5362                 static const tcu::Vec4 offsetData[] =
5363                 {
5364                         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
5365                         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
5366                         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
5367                         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
5368                 };
5369
5370                 const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
5371                 const int                               feedbackSize    = 8 * (int)sizeof(float[4]);
5372
5373                 m_vao = new glu::VertexArray(m_context.getRenderContext());
5374                 gl.bindVertexArray(**m_vao);
5375                 GLU_EXPECT_NO_ERROR(gl.getError(), "set up vao");
5376
5377                 gl.genBuffers(1, &m_elementBuf);
5378                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf);
5379                 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), &elementData[0], GL_STATIC_DRAW);
5380                 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf");
5381
5382                 gl.genBuffers(1, &m_arrayBuf);
5383                 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf);
5384                 gl.bufferData(GL_ARRAY_BUFFER, sizeof(arrayData), &arrayData[0], GL_STATIC_DRAW);
5385                 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf");
5386
5387                 gl.genBuffers(1, &m_offsetBuf);
5388                 gl.bindBuffer(GL_ARRAY_BUFFER, m_offsetBuf);
5389                 gl.bufferData(GL_ARRAY_BUFFER, sizeof(offsetData), &offsetData[0], GL_STATIC_DRAW);
5390                 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf");
5391
5392                 gl.genBuffers(1, &m_feedbackBuf);
5393                 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_feedbackBuf);
5394                 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackSize, DE_NULL, GL_DYNAMIC_COPY);
5395                 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf");
5396
5397                 m_program = genProgram();
5398
5399                 if (!m_program->isOk())
5400                 {
5401                         m_testCtx.getLog() << *m_program;
5402                         throw tcu::TestError("could not build program");
5403                 }
5404         }
5405 }
5406
5407 void VertexFeedbackCase::deinit (void)
5408 {
5409         if (m_elementBuf)
5410         {
5411                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuf);
5412                 m_elementBuf = 0;
5413         }
5414
5415         if (m_arrayBuf)
5416         {
5417                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_arrayBuf);
5418                 m_arrayBuf = 0;
5419         }
5420
5421         if (m_offsetBuf)
5422         {
5423                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_offsetBuf);
5424                 m_offsetBuf = 0;
5425         }
5426
5427         if (m_feedbackBuf)
5428         {
5429                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_feedbackBuf);
5430                 m_feedbackBuf = 0;
5431         }
5432
5433         if (m_indirectBuffer)
5434         {
5435                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indirectBuffer);
5436                 m_indirectBuffer = 0;
5437         }
5438
5439         delete m_program;
5440         m_program = DE_NULL;
5441
5442         delete m_vao;
5443         m_vao = DE_NULL;
5444 }
5445
5446 VertexFeedbackCase::IterateResult VertexFeedbackCase::iterate (void)
5447 {
5448         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
5449         const deUint32                  outputPrimitive = getOutputPrimitive();
5450         const deUint32                  basePrimitive   = getBasePrimitive();
5451
5452         const int                               posLocation             = gl.getAttribLocation(m_program->getProgram(), "a_position");
5453         const int                               offsetLocation  = gl.getAttribLocation(m_program->getProgram(), "a_offset");
5454
5455         if (posLocation == -1)
5456                 throw tcu::TestError("a_position location was -1");
5457         if (offsetLocation == -1)
5458                 throw tcu::TestError("a_offset location was -1");
5459
5460         gl.useProgram(m_program->getProgram());
5461
5462         gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf);
5463         gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
5464         gl.enableVertexAttribArray(posLocation);
5465
5466         gl.bindBuffer(GL_ARRAY_BUFFER, m_offsetBuf);
5467         gl.vertexAttribPointer(offsetLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
5468         gl.enableVertexAttribArray(offsetLocation);
5469
5470         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_feedbackBuf);
5471         GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffer base");
5472
5473         m_testCtx.getLog() << tcu::TestLog::Message << "Calling BeginTransformFeedback(" << glu::getPrimitiveTypeStr(basePrimitive) << ")" << tcu::TestLog::EndMessage;
5474         gl.beginTransformFeedback(basePrimitive);
5475         GLU_EXPECT_NO_ERROR(gl.getError(), "beginTransformFeedback");
5476
5477         switch (m_method)
5478         {
5479                 case METHOD_DRAW_ARRAYS:
5480                 {
5481                         m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawArrays(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage;
5482                         gl.drawArrays(outputPrimitive, 0, 4);
5483                         break;
5484                 }
5485
5486                 case METHOD_DRAW_ARRAYS_INSTANCED:
5487                 {
5488                         m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawArraysInstanced(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage;
5489                         gl.vertexAttribDivisor(offsetLocation, 2);
5490                         gl.drawArraysInstanced(outputPrimitive, 0, 3, 2);
5491                         break;
5492                 }
5493
5494                 case METHOD_DRAW_ELEMENTS:
5495                 {
5496                         m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElements(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage;
5497                         gl.drawElements(outputPrimitive, 4, GL_UNSIGNED_SHORT, DE_NULL);
5498                         break;
5499                 }
5500
5501                 case METHOD_DRAW_ELEMENTS_INSTANCED:
5502                 {
5503                         m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsInstanced(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage;
5504                         gl.drawElementsInstanced(outputPrimitive, 3, GL_UNSIGNED_SHORT, DE_NULL, 2);
5505                         break;
5506                 }
5507
5508                 case METHOD_DRAW_ARRAYS_INDIRECT:
5509                 {
5510                         struct DrawArraysIndirectCommand
5511                         {
5512                                 deUint32 count;
5513                                 deUint32 instanceCount;
5514                                 deUint32 first;
5515                                 deUint32 reservedMustBeZero;
5516                         } params;
5517
5518                         DE_STATIC_ASSERT(sizeof(DrawArraysIndirectCommand) == sizeof(deUint32[4]));
5519
5520                         params.count = 4;
5521                         params.instanceCount = 1;
5522                         params.first = 0;
5523                         params.reservedMustBeZero = 0;
5524
5525                         gl.genBuffers(1, &m_indirectBuffer);
5526                         gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirectBuffer);
5527                         gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(params), &params, GL_STATIC_DRAW);
5528
5529                         m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsIndirect(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage;
5530                         gl.drawArraysIndirect(outputPrimitive, DE_NULL);
5531                         break;
5532                 }
5533
5534                 case METHOD_DRAW_ELEMENTS_INDIRECT:
5535                 {
5536                         struct DrawElementsIndirectCommand
5537                         {
5538                                 deUint32        count;
5539                                 deUint32        instanceCount;
5540                                 deUint32        firstIndex;
5541                                 deInt32         baseVertex;
5542                                 deUint32        reservedMustBeZero;
5543                         } params;
5544
5545                         DE_STATIC_ASSERT(sizeof(DrawElementsIndirectCommand) == sizeof(deUint32[5]));
5546
5547                         params.count = 4;
5548                         params.instanceCount = 1;
5549                         params.firstIndex = 0;
5550                         params.baseVertex = 0;
5551                         params.reservedMustBeZero = 0;
5552
5553                         gl.genBuffers(1, &m_indirectBuffer);
5554                         gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirectBuffer);
5555                         gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(params), &params, GL_STATIC_DRAW);
5556
5557                         m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsIndirect(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage;
5558                         gl.drawElementsIndirect(outputPrimitive, GL_UNSIGNED_SHORT, DE_NULL);
5559                         break;
5560                 }
5561
5562                 default:
5563                         DE_ASSERT(false);
5564         }
5565         GLU_EXPECT_NO_ERROR(gl.getError(), "draw");
5566
5567         gl.endTransformFeedback();
5568         GLU_EXPECT_NO_ERROR(gl.getError(), "endTransformFeedback");
5569
5570         m_testCtx.getLog() << tcu::TestLog::Message << "No errors." << tcu::TestLog::EndMessage;
5571         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5572
5573         return STOP;
5574 }
5575
5576 glu::ShaderProgram* VertexFeedbackCase::genProgram (void)
5577 {
5578         static const char* const vertexSource =         "#version 310 es\n"
5579                                                                                                 "in highp vec4 a_position;\n"
5580                                                                                                 "in highp vec4 a_offset;\n"
5581                                                                                                 "out highp vec4 tf_value;\n"
5582                                                                                                 "void main (void)\n"
5583                                                                                                 "{\n"
5584                                                                                                 "       gl_Position = a_position;\n"
5585                                                                                                 "       tf_value = a_position + a_offset;\n"
5586                                                                                                 "}\n";
5587         static const char* const fragmentSource =       "#version 310 es\n"
5588                                                                                                 "layout(location = 0) out mediump vec4 fragColor;\n"
5589                                                                                                 "void main (void)\n"
5590                                                                                                 "{\n"
5591                                                                                                 "       fragColor = vec4(1.0);\n"
5592                                                                                                 "}\n";
5593
5594         return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
5595                                                                                                                                 << glu::VertexSource(vertexSource)
5596                                                                                                                                 << glu::FragmentSource(fragmentSource)
5597                                                                                                                                 << glu::TransformFeedbackVarying("tf_value")
5598                                                                                                                                 << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS));
5599 }
5600
5601 deUint32 VertexFeedbackCase::getOutputPrimitive (void)
5602 {
5603         switch(m_output)
5604         {
5605                 case PRIMITIVE_LINE_LOOP:               return GL_LINE_LOOP;
5606                 case PRIMITIVE_LINE_STRIP:              return GL_LINE_STRIP;
5607                 case PRIMITIVE_TRIANGLE_STRIP:  return GL_TRIANGLE_STRIP;
5608                 case PRIMITIVE_TRIANGLE_FAN:    return GL_TRIANGLE_FAN;
5609                 case PRIMITIVE_POINTS:                  return GL_POINTS;
5610                 default:
5611                         DE_ASSERT(false);
5612                         return 0;
5613         }
5614 }
5615
5616 deUint32 VertexFeedbackCase::getBasePrimitive (void)
5617 {
5618         switch(m_output)
5619         {
5620                 case PRIMITIVE_LINE_LOOP:               return GL_LINES;
5621                 case PRIMITIVE_LINE_STRIP:              return GL_LINES;
5622                 case PRIMITIVE_TRIANGLE_STRIP:  return GL_TRIANGLES;
5623                 case PRIMITIVE_TRIANGLE_FAN:    return GL_TRIANGLES;
5624                 case PRIMITIVE_POINTS:                  return GL_POINTS;
5625                 default:
5626                         DE_ASSERT(false);
5627                         return 0;
5628         }
5629 }
5630
5631 class VertexFeedbackOverflowCase : public TestCase
5632 {
5633 public:
5634         enum Method
5635         {
5636                 METHOD_DRAW_ARRAYS = 0,
5637                 METHOD_DRAW_ELEMENTS,
5638         };
5639
5640                                                 VertexFeedbackOverflowCase      (Context& context, const char* name, const char* description, Method method);
5641                                                 ~VertexFeedbackOverflowCase     (void);
5642
5643 private:
5644         void                            init                                            (void);
5645         void                            deinit                                          (void);
5646         IterateResult           iterate                                         (void);
5647         glu::ShaderProgram*     genProgram                                      (void);
5648
5649         const Method            m_method;
5650
5651         deUint32                        m_elementBuf;
5652         deUint32                        m_arrayBuf;
5653         deUint32                        m_feedbackBuf;
5654         glu::ShaderProgram*     m_program;
5655         glu::VertexArray*       m_vao;
5656 };
5657
5658 VertexFeedbackOverflowCase::VertexFeedbackOverflowCase (Context& context, const char* name, const char* description, Method method)
5659         : TestCase              (context, name, description)
5660         , m_method              (method)
5661         , m_elementBuf  (0)
5662         , m_arrayBuf    (0)
5663         , m_feedbackBuf (0)
5664         , m_program             (DE_NULL)
5665         , m_vao                 (DE_NULL)
5666 {
5667 }
5668
5669 VertexFeedbackOverflowCase::~VertexFeedbackOverflowCase (void)
5670 {
5671         deinit();
5672 }
5673
5674 void VertexFeedbackOverflowCase::init (void)
5675 {
5676         // requirements
5677
5678         if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
5679                 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension");
5680
5681         // log what test tries to do
5682
5683         m_testCtx.getLog()
5684                 << tcu::TestLog::Message
5685                 << "Testing GL_EXT_geometry_shader transform feedback overflow behavior.\n"
5686                 << "Capturing vertex shader varying, rendering 2 triangles. Allocating feedback buffer for 5 vertices."
5687                 << tcu::TestLog::EndMessage;
5688
5689         // resources
5690
5691         {
5692                 static const deUint16   elementData[] =
5693                 {
5694                         0, 1, 2,
5695                         0, 1, 2,
5696                 };
5697                 static const tcu::Vec4  arrayData[] =
5698                 {
5699                         tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
5700                         tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
5701                         tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
5702                         tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
5703                 };
5704
5705                 const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
5706
5707                 m_vao = new glu::VertexArray(m_context.getRenderContext());
5708                 gl.bindVertexArray(**m_vao);
5709                 GLU_EXPECT_NO_ERROR(gl.getError(), "set up vao");
5710
5711                 if (m_method == METHOD_DRAW_ELEMENTS)
5712                 {
5713                         gl.genBuffers(1, &m_elementBuf);
5714                         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf);
5715                         gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), &elementData[0], GL_STATIC_DRAW);
5716                         GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf");
5717                 }
5718
5719                 gl.genBuffers(1, &m_arrayBuf);
5720                 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf);
5721                 gl.bufferData(GL_ARRAY_BUFFER, sizeof(arrayData), &arrayData[0], GL_STATIC_DRAW);
5722                 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf");
5723
5724                 {
5725                         const int                                       feedbackCount                   = 5 * 4; // 5x vec4
5726                         const std::vector<float>        initialBufferContents   (feedbackCount, -1.0f);
5727
5728                         m_testCtx.getLog() << tcu::TestLog::Message << "Filling feeback buffer with dummy value (-1.0)." << tcu::TestLog::EndMessage;
5729
5730                         gl.genBuffers(1, &m_feedbackBuf);
5731                         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_feedbackBuf);
5732                         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, (int)(sizeof(float) * initialBufferContents.size()), &initialBufferContents[0], GL_DYNAMIC_COPY);
5733                         GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf");
5734                 }
5735
5736                 m_program = genProgram();
5737
5738                 if (!m_program->isOk())
5739                 {
5740                         m_testCtx.getLog() << *m_program;
5741                         throw tcu::TestError("could not build program");
5742                 }
5743         }
5744 }
5745
5746 void VertexFeedbackOverflowCase::deinit (void)
5747 {
5748         if (m_elementBuf)
5749         {
5750                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuf);
5751                 m_elementBuf = 0;
5752         }
5753
5754         if (m_arrayBuf)
5755         {
5756                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_arrayBuf);
5757                 m_arrayBuf = 0;
5758         }
5759
5760         if (m_feedbackBuf)
5761         {
5762                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_feedbackBuf);
5763                 m_feedbackBuf = 0;
5764         }
5765
5766         delete m_program;
5767         m_program = DE_NULL;
5768
5769         delete m_vao;
5770         m_vao = DE_NULL;
5771 }
5772
5773 VertexFeedbackOverflowCase::IterateResult VertexFeedbackOverflowCase::iterate (void)
5774 {
5775         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
5776         const int                               posLocation             = gl.getAttribLocation(m_program->getProgram(), "a_position");
5777
5778         if (posLocation == -1)
5779                 throw tcu::TestError("a_position location was -1");
5780
5781         gl.useProgram(m_program->getProgram());
5782
5783         gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf);
5784         gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
5785         gl.enableVertexAttribArray(posLocation);
5786
5787         if (m_method == METHOD_DRAW_ELEMENTS)
5788         {
5789                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf);
5790                 GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffers");
5791         }
5792
5793         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_feedbackBuf);
5794         GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffer base");
5795
5796         m_testCtx.getLog() << tcu::TestLog::Message << "Capturing 2 triangles." << tcu::TestLog::EndMessage;
5797
5798         gl.beginTransformFeedback(GL_TRIANGLES);
5799
5800         if (m_method == METHOD_DRAW_ELEMENTS)
5801                 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL);
5802         else if (m_method == METHOD_DRAW_ARRAYS)
5803                 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
5804         else
5805                 DE_ASSERT(false);
5806
5807         gl.endTransformFeedback();
5808         GLU_EXPECT_NO_ERROR(gl.getError(), "capture");
5809
5810         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying final triangle was not partially written to the feedback buffer." << tcu::TestLog::EndMessage;
5811
5812         {
5813                 const void*                             ptr             = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(float[4]) * 5, GL_MAP_READ_BIT);
5814                 std::vector<float>              feedback;
5815                 bool                                    error   = false;
5816
5817                 GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange");
5818                 if (!ptr)
5819                         throw tcu::TestError("mapBufferRange returned null");
5820
5821                 feedback.resize(5*4);
5822                 deMemcpy(&feedback[0], ptr, sizeof(float[4]) * 5);
5823
5824                 if (gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER) != GL_TRUE)
5825                         throw tcu::TestError("unmapBuffer returned false");
5826
5827                 // Verify vertices 0 - 2
5828                 for (int vertex = 0; vertex < 3; ++vertex)
5829                 {
5830                         for (int component = 0; component < 4; ++component)
5831                         {
5832                                 if (feedback[vertex*4 + component] != 1.0f)
5833                                 {
5834                                         m_testCtx.getLog()
5835                                                 << tcu::TestLog::Message
5836                                                 << "Feedback buffer vertex " << vertex << ", component " << component << ": unexpected value, expected 1.0, got " << feedback[vertex*4 + component]
5837                                                 << tcu::TestLog::EndMessage;
5838                                         error = true;
5839                                 }
5840                         }
5841                 }
5842
5843                 // Verify vertices 3 - 4
5844                 for (int vertex = 3; vertex < 5; ++vertex)
5845                 {
5846                         for (int component = 0; component < 4; ++component)
5847                         {
5848                                 if (feedback[vertex*4 + component] != -1.0f)
5849                                 {
5850                                         m_testCtx.getLog()
5851                                                 << tcu::TestLog::Message
5852                                                 << "Feedback buffer vertex " << vertex << ", component " << component << ": unexpected value, expected -1.0, got " << feedback[vertex*4 + component]
5853                                                 << tcu::TestLog::EndMessage;
5854                                         error = true;
5855                                 }
5856                         }
5857                 }
5858
5859                 if (error)
5860                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Feedback result validation failed");
5861                 else
5862                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5863         }
5864
5865         return STOP;
5866 }
5867
5868 glu::ShaderProgram* VertexFeedbackOverflowCase::genProgram (void)
5869 {
5870         static const char* const vertexSource =         "#version 310 es\n"
5871                                                                                                 "in highp vec4 a_position;\n"
5872                                                                                                 "void main (void)\n"
5873                                                                                                 "{\n"
5874                                                                                                 "       gl_Position = a_position;\n"
5875                                                                                                 "}\n";
5876         static const char* const fragmentSource =       "#version 310 es\n"
5877                                                                                                 "layout(location = 0) out mediump vec4 fragColor;\n"
5878                                                                                                 "void main (void)\n"
5879                                                                                                 "{\n"
5880                                                                                                 "       fragColor = vec4(1.0);\n"
5881                                                                                                 "}\n";
5882
5883         return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
5884                                                                                                                                 << glu::VertexSource(vertexSource)
5885                                                                                                                                 << glu::FragmentSource(fragmentSource)
5886                                                                                                                                 << glu::TransformFeedbackVarying("gl_Position")
5887                                                                                                                                 << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS));
5888 }
5889
5890 } // anonymous
5891
5892 GeometryShaderTests::GeometryShaderTests (Context& context)
5893         : TestCaseGroup(context, "geometry_shading", "Geometry shader tests")
5894 {
5895 }
5896
5897 GeometryShaderTests::~GeometryShaderTests (void)
5898 {
5899 }
5900
5901 void GeometryShaderTests::init (void)
5902 {
5903         struct PrimitiveTestSpec
5904         {
5905                 deUint32        primitiveType;
5906                 const char* name;
5907                 deUint32        outputType;
5908         };
5909
5910         struct EmitTestSpec
5911         {
5912                 deUint32        outputType;
5913                 int                     emitCountA;             //!< primitive A emit count
5914                 int                     endCountA;              //!< primitive A end count
5915                 int                     emitCountB;             //!<
5916                 int                     endCountB;              //!<
5917                 const char* name;
5918         };
5919
5920         static const struct LayeredTarget
5921         {
5922                 LayeredRenderCase::LayeredRenderTargetType      target;
5923                 const char*                                                                     name;
5924                 const char*                                                                     desc;
5925         } layerTargets[] =
5926         {
5927                 { LayeredRenderCase::TARGET_CUBE,                       "cubemap",                              "cubemap"                                               },
5928                 { LayeredRenderCase::TARGET_3D,                         "3d",                                   "3D texture"                                    },
5929                 { LayeredRenderCase::TARGET_2D_ARRAY,           "2d_array",                             "2D array texture"                              },
5930                 { LayeredRenderCase::TARGET_2D_MS_ARRAY,        "2d_multisample_array", "2D multisample array texture"  },
5931         };
5932
5933         tcu::TestCaseGroup* const queryGroup                            = new tcu::TestCaseGroup(m_testCtx, "query", "Query tests.");
5934         tcu::TestCaseGroup* const basicGroup                            = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic tests.");
5935         tcu::TestCaseGroup* const inputPrimitiveGroup           = new tcu::TestCaseGroup(m_testCtx, "input", "Different input primitives.");
5936         tcu::TestCaseGroup* const conversionPrimitiveGroup      = new tcu::TestCaseGroup(m_testCtx, "conversion", "Different input and output primitives.");
5937         tcu::TestCaseGroup* const emitGroup                                     = new tcu::TestCaseGroup(m_testCtx, "emit", "Different emit counts.");
5938         tcu::TestCaseGroup* const varyingGroup                          = new tcu::TestCaseGroup(m_testCtx, "varying", "Test varyings.");
5939         tcu::TestCaseGroup* const layeredGroup                          = new tcu::TestCaseGroup(m_testCtx, "layered", "Layered rendering.");
5940         tcu::TestCaseGroup* const instancedGroup                        = new tcu::TestCaseGroup(m_testCtx, "instanced", "Instanced rendering.");
5941         tcu::TestCaseGroup* const negativeGroup                         = new tcu::TestCaseGroup(m_testCtx, "negative", "Negative tests.");
5942         tcu::TestCaseGroup* const feedbackGroup                         = new tcu::TestCaseGroup(m_testCtx, "vertex_transform_feedback", "Transform feedback.");
5943
5944         this->addChild(queryGroup);
5945         this->addChild(basicGroup);
5946         this->addChild(inputPrimitiveGroup);
5947         this->addChild(conversionPrimitiveGroup);
5948         this->addChild(emitGroup);
5949         this->addChild(varyingGroup);
5950         this->addChild(layeredGroup);
5951         this->addChild(instancedGroup);
5952         this->addChild(negativeGroup);
5953         this->addChild(feedbackGroup);
5954
5955         // query test
5956         {
5957                 // limits with a corresponding glsl constant
5958                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_input_components",                           "", GL_MAX_GEOMETRY_INPUT_COMPONENTS,                           "MaxGeometryInputComponents",           64));
5959                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_output_components",                          "", GL_MAX_GEOMETRY_OUTPUT_COMPONENTS,                          "MaxGeometryOutputComponents",          128));
5960                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_image_uniforms",                                     "", GL_MAX_GEOMETRY_IMAGE_UNIFORMS,                                     "MaxGeometryImageUniforms",                     0));
5961                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_texture_image_units",                        "", GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS,                        "MaxGeometryTextureImageUnits",         16));
5962                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_output_vertices",                            "", GL_MAX_GEOMETRY_OUTPUT_VERTICES,                            "MaxGeometryOutputVertices",            256));
5963                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_total_output_components",            "", GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS,            "MaxGeometryTotalOutputComponents",     1024));
5964                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_uniform_components",                         "", GL_MAX_GEOMETRY_UNIFORM_COMPONENTS,                         "MaxGeometryUniformComponents",         1024));
5965                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_atomic_counters",                            "", GL_MAX_GEOMETRY_ATOMIC_COUNTERS,                            "MaxGeometryAtomicCounters",            0));
5966                 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_atomic_counter_buffers",                     "", GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS,                     "MaxGeometryAtomicCounterBuffers",      0));
5967
5968                 // program queries
5969                 queryGroup->addChild(new GeometryShaderVerticesQueryCase        (m_context, "geometry_linked_vertices_out",     "GL_GEOMETRY_LINKED_VERTICES_OUT"));
5970                 queryGroup->addChild(new GeometryShaderInputQueryCase           (m_context, "geometry_linked_input_type",       "GL_GEOMETRY_LINKED_INPUT_TYPE"));
5971                 queryGroup->addChild(new GeometryShaderOutputQueryCase          (m_context, "geometry_linked_output_type",      "GL_GEOMETRY_LINKED_OUTPUT_TYPE"));
5972                 queryGroup->addChild(new GeometryShaderInvocationsQueryCase     (m_context, "geometry_shader_invocations",      "GL_GEOMETRY_SHADER_INVOCATIONS"));
5973
5974                 // limits
5975                 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_shader_invocations",          "", GL_MAX_GEOMETRY_SHADER_INVOCATIONS,         32));
5976                 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_uniform_blocks",                      "", GL_MAX_GEOMETRY_UNIFORM_BLOCKS,                     12));
5977                 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_shader_storage_blocks",       "", GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,      0));
5978
5979                 // layer_provoking_vertex_ext
5980                 queryGroup->addChild(new LayerProvokingVertexQueryCase(m_context, "layer_provoking_vertex", "GL_LAYER_PROVOKING_VERTEX"));
5981
5982                 // primitives_generated
5983                 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_no_geometry",            "PRIMITIVES_GENERATED query with no geometry shader",                                                           PrimitivesGeneratedQueryCase::TEST_NO_GEOMETRY));
5984                 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_no_amplification",       "PRIMITIVES_GENERATED query with non amplifying geometry shader",                                       PrimitivesGeneratedQueryCase::TEST_NO_AMPLIFICATION));
5985                 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_amplification",          "PRIMITIVES_GENERATED query with amplifying geometry shader",                                           PrimitivesGeneratedQueryCase::TEST_AMPLIFICATION));
5986                 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_partial_primitives", "PRIMITIVES_GENERATED query with geometry shader emitting partial primitives",              PrimitivesGeneratedQueryCase::TEST_PARTIAL_PRIMITIVES));
5987                 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_instanced",                      "PRIMITIVES_GENERATED query with instanced geometry shader",                                            PrimitivesGeneratedQueryCase::TEST_INSTANCED));
5988
5989                 queryGroup->addChild(new PrimitivesGeneratedQueryObjectQueryCase(m_context, "primitives_generated", "Query bound PRIMITIVES_GENERATED query"));
5990
5991                 // fbo
5992                 queryGroup->addChild(new ImplementationLimitCase                                (m_context, "max_framebuffer_layers",                           "", GL_MAX_FRAMEBUFFER_LAYERS,  256));
5993                 queryGroup->addChild(new FramebufferDefaultLayersCase                   (m_context, "framebuffer_default_layers",                       ""));
5994                 queryGroup->addChild(new FramebufferAttachmentLayeredCase               (m_context, "framebuffer_attachment_layered",           ""));
5995                 queryGroup->addChild(new FramebufferIncompleteLayereTargetsCase (m_context, "framebuffer_incomplete_layer_targets",     ""));
5996
5997                 // resource query
5998                 queryGroup->addChild(new ReferencedByGeometryShaderCase                 (m_context, "referenced_by_geometry_shader",    ""));
5999
6000                 // combined limits
6001                 queryGroup->addChild(new CombinedGeometryUniformLimitCase               (m_context, "max_combined_geometry_uniform_components", "MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"));
6002         }
6003
6004         // basic tests
6005         {
6006                 basicGroup->addChild(new OutputCountCase                        (m_context,     "output_10",                            "Output 10 vertices",                                                           OutputCountPatternSpec(10)));
6007                 basicGroup->addChild(new OutputCountCase                        (m_context,     "output_128",                           "Output 128 vertices",                                                          OutputCountPatternSpec(128)));
6008                 basicGroup->addChild(new OutputCountCase                        (m_context,     "output_256",                           "Output 256 vertices",                                                          OutputCountPatternSpec(256)));
6009                 basicGroup->addChild(new OutputCountCase                        (m_context,     "output_max",                           "Output max vertices",                                                          OutputCountPatternSpec(-1)));
6010                 basicGroup->addChild(new OutputCountCase                        (m_context,     "output_10_and_100",            "Output 10 and 100 vertices in two invocations",        OutputCountPatternSpec(10, 100)));
6011                 basicGroup->addChild(new OutputCountCase                        (m_context,     "output_100_and_10",            "Output 100 and 10 vertices in two invocations",        OutputCountPatternSpec(100, 10)));
6012                 basicGroup->addChild(new OutputCountCase                        (m_context,     "output_0_and_128",                     "Output 0 and 128 vertices in two invocations",         OutputCountPatternSpec(0, 128)));
6013                 basicGroup->addChild(new OutputCountCase                        (m_context,     "output_128_and_0",                     "Output 128 and 0 vertices in two invocations",         OutputCountPatternSpec(128, 0)));
6014
6015                 basicGroup->addChild(new VaryingOutputCountCase         (m_context,     "output_vary_by_attribute",     "Output varying number of vertices",                            VaryingOutputCountShader::READ_ATTRIBUTE,       VaryingOutputCountCase::MODE_WITHOUT_INSTANCING));
6016                 basicGroup->addChild(new VaryingOutputCountCase         (m_context,     "output_vary_by_uniform",       "Output varying number of vertices",                            VaryingOutputCountShader::READ_UNIFORM,         VaryingOutputCountCase::MODE_WITHOUT_INSTANCING));
6017                 basicGroup->addChild(new VaryingOutputCountCase         (m_context,     "output_vary_by_texture",       "Output varying number of vertices",                            VaryingOutputCountShader::READ_TEXTURE,         VaryingOutputCountCase::MODE_WITHOUT_INSTANCING));
6018
6019                 basicGroup->addChild(new BuiltinVariableRenderTest      (m_context,     "point_size",                           "test gl_PointSize",                                                            BuiltinVariableShader::TEST_POINT_SIZE));
6020                 basicGroup->addChild(new BuiltinVariableRenderTest      (m_context,     "primitive_id_in",                      "test gl_PrimitiveIDIn",                                                        BuiltinVariableShader::TEST_PRIMITIVE_ID_IN));
6021                 basicGroup->addChild(new BuiltinVariableRenderTest      (m_context,     "primitive_id_in_restarted","test gl_PrimitiveIDIn with primitive restart",             BuiltinVariableShader::TEST_PRIMITIVE_ID_IN, GeometryShaderRenderTest::FLAG_USE_RESTART_INDEX | GeometryShaderRenderTest::FLAG_USE_INDICES));
6022                 basicGroup->addChild(new BuiltinVariableRenderTest      (m_context,     "primitive_id",                         "test gl_PrimitiveID",                                                          BuiltinVariableShader::TEST_PRIMITIVE_ID));
6023         }
6024
6025         // input primitives
6026         {
6027                 static const PrimitiveTestSpec inputPrimitives[] =
6028                 {
6029                         { GL_POINTS,                                    "points",                                       GL_POINTS                       },
6030                         { GL_LINES,                                             "lines",                                        GL_LINE_STRIP           },
6031                         { GL_LINE_LOOP,                                 "line_loop",                            GL_LINE_STRIP           },
6032                         { GL_LINE_STRIP,                                "line_strip",                           GL_LINE_STRIP           },
6033                         { GL_TRIANGLES,                                 "triangles",                            GL_TRIANGLE_STRIP       },
6034                         { GL_TRIANGLE_STRIP,                    "triangle_strip",                       GL_TRIANGLE_STRIP       },
6035                         { GL_TRIANGLE_FAN,                              "triangle_fan",                         GL_TRIANGLE_STRIP       },
6036                         { GL_LINES_ADJACENCY,                   "lines_adjacency",                      GL_LINE_STRIP           },
6037                         { GL_LINE_STRIP_ADJACENCY,              "line_strip_adjacency",         GL_LINE_STRIP           },
6038                         { GL_TRIANGLES_ADJACENCY,               "triangles_adjacency",          GL_TRIANGLE_STRIP       }
6039                 };
6040
6041                 tcu::TestCaseGroup* const basicPrimitiveGroup           = new tcu::TestCaseGroup(m_testCtx, "basic_primitive",                  "Different input and output primitives.");
6042                 tcu::TestCaseGroup* const triStripAdjacencyGroup        = new tcu::TestCaseGroup(m_testCtx, "triangle_strip_adjacency", "Different triangle_strip_adjacency vertex counts.");
6043
6044                 // more basic types
6045                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(inputPrimitives); ++ndx)
6046                         basicPrimitiveGroup->addChild(new GeometryExpanderRenderTest(m_context, inputPrimitives[ndx].name, inputPrimitives[ndx].name, inputPrimitives[ndx].primitiveType, inputPrimitives[ndx].outputType));
6047
6048                 // triangle strip adjacency with different vtx counts
6049                 for (int vtxCount = 0; vtxCount <= 12; ++vtxCount)
6050                 {
6051                         const std::string name = "vertex_count_" + de::toString(vtxCount);
6052                         const std::string desc = "Vertex count is " + de::toString(vtxCount);
6053
6054                         triStripAdjacencyGroup->addChild(new TriangleStripAdjacencyVertexCountTest(m_context, name.c_str(), desc.c_str(), vtxCount));
6055                 }
6056
6057                 inputPrimitiveGroup->addChild(basicPrimitiveGroup);
6058                 inputPrimitiveGroup->addChild(triStripAdjacencyGroup);
6059         }
6060
6061         // different type conversions
6062         {
6063                 static const PrimitiveTestSpec conversionPrimitives[] =
6064                 {
6065                         { GL_TRIANGLES,         "triangles_to_points",  GL_POINTS                       },
6066                         { GL_LINES,                     "lines_to_points",              GL_POINTS                       },
6067                         { GL_POINTS,            "points_to_lines",              GL_LINE_STRIP           },
6068                         { GL_TRIANGLES,         "triangles_to_lines",   GL_LINE_STRIP           },
6069                         { GL_POINTS,            "points_to_triangles",  GL_TRIANGLE_STRIP       },
6070                         { GL_LINES,                     "lines_to_triangles",   GL_TRIANGLE_STRIP       }
6071                 };
6072
6073                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(conversionPrimitives); ++ndx)
6074                         conversionPrimitiveGroup->addChild(new GeometryExpanderRenderTest(m_context, conversionPrimitives[ndx].name, conversionPrimitives[ndx].name, conversionPrimitives[ndx].primitiveType, conversionPrimitives[ndx].outputType));
6075         }
6076
6077         // emit different amounts
6078         {
6079                 static const EmitTestSpec emitTests[] =
6080                 {
6081                         { GL_POINTS,                     0,             0,      0,      0,      "points"                        },
6082                         { GL_POINTS,                     0,             1,      0,      0,      "points"                        },
6083                         { GL_POINTS,                     1,             1,      0,      0,      "points"                        },
6084                         { GL_POINTS,                     0,             2,      0,      0,      "points"                        },
6085                         { GL_POINTS,                     1,             2,      0,      0,      "points"                        },
6086                         { GL_LINE_STRIP,                 0,             0,      0,      0,      "line_strip"            },
6087                         { GL_LINE_STRIP,                 0,             1,      0,      0,      "line_strip"            },
6088                         { GL_LINE_STRIP,                 1,             1,      0,      0,      "line_strip"            },
6089                         { GL_LINE_STRIP,                 2,             1,      0,      0,      "line_strip"            },
6090                         { GL_LINE_STRIP,                 0,             2,      0,      0,      "line_strip"            },
6091                         { GL_LINE_STRIP,                 1,             2,      0,      0,      "line_strip"            },
6092                         { GL_LINE_STRIP,                 2,             2,      0,      0,      "line_strip"            },
6093                         { GL_LINE_STRIP,                 2,             2,      2,      0,      "line_strip"            },
6094                         { GL_TRIANGLE_STRIP,     0,             0,      0,      0,      "triangle_strip"        },
6095                         { GL_TRIANGLE_STRIP,     0,             1,      0,      0,      "triangle_strip"        },
6096                         { GL_TRIANGLE_STRIP,     1,             1,      0,      0,      "triangle_strip"        },
6097                         { GL_TRIANGLE_STRIP,     2,             1,      0,      0,      "triangle_strip"        },
6098                         { GL_TRIANGLE_STRIP,     3,             1,      0,      0,      "triangle_strip"        },
6099                         { GL_TRIANGLE_STRIP,     0,             2,      0,      0,      "triangle_strip"        },
6100                         { GL_TRIANGLE_STRIP,     1,             2,      0,      0,      "triangle_strip"        },
6101                         { GL_TRIANGLE_STRIP,     2,             2,      0,      0,      "triangle_strip"        },
6102                         { GL_TRIANGLE_STRIP,     3,             2,      0,      0,      "triangle_strip"        },
6103                         { GL_TRIANGLE_STRIP,     3,             2,      3,      0,      "triangle_strip"        },
6104                 };
6105
6106                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(emitTests); ++ndx)
6107                 {
6108                         std::string name = std::string(emitTests[ndx].name) + "_emit_" + de::toString(emitTests[ndx].emitCountA) + "_end_" + de::toString(emitTests[ndx].endCountA);
6109                         std::string desc = std::string(emitTests[ndx].name) + " output, emit " + de::toString(emitTests[ndx].emitCountA) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountA) + " times";
6110
6111                         if (emitTests[ndx].emitCountB)
6112                         {
6113                                 name += "_emit_" + de::toString(emitTests[ndx].emitCountB) + "_end_" + de::toString(emitTests[ndx].endCountB);
6114                                 desc += ", emit " + de::toString(emitTests[ndx].emitCountB) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountB) + " times";
6115                         }
6116
6117                         emitGroup->addChild(new EmitTest(m_context, name.c_str(), desc.c_str(), emitTests[ndx].emitCountA, emitTests[ndx].endCountA, emitTests[ndx].emitCountB, emitTests[ndx].endCountB, emitTests[ndx].outputType));
6118                 }
6119         }
6120
6121         // varying
6122         {
6123                 struct VaryingTestSpec
6124                 {
6125                         int                     vertexOutputs;
6126                         int                     geometryOutputs;
6127                         const char*     name;
6128                         const char*     desc;
6129                 };
6130
6131                 static const VaryingTestSpec varyingTests[] =
6132                 {
6133                         { -1, 1, "vertex_no_op_geometry_out_1", "vertex_no_op_geometry_out_1" },
6134                         {  0, 1, "vertex_out_0_geometry_out_1", "vertex_out_0_geometry_out_1" },
6135                         {  0, 2, "vertex_out_0_geometry_out_2", "vertex_out_0_geometry_out_2" },
6136                         {  1, 0, "vertex_out_1_geometry_out_0", "vertex_out_1_geometry_out_0" },
6137                         {  1, 2, "vertex_out_1_geometry_out_2", "vertex_out_1_geometry_out_2" },
6138                 };
6139
6140                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(varyingTests); ++ndx)
6141                         varyingGroup->addChild(new VaryingTest(m_context, varyingTests[ndx].name, varyingTests[ndx].desc, varyingTests[ndx].vertexOutputs, varyingTests[ndx].geometryOutputs));
6142         }
6143
6144         // layered
6145         {
6146                 static const struct TestType
6147                 {
6148                         LayeredRenderCase::TestType     test;
6149                         const char*                                     testPrefix;
6150                         const char*                                     descPrefix;
6151                 } tests[] =
6152                 {
6153                         { LayeredRenderCase::TEST_DEFAULT_LAYER,                        "render_with_default_layer_",   "Render to all layers of "                                      },
6154                         { LayeredRenderCase::TEST_SINGLE_LAYER,                         "render_to_one_",                               "Render to one layer of "                                       },
6155                         { LayeredRenderCase::TEST_ALL_LAYERS,                           "render_to_all_",                               "Render to all layers of "                                      },
6156                         { LayeredRenderCase::TEST_DIFFERENT_LAYERS,                     "render_different_to_",                 "Render different data to different layers"     },
6157                         { LayeredRenderCase::TEST_LAYER_ID,                                     "fragment_layer_",                              "Read gl_Layer in fragment shader"                      },
6158                         { LayeredRenderCase::TEST_LAYER_PROVOKING_VERTEX,       "layer_provoking_vertex_",              "Verify LAYER_PROVOKING_VERTEX"                         },
6159                 };
6160
6161                 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
6162                 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx)
6163                 {
6164                         const std::string name = std::string(tests[testNdx].testPrefix) + layerTargets[targetNdx].name;
6165                         const std::string desc = std::string(tests[testNdx].descPrefix) + layerTargets[targetNdx].desc;
6166
6167                         layeredGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, tests[testNdx].test));
6168                 }
6169         }
6170
6171         // instanced
6172         {
6173                 static const struct InvocationCase
6174                 {
6175                         const char* name;
6176                         int                     numInvocations;
6177                 } invocationCases[] =
6178                 {
6179                         { "1",          1  },
6180                         { "2",          2  },
6181                         { "8",          8  },
6182                         { "32",         32 },
6183                         { "max",        -1 },
6184                 };
6185                 static const int numDrawInstances[] = { 2, 4, 8 };
6186                 static const int numDrawInvocations[] = { 2, 8 };
6187
6188                 // same amount of content to all invocations
6189                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(invocationCases); ++ndx)
6190                         instancedGroup->addChild(new GeometryInvocationCase(m_context,
6191                                                                                                                                 (std::string("geometry_") + invocationCases[ndx].name + "_invocations").c_str(),
6192                                                                                                                                 (std::string("Geometry shader with ") + invocationCases[ndx].name + " invocation(s)").c_str(),
6193                                                                                                                                 invocationCases[ndx].numInvocations,
6194                                                                                                                                 GeometryInvocationCase::CASE_FIXED_OUTPUT_COUNTS));
6195
6196                 // different amount of content to each invocation
6197                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(invocationCases); ++ndx)
6198                         if (invocationCases[ndx].numInvocations != 1)
6199                                 instancedGroup->addChild(new GeometryInvocationCase(m_context,
6200                                                                                                                                         (std::string("geometry_output_different_") + invocationCases[ndx].name + "_invocations").c_str(),
6201                                                                                                                                         "Geometry shader invocation(s) with different emit counts",
6202                                                                                                                                         invocationCases[ndx].numInvocations,
6203                                                                                                                                         GeometryInvocationCase::CASE_DIFFERENT_OUTPUT_COUNTS));
6204
6205                 // invocation per layer
6206                 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx)
6207                 {
6208                         const std::string name = std::string("invocation_per_layer_") + layerTargets[targetNdx].name;
6209                         const std::string desc = std::string("Render to multiple layers with multiple invocations, one invocation per layer, target ") + layerTargets[targetNdx].desc;
6210
6211                         instancedGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, LayeredRenderCase::TEST_INVOCATION_PER_LAYER));
6212                 }
6213
6214                 // multiple layers per invocation
6215                 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx)
6216                 {
6217                         const std::string name = std::string("multiple_layers_per_invocation_") + layerTargets[targetNdx].name;
6218                         const std::string desc = std::string("Render to multiple layers with multiple invocations, multiple layers per invocation, target ") + layerTargets[targetNdx].desc;
6219
6220                         instancedGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, LayeredRenderCase::TEST_MULTIPLE_LAYERS_PER_INVOCATION));
6221                 }
6222
6223                 // different invocation output counts depending on {uniform, attrib, texture}
6224                 instancedGroup->addChild(new VaryingOutputCountCase(m_context,  "invocation_output_vary_by_attribute",  "Output varying number of vertices", VaryingOutputCountShader::READ_ATTRIBUTE,  VaryingOutputCountCase::MODE_WITH_INSTANCING));
6225                 instancedGroup->addChild(new VaryingOutputCountCase(m_context,  "invocation_output_vary_by_uniform",    "Output varying number of vertices", VaryingOutputCountShader::READ_UNIFORM,    VaryingOutputCountCase::MODE_WITH_INSTANCING));
6226                 instancedGroup->addChild(new VaryingOutputCountCase(m_context,  "invocation_output_vary_by_texture",    "Output varying number of vertices", VaryingOutputCountShader::READ_TEXTURE,    VaryingOutputCountCase::MODE_WITH_INSTANCING));
6227
6228                 // with drawInstanced
6229                 for (int instanceNdx = 0; instanceNdx < DE_LENGTH_OF_ARRAY(numDrawInstances); ++instanceNdx)
6230                 for (int invocationNdx = 0; invocationNdx < DE_LENGTH_OF_ARRAY(numDrawInvocations); ++invocationNdx)
6231                 {
6232                         const std::string name = std::string("draw_") + de::toString(numDrawInstances[instanceNdx]) + "_instances_geometry_" + de::toString(numDrawInvocations[invocationNdx]) + "_invocations";
6233                         const std::string desc = std::string("Draw ") + de::toString(numDrawInstances[instanceNdx]) + " instances, with " + de::toString(numDrawInvocations[invocationNdx]) + " geometry shader invocations.";
6234
6235                         instancedGroup->addChild(new DrawInstancedGeometryInstancedCase(m_context, name.c_str(), desc.c_str(), numDrawInstances[instanceNdx], numDrawInvocations[invocationNdx]));
6236                 }
6237         }
6238
6239         // negative (wrong types)
6240         {
6241                 struct PrimitiveToInputTypeConversion
6242                 {
6243                         GLenum inputType;
6244                         GLenum primitiveType;
6245                 };
6246
6247                 static const PrimitiveToInputTypeConversion legalConversions[] =
6248                 {
6249                         { GL_POINTS,                            GL_POINTS                                       },
6250                         { GL_LINES,                                     GL_LINES                                        },
6251                         { GL_LINES,                                     GL_LINE_LOOP                            },
6252                         { GL_LINES,                                     GL_LINE_STRIP                           },
6253                         { GL_LINES_ADJACENCY,           GL_LINES_ADJACENCY                      },
6254                         { GL_LINES_ADJACENCY,           GL_LINE_STRIP_ADJACENCY         },
6255                         { GL_TRIANGLES,                         GL_TRIANGLES                            },
6256                         { GL_TRIANGLES,                         GL_TRIANGLE_STRIP                       },
6257                         { GL_TRIANGLES,                         GL_TRIANGLE_FAN                         },
6258                         { GL_TRIANGLES_ADJACENCY,       GL_TRIANGLES_ADJACENCY          },
6259                         { GL_TRIANGLES_ADJACENCY,       GL_TRIANGLE_STRIP_ADJACENCY     },
6260                 };
6261
6262                 static const GLenum inputTypes[] =
6263                 {
6264                         GL_POINTS,
6265                         GL_LINES,
6266                         GL_LINES_ADJACENCY,
6267                         GL_TRIANGLES,
6268                         GL_TRIANGLES_ADJACENCY
6269                 };
6270
6271                 static const GLenum primitiveTypes[] =
6272                 {
6273                         GL_POINTS,
6274                         GL_LINES,
6275                         GL_LINE_LOOP,
6276                         GL_LINE_STRIP,
6277                         GL_LINES_ADJACENCY,
6278                         GL_LINE_STRIP_ADJACENCY,
6279                         GL_TRIANGLES,
6280                         GL_TRIANGLE_STRIP,
6281                         GL_TRIANGLE_FAN,
6282                         GL_TRIANGLES_ADJACENCY,
6283                         GL_TRIANGLE_STRIP_ADJACENCY
6284                 };
6285
6286                 for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); ++inputTypeNdx)
6287                 for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx)
6288                 {
6289                         const GLenum            inputType               = inputTypes[inputTypeNdx];
6290                         const GLenum            primitiveType   = primitiveTypes[primitiveTypeNdx];
6291                         const std::string       name                    = std::string("type_") + inputTypeToGLString(sglr::rr_util::mapGLGeometryShaderInputType(inputType)) + "_primitive_" + primitiveTypeToString(primitiveType);
6292                         const std::string       desc                    = std::string("Shader input type ") + inputTypeToGLString(sglr::rr_util::mapGLGeometryShaderInputType(inputType)) + ", draw primitive type " + primitiveTypeToString(primitiveType);
6293
6294                         bool isLegal = false;
6295
6296                         for (int legalNdx = 0; legalNdx < DE_LENGTH_OF_ARRAY(legalConversions); ++legalNdx)
6297                                 if (legalConversions[legalNdx].inputType == inputType && legalConversions[legalNdx].primitiveType == primitiveType)
6298                                         isLegal = true;
6299
6300                         // only illegal
6301                         if (!isLegal)
6302                                 negativeGroup->addChild(new NegativeDrawCase(m_context, name.c_str(), desc.c_str(), inputType, primitiveType));
6303                 }
6304         }
6305
6306         // vertex transform feedback
6307         {
6308                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_line_loop",                           "Capture line loop lines",                                                                      VertexFeedbackCase::METHOD_DRAW_ARRAYS,                         VertexFeedbackCase::PRIMITIVE_LINE_LOOP));
6309                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_line_strip",                          "Capture line strip lines",                                                                     VertexFeedbackCase::METHOD_DRAW_ARRAYS,                         VertexFeedbackCase::PRIMITIVE_LINE_STRIP));
6310                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_triangle_strip",                      "Capture triangle strip triangles",                                                     VertexFeedbackCase::METHOD_DRAW_ARRAYS,                         VertexFeedbackCase::PRIMITIVE_TRIANGLE_STRIP));
6311                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_triangle_fan",                        "Capture triangle fan triangles",                                                       VertexFeedbackCase::METHOD_DRAW_ARRAYS,                         VertexFeedbackCase::PRIMITIVE_TRIANGLE_FAN));
6312                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays",                         "Capture primitives generated with drawArrays",                         VertexFeedbackCase::METHOD_DRAW_ARRAYS,                         VertexFeedbackCase::PRIMITIVE_POINTS));
6313                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays_instanced",       "Capture primitives generated with drawArraysInstanced",        VertexFeedbackCase::METHOD_DRAW_ARRAYS_INSTANCED,       VertexFeedbackCase::PRIMITIVE_POINTS));
6314                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays_indirect",        "Capture primitives generated with drawArraysIndirect",         VertexFeedbackCase::METHOD_DRAW_ARRAYS_INDIRECT,        VertexFeedbackCase::PRIMITIVE_POINTS));
6315                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements",                       "Capture primitives generated with drawElements",                       VertexFeedbackCase::METHOD_DRAW_ELEMENTS,                       VertexFeedbackCase::PRIMITIVE_POINTS));
6316                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements_instanced",     "Capture primitives generated with drawElementsInstanced",      VertexFeedbackCase::METHOD_DRAW_ELEMENTS_INSTANCED,     VertexFeedbackCase::PRIMITIVE_POINTS));
6317                 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements_indirect",      "Capture primitives generated with drawElementsIndirect",       VertexFeedbackCase::METHOD_DRAW_ELEMENTS_INDIRECT,      VertexFeedbackCase::PRIMITIVE_POINTS));
6318
6319                 feedbackGroup->addChild(new VertexFeedbackOverflowCase(m_context, "capture_vertex_draw_arrays_overflow_single_buffer",          "Capture triangles to too small a buffer", VertexFeedbackOverflowCase::METHOD_DRAW_ARRAYS));
6320                 feedbackGroup->addChild(new VertexFeedbackOverflowCase(m_context, "capture_vertex_draw_elements_overflow_single_buffer",        "Capture triangles to too small a buffer", VertexFeedbackOverflowCase::METHOD_DRAW_ELEMENTS));
6321         }
6322 }
6323
6324 } // Functional
6325 } // gles31
6326 } // deqp