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