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