• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 << "/" << (m_testConfiguration.m_numberOfDrawnPrimitives *
487 															   m_maxGeometryOutputVertices * m_nrVaryings)
488 								   << "]: " << data[nValue] << " != " << nEmittedValuesPerPrimitive
489 								   << tcu::TestLog::EndMessage;
490 
491 				testPassed = false;
492 			}
493 		} /* for (all values) */
494 	}	 /* for (all primitives) */
495 
496 	return testPassed;
497 }
498 
499 /** Creates a program object using predefined fragment & vertex shaders
500  *   and a geometry shader that is constructed on-the-fly, according
501  *   to testConfiguration parameters. The function also sets up transform
502  *   feedback varyings, prior to linking.
503  **/
createAndBuildProgramWithFeedback(void)504 void GeometryShaderPrimitiveCounter::createAndBuildProgramWithFeedback(void)
505 {
506 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
507 
508 	/* Create a program object */
509 	m_program_id = gl.createProgram();
510 
511 	/* Specify transform feedback varyings */
512 	const char* feedbackVaryings[] = { "test_gl_PrimitiveIDIn" };
513 
514 	m_nrVaryings = sizeof(feedbackVaryings) / sizeof(char*);
515 
516 	gl.transformFeedbackVaryings(m_program_id, m_nrVaryings, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
517 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set transform feedback varyings!");
518 
519 	/* Create shader objects that will make up the program object */
520 	m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
521 	m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
522 	m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
523 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
524 
525 	/* Retrieve GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT pname value and use it as argument for
526 	 * max_vertices layout qualifier of the geometry shader. */
527 	std::stringstream max_vertices_sstream;
528 	std::string		  max_vertices_string;
529 
530 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_OUTPUT_VERTICES, &m_maxGeometryOutputVertices);
531 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT!");
532 
533 	m_maxGeometryOutputVertices = m_maxGeometryOutputVertices / (m_n_components + m_nrVaryings);
534 
535 	max_vertices_sstream << m_maxGeometryOutputVertices;
536 	max_vertices_string = max_vertices_sstream.str();
537 
538 	/* Calculate the possible for loops count in Geometry Shader */
539 	glw::GLint n_loop_iterations =
540 		m_maxGeometryOutputVertices / m_testConfiguration.m_numberOfVerticesPerOneOutputPrimitive;
541 
542 	/* adjust the m_maxGeometryOutputVertices to be the number of emitted vertices  */
543 	m_maxGeometryOutputVertices = n_loop_iterations * m_testConfiguration.m_numberOfVerticesPerOneOutputPrimitive;
544 
545 	std::stringstream n_loop_iterations_sstream;
546 	std::string		  n_loop_iterations_string;
547 
548 	n_loop_iterations_sstream << n_loop_iterations;
549 	n_loop_iterations_string = n_loop_iterations_sstream.str();
550 
551 	/* Construct geometry shader code */
552 	std::string geometry_shader_code =
553 		GetGeometryShaderCode(max_vertices_string, m_testConfiguration.m_layoutIn, m_testConfiguration.m_layoutOut,
554 							  m_testConfiguration.m_emitVertexCodeForGeometryShader, n_loop_iterations_string);
555 
556 	const char* geometry_shader_code_ptr = (const char*)geometry_shader_code.c_str();
557 
558 	/* Build program */
559 	if (!buildProgram(m_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, m_geometry_shader_id, 1,
560 					  &geometry_shader_code_ptr, m_vertex_shader_id, 1, &m_vertex_shader_code))
561 	{
562 		TCU_FAIL("Program could not have been created sucessfully");
563 	}
564 }
565 
566 /** Deinitializes GLES objects created during the test.
567  *
568  */
deinit(void)569 void GeometryShaderPrimitiveCounter::deinit(void)
570 {
571 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
572 
573 	/* Reset OpenGL ES state */
574 	gl.useProgram(0);
575 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
576 	gl.bindVertexArray(0);
577 
578 	/* Delete program object and shader objects */
579 	if (m_program_id != 0)
580 	{
581 		gl.deleteProgram(m_program_id);
582 	}
583 
584 	if (m_vertex_shader_id != 0)
585 	{
586 		gl.deleteShader(m_vertex_shader_id);
587 	}
588 
589 	if (m_geometry_shader_id != 0)
590 	{
591 		gl.deleteShader(m_geometry_shader_id);
592 	}
593 
594 	if (m_fragment_shader_id != 0)
595 	{
596 		gl.deleteShader(m_fragment_shader_id);
597 	}
598 
599 	if (m_vbo != 0)
600 	{
601 		gl.deleteBuffers(1, &m_vbo);
602 	}
603 
604 	if (m_tbo != 0)
605 	{
606 		gl.deleteBuffers(1, &m_tbo);
607 	}
608 
609 	if (m_vao != 0)
610 	{
611 		gl.deleteVertexArrays(1, &m_vao);
612 	}
613 
614 	/* Deinitialize base class */
615 	TestCaseBase::deinit();
616 }
617 
618 /** Render a test geometry and retrieve data generated by XFB.
619  *
620  *  @param feedbackResult Will be filled with data generated by XFB.
621  *                        Must provide m_sizeOfFeedbackBuffer bytes of space.
622  *                        Must not be NULL.
623  */
drawAndGetFeedback(glw::GLint * feedbackResult)624 void GeometryShaderPrimitiveCounter::drawAndGetFeedback(glw::GLint* feedbackResult)
625 {
626 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
627 
628 	gl.useProgram(m_program_id);
629 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
630 
631 	gl.enable(GL_RASTERIZER_DISCARD);
632 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed!");
633 
634 	/* Perform transform feedback */
635 	gl.beginTransformFeedback(m_testConfiguration.m_feedbackMode);
636 	{
637 		drawFunction();
638 	}
639 	gl.endTransformFeedback();
640 
641 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
642 
643 	gl.disable(GL_RASTERIZER_DISCARD);
644 	GLU_EXPECT_NO_ERROR(gl.getError(), "giDisable(GL_RASTERIZER_DISCARD) failed");
645 
646 	/* Fetch the generated data */
647 	glw::GLint* feedback = NULL;
648 
649 	feedback = (glw::GLint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
650 											  m_sizeOfFeedbackBuffer, GL_MAP_READ_BIT);
651 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
652 
653 	memcpy(feedbackResult, feedback, m_sizeOfFeedbackBuffer);
654 
655 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
656 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
657 }
658 
659 /**  Renders the test geometry.
660  *
661  */
drawFunction()662 void GeometryShaderPrimitiveCounter::drawFunction()
663 {
664 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
665 
666 	gl.drawArrays(m_testConfiguration.m_drawMode, 0, /* first */
667 				  m_testConfiguration.m_numberOfDrawnPrimitives *
668 					  m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive);
669 }
670 
671 /** Fill geometry shader template
672  *
673  *  @param max_vertices  String in "max_vertices=N" format (where N is a valid value);
674  *  @param layout_in     String storing an "in" layout qualifier definition;
675  *  @param layout_out    String storing an "out" layout qualifier definition;
676  *  @param emit_vertices String storing the vertex emitting code;
677  *  @param n_iterations  String storing a number of vertex emitting iterations;
678  */
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)679 std::string GeometryShaderPrimitiveCounter::GetGeometryShaderCode(const std::string& max_vertices,
680 																  const std::string& layout_in,
681 																  const std::string& layout_out,
682 																  const std::string& emit_vertices,
683 																  const std::string& n_iterations)
684 {
685 	/* Geometry shader template code */
686 	std::string m_geometry_shader_template = "${VERSION}\n"
687 											 "\n"
688 											 "${GEOMETRY_SHADER_REQUIRE}\n"
689 											 "\n"
690 											 "precision highp float;\n"
691 											 "\n"
692 											 "layout(<-LAYOUT-IN->)                                  in;\n"
693 											 "layout(<-LAYOUT-OUT->, max_vertices =<-MAX-VERTICES->) out;\n"
694 											 "\n"
695 											 "flat out int test_gl_PrimitiveIDIn;\n"
696 											 "\n"
697 											 "void main()\n"
698 											 "{\n"
699 											 "    for (int i=0; i<<-N_ITERATIONS->; i++)\n"
700 											 "    {\n"
701 											 "        <-EMIT-VERTICES->\n"
702 											 "        EndPrimitive();\n"
703 											 "    }\n"
704 											 "}\n";
705 
706 	/* Max number of emited vertices */
707 	std::string template_name	 = "<-MAX-VERTICES->";
708 	std::size_t template_position = m_geometry_shader_template.find(template_name);
709 
710 	while (template_position != std::string::npos)
711 	{
712 		m_geometry_shader_template =
713 			m_geometry_shader_template.replace(template_position, template_name.length(), max_vertices);
714 
715 		template_position = m_geometry_shader_template.find(template_name);
716 	}
717 
718 	/* In primitive type */
719 	template_name	 = "<-LAYOUT-IN->";
720 	template_position = m_geometry_shader_template.find(template_name);
721 
722 	while (template_position != std::string::npos)
723 	{
724 		m_geometry_shader_template =
725 			m_geometry_shader_template.replace(template_position, template_name.length(), layout_in);
726 
727 		template_position = m_geometry_shader_template.find(template_name);
728 	}
729 
730 	/* Out primitive type */
731 	template_name	 = "<-LAYOUT-OUT->";
732 	template_position = m_geometry_shader_template.find(template_name);
733 
734 	while (template_position != std::string::npos)
735 	{
736 		m_geometry_shader_template =
737 			m_geometry_shader_template.replace(template_position, template_name.length(), layout_out);
738 
739 		template_position = m_geometry_shader_template.find(template_name);
740 	}
741 
742 	/* Vertex emit code */
743 	template_name	 = "<-EMIT-VERTICES->";
744 	template_position = m_geometry_shader_template.find(template_name);
745 
746 	while (template_position != std::string::npos)
747 	{
748 		m_geometry_shader_template =
749 			m_geometry_shader_template.replace(template_position, template_name.length(), emit_vertices);
750 
751 		template_position = m_geometry_shader_template.find(template_name);
752 	}
753 
754 	/* Number of iterations, during which we'll be emitting vertices */
755 	template_name	 = "<-N_ITERATIONS->";
756 	template_position = m_geometry_shader_template.find(template_name);
757 
758 	while (template_position != std::string::npos)
759 	{
760 		m_geometry_shader_template =
761 			m_geometry_shader_template.replace(template_position, template_name.length(), n_iterations);
762 
763 		template_position = m_geometry_shader_template.find(template_name);
764 	}
765 
766 	return m_geometry_shader_template;
767 }
768 
769 /** Executes the test.
770  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
771  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
772  *  Note the function throws exception should an error occur!
773  **/
iterate(void)774 tcu::TestNode::IterateResult GeometryShaderPrimitiveCounter::iterate(void)
775 {
776 	if (!m_is_geometry_shader_extension_supported)
777 	{
778 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
779 	}
780 
781 	/* Set up */
782 	glw::GLint* feedbackResult = NULL;
783 
784 	createAndBuildProgramWithFeedback();
785 	prepareBufferObjects();
786 
787 	feedbackResult = new glw::GLint[m_sizeOfFeedbackBuffer];
788 
789 	/* Execute the test */
790 	drawAndGetFeedback(feedbackResult);
791 
792 	/* Set the CTS test result, depending on the outcome */
793 	if (checkResult(feedbackResult))
794 	{
795 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
796 	}
797 	else
798 	{
799 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
800 	}
801 
802 	if (feedbackResult != NULL)
803 	{
804 		delete[] feedbackResult;
805 
806 		feedbackResult = DE_NULL;
807 	}
808 
809 	return STOP;
810 }
811 
812 /** Prepare buffer objects and initialize their storage. It will
813  *   later be used as vertex attribute array data source, as well
814  *   as transform feedback destination.
815  **/
prepareBufferObjects()816 void GeometryShaderPrimitiveCounter::prepareBufferObjects()
817 {
818 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
819 
820 	/* Create a VAO */
821 	gl.genVertexArrays(1, &m_vao);
822 	gl.bindVertexArray(m_vao);
823 
824 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a VAO!");
825 
826 	m_sizeOfDataArray = m_testConfiguration.m_numberOfDrawnPrimitives * m_n_components *
827 						m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive;
828 
829 	gl.genBuffers(1, &m_vbo);
830 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo);
831 	gl.bufferData(GL_ARRAY_BUFFER, m_sizeOfDataArray * sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
832 
833 	GLU_EXPECT_NO_ERROR(gl.getError(),
834 						"Could not initialize a buffer object to hold data for vertex_position attribute!");
835 
836 	/* Set up "vertex_position" vertex attribute array */
837 	glw::GLint vertex_position_attribute_location = -1;
838 
839 	vertex_position_attribute_location = gl.getAttribLocation(m_program_id, "vertex_position");
840 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve vertex_position attribute location!");
841 
842 	gl.vertexAttribPointer(vertex_position_attribute_location, 4, /* size */
843 						   GL_FLOAT, GL_FALSE,					  /* normalized */
844 						   0,									  /* stride */
845 						   0);									  /* pointer */
846 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed for vertex_position attribute!");
847 
848 	gl.enableVertexAttribArray(vertex_position_attribute_location);
849 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed for vertex_position attribute!");
850 
851 	/* Set up buffer object to hold result transform feedback data */
852 	m_sizeOfFeedbackBuffer = static_cast<glw::GLuint>(m_testConfiguration.m_numberOfDrawnPrimitives *
853 													  m_maxGeometryOutputVertices * m_nrVaryings * sizeof(glw::GLint));
854 
855 	gl.genBuffers(1, &m_tbo);
856 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tbo);
857 	gl.bufferData(GL_ARRAY_BUFFER, m_sizeOfFeedbackBuffer, DE_NULL, GL_STATIC_COPY);
858 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a buffer object to hold transform feedback data!");
859 
860 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_tbo);
861 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind a buffer object to transform feedback binding point!");
862 }
863 
864 /** Constructor
865  *
866  * @param context               Test context;
867  * @param name                  Test case's name;
868  * @param description           Test case's description;
869  * @param testConfiguration     Configuration that specifies the "in" and "out" primitive type
870  *                              for the geometry shader, as well as defines other miscellaneous
871  *                              properties of the test the shader.
872  **/
GeometryShaderPrimitiveCounterRestartingPrimitive(Context & context,const ExtParameters & extParams,const char * name,const char * description,const DataPrimitiveIDInCounter & testConfiguration)873 GeometryShaderPrimitiveCounterRestartingPrimitive::GeometryShaderPrimitiveCounterRestartingPrimitive(
874 	Context& context, const ExtParameters& extParams, const char* name, const char* description,
875 	const DataPrimitiveIDInCounter& testConfiguration)
876 	: GeometryShaderPrimitiveCounter(context, extParams, name, description, testConfiguration)
877 	, m_bo_id(0)
878 	, m_numberOfRestarts(2)
879 {
880 }
881 
882 /** Deinitializes GLES objects created during the test.
883  *
884  */
deinit(void)885 void GeometryShaderPrimitiveCounterRestartingPrimitive::deinit(void)
886 {
887 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
888 
889 	if (m_bo_id != 0)
890 	{
891 		gl.deleteBuffers(1, &m_bo_id);
892 
893 		m_bo_id = 0;
894 	}
895 
896 	/* Call base class' deinit() */
897 	GeometryShaderPrimitiveCounter::deinit();
898 }
899 
900 /** Renders the test geometry.
901  *
902  */
drawFunction()903 void GeometryShaderPrimitiveCounterRestartingPrimitive::drawFunction()
904 {
905 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
906 
907 	gl.drawElements(m_testConfiguration.m_drawMode, (m_testConfiguration.m_numberOfDrawnPrimitives *
908 														 m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive +
909 													 m_numberOfRestarts),
910 					GL_UNSIGNED_INT, 0 /* indices */);
911 }
912 
913 /** Executes the test.
914  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
915  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
916  *  Note the function throws exception should an error occur!
917  **/
iterate(void)918 tcu::TestNode::IterateResult GeometryShaderPrimitiveCounterRestartingPrimitive::iterate(void)
919 {
920 	if (!m_is_geometry_shader_extension_supported)
921 	{
922 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
923 	}
924 
925 	/* Set up */
926 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
927 
928 	createAndBuildProgramWithFeedback();
929 	prepareBufferObjects();
930 
931 	glw::GLenum restart_token;
932 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
933 	{
934 		restart_token = GL_PRIMITIVE_RESTART;
935 	}
936 	else
937 	{
938 		restart_token = GL_PRIMITIVE_RESTART_FIXED_INDEX;
939 	}
940 
941 	gl.enable(restart_token);
942 	GLU_EXPECT_NO_ERROR(gl.getError(), "Enabling primitive restart failed");
943 
944 	setUpVertexAttributeArrays();
945 
946 	/* Render the test geometry */
947 	glw::GLint* feedbackResult = NULL;
948 	feedbackResult			   = new glw::GLint[m_sizeOfFeedbackBuffer];
949 	try
950 	{
951 		drawAndGetFeedback(feedbackResult);
952 	}
953 	catch (...)
954 	{
955 		delete[] feedbackResult;
956 		feedbackResult = NULL;
957 		throw;
958 	}
959 
960 	gl.disable(restart_token);
961 
962 	int error = gl.getError();
963 	if (error != GL_NO_ERROR)
964 	{
965 		delete[] feedbackResult;
966 		feedbackResult = NULL;
967 		GLU_EXPECT_NO_ERROR(error, "Disabling primitive restart failed");
968 	}
969 
970 	/* Check the result and update the DEQP test result accordingly */
971 	if (checkResult(feedbackResult))
972 	{
973 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
974 	}
975 	else
976 	{
977 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
978 	}
979 
980 	delete[] feedbackResult;
981 	feedbackResult = NULL;
982 
983 	return STOP;
984 }
985 
986 /** Prepare the element vertex attribute array data. Make sure to
987  *  use primitive index functionality.
988  */
setUpVertexAttributeArrays()989 void GeometryShaderPrimitiveCounterRestartingPrimitive::setUpVertexAttributeArrays()
990 {
991 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
992 
993 	/* Create a buffer object to hold the element data */
994 	glw::GLuint*	   indices = DE_NULL;
995 	const unsigned int nIndices =
996 		m_testConfiguration.m_numberOfDrawnPrimitives * m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive +
997 		m_numberOfRestarts;
998 	unsigned int restartIndex;
999 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1000 	{
1001 		restartIndex = nIndices;
1002 	}
1003 	else
1004 	{
1005 		restartIndex = 0xFFFFFFFF;
1006 	}
1007 
1008 	gl.genBuffers(1, &m_bo_id);
1009 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1010 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate a buffer object");
1011 
1012 	/* Prepare the data we will later use for configuring buffer object storage contents */
1013 	indices = new unsigned int[nIndices];
1014 	memset(indices, 0, nIndices * sizeof(unsigned int));
1015 
1016 	for (unsigned int restartNr = 0; restartNr < m_numberOfRestarts; ++restartNr)
1017 	{
1018 		for (unsigned int i = m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive * restartNr + 1; i < nIndices;
1019 			 i++)
1020 		{
1021 			if (i < m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive * (restartNr + 1) + restartNr)
1022 			{
1023 				indices[i] = i - restartNr;
1024 			}
1025 			else if (i > m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive * (restartNr + 1) + restartNr)
1026 			{
1027 				indices[i] = (i - 1 - restartNr);
1028 			}
1029 		}
1030 		indices[m_testConfiguration.m_numberOfVerticesPerOneInputPrimitive * (restartNr + 1) + restartNr] =
1031 			restartIndex;
1032 	}
1033 
1034 	/*
1035 	 m_testCtx.getLog() << tcu::TestLog::Message << "Indices table [ " << tcu::TestLog::EndMessage;
1036 	 for (unsigned int i = 0; i < nIndices; i++)
1037 	 {
1038 	 m_testCtx.getLog() << tcu::TestLog::Message << indices[i] << ", " << tcu::TestLog::EndMessage;
1039 	 }
1040 	 m_testCtx.getLog() << tcu::TestLog::Message << " ]" << tcu::TestLog::EndMessage;
1041 	 */
1042 
1043 	/* Set up buffer object data storage */
1044 	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(glw::GLuint) * nIndices, indices, GL_STATIC_DRAW);
1045 	/* Free the buffer we no longer need */
1046 	delete[] indices;
1047 	indices = NULL;
1048 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create element array buffer object");
1049 
1050 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1051 	{
1052 		/* Set up primitive restarting */
1053 		gl.primitiveRestartIndex(restartIndex);
1054 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set primitive restart index");
1055 	}
1056 }
1057 
1058 /* Vertex shader code */
1059 const char* GeometryShaderPrimitiveIDFromFragmentShader::m_vertex_shader_code = "${VERSION}\n"
1060 																				"\n"
1061 																				"precision highp float;\n"
1062 																				"\n"
1063 																				"flat out int vs_vertex_id;"
1064 																				"\n"
1065 																				"     in vec4 vertex_position;\n"
1066 																				"\n"
1067 																				"void main()\n"
1068 																				"{\n"
1069 																				"    vs_vertex_id = gl_VertexID;"
1070 																				"}\n";
1071 
1072 /* Geometry Shader code */
1073 const char* GeometryShaderPrimitiveIDFromFragmentShader::m_geometry_shader_code =
1074 	"${VERSION}\n"
1075 	"\n"
1076 	"${GEOMETRY_SHADER_REQUIRE}\n"
1077 	"\n"
1078 	"precision highp float;\n"
1079 	"\n"
1080 	"layout(points)                           in;\n"
1081 	"layout(triangle_strip, max_vertices = 4) out;\n"
1082 	"\n"
1083 	"flat in int vs_vertex_id[1];\n"
1084 	"\n"
1085 	"void main()\n"
1086 	"{\n"
1087 	"    int column = vs_vertex_id[0] % 64;\n"
1088 	"    int row    = vs_vertex_id[0] / 64;\n"
1089 	"\n"
1090 	"    gl_PrimitiveID = vs_vertex_id[0];\n"
1091 	"    gl_Position    = vec4(-1.0 + float(column+1) / 32.0, -1.0 + float(row + 1) / 32.0, 0, 1);\n"
1092 	"    EmitVertex();\n"
1093 	"\n"
1094 	"    gl_PrimitiveID = vs_vertex_id[0];\n"
1095 	"    gl_Position    = vec4(-1.0 + float(column+1) / 32.0, -1.0 + float(row) / 32.0, 0, 1);\n"
1096 	"    EmitVertex();\n"
1097 	"\n"
1098 	"    gl_PrimitiveID = vs_vertex_id[0];\n"
1099 	"    gl_Position    = vec4(-1.0 + float(column)   / 32.0, -1.0 + float(row + 1) / 32.0, 0, 1);\n"
1100 	"    EmitVertex();\n"
1101 	"\n"
1102 	"    gl_PrimitiveID = vs_vertex_id[0];\n"
1103 	"    gl_Position    = vec4(-1.0 + float(column)/ 32.0, -1.0 + float(row)/ 32.0, 0, 1);\n"
1104 	"    EmitVertex();\n"
1105 	"\n"
1106 	"    EndPrimitive();\n"
1107 	"}\n";
1108 
1109 /* Fragment shader code */
1110 const char* GeometryShaderPrimitiveIDFromFragmentShader::m_fragment_shader_code =
1111 	"${VERSION}\n"
1112 	"\n"
1113 	"${GEOMETRY_SHADER_REQUIRE}\n"
1114 	"\n"
1115 	"precision highp float;\n"
1116 	"\n"
1117 	"layout(location = 0) out vec4 result;\n"
1118 	"\n"
1119 	"void main()\n"
1120 	"{\n"
1121 	"    result.x =       float(gl_PrimitiveID % 64)          / 64.0f;\n"
1122 	"    result.y = floor(float(gl_PrimitiveID)      / 64.0f) / 64.0f;\n"
1123 	"    result.z =       float(gl_PrimitiveID)               / 4096.0f;\n"
1124 	"    result.w = ((gl_PrimitiveID % 2) == 0) ? 1.0f : 0.0f;\n"
1125 	"}\n";
1126 
1127 /** Constructor
1128  *
1129  * @param context               Test context;
1130  * @param name                  Test case's name;
1131  * @param description           Test case's description;
1132  **/
GeometryShaderPrimitiveIDFromFragmentShader(Context & context,const ExtParameters & extParams,const char * name,const char * description)1133 GeometryShaderPrimitiveIDFromFragmentShader::GeometryShaderPrimitiveIDFromFragmentShader(Context&			  context,
1134 																						 const ExtParameters& extParams,
1135 																						 const char*		  name,
1136 																						 const char* description)
1137 	: TestCaseBase(context, extParams, name, description)
1138 	, m_n_drawn_vertices(4096)
1139 	, m_squareEdgeSize(16)
1140 	, m_texture_height(1024)
1141 	, m_texture_n_components(4)
1142 	, m_texture_n_levels(1)
1143 	, m_texture_width(1024)
1144 	, m_fbo_id(0)
1145 	, m_fragment_shader_id(0)
1146 	, m_geometry_shader_id(0)
1147 	, m_program_id(0)
1148 	, m_texture_id(0)
1149 	, m_vao_id(0)
1150 	, m_vbo_id(0)
1151 	, m_vertex_shader_id(0)
1152 {
1153 }
1154 
1155 /** Deinitializes GLES objects created during the test.
1156  *
1157  */
deinit(void)1158 void GeometryShaderPrimitiveIDFromFragmentShader::deinit(void)
1159 {
1160 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1161 
1162 	/* Reset OpenGL ES state */
1163 	gl.useProgram(0);
1164 	gl.bindTexture(GL_TEXTURE_2D, 0);
1165 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1166 	gl.bindVertexArray(0);
1167 
1168 	if (m_program_id != 0)
1169 	{
1170 		gl.deleteProgram(m_program_id);
1171 
1172 		m_program_id = 0;
1173 	}
1174 
1175 	if (m_fragment_shader_id != 0)
1176 	{
1177 		gl.deleteShader(m_fragment_shader_id);
1178 
1179 		m_fragment_shader_id = 0;
1180 	}
1181 
1182 	if (m_geometry_shader_id != 0)
1183 	{
1184 		gl.deleteShader(m_geometry_shader_id);
1185 
1186 		m_geometry_shader_id = 0;
1187 	}
1188 
1189 	if (m_vertex_shader_id != 0)
1190 	{
1191 		gl.deleteShader(m_vertex_shader_id);
1192 
1193 		m_vertex_shader_id = 0;
1194 	}
1195 
1196 	if (m_texture_id != 0)
1197 	{
1198 		gl.deleteTextures(1, &m_texture_id);
1199 
1200 		m_texture_id = 0;
1201 	}
1202 
1203 	if (m_fbo_id != 0)
1204 	{
1205 		gl.deleteFramebuffers(1, &m_fbo_id);
1206 
1207 		m_fbo_id = 0;
1208 	}
1209 
1210 	if (m_vao_id != 0)
1211 	{
1212 		gl.deleteVertexArrays(1, &m_vao_id);
1213 
1214 		m_vao_id = 0;
1215 	}
1216 
1217 	if (m_vbo_id != 0)
1218 	{
1219 		gl.deleteBuffers(1, &m_vbo_id);
1220 
1221 		m_vbo_id = 0;
1222 	}
1223 
1224 	/* Release base class */
1225 	TestCaseBase::deinit();
1226 }
1227 
1228 /** Executes the test.
1229  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1230  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1231  *  Note the function throws exception should an error occur!
1232  **/
iterate(void)1233 tcu::TestNode::IterateResult GeometryShaderPrimitiveIDFromFragmentShader::iterate(void)
1234 {
1235 	const float epsilon = 1.0f / 256.0f;
1236 
1237 	if (!m_is_geometry_shader_extension_supported)
1238 	{
1239 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1240 	}
1241 
1242 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1243 
1244 	/* Create a program object */
1245 	m_program_id = gl.createProgram();
1246 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
1247 
1248 	/* Create shader objects */
1249 	m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
1250 	m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1251 	m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
1252 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
1253 
1254 	/* Build the program object */
1255 	if (!buildProgram(m_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, m_geometry_shader_id, 1,
1256 					  &m_geometry_shader_code, m_vertex_shader_id, 1, &m_vertex_shader_code))
1257 	{
1258 		TCU_FAIL("Program could not have been created sucessfully");
1259 	}
1260 
1261 	/* Create and configure a texture object we'll be rendering to */
1262 	gl.genTextures(1, &m_texture_id);
1263 	gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
1264 	gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height);
1265 
1266 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating a texture object!");
1267 
1268 	/* Create and configure the framebuffer object */
1269 	gl.genFramebuffers(1, &m_fbo_id);
1270 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
1271 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
1272 
1273 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring framebuffer object!");
1274 
1275 	/* Create and bind a vertex array object */
1276 	gl.genVertexArrays(1, &m_vao_id);
1277 	gl.bindVertexArray(m_vao_id);
1278 
1279 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring a vertex array object");
1280 
1281 	/* Set up a buffer object we will use to hold vertex_position attribute data */
1282 	const glw::GLuint sizeOfDataArray =
1283 		static_cast<glw::GLuint>(m_n_drawn_vertices * m_texture_n_components * sizeof(glw::GLfloat));
1284 
1285 	gl.genBuffers(1, &m_vbo_id);
1286 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
1287 	gl.bufferData(GL_ARRAY_BUFFER, sizeOfDataArray, DE_NULL, GL_STATIC_DRAW);
1288 
1289 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a buffer object to hold vertex_position attribute data!");
1290 
1291 	/* Set up the viewport */
1292 	gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
1293 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
1294 
1295 	/* Clear the color buffer */
1296 	gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
1297 	gl.clear(GL_COLOR_BUFFER_BIT);
1298 
1299 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer!");
1300 
1301 	/* Render the test geometry */
1302 	gl.useProgram(m_program_id);
1303 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
1304 
1305 	gl.drawArrays(GL_POINTS, 0 /* first */, m_n_drawn_vertices);
1306 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
1307 
1308 	/* Read the rendered data */
1309 	glw::GLubyte* resultBuffer = new glw::GLubyte[m_texture_width * m_texture_height * m_texture_n_components];
1310 
1311 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
1312 	int error = gl.getError();
1313 	if (error != GL_NO_ERROR)
1314 	{
1315 		delete[] resultBuffer;
1316 		resultBuffer = NULL;
1317 		GLU_EXPECT_NO_ERROR(error, "glBindFramebuffer() call failed");
1318 	}
1319 
1320 	gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, resultBuffer);
1321 
1322 	error = gl.getError();
1323 	if (error != GL_NO_ERROR)
1324 	{
1325 		delete[] resultBuffer;
1326 		resultBuffer = NULL;
1327 		GLU_EXPECT_NO_ERROR(error, "Reading pixels failed!");
1328 	}
1329 
1330 	/* Loop over all pixels and compare the rendered data with reference values */
1331 	for (glw::GLuint y = 0; y < m_texture_height; ++y)
1332 	{
1333 		glw::GLubyte* data_row = resultBuffer + y * m_texture_width * m_texture_n_components;
1334 
1335 		for (glw::GLuint x = 0; x < m_texture_width; ++x)
1336 		{
1337 			glw::GLuint   column	  = (x / m_squareEdgeSize);
1338 			glw::GLubyte* data		  = data_row + x * m_texture_n_components;
1339 			glw::GLuint   row		  = (y / m_squareEdgeSize);
1340 			glw::GLuint   primitiveID = column + (row * (m_texture_width / m_squareEdgeSize));
1341 
1342 			/* Calculate expected and rendered pixel color */
1343 			float rendered_rgba[4] = { 0 };
1344 			float expected_rgba[4];
1345 
1346 			for (unsigned int n_channel = 0; n_channel < 4 /* RGBA */; ++n_channel)
1347 			{
1348 				rendered_rgba[n_channel] = float(data[n_channel]) / 255.0f;
1349 			}
1350 
1351 			expected_rgba[0] = (glw::GLfloat)(primitiveID % 64) / 64.0f;
1352 			expected_rgba[1] = deFloatFloor((glw::GLfloat)(primitiveID) / 64.0f) / 64.0f;
1353 			expected_rgba[2] = (glw::GLfloat)(primitiveID) / 4096.0f;
1354 			expected_rgba[3] = (((primitiveID % 2) == 0) ? 1.0f : 0.0f);
1355 
1356 			/* Compare the data */
1357 			if (de::abs(rendered_rgba[0] - expected_rgba[0]) > epsilon ||
1358 				de::abs(rendered_rgba[1] - expected_rgba[1]) > epsilon ||
1359 				de::abs(rendered_rgba[2] - expected_rgba[2]) > epsilon ||
1360 				de::abs(rendered_rgba[3] - expected_rgba[3]) > epsilon)
1361 			{
1362 				m_testCtx.getLog() << tcu::TestLog::Message << "Primitive ID: " << primitiveID << "Rendered data"
1363 								   << "equal (" << rendered_rgba[0] << ", " << rendered_rgba[1] << ", "
1364 								   << rendered_rgba[2] << ", " << rendered_rgba[3] << ") "
1365 								   << "exceeds allowed epsilon when compared to expected data equal ("
1366 								   << expected_rgba[0] << ", " << expected_rgba[1] << ", " << expected_rgba[2] << ", "
1367 								   << expected_rgba[3] << ")." << tcu::TestLog::EndMessage;
1368 
1369 				delete[] resultBuffer;
1370 				resultBuffer = NULL;
1371 
1372 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1373 				return STOP;
1374 			} /* if (rendered data is invalid) */
1375 		}	 /* for (all columns) */
1376 	}		  /* for (all rows) */
1377 
1378 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1379 
1380 	delete[] resultBuffer;
1381 	resultBuffer = NULL;
1382 
1383 	return STOP;
1384 }
1385 
1386 } // namespace glcts
1387