• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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