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