1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "esextcGeometryShaderPrimitiveCounter.hpp"
25 #include "deMath.h"
26 #include "gluContextInfo.hpp"
27 #include "gluDefs.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuTestLog.hpp"
31 #include <string.h>
32 
33 namespace glcts
34 {
35 /* Fragment shader code */
36 const char *GeometryShaderPrimitiveCounter::m_fragment_shader_code = "${VERSION}\n"
37                                                                      "\n"
38                                                                      "precision highp float;\n"
39                                                                      "\n"
40                                                                      "layout(location = 0) out vec4 color;\n"
41                                                                      "\n"
42                                                                      "flat in int test_gl_PrimitiveIDIn;\n"
43                                                                      "\n"
44                                                                      "void main()\n"
45                                                                      "{\n"
46                                                                      "    color = vec4(1, 1, 1, 1);\n"
47                                                                      "}\n";
48 
49 /* Vertex shader code */
50 const char *GeometryShaderPrimitiveCounter::m_vertex_shader_code = "${VERSION}\n"
51                                                                    "\n"
52                                                                    "precision highp float;\n"
53                                                                    "\n"
54                                                                    "in vec4 vertex_position;\n"
55                                                                    "\n"
56                                                                    "void main()\n"
57                                                                    "{\n"
58                                                                    "    gl_Position = vertex_position;\n"
59                                                                    "}\n";
60 
61 /** Constructor
62  *
63  * @param context       Test context
64  * @param name          Test group's name
65  * @param description   Test group's desricption
66  **/
GeometryShaderPrimitiveCounterTestGroup(Context & context,const ExtParameters & extParams,const char * name,const char * description)67 GeometryShaderPrimitiveCounterTestGroup::GeometryShaderPrimitiveCounterTestGroup(Context &context,
68                                                                                  const ExtParameters &extParams,
69                                                                                  const char *name,
70                                                                                  const char *description)
71     : TestCaseGroupBase(context, extParams, name, description)
72 {
73     /* Left blank on purpose */
74 }
75 
76 /** Initializes the test group creating test cases that this group consists of
77  **/
init(void)78 void GeometryShaderPrimitiveCounterTestGroup::init(void)
79 {
80     DataPrimitiveIDInCounter testConfiguration;
81 
82     /* Test case 6.1 */
83 
84     /* Points-to-Points Configuration */
85     testConfiguration.m_drawMode                              = GL_POINTS;
86     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
87                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
88                                                                 "        EmitVertex();\n";
89     testConfiguration.m_feedbackMode                          = GL_POINTS;
90     testConfiguration.m_layoutIn                              = "points";
91     testConfiguration.m_layoutOut                             = "points";
92     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
93     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 1;
94     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 1;
95 
96     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "point_to_point",
97                                                 "Test Group 6.1 points to points", testConfiguration));
98 
99     /* Points-to-Line Strip Configuration*/
100     testConfiguration.m_drawMode                              = GL_POINTS;
101     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
102                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
103                                                                 "        EmitVertex();\n"
104                                                                 "\n"
105                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
106                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
107                                                                 "        EmitVertex();\n";
108     testConfiguration.m_feedbackMode                          = GL_LINES;
109     testConfiguration.m_layoutIn                              = "points";
110     testConfiguration.m_layoutOut                             = "line_strip";
111     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
112     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 2;
113     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 1;
114 
115     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "points_to_line_strip",
116                                                 "Test Group 6.1 points to line strip", testConfiguration));
117 
118     /* Points-to-Triangle Strip Configuration */
119     testConfiguration.m_drawMode                              = GL_POINTS;
120     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
121                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
122                                                                 "        EmitVertex();\n"
123                                                                 "\n"
124                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
125                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
126                                                                 "        EmitVertex();\n"
127                                                                 "\n"
128                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
129                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
130                                                                 "        EmitVertex();\n";
131     testConfiguration.m_feedbackMode                          = GL_TRIANGLES;
132     testConfiguration.m_layoutIn                              = "points";
133     testConfiguration.m_layoutOut                             = "triangle_strip";
134     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
135     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 3;
136     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 1;
137 
138     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "points_to_triangle_strip",
139                                                 "Test Group 6.1 points to triangle strip", testConfiguration));
140 
141     /* Lines-to-Points Configuration */
142     testConfiguration.m_drawMode                              = GL_LINES;
143     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
144                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
145                                                                 "        EmitVertex();\n";
146     testConfiguration.m_feedbackMode                          = GL_POINTS;
147     testConfiguration.m_layoutIn                              = "lines";
148     testConfiguration.m_layoutOut                             = "points";
149     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
150     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 1;
151     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 2;
152 
153     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "lines_to_points",
154                                                 "Test Group 6.1 lines to points", testConfiguration));
155 
156     /* Lines-to-Line Strip Configuration */
157     testConfiguration.m_drawMode                              = GL_LINES;
158     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
159                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
160                                                                 "        EmitVertex();\n"
161                                                                 "\n"
162                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
163                                                                 "        gl_Position           = gl_in[1].gl_Position;\n"
164                                                                 "        EmitVertex();\n";
165     testConfiguration.m_feedbackMode                          = GL_LINES;
166     testConfiguration.m_layoutIn                              = "lines";
167     testConfiguration.m_layoutOut                             = "line_strip";
168     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 2;
169     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 2;
170     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
171 
172     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "lines_to_line_strip",
173                                                 "Test Group 6.1 lines to line strip", testConfiguration));
174 
175     /* Lines-to-Triangle Strip Configuration */
176     testConfiguration.m_drawMode                              = GL_LINES;
177     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
178                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
179                                                                 "        EmitVertex();\n"
180                                                                 "\n"
181                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
182                                                                 "        gl_Position           = gl_in[1].gl_Position;\n"
183                                                                 "        EmitVertex();\n"
184                                                                 "\n"
185                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
186                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
187                                                                 "        EmitVertex();\n";
188     testConfiguration.m_feedbackMode                          = GL_TRIANGLES;
189     testConfiguration.m_layoutIn                              = "lines";
190     testConfiguration.m_layoutOut                             = "triangle_strip";
191     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
192     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 3;
193     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 2;
194 
195     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "lines_to_triangle_strip",
196                                                 "Test Group 6.1 lines to triangle strip", testConfiguration));
197 
198     /* Triangles-to-Points Configuration */
199     testConfiguration.m_drawMode                              = GL_TRIANGLES;
200     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
201                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
202                                                                 "        EmitVertex();\n";
203     testConfiguration.m_feedbackMode                          = GL_POINTS;
204     testConfiguration.m_layoutIn                              = "triangles";
205     testConfiguration.m_layoutOut                             = "points";
206     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
207     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 1;
208     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 3;
209 
210     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "triangles_to_points",
211                                                 "Test Group 6.1 triangles to points", testConfiguration));
212 
213     /* Triangles-to-Line Strip Configuration */
214     testConfiguration.m_drawMode                              = GL_TRIANGLES;
215     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
216                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
217                                                                 "        EmitVertex();\n"
218                                                                 "\n"
219                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
220                                                                 "        gl_Position           = gl_in[1].gl_Position;\n"
221                                                                 "        EmitVertex();\n";
222     testConfiguration.m_feedbackMode                          = GL_LINES;
223     testConfiguration.m_layoutIn                              = "triangles";
224     testConfiguration.m_layoutOut                             = "line_strip";
225     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
226     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 2;
227     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 3;
228 
229     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "triangles_to_line_strip",
230                                                 "Test Group 6.1 triangles to line strip", testConfiguration));
231 
232     /* Triangles-to-Triangle Strip Configuration */
233     testConfiguration.m_drawMode                              = GL_TRIANGLES;
234     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn=gl_PrimitiveIDIn;\n"
235                                                                 "        gl_Position = gl_in[0].gl_Position;\n"
236                                                                 "        EmitVertex();\n"
237                                                                 "\n"
238                                                                 "        test_gl_PrimitiveIDIn=gl_PrimitiveIDIn;\n"
239                                                                 "        gl_Position = gl_in[1].gl_Position;\n"
240                                                                 "        EmitVertex();\n"
241                                                                 "\n"
242                                                                 "        test_gl_PrimitiveIDIn=gl_PrimitiveIDIn;\n"
243                                                                 "        gl_Position = gl_in[2].gl_Position;\n"
244                                                                 "        EmitVertex();\n";
245     testConfiguration.m_feedbackMode                          = GL_TRIANGLES;
246     testConfiguration.m_layoutIn                              = "triangles";
247     testConfiguration.m_layoutOut                             = "triangle_strip";
248     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
249     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 3;
250     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 3;
251 
252     addChild(new GeometryShaderPrimitiveCounter(getContext(), m_extParams, "triangles_to_triangle_strip",
253                                                 "Test Group 6.1 triangles to triangle strip", testConfiguration));
254 
255     /* Test case 6.2 */
256 
257     /* Points-to-Points Configuration */
258     testConfiguration.m_drawMode                              = GL_POINTS;
259     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
260                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
261                                                                 "        EmitVertex();\n";
262     testConfiguration.m_feedbackMode                          = GL_POINTS;
263     testConfiguration.m_layoutIn                              = "points";
264     testConfiguration.m_layoutOut                             = "points";
265     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
266     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 1;
267     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 1;
268 
269     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(
270         getContext(), m_extParams, "points_to_points_rp", "Test Group 6.2 points to points", testConfiguration));
271 
272     /* Points-to-Line Strip Configuration */
273     testConfiguration.m_drawMode                              = GL_POINTS;
274     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
275                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
276                                                                 "        EmitVertex();\n"
277                                                                 "\n"
278                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
279                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
280                                                                 "        EmitVertex();\n";
281     testConfiguration.m_feedbackMode                          = GL_LINES;
282     testConfiguration.m_layoutIn                              = "points";
283     testConfiguration.m_layoutOut                             = "line_strip";
284     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
285     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 2;
286     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 1;
287 
288     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(getContext(), m_extParams, "points_to_line_strip_rp",
289                                                                    "Test Group 6.2 point to line", testConfiguration));
290 
291     /* Points-to-Triangle Strip Configuration */
292     testConfiguration.m_drawMode                              = GL_POINTS;
293     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
294                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
295                                                                 "        EmitVertex();\n"
296                                                                 "\n"
297                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
298                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
299                                                                 "        EmitVertex();\n"
300                                                                 "\n"
301                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
302                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
303                                                                 "        EmitVertex();\n";
304     testConfiguration.m_feedbackMode                          = GL_TRIANGLES;
305     testConfiguration.m_layoutIn                              = "points";
306     testConfiguration.m_layoutOut                             = "triangle_strip";
307     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
308     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 3;
309     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 1;
310 
311     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(
312         getContext(), m_extParams, "points_to_triangle_strip_rp", "Test Group 6.2 points to triangle strip",
313         testConfiguration));
314 
315     /* Lines-to-Points Configuration */
316     testConfiguration.m_layoutIn                              = "lines";
317     testConfiguration.m_layoutOut                             = "points";
318     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
319                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
320                                                                 "        EmitVertex();\n";
321     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 1;
322     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 2;
323     testConfiguration.m_feedbackMode                          = GL_POINTS;
324     testConfiguration.m_drawMode                              = GL_LINES;
325     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
326 
327     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(
328         getContext(), m_extParams, "lines_to_points_rp", "Test Group 6.2 lines to points", testConfiguration));
329 
330     /* Lines to Line Strip Configuration*/
331     testConfiguration.m_drawMode                              = GL_LINES;
332     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
333                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
334                                                                 "        EmitVertex();\n"
335                                                                 "\n"
336                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
337                                                                 "        gl_Position           = gl_in[1].gl_Position;\n"
338                                                                 "        EmitVertex();\n";
339     testConfiguration.m_feedbackMode                          = GL_LINES;
340     testConfiguration.m_layoutIn                              = "lines";
341     testConfiguration.m_layoutOut                             = "line_strip";
342     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
343     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 2;
344     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 2;
345 
346     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(
347         getContext(), m_extParams, "lines_to_line_strip_rp", "Test Group 6.2 lines to line strip", testConfiguration));
348 
349     /* Lines to Triangle Strip Configuration */
350     testConfiguration.m_drawMode                              = GL_LINES;
351     testConfiguration.m_feedbackMode                          = GL_TRIANGLES;
352     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
353                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
354                                                                 "        EmitVertex();\n"
355                                                                 "\n"
356                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
357                                                                 "        gl_Position           = gl_in[1].gl_Position;\n"
358                                                                 "        EmitVertex();\n"
359                                                                 "\n"
360                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
361                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
362                                                                 "        EmitVertex();\n";
363     testConfiguration.m_layoutIn                              = "lines";
364     testConfiguration.m_layoutOut                             = "triangle_strip";
365     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
366     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 3;
367     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 2;
368 
369     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(
370         getContext(), m_extParams, "lines_to_triangle_strip_rp", "Test Group 6.2 line to triangle", testConfiguration));
371 
372     /* Triangles to Points Configuration */
373     testConfiguration.m_drawMode                              = GL_TRIANGLES;
374     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
375                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
376                                                                 "        EmitVertex();\n";
377     testConfiguration.m_feedbackMode                          = GL_POINTS;
378     testConfiguration.m_layoutIn                              = "triangles";
379     testConfiguration.m_layoutOut                             = "points";
380     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
381     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 1;
382     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 3;
383 
384     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(
385         getContext(), m_extParams, "triangles_to_points_rp", "Test Group 6.2 triangles to points", testConfiguration));
386 
387     /* Triangles to Line Strip Configuration */
388     testConfiguration.m_drawMode                              = GL_TRIANGLES;
389     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
390                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
391                                                                 "        EmitVertex();\n"
392                                                                 "\n"
393                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
394                                                                 "        gl_Position           = gl_in[1].gl_Position;\n"
395                                                                 "        EmitVertex();\n";
396     testConfiguration.m_feedbackMode                          = GL_LINES;
397     testConfiguration.m_layoutIn                              = "triangles";
398     testConfiguration.m_layoutOut                             = "line_strip";
399     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
400     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 2;
401     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 3;
402 
403     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(
404         getContext(), m_extParams, "triangles_to_line_strip_rp", "Test Group 6.2 triangles to line strip",
405         testConfiguration));
406 
407     /* Triangles to Triangle Strip Configuration*/
408     testConfiguration.m_drawMode                              = GL_TRIANGLES;
409     testConfiguration.m_emitVertexCodeForGeometryShader       = "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
410                                                                 "        gl_Position           = gl_in[0].gl_Position;\n"
411                                                                 "        EmitVertex();\n"
412                                                                 "\n"
413                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
414                                                                 "        gl_Position           = gl_in[1].gl_Position;\n"
415                                                                 "        EmitVertex();\n"
416                                                                 "\n"
417                                                                 "        test_gl_PrimitiveIDIn = gl_PrimitiveIDIn;\n"
418                                                                 "        gl_Position           = gl_in[2].gl_Position;\n"
419                                                                 "        EmitVertex();\n";
420     testConfiguration.m_feedbackMode                          = GL_TRIANGLES;
421     testConfiguration.m_layoutIn                              = "triangles";
422     testConfiguration.m_layoutOut                             = "triangle_strip";
423     testConfiguration.m_numberOfDrawnPrimitives               = 1024;
424     testConfiguration.m_numberOfVerticesPerOneOutputPrimitive = 3;
425     testConfiguration.m_numberOfVerticesPerOneInputPrimitive  = 3;
426 
427     addChild(new GeometryShaderPrimitiveCounterRestartingPrimitive(
428         getContext(), m_extParams, "triangles_to_triangle_strip_rp", "Test Group 6.2 triangles to triangle strip",
429         testConfiguration));
430 
431     /* Test case 6.3 */
432     addChild(new GeometryShaderPrimitiveIDFromFragmentShader(getContext(), m_extParams, "primitive_id_from_fragment",
433                                                              "Test Group 6.3 gl_PrimitiveID from fragment shader"));
434 }
435 
436 /** Constructor
437  *
438  * @param context               Test context
439  * @param name                  Test case's name
440  * @param description           Test case's description
441  * @param testConfiguration     Configuration that specifies the "in" and "out" primitive types
442  *                              for the geometry shader and the shader itself
443  **/
GeometryShaderPrimitiveCounter(Context & context,const ExtParameters & extParams,const char * name,const char * description,const DataPrimitiveIDInCounter & testConfiguration)444 GeometryShaderPrimitiveCounter::GeometryShaderPrimitiveCounter(Context &context, const ExtParameters &extParams,
445                                                                const char *name, const char *description,
446                                                                const DataPrimitiveIDInCounter &testConfiguration)
447     : TestCaseBase(context, extParams, name, description)
448     , m_testConfiguration(testConfiguration)
449     , m_nrVaryings(0)
450     , m_sizeOfDataArray(0)
451     , m_sizeOfFeedbackBuffer(0)
452     , m_n_components(4)
453     , m_maxGeometryOutputVertices(0)
454     , m_fragment_shader_id(0)
455     , m_geometry_shader_id(0)
456     , m_vertex_shader_id(0)
457     , m_program_id(0)
458     , m_tbo(0)
459     , m_vao(0)
460     , m_vbo(0)
461 {
462     /* Left blank on purpose */
463 }
464 
465 /** Verifies the data generated by XFB during a draw call.
466  *
467  *  @param data Input data. Must not be NULL.
468  *
469  *  @return true if successful, false otherwise.
470  */
checkResult(const glw::GLint * data)471 bool GeometryShaderPrimitiveCounter::checkResult(const glw::GLint *data)
472 {
473     bool testPassed = true;
474 
475     for (unsigned int nDrawnPrimitive = 0; nDrawnPrimitive < m_testConfiguration.m_numberOfDrawnPrimitives;
476          nDrawnPrimitive++)
477     {
478         unsigned int nEmittedValuesPerPrimitive = m_maxGeometryOutputVertices * m_nrVaryings;
479 
480         for (unsigned int nValue = (nEmittedValuesPerPrimitive * (nDrawnPrimitive));
481              nValue < (nEmittedValuesPerPrimitive * (nDrawnPrimitive + 1)); nValue++)
482         {
483             if ((unsigned int)data[nValue] != nDrawnPrimitive)
484             {
485                 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered value at index "
486                                    << "[" << nValue << "/"
487                                    << (m_testConfiguration.m_numberOfDrawnPrimitives * m_maxGeometryOutputVertices *
488                                        m_nrVaryings)
489                                    << "]: " << data[nValue] << " != " << nEmittedValuesPerPrimitive
490                                    << tcu::TestLog::EndMessage;
491 
492                 testPassed = false;
493             }
494         } /* for (all values) */
495     }     /* for (all primitives) */
496 
497     return testPassed;
498 }
499 
500 /** Creates a program object using predefined fragment & vertex shaders
501  *   and a geometry shader that is constructed on-the-fly, according
502  *   to testConfiguration parameters. The function also sets up transform
503  *   feedback varyings, prior to linking.
504  **/
createAndBuildProgramWithFeedback(void)505 void GeometryShaderPrimitiveCounter::createAndBuildProgramWithFeedback(void)
506 {
507     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
508 
509     /* Create a program object */
510     m_program_id = gl.createProgram();
511 
512     /* Specify transform feedback varyings */
513     const char *feedbackVaryings[] = {"test_gl_PrimitiveIDIn"};
514 
515     m_nrVaryings = sizeof(feedbackVaryings) / sizeof(char *);
516 
517     gl.transformFeedbackVaryings(m_program_id, m_nrVaryings, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
518     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set transform feedback varyings!");
519 
520     /* Create shader objects that will make up the program object */
521     m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
522     m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
523     m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
524     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
525 
526     /* Retrieve GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT pname value and use it as argument for
527      * max_vertices layout qualifier of the geometry shader. */
528     std::stringstream max_vertices_sstream;
529     std::string max_vertices_string;
530 
531     gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_OUTPUT_VERTICES, &m_maxGeometryOutputVertices);
532     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT!");
533 
534     m_maxGeometryOutputVertices = m_maxGeometryOutputVertices / (m_n_components + m_nrVaryings);
535 
536     max_vertices_sstream << m_maxGeometryOutputVertices;
537     max_vertices_string = max_vertices_sstream.str();
538 
539     /* Calculate the possible for loops count in Geometry Shader */
540     glw::GLint n_loop_iterations =
541         m_maxGeometryOutputVertices / m_testConfiguration.m_numberOfVerticesPerOneOutputPrimitive;
542 
543     /* adjust the m_maxGeometryOutputVertices to be the number of emitted vertices  */
544     m_maxGeometryOutputVertices = n_loop_iterations * m_testConfiguration.m_numberOfVerticesPerOneOutputPrimitive;
545 
546     std::stringstream n_loop_iterations_sstream;
547     std::string n_loop_iterations_string;
548 
549     n_loop_iterations_sstream << n_loop_iterations;
550     n_loop_iterations_string = n_loop_iterations_sstream.str();
551 
552     /* Construct geometry shader code */
553     std::string geometry_shader_code =
554         GetGeometryShaderCode(max_vertices_string, m_testConfiguration.m_layoutIn, m_testConfiguration.m_layoutOut,
555                               m_testConfiguration.m_emitVertexCodeForGeometryShader, n_loop_iterations_string);
556 
557     const char *geometry_shader_code_ptr = (const char *)geometry_shader_code.c_str();
558 
559     /* Build program */
560     if (!buildProgram(m_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, m_geometry_shader_id, 1,
561                       &geometry_shader_code_ptr, m_vertex_shader_id, 1, &m_vertex_shader_code))
562     {
563         TCU_FAIL("Program could not have been created sucessfully");
564     }
565 }
566 
567 /** Deinitializes GLES objects created during the test.
568  *
569  */
deinit(void)570 void GeometryShaderPrimitiveCounter::deinit(void)
571 {
572     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
573 
574     /* Reset OpenGL ES state */
575     gl.useProgram(0);
576     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
577     gl.bindVertexArray(0);
578 
579     /* Delete program object and shader objects */
580     if (m_program_id != 0)
581     {
582         gl.deleteProgram(m_program_id);
583     }
584 
585     if (m_vertex_shader_id != 0)
586     {
587         gl.deleteShader(m_vertex_shader_id);
588     }
589 
590     if (m_geometry_shader_id != 0)
591     {
592         gl.deleteShader(m_geometry_shader_id);
593     }
594 
595     if (m_fragment_shader_id != 0)
596     {
597         gl.deleteShader(m_fragment_shader_id);
598     }
599 
600     if (m_vbo != 0)
601     {
602         gl.deleteBuffers(1, &m_vbo);
603     }
604 
605     if (m_tbo != 0)
606     {
607         gl.deleteBuffers(1, &m_tbo);
608     }
609 
610     if (m_vao != 0)
611     {
612         gl.deleteVertexArrays(1, &m_vao);
613     }
614 
615     /* Deinitialize base class */
616     TestCaseBase::deinit();
617 }
618 
619 /** Render a test geometry and retrieve data generated by XFB.
620  *
621  *  @param feedbackResult Will be filled with data generated by XFB.
622  *                        Must provide m_sizeOfFeedbackBuffer bytes of space.
623  *                        Must not be NULL.
624  */
drawAndGetFeedback(glw::GLint * feedbackResult)625 void GeometryShaderPrimitiveCounter::drawAndGetFeedback(glw::GLint *feedbackResult)
626 {
627     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
628 
629     gl.useProgram(m_program_id);
630     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
631 
632     gl.enable(GL_RASTERIZER_DISCARD);
633     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed!");
634 
635     /* Perform transform feedback */
636     gl.beginTransformFeedback(m_testConfiguration.m_feedbackMode);
637     {
638         drawFunction();
639     }
640     gl.endTransformFeedback();
641 
642     GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
643 
644     gl.disable(GL_RASTERIZER_DISCARD);
645     GLU_EXPECT_NO_ERROR(gl.getError(), "giDisable(GL_RASTERIZER_DISCARD) failed");
646 
647     /* Fetch the generated data */
648     glw::GLint *feedback = NULL;
649 
650     feedback = (glw::GLint *)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
651                                                m_sizeOfFeedbackBuffer, GL_MAP_READ_BIT);
652     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
653 
654     memcpy(feedbackResult, feedback, m_sizeOfFeedbackBuffer);
655 
656     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
657     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
658 }
659 
660 /**  Renders the test geometry.
661  *
662  */
drawFunction()663 void GeometryShaderPrimitiveCounter::drawFunction()
664 {
665     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
666 
667     gl.drawArrays(m_testConfiguration.m_drawMode, 0, /* first */
668                   m_testConfiguration.m_numberOfDrawnPrimitives *
669                       m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive);
670 }
671 
672 /** Fill geometry shader template
673  *
674  *  @param max_vertices  String in "max_vertices=N" format (where N is a valid value);
675  *  @param layout_in     String storing an "in" layout qualifier definition;
676  *  @param layout_out    String storing an "out" layout qualifier definition;
677  *  @param emit_vertices String storing the vertex emitting code;
678  *  @param n_iterations  String storing a number of vertex emitting iterations;
679  */
GetGeometryShaderCode(const std::string & max_vertices,const std::string & layout_in,const std::string & layout_out,const std::string & emit_vertices,const std::string & n_iterations)680 std::string GeometryShaderPrimitiveCounter::GetGeometryShaderCode(const std::string &max_vertices,
681                                                                   const std::string &layout_in,
682                                                                   const std::string &layout_out,
683                                                                   const std::string &emit_vertices,
684                                                                   const std::string &n_iterations)
685 {
686     /* Geometry shader template code */
687     std::string m_geometry_shader_template = "${VERSION}\n"
688                                              "\n"
689                                              "${GEOMETRY_SHADER_REQUIRE}\n"
690                                              "\n"
691                                              "precision highp float;\n"
692                                              "\n"
693                                              "layout(<-LAYOUT-IN->)                                  in;\n"
694                                              "layout(<-LAYOUT-OUT->, max_vertices =<-MAX-VERTICES->) out;\n"
695                                              "\n"
696                                              "flat out int test_gl_PrimitiveIDIn;\n"
697                                              "\n"
698                                              "void main()\n"
699                                              "{\n"
700                                              "    for (int i=0; i<<-N_ITERATIONS->; i++)\n"
701                                              "    {\n"
702                                              "        <-EMIT-VERTICES->\n"
703                                              "        EndPrimitive();\n"
704                                              "    }\n"
705                                              "}\n";
706 
707     /* Max number of emited vertices */
708     std::string template_name     = "<-MAX-VERTICES->";
709     std::size_t template_position = m_geometry_shader_template.find(template_name);
710 
711     while (template_position != std::string::npos)
712     {
713         m_geometry_shader_template =
714             m_geometry_shader_template.replace(template_position, template_name.length(), max_vertices);
715 
716         template_position = m_geometry_shader_template.find(template_name);
717     }
718 
719     /* In primitive type */
720     template_name     = "<-LAYOUT-IN->";
721     template_position = m_geometry_shader_template.find(template_name);
722 
723     while (template_position != std::string::npos)
724     {
725         m_geometry_shader_template =
726             m_geometry_shader_template.replace(template_position, template_name.length(), layout_in);
727 
728         template_position = m_geometry_shader_template.find(template_name);
729     }
730 
731     /* Out primitive type */
732     template_name     = "<-LAYOUT-OUT->";
733     template_position = m_geometry_shader_template.find(template_name);
734 
735     while (template_position != std::string::npos)
736     {
737         m_geometry_shader_template =
738             m_geometry_shader_template.replace(template_position, template_name.length(), layout_out);
739 
740         template_position = m_geometry_shader_template.find(template_name);
741     }
742 
743     /* Vertex emit code */
744     template_name     = "<-EMIT-VERTICES->";
745     template_position = m_geometry_shader_template.find(template_name);
746 
747     while (template_position != std::string::npos)
748     {
749         m_geometry_shader_template =
750             m_geometry_shader_template.replace(template_position, template_name.length(), emit_vertices);
751 
752         template_position = m_geometry_shader_template.find(template_name);
753     }
754 
755     /* Number of iterations, during which we'll be emitting vertices */
756     template_name     = "<-N_ITERATIONS->";
757     template_position = m_geometry_shader_template.find(template_name);
758 
759     while (template_position != std::string::npos)
760     {
761         m_geometry_shader_template =
762             m_geometry_shader_template.replace(template_position, template_name.length(), n_iterations);
763 
764         template_position = m_geometry_shader_template.find(template_name);
765     }
766 
767     return m_geometry_shader_template;
768 }
769 
770 /** Executes the test.
771  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
772  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
773  *  Note the function throws exception should an error occur!
774  **/
iterate(void)775 tcu::TestNode::IterateResult GeometryShaderPrimitiveCounter::iterate(void)
776 {
777     if (!m_is_geometry_shader_extension_supported)
778     {
779         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
780     }
781 
782     /* Set up */
783     glw::GLint *feedbackResult = NULL;
784 
785     createAndBuildProgramWithFeedback();
786     prepareBufferObjects();
787 
788     feedbackResult = new glw::GLint[m_sizeOfFeedbackBuffer];
789 
790     /* Execute the test */
791     drawAndGetFeedback(feedbackResult);
792 
793     /* Set the CTS test result, depending on the outcome */
794     if (checkResult(feedbackResult))
795     {
796         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
797     }
798     else
799     {
800         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
801     }
802 
803     if (feedbackResult != NULL)
804     {
805         delete[] feedbackResult;
806 
807         feedbackResult = DE_NULL;
808     }
809 
810     return STOP;
811 }
812 
813 /** Prepare buffer objects and initialize their storage. It will
814  *   later be used as vertex attribute array data source, as well
815  *   as transform feedback destination.
816  **/
prepareBufferObjects()817 void GeometryShaderPrimitiveCounter::prepareBufferObjects()
818 {
819     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
820 
821     /* Create a VAO */
822     gl.genVertexArrays(1, &m_vao);
823     gl.bindVertexArray(m_vao);
824 
825     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a VAO!");
826 
827     m_sizeOfDataArray = m_testConfiguration.m_numberOfDrawnPrimitives * m_n_components *
828                         m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive;
829 
830     gl.genBuffers(1, &m_vbo);
831     gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
832     gl.bufferData(GL_ARRAY_BUFFER, m_sizeOfDataArray * sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
833 
834     GLU_EXPECT_NO_ERROR(gl.getError(),
835                         "Could not initialize a buffer object to hold data for vertex_position attribute!");
836 
837     /* Set up "vertex_position" vertex attribute array */
838     glw::GLint vertex_position_attribute_location = -1;
839 
840     vertex_position_attribute_location = gl.getAttribLocation(m_program_id, "vertex_position");
841     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve vertex_position attribute location!");
842 
843     gl.vertexAttribPointer(vertex_position_attribute_location, 4, /* size */
844                            GL_FLOAT, GL_FALSE,                    /* normalized */
845                            0,                                     /* stride */
846                            0);                                    /* pointer */
847     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed for vertex_position attribute!");
848 
849     gl.enableVertexAttribArray(vertex_position_attribute_location);
850     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed for vertex_position attribute!");
851 
852     /* Set up buffer object to hold result transform feedback data */
853     m_sizeOfFeedbackBuffer = static_cast<glw::GLuint>(m_testConfiguration.m_numberOfDrawnPrimitives *
854                                                       m_maxGeometryOutputVertices * m_nrVaryings * sizeof(glw::GLint));
855 
856     gl.genBuffers(1, &m_tbo);
857     gl.bindBuffer(GL_ARRAY_BUFFER, m_tbo);
858     gl.bufferData(GL_ARRAY_BUFFER, m_sizeOfFeedbackBuffer, DE_NULL, GL_STATIC_COPY);
859     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a buffer object to hold transform feedback data!");
860 
861     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_tbo);
862     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind a buffer object to transform feedback binding point!");
863 }
864 
865 /** Constructor
866  *
867  * @param context               Test context;
868  * @param name                  Test case's name;
869  * @param description           Test case's description;
870  * @param testConfiguration     Configuration that specifies the "in" and "out" primitive type
871  *                              for the geometry shader, as well as defines other miscellaneous
872  *                              properties of the test the shader.
873  **/
GeometryShaderPrimitiveCounterRestartingPrimitive(Context & context,const ExtParameters & extParams,const char * name,const char * description,const DataPrimitiveIDInCounter & testConfiguration)874 GeometryShaderPrimitiveCounterRestartingPrimitive::GeometryShaderPrimitiveCounterRestartingPrimitive(
875     Context &context, const ExtParameters &extParams, const char *name, const char *description,
876     const DataPrimitiveIDInCounter &testConfiguration)
877     : GeometryShaderPrimitiveCounter(context, extParams, name, description, testConfiguration)
878     , m_bo_id(0)
879     , m_numberOfRestarts(2)
880 {
881 }
882 
883 /** Deinitializes GLES objects created during the test.
884  *
885  */
deinit(void)886 void GeometryShaderPrimitiveCounterRestartingPrimitive::deinit(void)
887 {
888     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
889 
890     if (m_bo_id != 0)
891     {
892         gl.deleteBuffers(1, &m_bo_id);
893 
894         m_bo_id = 0;
895     }
896 
897     /* Call base class' deinit() */
898     GeometryShaderPrimitiveCounter::deinit();
899 }
900 
901 /** Renders the test geometry.
902  *
903  */
drawFunction()904 void GeometryShaderPrimitiveCounterRestartingPrimitive::drawFunction()
905 {
906     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
907 
908     gl.drawElements(
909         m_testConfiguration.m_drawMode,
910         (m_testConfiguration.m_numberOfDrawnPrimitives * m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive +
911          m_numberOfRestarts),
912         GL_UNSIGNED_INT, 0 /* indices */);
913 }
914 
915 /** Executes the test.
916  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
917  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
918  *  Note the function throws exception should an error occur!
919  **/
iterate(void)920 tcu::TestNode::IterateResult GeometryShaderPrimitiveCounterRestartingPrimitive::iterate(void)
921 {
922     if (!m_is_geometry_shader_extension_supported)
923     {
924         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
925     }
926 
927     /* Set up */
928     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
929 
930     createAndBuildProgramWithFeedback();
931     prepareBufferObjects();
932 
933     glw::GLenum restart_token;
934     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
935     {
936         restart_token = GL_PRIMITIVE_RESTART;
937     }
938     else
939     {
940         restart_token = GL_PRIMITIVE_RESTART_FIXED_INDEX;
941     }
942 
943     gl.enable(restart_token);
944     GLU_EXPECT_NO_ERROR(gl.getError(), "Enabling primitive restart failed");
945 
946     setUpVertexAttributeArrays();
947 
948     /* Render the test geometry */
949     glw::GLint *feedbackResult = NULL;
950     feedbackResult             = new glw::GLint[m_sizeOfFeedbackBuffer];
951     try
952     {
953         drawAndGetFeedback(feedbackResult);
954     }
955     catch (...)
956     {
957         delete[] feedbackResult;
958         feedbackResult = NULL;
959         throw;
960     }
961 
962     gl.disable(restart_token);
963 
964     int error = gl.getError();
965     if (error != GL_NO_ERROR)
966     {
967         delete[] feedbackResult;
968         feedbackResult = NULL;
969         GLU_EXPECT_NO_ERROR(error, "Disabling primitive restart failed");
970     }
971 
972     /* Check the result and update the DEQP test result accordingly */
973     if (checkResult(feedbackResult))
974     {
975         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
976     }
977     else
978     {
979         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
980     }
981 
982     delete[] feedbackResult;
983     feedbackResult = NULL;
984 
985     return STOP;
986 }
987 
988 /** Prepare the element vertex attribute array data. Make sure to
989  *  use primitive index functionality.
990  */
setUpVertexAttributeArrays()991 void GeometryShaderPrimitiveCounterRestartingPrimitive::setUpVertexAttributeArrays()
992 {
993     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
994 
995     /* Create a buffer object to hold the element data */
996     glw::GLuint *indices = DE_NULL;
997     const unsigned int nIndices =
998         m_testConfiguration.m_numberOfDrawnPrimitives * m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive +
999         m_numberOfRestarts;
1000     unsigned int restartIndex;
1001     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1002     {
1003         restartIndex = nIndices;
1004     }
1005     else
1006     {
1007         restartIndex = 0xFFFFFFFF;
1008     }
1009 
1010     gl.genBuffers(1, &m_bo_id);
1011     gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1012     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate a buffer object");
1013 
1014     /* Prepare the data we will later use for configuring buffer object storage contents */
1015     indices = new unsigned int[nIndices];
1016     memset(indices, 0, nIndices * sizeof(unsigned int));
1017 
1018     for (unsigned int restartNr = 0; restartNr < m_numberOfRestarts; ++restartNr)
1019     {
1020         for (unsigned int i = m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive * restartNr + 1; i < nIndices;
1021              i++)
1022         {
1023             if (i < m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive * (restartNr + 1) + restartNr)
1024             {
1025                 indices[i] = i - restartNr;
1026             }
1027             else if (i > m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive * (restartNr + 1) + restartNr)
1028             {
1029                 indices[i] = (i - 1 - restartNr);
1030             }
1031         }
1032         indices[m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive * (restartNr + 1) + restartNr] =
1033             restartIndex;
1034     }
1035 
1036     /*
1037      m_testCtx.getLog() << tcu::TestLog::Message << "Indices table [ " << tcu::TestLog::EndMessage;
1038      for (unsigned int i = 0; i < nIndices; i++)
1039      {
1040      m_testCtx.getLog() << tcu::TestLog::Message << indices[i] << ", " << tcu::TestLog::EndMessage;
1041      }
1042      m_testCtx.getLog() << tcu::TestLog::Message << " ]" << tcu::TestLog::EndMessage;
1043      */
1044 
1045     /* Set up buffer object data storage */
1046     gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(glw::GLuint) * nIndices, indices, GL_STATIC_DRAW);
1047     /* Free the buffer we no longer need */
1048     delete[] indices;
1049     indices = NULL;
1050     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create element array buffer object");
1051 
1052     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1053     {
1054         /* Set up primitive restarting */
1055         gl.primitiveRestartIndex(restartIndex);
1056         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set primitive restart index");
1057     }
1058 }
1059 
1060 /* Vertex shader code */
1061 const char *GeometryShaderPrimitiveIDFromFragmentShader::m_vertex_shader_code = "${VERSION}\n"
1062                                                                                 "\n"
1063                                                                                 "precision highp float;\n"
1064                                                                                 "\n"
1065                                                                                 "flat out int vs_vertex_id;"
1066                                                                                 "\n"
1067                                                                                 "     in vec4 vertex_position;\n"
1068                                                                                 "\n"
1069                                                                                 "void main()\n"
1070                                                                                 "{\n"
1071                                                                                 "    vs_vertex_id = gl_VertexID;"
1072                                                                                 "}\n";
1073 
1074 /* Geometry Shader code */
1075 const char *GeometryShaderPrimitiveIDFromFragmentShader::m_geometry_shader_code =
1076     "${VERSION}\n"
1077     "\n"
1078     "${GEOMETRY_SHADER_REQUIRE}\n"
1079     "\n"
1080     "precision highp float;\n"
1081     "\n"
1082     "layout(points)                           in;\n"
1083     "layout(triangle_strip, max_vertices = 4) out;\n"
1084     "\n"
1085     "flat in int vs_vertex_id[1];\n"
1086     "\n"
1087     "void main()\n"
1088     "{\n"
1089     "    int column = vs_vertex_id[0] % 64;\n"
1090     "    int row    = vs_vertex_id[0] / 64;\n"
1091     "\n"
1092     "    gl_PrimitiveID = vs_vertex_id[0];\n"
1093     "    gl_Position    = vec4(-1.0 + float(column+1) / 32.0, -1.0 + float(row + 1) / 32.0, 0, 1);\n"
1094     "    EmitVertex();\n"
1095     "\n"
1096     "    gl_PrimitiveID = vs_vertex_id[0];\n"
1097     "    gl_Position    = vec4(-1.0 + float(column+1) / 32.0, -1.0 + float(row) / 32.0, 0, 1);\n"
1098     "    EmitVertex();\n"
1099     "\n"
1100     "    gl_PrimitiveID = vs_vertex_id[0];\n"
1101     "    gl_Position    = vec4(-1.0 + float(column)   / 32.0, -1.0 + float(row + 1) / 32.0, 0, 1);\n"
1102     "    EmitVertex();\n"
1103     "\n"
1104     "    gl_PrimitiveID = vs_vertex_id[0];\n"
1105     "    gl_Position    = vec4(-1.0 + float(column)/ 32.0, -1.0 + float(row)/ 32.0, 0, 1);\n"
1106     "    EmitVertex();\n"
1107     "\n"
1108     "    EndPrimitive();\n"
1109     "}\n";
1110 
1111 /* Fragment shader code */
1112 const char *GeometryShaderPrimitiveIDFromFragmentShader::m_fragment_shader_code =
1113     "${VERSION}\n"
1114     "\n"
1115     "${GEOMETRY_SHADER_REQUIRE}\n"
1116     "\n"
1117     "precision highp float;\n"
1118     "\n"
1119     "layout(location = 0) out vec4 result;\n"
1120     "\n"
1121     "void main()\n"
1122     "{\n"
1123     "    result.x =       float(gl_PrimitiveID % 64)          / 64.0f;\n"
1124     "    result.y = floor(float(gl_PrimitiveID)      / 64.0f) / 64.0f;\n"
1125     "    result.z =       float(gl_PrimitiveID)               / 4096.0f;\n"
1126     "    result.w = ((gl_PrimitiveID % 2) == 0) ? 1.0f : 0.0f;\n"
1127     "}\n";
1128 
1129 /** Constructor
1130  *
1131  * @param context               Test context;
1132  * @param name                  Test case's name;
1133  * @param description           Test case's description;
1134  **/
GeometryShaderPrimitiveIDFromFragmentShader(Context & context,const ExtParameters & extParams,const char * name,const char * description)1135 GeometryShaderPrimitiveIDFromFragmentShader::GeometryShaderPrimitiveIDFromFragmentShader(Context &context,
1136                                                                                          const ExtParameters &extParams,
1137                                                                                          const char *name,
1138                                                                                          const char *description)
1139     : TestCaseBase(context, extParams, name, description)
1140     , m_n_drawn_vertices(4096)
1141     , m_squareEdgeSize(16)
1142     , m_texture_height(1024)
1143     , m_texture_n_components(4)
1144     , m_texture_n_levels(1)
1145     , m_texture_width(1024)
1146     , m_fbo_id(0)
1147     , m_fragment_shader_id(0)
1148     , m_geometry_shader_id(0)
1149     , m_program_id(0)
1150     , m_texture_id(0)
1151     , m_vao_id(0)
1152     , m_vbo_id(0)
1153     , m_vertex_shader_id(0)
1154 {
1155 }
1156 
1157 /** Deinitializes GLES objects created during the test.
1158  *
1159  */
deinit(void)1160 void GeometryShaderPrimitiveIDFromFragmentShader::deinit(void)
1161 {
1162     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1163 
1164     /* Reset OpenGL ES state */
1165     gl.useProgram(0);
1166     gl.bindTexture(GL_TEXTURE_2D, 0);
1167     gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1168     gl.bindVertexArray(0);
1169 
1170     if (m_program_id != 0)
1171     {
1172         gl.deleteProgram(m_program_id);
1173 
1174         m_program_id = 0;
1175     }
1176 
1177     if (m_fragment_shader_id != 0)
1178     {
1179         gl.deleteShader(m_fragment_shader_id);
1180 
1181         m_fragment_shader_id = 0;
1182     }
1183 
1184     if (m_geometry_shader_id != 0)
1185     {
1186         gl.deleteShader(m_geometry_shader_id);
1187 
1188         m_geometry_shader_id = 0;
1189     }
1190 
1191     if (m_vertex_shader_id != 0)
1192     {
1193         gl.deleteShader(m_vertex_shader_id);
1194 
1195         m_vertex_shader_id = 0;
1196     }
1197 
1198     if (m_texture_id != 0)
1199     {
1200         gl.deleteTextures(1, &m_texture_id);
1201 
1202         m_texture_id = 0;
1203     }
1204 
1205     if (m_fbo_id != 0)
1206     {
1207         gl.deleteFramebuffers(1, &m_fbo_id);
1208 
1209         m_fbo_id = 0;
1210     }
1211 
1212     if (m_vao_id != 0)
1213     {
1214         gl.deleteVertexArrays(1, &m_vao_id);
1215 
1216         m_vao_id = 0;
1217     }
1218 
1219     if (m_vbo_id != 0)
1220     {
1221         gl.deleteBuffers(1, &m_vbo_id);
1222 
1223         m_vbo_id = 0;
1224     }
1225 
1226     /* Release base class */
1227     TestCaseBase::deinit();
1228 }
1229 
1230 /** Executes the test.
1231  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1232  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1233  *  Note the function throws exception should an error occur!
1234  **/
iterate(void)1235 tcu::TestNode::IterateResult GeometryShaderPrimitiveIDFromFragmentShader::iterate(void)
1236 {
1237     const float epsilon = 1.0f / 256.0f;
1238 
1239     if (!m_is_geometry_shader_extension_supported)
1240     {
1241         throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1242     }
1243 
1244     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1245 
1246     /* Create a program object */
1247     m_program_id = gl.createProgram();
1248     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
1249 
1250     /* Create shader objects */
1251     m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
1252     m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1253     m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
1254     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
1255 
1256     /* Build the program object */
1257     if (!buildProgram(m_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, m_geometry_shader_id, 1,
1258                       &m_geometry_shader_code, m_vertex_shader_id, 1, &m_vertex_shader_code))
1259     {
1260         TCU_FAIL("Program could not have been created sucessfully");
1261     }
1262 
1263     /* Create and configure a texture object we'll be rendering to */
1264     gl.genTextures(1, &m_texture_id);
1265     gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
1266     gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height);
1267 
1268     GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating a texture object!");
1269 
1270     /* Create and configure the framebuffer object */
1271     gl.genFramebuffers(1, &m_fbo_id);
1272     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
1273     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
1274 
1275     GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring framebuffer object!");
1276 
1277     /* Create and bind a vertex array object */
1278     gl.genVertexArrays(1, &m_vao_id);
1279     gl.bindVertexArray(m_vao_id);
1280 
1281     GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring a vertex array object");
1282 
1283     /* Set up a buffer object we will use to hold vertex_position attribute data */
1284     const glw::GLuint sizeOfDataArray =
1285         static_cast<glw::GLuint>(m_n_drawn_vertices * m_texture_n_components * sizeof(glw::GLfloat));
1286 
1287     gl.genBuffers(1, &m_vbo_id);
1288     gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
1289     gl.bufferData(GL_ARRAY_BUFFER, sizeOfDataArray, DE_NULL, GL_STATIC_DRAW);
1290 
1291     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a buffer object to hold vertex_position attribute data!");
1292 
1293     /* Set up the viewport */
1294     gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
1295     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
1296 
1297     /* Clear the color buffer */
1298     gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
1299     gl.clear(GL_COLOR_BUFFER_BIT);
1300 
1301     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer!");
1302 
1303     /* Render the test geometry */
1304     gl.useProgram(m_program_id);
1305     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
1306 
1307     gl.drawArrays(GL_POINTS, 0 /* first */, m_n_drawn_vertices);
1308     GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
1309 
1310     /* Read the rendered data */
1311     glw::GLubyte *resultBuffer = new glw::GLubyte[m_texture_width * m_texture_height * m_texture_n_components];
1312 
1313     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
1314     int error = gl.getError();
1315     if (error != GL_NO_ERROR)
1316     {
1317         delete[] resultBuffer;
1318         resultBuffer = NULL;
1319         GLU_EXPECT_NO_ERROR(error, "glBindFramebuffer() call failed");
1320     }
1321 
1322     gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, resultBuffer);
1323 
1324     error = gl.getError();
1325     if (error != GL_NO_ERROR)
1326     {
1327         delete[] resultBuffer;
1328         resultBuffer = NULL;
1329         GLU_EXPECT_NO_ERROR(error, "Reading pixels failed!");
1330     }
1331 
1332     /* Loop over all pixels and compare the rendered data with reference values */
1333     for (glw::GLuint y = 0; y < m_texture_height; ++y)
1334     {
1335         glw::GLubyte *data_row = resultBuffer + y * m_texture_width * m_texture_n_components;
1336 
1337         for (glw::GLuint x = 0; x < m_texture_width; ++x)
1338         {
1339             glw::GLuint column      = (x / m_squareEdgeSize);
1340             glw::GLubyte *data      = data_row + x * m_texture_n_components;
1341             glw::GLuint row         = (y / m_squareEdgeSize);
1342             glw::GLuint primitiveID = column + (row * (m_texture_width / m_squareEdgeSize));
1343 
1344             /* Calculate expected and rendered pixel color */
1345             float rendered_rgba[4] = {0};
1346             float expected_rgba[4];
1347 
1348             for (unsigned int n_channel = 0; n_channel < 4 /* RGBA */; ++n_channel)
1349             {
1350                 rendered_rgba[n_channel] = float(data[n_channel]) / 255.0f;
1351             }
1352 
1353             expected_rgba[0] = (glw::GLfloat)(primitiveID % 64) / 64.0f;
1354             expected_rgba[1] = deFloatFloor((glw::GLfloat)(primitiveID) / 64.0f) / 64.0f;
1355             expected_rgba[2] = (glw::GLfloat)(primitiveID) / 4096.0f;
1356             expected_rgba[3] = (((primitiveID % 2) == 0) ? 1.0f : 0.0f);
1357 
1358             /* Compare the data */
1359             if (de::abs(rendered_rgba[0] - expected_rgba[0]) > epsilon ||
1360                 de::abs(rendered_rgba[1] - expected_rgba[1]) > epsilon ||
1361                 de::abs(rendered_rgba[2] - expected_rgba[2]) > epsilon ||
1362                 de::abs(rendered_rgba[3] - expected_rgba[3]) > epsilon)
1363             {
1364                 m_testCtx.getLog() << tcu::TestLog::Message << "Primitive ID: " << primitiveID << "Rendered data"
1365                                    << "equal (" << rendered_rgba[0] << ", " << rendered_rgba[1] << ", "
1366                                    << rendered_rgba[2] << ", " << rendered_rgba[3] << ") "
1367                                    << "exceeds allowed epsilon when compared to expected data equal ("
1368                                    << expected_rgba[0] << ", " << expected_rgba[1] << ", " << expected_rgba[2] << ", "
1369                                    << expected_rgba[3] << ")." << tcu::TestLog::EndMessage;
1370 
1371                 delete[] resultBuffer;
1372                 resultBuffer = NULL;
1373 
1374                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1375                 return STOP;
1376             } /* if (rendered data is invalid) */
1377         }     /* for (all columns) */
1378     }         /* for (all rows) */
1379 
1380     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1381 
1382     delete[] resultBuffer;
1383     resultBuffer = NULL;
1384 
1385     return STOP;
1386 }
1387 
1388 } // namespace glcts
1389