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