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 "esextcGeometryShaderRendering.hpp"
25
26 #include "gluContextInfo.hpp"
27 #include "gluDefs.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuTestLog.hpp"
31 #include <cmath>
32 #include <cstdlib>
33 #include <cstring>
34
35 namespace glcts
36 {
37
38 /** Constructor of the geometry shader test base class.
39 *
40 * @param context Rendering context
41 * @param name Name of the test
42 * @param description Description of the test
43 **/
GeometryShaderRendering(Context & context,const ExtParameters & extParams,const char * name,const char * description)44 GeometryShaderRendering::GeometryShaderRendering(Context& context, const ExtParameters& extParams, const char* name,
45 const char* description)
46 : TestCaseGroupBase(context, extParams, name, description)
47 {
48 /* Left blank intentionally */
49 }
50
51 /** Retrieves test name for specific <input layout qualifier,
52 * output layout qualifier, draw call mode> combination.
53 *
54 * @param input Input layout qualifier.
55 * @param output_type Output layout qualifier.
56 * @param drawcall_mode Draw call mode.
57 *
58 * NOTE: This function throws TestError exception if the requested combination
59 * is considered invalid.
60 *
61 * @return Requested string.
62 **/
getTestName(_shader_input input,_shader_output_type output_type,glw::GLenum drawcall_mode)63 const char* GeometryShaderRendering::getTestName(_shader_input input, _shader_output_type output_type,
64 glw::GLenum drawcall_mode)
65 {
66 const char* result = NULL;
67
68 switch (input)
69 {
70 case SHADER_INPUT_POINTS:
71 {
72 switch (output_type)
73 {
74 case SHADER_OUTPUT_TYPE_LINE_STRIP:
75 result = "points_input_line_strip_output";
76 break;
77 case SHADER_OUTPUT_TYPE_POINTS:
78 result = "points_input_points_output";
79 break;
80 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
81 result = "points_input_triangles_output";
82 break;
83
84 default:
85 {
86 TCU_FAIL("Unrecognized shader output type requested");
87 }
88 } /* switch (output_type) */
89
90 break;
91 }
92
93 case SHADER_INPUT_LINES:
94 {
95 switch (output_type)
96 {
97 case SHADER_OUTPUT_TYPE_LINE_STRIP:
98 {
99 switch (drawcall_mode)
100 {
101 case GL_LINES:
102 result = "lines_input_line_strip_output_lines_drawcall";
103 break;
104 case GL_LINE_STRIP:
105 result = "lines_input_line_strip_output_line_strip_drawcall";
106 break;
107 case GL_LINE_LOOP:
108 result = "lines_input_line_strip_output_line_loop_drawcall";
109 break;
110
111 default:
112 {
113 TCU_FAIL("UNrecognized draw call mode");
114 }
115 } /* switch (drawcall_mode) */
116
117 break;
118 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */
119
120 case SHADER_OUTPUT_TYPE_POINTS:
121 {
122 switch (drawcall_mode)
123 {
124 case GL_LINES:
125 result = "lines_input_points_output_lines_drawcall";
126 break;
127 case GL_LINE_STRIP:
128 result = "lines_input_points_output_line_strip_drawcall";
129 break;
130 case GL_LINE_LOOP:
131 result = "lines_input_points_output_line_loop_drawcall";
132 break;
133
134 default:
135 {
136 TCU_FAIL("UNrecognized draw call mode");
137 }
138 } /* switch (drawcall_mode) */
139
140 break;
141 } /* case SHADER_OUTPUT_TYPE_POINTS: */
142
143 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
144 {
145 switch (drawcall_mode)
146 {
147 case GL_LINES:
148 result = "lines_input_triangle_strip_output_lines_drawcall";
149 break;
150 case GL_LINE_STRIP:
151 result = "lines_input_triangle_strip_output_line_strip_drawcall";
152 break;
153 case GL_LINE_LOOP:
154 result = "lines_input_triangle_strip_output_line_loop_drawcall";
155 break;
156
157 default:
158 {
159 TCU_FAIL("UNrecognized draw call mode");
160 }
161 } /* switch (drawcall_mode) */
162
163 break;
164 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */
165
166 default:
167 {
168 TCU_FAIL("Unrecognized shader output type requested");
169 }
170 } /* switch (output_type) */
171
172 break;
173 } /* case SHADER_INPUT_LINES:*/
174
175 case SHADER_INPUT_LINES_WITH_ADJACENCY:
176 {
177 switch (output_type)
178 {
179 case SHADER_OUTPUT_TYPE_LINE_STRIP:
180 {
181 if ((drawcall_mode == GL_LINES_ADJACENCY_EXT) || (drawcall_mode == GL_LINES_ADJACENCY))
182 {
183 result = "lines_with_adjacency_input_line_strip_output_lines_adjacency_drawcall";
184 }
185 else if ((drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) || (drawcall_mode == GL_LINE_STRIP_ADJACENCY))
186 {
187 result = "lines_with_adjacency_input_line_strip_output_line_strip_drawcall";
188 }
189 else
190 {
191 TCU_FAIL("Unrecognized draw call mode");
192 }
193
194 break;
195 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */
196
197 case SHADER_OUTPUT_TYPE_POINTS:
198 {
199 if ((drawcall_mode == GL_LINES_ADJACENCY_EXT) || (drawcall_mode == GL_LINES_ADJACENCY))
200 {
201 result = "lines_with_adjacency_input_points_output_lines_adjacency_drawcall";
202 }
203 else if ((drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) || (drawcall_mode == GL_LINE_STRIP_ADJACENCY))
204 {
205 result = "lines_with_adjacency_input_points_output_line_strip_drawcall";
206 }
207 else
208 {
209 TCU_FAIL("Unrecognized draw call mode");
210 }
211
212 break;
213 } /* case SHADER_OUTPUT_TYPE_POINTS: */
214
215 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
216 {
217 if ((drawcall_mode == GL_LINES_ADJACENCY_EXT) || (drawcall_mode == GL_LINES_ADJACENCY))
218 {
219 result = "lines_with_adjacency_input_triangle_strip_output_lines_adjacency_drawcall";
220 }
221 else if ((drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT) || (drawcall_mode == GL_LINE_STRIP_ADJACENCY))
222 {
223 result = "lines_with_adjacency_input_triangle_strip_output_line_strip_drawcall";
224 }
225 else
226 {
227 TCU_FAIL("Unrecognized draw call mode");
228 }
229
230 break;
231 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */
232
233 default:
234 {
235 TCU_FAIL("Unrecognized shader output type requested");
236 }
237 } /* switch (output_type) */
238
239 break;
240 } /* case SHADER_INPUT_LINES_WITH_ADJACENCY: */
241
242 case SHADER_INPUT_TRIANGLES:
243 {
244 switch (output_type)
245 {
246 case SHADER_OUTPUT_TYPE_LINE_STRIP:
247 {
248 switch (drawcall_mode)
249 {
250 case GL_TRIANGLES:
251 result = "triangles_input_line_strip_output_triangles_drawcall";
252 break;
253 case GL_TRIANGLE_FAN:
254 result = "triangles_input_line_strip_output_triangle_fan_drawcall";
255 break;
256 case GL_TRIANGLE_STRIP:
257 result = "triangles_input_line_strip_output_triangle_strip_drawcall";
258 break;
259
260 default:
261 {
262 TCU_FAIL("Unrecognized draw call mode");
263 }
264 } /* switch (drawcall_mode) */
265
266 break;
267 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */
268
269 case SHADER_OUTPUT_TYPE_POINTS:
270 {
271 switch (drawcall_mode)
272 {
273 case GL_TRIANGLES:
274 result = "triangles_input_points_output_triangles_drawcall";
275 break;
276 case GL_TRIANGLE_FAN:
277 result = "triangles_input_points_output_triangle_fan_drawcall";
278 break;
279 case GL_TRIANGLE_STRIP:
280 result = "triangles_input_points_output_triangle_strip_drawcall";
281 break;
282
283 default:
284 {
285 TCU_FAIL("Unrecognized draw call mode");
286 }
287 } /* switch (drawcall_mode) */
288
289 break;
290 } /* case SHADER_OUTPUT_TYPE_POINTS: */
291
292 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
293 {
294 switch (drawcall_mode)
295 {
296 case GL_TRIANGLES:
297 result = "triangles_input_triangle_strip_output_triangles_drawcall";
298 break;
299 case GL_TRIANGLE_FAN:
300 result = "triangles_input_triangle_strip_output_triangle_fan_drawcall";
301 break;
302 case GL_TRIANGLE_STRIP:
303 result = "triangles_input_triangle_strip_output_triangle_strip_drawcall";
304 break;
305
306 default:
307 {
308 TCU_FAIL("Unrecognized draw call mode");
309 }
310 } /* switch (drawcall_mode) */
311
312 break;
313 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */
314
315 default:
316 {
317 TCU_FAIL("Unrecognized shader output type requested");
318 }
319 } /* switch (output_type) */
320
321 break;
322 } /* case SHADER_INPUT_TRIANGLES: */
323
324 case SHADER_INPUT_TRIANGLES_WITH_ADJACENCY:
325 {
326 switch (output_type)
327 {
328 case SHADER_OUTPUT_TYPE_LINE_STRIP:
329 {
330 if ((drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT) || (drawcall_mode == GL_TRIANGLES_ADJACENCY))
331 {
332 result = "triangles_with_adjacency_input_line_strip_output_triangles_adjacency_drawcall";
333 }
334 else if ((drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) ||
335 (drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY))
336 {
337 result = "triangles_with_adjacency_input_line_strip_output_triangle_strip_adjacency_drawcall";
338 }
339 else
340 {
341 TCU_FAIL("Unrecognized draw call mode");
342 }
343
344 break;
345 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */
346
347 case SHADER_OUTPUT_TYPE_POINTS:
348 {
349 if ((drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT) || (drawcall_mode == GL_TRIANGLES_ADJACENCY))
350 {
351 result = "triangles_with_adjacency_input_points_output_triangles_adjacency_drawcall";
352 }
353 else if ((drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) ||
354 (drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY))
355 {
356 result = "triangles_with_adjacency_input_points_output_triangle_strip_adjacency_drawcall";
357 break;
358 }
359 else
360 {
361 TCU_FAIL("Unrecognized draw call mode");
362 }
363
364 break;
365 } /* case SHADER_OUTPUT_TYPE_POINTS:*/
366
367 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
368 {
369 if ((drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT) || (drawcall_mode == GL_TRIANGLES_ADJACENCY))
370 {
371 result = "triangles_with_adjacency_input_triangle_strip_output_triangles_adjacency_drawcall";
372 }
373 else if ((drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) ||
374 (drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY))
375 {
376 result = "triangles_with_adjacency_input_triangle_strip_output_triangle_strip_adjacency_drawcall";
377 }
378 else
379 {
380 TCU_FAIL("Unrecognized draw call mode");
381 }
382
383 break;
384 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */
385
386 default:
387 {
388 TCU_FAIL("Unrecognized shader output type requested");
389 }
390 } /* switch (output_type) */
391
392 break;
393 } /* case SHADER_INPUT_TRIANGLES_WITH_ADJACENCY: */
394
395 default:
396 {
397 /* Unrecognized geometry shader input layout qualifier */
398 TCU_FAIL("Unrecognized layout qualifier");
399 }
400 } /* switch (input) */
401
402 return result;
403 }
404
405 /* Initializes child instances of the group that will execute actual tests. */
init(void)406 void GeometryShaderRendering::init(void)
407 {
408 /* Initialize base class */
409 TestCaseGroupBase::init();
410
411 /* General variables */
412 glw::GLenum drawcall_mode = GL_NONE;
413 _shader_input input = SHADER_INPUT_UNKNOWN;
414
415 const glw::GLenum iterations[] = { /* geometry shader input layout qualifier */ /* draw call mode. */
416 SHADER_INPUT_POINTS, GL_POINTS, SHADER_INPUT_LINES, GL_LINES, SHADER_INPUT_LINES,
417 GL_LINE_STRIP, SHADER_INPUT_LINES, GL_LINE_LOOP,
418 SHADER_INPUT_LINES_WITH_ADJACENCY, GL_LINES_ADJACENCY_EXT,
419 SHADER_INPUT_LINES_WITH_ADJACENCY, GL_LINE_STRIP_ADJACENCY_EXT,
420 SHADER_INPUT_TRIANGLES, GL_TRIANGLES, SHADER_INPUT_TRIANGLES, GL_TRIANGLE_FAN,
421 SHADER_INPUT_TRIANGLES, GL_TRIANGLE_STRIP, SHADER_INPUT_TRIANGLES_WITH_ADJACENCY,
422 GL_TRIANGLES_ADJACENCY_EXT, SHADER_INPUT_TRIANGLES_WITH_ADJACENCY,
423 GL_TRIANGLE_STRIP_ADJACENCY_EXT };
424 const unsigned int n_iterations = sizeof(iterations) / sizeof(iterations[0]) / 2;
425 unsigned int n_output = 0;
426
427 for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration)
428 {
429 /* Retrieve iteration-specific input layout qualifier and draw call mode data */
430 input = (_shader_input)iterations[n_iteration * 2 + 0];
431 drawcall_mode = iterations[n_iteration * 2 + 1];
432
433 /* Instantiate a worker. Each worker needs to be initialized & executed separately for each
434 * of the three supported input layout qualifiers.*/
435 for (n_output = 0; n_output < SHADER_OUTPUT_TYPE_COUNT; ++n_output)
436 {
437 _shader_output_type output_type = (_shader_output_type)n_output;
438 const char* name = getTestName(input, output_type, drawcall_mode);
439
440 switch (input)
441 {
442 case SHADER_INPUT_POINTS:
443 {
444 addChild(
445 new GeometryShaderRenderingPointsCase(m_context, m_extParams, name, drawcall_mode, output_type));
446
447 break;
448 }
449
450 case SHADER_INPUT_LINES:
451 {
452 addChild(new GeometryShaderRenderingLinesCase(m_context, m_extParams, name, false, drawcall_mode,
453 output_type));
454
455 break;
456 } /* case SHADER_INPUT_LINES:*/
457
458 case SHADER_INPUT_LINES_WITH_ADJACENCY:
459 {
460 addChild(new GeometryShaderRenderingLinesCase(m_context, m_extParams, name, true, drawcall_mode,
461 output_type));
462
463 break;
464 } /* case SHADER_INPUT_LINES_WITH_ADJACENCY: */
465
466 case SHADER_INPUT_TRIANGLES:
467 {
468 addChild(new GeometryShaderRenderingTrianglesCase(m_context, m_extParams, name, false, drawcall_mode,
469 output_type));
470
471 break;
472 }
473
474 case SHADER_INPUT_TRIANGLES_WITH_ADJACENCY:
475 {
476 addChild(new GeometryShaderRenderingTrianglesCase(m_context, m_extParams, name, true, drawcall_mode,
477 output_type));
478
479 break;
480 }
481
482 default:
483 {
484 /* Unrecognized geometry shader input layout qualifier */
485 TCU_FAIL("Unrecognized layout qualifier");
486 }
487 } /* switch (input) */
488 } /* for (all output layout qualifiers) */
489 } /* for (all iterations) */
490 }
491
492 /** Base worker implementation */
493 /** Constructor.
494 *
495 * @param context Rendering context.
496 * @param testContext Test context.
497 * @param name Name of the test.
498 * @param description Description of what the test does.
499 **/
GeometryShaderRenderingCase(Context & context,const ExtParameters & extParams,const char * name,const char * description)500 GeometryShaderRenderingCase::GeometryShaderRenderingCase(Context& context, const ExtParameters& extParams,
501 const char* name, const char* description)
502 : TestCaseBase(context, extParams, name, description)
503 , m_context(context)
504 , m_instanced_raw_arrays_bo_id(0)
505 , m_instanced_unordered_arrays_bo_id(0)
506 , m_instanced_unordered_elements_bo_id(0)
507 , m_noninstanced_raw_arrays_bo_id(0)
508 , m_noninstanced_unordered_arrays_bo_id(0)
509 , m_noninstanced_unordered_elements_bo_id(0)
510 , m_fs_id(0)
511 , m_gs_id(0)
512 , m_po_id(0)
513 , m_renderingTargetSize_uniform_location(0)
514 , m_singleRenderingTargetSize_uniform_location(0)
515 , m_vao_id(0)
516 , m_vs_id(0)
517 , m_fbo_id(0)
518 , m_read_fbo_id(0)
519 , m_to_id(0)
520 , m_instanced_fbo_id(0)
521 , m_instanced_read_fbo_id(0)
522 , m_instanced_to_id(0)
523 {
524 /* Left blank intentionally */
525 }
526
527 /** Releases all GLES objects initialized by the base class for geometry shader rendering case implementations. */
deinit()528 void GeometryShaderRenderingCase::deinit()
529 {
530 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
531
532 if (m_fbo_id != 0)
533 {
534 gl.deleteFramebuffers(1, &m_fbo_id);
535
536 m_fbo_id = 0;
537 }
538
539 if (m_fs_id != 0)
540 {
541 gl.deleteShader(m_fs_id);
542
543 m_fs_id = 0;
544 }
545
546 if (m_gs_id != 0)
547 {
548 gl.deleteShader(m_gs_id);
549
550 m_gs_id = 0;
551 }
552
553 if (m_instanced_fbo_id != 0)
554 {
555 gl.deleteFramebuffers(1, &m_instanced_fbo_id);
556
557 m_instanced_fbo_id = 0;
558 }
559
560 if (m_instanced_read_fbo_id != 0)
561 {
562 gl.deleteFramebuffers(1, &m_instanced_read_fbo_id);
563
564 m_instanced_read_fbo_id = 0;
565 }
566
567 if (m_instanced_to_id != 0)
568 {
569 gl.deleteTextures(1, &m_instanced_to_id);
570
571 m_instanced_to_id = 0;
572 }
573
574 if (m_po_id != 0)
575 {
576 gl.deleteProgram(m_po_id);
577
578 m_po_id = 0;
579 }
580
581 if (m_instanced_raw_arrays_bo_id != 0)
582 {
583 gl.deleteBuffers(1, &m_instanced_raw_arrays_bo_id);
584
585 m_instanced_raw_arrays_bo_id = 0;
586 }
587
588 if (m_instanced_unordered_arrays_bo_id != 0)
589 {
590 gl.deleteBuffers(1, &m_instanced_unordered_arrays_bo_id);
591
592 m_instanced_unordered_arrays_bo_id = 0;
593 }
594
595 if (m_instanced_unordered_elements_bo_id != 0)
596 {
597 gl.deleteBuffers(1, &m_instanced_unordered_elements_bo_id);
598
599 m_instanced_unordered_elements_bo_id = 0;
600 }
601
602 if (m_noninstanced_raw_arrays_bo_id != 0)
603 {
604 gl.deleteBuffers(1, &m_noninstanced_raw_arrays_bo_id);
605
606 m_noninstanced_raw_arrays_bo_id = 0;
607 }
608
609 if (m_noninstanced_unordered_arrays_bo_id != 0)
610 {
611 gl.deleteBuffers(1, &m_noninstanced_unordered_arrays_bo_id);
612
613 m_noninstanced_unordered_arrays_bo_id = 0;
614 }
615
616 if (m_noninstanced_unordered_elements_bo_id != 0)
617 {
618 gl.deleteBuffers(1, &m_noninstanced_unordered_elements_bo_id);
619
620 m_noninstanced_unordered_elements_bo_id = 0;
621 }
622
623 if (m_read_fbo_id != 0)
624 {
625 gl.deleteFramebuffers(1, &m_read_fbo_id);
626
627 m_read_fbo_id = 0;
628 }
629
630 if (m_to_id != 0)
631 {
632 gl.deleteTextures(1, &m_to_id);
633
634 m_to_id = 0;
635 }
636
637 if (m_vao_id != 0)
638 {
639 gl.deleteVertexArrays(1, &m_vao_id);
640
641 m_vao_id = 0;
642 }
643
644 if (m_vs_id != 0)
645 {
646 gl.deleteShader(m_vs_id);
647
648 m_vs_id = 0;
649 }
650 }
651
652 /** Executes actual geometry shader-based rendering test, using an user-specified draw call.
653 *
654 * @param type Type of the draw call to use for the test.
655 **/
executeTest(GeometryShaderRenderingCase::_draw_call_type type)656 void GeometryShaderRenderingCase::executeTest(GeometryShaderRenderingCase::_draw_call_type type)
657 {
658 glw::GLuint draw_fbo_id = 0;
659 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
660 const glw::GLenum index_type = getUnorderedElementsDataType();
661 const glw::GLubyte max_elements_index = getUnorderedElementsMaxIndex();
662 const glw::GLubyte min_elements_index = getUnorderedElementsMinIndex();
663 const glw::GLenum mode = getDrawCallMode();
664 unsigned int n_elements = getAmountOfElementsPerInstance();
665 unsigned int n_instance = 0;
666 unsigned int n_instances = getAmountOfDrawInstances();
667 const unsigned int n_vertices = getAmountOfVerticesPerInstance();
668 const glw::GLint position_attribute_location = gl.getAttribLocation(m_po_id, "position");
669 glw::GLuint read_fbo_id = 0;
670 unsigned int rt_height = 0;
671 unsigned int rt_width = 0;
672 unsigned int single_rt_height = 0;
673 unsigned int single_rt_width = 0;
674
675 /* Reduce n_instances to 1 for non-instanced draw call modes */
676 if (type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS || type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
677 type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS)
678 {
679 draw_fbo_id = m_fbo_id;
680 n_instances = 1;
681 read_fbo_id = m_read_fbo_id;
682 }
683 else
684 {
685 draw_fbo_id = m_instanced_fbo_id;
686 read_fbo_id = m_instanced_read_fbo_id;
687 }
688
689 /* Retrieve render-target size */
690 getRenderTargetSize(n_instances, &rt_width, &rt_height);
691 getRenderTargetSize(1, &single_rt_width, &single_rt_height);
692
693 /* Configure GL_ARRAY_BUFFER binding */
694 switch (type)
695 {
696 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS:
697 {
698 gl.bindBuffer(GL_ARRAY_BUFFER, m_noninstanced_raw_arrays_bo_id);
699
700 break;
701 }
702
703 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED:
704 {
705 gl.bindBuffer(GL_ARRAY_BUFFER, m_instanced_raw_arrays_bo_id);
706
707 break;
708 }
709
710 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED:
711 {
712 gl.bindBuffer(GL_ARRAY_BUFFER, m_instanced_unordered_arrays_bo_id);
713
714 break;
715 }
716
717 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS:
718 case DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS:
719 {
720 gl.bindBuffer(GL_ARRAY_BUFFER, m_noninstanced_unordered_arrays_bo_id);
721
722 break;
723 }
724
725 default:
726 {
727 /* Unrecognized draw call mode */
728 TCU_FAIL("Unrecognized draw call mode");
729 }
730 } /* switch (type) */
731
732 gl.vertexAttribPointer(position_attribute_location, 4, GL_FLOAT, GL_FALSE, 0 /* stride */, NULL);
733 gl.enableVertexAttribArray(position_attribute_location);
734
735 /* Configure GL_ELEMENT_ARRAY_BUFFER binding */
736 switch (type)
737 {
738 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS:
739 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED:
740 {
741 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
742
743 break;
744 }
745
746 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED:
747 {
748 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_instanced_unordered_elements_bo_id);
749
750 break;
751 }
752
753 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS:
754 case DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS:
755 {
756 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_noninstanced_unordered_elements_bo_id);
757
758 break;
759 }
760
761 default:
762 {
763 /* Unrecognized draw call mode */
764 TCU_FAIL("Unrecognized draw call mode");
765 }
766 } /* switch (type) */
767
768 /* Configure draw framebuffer */
769 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_fbo_id);
770 gl.viewport(0 /* x */, 0 /* y */, rt_width, rt_height);
771
772 /* Clear the color buffer. */
773 gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */);
774 gl.clear(GL_COLOR_BUFFER_BIT);
775
776 GLU_EXPECT_NO_ERROR(gl.getError(), "Test set-up failed.");
777
778 /* Render the test geometry */
779 gl.useProgram(m_po_id);
780 gl.uniform2i(m_renderingTargetSize_uniform_location, rt_width, rt_height);
781 gl.uniform2i(m_singleRenderingTargetSize_uniform_location, single_rt_width, single_rt_height);
782
783 setUniformsBeforeDrawCall(type);
784
785 switch (type)
786 {
787 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS:
788 {
789 gl.drawArrays(mode, 0 /* first */, n_vertices);
790
791 break;
792 }
793
794 case DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED:
795 {
796 gl.drawArraysInstanced(mode, 0 /* first */, n_vertices, n_instances);
797
798 break;
799 }
800
801 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS:
802 {
803 gl.drawElements(mode, n_elements, index_type, NULL);
804
805 break;
806 }
807
808 case DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED:
809 {
810 gl.drawElementsInstanced(mode, n_elements, index_type, NULL, n_instances);
811
812 break;
813 }
814
815 case DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS:
816 {
817 gl.drawRangeElements(mode, min_elements_index, max_elements_index, n_elements, index_type, NULL);
818
819 break;
820 }
821
822 default:
823 {
824 /* Unrecognized draw call mode */
825 TCU_FAIL("Unrecognized draw call mode");
826 }
827 } /* switch (type) */
828
829 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed.");
830
831 /* Retrieve rendered data */
832 unsigned char* rendered_data = new unsigned char[rt_height * rt_width * 4 /* components */];
833
834 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo_id);
835 gl.readPixels(0 /* x */, 0 /* y */, rt_width, rt_height, GL_RGBA, GL_UNSIGNED_BYTE, rendered_data);
836
837 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
838
839 /* Verify if the test succeeded */
840 for (n_instance = 0; n_instance < n_instances; ++n_instance)
841 {
842 verify(type, n_instance, rendered_data);
843 } /* for (all instances) */
844
845 /* Release the data buffer */
846 delete[] rendered_data;
847 }
848
849 /** Initializes ES objects required to execute a set of tests for particular input layout qualifier. */
initTest()850 void GeometryShaderRenderingCase::initTest()
851 {
852 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
853
854 /* Retrieve derivative class' properties */
855 std::string fs_code = getFragmentShaderCode();
856 std::string gs_code = getGeometryShaderCode();
857 unsigned int n = 0;
858 unsigned int n_instances = getAmountOfDrawInstances();
859 std::string vs_code = getVertexShaderCode();
860
861 /* Set pixel storage properties before we continue */
862 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
863 gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
864
865 /* Create buffer objects the derivative implementation will fill with data */
866 gl.genBuffers(1, &m_instanced_raw_arrays_bo_id);
867 gl.genBuffers(1, &m_instanced_unordered_arrays_bo_id);
868 gl.genBuffers(1, &m_instanced_unordered_elements_bo_id);
869 gl.genBuffers(1, &m_noninstanced_raw_arrays_bo_id);
870 gl.genBuffers(1, &m_noninstanced_unordered_arrays_bo_id);
871 gl.genBuffers(1, &m_noninstanced_unordered_elements_bo_id);
872
873 /* Set up a separate set of objects, that will be used for testing instanced and non-instanced draw calls */
874 for (n = 0; n < 2 /* non-/instanced draw calls */; ++n)
875 {
876 bool is_instanced = (n == 1);
877
878 glw::GLuint* draw_fbo_id_ptr = !is_instanced ? &m_fbo_id : &m_instanced_fbo_id;
879 glw::GLuint* read_fbo_id_ptr = (!is_instanced) ? &m_read_fbo_id : &m_instanced_read_fbo_id;
880 unsigned int to_height = 0;
881 unsigned int to_width = 0;
882 glw::GLuint* to_id_ptr = (!is_instanced) ? &m_to_id : &m_instanced_to_id;
883
884 /* n == 0: non-instanced draw calls, instanced otherwise */
885 getRenderTargetSize((n == 0) ? 1 : n_instances, &to_width, &to_height);
886
887 /* Create a texture object we will be rendering to */
888 gl.genTextures(1, to_id_ptr);
889 gl.bindTexture(GL_TEXTURE_2D, *to_id_ptr);
890 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, to_width, to_height);
891
892 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure a 2D texture object");
893
894 /* Create and configure a framebuffer object that will be used for rendering */
895 gl.genFramebuffers(1, draw_fbo_id_ptr);
896 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *draw_fbo_id_ptr);
897
898 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *to_id_ptr, 0 /* level */);
899
900 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure draw framebuffer object");
901
902 if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
903 {
904 TCU_FAIL("Draw framebuffer is reported to be incomplete");
905 } /* if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) */
906
907 /* Create and bind a FBO we will use for reading rendered data */
908 gl.genFramebuffers(1, read_fbo_id_ptr);
909 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *read_fbo_id_ptr);
910
911 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *to_id_ptr, 0 /* level */);
912
913 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure read framebuffer object");
914
915 if (gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
916 {
917 TCU_FAIL("Read framebuffer is reported to be incomplete");
918 } /* if (gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) */
919
920 /* Fill the iteration-specific buffer objects with data */
921 glw::GLuint raw_arrays_bo_id = (is_instanced) ? m_instanced_raw_arrays_bo_id : m_noninstanced_raw_arrays_bo_id;
922 unsigned int raw_arrays_bo_size = getRawArraysDataBufferSize(is_instanced);
923 const void* raw_arrays_data = getRawArraysDataBuffer(is_instanced);
924 glw::GLuint unordered_arrays_bo_id =
925 (is_instanced) ? m_instanced_unordered_arrays_bo_id : m_noninstanced_unordered_arrays_bo_id;
926 unsigned int unordered_arrays_bo_size = getUnorderedArraysDataBufferSize(is_instanced);
927 const void* unordered_arrays_data = getUnorderedArraysDataBuffer(is_instanced);
928 glw::GLuint unordered_elements_bo_id =
929 (is_instanced) ? m_instanced_unordered_elements_bo_id : m_noninstanced_unordered_elements_bo_id;
930 unsigned int unordered_elements_bo_size = getUnorderedElementsDataBufferSize(is_instanced);
931 const void* unordered_elements_data = getUnorderedElementsDataBuffer(is_instanced);
932
933 gl.bindBuffer(GL_ARRAY_BUFFER, raw_arrays_bo_id);
934 gl.bufferData(GL_ARRAY_BUFFER, raw_arrays_bo_size, raw_arrays_data, GL_STATIC_COPY);
935
936 gl.bindBuffer(GL_ARRAY_BUFFER, unordered_arrays_bo_id);
937 gl.bufferData(GL_ARRAY_BUFFER, unordered_arrays_bo_size, unordered_arrays_data, GL_STATIC_COPY);
938
939 gl.bindBuffer(GL_ARRAY_BUFFER, unordered_elements_bo_id);
940 gl.bufferData(GL_ARRAY_BUFFER, unordered_elements_bo_size, unordered_elements_data, GL_STATIC_COPY);
941 }
942
943 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure test buffer objects");
944
945 /* Create and bind a VAO */
946 gl.genVertexArrays(1, &m_vao_id);
947 gl.bindVertexArray(m_vao_id);
948
949 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate & bind a vertex array object");
950
951 /* Create and configure program & shader objects that will be used for the test case */
952 const char* fs_code_ptr = fs_code.c_str();
953 const char* gs_code_ptr = gs_code.c_str();
954 const char* vs_code_ptr = vs_code.c_str();
955
956 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
957 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
958 m_po_id = gl.createProgram();
959 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
960
961 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader/program objects");
962
963 if (!buildProgram(m_po_id, m_fs_id, 1, &fs_code_ptr, m_gs_id, 1, &gs_code_ptr, m_vs_id, 1, &vs_code_ptr))
964 {
965 TCU_FAIL("Could not build shader program");
966 }
967
968 /* Retrieve uniform locations */
969 m_renderingTargetSize_uniform_location = gl.getUniformLocation(m_po_id, "renderingTargetSize");
970 m_singleRenderingTargetSize_uniform_location = gl.getUniformLocation(m_po_id, "singleRenderingTargetSize");
971 }
972
973 /* Checks all draw call types for a specific Geometry Shader input layout qualifier.
974 *
975 * @return Always STOP.
976 */
iterate()977 tcu::TestNode::IterateResult GeometryShaderRenderingCase::iterate()
978 {
979 if (!m_is_geometry_shader_extension_supported)
980 {
981 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
982 }
983
984 initTest();
985
986 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_ARRAYS);
987 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED);
988 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_ELEMENTS);
989 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED);
990 executeTest(GeometryShaderRenderingCase::DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS);
991
992 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
993 return STOP;
994 }
995
996 /** Constructor.
997 *
998 * @param drawcall_mode Draw call mode that should be tested with this test case instance.
999 * @param output_type Geometry shader output type to be used.
1000 * @param context Rendering context;
1001 * @param testContext Test context;
1002 * @param name Test name.
1003 **/
GeometryShaderRenderingPointsCase(Context & context,const ExtParameters & extParams,const char * name,glw::GLenum drawcall_mode,_shader_output_type output_type)1004 GeometryShaderRenderingPointsCase::GeometryShaderRenderingPointsCase(Context& context, const ExtParameters& extParams,
1005 const char* name, glw::GLenum drawcall_mode,
1006 _shader_output_type output_type)
1007 : GeometryShaderRenderingCase(
1008 context, extParams, name,
1009 "Verifies all draw calls work correctly for specific input+output+draw call mode combination")
1010 , m_output_type(output_type)
1011 {
1012 /* Sanity checks */
1013 if (drawcall_mode != GL_POINTS)
1014 {
1015 TCU_FAIL("Only GL_POINTS draw call mode is supported for 'points' geometry shader input layout qualifier test "
1016 "implementation");
1017 }
1018
1019 if (output_type != SHADER_OUTPUT_TYPE_POINTS && output_type != SHADER_OUTPUT_TYPE_LINE_STRIP &&
1020 output_type != SHADER_OUTPUT_TYPE_TRIANGLE_STRIP)
1021 {
1022 TCU_FAIL("Unsupported output layout qualifier type requested for 'points' geometry shader input layout "
1023 "qualifier test implementation");
1024 }
1025
1026 /* Retrieve rendertarget resolution for a single-instance case.
1027 *
1028 * Y coordinates will be dynamically updated in a vertex shader for
1029 * multiple-instance tests. That's fine, since in multi-instanced tests
1030 * we only expand the rendertarget's height; its width is unaffected.
1031 */
1032 unsigned int rendertarget_height = 0;
1033 unsigned int rendertarget_width = 0;
1034
1035 getRenderTargetSize(1, &rendertarget_width, &rendertarget_height);
1036
1037 /* Generate raw vertex array data. Note we do not differentiate between instanced and
1038 * non-instanced cases for geometry shaders that emit points */
1039 const unsigned int raw_array_data_size = getRawArraysDataBufferSize(false);
1040
1041 m_raw_array_data = new float[raw_array_data_size / sizeof(float)];
1042
1043 for (unsigned int n_point = 0; n_point < 8 /* points, as per test spec */; ++n_point)
1044 {
1045 switch (m_output_type)
1046 {
1047 case SHADER_OUTPUT_TYPE_LINE_STRIP:
1048 {
1049 m_raw_array_data[n_point * 4 + 0] =
1050 -1 + ((float(3 + 7 * n_point) + 0.5f) / float(rendertarget_width)) * 2.0f;
1051 m_raw_array_data[n_point * 4 + 1] = -1 + ((float(3.0f + 0.5f)) / float(rendertarget_height)) * 2.0f;
1052 m_raw_array_data[n_point * 4 + 2] = 0.0f;
1053 m_raw_array_data[n_point * 4 + 3] = 1.0f;
1054
1055 break;
1056 }
1057
1058 case SHADER_OUTPUT_TYPE_POINTS:
1059 {
1060 m_raw_array_data[n_point * 4 + 0] =
1061 -1 + ((float(1 + 5 * n_point) + 0.5f) / float(rendertarget_width)) * 2.0f;
1062 m_raw_array_data[n_point * 4 + 1] = -1 + (float(1.5f + 0.5f) / float(rendertarget_height)) * 2.0f;
1063 m_raw_array_data[n_point * 4 + 2] = 0.0f;
1064 m_raw_array_data[n_point * 4 + 3] = 1.0f;
1065
1066 break;
1067 }
1068
1069 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
1070 {
1071 m_raw_array_data[n_point * 4 + 0] = -1 + ((float(6 * n_point) + 0.5f) / float(rendertarget_width)) * 2.0f;
1072 m_raw_array_data[n_point * 4 + 1] = -1.0f;
1073 m_raw_array_data[n_point * 4 + 2] = 0.0f;
1074 m_raw_array_data[n_point * 4 + 3] = 1.0f;
1075
1076 break;
1077 }
1078
1079 default:
1080 {
1081 TCU_FAIL("Unsupported shader output layout qualifier requested");
1082 }
1083 } /* switch (m_output_type) */
1084 } /* for (all points) */
1085
1086 /* Generate unordered data - we do not differentiate between instanced & non-instanced cases
1087 * for "points" tests
1088 */
1089 const unsigned int unordered_array_data_size = getUnorderedArraysDataBufferSize(false);
1090 const unsigned int unordered_elements_data_size = getUnorderedElementsDataBufferSize(false);
1091
1092 m_unordered_array_data = new float[unordered_array_data_size / sizeof(float)];
1093 m_unordered_elements_data = new unsigned char[unordered_elements_data_size];
1094
1095 for (unsigned int n_point = 0; n_point < 8 /* points, as per test spec */; ++n_point)
1096 {
1097 memcpy(m_unordered_array_data + n_point * 4, m_raw_array_data + (8 - n_point - 1) * 4,
1098 sizeof(float) * 4 /* components */);
1099 } /* for (all points) */
1100
1101 for (unsigned int n_point = 0; n_point < 8 /* points, as per test spec */; ++n_point)
1102 {
1103 m_unordered_elements_data[n_point] = (unsigned char)((n_point * 2) % 8 + n_point / 4);
1104 } /* for (all points) */
1105 }
1106
1107 /** Destructor. */
~GeometryShaderRenderingPointsCase()1108 GeometryShaderRenderingPointsCase::~GeometryShaderRenderingPointsCase()
1109 {
1110 if (m_raw_array_data != NULL)
1111 {
1112 delete[] m_raw_array_data;
1113
1114 m_raw_array_data = NULL;
1115 }
1116
1117 if (m_unordered_array_data != NULL)
1118 {
1119 delete[] m_unordered_array_data;
1120
1121 m_unordered_array_data = NULL;
1122 }
1123
1124 if (m_unordered_elements_data != NULL)
1125 {
1126 delete[] m_unordered_elements_data;
1127
1128 m_unordered_elements_data = NULL;
1129 }
1130 }
1131
1132 /** Retrieves amount of instances that should be drawn with glDraw*Elements() calls.
1133 *
1134 * @return As per description.
1135 **/
getAmountOfDrawInstances()1136 unsigned int GeometryShaderRenderingPointsCase::getAmountOfDrawInstances()
1137 {
1138 return 4 /* instances */;
1139 }
1140
1141 /** Retrieves amount of indices that should be used for rendering a single instance
1142 * (glDraw*Elements() calls only)
1143 *
1144 * @return As per description.
1145 */
getAmountOfElementsPerInstance()1146 unsigned int GeometryShaderRenderingPointsCase::getAmountOfElementsPerInstance()
1147 {
1148 return 8 /* elements */;
1149 }
1150
1151 /** Retrieves amount of vertices that should be used for rendering a single instance
1152 * (glDrawArrays*() calls only)
1153 *
1154 * @return As per description.
1155 **/
getAmountOfVerticesPerInstance()1156 unsigned int GeometryShaderRenderingPointsCase::getAmountOfVerticesPerInstance()
1157 {
1158 return 8 /* points */;
1159 }
1160
1161 /** Draw call mode that should be used glDraw*() calls.
1162 *
1163 * @return As per description.
1164 **/
getDrawCallMode()1165 glw::GLenum GeometryShaderRenderingPointsCase::getDrawCallMode()
1166 {
1167 return GL_POINTS;
1168 }
1169
1170 /** Source code for a fragment shader that should be used for the test.
1171 *
1172 * @return As per description.
1173 **/
getFragmentShaderCode()1174 std::string GeometryShaderRenderingPointsCase::getFragmentShaderCode()
1175 {
1176 static std::string fs_code = "${VERSION}\n"
1177 "\n"
1178 "precision highp float;\n"
1179 "\n"
1180 "in vec4 gs_fs_color;\n"
1181 "out vec4 result;\n"
1182 "\n"
1183 "void main()\n"
1184 "{\n"
1185 " result = gs_fs_color;\n"
1186 "}\n";
1187
1188 return fs_code;
1189 }
1190
1191 /** Source code for a geometry shader that should be used for the test.
1192 *
1193 * @return As per description.
1194 **/
getGeometryShaderCode()1195 std::string GeometryShaderRenderingPointsCase::getGeometryShaderCode()
1196 {
1197 static const char* lines_gs_code = "${VERSION}\n"
1198 "\n"
1199 "${GEOMETRY_SHADER_ENABLE}\n"
1200 "\n"
1201 "layout(points) in;\n"
1202 "layout(line_strip, max_vertices=15) out;\n"
1203 "\n"
1204 "in vec4 vs_gs_color[1];\n"
1205 "out vec4 gs_fs_color;\n"
1206 "\n"
1207 "uniform ivec2 renderingTargetSize;\n"
1208 "\n"
1209 "void main()\n"
1210 "{\n"
1211 " float bias = 0.0035;"
1212 " for (int delta = 1; delta <= 3; ++delta)\n"
1213 " {\n"
1214 " float dx = float(delta * 2) / float(renderingTargetSize.x) + bias;\n"
1215 " float dy = float(delta * 2) / float(renderingTargetSize.y) + bias;\n"
1216 "\n"
1217 /* TL->TR */
1218 " gs_fs_color = vs_gs_color[0];\n"
1219 " gl_Position = gl_in[0].gl_Position + vec4(-dx, -dy, 0, 0);\n"
1220 " EmitVertex();\n"
1221 " gs_fs_color = vs_gs_color[0];\n"
1222 " gl_Position = gl_in[0].gl_Position + vec4(dx, -dy, 0, 0);\n"
1223 " EmitVertex();\n"
1224 /* TR->BR */
1225 " gs_fs_color = vs_gs_color[0];\n"
1226 " gl_Position = gl_in[0].gl_Position + vec4(dx, dy, 0, 0);\n"
1227 " EmitVertex();\n"
1228 /* BR->BL */
1229 " gs_fs_color = vs_gs_color[0];\n"
1230 " gl_Position = gl_in[0].gl_Position + vec4(-dx, dy, 0, 0);\n"
1231 " EmitVertex();\n"
1232 /* BL->TL */
1233 " gs_fs_color = vs_gs_color[0];\n"
1234 " gl_Position = gl_in[0].gl_Position + vec4(-dx, -dy, 0, 0);\n"
1235 " EmitVertex();\n"
1236 " EndPrimitive();\n"
1237 " }\n"
1238 "}\n";
1239
1240 static const char* points_gs_code = "${VERSION}\n"
1241 "\n"
1242 "${GEOMETRY_SHADER_ENABLE}\n"
1243 "\n"
1244 "layout(points) in;\n"
1245 "layout(points, max_vertices=9) out;\n"
1246 "\n"
1247 "in vec4 vs_gs_color[1];\n"
1248 "out vec4 gs_fs_color;\n"
1249 "\n"
1250 "uniform ivec2 renderingTargetSize;\n"
1251 "\n"
1252 "void main()\n"
1253 "{\n"
1254 " float dx = 2.0 / float(renderingTargetSize.x);\n"
1255 " float dy = 2.0 / float(renderingTargetSize.y);\n"
1256 "\n"
1257 /* TL */
1258 " gs_fs_color = vs_gs_color[0];\n"
1259 " gl_Position = gl_in[0].gl_Position + vec4(-dx, -dy, 0, 0);\n"
1260 " EmitVertex();\n"
1261 /* TM */
1262 " gs_fs_color = vs_gs_color[0];\n"
1263 " gl_Position = gl_in[0].gl_Position + vec4(0, -dy, 0, 0);\n"
1264 " EmitVertex();\n"
1265 /* TR */
1266 " gs_fs_color = vs_gs_color[0];\n"
1267 " gl_Position = gl_in[0].gl_Position + vec4(dx, -dy, 0, 0);\n"
1268 " EmitVertex();\n"
1269 /* L */
1270 " gs_fs_color = vs_gs_color[0];\n"
1271 " gl_Position = gl_in[0].gl_Position + vec4(-dx, 0, 0, 0); \n"
1272 " EmitVertex();\n"
1273 /* M */
1274 " gs_fs_color = vs_gs_color[0];\n"
1275 " gl_Position = gl_in[0].gl_Position;\n"
1276 " EmitVertex();\n"
1277 /* R */
1278 " gs_fs_color = vs_gs_color[0];\n"
1279 " gl_Position = gl_in[0].gl_Position + vec4(dx, 0, 0, 0);\n"
1280 " EmitVertex();\n"
1281 /* BL */
1282 " gs_fs_color = vs_gs_color[0];\n"
1283 " gl_Position = gl_in[0].gl_Position + vec4(-dx, dy, 0, 0);\n"
1284 " EmitVertex();\n"
1285 /* BM */
1286 " gs_fs_color = vs_gs_color[0];\n"
1287 " gl_Position = gl_in[0].gl_Position + vec4(0, dy, 0, 0);\n"
1288 " EmitVertex();\n"
1289 /* BR */
1290 " gs_fs_color = vs_gs_color[0];\n"
1291 " gl_Position = gl_in[0].gl_Position + vec4(dx, dy, 0, 0);\n"
1292 " EmitVertex();\n"
1293 "}\n";
1294
1295 static const char* triangles_gs_code = "${VERSION}\n"
1296 "\n"
1297 "${GEOMETRY_SHADER_ENABLE}\n"
1298 "\n"
1299 "layout(points) in;\n"
1300 "layout(triangle_strip, max_vertices=6) out;\n"
1301 "\n"
1302 "in vec4 vs_gs_color[1];\n"
1303 "out vec4 gs_fs_color;\n"
1304 "\n"
1305 "uniform ivec2 renderingTargetSize;\n"
1306 "\n"
1307 "void main()\n"
1308 "{\n"
1309 /* Assume that point position corresponds to TL corner. */
1310 " float dx = float(2.0) / float(renderingTargetSize.x);\n"
1311 " float dy = float(2.0) / float(renderingTargetSize.y);\n"
1312 "\n"
1313 /* BL 1 */
1314 " gs_fs_color = vec4(vs_gs_color[0].x, 0, 0, 0);\n"
1315 " gl_Position = gl_in[0].gl_Position + vec4(0, 6.0 * dy, 0, 0);\n"
1316 " EmitVertex();\n"
1317 /* TL 1 */
1318 " gs_fs_color = vec4(vs_gs_color[0].x, 0, 0, 0);\n"
1319 " gl_Position = gl_in[0].gl_Position;\n"
1320 " EmitVertex();\n"
1321 /* BR 1 */
1322 " gs_fs_color = vec4(vs_gs_color[0].x, 0, 0, 0);\n"
1323 " gl_Position = gl_in[0].gl_Position + vec4(6.0 * dx, 6.0 * dy, 0, 0);\n"
1324 " EmitVertex();\n"
1325 " EndPrimitive();\n"
1326 /* BR 2 */
1327 " gs_fs_color = vec4(0, vs_gs_color[0].y, 0, 0);\n"
1328 " gl_Position = gl_in[0].gl_Position + vec4(6.0 * dx, 6.0 * dy, 0, 0);\n"
1329 " EmitVertex();\n"
1330 /* TL 2 */
1331 " gs_fs_color = vec4(0, vs_gs_color[0].y, 0, 0);\n"
1332 " gl_Position = gl_in[0].gl_Position;\n"
1333 " EmitVertex();\n"
1334 /* TR 2 */
1335 " gs_fs_color = vec4(0, vs_gs_color[0].y, 0, 0);\n"
1336 " gl_Position = gl_in[0].gl_Position + vec4(6.0 * dx, 0, 0, 0);\n"
1337 " EmitVertex();\n"
1338 " EndPrimitive();\n"
1339 "}\n";
1340 const char* result = NULL;
1341
1342 switch (m_output_type)
1343 {
1344 case SHADER_OUTPUT_TYPE_LINE_STRIP:
1345 {
1346 result = lines_gs_code;
1347
1348 break;
1349 }
1350
1351 case SHADER_OUTPUT_TYPE_POINTS:
1352 {
1353 result = points_gs_code;
1354
1355 break;
1356 }
1357
1358 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
1359 {
1360 result = triangles_gs_code;
1361
1362 break;
1363 }
1364
1365 default:
1366 {
1367 TCU_FAIL("Requested shader output layout qualifier is unsupported");
1368 }
1369 } /* switch (m_output_type) */
1370
1371 return result;
1372 }
1373
1374 /** Returns amount of bytes that should be allocated for a buffer object to hold
1375 * vertex data to be used for glDrawArrays*() calls.
1376 *
1377 * @param instanced Ignored.
1378 *
1379 * @return As per description.
1380 **/
getRawArraysDataBufferSize(bool)1381 glw::GLuint GeometryShaderRenderingPointsCase::getRawArraysDataBufferSize(bool /*instanced*/)
1382 {
1383
1384 return sizeof(float) * (1 /* point */ * 4 /* coordinates */) * 8 /* points in total, as per test spec */;
1385 }
1386
1387 /** Returns vertex data for the test. Only to be used for glDrawArrays*() calls.
1388 *
1389 * @param instanced Ignored.
1390 *
1391 * @return As per description.
1392 **/
getRawArraysDataBuffer(bool)1393 const void* GeometryShaderRenderingPointsCase::getRawArraysDataBuffer(bool /*instanced*/)
1394 {
1395 return m_raw_array_data;
1396 }
1397
1398 /** Retrieves resolution of off-screen rendering buffer that should be used for the test.
1399 *
1400 * @param n_instances Amount of draw call instances this render target will be used for.
1401 * @param out_width Deref will be used to store rendertarget's width. Must not be NULL.
1402 * @param out_height Deref will be used to store rendertarget's height. Must not be NULL.
1403 **/
getRenderTargetSize(unsigned int n_instances,unsigned int * out_width,unsigned int * out_height)1404 void GeometryShaderRenderingPointsCase::getRenderTargetSize(unsigned int n_instances, unsigned int* out_width,
1405 unsigned int* out_height)
1406 {
1407 switch (m_output_type)
1408 {
1409 case SHADER_OUTPUT_TYPE_LINE_STRIP:
1410 {
1411 *out_width = 56; /* as per test spec */
1412 *out_height = 7 * n_instances; /* as per test spec */
1413
1414 break;
1415 }
1416
1417 case SHADER_OUTPUT_TYPE_POINTS:
1418 {
1419 *out_width = 38; /* as per test spec */
1420 *out_height = 3 * n_instances + 2 * (n_instances - 1); /* as per test spec */
1421
1422 break;
1423 }
1424
1425 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
1426 {
1427 *out_width = 48; /* as per test spec */
1428 *out_height = 6 * n_instances; /* as per test spec */
1429
1430 break;
1431 }
1432
1433 default:
1434 {
1435 TCU_FAIL("Unsupported shader output type");
1436 }
1437 } /* switch (m_output_type) */
1438 }
1439
1440 /** Returns amount of bytes that should be allocated for a buffer object to hold
1441 * vertex data to be used for glDrawElements*() calls.
1442 *
1443 * @param instanced Ignored.
1444 *
1445 * @return As per description.
1446 **/
getUnorderedArraysDataBufferSize(bool)1447 glw::GLuint GeometryShaderRenderingPointsCase::getUnorderedArraysDataBufferSize(bool /*instanced*/)
1448 {
1449
1450 /* Note: No difference between non-instanced and instanced cases for this class */
1451 return sizeof(float) * (1 /* point */ * 4 /* coordinates */) * 8 /* points in total, as per test spec */;
1452 }
1453
1454 /** Returns vertex data for the test. Only to be used for glDrawElements*() calls.
1455 *
1456 * @param instanced Ignored.
1457 *
1458 * @return As per description.
1459 **/
getUnorderedArraysDataBuffer(bool)1460 const void* GeometryShaderRenderingPointsCase::getUnorderedArraysDataBuffer(bool /*instanced*/)
1461 {
1462
1463 /* Note: No difference between non-instanced and instanced cases for this class */
1464 return m_unordered_array_data;
1465 }
1466
1467 /** Returns amount of bytes that should be allocated for a buffer object to hold
1468 * index data to be used for glDrawElements*() calls.
1469 *
1470 * @param instanced Ignored.
1471 *
1472 * @return As per description.
1473 */
getUnorderedElementsDataBufferSize(bool)1474 glw::GLuint GeometryShaderRenderingPointsCase::getUnorderedElementsDataBufferSize(bool /*instanced*/)
1475 {
1476
1477 /* Note: No difference between non-instanced and instanced cases for this class */
1478 return 8 /* indices */ * sizeof(unsigned char);
1479 }
1480
1481 /** Returns index data for the test. Only to be used for glDrawElements*() calls.
1482 *
1483 * @param instanced Ignored.
1484 *
1485 * @return As per description.
1486 **/
getUnorderedElementsDataBuffer(bool)1487 const void* GeometryShaderRenderingPointsCase::getUnorderedElementsDataBuffer(bool /*instanced*/)
1488 {
1489
1490 /* Note: No difference between non-instanced and instanced cases for this class */
1491 return m_unordered_elements_data;
1492 }
1493
1494 /** Returns type of the index, to be used for glDrawElements*() calls.
1495 *
1496 * @return As per description.
1497 **/
getUnorderedElementsDataType()1498 glw::GLenum GeometryShaderRenderingPointsCase::getUnorderedElementsDataType()
1499 {
1500 return GL_UNSIGNED_BYTE;
1501 }
1502
1503 /** Retrieves maximum index value. To be used for glDrawRangeElements() test only.
1504 *
1505 * @return As per description.
1506 **/
getUnorderedElementsMaxIndex()1507 glw::GLubyte GeometryShaderRenderingPointsCase::getUnorderedElementsMaxIndex()
1508 {
1509 return 8 /* up to 8 points will be rendered */;
1510 }
1511
1512 /** Retrieves minimum index value. To be used for glDrawRangeElements() test only.
1513 *
1514 * @return As per description.
1515 **/
getUnorderedElementsMinIndex()1516 glw::GLubyte GeometryShaderRenderingPointsCase::getUnorderedElementsMinIndex()
1517 {
1518 return 0;
1519 }
1520
1521 /** Retrieves vertex shader code to be used for the test.
1522 *
1523 * @return As per description.
1524 **/
getVertexShaderCode()1525 std::string GeometryShaderRenderingPointsCase::getVertexShaderCode()
1526 {
1527 static std::string lines_vs_code =
1528 "${VERSION}\n"
1529 "\n"
1530 "in vec4 position;\n"
1531 "uniform ivec2 renderingTargetSize;\n"
1532 "out vec4 vs_gs_color;\n"
1533 "\n"
1534 "void main()\n"
1535 "{\n"
1536 /* non-instanced draw call cases */
1537 " if (renderingTargetSize.y == 7)\n"
1538 " {\n"
1539 " gl_Position = position;"
1540 " }\n"
1541 " else\n"
1542 " {\n"
1543 /* instanced draw call cases: */
1544 " gl_Position = vec4(position.x, \n"
1545 " -1.0 + ((float(3 + gl_InstanceID * 7)) / float(renderingTargetSize.y - 1)) * 2.0,\n"
1546 " position.zw);\n"
1547 " }\n"
1548 "\n"
1549 " switch(gl_VertexID)\n"
1550 " {\n"
1551 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
1552 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
1553 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
1554 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
1555 " case 4: vs_gs_color = vec4(1, 1, 0, 0); break;\n"
1556 " case 5: vs_gs_color = vec4(1, 0, 1, 0); break;\n"
1557 " case 6: vs_gs_color = vec4(1, 0, 0, 1); break;\n"
1558 " case 7: vs_gs_color = vec4(1, 1, 1, 0); break;\n"
1559 " case 8: vs_gs_color = vec4(1, 1, 0, 1); break;\n"
1560 " }\n"
1561 "}\n";
1562
1563 static std::string points_vs_code =
1564 "${VERSION}\n"
1565 "\n"
1566 "in vec4 position;\n"
1567 "uniform ivec2 renderingTargetSize;\n"
1568 "out vec4 vs_gs_color;\n"
1569 "\n"
1570 "void main()\n"
1571 "{\n"
1572 " gl_PointSize = 1.0;\n"
1573 "\n"
1574 /* non-instanced draw call cases */
1575 " if (renderingTargetSize.y == 3)\n"
1576 " {\n"
1577 " gl_Position = position;\n"
1578 " }\n"
1579 /* instanced draw call cases */
1580 " else\n"
1581 " {\n"
1582 " gl_Position = vec4(position.x,\n"
1583 " -1.0 + (1.5 + float(5 * gl_InstanceID)) / float(renderingTargetSize.y) * 2.0,\n"
1584 " position.zw);\n"
1585 " }\n"
1586 "\n"
1587 " switch(gl_VertexID)\n"
1588 " {\n"
1589 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
1590 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
1591 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
1592 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
1593 " case 4: vs_gs_color = vec4(1, 1, 0, 0); break;\n"
1594 " case 5: vs_gs_color = vec4(1, 0, 1, 0); break;\n"
1595 " case 6: vs_gs_color = vec4(1, 0, 0, 1); break;\n"
1596 " case 7: vs_gs_color = vec4(1, 1, 1, 0); break;\n"
1597 " case 8: vs_gs_color = vec4(1, 1, 0, 1); break;\n"
1598 " }\n"
1599 "}\n";
1600
1601 static std::string triangles_vs_code =
1602 "${VERSION}\n"
1603 "\n"
1604 "in vec4 position;\n"
1605 "uniform ivec2 renderingTargetSize;\n"
1606 "out vec4 vs_gs_color;\n"
1607 "\n"
1608 "void main()\n"
1609 "{\n"
1610 " if (renderingTargetSize.y == 6)\n"
1611 " {\n"
1612 " gl_Position = position;\n"
1613 " }\n"
1614 " else\n"
1615 " {\n"
1616 " gl_Position = vec4(position.x,\n"
1617 " position.y + float(gl_InstanceID) * 6.0 / float(renderingTargetSize.y) * 2.0,\n"
1618 " position.zw);\n"
1619 " }\n"
1620 "\n"
1621 " switch(gl_VertexID)\n"
1622 " {\n"
1623 " case 0: vs_gs_color = vec4(0.1, 0.8, 0, 0); break;\n"
1624 " case 1: vs_gs_color = vec4(0.2, 0.7, 0, 0); break;\n"
1625 " case 2: vs_gs_color = vec4(0.3, 0.6, 1, 0); break;\n"
1626 " case 3: vs_gs_color = vec4(0.4, 0.5, 0, 1); break;\n"
1627 " case 4: vs_gs_color = vec4(0.5, 0.4, 0, 0); break;\n"
1628 " case 5: vs_gs_color = vec4(0.6, 0.3, 1, 0); break;\n"
1629 " case 6: vs_gs_color = vec4(0.7, 0.2, 0, 1); break;\n"
1630 " case 7: vs_gs_color = vec4(0.8, 0.1, 1, 0); break;\n"
1631 " }\n"
1632 "}\n";
1633 std::string result;
1634
1635 switch (m_output_type)
1636 {
1637 case SHADER_OUTPUT_TYPE_LINE_STRIP:
1638 {
1639 result = lines_vs_code;
1640
1641 break;
1642 }
1643
1644 case SHADER_OUTPUT_TYPE_POINTS:
1645 {
1646 result = points_vs_code;
1647
1648 break;
1649 }
1650
1651 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
1652 {
1653 result = triangles_vs_code;
1654
1655 break;
1656 }
1657
1658 default:
1659 {
1660 TCU_FAIL("Unsupported shader output type used");
1661 }
1662 } /* switch (m_output_type) */
1663
1664 return result;
1665 }
1666
1667 /** Verifies that the rendered data is correct.
1668 *
1669 * @param drawcall_type Type of the draw call that was used to render the geometry.
1670 * @param instance_id Instance ID to be verified. Use 0 for non-instanced draw calls.
1671 * @param data Contents of the rendertarget after the test has finished rendering.
1672 **/
verify(_draw_call_type drawcall_type,unsigned int instance_id,const unsigned char * data)1673 void GeometryShaderRenderingPointsCase::verify(_draw_call_type drawcall_type, unsigned int instance_id,
1674 const unsigned char* data)
1675 {
1676 /* The array is directly related to vertex shader contents for "points" and "line_strip"
1677 * outputs */
1678 static const unsigned char ref_data[] = { 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0,
1679 0, 0, 0, 255, 255, 255, 0, 0, 255, 0, 255, 0,
1680 255, 0, 0, 255, 255, 255, 255, 0, 255, 255, 0, 255 };
1681 /* The array refers to colors as defined in vertex shader used for "triangle_strip"
1682 * output.
1683 */
1684 static const unsigned char ref_data_triangle_strip[] = {
1685 (unsigned char)(0.1f * 255), (unsigned char)(0.8f * 255), 0, 0,
1686 (unsigned char)(0.2f * 255), (unsigned char)(0.7f * 255), 0, 0,
1687 (unsigned char)(0.3f * 255), (unsigned char)(0.6f * 255), 255, 0,
1688 (unsigned char)(0.4f * 255), (unsigned char)(0.5f * 255), 0, 255,
1689 (unsigned char)(0.5f * 255), (unsigned char)(0.4f * 255), 0, 0,
1690 (unsigned char)(0.6f * 255), (unsigned char)(0.3f * 255), 255, 0,
1691 (unsigned char)(0.7f * 255), (unsigned char)(0.2f * 255), 0, 255,
1692 (unsigned char)(0.8f * 255), (unsigned char)(0.1f * 255), 255, 0
1693 };
1694 unsigned int rt_height = 0;
1695 unsigned int rt_width = 0;
1696
1697 /* Retrieve render-target size */
1698 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED ||
1699 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED)
1700 {
1701 getRenderTargetSize(getAmountOfDrawInstances(), &rt_width, &rt_height);
1702 }
1703 else
1704 {
1705 getRenderTargetSize(1, &rt_width, &rt_height);
1706 }
1707
1708 switch (m_output_type)
1709 {
1710 case SHADER_OUTPUT_TYPE_LINE_STRIP:
1711 {
1712 for (unsigned int n_point = 0; n_point < 8 /* points */; ++n_point)
1713 {
1714 /* Each point takes a 7x7 block. The test should verify that the second "nested" block
1715 * is of the valid color. Blocks can be built on top of each other if instanced draw
1716 * calls are used. */
1717 const unsigned char* reference_data = NULL;
1718 const unsigned char* rendered_data = NULL;
1719 const int row_width = rt_width * 4 /* components */;
1720 const int sample_region_edge_px = 5 /* pixels */;
1721
1722 for (int n_edge = 0; n_edge < 4 /* edges */; ++n_edge)
1723 {
1724 /* Edge 1: TL->TR
1725 * Edge 2: TR->BR
1726 * Edge 3: BR->BL
1727 * Edge 4: BL->TL
1728 */
1729 int dx = 0;
1730 int dy = 0;
1731 int x = 0;
1732 int x_start = 0;
1733 int y = 0;
1734 int y_start = 0;
1735
1736 switch (n_edge)
1737 {
1738 /* NOTE: The numbers here are as per test spec */
1739 case 0:
1740 dx = 1 /* px */;
1741 dy = 0 /* px */;
1742 x_start = 1 /* px */;
1743 y_start = 1 /* px */;
1744 break;
1745 case 1:
1746 dx = 0 /* px */;
1747 dy = 1 /* px */;
1748 x_start = 5 /* px */;
1749 y_start = 1 /* px */;
1750 break;
1751 case 2:
1752 dx = -1 /* px */;
1753 dy = 0 /* px */;
1754 x_start = 5 /* px */;
1755 y_start = 5 /* px */;
1756 break;
1757 case 3:
1758 dx = 0 /* px */;
1759 dy = -1 /* px */;
1760 x_start = 1 /* px */;
1761 y_start = 5 /* px */;
1762 break;
1763
1764 default:
1765 {
1766 TCU_FAIL("Invalid edge index");
1767 }
1768 } /* switch (n_edge) */
1769
1770 /* What color should the pixels have? */
1771 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS ||
1772 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED)
1773 {
1774 reference_data = ref_data + n_point * 4 /* components */;
1775 x = x_start + n_point * 7 /* pixel block size */;
1776 y = y_start + instance_id * 7 /* pixel block size */;
1777 }
1778 else
1779 {
1780 int index = m_unordered_elements_data[n_point];
1781
1782 reference_data = ref_data + (8 - 1 - index) * 4 /* components */;
1783 x = x_start + index * 7 /* pixel block size */;
1784 y = y_start + instance_id * 7 /* pixel block size */;
1785 }
1786
1787 /* Verify edge pixels */
1788 for (int n_pixel = 0; n_pixel < sample_region_edge_px; ++n_pixel)
1789 {
1790 rendered_data = data + y * row_width + x * 4 /* components */;
1791
1792 if (memcmp(rendered_data, reference_data, 4 /* components */) != 0)
1793 {
1794 m_testCtx.getLog() << tcu::TestLog::Message << "At (" << (int)x << ", " << (int)y
1795 << "), "
1796 "rendered data ("
1797 << (int)rendered_data[0] << ", " << (int)rendered_data[1] << ", "
1798 << (int)rendered_data[2] << ", " << (int)rendered_data[3]
1799 << ") "
1800 "is different from reference data ("
1801 << (int)reference_data[0] << ", " << (int)reference_data[1] << ", "
1802 << (int)reference_data[2] << ", " << (int)reference_data[3] << ")"
1803 << tcu::TestLog::EndMessage;
1804
1805 TCU_FAIL("Data comparison failed");
1806 } /* if (data comparison failed) */
1807
1808 /* Move to next pixel */
1809 x += dx;
1810 y += dy;
1811 } /* for (all pixels) */
1812 } /* for (all edges) */
1813 } /* for (all points) */
1814
1815 break;
1816 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */
1817
1818 case SHADER_OUTPUT_TYPE_POINTS:
1819 {
1820 /* For each 3px high row, we want to sample the second row. Area of a single "pixel" (incl. delta)
1821 * can take no more than 5px, with the actual sampled area located in the second pixel.
1822 */
1823 const int sample_region_width_px = 5; /* pixels */
1824
1825 for (int n = 0; n < 8 /* points */; ++n)
1826 {
1827 int x = 0;
1828 int y = 0;
1829 const unsigned char* reference_data = NULL;
1830 const unsigned char* rendered_data = NULL;
1831
1832 /* Different ordering is used for indexed draw calls */
1833 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
1834 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED ||
1835 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS)
1836 {
1837 /* For indexed calls, vertex data is laid out in a reversed ordered */
1838 int index = m_unordered_elements_data[n];
1839
1840 x = index * sample_region_width_px + 1;
1841 y = instance_id * 5 + 1; /* middle row */
1842 reference_data = ref_data + ((8 - 1 - index) * 4 /* components */);
1843 rendered_data = data + (y * rt_width + x) * 4 /* components */;
1844 } /* if (draw call is indiced) */
1845 else
1846 {
1847 x = n * sample_region_width_px + 1;
1848 y = instance_id * 5 + 1; /* middle row */
1849 reference_data = ref_data + (n * 4 /* components */);
1850 rendered_data = data + (y * rt_width + x) * 4 /* components */;
1851 }
1852
1853 if (memcmp(rendered_data, reference_data, 4 /* components */) != 0)
1854 {
1855 m_testCtx.getLog() << tcu::TestLog::Message << "Reference data: [" << (int)reference_data[0] << ", "
1856 << (int)reference_data[1] << ", " << (int)reference_data[2] << ", "
1857 << (int)reference_data[3] << "] "
1858 "for pixel at ("
1859 << x << ", " << y << ") "
1860 "does not match ["
1861 << (int)rendered_data[0] << ", " << (int)rendered_data[1] << ", "
1862 << (int)rendered_data[2] << ", " << (int)rendered_data[3] << ").";
1863
1864 TCU_FAIL("Data comparison failed.");
1865 } /* if (memcmp(rendered_data, reference_data, 4) != 0) */
1866 } /* for (all points) */
1867
1868 break;
1869 } /* case SHADER_OUTPUT_TYPE_POINTS: */
1870
1871 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
1872 {
1873 /* A pair of adjacent triangles is contained within a 6x6 bounding box.
1874 * The box is defined by top-left corner which is located at input point's
1875 * location.
1876 * The left triangle should only use red channel, the one on the right
1877 * should only use green channel.
1878 * We find centroid for each triangle, sample its color and make sure
1879 * it's valid.
1880 */
1881 for (int n_point = 0; n_point < 8 /* points */; ++n_point)
1882 {
1883 const unsigned int epsilon = 1;
1884 int point_x = 0;
1885 int point_y = 6 * instance_id;
1886 const unsigned char* rendered_data = NULL;
1887 const unsigned char* reference_data = 0;
1888 const unsigned int row_width = rt_width * 4 /* components */;
1889 int t1[6 /* 3 * {x, y} */] = { 0 };
1890 int t2[6 /* 3 * {x, y} */] = { 0 };
1891 int t1_center[2 /* {x, y} */] = { 0 };
1892 int t2_center[2 /* {x, y} */] = { 0 };
1893
1894 /* Different ordering is used for indexed draw calls */
1895 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
1896 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED ||
1897 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS)
1898 {
1899 int index = m_unordered_elements_data[n_point];
1900
1901 point_x = 6 * index;
1902 reference_data = ref_data_triangle_strip + (8 - 1 - index) * 4 /* components */;
1903 }
1904 else
1905 {
1906 point_x = 6 * n_point;
1907 reference_data = ref_data_triangle_strip + n_point * 4 /* components */;
1908 }
1909
1910 /* Calculate triangle vertex locations (corresponds to geometry shader logic) */
1911 t1[0] = point_x;
1912 t1[1] = point_y + 6;
1913 t1[2] = point_x;
1914 t1[3] = point_y;
1915 t1[4] = point_x + 6;
1916 t1[5] = point_y + 6;
1917
1918 t2[0] = point_x + 6;
1919 t2[1] = point_y + 6;
1920 t2[2] = point_x;
1921 t2[3] = point_y;
1922 t2[4] = point_x + 6;
1923 t2[5] = point_y;
1924
1925 /* Calculate centroid locations */
1926 t1_center[0] = (t1[0] + t1[2] + t1[4]) / 3;
1927 t2_center[0] = (t2[0] + t2[2] + t2[4]) / 3;
1928 t1_center[1] = (t1[1] + t1[3] + t1[5]) / 3;
1929 t2_center[1] = (t2[1] + t2[3] + t2[5]) / 3;
1930
1931 /* Check the first triangle */
1932 point_x = t1_center[0];
1933 point_y = t1_center[1];
1934
1935 rendered_data = data + point_y * row_width + point_x * 4 /* components */;
1936
1937 if ((unsigned int)de::abs((int)rendered_data[0] - reference_data[0]) > epsilon || rendered_data[1] != 0 ||
1938 rendered_data[2] != 0 || rendered_data[3] != 0)
1939 {
1940 m_testCtx.getLog() << tcu::TestLog::Message << "At (" << (int)point_x << ", " << (int)point_y << ") "
1941 << "rendered pixel (" << (int)rendered_data[0] << ", " << (int)rendered_data[1]
1942 << ", " << (int)rendered_data[2] << ", " << (int)rendered_data[3] << ") "
1943 << "is different than (" << (int)reference_data[0] << ", 0, 0, 0)."
1944 << tcu::TestLog::EndMessage;
1945
1946 TCU_FAIL("Data comparison failed.");
1947 }
1948
1949 /* Check the other triangle */
1950 point_x = t2_center[0];
1951 point_y = t2_center[1];
1952
1953 rendered_data = data + point_y * row_width + point_x * 4 /* components */;
1954
1955 if (rendered_data[0] != 0 || (unsigned int)de::abs((int)rendered_data[1] - reference_data[1]) > epsilon ||
1956 rendered_data[2] != 0 || rendered_data[3] != 0)
1957 {
1958 m_testCtx.getLog() << tcu::TestLog::Message << "At (" << (int)point_x << ", " << (int)point_y << ") "
1959 << "rendered pixel (" << (int)rendered_data[0] << ", " << (int)rendered_data[1]
1960 << ", " << (int)rendered_data[2] << ", " << (int)rendered_data[3] << ") "
1961 << "is different than (0, " << (int)reference_data[1] << ", 0, 0)."
1962 << tcu::TestLog::EndMessage;
1963
1964 TCU_FAIL("Data comparison failed.");
1965 }
1966 } /* for (all points) */
1967
1968 break;
1969 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:*/
1970
1971 default:
1972 {
1973 TCU_FAIL("Unsupported output layout qualifier requested.");
1974
1975 break;
1976 }
1977 } /* switch(m_output_type) */
1978 }
1979
1980 /* "lines" input primitive test implementation */
1981 /** Constructor.
1982 *
1983 * @param use_adjacency_data true if the test case is being instantiated for draw call modes that will
1984 * features adjacency data,
1985 * false otherwise.
1986 * @param drawcall_mode GL draw call mode that will be used for the tests.
1987 * @param output_type Shader output type that the test case is being instantiated for.
1988 * @param context Rendering context;
1989 * @param testContext Test context;
1990 * @param name Test name.
1991 **/
GeometryShaderRenderingLinesCase(Context & context,const ExtParameters & extParams,const char * name,bool use_adjacency_data,glw::GLenum drawcall_mode,_shader_output_type output_type)1992 GeometryShaderRenderingLinesCase::GeometryShaderRenderingLinesCase(Context& context, const ExtParameters& extParams,
1993 const char* name, bool use_adjacency_data,
1994 glw::GLenum drawcall_mode,
1995 _shader_output_type output_type)
1996 : GeometryShaderRenderingCase(
1997 context, extParams, name,
1998 "Verifies all draw calls work correctly for specific input+output+draw call mode combination")
1999 , m_output_type(output_type)
2000 , m_drawcall_mode(drawcall_mode)
2001 , m_use_adjacency_data(use_adjacency_data)
2002 , m_raw_array_instanced_data(0)
2003 , m_raw_array_instanced_data_size(0)
2004 , m_raw_array_noninstanced_data(0)
2005 , m_raw_array_noninstanced_data_size(0)
2006 , m_unordered_array_instanced_data(0)
2007 , m_unordered_array_instanced_data_size(0)
2008 , m_unordered_array_noninstanced_data(0)
2009 , m_unordered_array_noninstanced_data_size(0)
2010 , m_unordered_elements_instanced_data(0)
2011 , m_unordered_elements_instanced_data_size(0)
2012 , m_unordered_elements_noninstanced_data(0)
2013 , m_unordered_elements_noninstanced_data_size(0)
2014 , m_unordered_elements_max_index(16) /* maximum amount of vertices generated for this case */
2015 , m_unordered_elements_min_index(0)
2016 {
2017 /* Sanity checks */
2018 if (!m_use_adjacency_data)
2019 {
2020 if (drawcall_mode != GL_LINE_LOOP && drawcall_mode != GL_LINE_STRIP && drawcall_mode != GL_LINES)
2021 {
2022 TCU_FAIL("Only GL_LINE_LOOP or GL_LINE_STRIP or GL_LINES draw call modes are supported for 'lines' "
2023 "geometry shader input layout qualifier test implementation");
2024 }
2025 }
2026 else
2027 {
2028 if (drawcall_mode != GL_LINES_ADJACENCY_EXT && drawcall_mode != GL_LINE_STRIP_ADJACENCY_EXT)
2029 {
2030 TCU_FAIL("Only GL_LINES_ADJACENCY_EXT or GL_LINE_STRIP_ADJACENCY_EXT draw call modes are supported for "
2031 "'lines_adjacency' geometry shader input layout qualifier test implementation");
2032 }
2033 }
2034
2035 if (output_type != SHADER_OUTPUT_TYPE_POINTS && output_type != SHADER_OUTPUT_TYPE_LINE_STRIP &&
2036 output_type != SHADER_OUTPUT_TYPE_TRIANGLE_STRIP)
2037 {
2038 TCU_FAIL("Unsupported output layout qualifier type requested for 'lines' geometry shader input layout "
2039 "qualifier test implementation");
2040 }
2041
2042 /* Generate data in two flavors - one for non-instanced case, the other one for instanced case */
2043 for (int n_case = 0; n_case < 2 /* cases */; ++n_case)
2044 {
2045 bool is_instanced = (n_case != 0);
2046 int n_instances = 0;
2047 float** raw_arrays_data_ptr = NULL;
2048 unsigned int* raw_arrays_data_size_ptr = NULL;
2049 unsigned int rendertarget_height = 0;
2050 unsigned int rendertarget_width = 0;
2051 float** unordered_arrays_data_ptr = NULL;
2052 unsigned int* unordered_arrays_data_size_ptr = NULL;
2053 unsigned char** unordered_elements_data_ptr = NULL;
2054 unsigned int* unordered_elements_data_size_ptr = NULL;
2055
2056 if (!is_instanced)
2057 {
2058 /* Non-instanced case */
2059 n_instances = 1;
2060 raw_arrays_data_ptr = &m_raw_array_noninstanced_data;
2061 raw_arrays_data_size_ptr = &m_raw_array_noninstanced_data_size;
2062 unordered_arrays_data_ptr = &m_unordered_array_noninstanced_data;
2063 unordered_arrays_data_size_ptr = &m_unordered_array_noninstanced_data_size;
2064 unordered_elements_data_ptr = &m_unordered_elements_noninstanced_data;
2065 unordered_elements_data_size_ptr = &m_unordered_elements_noninstanced_data_size;
2066 }
2067 else
2068 {
2069 /* Instanced case */
2070 n_instances = getAmountOfDrawInstances();
2071 raw_arrays_data_ptr = &m_raw_array_instanced_data;
2072 raw_arrays_data_size_ptr = &m_raw_array_instanced_data_size;
2073 unordered_arrays_data_ptr = &m_unordered_array_instanced_data;
2074 unordered_arrays_data_size_ptr = &m_unordered_array_instanced_data_size;
2075 unordered_elements_data_ptr = &m_unordered_elements_instanced_data;
2076 unordered_elements_data_size_ptr = &m_unordered_elements_instanced_data_size;
2077 }
2078
2079 getRenderTargetSize(n_instances, &rendertarget_width, &rendertarget_height);
2080
2081 /* Store full-screen quad coordinates that will be used for actual array data generation. */
2082 float dx = 2.0f / float(rendertarget_width);
2083 float dy = 2.0f / float(rendertarget_height);
2084
2085 /* Generate raw vertex array data */
2086
2087 float* raw_array_data_traveller = NULL;
2088 unsigned int single_rt_height = 0;
2089 unsigned int single_rt_width = 0;
2090 unsigned int whole_rt_width = 0;
2091 unsigned int whole_rt_height = 0;
2092
2093 switch (m_drawcall_mode)
2094 {
2095 case GL_LINE_LOOP:
2096 {
2097 *raw_arrays_data_size_ptr = 4 /* vertices making up the line strip */ * 4 /* components */ * sizeof(float);
2098
2099 break;
2100 }
2101
2102 case GL_LINE_STRIP:
2103 {
2104 *raw_arrays_data_size_ptr = 5 /* vertices making up the line strip */ * 4 /* components */ * sizeof(float);
2105
2106 break;
2107 }
2108
2109 case GL_LINE_STRIP_ADJACENCY_EXT:
2110 {
2111 *raw_arrays_data_size_ptr =
2112 (5 /* vertices making up the line strip */ + 2 /* additional start/end adjacency vertices */) *
2113 4 /* components */
2114 * sizeof(float);
2115
2116 break;
2117 }
2118
2119 case GL_LINES:
2120 {
2121 *raw_arrays_data_size_ptr =
2122 2 /* points per line segment */ * 4 /* lines */ * 4 /* components */ * sizeof(float);
2123
2124 break;
2125 }
2126
2127 case GL_LINES_ADJACENCY_EXT:
2128 {
2129 *raw_arrays_data_size_ptr =
2130 4 /* points per line segment */ * 4 /* lines */ * 4 /* components */ * sizeof(float);
2131
2132 break;
2133 }
2134
2135 default:
2136 {
2137 TCU_FAIL("Unrecognized draw call mode");
2138 }
2139 } /* switch (m_drawcall_mode) */
2140
2141 *raw_arrays_data_ptr = new float[*raw_arrays_data_size_ptr / sizeof(float)];
2142 raw_array_data_traveller = *raw_arrays_data_ptr;
2143
2144 getRenderTargetSize(1, &single_rt_width, &single_rt_height);
2145 getRenderTargetSize(getAmountOfDrawInstances(), &whole_rt_width, &whole_rt_height);
2146
2147 /* Generate the data */
2148 float end_y = 0;
2149 std::vector<tcu::Vec4> quad_coordinates;
2150 float start_y = 0;
2151 float w = 1.0f;
2152
2153 if (n_instances != 1)
2154 {
2155 float delta = float(single_rt_height) / float(whole_rt_height);
2156
2157 /* Y coordinates are calculated in a vertex shader in multi-instanced case */
2158 start_y = 0.0f;
2159 end_y = 0.0f;
2160 w = delta;
2161 }
2162 else
2163 {
2164 start_y = -1;
2165 end_y = 1;
2166 }
2167
2168 /* X, Y coordinates: correspond to X & Y locations of the vertex.
2169 * Z coordinates: set to 0 if the vertex is located on top edge, otherwise set to 1.
2170 * W coordinate: stores the delta (single-instanced RT height / multi-instanced RT height).
2171 */
2172 float dx_multiplier = 1.5f; /* Default value for lines and line_strip output layout qualifiers */
2173 float dy_multiplier = 1.5f; /* Default value for lines and line_strip output layout qualifiers */
2174
2175 if (m_output_type == SHADER_OUTPUT_TYPE_TRIANGLE_STRIP)
2176 {
2177 dx_multiplier = 0.0f;
2178 dy_multiplier = 0.0f;
2179 }
2180
2181 quad_coordinates.push_back(tcu::Vec4(-1 + dx_multiplier * dx, start_y + dy_multiplier * dy, 0, w)); /* TL */
2182 quad_coordinates.push_back(tcu::Vec4(1 - dx_multiplier * dx, start_y + dy_multiplier * dy, 0, w)); /* TR */
2183 quad_coordinates.push_back(tcu::Vec4(1 - dx_multiplier * dx, end_y - dy_multiplier * dy, 1, w)); /* BR */
2184 quad_coordinates.push_back(tcu::Vec4(-1 + dx_multiplier * dx, end_y - dy_multiplier * dy, 1, w)); /* BL */
2185
2186 for (int n_line_segment = 0; n_line_segment < 4 /* edges */; ++n_line_segment)
2187 {
2188 /* Note we need to clamp coordinate indices here */
2189 int coordinate0_index = (4 + n_line_segment - 1) % 4; /* protect against negative modulo values */
2190 int coordinate1_index = (n_line_segment) % 4;
2191 int coordinate2_index = (n_line_segment + 1) % 4;
2192 int coordinate3_index = (n_line_segment + 2) % 4;
2193 const tcu::Vec4& coordinate0 = quad_coordinates[coordinate0_index];
2194 const tcu::Vec4& coordinate1 = quad_coordinates[coordinate1_index];
2195 const tcu::Vec4& coordinate2 = quad_coordinates[coordinate2_index];
2196 const tcu::Vec4& coordinate3 = quad_coordinates[coordinate3_index];
2197
2198 /* For GL_LINES, we need to explicitly define start & end-points for each segment.
2199 * For GL_LINE_STRIP, we only need to explicitly define first start point. Following
2200 * vertices define subsequent points making up the line strip.
2201 * For GL_LINE_LOOP, we need all the data we used for GL_LINE_STRIP excluding the very
2202 * last vertex.
2203 *
2204 * For GL_LINES_ADJACENCY_EXT, we extend GL_LINES data by vertices preceding and following points
2205 * that make up a single line segment.
2206 * For GL_LINE_STRIP_ADJACENCY_EXT, we extend GL_LINE_STRIP data by including a vertex preceding the
2207 * actual first vertex, and by including a vertex that follows the end vertex closing the line
2208 * strip.
2209 */
2210
2211 /* Preceding vertex */
2212 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT ||
2213 (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT && n_line_segment == 0))
2214 {
2215 *raw_array_data_traveller = coordinate0.x();
2216 raw_array_data_traveller++;
2217 *raw_array_data_traveller = coordinate0.y();
2218 raw_array_data_traveller++;
2219 *raw_array_data_traveller = coordinate0.z();
2220 raw_array_data_traveller++;
2221 *raw_array_data_traveller = coordinate0.w();
2222 raw_array_data_traveller++;
2223 }
2224
2225 /* Vertex 1 */
2226 if ((m_drawcall_mode != GL_LINE_STRIP && m_drawcall_mode != GL_LINE_STRIP_ADJACENCY_EXT &&
2227 m_drawcall_mode != GL_LINE_LOOP) ||
2228 ((m_drawcall_mode == GL_LINE_STRIP || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT ||
2229 m_drawcall_mode == GL_LINE_LOOP) &&
2230 n_line_segment == 0))
2231 {
2232 *raw_array_data_traveller = coordinate1.x();
2233 raw_array_data_traveller++;
2234 *raw_array_data_traveller = coordinate1.y();
2235 raw_array_data_traveller++;
2236 *raw_array_data_traveller = coordinate1.z();
2237 raw_array_data_traveller++;
2238 *raw_array_data_traveller = coordinate1.w();
2239 raw_array_data_traveller++;
2240 }
2241
2242 /* Vertex 2 */
2243 if (m_drawcall_mode != GL_LINE_LOOP || (m_drawcall_mode == GL_LINE_LOOP && n_line_segment != 3))
2244 {
2245 *raw_array_data_traveller = coordinate2.x();
2246 raw_array_data_traveller++;
2247 *raw_array_data_traveller = coordinate2.y();
2248 raw_array_data_traveller++;
2249 *raw_array_data_traveller = coordinate2.z();
2250 raw_array_data_traveller++;
2251 *raw_array_data_traveller = coordinate2.w();
2252 raw_array_data_traveller++;
2253 }
2254
2255 /* Following vertex */
2256 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT ||
2257 (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT && n_line_segment == 3))
2258 {
2259 *raw_array_data_traveller = coordinate3.x();
2260 raw_array_data_traveller++;
2261 *raw_array_data_traveller = coordinate3.y();
2262 raw_array_data_traveller++;
2263 *raw_array_data_traveller = coordinate3.z();
2264 raw_array_data_traveller++;
2265 *raw_array_data_traveller = coordinate3.w();
2266 raw_array_data_traveller++;
2267 }
2268 } /* for (all line segments) */
2269
2270 /* Generate unordered data:
2271 *
2272 * The way we organise data in this case is that:
2273 *
2274 * - For index data, start and end points are flipped for each line segment.
2275 * - For vertex data, vertex locations are stored to correspond to this order.
2276 *
2277 * We *DO NOT* modify the order in which we draw the line segments, since that could make the verification
2278 * process even more complex than it already is.
2279 */
2280 switch (m_drawcall_mode)
2281 {
2282 case GL_LINE_LOOP:
2283 {
2284 *unordered_arrays_data_size_ptr = *raw_arrays_data_size_ptr;
2285 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr / sizeof(float)];
2286
2287 *unordered_elements_data_size_ptr = sizeof(unsigned char) * 4 /* points */;
2288 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr];
2289
2290 for (unsigned int index = 0; index < 4 /* points */; ++index)
2291 {
2292 /* Gives 3-{0, 1, 2, 3} */
2293 int new_index = 3 - index;
2294
2295 /* Store index data */
2296 (*unordered_elements_data_ptr)[index] = (unsigned char)new_index;
2297
2298 /* Store vertex data */
2299 memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */,
2300 (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */);
2301 } /* for (all indices) */
2302
2303 break;
2304 }
2305
2306 case GL_LINE_STRIP:
2307 {
2308 *unordered_arrays_data_size_ptr = *raw_arrays_data_size_ptr;
2309 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr / sizeof(float)];
2310
2311 *unordered_elements_data_size_ptr = sizeof(unsigned char) * 5 /* points */;
2312 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr];
2313
2314 for (unsigned int index = 0; index < 5 /* points */; ++index)
2315 {
2316 /* Gives 4-{0, 1, 2, 3, 4} */
2317 int new_index = 4 - index;
2318
2319 /* Store index data */
2320 (*unordered_elements_data_ptr)[index] = (unsigned char)new_index;
2321
2322 /* Store vertex data */
2323 memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */,
2324 (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */);
2325 } /* for (all indices) */
2326
2327 break;
2328 }
2329
2330 case GL_LINES:
2331 {
2332 *unordered_arrays_data_size_ptr = sizeof(float) * 8 /* points */ * 4 /* components */;
2333 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr / sizeof(float)];
2334
2335 *unordered_elements_data_size_ptr = sizeof(unsigned char) * 8 /* points */;
2336 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr];
2337
2338 for (unsigned int index = 0; index < 8 /* points */; ++index)
2339 {
2340 /* Gives 7-{(1, 0), (3, 2), (5, 4), (7, 6)} */
2341 int new_index = 7 - ((index / 2) * 2 + (index + 1) % 2);
2342
2343 /* Store index data */
2344 (*unordered_elements_data_ptr)[index] = (unsigned char)new_index;
2345
2346 /* Store vertex data */
2347 memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */,
2348 (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */);
2349 } /* for (all indices) */
2350
2351 break;
2352 } /* case GL_LINES: */
2353
2354 case GL_LINES_ADJACENCY_EXT:
2355 case GL_LINE_STRIP_ADJACENCY_EXT:
2356 {
2357 /* For adjacency case, we may simplify the approach. Since the index data is now also going
2358 * to include references to adjacent vertices, we can use the same ordering as in raw arrays data.
2359 * Should the implementation misinterpret the data, it will treat adjacent vertex indices as actual
2360 * vertex indices, breaking the verification.
2361 */
2362 /* For array data, just point to unique vertex locations. Use the same order as in raw arrays data case
2363 * to simplify the vertex shader for the pass.
2364 **/
2365 *unordered_arrays_data_size_ptr = sizeof(float) * 4 /* points */ * 4 /* components */;
2366 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr / sizeof(float)];
2367
2368 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT)
2369 {
2370 *unordered_elements_data_size_ptr =
2371 sizeof(unsigned char) * 4 /* vertices per line segment */ * 4 /* line segments */;
2372 }
2373 else
2374 {
2375 *unordered_elements_data_size_ptr =
2376 sizeof(unsigned char) * (5 /* vertices making up a line strip */ + 2 /* start/end vertices */);
2377 }
2378
2379 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr];
2380
2381 for (int n = 0; n < 4; ++n)
2382 {
2383 (*unordered_arrays_data_ptr)[4 * n + 0] = quad_coordinates[n].x();
2384 (*unordered_arrays_data_ptr)[4 * n + 1] = quad_coordinates[n].y();
2385 (*unordered_arrays_data_ptr)[4 * n + 2] = quad_coordinates[n].z();
2386 (*unordered_arrays_data_ptr)[4 * n + 3] = quad_coordinates[n].w();
2387 }
2388
2389 /* For elements data, we just walk over the quad and make sure we turn a full circle */
2390 unsigned char* elements_data_traveller_ptr = *unordered_elements_data_ptr;
2391
2392 for (int n = 0; n < 4; ++n)
2393 {
2394 int component0_index = (n + 4 - 1) % 4; /* protect against underflow */
2395 int component1_index = (n) % 4;
2396 int component2_index = (n + 1) % 4;
2397 int component3_index = (n + 2) % 4;
2398
2399 if (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)
2400 {
2401 /* Vertex adjacent to start vertex - include only at start */
2402 if (n == 0)
2403 {
2404 *elements_data_traveller_ptr = (unsigned char)component0_index;
2405
2406 ++elements_data_traveller_ptr;
2407 }
2408
2409 /* Vertex index */
2410 *elements_data_traveller_ptr = (unsigned char)component1_index;
2411
2412 ++elements_data_traveller_ptr;
2413
2414 /* End vertex and the adjacent vertex - include only for final iteration */
2415 if (n == 3)
2416 {
2417 /* End vertex */
2418 *elements_data_traveller_ptr = (unsigned char)component2_index;
2419
2420 ++elements_data_traveller_ptr;
2421
2422 /* Adjacent vertex */
2423 *elements_data_traveller_ptr = (unsigned char)component3_index;
2424
2425 ++elements_data_traveller_ptr;
2426 }
2427 }
2428 else
2429 {
2430 /* GL_LINES_ADJACENCY_EXT */
2431 *elements_data_traveller_ptr = (unsigned char)component0_index;
2432 ++elements_data_traveller_ptr;
2433 *elements_data_traveller_ptr = (unsigned char)component1_index;
2434 ++elements_data_traveller_ptr;
2435 *elements_data_traveller_ptr = (unsigned char)component2_index;
2436 ++elements_data_traveller_ptr;
2437 *elements_data_traveller_ptr = (unsigned char)component3_index;
2438 ++elements_data_traveller_ptr;
2439 }
2440 }
2441
2442 break;
2443 } /* case GL_LINES: */
2444
2445 default:
2446 {
2447 TCU_FAIL("Unrecognized draw call mode");
2448 }
2449 } /* switch (m_drawcall_mode) */
2450 } /* for (both cases) */
2451 }
2452
2453 /** Destructor. */
~GeometryShaderRenderingLinesCase()2454 GeometryShaderRenderingLinesCase::~GeometryShaderRenderingLinesCase()
2455 {
2456 if (m_raw_array_instanced_data != NULL)
2457 {
2458 delete[] m_raw_array_instanced_data;
2459
2460 m_raw_array_instanced_data = NULL;
2461 }
2462
2463 if (m_raw_array_noninstanced_data != NULL)
2464 {
2465 delete[] m_raw_array_noninstanced_data;
2466
2467 m_raw_array_noninstanced_data = NULL;
2468 }
2469
2470 if (m_unordered_array_instanced_data != NULL)
2471 {
2472 delete[] m_unordered_array_instanced_data;
2473
2474 m_unordered_array_instanced_data = NULL;
2475 }
2476
2477 if (m_unordered_array_noninstanced_data != NULL)
2478 {
2479 delete[] m_unordered_array_noninstanced_data;
2480
2481 m_unordered_array_noninstanced_data = NULL;
2482 }
2483
2484 if (m_unordered_elements_instanced_data != NULL)
2485 {
2486 delete[] m_unordered_elements_instanced_data;
2487
2488 m_unordered_elements_instanced_data = NULL;
2489 }
2490
2491 if (m_unordered_elements_noninstanced_data != NULL)
2492 {
2493 delete[] m_unordered_elements_noninstanced_data;
2494
2495 m_unordered_elements_noninstanced_data = NULL;
2496 }
2497 }
2498
2499 /** Retrieves amount of instances that should be drawn with glDraw*Elements() calls.
2500 *
2501 * @return As per description.
2502 **/
getAmountOfDrawInstances()2503 unsigned int GeometryShaderRenderingLinesCase::getAmountOfDrawInstances()
2504 {
2505 return 4;
2506 }
2507
2508 /** Retrieves amount of indices that should be used for rendering a single instance
2509 * (glDraw*Elements() calls only)
2510 *
2511 * @return As per description.
2512 */
getAmountOfElementsPerInstance()2513 unsigned int GeometryShaderRenderingLinesCase::getAmountOfElementsPerInstance()
2514 {
2515 unsigned int result = 0;
2516
2517 switch (m_drawcall_mode)
2518 {
2519 case GL_LINE_LOOP:
2520 result = 4;
2521 break;
2522 case GL_LINE_STRIP:
2523 result = 5;
2524 break;
2525 case GL_LINE_STRIP_ADJACENCY_EXT:
2526 result = 7;
2527 break;
2528 case GL_LINES:
2529 result = 8;
2530 break;
2531 case GL_LINES_ADJACENCY_EXT:
2532 result = 16;
2533 break;
2534
2535 default:
2536 {
2537 TCU_FAIL("Unrecognized draw call mode");
2538 }
2539 } /* switch (m_drawcall_mode) */
2540
2541 return result;
2542 }
2543
2544 /** Retrieves amount of vertices that should be used for rendering a single instance
2545 * (glDrawArrays*() calls only)
2546 *
2547 * @return As per description.
2548 **/
getAmountOfVerticesPerInstance()2549 unsigned int GeometryShaderRenderingLinesCase::getAmountOfVerticesPerInstance()
2550 {
2551 unsigned int result = 0;
2552
2553 switch (m_drawcall_mode)
2554 {
2555 case GL_LINE_LOOP:
2556 result = 4;
2557 break;
2558 case GL_LINE_STRIP:
2559 result = 5;
2560 break;
2561 case GL_LINE_STRIP_ADJACENCY_EXT:
2562 result = 7;
2563 break;
2564 case GL_LINES:
2565 result = 8;
2566 break;
2567 case GL_LINES_ADJACENCY_EXT:
2568 result = 16;
2569 break;
2570
2571 default:
2572 {
2573 TCU_FAIL("Unrecognized draw call mode");
2574 }
2575 } /* switch (m_drawcall_mode) */
2576
2577 return result;
2578 }
2579
2580 /** Draw call mode that should be used glDraw*() calls.
2581 *
2582 * @return As per description.
2583 **/
getDrawCallMode()2584 glw::GLenum GeometryShaderRenderingLinesCase::getDrawCallMode()
2585 {
2586 return m_drawcall_mode;
2587 }
2588
2589 /** Source code for a fragment shader that should be used for the test.
2590 *
2591 * @return As per description.
2592 **/
getFragmentShaderCode()2593 std::string GeometryShaderRenderingLinesCase::getFragmentShaderCode()
2594 {
2595 static std::string fs_code = "${VERSION}\n"
2596 "\n"
2597 "precision highp float;\n"
2598 "\n"
2599 "in vec4 gs_fs_color;\n"
2600 "out vec4 result;\n"
2601 "\n"
2602 "void main()\n"
2603 "{\n"
2604 " result = gs_fs_color;\n"
2605 "}\n";
2606
2607 return fs_code;
2608 }
2609
2610 /** Source code for a geometry shader that should be used for the test.
2611 *
2612 * @return As per description.
2613 **/
getGeometryShaderCode()2614 std::string GeometryShaderRenderingLinesCase::getGeometryShaderCode()
2615 {
2616 static const char* lines_in_line_strip_out_gs_code_preamble = "${VERSION}\n"
2617 "\n"
2618 "${GEOMETRY_SHADER_ENABLE}\n"
2619 "\n"
2620 "layout(lines) in;\n"
2621 "layout(line_strip, max_vertices=6) out;\n"
2622 "\n"
2623 "#define N_VERTICES_IN (2)\n"
2624 "#define N_VERTEX0 (0)\n"
2625 "#define N_VERTEX1 (1)\n"
2626 "\n";
2627
2628 static const char* lines_adjacency_in_line_strip_out_gs_code_preamble = "${VERSION}\n"
2629 "\n"
2630 "${GEOMETRY_SHADER_ENABLE}\n"
2631 "\n"
2632 "layout(lines_adjacency) in;\n"
2633 "layout(line_strip, max_vertices=6) out;\n"
2634 "\n"
2635 "#define N_VERTICES_IN (4)\n"
2636 "#define N_VERTEX0 (1)\n"
2637 "#define N_VERTEX1 (2)\n"
2638 "\n";
2639
2640 static const char* lines_gs_code_main = "\n"
2641 "in vec4 vs_gs_color[N_VERTICES_IN];\n"
2642 "out vec4 gs_fs_color;\n"
2643 "\n"
2644 "uniform ivec2 renderingTargetSize;\n"
2645 "\n"
2646 "void main()\n"
2647 "{\n"
2648 " float dx = float(2.0) / float(renderingTargetSize.x);\n"
2649 " float dy = float(2.0) / float(renderingTargetSize.y);\n"
2650 "\n"
2651 " vec4 start_pos = gl_in[N_VERTEX0].gl_Position;\n"
2652 " vec4 end_pos = gl_in[N_VERTEX1].gl_Position;\n"
2653 " vec4 start_col = vs_gs_color[N_VERTEX0];\n"
2654 " vec4 end_col = vs_gs_color[N_VERTEX1];\n"
2655 "\n"
2656 /* Determine if this is a horizontal or vertical edge */
2657 " if (start_pos.x != end_pos.x)\n"
2658 " {\n"
2659 /* Bottom line segment */
2660 " gl_Position = vec4(-1.0, start_pos.y + dy, 0, 1);\n"
2661 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2662 " EmitVertex();\n"
2663 "\n"
2664 " gl_Position = vec4(1.0, end_pos.y + dy, 0, 1);\n"
2665 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2666 " EmitVertex();\n"
2667 " EndPrimitive();\n"
2668 /* Middle line segment */
2669 " gl_Position = vec4(-1.0, start_pos.y, 0, 1);\n"
2670 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2671 " EmitVertex();\n"
2672 "\n"
2673 " gl_Position = vec4(1.0, end_pos.y, 0, 1);\n"
2674 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2675 " EmitVertex();\n"
2676 " EndPrimitive();\n"
2677 /* Top line segment */
2678 " gl_Position = vec4(-1.0, start_pos.y - dy, 0, 1);\n"
2679 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2680 " EmitVertex();\n"
2681 "\n"
2682 " gl_Position = vec4(1.0, end_pos.y - dy, 0, 1);\n"
2683 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2684 " EmitVertex();\n"
2685 " EndPrimitive();\n"
2686 " }\n"
2687 " else\n"
2688 " {\n"
2689 /* Left line segment */
2690 " gl_Position = vec4(start_pos.x - dx, start_pos.y, 0, 1);\n"
2691 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2692 " EmitVertex();\n"
2693 "\n"
2694 " gl_Position = vec4(end_pos.x - dx, end_pos.y, 0, 1);\n"
2695 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2696 " EmitVertex();\n"
2697 " EndPrimitive();\n"
2698 /* Middle line segment */
2699 " gl_Position = vec4(start_pos.x, start_pos.y, 0, 1);\n"
2700 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2701 " EmitVertex();\n"
2702 "\n"
2703 " gl_Position = vec4(end_pos.x, end_pos.y, 0, 1);\n"
2704 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2705 " EmitVertex();\n"
2706 " EndPrimitive();\n"
2707 /* Right line segment */
2708 " gl_Position = vec4(start_pos.x + dx, start_pos.y, 0, 1);\n"
2709 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2710 " EmitVertex();\n"
2711 "\n"
2712 " gl_Position = vec4(end_pos.x + dx, end_pos.y, 0, 1);\n"
2713 " gs_fs_color = mix(start_col, end_col, 0.5);\n"
2714 " EmitVertex();\n"
2715 " EndPrimitive();\n"
2716 " }\n"
2717 "}\n";
2718
2719 static const char* lines_in_points_out_gs_code_preamble = "${VERSION}\n"
2720 "\n"
2721 "${GEOMETRY_SHADER_ENABLE}\n"
2722 "\n"
2723 "layout(lines) in;\n"
2724 "layout(points, max_vertices=72) out;\n"
2725 "\n"
2726 "#define N_VERTEX0 (0)\n"
2727 "#define N_VERTEX1 (1)\n"
2728 "#define N_VERTICES_IN (2)\n"
2729 "\n";
2730
2731 static const char* lines_adjacency_in_points_out_gs_code_preamble = "${VERSION}\n"
2732 "\n"
2733 "${GEOMETRY_SHADER_ENABLE}\n"
2734 "\n"
2735 "layout(lines_adjacency) in;\n"
2736 "layout(points, max_vertices=72) out;\n"
2737 "\n"
2738 "#define N_VERTEX0 (1)\n"
2739 "#define N_VERTEX1 (2)\n"
2740 "#define N_VERTICES_IN (4)\n"
2741 "\n";
2742
2743 static const char* points_gs_code_main = "\n"
2744 "in vec4 vs_gs_color[N_VERTICES_IN];\n"
2745 "out vec4 gs_fs_color;\n"
2746 "\n"
2747 "uniform ivec2 renderingTargetSize;\n"
2748 "\n"
2749 "void main()\n"
2750 "{\n"
2751 " float dx = float(2.0) / float(renderingTargetSize.x);\n"
2752 " float dy = float(2.0) / float(renderingTargetSize.y);\n"
2753 "\n"
2754 " vec4 start_pos = gl_in[N_VERTEX0].gl_Position;\n"
2755 " vec4 end_pos = gl_in[N_VERTEX1].gl_Position;\n"
2756 " vec4 start_col = vs_gs_color[N_VERTEX0];\n"
2757 " vec4 end_col = vs_gs_color[N_VERTEX1];\n"
2758 " vec4 delta_col = (end_col - start_col) / vec4(7.0);\n"
2759 " vec4 delta_pos = (end_pos - start_pos) / vec4(7.0);\n"
2760 "\n"
2761 " for (int n_point = 0; n_point < 8; ++n_point)\n"
2762 " {\n"
2763 " vec4 ref_color = start_col + vec4(float(n_point)) * delta_col;\n"
2764 " vec4 ref_pos = start_pos + vec4(float(n_point)) * delta_pos;\n"
2765 "\n"
2766 /* TL */
2767 " gl_Position = ref_pos + vec4(-dx, -dy, 0, 0);\n"
2768 " gs_fs_color = ref_color;\n"
2769 " EmitVertex();\n"
2770 /* TM */
2771 " gl_Position = ref_pos + vec4(0, -dy, 0, 0);\n"
2772 " gs_fs_color = ref_color;\n"
2773 " EmitVertex();\n"
2774 /* TR */
2775 " gl_Position = ref_pos + vec4(dx, -dy, 0, 0);\n"
2776 " gs_fs_color = ref_color;\n"
2777 " EmitVertex();\n"
2778 /* ML */
2779 " gl_Position = ref_pos + vec4(-dx, 0, 0, 0);\n"
2780 " gs_fs_color = ref_color;\n"
2781 " EmitVertex();\n"
2782 /* MM */
2783 " gl_Position = ref_pos + vec4(0, 0, 0, 0);\n"
2784 " gs_fs_color = ref_color;\n"
2785 " EmitVertex();\n"
2786 /* MR */
2787 " gl_Position = ref_pos + vec4(dx, 0, 0, 0);\n"
2788 " gs_fs_color = ref_color;\n"
2789 " EmitVertex();\n"
2790 /* BL */
2791 " gl_Position = ref_pos + vec4(-dx, dy, 0, 0);\n"
2792 " gs_fs_color = ref_color;\n"
2793 " EmitVertex();\n"
2794 /* BM */
2795 " gl_Position = ref_pos + vec4(0, dy, 0, 0);\n"
2796 " gs_fs_color = ref_color;\n"
2797 " EmitVertex();\n"
2798 /* BR */
2799 " gl_Position = ref_pos + vec4(dx, dy, 0, 0);\n"
2800 " gs_fs_color = ref_color;\n"
2801 " EmitVertex();\n"
2802 " }\n"
2803 "}\n";
2804
2805 static const char* lines_adjacency_in_triangle_strip_out_gs_code_preamble =
2806 "${VERSION}\n"
2807 "\n"
2808 "${GEOMETRY_SHADER_ENABLE}\n"
2809 "\n"
2810 "layout(lines_adjacency) in;\n"
2811 "layout(triangle_strip, max_vertices=3) out;\n"
2812 "\n"
2813 "#define N_VERTEX0 (1)\n"
2814 "#define N_VERTEX1 (2)\n"
2815 "#define N_VERTICES_IN (4)\n";
2816
2817 static const char* lines_in_triangle_strip_out_gs_code_preamble = "${VERSION}\n"
2818 "\n"
2819 "${GEOMETRY_SHADER_ENABLE}\n"
2820 "\n"
2821 "layout(lines) in;\n"
2822 "layout(triangle_strip, max_vertices=3) out;\n"
2823 "\n"
2824 "#define N_VERTEX0 (0)\n"
2825 "#define N_VERTEX1 (1)\n"
2826 "#define N_VERTICES_IN (2)\n";
2827
2828 static const char* triangles_gs_code_main = "flat in int instance_id[N_VERTICES_IN];\n"
2829 " in vec4 vs_gs_color[N_VERTICES_IN];\n"
2830 " out vec4 gs_fs_color;\n"
2831 "\n"
2832 "uniform ivec2 renderingTargetSize;\n"
2833 "\n"
2834 "void main()\n"
2835 "{\n"
2836 " float dx = float(1.5) / float(renderingTargetSize.x);\n"
2837 " float dy = float(1.5) / float(renderingTargetSize.y);\n"
2838 "\n"
2839 " gl_Position = gl_in[N_VERTEX0].gl_Position;\n"
2840 " gs_fs_color = vs_gs_color[N_VERTEX0];\n"
2841 " EmitVertex();\n"
2842 "\n"
2843 " gl_Position = gl_in[N_VERTEX1].gl_Position;\n"
2844 " gs_fs_color = vs_gs_color[N_VERTEX0];\n"
2845 " EmitVertex();\n"
2846 "\n"
2847 " if (renderingTargetSize.y == 45 /* block size */)\n"
2848 " {\n"
2849 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
2850 " }\n"
2851 " else\n"
2852 " {\n"
2853 /* Each block takes 1/4th of the total render target.
2854 * Third vertex should be placed in the middle of the block.
2855 */
2856 " float y = -1.0 + 1.0 / 4.0 + float(instance_id[0]) * 0.5;\n"
2857 "\n"
2858 " gl_Position = vec4(0.0, y, 0.0, 1.0);\n"
2859 " }\n"
2860 "\n"
2861 " gs_fs_color = vs_gs_color[N_VERTEX0];\n"
2862 " EmitVertex();\n"
2863 "\n"
2864 " EndPrimitive();\n"
2865 "}\n";
2866 std::string result;
2867
2868 switch (m_output_type)
2869 {
2870 case SHADER_OUTPUT_TYPE_LINE_STRIP:
2871 {
2872 std::stringstream lines_adjacency_gs_code_stringstream;
2873 std::string lines_adjacency_gs_code_string;
2874 std::stringstream lines_gs_code_stringstream;
2875 std::string lines_gs_code_string;
2876
2877 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)
2878 {
2879 /* First request for lines_adjacency GS, form the string */
2880 lines_adjacency_gs_code_stringstream << lines_adjacency_in_line_strip_out_gs_code_preamble
2881 << lines_gs_code_main;
2882
2883 lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str();
2884 result = lines_adjacency_gs_code_string;
2885 }
2886 else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP)
2887 {
2888 /* First request for lines GS, form the string */
2889 lines_gs_code_stringstream << lines_in_line_strip_out_gs_code_preamble << lines_gs_code_main;
2890
2891 lines_gs_code_string = lines_gs_code_stringstream.str();
2892 result = lines_gs_code_string;
2893 }
2894 else
2895 {
2896 TCU_FAIL("Unrecognized draw call mode");
2897 }
2898
2899 break;
2900 }
2901
2902 case SHADER_OUTPUT_TYPE_POINTS:
2903 {
2904 std::stringstream lines_adjacency_gs_code_stringstream;
2905 std::string lines_adjacency_gs_code_string;
2906 std::stringstream lines_gs_code_stringstream;
2907 std::string lines_gs_code_string;
2908
2909 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)
2910 {
2911 /* First request for lines_adjacency GS, form the string */
2912 lines_adjacency_gs_code_stringstream << lines_adjacency_in_points_out_gs_code_preamble
2913 << points_gs_code_main;
2914
2915 lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str();
2916 result = lines_adjacency_gs_code_string;
2917 }
2918 else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP)
2919 {
2920 /* First request for lines GS, form the string */
2921 lines_gs_code_stringstream << lines_in_points_out_gs_code_preamble << points_gs_code_main;
2922
2923 lines_gs_code_string = lines_gs_code_stringstream.str();
2924 result = lines_gs_code_string;
2925 }
2926 else
2927 {
2928 TCU_FAIL("Unrecognized draw call mode");
2929 }
2930
2931 break;
2932 }
2933
2934 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
2935 {
2936 std::stringstream lines_adjacency_gs_code_stringstream;
2937 std::string lines_adjacency_gs_code_string;
2938 std::stringstream lines_gs_code_stringstream;
2939 std::string lines_gs_code_string;
2940
2941 if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)
2942 {
2943 /* First request for lines_adjacency GS, form the string */
2944 lines_adjacency_gs_code_stringstream << lines_adjacency_in_triangle_strip_out_gs_code_preamble
2945 << triangles_gs_code_main;
2946
2947 lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str();
2948 result = lines_adjacency_gs_code_string;
2949 }
2950 else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP)
2951 {
2952 /* First request for lines GS, form the string */
2953 lines_gs_code_stringstream << lines_in_triangle_strip_out_gs_code_preamble << triangles_gs_code_main;
2954
2955 lines_gs_code_string = lines_gs_code_stringstream.str();
2956 result = lines_gs_code_string;
2957 }
2958 else
2959 {
2960 TCU_FAIL("Unrecognized draw call mode");
2961 }
2962
2963 break;
2964 }
2965
2966 default:
2967 {
2968 TCU_FAIL("Requested shader output layout qualifier is unsupported");
2969 }
2970 } /* switch (m_output_type) */
2971
2972 return result;
2973 }
2974
2975 /** Returns amount of bytes that should be allocated for a buffer object to hold
2976 * vertex data to be used for glDrawArrays*() calls.
2977 *
2978 * @param instanced True if the data is to be used in regard to instanced draw calls,
2979 * false otherwise.
2980 *
2981 * @return As per description.
2982 **/
getRawArraysDataBufferSize(bool instanced)2983 glw::GLuint GeometryShaderRenderingLinesCase::getRawArraysDataBufferSize(bool instanced)
2984 {
2985 return instanced ? m_raw_array_instanced_data_size : m_raw_array_noninstanced_data_size;
2986 }
2987
2988 /** Returns vertex data for the test. Only to be used for glDrawArrays*() calls.
2989 *
2990 * @param instanced True if the data is to be used in regard to instanced draw calls,
2991 * false otherwise.
2992 *
2993 * @return As per description.
2994 **/
getRawArraysDataBuffer(bool instanced)2995 const void* GeometryShaderRenderingLinesCase::getRawArraysDataBuffer(bool instanced)
2996 {
2997 return instanced ? m_raw_array_instanced_data : m_raw_array_noninstanced_data;
2998 }
2999
3000 /** Retrieves resolution of off-screen rendering buffer that should be used for the test.
3001 *
3002 * @param n_instances Amount of draw call instances this render target will be used for.
3003 * @param out_width Deref will be used to store rendertarget's width. Must not be NULL.
3004 * @param out_height Deref will be used to store rendertarget's height. Must not be NULL.
3005 **/
getRenderTargetSize(unsigned int n_instances,unsigned int * out_width,unsigned int * out_height)3006 void GeometryShaderRenderingLinesCase::getRenderTargetSize(unsigned int n_instances, unsigned int* out_width,
3007 unsigned int* out_height)
3008 {
3009 switch (m_output_type)
3010 {
3011 case SHADER_OUTPUT_TYPE_LINE_STRIP:
3012 case SHADER_OUTPUT_TYPE_POINTS:
3013 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
3014 {
3015 /* For SHADER_OUTPUT_TYPE_POINTS:
3016 * An edge size of 45px should be used. Given that each input will generate a 3x3 block,
3017 * this should give us a delta of 3px between the "quads".
3018 *
3019 * For instanced draw calls, use a delta of 3px as well.
3020 *
3021 * For SHADER_OUTPUT_TYPE_LINE_STRIP:
3022 * Each rectangle outline will take a 45x45 block. No vertical delta needs to be used.
3023 *
3024 * For SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
3025 * Each combination of 4 triangles makes up a triangles that takes 45x45 area.
3026 * No vertical delta needs to be used.
3027 */
3028 *out_width = 3 /* 'pixel' size */ * 8 + 3 /* Delta size */ * 7;
3029 *out_height = (3 /* 'pixel' size */ * 8 + 3 /* Delta size */ * 7) * n_instances;
3030
3031 break;
3032 }
3033
3034 default:
3035 {
3036 TCU_FAIL("Unsupported shader output type");
3037 }
3038 } /* switch (m_output_type) */
3039 }
3040
3041 /** Returns amount of bytes that should be allocated for a buffer object to hold
3042 * vertex data to be used for glDrawElements*() calls.
3043 *
3044 * @param instanced true if the call is being made for an instanced draw call, false otherwise.
3045 *
3046 * @return As per description.
3047 **/
getUnorderedArraysDataBufferSize(bool instanced)3048 glw::GLuint GeometryShaderRenderingLinesCase::getUnorderedArraysDataBufferSize(bool instanced)
3049 {
3050 return (instanced) ? m_unordered_array_instanced_data_size : m_unordered_array_noninstanced_data_size;
3051 }
3052
3053 /** Returns vertex data for the test. Only to be used for glDrawElements*() calls.
3054 *
3055 * @param instanced true if the call is being made for an instanced draw call, false otherwise.
3056 *
3057 * @return As per description.
3058 **/
getUnorderedArraysDataBuffer(bool instanced)3059 const void* GeometryShaderRenderingLinesCase::getUnorderedArraysDataBuffer(bool instanced)
3060 {
3061 return instanced ? m_unordered_array_instanced_data : m_unordered_array_noninstanced_data;
3062 }
3063
3064 /** Returns amount of bytes that should be allocated for a buffer object to hold
3065 * index data to be used for glDrawElements*() calls.
3066 *
3067 * @param instanced true if the call is being made for an instanced draw call, false otherwise.
3068 *
3069 * @return As per description.
3070 **/
getUnorderedElementsDataBufferSize(bool instanced)3071 glw::GLuint GeometryShaderRenderingLinesCase::getUnorderedElementsDataBufferSize(bool instanced)
3072 {
3073 return instanced ? m_unordered_elements_instanced_data_size : m_unordered_elements_noninstanced_data_size;
3074 }
3075
3076 /** Returns index data for the test. Only to be used for glDrawElements*() calls.
3077 *
3078 * @param instanced true if the call is being made for an instanced draw call, false otherwise.
3079 *
3080 **/
getUnorderedElementsDataBuffer(bool instanced)3081 const void* GeometryShaderRenderingLinesCase::getUnorderedElementsDataBuffer(bool instanced)
3082 {
3083 return instanced ? m_unordered_elements_instanced_data : m_unordered_elements_noninstanced_data;
3084 }
3085
3086 /** Returns type of the index, to be used for glDrawElements*() calls.
3087 *
3088 * @return As per description.
3089 **/
getUnorderedElementsDataType()3090 glw::GLenum GeometryShaderRenderingLinesCase::getUnorderedElementsDataType()
3091 {
3092 return GL_UNSIGNED_BYTE;
3093 }
3094
3095 /** Retrieves maximum index value. To be used for glDrawRangeElements() test only.
3096 *
3097 * @return As per description.
3098 **/
getUnorderedElementsMaxIndex()3099 glw::GLubyte GeometryShaderRenderingLinesCase::getUnorderedElementsMaxIndex()
3100 {
3101 return m_unordered_elements_max_index;
3102 }
3103
3104 /** Retrieves minimum index value. To be used for glDrawRangeElements() test only.
3105 *
3106 * @return As per description.
3107 **/
getUnorderedElementsMinIndex()3108 glw::GLubyte GeometryShaderRenderingLinesCase::getUnorderedElementsMinIndex()
3109 {
3110 return m_unordered_elements_min_index;
3111 }
3112
3113 /** Retrieves vertex shader code to be used for the test.
3114 *
3115 * @return As per description.
3116 **/
getVertexShaderCode()3117 std::string GeometryShaderRenderingLinesCase::getVertexShaderCode()
3118 {
3119 static std::string vs_code =
3120 "${VERSION}\n"
3121 "\n"
3122 " in vec4 position;\n"
3123 " uniform bool is_indexed_draw_call;\n"
3124 " uniform bool is_gl_lines_adjacency_draw_call;\n"
3125 " uniform bool is_gl_line_strip_adjacency_draw_call;\n"
3126 " uniform bool is_gl_lines_draw_call;\n"
3127 " uniform bool is_gl_line_loop_draw_call;\n"
3128 " uniform ivec2 renderingTargetSize;\n"
3129 "flat out int instance_id;\n"
3130 " out vec4 vs_gs_color;\n"
3131 "\n"
3132 "void main()\n"
3133 "{\n"
3134 " instance_id = gl_InstanceID;\n"
3135 "\n"
3136 /* non-instanced */
3137 " if (renderingTargetSize.y == 45 /* block size */)\n"
3138 " {\n"
3139 " gl_Position = position;\n"
3140 " }\n"
3141 " else\n"
3142 " {\n"
3143 " bool represents_top_edge = (position.z == 0.0);\n"
3144 " float delta = position.w;\n"
3145 " float y = 0.0;\n"
3146 "\n"
3147 " if (represents_top_edge)\n"
3148 " {\n"
3149 /* top vertices */
3150 " y = position.y + float(gl_InstanceID) * delta * 2.0 - 1.0;\n"
3151 " }\n"
3152 " else\n"
3153 " {\n"
3154 " y = position.y + float(gl_InstanceID) * delta * 2.0 - 1.0 + delta * 2.0;\n"
3155 /* bottom vertices */
3156 " }\n"
3157 "\n"
3158 " gl_Position = vec4(position.x,\n"
3159 " y,\n"
3160 " position.z,\n"
3161 " 1.0);\n"
3162 " }\n"
3163 "\n"
3164 " vs_gs_color = vec4(0, 0, 0, 0);\n"
3165 "\n"
3166 " if (is_gl_line_loop_draw_call)\n"
3167 " {\n"
3168 /* GL_LINE_LOOP */
3169 " if (!is_indexed_draw_call)\n"
3170 " {\n"
3171 " switch(gl_VertexID)\n"
3172 " {\n"
3173 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3174 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3175 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3176 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3177 " }\n"
3178 " }\n"
3179 " else\n"
3180 " {\n"
3181 " switch(gl_VertexID)\n"
3182 " {\n"
3183 " case 3: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3184 " case 0: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3185 " case 1: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3186 " case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3187 " }\n"
3188 " }\n"
3189 " }\n"
3190 " else\n"
3191 " if (is_gl_line_strip_adjacency_draw_call)\n"
3192 " {\n"
3193 /* GL_LINE_STRIP_ADJACENCY_EXT */
3194 " if (!is_indexed_draw_call)\n"
3195 " {\n"
3196 " switch(gl_VertexID)\n"
3197 " {\n"
3198 " case 1:\n"
3199 " case 5: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3200 " case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3201 " case 3: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3202 " case 0:\n"
3203 " case 4: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3204 " }\n"
3205 " }\n"
3206 " else\n"
3207 " {\n"
3208 " switch(gl_VertexID)\n"
3209 " {\n"
3210 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3211 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3212 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3213 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3214 " }\n"
3215 " }\n"
3216 " }\n"
3217 " else\n"
3218 " if (is_gl_lines_adjacency_draw_call)\n"
3219 " {\n"
3220 /* GL_LINES_ADJACENCY_EXT */
3221 " if (!is_indexed_draw_call)\n"
3222 " {\n"
3223 " switch(gl_VertexID)\n"
3224 " {\n"
3225 " case 1:\n"
3226 " case 14: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3227 "\n"
3228 " case 2:\n"
3229 " case 5: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3230
3231 " case 6:\n"
3232 " case 9: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3233
3234 " case 10:\n"
3235 " case 13: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3236 " }\n"
3237 " }\n"
3238 " else\n"
3239 " {\n"
3240 " switch(gl_VertexID)\n"
3241 " {\n"
3242 " case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3243 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3244 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3245 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3246 " }\n"
3247 " }\n"
3248 " }\n"
3249 " else\n"
3250 " if (is_gl_lines_draw_call)\n"
3251 " {\n"
3252 /* GL_LINES */
3253 " if (!is_indexed_draw_call)\n"
3254 " {\n"
3255 " switch(gl_VertexID)\n"
3256 " {\n"
3257 " case 0:\n"
3258 " case 7: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3259 "\n"
3260 " case 1:\n"
3261 " case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3262
3263 " case 3:\n"
3264 " case 4: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3265
3266 " case 5:\n"
3267 " case 6: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3268 " }\n"
3269 " }\n"
3270 " else\n"
3271 " {\n"
3272 " switch(gl_VertexID)\n"
3273 " {\n"
3274 " case 6:\n"
3275 " case 1: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3276 "\n"
3277 " case 7:\n"
3278 " case 4: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3279
3280 " case 5:\n"
3281 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3282
3283 " case 3:\n"
3284 " case 0: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3285 " }\n"
3286 " }\n"
3287 " }\n"
3288 " else\n"
3289 " {\n"
3290 /* GL_LINE_STRIP */
3291 " if (!is_indexed_draw_call)\n"
3292 " {\n"
3293 " switch(gl_VertexID)\n"
3294 " {\n"
3295 " case 0:\n"
3296 " case 4: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3297 " case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3298 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3299 " case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3300 " }\n"
3301 " }\n"
3302 " else\n"
3303 " {\n"
3304 " switch(gl_VertexID)\n"
3305 " {\n"
3306 " case 0:\n"
3307 " case 4: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3308 " case 1: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3309 " case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3310 " case 3: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3311 " }\n"
3312 " }\n"
3313 " }\n"
3314 "}\n";
3315
3316 std::string result;
3317
3318 switch (m_output_type)
3319 {
3320 case SHADER_OUTPUT_TYPE_LINE_STRIP:
3321 case SHADER_OUTPUT_TYPE_POINTS:
3322 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
3323 {
3324 result = vs_code;
3325
3326 break;
3327 }
3328
3329 default:
3330 {
3331 TCU_FAIL("Unsupported shader output type used");
3332 }
3333 } /* switch (m_output_type) */
3334
3335 return result;
3336 }
3337
3338 /** Sets test-specific uniforms for a program object that is then used for the draw call.
3339 *
3340 * @param drawcall_type Type of the draw call that is to follow right after this function is called.
3341 **/
setUniformsBeforeDrawCall(_draw_call_type drawcall_type)3342 void GeometryShaderRenderingLinesCase::setUniformsBeforeDrawCall(_draw_call_type drawcall_type)
3343 {
3344 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3345 glw::GLint is_gl_line_loop_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_gl_line_loop_draw_call");
3346 glw::GLint is_gl_line_strip_adjacency_draw_call_uniform_location =
3347 gl.getUniformLocation(m_po_id, "is_gl_line_strip_adjacency_draw_call");
3348 glw::GLint is_gl_lines_adjacency_draw_call_uniform_location =
3349 gl.getUniformLocation(m_po_id, "is_gl_lines_adjacency_draw_call");
3350 glw::GLint is_gl_lines_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_gl_lines_draw_call");
3351 glw::GLint is_indexed_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_indexed_draw_call");
3352
3353 TCU_CHECK(is_gl_line_loop_draw_call_uniform_location != -1);
3354 TCU_CHECK(is_gl_line_strip_adjacency_draw_call_uniform_location != -1);
3355 TCU_CHECK(is_gl_lines_adjacency_draw_call_uniform_location != -1);
3356 TCU_CHECK(is_gl_lines_draw_call_uniform_location != -1);
3357 TCU_CHECK(is_indexed_draw_call_uniform_location != -1);
3358
3359 gl.uniform1i(is_indexed_draw_call_uniform_location, (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
3360 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED ||
3361 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS));
3362 gl.uniform1i(is_gl_line_loop_draw_call_uniform_location, (m_drawcall_mode == GL_LINE_LOOP));
3363 gl.uniform1i(is_gl_line_strip_adjacency_draw_call_uniform_location,
3364 (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT));
3365 gl.uniform1i(is_gl_lines_adjacency_draw_call_uniform_location, (m_drawcall_mode == GL_LINES_ADJACENCY_EXT));
3366 gl.uniform1i(is_gl_lines_draw_call_uniform_location, (m_drawcall_mode == GL_LINES));
3367 }
3368
3369 /** Verifies that the rendered data is correct.
3370 *
3371 * @param drawcall_type Type of the draw call that was used to render the geometry.
3372 * @param instance_id Instance ID to be verified. Use 0 for non-instanced draw calls.
3373 * @param data Contents of the rendertarget after the test has finished rendering.
3374 **/
verify(_draw_call_type drawcall_type,unsigned int instance_id,const unsigned char * data)3375 void GeometryShaderRenderingLinesCase::verify(_draw_call_type drawcall_type, unsigned int instance_id,
3376 const unsigned char* data)
3377 {
3378 const float epsilon = 1.0f / 256.0f;
3379 unsigned int rt_height = 0;
3380 unsigned int rt_width = 0;
3381 unsigned int single_rt_height = 0;
3382 unsigned int single_rt_width = 0;
3383
3384 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED ||
3385 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED)
3386 {
3387 getRenderTargetSize(getAmountOfDrawInstances(), &rt_width, &rt_height);
3388 }
3389 else
3390 {
3391 getRenderTargetSize(1, &rt_width, &rt_height);
3392 }
3393
3394 getRenderTargetSize(1, &single_rt_width, &single_rt_height);
3395
3396 /* Verification is output type-specific */
3397 const unsigned int row_width = rt_width * 4 /* components */;
3398
3399 switch (m_output_type)
3400 {
3401 case SHADER_OUTPUT_TYPE_LINE_STRIP:
3402 {
3403 /* The test renders a rectangle outline with 3 line segments for each edge.
3404 * The verification checks color of each edge's middle line segment.
3405 *
3406 * Corners are skipped to keep the implementation simple. */
3407 for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge)
3408 {
3409 /* Determine edge-specific properties:
3410 *
3411 * Edge 0 - top edge;
3412 * Edge 1 - right edge;
3413 * Edge 2 - bottom edge;
3414 * Edge 3 - left edge.
3415 *
3416 **/
3417 int end_x = 0;
3418 int end_y = 0;
3419 tcu::Vec4 expected_rgba;
3420 int start_x = 0;
3421 int start_y = 0;
3422
3423 switch (n_edge)
3424 {
3425 case 0:
3426 {
3427 /* Top edge */
3428 start_x = 3; /* skip the corner */
3429 start_y = 1 + instance_id * single_rt_height; /* middle segment */
3430
3431 end_x = single_rt_width - 3; /* skip the corner */
3432 end_y = start_y;
3433
3434 expected_rgba = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f) +
3435 tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f);
3436
3437 break;
3438 }
3439
3440 case 1:
3441 {
3442 /* Right edge */
3443 start_x = single_rt_width - 2; /* middle segment */
3444 start_y = 3 + instance_id * single_rt_height; /* skip the corner */
3445
3446 end_x = start_x;
3447 end_y = start_y + single_rt_height - 6; /* skip the corners */
3448
3449 expected_rgba = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f) +
3450 tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f) * tcu::Vec4(0.5f);
3451
3452 break;
3453 }
3454
3455 case 2:
3456 {
3457 /* Bottom edge */
3458 start_x = 3; /* skip the corner */
3459 start_y = single_rt_height - 3 + instance_id * single_rt_height; /* middle segment */
3460
3461 end_x = single_rt_width - 6; /* skip the corners */
3462 end_y = start_y;
3463
3464 expected_rgba = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f) * tcu::Vec4(0.5f) +
3465 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * tcu::Vec4(0.5f);
3466
3467 break;
3468 }
3469
3470 case 3:
3471 {
3472 /* Left edge */
3473 start_x = 1; /* middle segment */
3474 start_y = 3 + instance_id * single_rt_height; /* skip the corner */
3475
3476 end_x = start_x;
3477 end_y = start_y + single_rt_height - 6; /* skip the corners */
3478
3479 expected_rgba = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * tcu::Vec4(0.5f) +
3480 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f);
3481
3482 break;
3483 }
3484
3485 default:
3486 {
3487 TCU_FAIL("Unrecognized edge index");
3488 }
3489 } /* switch(n_edge) */
3490
3491 /* Move over the edge and make sure the rendered pixels are valid */
3492 int dx = (end_x != start_x) ? 1 : 0;
3493 int dy = (end_y != start_y) ? 1 : 0;
3494 int n_pixels = (end_x - start_x) + (end_y - start_y);
3495
3496 for (int n_pixel = 0; n_pixel < n_pixels; ++n_pixel)
3497 {
3498 int cur_x = start_x + n_pixel * dx;
3499 int cur_y = start_y + n_pixel * dy;
3500
3501 /* Calculate expected and rendered pixel color */
3502 const unsigned char* read_data = data + cur_y * row_width + cur_x * 4 /* components */;
3503 float rendered_rgba[4] = { 0 };
3504
3505 for (unsigned int n_channel = 0; n_channel < 4 /* RGBA */; ++n_channel)
3506 {
3507 rendered_rgba[n_channel] = float(read_data[n_channel]) / 255.0f;
3508 }
3509
3510 /* Compare the data */
3511 if (de::abs(rendered_rgba[0] - expected_rgba[0]) > epsilon ||
3512 de::abs(rendered_rgba[1] - expected_rgba[1]) > epsilon ||
3513 de::abs(rendered_rgba[2] - expected_rgba[2]) > epsilon ||
3514 de::abs(rendered_rgba[3] - expected_rgba[3]) > epsilon)
3515 {
3516 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << cur_x << ", " << cur_y
3517 << ") "
3518 << "equal (" << rendered_rgba[0] << ", " << rendered_rgba[1] << ", "
3519 << rendered_rgba[2] << ", " << rendered_rgba[3] << ") "
3520 << "exceeds allowed epsilon when compared to reference data equal ("
3521 << expected_rgba[0] << ", " << expected_rgba[1] << ", " << expected_rgba[2]
3522 << ", " << expected_rgba[3] << ")." << tcu::TestLog::EndMessage;
3523
3524 TCU_FAIL("Data comparison failed");
3525 } /* if (data comparison failed) */
3526 } /* for (all points) */
3527 } /* for (all edges) */
3528
3529 break;
3530 } /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */
3531
3532 case SHADER_OUTPUT_TYPE_POINTS:
3533 {
3534 /* Verify centers of the points generated by geometry shader */
3535 int dx = 0;
3536 int dy = 0;
3537
3538 bool ignore_first_point = false;
3539 int start_x = 0;
3540 int start_y = 0;
3541
3542 tcu::Vec4 end_color;
3543 tcu::Vec4 start_color;
3544
3545 for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge)
3546 {
3547 /* Determine edge-specific properties:
3548 *
3549 * Edge 0 - top edge; NOTE: the test should skip point at (1px, 1px) as it is overwritten by
3550 * edge 3!
3551 * Edge 1 - right edge;
3552 * Edge 2 - bottom edge;
3553 * Edge 3 - left edge.
3554 *
3555 **/
3556 switch (n_edge)
3557 {
3558 case 0:
3559 {
3560 dx = 6;
3561 dy = 0;
3562 ignore_first_point = true;
3563 start_x = 1;
3564 start_y = 1 + instance_id * single_rt_height;
3565
3566 end_color = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f);
3567 start_color = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
3568
3569 break;
3570 }
3571
3572 case 1:
3573 {
3574 dx = 0;
3575 dy = 6;
3576 ignore_first_point = false;
3577 start_x = single_rt_width - 1;
3578 start_y = 1 + instance_id * single_rt_height;
3579
3580 end_color = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f);
3581 start_color = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f);
3582
3583 break;
3584 }
3585
3586 case 2:
3587 {
3588 dx = -6;
3589 dy = 0;
3590 ignore_first_point = false;
3591 start_x = single_rt_width - 1;
3592 start_y = single_rt_height - 1 + instance_id * single_rt_height;
3593
3594 end_color = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
3595 start_color = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f);
3596
3597 break;
3598 }
3599
3600 case 3:
3601 {
3602 dx = 0;
3603 dy = -6;
3604 ignore_first_point = false;
3605 start_x = 1;
3606 start_y = single_rt_height - 1 + instance_id * single_rt_height;
3607
3608 end_color = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
3609 start_color = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
3610
3611 break;
3612 }
3613
3614 default:
3615 {
3616 TCU_FAIL("Unrecognized edge index");
3617 }
3618 } /* switch(n_edge) */
3619
3620 for (unsigned int n_point = 0; n_point < 8 /* points */; ++n_point)
3621 {
3622 int cur_x = start_x + n_point * dx;
3623 int cur_y = start_y + n_point * dy;
3624
3625 /* Skip the iteration if we're dealing with a first point, for which
3626 * the comparison should be skipped */
3627 if (ignore_first_point && n_point == 0)
3628 {
3629 continue;
3630 }
3631
3632 /* Calculate expected and rendered pixel color */
3633 const unsigned char* read_data = data + cur_y * row_width + cur_x * 4 /* components */;
3634 float reference_rgba[4] = { 0 };
3635 float rendered_rgba[4] = { 0 };
3636
3637 for (unsigned int n_channel = 0; n_channel < 4 /* RGBA */; ++n_channel)
3638 {
3639 reference_rgba[n_channel] = start_color[n_channel] +
3640 (end_color[n_channel] - start_color[n_channel]) * float(n_point) / 7.0f;
3641 rendered_rgba[n_channel] = (float)(read_data[n_channel]) / 255.0f;
3642 }
3643
3644 /* Compare the data */
3645 if (de::abs(rendered_rgba[0] - reference_rgba[0]) > epsilon ||
3646 de::abs(rendered_rgba[1] - reference_rgba[1]) > epsilon ||
3647 de::abs(rendered_rgba[2] - reference_rgba[2]) > epsilon ||
3648 de::abs(rendered_rgba[3] - reference_rgba[3]) > epsilon)
3649 {
3650 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << cur_x << ", " << cur_y
3651 << ") "
3652 << "equal (" << rendered_rgba[0] << ", " << rendered_rgba[1] << ", "
3653 << rendered_rgba[2] << ", " << rendered_rgba[3] << ") "
3654 << "exceeds allowed epsilon when compared to reference data equal ("
3655 << reference_rgba[0] << ", " << reference_rgba[1] << ", " << reference_rgba[2]
3656 << ", " << reference_rgba[3] << ")." << tcu::TestLog::EndMessage;
3657
3658 TCU_FAIL("Data comparison failed");
3659 } /* if (data comparison failed) */
3660
3661 } /* for (all points) */
3662 } /* for (all edges) */
3663
3664 /* Done */
3665 break;
3666 } /* case SHADER_OUTPUT_TYPE_POINTS: */
3667
3668 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
3669 {
3670 /* The test renders four triangles - two vertices are taken from each edge and the third
3671 * one is set at (0, 0, 0, 1) (screen-space). The rendering output is verified by
3672 * sampling centroids off each triangle */
3673 for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge)
3674 {
3675 /* Determine edge-specific properties */
3676 tcu::Vec2 centroid;
3677 tcu::Vec4 reference_rgba;
3678 tcu::Vec2 v1;
3679 tcu::Vec2 v2;
3680 tcu::Vec2 v3 = tcu::Vec2(0.5f, 0.5f + float(instance_id));
3681
3682 switch (n_edge)
3683 {
3684 case 0:
3685 {
3686 /* Top edge */
3687 v1 = tcu::Vec2(0.0f, float(instance_id) + 0.0f);
3688 v2 = tcu::Vec2(1.0f, float(instance_id) + 0.0f);
3689
3690 reference_rgba = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
3691
3692 break;
3693 }
3694
3695 case 1:
3696 {
3697 /* Right edge */
3698 v1 = tcu::Vec2(1.0f, float(instance_id) + 0.0f);
3699 v2 = tcu::Vec2(1.0f, float(instance_id) + 1.0f);
3700
3701 reference_rgba = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f);
3702
3703 break;
3704 }
3705
3706 case 2:
3707 {
3708 /* Bottom edge */
3709 v1 = tcu::Vec2(0.0f, float(instance_id) + 1.0f);
3710 v2 = tcu::Vec2(1.0f, float(instance_id) + 1.0f);
3711
3712 reference_rgba = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f);
3713
3714 break;
3715 }
3716
3717 case 3:
3718 {
3719 /* Left edge */
3720 v1 = tcu::Vec2(0.0f, float(instance_id) + 0.0f);
3721 v2 = tcu::Vec2(0.0f, float(instance_id) + 1.0f);
3722
3723 reference_rgba = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
3724
3725 break;
3726 }
3727
3728 default:
3729 {
3730 TCU_FAIL("Unrecognized edge index");
3731 }
3732 } /* switch (n_edge) */
3733
3734 /* Calculate centroid of the triangle. */
3735 centroid[0] = (v1[0] + v2[0] + v3[0]) / 3.0f;
3736 centroid[1] = (v1[1] + v2[1] + v3[1]) / 3.0f;
3737
3738 /* Retrieve the sample */
3739 int centroid_xy[2] = { int(centroid[0] * float(single_rt_width)),
3740 int(centroid[1] * float(single_rt_height)) };
3741 const unsigned char* rendered_rgba_ubyte =
3742 data + centroid_xy[1] * row_width + centroid_xy[0] * 4 /* components */;
3743 const float rendered_rgba_float[] = {
3744 float(rendered_rgba_ubyte[0]) / 255.0f, float(rendered_rgba_ubyte[1]) / 255.0f,
3745 float(rendered_rgba_ubyte[2]) / 255.0f, float(rendered_rgba_ubyte[3]) / 255.0f,
3746 };
3747
3748 /* Compare the reference and rendered pixels */
3749 if (de::abs(rendered_rgba_float[0] - reference_rgba[0]) > epsilon ||
3750 de::abs(rendered_rgba_float[1] - reference_rgba[1]) > epsilon ||
3751 de::abs(rendered_rgba_float[2] - reference_rgba[2]) > epsilon ||
3752 de::abs(rendered_rgba_float[3] - reference_rgba[3]) > epsilon)
3753 {
3754 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << centroid_xy[0] << ", "
3755 << centroid_xy[1] << ") "
3756 << "equal (" << rendered_rgba_float[0] << ", " << rendered_rgba_float[1] << ", "
3757 << rendered_rgba_float[2] << ", " << rendered_rgba_float[3] << ") "
3758 << "exceeds allowed epsilon when compared to reference data equal ("
3759 << reference_rgba[0] << ", " << reference_rgba[1] << ", " << reference_rgba[2]
3760 << ", " << reference_rgba[3] << ")." << tcu::TestLog::EndMessage;
3761
3762 TCU_FAIL("Data comparison failed");
3763 } /* if (data comparison failed) */
3764 } /* for (all edges) */
3765
3766 break;
3767 }
3768
3769 default:
3770 {
3771 TCU_FAIL("Unsupported shader output type used");
3772 }
3773 } /* switch (m_output_type) */
3774 }
3775
3776 /** Constructor.
3777 *
3778 * @param use_adjacency_data true if the test case is being instantiated for draw call modes that will
3779 * features adjacency data,
3780 * false otherwise.
3781 * @param drawcall_mode GL draw call mode that will be used for the tests.
3782 * @param output_type Shader output type that the test case is being instantiated for.
3783 * @param context Rendering context;
3784 * @param testContext Test context;
3785 * @param name Test name.
3786 **/
GeometryShaderRenderingTrianglesCase(Context & context,const ExtParameters & extParams,const char * name,bool use_adjacency_data,glw::GLenum drawcall_mode,_shader_output_type output_type)3787 GeometryShaderRenderingTrianglesCase::GeometryShaderRenderingTrianglesCase(Context& context,
3788 const ExtParameters& extParams,
3789 const char* name, bool use_adjacency_data,
3790 glw::GLenum drawcall_mode,
3791 _shader_output_type output_type)
3792 : GeometryShaderRenderingCase(
3793 context, extParams, name,
3794 "Verifies all draw calls work correctly for specific input+output+draw call mode combination")
3795 , m_output_type(output_type)
3796 , m_drawcall_mode(drawcall_mode)
3797 , m_use_adjacency_data(use_adjacency_data)
3798 , m_raw_array_instanced_data(0)
3799 , m_raw_array_instanced_data_size(0)
3800 , m_raw_array_noninstanced_data(0)
3801 , m_raw_array_noninstanced_data_size(0)
3802 , m_unordered_array_instanced_data(0)
3803 , m_unordered_array_instanced_data_size(0)
3804 , m_unordered_array_noninstanced_data(0)
3805 , m_unordered_array_noninstanced_data_size(0)
3806 , m_unordered_elements_instanced_data(0)
3807 , m_unordered_elements_instanced_data_size(0)
3808 , m_unordered_elements_noninstanced_data(0)
3809 , m_unordered_elements_noninstanced_data_size(0)
3810 , m_unordered_elements_max_index(24) /* maximum amount of vertices generated by this test case */
3811 , m_unordered_elements_min_index(0)
3812 {
3813 /* Sanity checks */
3814 if (!m_use_adjacency_data)
3815 {
3816 if (drawcall_mode != GL_TRIANGLES && drawcall_mode != GL_TRIANGLE_STRIP && drawcall_mode != GL_TRIANGLE_FAN)
3817 {
3818 TCU_FAIL("Only GL_TRIANGLES or GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN draw call modes are supported for "
3819 "'triangles' geometry shader input layout qualifier test implementation");
3820 }
3821 }
3822 else
3823 {
3824 if (drawcall_mode != GL_TRIANGLES_ADJACENCY_EXT && drawcall_mode != GL_TRIANGLE_STRIP_ADJACENCY_EXT)
3825 {
3826 TCU_FAIL("Only GL_TRIANGLES_ADJACENCY_EXT or GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call modes are supported "
3827 "for 'triangles_adjacency' geometry shader input layout qualifier test implementation");
3828 }
3829 }
3830
3831 if (output_type != SHADER_OUTPUT_TYPE_POINTS && output_type != SHADER_OUTPUT_TYPE_LINE_STRIP &&
3832 output_type != SHADER_OUTPUT_TYPE_TRIANGLE_STRIP)
3833 {
3834 TCU_FAIL("Unsupported output layout qualifier type requested for 'triangles' geometry shader input layout "
3835 "qualifier test implementation");
3836 }
3837
3838 /* Generate data in two flavors - one for non-instanced case, the other one for instanced case */
3839 for (int n_case = 0; n_case < 2 /* cases */; ++n_case)
3840 {
3841 bool is_instanced = (n_case != 0);
3842 int n_instances = 0;
3843 float** raw_arrays_data_ptr = NULL;
3844 unsigned int* raw_arrays_data_size_ptr = NULL;
3845 unsigned int rendertarget_height = 0;
3846 unsigned int rendertarget_width = 0;
3847 float** unordered_arrays_data_ptr = NULL;
3848 unsigned int* unordered_arrays_data_size_ptr = NULL;
3849 unsigned char** unordered_elements_data_ptr = NULL;
3850 unsigned int* unordered_elements_data_size_ptr = NULL;
3851
3852 if (!is_instanced)
3853 {
3854 /* Non-instanced case */
3855 n_instances = 1;
3856 raw_arrays_data_ptr = &m_raw_array_noninstanced_data;
3857 raw_arrays_data_size_ptr = &m_raw_array_noninstanced_data_size;
3858 unordered_arrays_data_ptr = &m_unordered_array_noninstanced_data;
3859 unordered_arrays_data_size_ptr = &m_unordered_array_noninstanced_data_size;
3860 unordered_elements_data_ptr = &m_unordered_elements_noninstanced_data;
3861 unordered_elements_data_size_ptr = &m_unordered_elements_noninstanced_data_size;
3862 }
3863 else
3864 {
3865 /* Instanced case */
3866 n_instances = getAmountOfDrawInstances();
3867 raw_arrays_data_ptr = &m_raw_array_instanced_data;
3868 raw_arrays_data_size_ptr = &m_raw_array_instanced_data_size;
3869 unordered_arrays_data_ptr = &m_unordered_array_instanced_data;
3870 unordered_arrays_data_size_ptr = &m_unordered_array_instanced_data_size;
3871 unordered_elements_data_ptr = &m_unordered_elements_instanced_data;
3872 unordered_elements_data_size_ptr = &m_unordered_elements_instanced_data_size;
3873 }
3874
3875 getRenderTargetSize(n_instances, &rendertarget_width, &rendertarget_height);
3876
3877 /* Store full-screen quad coordinates that will be used for actual array data generation. */
3878 float dx = 2.0f / float(rendertarget_width);
3879 float dy = 2.0f / float(rendertarget_height);
3880
3881 /* Generate raw vertex array data */
3882 unsigned int single_rt_height = 0;
3883 unsigned int single_rt_width = 0;
3884 unsigned int whole_rt_width = 0;
3885 unsigned int whole_rt_height = 0;
3886
3887 *raw_arrays_data_size_ptr =
3888 static_cast<unsigned int>(getAmountOfVerticesPerInstance() * 4 /* components */ * sizeof(float));
3889 *raw_arrays_data_ptr = new float[*raw_arrays_data_size_ptr / sizeof(float)];
3890
3891 getRenderTargetSize(1, &single_rt_width, &single_rt_height);
3892 getRenderTargetSize(getAmountOfDrawInstances(), &whole_rt_width, &whole_rt_height);
3893
3894 /* Generate the general coordinates storage first.
3895 *
3896 * For non-instanced draw calls, we only need to draw a single instance, hence we are free
3897 * to use screen-space coordinates.
3898 * For instanced draw calls, we'll have the vertex shader add gl_InstanceID-specific deltas
3899 * to make sure the vertices are laid out correctly, so map <-1, 1> range to <0, screen_space_height_of_single_instance>
3900 */
3901 std::vector<tcu::Vec4> data_coordinates;
3902 float dx_multiplier = 0.0f;
3903 float dy_multiplier = 0.0f;
3904 float end_y = 0.0f;
3905 float mid_y = 0.0f;
3906 float start_y = 0.0f;
3907
3908 if (is_instanced)
3909 {
3910 start_y = -1.0f;
3911 end_y = start_y + float(single_rt_height) / float(whole_rt_height) * 2.0f;
3912 mid_y = start_y + (end_y - start_y) * 0.5f;
3913 }
3914 else
3915 {
3916 end_y = 1.0f;
3917 mid_y = 0.0f;
3918 start_y = -1.0f;
3919 }
3920
3921 if (output_type == SHADER_OUTPUT_TYPE_POINTS)
3922 {
3923 dx_multiplier = 1.5f;
3924 dy_multiplier = 1.5f;
3925 }
3926 else if (output_type == SHADER_OUTPUT_TYPE_LINE_STRIP)
3927 {
3928 dx_multiplier = 1.5f;
3929 dy_multiplier = 1.5f;
3930 }
3931
3932 /* W stores information whether given vertex is the middle vertex */
3933 data_coordinates.push_back(tcu::Vec4(0, mid_y, 0, 1)); /* Middle vertex */
3934 data_coordinates.push_back(tcu::Vec4(-1 + dx * dx_multiplier, mid_y, 0, 0)); /* Left vertex */
3935 data_coordinates.push_back(tcu::Vec4(0, start_y + dy * dy_multiplier, 0, 0)); /* Top vertex */
3936 data_coordinates.push_back(tcu::Vec4(1 - dx * dx_multiplier, mid_y, 0, 0)); /* Right vertex */
3937 data_coordinates.push_back(tcu::Vec4(0, end_y - dy * dy_multiplier, 0, 0)); /* Bottom vertex */
3938
3939 /* Now that we have the general storage ready, we can generate raw array data for specific draw
3940 * call that this specific test instance will be verifying */
3941 int n_raw_array_indices = 0;
3942 int raw_array_indices[24] = { -1 }; /* 12 is a max for all supported input geometry */
3943 float* raw_array_traveller_ptr = *raw_arrays_data_ptr;
3944
3945 for (unsigned int n = 0; n < sizeof(raw_array_indices) / sizeof(raw_array_indices[0]); ++n)
3946 {
3947 raw_array_indices[n] = -1;
3948 }
3949
3950 switch (m_drawcall_mode)
3951 {
3952 case GL_TRIANGLES:
3953 {
3954 /* ABC triangle */
3955 raw_array_indices[0] = 0;
3956 raw_array_indices[1] = 1;
3957 raw_array_indices[2] = 2;
3958
3959 /* ACD triangle */
3960 raw_array_indices[3] = 0;
3961 raw_array_indices[4] = 2;
3962 raw_array_indices[5] = 3;
3963
3964 /* ADE triangle */
3965 raw_array_indices[6] = 0;
3966 raw_array_indices[7] = 3;
3967 raw_array_indices[8] = 4;
3968
3969 /* AEB triangle */
3970 raw_array_indices[9] = 0;
3971 raw_array_indices[10] = 4;
3972 raw_array_indices[11] = 1;
3973
3974 n_raw_array_indices = 12;
3975
3976 break;
3977 } /* case GL_TRIANGLES: */
3978
3979 case GL_TRIANGLES_ADJACENCY_EXT:
3980 {
3981 /* Note: Geometry shader used by this test does not rely on adjacency data
3982 * so we will fill corresponding indices with meaningless information
3983 * (always first vertex data) */
3984 /* ABC triangle */
3985 raw_array_indices[0] = 0;
3986 raw_array_indices[1] = 0;
3987 raw_array_indices[2] = 1;
3988 raw_array_indices[3] = 0;
3989 raw_array_indices[4] = 2;
3990 raw_array_indices[5] = 0;
3991
3992 /* ACD triangle */
3993 raw_array_indices[6] = 0;
3994 raw_array_indices[7] = 0;
3995 raw_array_indices[8] = 2;
3996 raw_array_indices[9] = 0;
3997 raw_array_indices[10] = 3;
3998 raw_array_indices[11] = 0;
3999
4000 /* ADE triangle */
4001 raw_array_indices[12] = 0;
4002 raw_array_indices[13] = 0;
4003 raw_array_indices[14] = 3;
4004 raw_array_indices[15] = 0;
4005 raw_array_indices[16] = 4;
4006 raw_array_indices[17] = 0;
4007
4008 /* AEB triangle */
4009 raw_array_indices[18] = 0;
4010 raw_array_indices[19] = 0;
4011 raw_array_indices[20] = 4;
4012 raw_array_indices[21] = 0;
4013 raw_array_indices[22] = 1;
4014 raw_array_indices[23] = 0;
4015
4016 n_raw_array_indices = 24;
4017
4018 break;
4019 } /* case GL_TRIANGLES_ADJACENCY_EXT:*/
4020
4021 case GL_TRIANGLE_FAN:
4022 {
4023 /* ABCDEB */
4024 raw_array_indices[0] = 0;
4025 raw_array_indices[1] = 1;
4026 raw_array_indices[2] = 2;
4027 raw_array_indices[3] = 3;
4028 raw_array_indices[4] = 4;
4029 raw_array_indices[5] = 1;
4030
4031 n_raw_array_indices = 6;
4032
4033 break;
4034 } /* case GL_TRIANGLE_FAN: */
4035
4036 case GL_TRIANGLE_STRIP:
4037 {
4038 /* BACDAEB.
4039 *
4040 * Note that this will generate a degenerate triangle (ACD & CDA) but that's fine
4041 * since we only sample triangle centroids in this test.
4042 */
4043 raw_array_indices[0] = 1;
4044 raw_array_indices[1] = 0;
4045 raw_array_indices[2] = 2;
4046 raw_array_indices[3] = 3;
4047 raw_array_indices[4] = 0;
4048 raw_array_indices[5] = 4;
4049 raw_array_indices[6] = 1;
4050
4051 n_raw_array_indices = 7;
4052
4053 break;
4054 } /* case GL_TRIANGLE_STRIP: */
4055
4056 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4057 {
4058 /* Order as in GL_TRIANGLE_STRIP case. Adjacency data not needed for the test,
4059 * hence any data can be used.
4060 */
4061 raw_array_indices[0] = 1;
4062 raw_array_indices[1] = 0;
4063 raw_array_indices[2] = 0;
4064 raw_array_indices[3] = 0;
4065 raw_array_indices[4] = 2;
4066 raw_array_indices[5] = 0;
4067 raw_array_indices[6] = 3;
4068 raw_array_indices[7] = 0;
4069 raw_array_indices[8] = 0;
4070 raw_array_indices[9] = 0;
4071 raw_array_indices[10] = 4;
4072 raw_array_indices[11] = 0;
4073 raw_array_indices[12] = 1;
4074 raw_array_indices[13] = 0;
4075
4076 n_raw_array_indices = 14;
4077 break;
4078 } /* case GL_TRIANGLE_STRIP_ADJACENCY_EXT: */
4079
4080 default:
4081 {
4082 TCU_FAIL("Unsupported draw call mode");
4083 }
4084 } /* switch (m_drawcall_mode) */
4085
4086 for (int index = 0; index < n_raw_array_indices; ++index)
4087 {
4088 if (raw_array_indices[index] != -1)
4089 {
4090 *raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].x();
4091 raw_array_traveller_ptr++;
4092 *raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].y();
4093 raw_array_traveller_ptr++;
4094 *raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].z();
4095 raw_array_traveller_ptr++;
4096 *raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].w();
4097 raw_array_traveller_ptr++;
4098 }
4099 }
4100
4101 /* Generate unordered data:
4102 *
4103 * Store vertices in reversed order and configure indices so that the pipeline receives
4104 * vertex data in original order */
4105 *unordered_arrays_data_size_ptr = *raw_arrays_data_size_ptr;
4106 *unordered_arrays_data_ptr = new float[*unordered_arrays_data_size_ptr];
4107 *unordered_elements_data_size_ptr = static_cast<unsigned int>(n_raw_array_indices * sizeof(unsigned char));
4108 *unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr];
4109
4110 /* Set unordered array data first */
4111 for (int index = 0; index < n_raw_array_indices; ++index)
4112 {
4113 memcpy(*unordered_arrays_data_ptr + 4 /* components */ * (n_raw_array_indices - 1 - index),
4114 *raw_arrays_data_ptr + 4 /* components */ * index, sizeof(float) * 4 /* components */);
4115 }
4116
4117 /* Followed by index data */
4118 for (int n = 0; n < n_raw_array_indices; ++n)
4119 {
4120 (*unordered_elements_data_ptr)[n] = (unsigned char)(n_raw_array_indices - 1 - n);
4121 }
4122 } /* for (both cases) */
4123 }
4124
4125 /** Destructor. */
~GeometryShaderRenderingTrianglesCase()4126 GeometryShaderRenderingTrianglesCase::~GeometryShaderRenderingTrianglesCase()
4127 {
4128 if (m_raw_array_instanced_data != NULL)
4129 {
4130 delete[] m_raw_array_instanced_data;
4131
4132 m_raw_array_instanced_data = NULL;
4133 }
4134
4135 if (m_raw_array_noninstanced_data != NULL)
4136 {
4137 delete[] m_raw_array_noninstanced_data;
4138
4139 m_raw_array_noninstanced_data = NULL;
4140 }
4141
4142 if (m_unordered_array_instanced_data != NULL)
4143 {
4144 delete[] m_unordered_array_instanced_data;
4145
4146 m_unordered_array_instanced_data = NULL;
4147 }
4148
4149 if (m_unordered_array_noninstanced_data != NULL)
4150 {
4151 delete[] m_unordered_array_noninstanced_data;
4152
4153 m_unordered_array_noninstanced_data = NULL;
4154 }
4155
4156 if (m_unordered_elements_instanced_data != NULL)
4157 {
4158 delete[] m_unordered_elements_instanced_data;
4159
4160 m_unordered_elements_instanced_data = NULL;
4161 }
4162
4163 if (m_unordered_elements_noninstanced_data != NULL)
4164 {
4165 delete[] m_unordered_elements_noninstanced_data;
4166
4167 m_unordered_elements_noninstanced_data = NULL;
4168 }
4169 }
4170
4171 /** Retrieves amount of instances that should be drawn with glDraw*Elements() calls.
4172 *
4173 * @return As per description.
4174 **/
getAmountOfDrawInstances()4175 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfDrawInstances()
4176 {
4177 return 8;
4178 }
4179
4180 /** Retrieves amount of indices that should be used for rendering a single instance
4181 * (glDraw*Elements() calls only)
4182 *
4183 * @return As per description.
4184 */
getAmountOfElementsPerInstance()4185 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfElementsPerInstance()
4186 {
4187 /* No difference between instanced and non-instanced case. */
4188 return static_cast<unsigned int>(m_unordered_elements_instanced_data_size / sizeof(unsigned char));
4189 }
4190
4191 /** Retrieves amount of vertices that should be used for rendering a single instance
4192 * (glDrawArrays*() calls only)
4193 *
4194 * @return As per description.
4195 **/
getAmountOfVerticesPerInstance()4196 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfVerticesPerInstance()
4197 {
4198 unsigned int result = 0;
4199
4200 switch (m_drawcall_mode)
4201 {
4202 case GL_TRIANGLES:
4203 {
4204 result = 3 /* vertices making up a single triangle */ * 4 /* triangles */;
4205
4206 break;
4207 }
4208
4209 case GL_TRIANGLES_ADJACENCY_EXT:
4210 {
4211 result = 3 /* vertices making up a single triangle */ * 4 /* triangles */ * 2 /* adjacency data */;
4212
4213 break;
4214 }
4215
4216 case GL_TRIANGLE_FAN:
4217 {
4218 result = 6 /* vertices in total */;
4219
4220 break;
4221 }
4222
4223 case GL_TRIANGLE_STRIP:
4224 {
4225 result = 7 /* vertices in total */;
4226
4227 break;
4228 }
4229
4230 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4231 {
4232 /* As per extension specification */
4233 result = (5 /* triangles */ + 2) * 2;
4234
4235 break;
4236 }
4237
4238 default:
4239 {
4240 TCU_FAIL("Unrecognized draw call mode");
4241 }
4242 } /* switch (m_drawcall_mode) */
4243
4244 return result;
4245 }
4246
4247 /** Draw call mode that should be used glDraw*() calls.
4248 *
4249 * @return As per description.
4250 **/
getDrawCallMode()4251 glw::GLenum GeometryShaderRenderingTrianglesCase::getDrawCallMode()
4252 {
4253 return m_drawcall_mode;
4254 }
4255
4256 /** Source code for a fragment shader that should be used for the test.
4257 *
4258 * @return As per description.
4259 **/
getFragmentShaderCode()4260 std::string GeometryShaderRenderingTrianglesCase::getFragmentShaderCode()
4261 {
4262 static std::string fs_code = "${VERSION}\n"
4263 "\n"
4264 "precision highp float;\n"
4265 "\n"
4266 "in vec4 gs_fs_color;\n"
4267 "out vec4 result;\n"
4268 "\n"
4269 "void main()\n"
4270 "{\n"
4271 " result = gs_fs_color;\n"
4272 "}\n";
4273
4274 return fs_code;
4275 }
4276
4277 /** Source code for a geometry shader that should be used for the test.
4278 *
4279 * @return As per description.
4280 **/
getGeometryShaderCode()4281 std::string GeometryShaderRenderingTrianglesCase::getGeometryShaderCode()
4282 {
4283 static const char* gs_triangles_in_lines_out_preamble = "${VERSION}\n"
4284 "\n"
4285 "${GEOMETRY_SHADER_ENABLE}\n"
4286 "\n"
4287 "layout(triangles) in;\n"
4288 "layout(line_strip, max_vertices=24) out;\n"
4289 "\n"
4290 "#define N_VERTICES (3)\n"
4291 "#define N_VERTEX0 (0)\n"
4292 "#define N_VERTEX1 (1)\n"
4293 "#define N_VERTEX2 (2)\n"
4294 "\n";
4295
4296 static const char* gs_triangles_adjacency_in_lines_out_preamble = "${VERSION}\n"
4297 "\n"
4298 "${GEOMETRY_SHADER_ENABLE}\n"
4299 "\n"
4300 "layout(triangles_adjacency) in;\n"
4301 "layout(line_strip, max_vertices=24) out;\n"
4302 "\n"
4303 "#define N_VERTICES (6)\n"
4304 "#define N_VERTEX0 (0)\n"
4305 "#define N_VERTEX1 (2)\n"
4306 "#define N_VERTEX2 (4)\n"
4307 "\n";
4308
4309 static const char* gs_lines_code =
4310 "uniform ivec2 renderingTargetSize;\n"
4311 "\n"
4312 "in vec4 vs_gs_color[N_VERTICES];\n"
4313 "out vec4 gs_fs_color;\n"
4314 "\n"
4315 "void main()\n"
4316 "{\n"
4317 " float dx = 2.0 / float(renderingTargetSize.x);\n"
4318 " float dy = 2.0 / float(renderingTargetSize.y);\n"
4319 "\n"
4320 " vec2 min_xy = gl_in[N_VERTEX0].gl_Position.xy;\n"
4321 " vec2 max_xy = gl_in[N_VERTEX0].gl_Position.xy;\n"
4322 "\n"
4323 " min_xy[0] = min(gl_in[N_VERTEX1].gl_Position.x, min_xy[0]);\n"
4324 " min_xy[0] = min(gl_in[N_VERTEX2].gl_Position.x, min_xy[0]);\n"
4325 " min_xy[1] = min(gl_in[N_VERTEX1].gl_Position.y, min_xy[1]);\n"
4326 " min_xy[1] = min(gl_in[N_VERTEX2].gl_Position.y, min_xy[1]);\n"
4327 "\n"
4328 " max_xy[0] = max(gl_in[N_VERTEX1].gl_Position.x, max_xy[0]);\n"
4329 " max_xy[0] = max(gl_in[N_VERTEX2].gl_Position.x, max_xy[0]);\n"
4330 " max_xy[1] = max(gl_in[N_VERTEX1].gl_Position.y, max_xy[1]);\n"
4331 " max_xy[1] = max(gl_in[N_VERTEX2].gl_Position.y, max_xy[1]);\n"
4332 "\n"
4333 " for (int n = 0; n < 3 /* segment \"sub\"-line */; ++n)\n"
4334 " {\n"
4335 " float hor_line_delta = 0.0;\n"
4336 " float ver_line_delta = 0.0;\n"
4337 "\n"
4338 " switch(n)\n"
4339 " {\n"
4340 " case 0: hor_line_delta = -dx; ver_line_delta = -dy; break;\n"
4341 " case 1: break;\n"
4342 " case 2: hor_line_delta = dx; ver_line_delta = dy; break;\n"
4343 " }\n"
4344 "\n"
4345 /* BL->TL */
4346 " gl_Position = vec4(min_xy[0] - hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n"
4347 " gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4348 " EmitVertex();\n"
4349 " gl_Position = vec4(min_xy[0] - hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n"
4350 " gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4351 " EmitVertex();\n"
4352 " EndPrimitive();\n"
4353 /* TL->TR */
4354 " gl_Position = vec4(max_xy[0] + hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n"
4355 " gs_fs_color = vs_gs_color[N_VERTEX1];\n"
4356 " EmitVertex();\n"
4357 " gl_Position = vec4(min_xy[0] - hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n"
4358 " gs_fs_color = vs_gs_color[N_VERTEX1];\n"
4359 " EmitVertex();\n"
4360 " EndPrimitive();\n"
4361 /* TR->BR */
4362 " gl_Position = vec4(max_xy[0] + hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n"
4363 " gs_fs_color = vs_gs_color[N_VERTEX2];\n"
4364 " EmitVertex();\n"
4365 " gl_Position = vec4(max_xy[0] + hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n"
4366 " gs_fs_color = vs_gs_color[N_VERTEX2];\n"
4367 " EmitVertex();\n"
4368 " EndPrimitive();\n"
4369 /* BR->BL */
4370 " gl_Position = vec4(min_xy[0] - hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n"
4371 " gs_fs_color = vec4(vs_gs_color[N_VERTEX0].r, vs_gs_color[N_VERTEX1].g, vs_gs_color[N_VERTEX2].b, "
4372 "vs_gs_color[N_VERTEX0].a);\n"
4373 " EmitVertex();\n"
4374 " gl_Position = vec4(max_xy[0] + hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n"
4375 " gs_fs_color = vec4(vs_gs_color[N_VERTEX0].r, vs_gs_color[N_VERTEX1].g, vs_gs_color[N_VERTEX2].b, "
4376 "vs_gs_color[N_VERTEX0].a);\n"
4377 " EmitVertex();\n"
4378 " EndPrimitive();\n"
4379 " }\n"
4380 "}\n";
4381
4382 static const char* gs_triangles_in_points_out_preamble = "${VERSION}\n"
4383 "\n"
4384 "${GEOMETRY_SHADER_ENABLE}\n"
4385 "\n"
4386 "layout(triangles) in;\n"
4387 "layout(points, max_vertices=27) out;\n"
4388 "\n"
4389 "#define N_VERTICES (3)\n"
4390 "#define N_VERTEX0 (0)\n"
4391 "#define N_VERTEX1 (1)\n"
4392 "#define N_VERTEX2 (2)\n"
4393 "\n";
4394
4395 static const char* gs_triangles_adjacency_in_points_out_preamble = "${VERSION}\n"
4396 "\n"
4397 "${GEOMETRY_SHADER_ENABLE}\n"
4398 "\n"
4399 "layout(triangles_adjacency) in;\n"
4400 "layout(points, max_vertices=27) out;\n"
4401 "\n"
4402 "#define N_VERTICES (6)\n"
4403 "#define N_VERTEX0 (0)\n"
4404 "#define N_VERTEX1 (2)\n"
4405 "#define N_VERTEX2 (4)\n"
4406 "\n";
4407
4408 static const char* gs_points_code =
4409 "uniform ivec2 renderingTargetSize;\n"
4410 "\n"
4411 "in vec4 vs_gs_color[N_VERTICES];\n"
4412 "out vec4 gs_fs_color;\n"
4413 "\n"
4414 "void main()\n"
4415 "{\n"
4416 " float dx = 2.0 / float(renderingTargetSize.x);\n"
4417 " float dy = 2.0 / float(renderingTargetSize.y);\n"
4418 "\n"
4419 " for (int n = 0; n < 3 /* vertices */; ++n)\n"
4420 " {\n"
4421 " int vertex_index = (n == 0) ? N_VERTEX0 : \n"
4422 " (n == 1) ? N_VERTEX1 : \n"
4423 " N_VERTEX2;\n"
4424 /* TL */
4425 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, -dy, 0, 0);\n"
4426 " gs_fs_color = vs_gs_color[vertex_index];\n"
4427 " EmitVertex();\n"
4428 /* TM */
4429 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, -dy, 0, 0);\n"
4430 " gs_fs_color = vs_gs_color[vertex_index];\n"
4431 " EmitVertex();\n"
4432 /* TR */
4433 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, -dy, 0, 0);\n"
4434 " gs_fs_color = vs_gs_color[vertex_index];\n"
4435 " EmitVertex();\n"
4436 /* ML */
4437 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, 0, 0, 0);\n"
4438 " gs_fs_color = vs_gs_color[vertex_index];\n"
4439 " EmitVertex();\n"
4440 /* MM */
4441 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, 0, 0, 0);\n"
4442 " gs_fs_color = vs_gs_color[vertex_index];\n"
4443 " EmitVertex();\n"
4444 /* MR */
4445 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, 0, 0, 0);\n"
4446 " gs_fs_color = vs_gs_color[vertex_index];\n"
4447 " EmitVertex();\n"
4448 /* BL */
4449 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, dy, 0, 0);\n"
4450 " gs_fs_color = vs_gs_color[vertex_index];\n"
4451 " EmitVertex();\n"
4452 /* BM */
4453 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, dy, 0, 0);\n"
4454 " gs_fs_color = vs_gs_color[vertex_index];\n"
4455 " EmitVertex();\n"
4456 /* BR */
4457 " gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, dy, 0, 0);\n"
4458 " gs_fs_color = vs_gs_color[vertex_index];\n"
4459 " EmitVertex();\n"
4460 " }\n"
4461 "}\n";
4462
4463 static const char* gs_triangles_in_triangles_out_preamble = "${VERSION}\n"
4464 "\n"
4465 "${GEOMETRY_SHADER_ENABLE}\n"
4466 "\n"
4467 "layout(triangles) in;\n"
4468 "layout(triangle_strip, max_vertices=6) out;\n"
4469 "\n"
4470 "#define N_VERTICES (3)\n"
4471 "#define N_VERTEX0 (0)\n"
4472 "#define N_VERTEX1 (1)\n"
4473 "#define N_VERTEX2 (2)\n"
4474 "\n";
4475
4476 static const char* gs_triangles_adjacency_in_triangles_out_preamble =
4477 "${VERSION}\n"
4478 "\n"
4479 "${GEOMETRY_SHADER_ENABLE}\n"
4480 "\n"
4481 "layout(triangles_adjacency) in;\n"
4482 "layout(triangle_strip, max_vertices=6) out;\n"
4483 "\n"
4484 "#define N_VERTICES (6)\n"
4485 "#define N_VERTEX0 (0)\n"
4486 "#define N_VERTEX1 (2)\n"
4487 "#define N_VERTEX2 (4)\n"
4488 "\n";
4489
4490 static const char* gs_triangles_code = "uniform ivec2 renderingTargetSize;\n"
4491 "\n"
4492 "in vec4 vs_gs_color[N_VERTICES];\n"
4493 "out vec4 gs_fs_color;\n"
4494 "\n"
4495 "void main()\n"
4496 "{\n"
4497 " float dx = 2.0 / float(renderingTargetSize.x);\n"
4498 " float dy = 2.0 / float(renderingTargetSize.y);\n"
4499 "\n"
4500 " vec4 v0 = gl_in[N_VERTEX0].gl_Position;\n"
4501 " vec4 v1 = gl_in[N_VERTEX1].gl_Position;\n"
4502 " vec4 v2 = gl_in[N_VERTEX2].gl_Position;\n"
4503 " vec4 a = v0;\n"
4504 " vec4 b;\n"
4505 " vec4 c;\n"
4506 " vec4 d;\n"
4507 "\n"
4508 /* Sort incoming vertices:
4509 *
4510 * a) a - vertex in origin.
4511 * b) b - vertex located on the same height as a.
4512 * c) c - remaining vertex.
4513 */
4514 " if (abs(v1.w) >= 1.0)\n"
4515 " {\n"
4516 " a = v1;\n"
4517 " \n"
4518 " if (abs(v0.x - a.x) < dx)\n"
4519 " {\n"
4520 " b = v0;\n"
4521 " c = v2;\n"
4522 " }\n"
4523 " else\n"
4524 " {\n"
4525 " b = v2;\n"
4526 " c = v0;\n"
4527 " }\n"
4528 " }\n"
4529 " else\n"
4530 " if (abs(v2.w) >= 1.0)\n"
4531 " {\n"
4532 " a = v2;\n"
4533 " \n"
4534 " if (abs(v0.x - a.x) < dx)\n"
4535 " {\n"
4536 " b = v0;\n"
4537 " c = v1;\n"
4538 " }\n"
4539 " else\n"
4540 " {\n"
4541 " b = v1;\n"
4542 " c = v0;\n"
4543 " }\n"
4544 " }\n"
4545 " else\n"
4546 " {\n"
4547 " if (abs(v1.x - a.x) < dx)\n"
4548 " {\n"
4549 " b = v1;\n"
4550 " c = v2;\n"
4551 " }\n"
4552 " else\n"
4553 " {\n"
4554 " b = v2;\n"
4555 " c = v1;\n"
4556 " }\n"
4557 " }\n"
4558 " \n"
4559 " d = (b + c) * vec4(0.5);\n"
4560 /* Now given the following configuration: (orientation does not matter)
4561 *
4562 * B
4563 * |\
4564 * | D
4565 * | \
4566 * A---C
4567 *
4568 * emit ABD and ACD triangles */
4569
4570 /* First sub-triangle */
4571 " gl_Position = vec4(a.xyz, 1);\n"
4572 " gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4573 " EmitVertex();\n"
4574 "\n"
4575 " gl_Position = vec4(b.xyz, 1);\n"
4576 " gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4577 " EmitVertex();\n"
4578 "\n"
4579 " gl_Position = vec4(d.xyz, 1);\n"
4580 " gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4581 " EmitVertex();\n"
4582 " EndPrimitive();\n"
4583 /* Second sub-triangle */
4584 " gl_Position = vec4(a.xyz, 1);\n"
4585 " gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n"
4586 " EmitVertex();\n"
4587 "\n"
4588 " gl_Position = vec4(c.xyz, 1);\n"
4589 " gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n"
4590 " EmitVertex();\n"
4591 "\n"
4592 " gl_Position = vec4(d.xyz, 1);\n"
4593 " gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n"
4594 " EmitVertex();\n"
4595 " EndPrimitive();\n"
4596 "}\n";
4597
4598 std::string result;
4599
4600 switch (m_output_type)
4601 {
4602 case SHADER_OUTPUT_TYPE_POINTS:
4603 {
4604 std::stringstream gs_triangles_code_stringstream;
4605 std::string gs_triangles_code_string;
4606 std::stringstream gs_triangles_adjacency_code_stringstream;
4607 std::string gs_triangles_adjacency_code_string;
4608
4609 switch (m_drawcall_mode)
4610 {
4611 case GL_TRIANGLE_FAN:
4612 case GL_TRIANGLE_STRIP:
4613 case GL_TRIANGLES:
4614 {
4615 gs_triangles_code_stringstream << gs_triangles_in_points_out_preamble << gs_points_code;
4616
4617 gs_triangles_code_string = gs_triangles_code_stringstream.str();
4618 result = gs_triangles_code_string;
4619
4620 break;
4621 }
4622
4623 case GL_TRIANGLES_ADJACENCY_EXT:
4624 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4625 {
4626 gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_points_out_preamble << gs_points_code;
4627
4628 gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str();
4629 result = gs_triangles_adjacency_code_string;
4630
4631 break;
4632 }
4633
4634 default:
4635 {
4636 TCU_FAIL("Unrecognized draw call mode");
4637 }
4638 }
4639
4640 break;
4641 }
4642
4643 case SHADER_OUTPUT_TYPE_LINE_STRIP:
4644 {
4645 std::stringstream gs_triangles_code_stringstream;
4646 std::string gs_triangles_code_string;
4647 std::stringstream gs_triangles_adjacency_code_stringstream;
4648 std::string gs_triangles_adjacency_code_string;
4649
4650 switch (m_drawcall_mode)
4651 {
4652 case GL_TRIANGLE_FAN:
4653 case GL_TRIANGLE_STRIP:
4654 case GL_TRIANGLES:
4655 {
4656 gs_triangles_code_stringstream << gs_triangles_in_lines_out_preamble << gs_lines_code;
4657
4658 gs_triangles_code_string = gs_triangles_code_stringstream.str();
4659 result = gs_triangles_code_string;
4660
4661 break;
4662 }
4663
4664 case GL_TRIANGLES_ADJACENCY_EXT:
4665 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4666 {
4667 gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_lines_out_preamble << gs_lines_code;
4668
4669 gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str();
4670 result = gs_triangles_adjacency_code_string;
4671
4672 break;
4673 }
4674
4675 default:
4676 {
4677 TCU_FAIL("Unrecognized draw call mode");
4678 }
4679 }
4680
4681 break;
4682 }
4683
4684 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
4685 {
4686 std::stringstream gs_triangles_code_stringstream;
4687 std::string gs_triangles_code_string;
4688 std::stringstream gs_triangles_adjacency_code_stringstream;
4689 std::string gs_triangles_adjacency_code_string;
4690
4691 switch (m_drawcall_mode)
4692 {
4693 case GL_TRIANGLE_FAN:
4694 case GL_TRIANGLE_STRIP:
4695 case GL_TRIANGLES:
4696 {
4697 gs_triangles_code_stringstream << gs_triangles_in_triangles_out_preamble << gs_triangles_code;
4698
4699 gs_triangles_code_string = gs_triangles_code_stringstream.str();
4700 result = gs_triangles_code_string;
4701
4702 break;
4703 } /* case GL_TRIANGLES: */
4704
4705 case GL_TRIANGLES_ADJACENCY_EXT:
4706 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4707 {
4708 gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_triangles_out_preamble
4709 << gs_triangles_code;
4710
4711 gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str();
4712 result = gs_triangles_adjacency_code_string;
4713
4714 break;
4715 }
4716
4717 default:
4718 {
4719 TCU_FAIL("Unrecognized draw call mode");
4720 }
4721 } /* switch (m_drawcall_mode) */
4722
4723 break;
4724 } /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */
4725
4726 default:
4727 {
4728 TCU_FAIL("Unsupported shader output type");
4729 }
4730 } /* switch (drawcall_mode) */
4731
4732 return result;
4733 }
4734
4735 /** Returns amount of bytes that should be allocated for a buffer object to hold
4736 * vertex data to be used for glDrawArrays*() calls.
4737 *
4738 * @param instanced True if the data is to be used in regard to instanced draw calls,
4739 * false otherwise.
4740 *
4741 * @return As per description.
4742 **/
getRawArraysDataBufferSize(bool instanced)4743 glw::GLuint GeometryShaderRenderingTrianglesCase::getRawArraysDataBufferSize(bool instanced)
4744 {
4745 return instanced ? m_raw_array_instanced_data_size : m_raw_array_noninstanced_data_size;
4746 }
4747
4748 /** Returns vertex data for the test. Only to be used for glDrawArrays*() calls.
4749 *
4750 * @param instanced True if the data is to be used in regard to instanced draw calls,
4751 * false otherwise.
4752 *
4753 * @return As per description.
4754 **/
getRawArraysDataBuffer(bool instanced)4755 const void* GeometryShaderRenderingTrianglesCase::getRawArraysDataBuffer(bool instanced)
4756 {
4757 return instanced ? m_raw_array_instanced_data : m_raw_array_noninstanced_data;
4758 }
4759
4760 /** Retrieves resolution of off-screen rendering buffer that should be used for the test.
4761 *
4762 * @param n_instances Amount of draw call instances this render target will be used for.
4763 * @param out_width Deref will be used to store rendertarget's width. Must not be NULL.
4764 * @param out_height Deref will be used to store rendertarget's height. Must not be NULL.
4765 **/
getRenderTargetSize(unsigned int n_instances,unsigned int * out_width,unsigned int * out_height)4766 void GeometryShaderRenderingTrianglesCase::getRenderTargetSize(unsigned int n_instances, unsigned int* out_width,
4767 unsigned int* out_height)
4768 {
4769 switch (m_output_type)
4770 {
4771 case SHADER_OUTPUT_TYPE_LINE_STRIP:
4772 case SHADER_OUTPUT_TYPE_POINTS:
4773 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
4774 {
4775 *out_width = 29; /* as per test spec */
4776 *out_height = 29 * n_instances; /* as per test spec */
4777
4778 break;
4779 }
4780
4781 default:
4782 {
4783 TCU_FAIL("Unsupported output type");
4784 }
4785 }
4786 }
4787
4788 /** Returns amount of bytes that should be allocated for a buffer object to hold
4789 * vertex data to be used for glDrawElements*() calls.
4790 *
4791 * @param instanced true if the call is being made for an instanced draw call, false otherwise.
4792 *
4793 * @return As per description.
4794 **/
getUnorderedArraysDataBufferSize(bool instanced)4795 glw::GLuint GeometryShaderRenderingTrianglesCase::getUnorderedArraysDataBufferSize(bool instanced)
4796 {
4797 return (instanced) ? m_unordered_array_instanced_data_size : m_unordered_array_noninstanced_data_size;
4798 }
4799
4800 /** Returns vertex data for the test. Only to be used for glDrawElements*() calls.
4801 *
4802 * @param instanced true if the call is being made for an instanced draw call, false otherwise.
4803 *
4804 * @return As per description.
4805 **/
getUnorderedArraysDataBuffer(bool instanced)4806 const void* GeometryShaderRenderingTrianglesCase::getUnorderedArraysDataBuffer(bool instanced)
4807 {
4808 return instanced ? m_unordered_array_instanced_data : m_unordered_array_noninstanced_data;
4809 }
4810
4811 /** Returns amount of bytes that should be allocated for a buffer object to hold
4812 * index data to be used for glDrawElements*() calls.
4813 *
4814 * @param instanced true if the call is being made for an instanced draw call, false otherwise.
4815 *
4816 * @return As per description.
4817 **/
getUnorderedElementsDataBufferSize(bool instanced)4818 glw::GLuint GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataBufferSize(bool instanced)
4819 {
4820 return instanced ? m_unordered_elements_instanced_data_size : m_unordered_elements_noninstanced_data_size;
4821 }
4822
4823 /** Returns index data for the test. Only to be used for glDrawElements*() calls.
4824 *
4825 * @param instanced true if the call is being made for an instanced draw call, false otherwise.
4826 *
4827 * @return As per description.
4828 **/
getUnorderedElementsDataBuffer(bool instanced)4829 const void* GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataBuffer(bool instanced)
4830 {
4831 return instanced ? m_unordered_elements_instanced_data : m_unordered_elements_noninstanced_data;
4832 }
4833
4834 /** Returns type of the index, to be used for glDrawElements*() calls.
4835 *
4836 * @return As per description.
4837 **/
getUnorderedElementsDataType()4838 glw::GLenum GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataType()
4839 {
4840 return GL_UNSIGNED_BYTE;
4841 }
4842
4843 /** Retrieves maximum index value. To be used for glDrawRangeElements() test only.
4844 *
4845 * @return As per description.
4846 **/
getUnorderedElementsMaxIndex()4847 glw::GLubyte GeometryShaderRenderingTrianglesCase::getUnorderedElementsMaxIndex()
4848 {
4849 return m_unordered_elements_max_index;
4850 }
4851
4852 /** Retrieves minimum index value. To be used for glDrawRangeElements() test only.
4853 *
4854 * @return As per description.
4855 **/
getUnorderedElementsMinIndex()4856 glw::GLubyte GeometryShaderRenderingTrianglesCase::getUnorderedElementsMinIndex()
4857 {
4858 return m_unordered_elements_min_index;
4859 }
4860
4861 /** Retrieves vertex shader code to be used for the test.
4862 *
4863 * @return As per description.
4864 **/
getVertexShaderCode()4865 std::string GeometryShaderRenderingTrianglesCase::getVertexShaderCode()
4866 {
4867 static std::string vs_code =
4868 "${VERSION}\n"
4869 "\n"
4870 "in vec4 position;\n"
4871 "out vec4 vs_gs_color;\n"
4872 "\n"
4873 "uniform bool is_lines_output;\n"
4874 "uniform bool is_indexed_draw_call;\n"
4875 "uniform bool is_instanced_draw_call;\n"
4876 "uniform bool is_points_output;\n"
4877 "uniform bool is_triangle_fan_input;\n"
4878 "uniform bool is_triangle_strip_input;\n"
4879 "uniform bool is_triangle_strip_adjacency_input;\n"
4880 "uniform bool is_triangles_adjacency_input;\n"
4881 "uniform bool is_triangles_input;\n"
4882 "uniform bool is_triangles_output;\n"
4883 "uniform ivec2 renderingTargetSize;\n"
4884 "uniform ivec2 singleRenderingTargetSize;\n"
4885 "\n"
4886 "void main()\n"
4887 "{\n"
4888 " gl_Position = position + vec4(float(gl_InstanceID) ) * vec4(0, float(singleRenderingTargetSize.y) / "
4889 "float(renderingTargetSize.y), 0, 0) * vec4(2.0);\n"
4890 " vs_gs_color = vec4(1.0, 0.0, 0.0, 0.0);\n"
4891 "\n"
4892 /*********************************** LINES OUTPUT *******************************/
4893 " if (is_lines_output)\n"
4894 " {\n"
4895 " if (!is_indexed_draw_call)\n"
4896 " {\n"
4897 /* Non-indiced draw calls: */
4898 /* GL_TRIANGLE_FAN draw call mode */
4899 " if (is_triangle_fan_input)\n"
4900 " {\n"
4901 " switch(gl_VertexID)\n"
4902 " {\n"
4903 " case 0: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4904 " case 1:\n"
4905 " case 5: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4906 " case 2: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4907 " case 3: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4908 " case 4: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4909 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
4910 " }\n" /* switch(gl_VertexID) */
4911 " }\n" /* if (is_triangle_fan_input) */
4912 " else\n"
4913 /* GL_TRIANGLE_STRIP draw call mode */
4914 " if (is_triangle_strip_input)\n"
4915 " {\n"
4916 " switch(gl_VertexID)\n"
4917 " {\n"
4918 " case 1:\n"
4919 " case 6: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4920 " case 0:\n"
4921 " case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4922 " case 2: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4923 " case 3: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4924 " case 5: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4925 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
4926 " }\n" /* switch(gl_VertexID) */
4927 " }\n" /* if (is_triangle_strip_input) */
4928 " else\n"
4929 /* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */
4930 " if (is_triangle_strip_adjacency_input)\n"
4931 " {\n"
4932 " switch(gl_VertexID)\n"
4933 " {\n"
4934 " case 2:\n"
4935 " case 12: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4936 " case 0:\n"
4937 " case 8: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4938 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4939 " case 6: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4940 " case 10: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4941 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
4942 " }\n" /* switch(gl_VertexID) */
4943 " }\n" /* if (is_triangle_strip_adjacency_input) */
4944 " else\n"
4945 " if (is_triangles_input)\n"
4946 " {\n"
4947 /* GL_TRIANGLES draw call mode */
4948 " switch(gl_VertexID)\n"
4949 " {\n"
4950 " case 0: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4951 " case 1: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4952 " case 2: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4953 " case 3: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4954 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4955 " case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4956 " case 6: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4957 " case 7: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4958 " case 8: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4959 " case 9: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4960 " case 10: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4961 " case 11: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4962 " }\n" /* switch(gl_VertexID) */
4963 " }\n" /* if (is_triangles_input) */
4964 " else\n"
4965 " if (is_triangles_adjacency_input)\n"
4966 " {\n"
4967 /* GL_TRIANGLES_ADJACENCY_EXT draw call mode */
4968 " vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
4969 "\n"
4970 " switch(gl_VertexID)\n"
4971 " {\n"
4972 /* TL triangle */
4973 " case 0: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4974 " case 2: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4975 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4976 /* TR triangle */
4977 " case 6: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4978 " case 8: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4979 " case 10: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4980 /* BR triangle */
4981 " case 12: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4982 " case 14: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4983 " case 16: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4984 /* BL triangle */
4985 " case 18: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4986 " case 20: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4987 " case 22: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4988 " }\n" /* switch (gl_VertexID) */
4989 " }\n" /* if (is_triangles_adjacency_input) */
4990 " }\n" /* if (!is_indexed_draw_call) */
4991 " else\n"
4992 " {\n"
4993 /* Indiced draw call: */
4994 " if (is_triangles_input)\n"
4995 " {\n"
4996 /* GL_TRIANGLES draw call mode */
4997 " switch(gl_VertexID)\n"
4998 " {\n"
4999 " case 11: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5000 " case 10: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5001 " case 9: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5002 " case 8: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5003 " case 7: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5004 " case 6: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5005 " case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5006 " case 4: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5007 " case 3: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5008 " case 2: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5009 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5010 " case 0: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5011 " }\n" /* switch(gl_VertexID) */
5012 " }\n" /* if (is_triangles_input) */
5013 " else\n"
5014 " if (is_triangle_fan_input)\n"
5015 " {\n"
5016 /* GL_TRIANGLE_FAN draw call mode */
5017 " switch(gl_VertexID)\n"
5018 " {\n"
5019 " case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5020 " case 4:\n"
5021 " case 0: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5022 " case 3: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5023 " case 2: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5024 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5025 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5026 " }\n" /* switch(gl_VertexID) */
5027 " }\n" /*( if (is_triangle_fan_input) */
5028 " else\n"
5029 " if (is_triangle_strip_input)\n"
5030 " {\n"
5031 /* GL_TRIANGLE_STRIP draw call mode */
5032 " switch (gl_VertexID)\n"
5033 " {\n"
5034 " case 5:\n"
5035 " case 0: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5036 " case 6:\n"
5037 " case 2: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5038 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5039 " case 3: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5040 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5041 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5042 " }\n" /* switch(gl_VertexID) */
5043 " }\n" /* if (is_triangle_strip_input) */
5044 " else\n"
5045 " if (is_triangle_strip_adjacency_input)\n"
5046 " {\n"
5047 /* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */
5048 " switch(gl_VertexID)\n"
5049 " {\n"
5050 " case 11:\n"
5051 " case 1: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5052 " case 13:\n"
5053 " case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5054 " case 9: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5055 " case 7: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5056 " case 3: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5057 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5058 " }\n" /* switch(gl_VertexID) */
5059 " }\n" /* if (is_triangle_strip_adjacency_input) */
5060 " else\n"
5061 " if (is_triangles_adjacency_input)\n"
5062 " {\n"
5063 /* GL_TRIANGLES_ADJACENCY_EXT draw call mode */
5064 " vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
5065 "\n"
5066 " switch(gl_VertexID)\n"
5067 " {\n"
5068 /* TL triangle */
5069 " case 23: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5070 " case 21: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5071 " case 19: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5072 /* TR triangle */
5073 " case 17: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5074 " case 15: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5075 " case 13: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5076 /* BR triangle */
5077 " case 11: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5078 " case 9: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5079 " case 7: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5080 /* BL triangle */
5081 " case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5082 " case 3: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5083 " case 1: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5084 " }\n" /* switch(gl_VertexID) */
5085 " }\n" /* if (is_triangles_adjacency_input) */
5086 " }\n"
5087 " }\n" /* if (is_lines_output) */
5088 " else\n"
5089 /*********************************** POINTS OUTPUT *******************************/
5090 " if (is_points_output)\n"
5091 " {\n"
5092 " if (!is_indexed_draw_call)\n"
5093 " {\n"
5094 /* Non-indiced draw calls */
5095 " if (is_triangles_adjacency_input)\n"
5096 " {\n"
5097 /* GL_TRIANGLES_ADJACENCY_EXT draw call mode */
5098 " vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
5099 "\n"
5100 " switch (gl_VertexID)\n"
5101 " {\n"
5102 " case 0:\n"
5103 " case 6:\n"
5104 " case 12:\n"
5105 " case 18: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5106 " case 2:\n"
5107 " case 22: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5108 " case 4:\n"
5109 " case 8: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5110 " case 10:\n"
5111 " case 14: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5112 " case 16:\n"
5113 " case 20: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5114 " }\n" /* switch (gl_VertexID) */
5115 " }\n" /* if (is_triangles_adjacency_input) */
5116 " else\n"
5117 " if (is_triangle_fan_input)\n"
5118 " {\n"
5119 /* GL_TRIANGLE_FAN draw call mode */
5120 " switch(gl_VertexID)\n"
5121 " {\n"
5122 " case 0: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5123 " case 1:\n"
5124 " case 5: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5125 " case 2: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5126 " case 3: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5127 " case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5128 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5129 " }\n" /* switch(gl_VertexID) */
5130 " }\n" /* if (is_triangle_fan_input) */
5131 " else\n"
5132 " if (is_triangle_strip_input)\n"
5133 " {\n"
5134 /* GL_TRIANGLE_STRIP draw call mode */
5135 " switch (gl_VertexID)\n"
5136 " {\n"
5137 " case 1:\n"
5138 " case 4: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5139 " case 0:\n"
5140 " case 6: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5141 " case 2: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5142 " case 3: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5143 " case 5: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5144 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5145 " }\n" /* switch(gl_VertexID) */
5146 " }\n" /* if (is_triangle_strip_input) */
5147 " else\n"
5148 " if (is_triangle_strip_adjacency_input)\n"
5149 " {\n"
5150 /* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */
5151 " switch (gl_VertexID)\n"
5152 " {\n"
5153 " case 2:\n"
5154 " case 8: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5155 " case 0:\n"
5156 " case 12: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5157 " case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5158 " case 6: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5159 " case 10: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5160 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5161 " }\n" /* switch(gl_VertexID) */
5162 " }\n" /* if (is_triangle_strip_input) */
5163 " else\n"
5164 " if (is_triangles_input)\n"
5165 " {\n"
5166 /* GL_TRIANGLES draw call mode */
5167 " switch (gl_VertexID)\n"
5168 " {\n"
5169 /* A */
5170 " case 0:\n"
5171 " case 3:\n"
5172 " case 6:\n"
5173 " case 9: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5174 /* B */
5175 " case 1:\n"
5176 " case 11: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5177 /* C */
5178 " case 2:\n"
5179 " case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5180 /* D */
5181 " case 5:\n"
5182 " case 7: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5183 /* E */
5184 " case 8:\n"
5185 " case 10: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5186 " }\n" /* switch (gl_VertexID) */
5187 " }\n" /* if (is_triangles_input) */
5188 " }\n" /* if (!is_indexed_draw_call) "*/
5189 " else\n"
5190 " {\n"
5191 /* Indiced draw calls: */
5192 " if (is_triangle_fan_input)\n"
5193 " {\n"
5194 /* GL_TRIANGLE_FAN input */
5195 " switch (gl_VertexID)\n"
5196 " {\n"
5197 " case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5198 " case 4:\n"
5199 " case 0: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5200 " case 3: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5201 " case 2: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5202 " case 1: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5203 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5204 " }\n" /* switch(gl_VertexID) */
5205 " }\n" /* if (is_triangle_fan_input) */
5206 " else\n"
5207 " if (is_triangle_strip_input)\n"
5208 " {\n"
5209 " switch (gl_VertexID)\n"
5210 " {\n"
5211 " case 5:\n"
5212 " case 2: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5213 " case 6:\n"
5214 " case 0: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5215 " case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5216 " case 3: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5217 " case 1: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5218 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5219 " }\n" /* switch(gl_VertexID) */
5220 " }\n" /* if (is_triangle_strip_input) */
5221 " else\n"
5222 " if (is_triangle_strip_adjacency_input)\n"
5223 " {\n"
5224 /* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */
5225 " switch (gl_VertexID)\n"
5226 " {\n"
5227 " case 11:\n"
5228 " case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5229 " case 13:\n"
5230 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5231 " case 9: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5232 " case 7: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5233 " case 3: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5234 " default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5235 " }\n" /* switch(gl_VertexID) */
5236 " }\n" /* if (is_triangle_strip_adjacency_input) */
5237 " else\n"
5238 " if (is_triangles_adjacency_input)\n"
5239 " {\n"
5240 " vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
5241 /* GL_TRIANGLES_ADJACENCY_EXT input */
5242 " switch (gl_VertexID)\n"
5243 " {\n"
5244 /* A */
5245 " case 23:\n"
5246 " case 17:\n"
5247 " case 11:\n"
5248 " case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5249 /* B */
5250 " case 21:\n"
5251 " case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5252 /* C */
5253 " case 19:\n"
5254 " case 15: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5255 /* D */
5256 " case 13:\n"
5257 " case 9: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5258 /* E */
5259 " case 7:\n"
5260 " case 3: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5261 " }\n" /* switch (gl_VertexID) */
5262 " }\n" /* if (is_triangles_adjacency_input) */
5263 " else\n"
5264 " if (is_triangles_input)\n"
5265 " {\n"
5266 /* GL_TRIANGLES input */
5267 " switch (gl_VertexID)\n"
5268 " {\n"
5269 " case 11:\n"
5270 " case 8:\n"
5271 " case 5:\n"
5272 " case 2: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5273 " case 10:\n"
5274 " case 0: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5275 " case 9:\n"
5276 " case 7: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5277 " case 6:\n"
5278 " case 4: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5279 " case 3:\n"
5280 " case 1: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5281 " }\n" /* switch (gl_VertexID) */
5282 " }\n" /* if (is_triangles_input) */
5283 " }\n"
5284 " }\n" /* if (is_points_output) */
5285 " else\n"
5286 /*********************************** TRIANGLES OUTPUT *******************************/
5287 " if (is_triangles_output)\n"
5288 " {\n"
5289 " int vertex_id = 0;\n"
5290 "\n"
5291 " if (!is_indexed_draw_call && is_triangles_adjacency_input && (gl_VertexID % 2 == 0) )\n"
5292 " {\n"
5293 " vertex_id = gl_VertexID / 2 + 1;\n"
5294 " }\n"
5295 " else\n"
5296 " {\n"
5297 " vertex_id = gl_VertexID + 1;\n"
5298 " }\n"
5299 "\n"
5300 " vs_gs_color = vec4(float(vertex_id) / 48.0, float(vertex_id % 3) / 2.0, float(vertex_id % 4) / 3.0, "
5301 "float(vertex_id % 5) / 4.0);\n"
5302 " }\n"
5303 "}\n";
5304 std::string result;
5305
5306 switch (m_output_type)
5307 {
5308 case SHADER_OUTPUT_TYPE_LINE_STRIP:
5309 case SHADER_OUTPUT_TYPE_POINTS:
5310 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
5311 {
5312 result = vs_code;
5313
5314 break;
5315 }
5316
5317 default:
5318 {
5319 TCU_FAIL("Unrecognized output type");
5320 }
5321 } /* switch (m_output_type) */
5322
5323 return result;
5324 }
5325
5326 /** Sets test-specific uniforms for a program object that is then used for the draw call.
5327 *
5328 * @param drawcall_type Type of the draw call that is to follow right after this function is called.
5329 **/
setUniformsBeforeDrawCall(_draw_call_type drawcall_type)5330 void GeometryShaderRenderingTrianglesCase::setUniformsBeforeDrawCall(_draw_call_type drawcall_type)
5331 {
5332 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5333
5334 glw::GLint is_lines_output_uniform_location = gl.getUniformLocation(m_po_id, "is_lines_output");
5335 glw::GLint is_indexed_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_indexed_draw_call");
5336 glw::GLint is_instanced_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_instanced_draw_call");
5337 glw::GLint is_points_output_uniform_location = gl.getUniformLocation(m_po_id, "is_points_output");
5338 glw::GLint is_triangle_fan_input_uniform_location = gl.getUniformLocation(m_po_id, "is_triangle_fan_input");
5339 glw::GLint is_triangle_strip_input_uniform_location = gl.getUniformLocation(m_po_id, "is_triangle_strip_input");
5340 glw::GLint is_triangle_strip_adjacency_input_uniform_location =
5341 gl.getUniformLocation(m_po_id, "is_triangle_strip_adjacency_input");
5342 glw::GLint is_triangles_adjacency_input_uniform_location =
5343 gl.getUniformLocation(m_po_id, "is_triangles_adjacency_input");
5344 glw::GLint is_triangles_input_uniform_location = gl.getUniformLocation(m_po_id, "is_triangles_input");
5345 glw::GLint is_triangles_output_uniform_location = gl.getUniformLocation(m_po_id, "is_triangles_output");
5346
5347 gl.uniform1i(is_lines_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_LINE_STRIP);
5348 gl.uniform1i(is_points_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_POINTS);
5349 gl.uniform1i(is_triangle_fan_input_uniform_location, m_drawcall_mode == GL_TRIANGLE_FAN);
5350 gl.uniform1i(is_triangle_strip_input_uniform_location, m_drawcall_mode == GL_TRIANGLE_STRIP);
5351 gl.uniform1i(is_triangles_adjacency_input_uniform_location, m_drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT);
5352 gl.uniform1i(is_triangle_strip_adjacency_input_uniform_location,
5353 m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT);
5354 gl.uniform1i(is_triangles_input_uniform_location, m_drawcall_mode == GL_TRIANGLES);
5355 gl.uniform1i(is_triangles_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_TRIANGLE_STRIP);
5356 gl.uniform1i(is_indexed_draw_call_uniform_location, (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
5357 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED ||
5358 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS));
5359 gl.uniform1i(is_instanced_draw_call_uniform_location,
5360 (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED) ||
5361 (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED));
5362 }
5363
5364 /** Verifies that the rendered data is correct.
5365 *
5366 * @param drawcall_type Type of the draw call that was used to render the geometry.
5367 * @param instance_id Instance ID to be verified. Use 0 for non-instanced draw calls.
5368 * @param data Contents of the rendertarget after the test has finished rendering.
5369 **/
verify(_draw_call_type drawcall_type,unsigned int instance_id,const unsigned char * data)5370 void GeometryShaderRenderingTrianglesCase::verify(_draw_call_type drawcall_type, unsigned int instance_id,
5371 const unsigned char* data)
5372 {
5373 const float epsilon = 1.0f / 256.0f;
5374 float dx = 0.0f;
5375 float dy = 0.0f;
5376 unsigned int single_rt_height = 0;
5377 unsigned int single_rt_width = 0;
5378
5379 getRenderTargetSize(1, &single_rt_width, &single_rt_height);
5380
5381 dx = 2.0f / float(single_rt_width);
5382 dy = 2.0f / float(single_rt_height);
5383
5384 switch (m_output_type)
5385 {
5386 case SHADER_OUTPUT_TYPE_LINE_STRIP:
5387 {
5388 /* Reference color data, taken directly from vertex shader. These are assigned
5389 * to subsequent vertex ids, starting from 0.
5390 */
5391 const float ref_color_data[] = { /* TL triangle */
5392 0.1f, 0.2f, 0.3f, 0.4f, 0.2f, 0.3f, 0.4f, 0.5f, 0.3f, 0.4f, 0.5f, 0.6f,
5393 /* TR triangle */
5394 0.1f, 0.2f, 0.3f, 0.4f, 0.3f, 0.4f, 0.5f, 0.6f, 0.4f, 0.5f, 0.6f, 0.7f,
5395 /* BR triangle */
5396 0.1f, 0.2f, 0.3f, 0.4f, 0.4f, 0.5f, 0.6f, 0.7f, 0.5f, 0.6f, 0.7f, 0.8f,
5397 /* BL triangle */
5398 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.2f, 0.3f, 0.4f, 0.5f
5399 };
5400
5401 /* Assuming single-instanced case, the test divides the screen-space into four adjacent quads.
5402 * Internal edges will overlap. Given their different coloring, we exclude them from verification.
5403 * This means we're only interested in checking the quad exteriors.
5404 *
5405 * GS takes a single triangle (ABC), calculates max & min XY of the BB and:
5406 * - uses (A.r, A.g, A.b, A.a) for left line segment (bottom left->top-left) (line segment index in code:0)
5407 * - uses (B.r, B.g, B.b, B.a) for top line segment (top-left->top-right) (line segment index in code:1)
5408 * - uses (C.r, C.g, C.b, C.a) for right line segment (top-right->bottom-right) (line segment index in code:2)
5409 * - uses (A.r, B.g, C.b, A.a) for bottom line segment (bottom-right->bottom-left) (line segment index in code:3)
5410 *
5411 * The test feeds input triangles arranged in the following order:
5412 * 1) Top-left corner; (quarter index in code:0);
5413 * 2) Top-right corner; (quarter index in code:1);
5414 * 3) Bottom-right corner; (quarter index in code:2);
5415 * 4) Bottom-left corner; (quarter index in code:3);
5416 *
5417 * The test renders line segments of width 3 by rendering three lines of width 1 next to each other.
5418 *
5419 * Sample locations are precomputed - they are centers of line segments being considered.
5420 *
5421 * Expected color is computed on-the-fly in code, to ease investigation for driver developers,
5422 * in case this test fails on any ES (or GL) implementation.
5423 */
5424 int ref_line_segment_index = -1;
5425 int ref_quarter_index = -1;
5426 float ref_sample_rgba[4] = { 0, 0, 0, 0 };
5427 float ref_sample_xy_float[2] = { 0 };
5428 int ref_sample_xy_int[2] = { 0 };
5429 int ref_triangle_index = -1;
5430
5431 for (int n_edge = 0; n_edge < 8 /* edges */; ++n_edge)
5432 {
5433 switch (n_edge)
5434 {
5435 case 0:
5436 {
5437 /* Top left half, left edge */
5438 ref_line_segment_index = 0;
5439 ref_quarter_index = 0;
5440 ref_triangle_index = 0;
5441
5442 break;
5443 }
5444
5445 case 1:
5446 {
5447 /* Top-left half, top edge. */
5448 ref_line_segment_index = 1;
5449 ref_quarter_index = 0;
5450 ref_triangle_index = 0;
5451
5452 break;
5453 }
5454
5455 case 2:
5456 {
5457 /* Top-right half, top edge. */
5458 ref_line_segment_index = 1;
5459 ref_quarter_index = 1;
5460 ref_triangle_index = 1;
5461
5462 break;
5463 }
5464
5465 case 3:
5466 {
5467 /* Top-right half, right edge. */
5468 ref_line_segment_index = 2;
5469 ref_quarter_index = 1;
5470 ref_triangle_index = 1;
5471
5472 break;
5473 }
5474
5475 case 4:
5476 {
5477 /* Bottom-right half, right edge. */
5478 ref_line_segment_index = 2;
5479 ref_quarter_index = 2;
5480 ref_triangle_index = 2;
5481
5482 break;
5483 }
5484
5485 case 5:
5486 {
5487 /* Bottom-right half, bottom edge. */
5488 ref_line_segment_index = 3;
5489 ref_quarter_index = 2;
5490 ref_triangle_index = 2;
5491
5492 break;
5493 }
5494
5495 case 6:
5496 {
5497 /* Bottom-left half, bottom edge. */
5498 ref_line_segment_index = 3;
5499 ref_quarter_index = 3;
5500 ref_triangle_index = 3;
5501
5502 break;
5503 }
5504
5505 case 7:
5506 {
5507 /* Bottom-left half, left edge. */
5508 ref_line_segment_index = 0;
5509 ref_quarter_index = 3;
5510 ref_triangle_index = 3;
5511
5512 break;
5513 }
5514
5515 default:
5516 {
5517 TCU_FAIL("Unrecognized edge index");
5518 }
5519 } /* switch (n_edge) */
5520
5521 /* Compute reference color.
5522 *
5523 * When drawing with GL_TRIANGLE_STRIP data or GL_TRIANGLE_STRIP_ADJACENCY_EXT, top-right triangle is drawn two times.
5524 * During second re-draw, a different combination of vertex colors is used.
5525 * Take this into account.
5526 */
5527 switch (ref_line_segment_index)
5528 {
5529 case 0:
5530 {
5531 /* Left segment */
5532 memcpy(ref_sample_rgba,
5533 ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5534 0 /* first vertex data */,
5535 sizeof(float) * 4 /* components */);
5536
5537 if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) &&
5538 ref_triangle_index == 1 /* top-right triangle */)
5539 {
5540 /* First vertex */
5541 ref_sample_rgba[0] = 0.3f;
5542 ref_sample_rgba[1] = 0.4f;
5543 ref_sample_rgba[2] = 0.5f;
5544 ref_sample_rgba[3] = 0.6f;
5545 }
5546
5547 break;
5548 }
5549
5550 case 1:
5551 {
5552 /* Top segment */
5553 memcpy(ref_sample_rgba,
5554 ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5555 4 /* second vertex data */,
5556 sizeof(float) * 4 /* components */);
5557
5558 if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) &&
5559 ref_triangle_index == 1 /* top-right triangle */)
5560 {
5561 /* Second vertex */
5562 ref_sample_rgba[0] = 0.4f;
5563 ref_sample_rgba[1] = 0.5f;
5564 ref_sample_rgba[2] = 0.6f;
5565 ref_sample_rgba[3] = 0.7f;
5566 }
5567 break;
5568 }
5569
5570 case 2:
5571 {
5572 /* Right segment */
5573 memcpy(ref_sample_rgba,
5574 ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5575 8 /* third vertex data */,
5576 sizeof(float) * 4 /* components */);
5577
5578 if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) &&
5579 ref_triangle_index == 1 /* top-right triangle */)
5580 {
5581 /* Third vertex */
5582 ref_sample_rgba[0] = 0.1f;
5583 ref_sample_rgba[1] = 0.2f;
5584 ref_sample_rgba[2] = 0.3f;
5585 ref_sample_rgba[3] = 0.4f;
5586 }
5587
5588 break;
5589 }
5590
5591 case 3:
5592 {
5593 /* Bottom segment */
5594 ref_sample_rgba[0] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5595 0 /* 1st vertex, red */];
5596 ref_sample_rgba[1] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5597 5 /* 2nd vertex, green */];
5598 ref_sample_rgba[2] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5599 10 /* 3rd vertex, blue */];
5600 ref_sample_rgba[3] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5601 3 /* 1st vertex, alpha */];
5602
5603 if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) &&
5604 ref_triangle_index == 1 /* top-right triangle */)
5605 {
5606 /* Combination of components of three vertices */
5607 ref_sample_rgba[0] = 0.3f;
5608 ref_sample_rgba[1] = 0.5f;
5609 ref_sample_rgba[2] = 0.3f;
5610 ref_sample_rgba[3] = 0.6f;
5611 }
5612
5613 break;
5614 }
5615
5616 default:
5617 {
5618 TCU_FAIL("Unrecognized line segment index");
5619 }
5620 }
5621
5622 /* Retrieve quad coordinates */
5623 float quad_x1y1x2y2[4] = { 0 };
5624
5625 switch (ref_quarter_index)
5626 {
5627 case 0:
5628 {
5629 /* Top-left quarter */
5630 quad_x1y1x2y2[0] = 0.0f;
5631 quad_x1y1x2y2[1] = 0.0f;
5632 quad_x1y1x2y2[2] = 0.5f;
5633 quad_x1y1x2y2[3] = 0.5f;
5634
5635 break;
5636 }
5637
5638 case 1:
5639 {
5640 /* Top-right quarter */
5641 quad_x1y1x2y2[0] = 0.5f;
5642 quad_x1y1x2y2[1] = 0.0f;
5643 quad_x1y1x2y2[2] = 1.0f;
5644 quad_x1y1x2y2[3] = 0.5f;
5645
5646 break;
5647 }
5648
5649 case 2:
5650 {
5651 /* Bottom-right quarter */
5652 quad_x1y1x2y2[0] = 0.5f;
5653 quad_x1y1x2y2[1] = 0.5f;
5654 quad_x1y1x2y2[2] = 1.0f;
5655 quad_x1y1x2y2[3] = 1.0f;
5656
5657 break;
5658 }
5659
5660 case 3:
5661 {
5662 /* Bottom-left quarter */
5663 quad_x1y1x2y2[0] = 0.0f;
5664 quad_x1y1x2y2[1] = 0.5f;
5665 quad_x1y1x2y2[2] = 0.5f;
5666 quad_x1y1x2y2[3] = 1.0f;
5667
5668 break;
5669 }
5670
5671 default:
5672 {
5673 TCU_FAIL("Unrecognized quarter index");
5674 }
5675 } /* switch (ref_quarter_index) */
5676
5677 /* Reduce quad coordinates to line segment coordinates */
5678 switch (ref_line_segment_index)
5679 {
5680 case 0:
5681 {
5682 /* Left segment */
5683 quad_x1y1x2y2[2] = quad_x1y1x2y2[0];
5684
5685 break;
5686 }
5687
5688 case 1:
5689 {
5690 /* Top segment */
5691 quad_x1y1x2y2[3] = quad_x1y1x2y2[1];
5692
5693 break;
5694 }
5695
5696 case 2:
5697 {
5698 /* Right segment */
5699 quad_x1y1x2y2[0] = quad_x1y1x2y2[2];
5700
5701 break;
5702 }
5703
5704 case 3:
5705 {
5706 /* Bottom segment */
5707 quad_x1y1x2y2[1] = quad_x1y1x2y2[3];
5708
5709 break;
5710 }
5711
5712 default:
5713 {
5714 TCU_FAIL("Unrecognized line segment index");
5715 }
5716 }
5717
5718 /* Compute sample location. Move one pixel ahead in direction of the bottom-right corner to make
5719 * sure we sample from the center of the line segment.
5720 **/
5721 ref_sample_xy_float[0] = quad_x1y1x2y2[0] + (quad_x1y1x2y2[2] - quad_x1y1x2y2[0]) * 0.5f;
5722 ref_sample_xy_float[1] = quad_x1y1x2y2[1] + (quad_x1y1x2y2[3] - quad_x1y1x2y2[1]) * 0.5f;
5723
5724 ref_sample_xy_int[0] = int(ref_sample_xy_float[0] * float(single_rt_width - 1));
5725 ref_sample_xy_int[1] = int(ref_sample_xy_float[1] * float(single_rt_height - 1));
5726
5727 /* If this is n-th instance, offset sample locations so that they point to rendering results specific
5728 * to instance of our concern */
5729 ref_sample_xy_int[1] += instance_id * single_rt_height;
5730
5731 /* Compare the rendered data with reference data */
5732 const int pixel_size = 4 /* components */;
5733 const int row_width = single_rt_width * pixel_size;
5734 const unsigned char* rendered_data_ptr =
5735 data + row_width * ref_sample_xy_int[1] + ref_sample_xy_int[0] * pixel_size;
5736 const float rendered_data[4] = { float(rendered_data_ptr[0]) / 255.0f, float(rendered_data_ptr[1]) / 255.0f,
5737 float(rendered_data_ptr[2]) / 255.0f,
5738 float(rendered_data_ptr[3]) / 255.0f };
5739
5740 if (de::abs(rendered_data[0] - ref_sample_rgba[0]) > epsilon ||
5741 de::abs(rendered_data[1] - ref_sample_rgba[1]) > epsilon ||
5742 de::abs(rendered_data[2] - ref_sample_rgba[2]) > epsilon ||
5743 de::abs(rendered_data[3] - ref_sample_rgba[3]) > epsilon)
5744 {
5745 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << ref_sample_xy_int[0] << ", "
5746 << ref_sample_xy_int[1] << ") "
5747 << "equal (" << rendered_data[0] << ", " << rendered_data[1] << ", "
5748 << rendered_data[2] << ", " << rendered_data[3] << ") "
5749 << "exceeds allowed epsilon when compared to reference data equal ("
5750 << ref_sample_rgba[0] << ", " << ref_sample_rgba[1] << ", " << ref_sample_rgba[2]
5751 << ", " << ref_sample_rgba[3] << ")." << tcu::TestLog::EndMessage;
5752
5753 TCU_FAIL("Data comparison failed");
5754 } /* if (data comparison failed) */
5755 } /* for (all edges) */
5756
5757 /* All done */
5758 break;
5759 }
5760
5761 case SHADER_OUTPUT_TYPE_POINTS:
5762 {
5763 /* In this case, the test should have rendered 6 large points.
5764 * Verification checks if centers of these blobs carry valid values.
5765 */
5766 const float ref_data[] = {
5767 /* Position (<-1, 1> x <-1, 1>) */
5768 0.0f, -1.0f + float(instance_id) * 2.0f + dy, /* top */
5769 0.1f, 0.2f,
5770 0.3f, 0.4f, /* rgba */
5771
5772 0.0f, 0.0f + float(instance_id) * 2.0f, /* middle */
5773 0.4f, 0.5f,
5774 0.6f, 0.7f, /* rgba */
5775
5776 -1.0f + dx, 0.0f + float(instance_id) * 2.0f, /* left */
5777 0.5f, 0.6f,
5778 0.7f, 0.8f, /* rgba */
5779
5780 1.0f - dx, 0.0f + float(instance_id) * 2.0f, /* right */
5781 0.2f, 0.3f,
5782 0.4f, 0.5f, /* rgba */
5783
5784 0.0f, 1.0f + float(instance_id) * 2.0f - dy, /* bottom */
5785 0.3f, 0.4f,
5786 0.5f, 0.6f, /* rgba */
5787 };
5788 const unsigned int n_points = 5; /* total number of points to check */
5789
5790 for (unsigned int n_point = 0; n_point < n_points; ++n_point)
5791 {
5792 /* Retrieve data from the array */
5793 tcu::Vec4 color_float = tcu::Vec4(ref_data[n_point * 6 + 2], ref_data[n_point * 6 + 3],
5794 ref_data[n_point * 6 + 4], ref_data[n_point * 6 + 5]);
5795 tcu::Vec2 position_float = tcu::Vec2(ref_data[n_point * 6 + 0], ref_data[n_point * 6 + 1]);
5796
5797 /* Convert position data to texture space */
5798 int position[] = { int((position_float[0] * 0.5f + 0.5f) * float(single_rt_width)),
5799 int((position_float[1] * 0.5f + 0.5f) * float(single_rt_height)) };
5800
5801 /* Compare the data */
5802 const int pixel_size = 4 /* components */;
5803 const int row_width = single_rt_width * pixel_size;
5804 const unsigned char* rendered_data = data + row_width * position[1] + position[0] * pixel_size;
5805 float rendered_data_float[] = { float(rendered_data[0]) / 255.0f, float(rendered_data[1]) / 255.0f,
5806 float(rendered_data[2]) / 255.0f, float(rendered_data[3]) / 255.0f };
5807
5808 if (de::abs(rendered_data_float[0] - color_float[0]) > epsilon ||
5809 de::abs(rendered_data_float[1] - color_float[1]) > epsilon ||
5810 de::abs(rendered_data_float[2] - color_float[2]) > epsilon ||
5811 de::abs(rendered_data_float[3] - color_float[3]) > epsilon)
5812 {
5813 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << position[0] << ", "
5814 << position[1] << ") "
5815 << "equal (" << rendered_data_float[0] << ", " << rendered_data_float[1] << ", "
5816 << rendered_data_float[2] << ", " << rendered_data_float[3] << ") "
5817 << "exceeds allowed epsilon when compared to reference data equal ("
5818 << color_float[0] << ", " << color_float[1] << ", " << color_float[2] << ", "
5819 << color_float[3] << ")." << tcu::TestLog::EndMessage;
5820
5821 TCU_FAIL("Data comparison failed");
5822 }
5823 } /* for (all points) */
5824
5825 break;
5826 }
5827
5828 case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
5829 {
5830 /* The test feeds the rendering pipeline with 4 triangles (per instance), which should
5831 * be converted to 8 differently colored triangles at the geometry shader stage.
5832 */
5833 for (unsigned int n_triangle = 0; n_triangle < 8 /* triangles */; ++n_triangle)
5834 {
5835 /* Retrieve base triangle-specific properties */
5836 tcu::Vec2 base_triangle_v1;
5837 tcu::Vec2 base_triangle_v2;
5838 tcu::Vec2 base_triangle_v3;
5839
5840 switch (n_triangle / 2)
5841 /* two sub-triangles per a triangle must be checked */
5842 {
5843 case 0:
5844 {
5845 /* Top-left triangle */
5846 base_triangle_v1[0] = 0.5f;
5847 base_triangle_v1[1] = 0.5f;
5848 base_triangle_v2[0] = 0.0f;
5849 base_triangle_v2[1] = 0.5f;
5850 base_triangle_v3[0] = 0.5f;
5851 base_triangle_v3[1] = 0.0f;
5852
5853 break;
5854 }
5855
5856 case 1:
5857 {
5858 /* Top-right triangle */
5859 base_triangle_v1[0] = 0.5f;
5860 base_triangle_v1[1] = 0.5f;
5861 base_triangle_v2[0] = 0.5f;
5862 base_triangle_v2[1] = 0.0f;
5863 base_triangle_v3[0] = 1.0f;
5864 base_triangle_v3[1] = 0.5f;
5865
5866 break;
5867 }
5868
5869 case 2:
5870 {
5871 /* Bottom-right triangle */
5872 base_triangle_v1[0] = 0.5f;
5873 base_triangle_v1[1] = 0.5f;
5874 base_triangle_v2[0] = 1.0f;
5875 base_triangle_v2[1] = 0.5f;
5876 base_triangle_v3[0] = 0.5f;
5877 base_triangle_v3[1] = 1.0f;
5878
5879 break;
5880 }
5881
5882 case 3:
5883 {
5884 /* Bottom-left triangle */
5885 base_triangle_v1[0] = 0.5f;
5886 base_triangle_v1[1] = 0.5f;
5887 base_triangle_v2[0] = 0.0f;
5888 base_triangle_v2[1] = 0.5f;
5889 base_triangle_v3[0] = 0.5f;
5890 base_triangle_v3[1] = 1.0f;
5891
5892 break;
5893 }
5894 } /* switch (n_triangle) */
5895
5896 /* Compute coordinates of the iteration-specific triangle. This logic has been
5897 * ported directly from the geometry shader */
5898 tcu::Vec4 expected_sample_color_rgba;
5899 glw::GLuint expected_sample_color_vertex_id = 0;
5900 tcu::Vec2 triangle_vertex1;
5901 tcu::Vec2 triangle_vertex2;
5902 tcu::Vec2 triangle_vertex3;
5903 tcu::Vec2 a = base_triangle_v1;
5904 tcu::Vec2 b;
5905 tcu::Vec2 c;
5906 tcu::Vec2 d;
5907
5908 if (base_triangle_v2.x() == 0.5f && base_triangle_v2.y() == 0.5f)
5909 {
5910 a = base_triangle_v2;
5911
5912 if (de::abs(base_triangle_v1.x() - a.x()) < dx * 0.5f)
5913 {
5914 b = base_triangle_v1;
5915 c = base_triangle_v3;
5916 }
5917 else
5918 {
5919 b = base_triangle_v3;
5920 c = base_triangle_v1;
5921 }
5922 }
5923 else if (base_triangle_v3.x() == 0.5f && base_triangle_v3.y() == 0.5f)
5924 {
5925 a = base_triangle_v3;
5926
5927 if (de::abs(base_triangle_v1.x() - a.x()) < dx * 0.5f)
5928 {
5929 b = base_triangle_v1;
5930 c = base_triangle_v2;
5931 }
5932 else
5933 {
5934 b = base_triangle_v2;
5935 c = base_triangle_v1;
5936 }
5937 }
5938 else
5939 {
5940 if (de::abs(base_triangle_v2.x() - a.x()) < dx * 0.5f)
5941 {
5942 b = base_triangle_v2;
5943 c = base_triangle_v3;
5944 }
5945 else
5946 {
5947 b = base_triangle_v3;
5948 c = base_triangle_v2;
5949 }
5950 }
5951
5952 d = (b + c) * tcu::Vec2(0.5f);
5953
5954 if (n_triangle % 2 == 0)
5955 {
5956 switch (m_drawcall_mode)
5957 {
5958 case GL_TRIANGLES:
5959 case GL_TRIANGLES_ADJACENCY_EXT:
5960 {
5961 /* First sub-triangle */
5962 expected_sample_color_vertex_id = 3 /* vertices per triangle */ * (n_triangle / 2) + 0;
5963
5964 break;
5965 } /* GL_TRIANGLEs or GL_TRIANGLES_ADJACENCY_EXT cases */
5966
5967 case GL_TRIANGLE_FAN:
5968 {
5969 /* First sub-triangle in this case is always assigned vertex id of 0, as 0 stands for
5970 * the hub vertex */
5971 expected_sample_color_vertex_id = 0;
5972
5973 break;
5974 }
5975
5976 case GL_TRIANGLE_STRIP:
5977 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
5978 {
5979 bool is_adjacency_data_present = (m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT);
5980
5981 /* These vertex ids correspond to index of vertex A which changes between triangle
5982 * orientations, hence the repeated expected vertex ID for cases 4 and 6 */
5983 switch (n_triangle)
5984 {
5985 /* Top-left triangle, first sub-triangle */
5986 case 0:
5987 {
5988 expected_sample_color_vertex_id = 0;
5989
5990 break;
5991 }
5992
5993 /* Top-right triangle, first sub-triangle */
5994 case 2:
5995 {
5996 expected_sample_color_vertex_id = 2 * (is_adjacency_data_present ? 2 : 1);
5997
5998 break;
5999 }
6000
6001 /* Bottom-right triangle, first sub-triangle */
6002 case 4:
6003 {
6004 expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1);
6005
6006 break;
6007 }
6008
6009 /* Bottom-left triangle, first sub-triangle */
6010 case 6:
6011 {
6012 expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1);
6013
6014 break;
6015 }
6016
6017 default:
6018 {
6019 TCU_FAIL("Unrecognized triangle index");
6020 }
6021 }
6022
6023 break;
6024 }
6025
6026 default:
6027 {
6028 TCU_FAIL("Unrecognized draw call mode");
6029 }
6030 } /* switch (m_drawcall_mode) */
6031
6032 triangle_vertex1 = a;
6033 triangle_vertex2 = b;
6034 triangle_vertex3 = d;
6035 } /* if (n_triangle % 2 == 0) */
6036 else
6037 {
6038 /* Second sub-triangle */
6039 switch (m_drawcall_mode)
6040 {
6041 case GL_TRIANGLES:
6042 case GL_TRIANGLES_ADJACENCY_EXT:
6043 {
6044 expected_sample_color_vertex_id = 3 /* vertices per triangle */ * (n_triangle / 2) + 2;
6045
6046 break;
6047 }
6048
6049 case GL_TRIANGLE_FAN:
6050 {
6051 expected_sample_color_vertex_id = 2 + n_triangle / 2;
6052
6053 break;
6054 }
6055
6056 case GL_TRIANGLE_STRIP:
6057 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
6058 {
6059 bool is_adjacency_data_present = (m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT);
6060
6061 switch (n_triangle)
6062 {
6063 /* Top-left triangle, second sub-triangle */
6064 case 1:
6065 {
6066 expected_sample_color_vertex_id = 2 * (is_adjacency_data_present ? 2 : 1);
6067
6068 break;
6069 }
6070
6071 /* Top-right triangle, second sub-triangle */
6072 case 3:
6073 {
6074 expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1);
6075
6076 break;
6077 }
6078
6079 /* Bottom-right triangle, second sub-triangle */
6080 case 5:
6081 {
6082 expected_sample_color_vertex_id = 5 * (is_adjacency_data_present ? 2 : 1);
6083
6084 break;
6085 }
6086
6087 /* Bottom-left triangle, second sub-triangle */
6088 case 7:
6089 {
6090 expected_sample_color_vertex_id = 6 * (is_adjacency_data_present ? 2 : 1);
6091
6092 break;
6093 }
6094
6095 default:
6096 {
6097 TCU_FAIL("Unrecognized triangle index");
6098 }
6099 }
6100
6101 break;
6102 }
6103
6104 default:
6105 {
6106 TCU_FAIL("UNrecognized draw call mode");
6107 }
6108 } /* switch (m_drawcall_mode) */
6109
6110 triangle_vertex1 = a;
6111 triangle_vertex2 = c;
6112 triangle_vertex3 = d;
6113 }
6114
6115 if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
6116 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED ||
6117 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS)
6118 {
6119 switch (m_drawcall_mode)
6120 {
6121 case GL_TRIANGLE_FAN:
6122 case GL_TRIANGLE_STRIP:
6123 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
6124 case GL_TRIANGLES:
6125 {
6126 expected_sample_color_vertex_id =
6127 (getAmountOfVerticesPerInstance() - 1) - expected_sample_color_vertex_id;
6128
6129 break;
6130 }
6131
6132 case GL_TRIANGLES_ADJACENCY_EXT:
6133 {
6134 /* In adjacency input, every even vertex is used for rendering. */
6135 expected_sample_color_vertex_id =
6136 (getAmountOfVerticesPerInstance() - 1) - expected_sample_color_vertex_id * 2;
6137
6138 break;
6139 }
6140
6141 default:
6142 {
6143 TCU_FAIL("Unrecognized draw call mode");
6144 }
6145 }
6146 }
6147
6148 /* Compute sample's reference color - logic as in vertex shader */
6149 expected_sample_color_rgba[0] = float((expected_sample_color_vertex_id + 1)) / 48.0f;
6150 expected_sample_color_rgba[1] = float((expected_sample_color_vertex_id + 1) % 3) / 2.0f;
6151 expected_sample_color_rgba[2] = float((expected_sample_color_vertex_id + 1) % 4) / 3.0f;
6152 expected_sample_color_rgba[3] = float((expected_sample_color_vertex_id + 1) % 5) / 4.0f;
6153
6154 if (n_triangle % 2 == 1)
6155 {
6156 expected_sample_color_rgba[0] *= 2.0f;
6157 }
6158
6159 /* Compute sample location */
6160 tcu::Vec2 sample_location;
6161 int sample_location_int[2]; /* X & Y coordinates */
6162
6163 sample_location = (triangle_vertex1 + triangle_vertex2 + triangle_vertex3) / 3.0f;
6164 sample_location_int[0] = int(sample_location[0] * static_cast<float>(single_rt_width - 1) + 0.5f);
6165 sample_location_int[1] = int(sample_location[1] * static_cast<float>(single_rt_height - 1) + 0.5f) +
6166 instance_id * single_rt_height;
6167
6168 /* Retrieve rendered data */
6169 const unsigned int pixel_size = 4 /* components */;
6170 const unsigned int row_width = single_rt_width * pixel_size;
6171 const unsigned char* rendered_data =
6172 data + row_width * sample_location_int[1] + sample_location_int[0] * pixel_size;
6173
6174 tcu::Vec4 rendered_data_rgba =
6175 tcu::Vec4(float(rendered_data[0]) / 255.0f, float(rendered_data[1]) / 255.0f,
6176 float(rendered_data[2]) / 255.0f, float(rendered_data[3]) / 255.0f);
6177
6178 /* Compare rendered data with reference color information */
6179 if (de::abs(rendered_data_rgba[0] - expected_sample_color_rgba[0]) > epsilon ||
6180 de::abs(rendered_data_rgba[1] - expected_sample_color_rgba[1]) > epsilon ||
6181 de::abs(rendered_data_rgba[2] - expected_sample_color_rgba[2]) > epsilon ||
6182 de::abs(rendered_data_rgba[3] - expected_sample_color_rgba[3]) > epsilon)
6183 {
6184 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << sample_location[0] << ", "
6185 << sample_location[1] << ") "
6186 << "equal (" << rendered_data_rgba[0] << ", " << rendered_data_rgba[1] << ", "
6187 << rendered_data_rgba[2] << ", " << rendered_data_rgba[3] << ") "
6188 << "exceeds allowed epsilon when compared to reference data equal ("
6189 << expected_sample_color_rgba[0] << ", " << expected_sample_color_rgba[1] << ", "
6190 << expected_sample_color_rgba[2] << ", " << expected_sample_color_rgba[3] << ")."
6191 << tcu::TestLog::EndMessage;
6192
6193 TCU_FAIL("Data comparison failed");
6194 } /* if (data comparison failed) */
6195 } /* for (all triangles) */
6196 /* All done */
6197 break;
6198 }
6199
6200 default:
6201 {
6202 TCU_FAIL("Unrecognized output type");
6203 }
6204 }
6205 }
6206
6207 } // namespace glcts
6208