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