• 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 		break;
1976 	}
1977 	} /* switch(m_output_type) */
1978 }
1979 
1980 /* "lines" input primitive test implementation */
1981 /** Constructor.
1982  *
1983  *  @param use_adjacency_data true  if the test case is being instantiated for draw call modes that will
1984  *                                  features adjacency data,
1985  *                            false otherwise.
1986  *  @param drawcall_mode      GL draw call mode that will be used for the tests.
1987  *  @param output_type        Shader output type that the test case is being instantiated for.
1988  *  @param context            Rendering context;
1989  *  @param testContext        Test context;
1990  *  @param name               Test name.
1991  **/
GeometryShaderRenderingLinesCase(Context & context,const ExtParameters & extParams,const char * name,bool use_adjacency_data,glw::GLenum drawcall_mode,_shader_output_type output_type)1992 GeometryShaderRenderingLinesCase::GeometryShaderRenderingLinesCase(Context& context, const ExtParameters& extParams,
1993 																   const char* name, bool use_adjacency_data,
1994 																   glw::GLenum		   drawcall_mode,
1995 																   _shader_output_type output_type)
1996 	: GeometryShaderRenderingCase(
1997 		  context, extParams, name,
1998 		  "Verifies all draw calls work correctly for specific input+output+draw call mode combination")
1999 	, m_output_type(output_type)
2000 	, m_drawcall_mode(drawcall_mode)
2001 	, m_use_adjacency_data(use_adjacency_data)
2002 	, m_raw_array_instanced_data(0)
2003 	, m_raw_array_instanced_data_size(0)
2004 	, m_raw_array_noninstanced_data(0)
2005 	, m_raw_array_noninstanced_data_size(0)
2006 	, m_unordered_array_instanced_data(0)
2007 	, m_unordered_array_instanced_data_size(0)
2008 	, m_unordered_array_noninstanced_data(0)
2009 	, m_unordered_array_noninstanced_data_size(0)
2010 	, m_unordered_elements_instanced_data(0)
2011 	, m_unordered_elements_instanced_data_size(0)
2012 	, m_unordered_elements_noninstanced_data(0)
2013 	, m_unordered_elements_noninstanced_data_size(0)
2014 	, m_unordered_elements_max_index(16) /* maximum amount of vertices generated for this case */
2015 	, m_unordered_elements_min_index(0)
2016 {
2017 	/* Sanity checks */
2018 	if (!m_use_adjacency_data)
2019 	{
2020 		if (drawcall_mode != GL_LINE_LOOP && drawcall_mode != GL_LINE_STRIP && drawcall_mode != GL_LINES)
2021 		{
2022 			TCU_FAIL("Only GL_LINE_LOOP or GL_LINE_STRIP or GL_LINES draw call modes are supported for 'lines' "
2023 					 "geometry shader input layout qualifier test implementation");
2024 		}
2025 	}
2026 	else
2027 	{
2028 		if (drawcall_mode != GL_LINES_ADJACENCY_EXT && drawcall_mode != GL_LINE_STRIP_ADJACENCY_EXT)
2029 		{
2030 			TCU_FAIL("Only GL_LINES_ADJACENCY_EXT or GL_LINE_STRIP_ADJACENCY_EXT draw call modes are supported for "
2031 					 "'lines_adjacency' geometry shader input layout qualifier test implementation");
2032 		}
2033 	}
2034 
2035 	if (output_type != SHADER_OUTPUT_TYPE_POINTS && output_type != SHADER_OUTPUT_TYPE_LINE_STRIP &&
2036 		output_type != SHADER_OUTPUT_TYPE_TRIANGLE_STRIP)
2037 	{
2038 		TCU_FAIL("Unsupported output layout qualifier type requested for 'lines' geometry shader input layout "
2039 				 "qualifier test implementation");
2040 	}
2041 
2042 	/* Generate data in two flavors - one for non-instanced case, the other one for instanced case */
2043 	for (int n_case = 0; n_case < 2 /* cases */; ++n_case)
2044 	{
2045 		bool			is_instanced					 = (n_case != 0);
2046 		int				n_instances						 = 0;
2047 		float**			raw_arrays_data_ptr				 = NULL;
2048 		unsigned int*   raw_arrays_data_size_ptr		 = NULL;
2049 		unsigned int	rendertarget_height				 = 0;
2050 		unsigned int	rendertarget_width				 = 0;
2051 		float**			unordered_arrays_data_ptr		 = NULL;
2052 		unsigned int*   unordered_arrays_data_size_ptr   = NULL;
2053 		unsigned char** unordered_elements_data_ptr		 = NULL;
2054 		unsigned int*   unordered_elements_data_size_ptr = NULL;
2055 
2056 		if (!is_instanced)
2057 		{
2058 			/* Non-instanced case */
2059 			n_instances						 = 1;
2060 			raw_arrays_data_ptr				 = &m_raw_array_noninstanced_data;
2061 			raw_arrays_data_size_ptr		 = &m_raw_array_noninstanced_data_size;
2062 			unordered_arrays_data_ptr		 = &m_unordered_array_noninstanced_data;
2063 			unordered_arrays_data_size_ptr   = &m_unordered_array_noninstanced_data_size;
2064 			unordered_elements_data_ptr		 = &m_unordered_elements_noninstanced_data;
2065 			unordered_elements_data_size_ptr = &m_unordered_elements_noninstanced_data_size;
2066 		}
2067 		else
2068 		{
2069 			/* Instanced case */
2070 			n_instances						 = getAmountOfDrawInstances();
2071 			raw_arrays_data_ptr				 = &m_raw_array_instanced_data;
2072 			raw_arrays_data_size_ptr		 = &m_raw_array_instanced_data_size;
2073 			unordered_arrays_data_ptr		 = &m_unordered_array_instanced_data;
2074 			unordered_arrays_data_size_ptr   = &m_unordered_array_instanced_data_size;
2075 			unordered_elements_data_ptr		 = &m_unordered_elements_instanced_data;
2076 			unordered_elements_data_size_ptr = &m_unordered_elements_instanced_data_size;
2077 		}
2078 
2079 		getRenderTargetSize(n_instances, &rendertarget_width, &rendertarget_height);
2080 
2081 		/* Store full-screen quad coordinates that will be used for actual array data generation. */
2082 		float dx = 2.0f / float(rendertarget_width);
2083 		float dy = 2.0f / float(rendertarget_height);
2084 
2085 		/* Generate raw vertex array data */
2086 
2087 		float*		 raw_array_data_traveller = NULL;
2088 		unsigned int single_rt_height		  = 0;
2089 		unsigned int single_rt_width		  = 0;
2090 		unsigned int whole_rt_width			  = 0;
2091 		unsigned int whole_rt_height		  = 0;
2092 
2093 		switch (m_drawcall_mode)
2094 		{
2095 		case GL_LINE_LOOP:
2096 		{
2097 			*raw_arrays_data_size_ptr = 4 /* vertices making up the line strip */ * 4 /* components */ * sizeof(float);
2098 
2099 			break;
2100 		}
2101 
2102 		case GL_LINE_STRIP:
2103 		{
2104 			*raw_arrays_data_size_ptr = 5 /* vertices making up the line strip */ * 4 /* components */ * sizeof(float);
2105 
2106 			break;
2107 		}
2108 
2109 		case GL_LINE_STRIP_ADJACENCY_EXT:
2110 		{
2111 			*raw_arrays_data_size_ptr =
2112 				(5 /* vertices making up the line strip */ + 2 /* additional start/end adjacency vertices */) *
2113 				4 /* components */
2114 				* sizeof(float);
2115 
2116 			break;
2117 		}
2118 
2119 		case GL_LINES:
2120 		{
2121 			*raw_arrays_data_size_ptr =
2122 				2 /* points per line segment */ * 4 /* lines */ * 4 /* components */ * sizeof(float);
2123 
2124 			break;
2125 		}
2126 
2127 		case GL_LINES_ADJACENCY_EXT:
2128 		{
2129 			*raw_arrays_data_size_ptr =
2130 				4 /* points per line segment */ * 4 /* lines */ * 4 /* components */ * sizeof(float);
2131 
2132 			break;
2133 		}
2134 
2135 		default:
2136 		{
2137 			TCU_FAIL("Unrecognized draw call mode");
2138 		}
2139 		} /* switch (m_drawcall_mode) */
2140 
2141 		*raw_arrays_data_ptr	 = new float[*raw_arrays_data_size_ptr / sizeof(float)];
2142 		raw_array_data_traveller = *raw_arrays_data_ptr;
2143 
2144 		getRenderTargetSize(1, &single_rt_width, &single_rt_height);
2145 		getRenderTargetSize(getAmountOfDrawInstances(), &whole_rt_width, &whole_rt_height);
2146 
2147 		/* Generate the data */
2148 		float				   end_y = 0;
2149 		std::vector<tcu::Vec4> quad_coordinates;
2150 		float				   start_y = 0;
2151 		float				   w	   = 1.0f;
2152 
2153 		if (n_instances != 1)
2154 		{
2155 			float delta = float(single_rt_height) / float(whole_rt_height);
2156 
2157 			/* Y coordinates are calculated in a vertex shader in multi-instanced case */
2158 			start_y = 0.0f;
2159 			end_y   = 0.0f;
2160 			w		= delta;
2161 		}
2162 		else
2163 		{
2164 			start_y = -1;
2165 			end_y   = 1;
2166 		}
2167 
2168 		/* X, Y coordinates: correspond to X & Y locations of the vertex.
2169 		 * Z    coordinates: set to 0 if the vertex is located on top edge, otherwise set to 1.
2170 		 * W    coordinate:  stores the delta (single-instanced RT height / multi-instanced RT height).
2171 		 */
2172 		float dx_multiplier = 1.5f; /* Default value for lines and line_strip output layout qualifiers */
2173 		float dy_multiplier = 1.5f; /* Default value for lines and line_strip output layout qualifiers */
2174 
2175 		if (m_output_type == SHADER_OUTPUT_TYPE_TRIANGLE_STRIP)
2176 		{
2177 			dx_multiplier = 0.0f;
2178 			dy_multiplier = 0.0f;
2179 		}
2180 
2181 		quad_coordinates.push_back(tcu::Vec4(-1 + dx_multiplier * dx, start_y + dy_multiplier * dy, 0, w)); /* TL */
2182 		quad_coordinates.push_back(tcu::Vec4(1 - dx_multiplier * dx, start_y + dy_multiplier * dy, 0, w));  /* TR */
2183 		quad_coordinates.push_back(tcu::Vec4(1 - dx_multiplier * dx, end_y - dy_multiplier * dy, 1, w));	/* BR */
2184 		quad_coordinates.push_back(tcu::Vec4(-1 + dx_multiplier * dx, end_y - dy_multiplier * dy, 1, w));   /* BL */
2185 
2186 		for (int n_line_segment = 0; n_line_segment < 4 /* edges */; ++n_line_segment)
2187 		{
2188 			/* Note we need to clamp coordinate indices here */
2189 			int coordinate0_index		 = (4 + n_line_segment - 1) % 4; /* protect against negative modulo values */
2190 			int coordinate1_index		 = (n_line_segment) % 4;
2191 			int coordinate2_index		 = (n_line_segment + 1) % 4;
2192 			int coordinate3_index		 = (n_line_segment + 2) % 4;
2193 			const tcu::Vec4& coordinate0 = quad_coordinates[coordinate0_index];
2194 			const tcu::Vec4& coordinate1 = quad_coordinates[coordinate1_index];
2195 			const tcu::Vec4& coordinate2 = quad_coordinates[coordinate2_index];
2196 			const tcu::Vec4& coordinate3 = quad_coordinates[coordinate3_index];
2197 
2198 			/* For GL_LINES,      we need to explicitly define start & end-points for each segment.
2199 			 * For GL_LINE_STRIP, we only need to explicitly define first start point. Following
2200 			 *                    vertices define subsequent points making up the line strip.
2201 			 * For GL_LINE_LOOP,  we need all the data we used for GL_LINE_STRIP excluding the very
2202 			 *                    last vertex.
2203 			 *
2204 			 * For GL_LINES_ADJACENCY_EXT, we extend GL_LINES data by vertices preceding and following points
2205 			 * that make up a single line segment.
2206 			 * For GL_LINE_STRIP_ADJACENCY_EXT, we extend GL_LINE_STRIP data by including a vertex preceding the
2207 			 * actual first vertex, and by including a vertex that follows the end vertex closing the line
2208 			 * strip.
2209 			 */
2210 
2211 			/* Preceding vertex */
2212 			if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT ||
2213 				(m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT && n_line_segment == 0))
2214 			{
2215 				*raw_array_data_traveller = coordinate0.x();
2216 				raw_array_data_traveller++;
2217 				*raw_array_data_traveller = coordinate0.y();
2218 				raw_array_data_traveller++;
2219 				*raw_array_data_traveller = coordinate0.z();
2220 				raw_array_data_traveller++;
2221 				*raw_array_data_traveller = coordinate0.w();
2222 				raw_array_data_traveller++;
2223 			}
2224 
2225 			/* Vertex 1 */
2226 			if ((m_drawcall_mode != GL_LINE_STRIP && m_drawcall_mode != GL_LINE_STRIP_ADJACENCY_EXT &&
2227 				 m_drawcall_mode != GL_LINE_LOOP) ||
2228 				((m_drawcall_mode == GL_LINE_STRIP || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT ||
2229 				  m_drawcall_mode == GL_LINE_LOOP) &&
2230 				 n_line_segment == 0))
2231 			{
2232 				*raw_array_data_traveller = coordinate1.x();
2233 				raw_array_data_traveller++;
2234 				*raw_array_data_traveller = coordinate1.y();
2235 				raw_array_data_traveller++;
2236 				*raw_array_data_traveller = coordinate1.z();
2237 				raw_array_data_traveller++;
2238 				*raw_array_data_traveller = coordinate1.w();
2239 				raw_array_data_traveller++;
2240 			}
2241 
2242 			/* Vertex 2 */
2243 			if (m_drawcall_mode != GL_LINE_LOOP || (m_drawcall_mode == GL_LINE_LOOP && n_line_segment != 3))
2244 			{
2245 				*raw_array_data_traveller = coordinate2.x();
2246 				raw_array_data_traveller++;
2247 				*raw_array_data_traveller = coordinate2.y();
2248 				raw_array_data_traveller++;
2249 				*raw_array_data_traveller = coordinate2.z();
2250 				raw_array_data_traveller++;
2251 				*raw_array_data_traveller = coordinate2.w();
2252 				raw_array_data_traveller++;
2253 			}
2254 
2255 			/* Following vertex */
2256 			if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT ||
2257 				(m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT && n_line_segment == 3))
2258 			{
2259 				*raw_array_data_traveller = coordinate3.x();
2260 				raw_array_data_traveller++;
2261 				*raw_array_data_traveller = coordinate3.y();
2262 				raw_array_data_traveller++;
2263 				*raw_array_data_traveller = coordinate3.z();
2264 				raw_array_data_traveller++;
2265 				*raw_array_data_traveller = coordinate3.w();
2266 				raw_array_data_traveller++;
2267 			}
2268 		} /* for (all line segments) */
2269 
2270 		/* Generate unordered data:
2271 		 *
2272 		 * The way we organise data in this case is that:
2273 		 *
2274 		 * - For index data,  start and end points are flipped for each line segment.
2275 		 * - For vertex data, vertex locations are stored to correspond to this order.
2276 		 *
2277 		 * We *DO NOT* modify the order in which we draw the line segments, since that could make the verification
2278 		 * process even more complex than it already is.
2279 		 */
2280 		switch (m_drawcall_mode)
2281 		{
2282 		case GL_LINE_LOOP:
2283 		{
2284 			*unordered_arrays_data_size_ptr = *raw_arrays_data_size_ptr;
2285 			*unordered_arrays_data_ptr		= new float[*unordered_arrays_data_size_ptr / sizeof(float)];
2286 
2287 			*unordered_elements_data_size_ptr = sizeof(unsigned char) * 4 /* points */;
2288 			*unordered_elements_data_ptr	  = new unsigned char[*unordered_elements_data_size_ptr];
2289 
2290 			for (unsigned int index = 0; index < 4 /* points */; ++index)
2291 			{
2292 				/* Gives 3-{0, 1, 2, 3} */
2293 				int new_index = 3 - index;
2294 
2295 				/* Store index data */
2296 				(*unordered_elements_data_ptr)[index] = (unsigned char)new_index;
2297 
2298 				/* Store vertex data */
2299 				memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */,
2300 					   (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */);
2301 			} /* for (all indices) */
2302 
2303 			break;
2304 		}
2305 
2306 		case GL_LINE_STRIP:
2307 		{
2308 			*unordered_arrays_data_size_ptr = *raw_arrays_data_size_ptr;
2309 			*unordered_arrays_data_ptr		= new float[*unordered_arrays_data_size_ptr / sizeof(float)];
2310 
2311 			*unordered_elements_data_size_ptr = sizeof(unsigned char) * 5 /* points */;
2312 			*unordered_elements_data_ptr	  = new unsigned char[*unordered_elements_data_size_ptr];
2313 
2314 			for (unsigned int index = 0; index < 5 /* points */; ++index)
2315 			{
2316 				/* Gives 4-{0, 1, 2, 3, 4} */
2317 				int new_index = 4 - index;
2318 
2319 				/* Store index data */
2320 				(*unordered_elements_data_ptr)[index] = (unsigned char)new_index;
2321 
2322 				/* Store vertex data */
2323 				memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */,
2324 					   (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */);
2325 			} /* for (all indices) */
2326 
2327 			break;
2328 		}
2329 
2330 		case GL_LINES:
2331 		{
2332 			*unordered_arrays_data_size_ptr = sizeof(float) * 8 /* points */ * 4 /* components */;
2333 			*unordered_arrays_data_ptr		= new float[*unordered_arrays_data_size_ptr / sizeof(float)];
2334 
2335 			*unordered_elements_data_size_ptr = sizeof(unsigned char) * 8 /* points */;
2336 			*unordered_elements_data_ptr	  = new unsigned char[*unordered_elements_data_size_ptr];
2337 
2338 			for (unsigned int index = 0; index < 8 /* points */; ++index)
2339 			{
2340 				/* Gives 7-{(1, 0), (3, 2), (5, 4), (7, 6)} */
2341 				int new_index = 7 - ((index / 2) * 2 + (index + 1) % 2);
2342 
2343 				/* Store index data */
2344 				(*unordered_elements_data_ptr)[index] = (unsigned char)new_index;
2345 
2346 				/* Store vertex data */
2347 				memcpy((*unordered_arrays_data_ptr) + new_index * 4 /* components */,
2348 					   (*raw_arrays_data_ptr) + index * 4 /* components */, sizeof(float) * 4 /* components */);
2349 			} /* for (all indices) */
2350 
2351 			break;
2352 		} /* case GL_LINES: */
2353 
2354 		case GL_LINES_ADJACENCY_EXT:
2355 		case GL_LINE_STRIP_ADJACENCY_EXT:
2356 		{
2357 			/* For adjacency case, we may simplify the approach. Since the index data is now also going
2358 			 * to include references to adjacent vertices, we can use the same ordering as in raw arrays data.
2359 			 * Should the implementation misinterpret the data, it will treat adjacent vertex indices as actual
2360 			 * vertex indices, breaking the verification.
2361 			 */
2362 			/* For array data, just point to unique vertex locations. Use the same order as in raw arrays data case
2363 			 * to simplify the vertex shader for the pass.
2364 			 **/
2365 			*unordered_arrays_data_size_ptr = sizeof(float) * 4 /* points */ * 4 /* components */;
2366 			*unordered_arrays_data_ptr		= new float[*unordered_arrays_data_size_ptr / sizeof(float)];
2367 
2368 			if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT)
2369 			{
2370 				*unordered_elements_data_size_ptr =
2371 					sizeof(unsigned char) * 4 /* vertices per line segment */ * 4 /* line segments */;
2372 			}
2373 			else
2374 			{
2375 				*unordered_elements_data_size_ptr =
2376 					sizeof(unsigned char) * (5 /* vertices making up a line strip */ + 2 /* start/end vertices */);
2377 			}
2378 
2379 			*unordered_elements_data_ptr = new unsigned char[*unordered_elements_data_size_ptr];
2380 
2381 			for (int n = 0; n < 4; ++n)
2382 			{
2383 				(*unordered_arrays_data_ptr)[4 * n + 0] = quad_coordinates[n].x();
2384 				(*unordered_arrays_data_ptr)[4 * n + 1] = quad_coordinates[n].y();
2385 				(*unordered_arrays_data_ptr)[4 * n + 2] = quad_coordinates[n].z();
2386 				(*unordered_arrays_data_ptr)[4 * n + 3] = quad_coordinates[n].w();
2387 			}
2388 
2389 			/* For elements data, we just walk over the quad and make sure we turn a full circle */
2390 			unsigned char* elements_data_traveller_ptr = *unordered_elements_data_ptr;
2391 
2392 			for (int n = 0; n < 4; ++n)
2393 			{
2394 				int component0_index = (n + 4 - 1) % 4; /* protect against underflow */
2395 				int component1_index = (n) % 4;
2396 				int component2_index = (n + 1) % 4;
2397 				int component3_index = (n + 2) % 4;
2398 
2399 				if (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)
2400 				{
2401 					/* Vertex adjacent to start vertex - include only at start */
2402 					if (n == 0)
2403 					{
2404 						*elements_data_traveller_ptr = (unsigned char)component0_index;
2405 
2406 						++elements_data_traveller_ptr;
2407 					}
2408 
2409 					/* Vertex index */
2410 					*elements_data_traveller_ptr = (unsigned char)component1_index;
2411 
2412 					++elements_data_traveller_ptr;
2413 
2414 					/* End vertex and the adjacent vertex - include only for final iteration */
2415 					if (n == 3)
2416 					{
2417 						/* End vertex */
2418 						*elements_data_traveller_ptr = (unsigned char)component2_index;
2419 
2420 						++elements_data_traveller_ptr;
2421 
2422 						/* Adjacent vertex */
2423 						*elements_data_traveller_ptr = (unsigned char)component3_index;
2424 
2425 						++elements_data_traveller_ptr;
2426 					}
2427 				}
2428 				else
2429 				{
2430 					/* GL_LINES_ADJACENCY_EXT */
2431 					*elements_data_traveller_ptr = (unsigned char)component0_index;
2432 					++elements_data_traveller_ptr;
2433 					*elements_data_traveller_ptr = (unsigned char)component1_index;
2434 					++elements_data_traveller_ptr;
2435 					*elements_data_traveller_ptr = (unsigned char)component2_index;
2436 					++elements_data_traveller_ptr;
2437 					*elements_data_traveller_ptr = (unsigned char)component3_index;
2438 					++elements_data_traveller_ptr;
2439 				}
2440 			}
2441 
2442 			break;
2443 		} /* case GL_LINES: */
2444 
2445 		default:
2446 		{
2447 			TCU_FAIL("Unrecognized draw call mode");
2448 		}
2449 		} /* switch (m_drawcall_mode) */
2450 	}	 /* for (both cases) */
2451 }
2452 
2453 /** Destructor. */
~GeometryShaderRenderingLinesCase()2454 GeometryShaderRenderingLinesCase::~GeometryShaderRenderingLinesCase()
2455 {
2456 	if (m_raw_array_instanced_data != NULL)
2457 	{
2458 		delete[] m_raw_array_instanced_data;
2459 
2460 		m_raw_array_instanced_data = NULL;
2461 	}
2462 
2463 	if (m_raw_array_noninstanced_data != NULL)
2464 	{
2465 		delete[] m_raw_array_noninstanced_data;
2466 
2467 		m_raw_array_noninstanced_data = NULL;
2468 	}
2469 
2470 	if (m_unordered_array_instanced_data != NULL)
2471 	{
2472 		delete[] m_unordered_array_instanced_data;
2473 
2474 		m_unordered_array_instanced_data = NULL;
2475 	}
2476 
2477 	if (m_unordered_array_noninstanced_data != NULL)
2478 	{
2479 		delete[] m_unordered_array_noninstanced_data;
2480 
2481 		m_unordered_array_noninstanced_data = NULL;
2482 	}
2483 
2484 	if (m_unordered_elements_instanced_data != NULL)
2485 	{
2486 		delete[] m_unordered_elements_instanced_data;
2487 
2488 		m_unordered_elements_instanced_data = NULL;
2489 	}
2490 
2491 	if (m_unordered_elements_noninstanced_data != NULL)
2492 	{
2493 		delete[] m_unordered_elements_noninstanced_data;
2494 
2495 		m_unordered_elements_noninstanced_data = NULL;
2496 	}
2497 }
2498 
2499 /** Retrieves amount of instances that should be drawn with glDraw*Elements() calls.
2500  *
2501  *  @return As per description.
2502  **/
getAmountOfDrawInstances()2503 unsigned int GeometryShaderRenderingLinesCase::getAmountOfDrawInstances()
2504 {
2505 	return 4;
2506 }
2507 
2508 /** Retrieves amount of indices that should be used for rendering a single instance
2509  *  (glDraw*Elements() calls only)
2510  *
2511  *  @return As per description.
2512  */
getAmountOfElementsPerInstance()2513 unsigned int GeometryShaderRenderingLinesCase::getAmountOfElementsPerInstance()
2514 {
2515 	unsigned int result = 0;
2516 
2517 	switch (m_drawcall_mode)
2518 	{
2519 	case GL_LINE_LOOP:
2520 		result = 4;
2521 		break;
2522 	case GL_LINE_STRIP:
2523 		result = 5;
2524 		break;
2525 	case GL_LINE_STRIP_ADJACENCY_EXT:
2526 		result = 7;
2527 		break;
2528 	case GL_LINES:
2529 		result = 8;
2530 		break;
2531 	case GL_LINES_ADJACENCY_EXT:
2532 		result = 16;
2533 		break;
2534 
2535 	default:
2536 	{
2537 		TCU_FAIL("Unrecognized draw call mode");
2538 	}
2539 	} /* switch (m_drawcall_mode) */
2540 
2541 	return result;
2542 }
2543 
2544 /** Retrieves amount of vertices that should be used for rendering a single instance
2545  *  (glDrawArrays*() calls only)
2546  *
2547  *  @return As per description.
2548  **/
getAmountOfVerticesPerInstance()2549 unsigned int GeometryShaderRenderingLinesCase::getAmountOfVerticesPerInstance()
2550 {
2551 	unsigned int result = 0;
2552 
2553 	switch (m_drawcall_mode)
2554 	{
2555 	case GL_LINE_LOOP:
2556 		result = 4;
2557 		break;
2558 	case GL_LINE_STRIP:
2559 		result = 5;
2560 		break;
2561 	case GL_LINE_STRIP_ADJACENCY_EXT:
2562 		result = 7;
2563 		break;
2564 	case GL_LINES:
2565 		result = 8;
2566 		break;
2567 	case GL_LINES_ADJACENCY_EXT:
2568 		result = 16;
2569 		break;
2570 
2571 	default:
2572 	{
2573 		TCU_FAIL("Unrecognized draw call mode");
2574 	}
2575 	} /* switch (m_drawcall_mode) */
2576 
2577 	return result;
2578 }
2579 
2580 /** Draw call mode that should be used glDraw*() calls.
2581  *
2582  *  @return As per description.
2583  **/
getDrawCallMode()2584 glw::GLenum GeometryShaderRenderingLinesCase::getDrawCallMode()
2585 {
2586 	return m_drawcall_mode;
2587 }
2588 
2589 /** Source code for a fragment shader that should be used for the test.
2590  *
2591  *  @return As per description.
2592  **/
getFragmentShaderCode()2593 std::string GeometryShaderRenderingLinesCase::getFragmentShaderCode()
2594 {
2595 	static std::string fs_code = "${VERSION}\n"
2596 								 "\n"
2597 								 "precision highp float;\n"
2598 								 "\n"
2599 								 "in  vec4 gs_fs_color;\n"
2600 								 "out vec4 result;\n"
2601 								 "\n"
2602 								 "void main()\n"
2603 								 "{\n"
2604 								 "    result = gs_fs_color;\n"
2605 								 "}\n";
2606 
2607 	return fs_code;
2608 }
2609 
2610 /** Source code for a geometry shader that should be used for the test.
2611  *
2612  *  @return As per description.
2613  **/
getGeometryShaderCode()2614 std::string GeometryShaderRenderingLinesCase::getGeometryShaderCode()
2615 {
2616 	static const char* lines_in_line_strip_out_gs_code_preamble = "${VERSION}\n"
2617 																  "\n"
2618 																  "${GEOMETRY_SHADER_ENABLE}\n"
2619 																  "\n"
2620 																  "layout(lines)                      in;\n"
2621 																  "layout(line_strip, max_vertices=6) out;\n"
2622 																  "\n"
2623 																  "#define N_VERTICES_IN (2)\n"
2624 																  "#define N_VERTEX0     (0)\n"
2625 																  "#define N_VERTEX1     (1)\n"
2626 																  "\n";
2627 
2628 	static const char* lines_adjacency_in_line_strip_out_gs_code_preamble = "${VERSION}\n"
2629 																			"\n"
2630 																			"${GEOMETRY_SHADER_ENABLE}\n"
2631 																			"\n"
2632 																			"layout(lines_adjacency)            in;\n"
2633 																			"layout(line_strip, max_vertices=6) out;\n"
2634 																			"\n"
2635 																			"#define N_VERTICES_IN (4)\n"
2636 																			"#define N_VERTEX0     (1)\n"
2637 																			"#define N_VERTEX1     (2)\n"
2638 																			"\n";
2639 
2640 	static const char* lines_gs_code_main = "\n"
2641 											"in  vec4 vs_gs_color[N_VERTICES_IN];\n"
2642 											"out vec4 gs_fs_color;\n"
2643 											"\n"
2644 											"uniform ivec2 renderingTargetSize;\n"
2645 											"\n"
2646 											"void main()\n"
2647 											"{\n"
2648 											"    float dx = float(2.0) / float(renderingTargetSize.x);\n"
2649 											"    float dy = float(2.0) / float(renderingTargetSize.y);\n"
2650 											"\n"
2651 											"    vec4 start_pos = gl_in[N_VERTEX0].gl_Position;\n"
2652 											"    vec4 end_pos   = gl_in[N_VERTEX1].gl_Position;\n"
2653 											"    vec4 start_col = vs_gs_color[N_VERTEX0];\n"
2654 											"    vec4 end_col   = vs_gs_color[N_VERTEX1];\n"
2655 											"\n"
2656 											/* Determine if this is a horizontal or vertical edge */
2657 											"    if (start_pos.x != end_pos.x)\n"
2658 											"    {\n"
2659 											/* Bottom line segment */
2660 											"        gl_Position = vec4(-1.0, start_pos.y + dy, 0, 1);\n"
2661 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2662 											"        EmitVertex();\n"
2663 											"\n"
2664 											"        gl_Position = vec4(1.0, end_pos.y + dy, 0, 1);\n"
2665 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2666 											"        EmitVertex();\n"
2667 											"        EndPrimitive();\n"
2668 											/* Middle line segment */
2669 											"        gl_Position = vec4(-1.0, start_pos.y, 0, 1);\n"
2670 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2671 											"        EmitVertex();\n"
2672 											"\n"
2673 											"        gl_Position = vec4(1.0, end_pos.y, 0, 1);\n"
2674 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2675 											"        EmitVertex();\n"
2676 											"        EndPrimitive();\n"
2677 											/* Top line segment */
2678 											"        gl_Position = vec4(-1.0, start_pos.y - dy, 0, 1);\n"
2679 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2680 											"        EmitVertex();\n"
2681 											"\n"
2682 											"        gl_Position = vec4(1.0, end_pos.y - dy, 0, 1);\n"
2683 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2684 											"        EmitVertex();\n"
2685 											"        EndPrimitive();\n"
2686 											"    }\n"
2687 											"    else\n"
2688 											"    {\n"
2689 											/* Left line segment */
2690 											"        gl_Position = vec4(start_pos.x - dx, start_pos.y, 0, 1);\n"
2691 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2692 											"        EmitVertex();\n"
2693 											"\n"
2694 											"        gl_Position = vec4(end_pos.x - dx, end_pos.y, 0, 1);\n"
2695 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2696 											"        EmitVertex();\n"
2697 											"        EndPrimitive();\n"
2698 											/* Middle line segment */
2699 											"        gl_Position = vec4(start_pos.x, start_pos.y, 0, 1);\n"
2700 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2701 											"        EmitVertex();\n"
2702 											"\n"
2703 											"        gl_Position = vec4(end_pos.x, end_pos.y, 0, 1);\n"
2704 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2705 											"        EmitVertex();\n"
2706 											"        EndPrimitive();\n"
2707 											/* Right line segment */
2708 											"        gl_Position = vec4(start_pos.x + dx, start_pos.y, 0, 1);\n"
2709 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2710 											"        EmitVertex();\n"
2711 											"\n"
2712 											"        gl_Position = vec4(end_pos.x + dx, end_pos.y, 0, 1);\n"
2713 											"        gs_fs_color = mix(start_col, end_col, 0.5);\n"
2714 											"        EmitVertex();\n"
2715 											"        EndPrimitive();\n"
2716 											"    }\n"
2717 											"}\n";
2718 
2719 	static const char* lines_in_points_out_gs_code_preamble = "${VERSION}\n"
2720 															  "\n"
2721 															  "${GEOMETRY_SHADER_ENABLE}\n"
2722 															  "\n"
2723 															  "layout(lines)                   in;\n"
2724 															  "layout(points, max_vertices=72) out;\n"
2725 															  "\n"
2726 															  "#define N_VERTEX0     (0)\n"
2727 															  "#define N_VERTEX1     (1)\n"
2728 															  "#define N_VERTICES_IN (2)\n"
2729 															  "\n";
2730 
2731 	static const char* lines_adjacency_in_points_out_gs_code_preamble = "${VERSION}\n"
2732 																		"\n"
2733 																		"${GEOMETRY_SHADER_ENABLE}\n"
2734 																		"\n"
2735 																		"layout(lines_adjacency)         in;\n"
2736 																		"layout(points, max_vertices=72) out;\n"
2737 																		"\n"
2738 																		"#define N_VERTEX0     (1)\n"
2739 																		"#define N_VERTEX1     (2)\n"
2740 																		"#define N_VERTICES_IN (4)\n"
2741 																		"\n";
2742 
2743 	static const char* points_gs_code_main = "\n"
2744 											 "in  vec4 vs_gs_color[N_VERTICES_IN];\n"
2745 											 "out vec4 gs_fs_color;\n"
2746 											 "\n"
2747 											 "uniform ivec2 renderingTargetSize;\n"
2748 											 "\n"
2749 											 "void main()\n"
2750 											 "{\n"
2751 											 "    float dx = float(2.0) / float(renderingTargetSize.x);\n"
2752 											 "    float dy = float(2.0) / float(renderingTargetSize.y);\n"
2753 											 "\n"
2754 											 "    vec4 start_pos = gl_in[N_VERTEX0].gl_Position;\n"
2755 											 "    vec4 end_pos   = gl_in[N_VERTEX1].gl_Position;\n"
2756 											 "    vec4 start_col = vs_gs_color[N_VERTEX0];\n"
2757 											 "    vec4 end_col   = vs_gs_color[N_VERTEX1];\n"
2758 											 "    vec4 delta_col = (end_col - start_col) / vec4(7.0);\n"
2759 											 "    vec4 delta_pos = (end_pos - start_pos) / vec4(7.0);\n"
2760 											 "\n"
2761 											 "    for (int n_point = 0; n_point < 8; ++n_point)\n"
2762 											 "    {\n"
2763 											 "        vec4 ref_color = start_col + vec4(float(n_point)) * delta_col;\n"
2764 											 "        vec4 ref_pos   = start_pos + vec4(float(n_point)) * delta_pos;\n"
2765 											 "\n"
2766 											 /* TL */
2767 											 "        gl_Position  = ref_pos + vec4(-dx, -dy, 0, 0);\n"
2768 											 "        gs_fs_color  = ref_color;\n"
2769 											 "        EmitVertex();\n"
2770 											 /* TM */
2771 											 "        gl_Position  = ref_pos + vec4(0, -dy, 0, 0);\n"
2772 											 "        gs_fs_color  = ref_color;\n"
2773 											 "        EmitVertex();\n"
2774 											 /* TR */
2775 											 "        gl_Position  = ref_pos + vec4(dx, -dy, 0, 0);\n"
2776 											 "        gs_fs_color  = ref_color;\n"
2777 											 "        EmitVertex();\n"
2778 											 /* ML */
2779 											 "        gl_Position  = ref_pos + vec4(-dx, 0, 0, 0);\n"
2780 											 "        gs_fs_color  = ref_color;\n"
2781 											 "        EmitVertex();\n"
2782 											 /* MM */
2783 											 "        gl_Position  = ref_pos + vec4(0, 0, 0, 0);\n"
2784 											 "        gs_fs_color  = ref_color;\n"
2785 											 "        EmitVertex();\n"
2786 											 /* MR */
2787 											 "        gl_Position  = ref_pos + vec4(dx, 0, 0, 0);\n"
2788 											 "        gs_fs_color  = ref_color;\n"
2789 											 "        EmitVertex();\n"
2790 											 /* BL */
2791 											 "        gl_Position  = ref_pos + vec4(-dx, dy, 0, 0);\n"
2792 											 "        gs_fs_color  = ref_color;\n"
2793 											 "        EmitVertex();\n"
2794 											 /* BM */
2795 											 "        gl_Position  = ref_pos + vec4(0, dy, 0, 0);\n"
2796 											 "        gs_fs_color  = ref_color;\n"
2797 											 "        EmitVertex();\n"
2798 											 /* BR */
2799 											 "        gl_Position  = ref_pos + vec4(dx, dy, 0, 0);\n"
2800 											 "        gs_fs_color  = ref_color;\n"
2801 											 "        EmitVertex();\n"
2802 											 "    }\n"
2803 											 "}\n";
2804 
2805 	static const char* lines_adjacency_in_triangle_strip_out_gs_code_preamble =
2806 		"${VERSION}\n"
2807 		"\n"
2808 		"${GEOMETRY_SHADER_ENABLE}\n"
2809 		"\n"
2810 		"layout(lines_adjacency)                in;\n"
2811 		"layout(triangle_strip, max_vertices=3) out;\n"
2812 		"\n"
2813 		"#define N_VERTEX0     (1)\n"
2814 		"#define N_VERTEX1     (2)\n"
2815 		"#define N_VERTICES_IN (4)\n";
2816 
2817 	static const char* lines_in_triangle_strip_out_gs_code_preamble = "${VERSION}\n"
2818 																	  "\n"
2819 																	  "${GEOMETRY_SHADER_ENABLE}\n"
2820 																	  "\n"
2821 																	  "layout(lines)                          in;\n"
2822 																	  "layout(triangle_strip, max_vertices=3) out;\n"
2823 																	  "\n"
2824 																	  "#define N_VERTEX0     (0)\n"
2825 																	  "#define N_VERTEX1     (1)\n"
2826 																	  "#define N_VERTICES_IN (2)\n";
2827 
2828 	static const char* triangles_gs_code_main = "flat in   int instance_id[N_VERTICES_IN];\n"
2829 												"     in  vec4 vs_gs_color[N_VERTICES_IN];\n"
2830 												"     out vec4 gs_fs_color;\n"
2831 												"\n"
2832 												"uniform ivec2 renderingTargetSize;\n"
2833 												"\n"
2834 												"void main()\n"
2835 												"{\n"
2836 												"    float dx = float(1.5) / float(renderingTargetSize.x);\n"
2837 												"    float dy = float(1.5) / float(renderingTargetSize.y);\n"
2838 												"\n"
2839 												"    gl_Position = gl_in[N_VERTEX0].gl_Position;\n"
2840 												"    gs_fs_color = vs_gs_color[N_VERTEX0];\n"
2841 												"    EmitVertex();\n"
2842 												"\n"
2843 												"    gl_Position = gl_in[N_VERTEX1].gl_Position;\n"
2844 												"    gs_fs_color = vs_gs_color[N_VERTEX0];\n"
2845 												"    EmitVertex();\n"
2846 												"\n"
2847 												"    if (renderingTargetSize.y == 45 /* block size */)\n"
2848 												"    {\n"
2849 												"        gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
2850 												"    }\n"
2851 												"    else\n"
2852 												"    {\n"
2853 												/* Each block takes 1/4th of the total render target.
2854 		 * Third vertex should be placed in the middle of the block.
2855 		 */
2856 												"        float y = -1.0 + 1.0 / 4.0 + float(instance_id[0]) * 0.5;\n"
2857 												"\n"
2858 												"        gl_Position = vec4(0.0, y, 0.0, 1.0);\n"
2859 												"    }\n"
2860 												"\n"
2861 												"    gs_fs_color = vs_gs_color[N_VERTEX0];\n"
2862 												"    EmitVertex();\n"
2863 												"\n"
2864 												"    EndPrimitive();\n"
2865 												"}\n";
2866 	std::string result;
2867 
2868 	switch (m_output_type)
2869 	{
2870 	case SHADER_OUTPUT_TYPE_LINE_STRIP:
2871 	{
2872 		std::stringstream lines_adjacency_gs_code_stringstream;
2873 		std::string		  lines_adjacency_gs_code_string;
2874 		std::stringstream lines_gs_code_stringstream;
2875 		std::string		  lines_gs_code_string;
2876 
2877 		if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)
2878 		{
2879 			/* First request for lines_adjacency GS, form the string */
2880 			lines_adjacency_gs_code_stringstream << lines_adjacency_in_line_strip_out_gs_code_preamble
2881 												 << lines_gs_code_main;
2882 
2883 			lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str();
2884 			result						   = lines_adjacency_gs_code_string;
2885 		}
2886 		else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP)
2887 		{
2888 			/* First request for lines GS, form the string */
2889 			lines_gs_code_stringstream << lines_in_line_strip_out_gs_code_preamble << lines_gs_code_main;
2890 
2891 			lines_gs_code_string = lines_gs_code_stringstream.str();
2892 			result				 = lines_gs_code_string;
2893 		}
2894 		else
2895 		{
2896 			TCU_FAIL("Unrecognized draw call mode");
2897 		}
2898 
2899 		break;
2900 	}
2901 
2902 	case SHADER_OUTPUT_TYPE_POINTS:
2903 	{
2904 		std::stringstream lines_adjacency_gs_code_stringstream;
2905 		std::string		  lines_adjacency_gs_code_string;
2906 		std::stringstream lines_gs_code_stringstream;
2907 		std::string		  lines_gs_code_string;
2908 
2909 		if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)
2910 		{
2911 			/* First request for lines_adjacency GS, form the string */
2912 			lines_adjacency_gs_code_stringstream << lines_adjacency_in_points_out_gs_code_preamble
2913 												 << points_gs_code_main;
2914 
2915 			lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str();
2916 			result						   = lines_adjacency_gs_code_string;
2917 		}
2918 		else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP)
2919 		{
2920 			/* First request for lines GS, form the string */
2921 			lines_gs_code_stringstream << lines_in_points_out_gs_code_preamble << points_gs_code_main;
2922 
2923 			lines_gs_code_string = lines_gs_code_stringstream.str();
2924 			result				 = lines_gs_code_string;
2925 		}
2926 		else
2927 		{
2928 			TCU_FAIL("Unrecognized draw call mode");
2929 		}
2930 
2931 		break;
2932 	}
2933 
2934 	case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
2935 	{
2936 		std::stringstream lines_adjacency_gs_code_stringstream;
2937 		std::string		  lines_adjacency_gs_code_string;
2938 		std::stringstream lines_gs_code_stringstream;
2939 		std::string		  lines_gs_code_string;
2940 
2941 		if (m_drawcall_mode == GL_LINES_ADJACENCY_EXT || m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT)
2942 		{
2943 			/* First request for lines_adjacency GS, form the string */
2944 			lines_adjacency_gs_code_stringstream << lines_adjacency_in_triangle_strip_out_gs_code_preamble
2945 												 << triangles_gs_code_main;
2946 
2947 			lines_adjacency_gs_code_string = lines_adjacency_gs_code_stringstream.str();
2948 			result						   = lines_adjacency_gs_code_string;
2949 		}
2950 		else if (m_drawcall_mode == GL_LINES || m_drawcall_mode == GL_LINE_LOOP || m_drawcall_mode == GL_LINE_STRIP)
2951 		{
2952 			/* First request for lines GS, form the string */
2953 			lines_gs_code_stringstream << lines_in_triangle_strip_out_gs_code_preamble << triangles_gs_code_main;
2954 
2955 			lines_gs_code_string = lines_gs_code_stringstream.str();
2956 			result				 = lines_gs_code_string;
2957 		}
2958 		else
2959 		{
2960 			TCU_FAIL("Unrecognized draw call mode");
2961 		}
2962 
2963 		break;
2964 	}
2965 
2966 	default:
2967 	{
2968 		TCU_FAIL("Requested shader output layout qualifier is unsupported");
2969 	}
2970 	} /* switch (m_output_type) */
2971 
2972 	return result;
2973 }
2974 
2975 /** Returns amount of bytes that should be allocated for a buffer object to hold
2976  *  vertex data to be used for glDrawArrays*() calls.
2977  *
2978  *  @param instanced True if the data is to be used in regard to instanced draw calls,
2979  *                   false otherwise.
2980  *
2981  *  @return As per description.
2982  **/
getRawArraysDataBufferSize(bool instanced)2983 glw::GLuint GeometryShaderRenderingLinesCase::getRawArraysDataBufferSize(bool instanced)
2984 {
2985 	return instanced ? m_raw_array_instanced_data_size : m_raw_array_noninstanced_data_size;
2986 }
2987 
2988 /** Returns vertex data for the test. Only to be used for glDrawArrays*() calls.
2989  *
2990  *  @param instanced True if the data is to be used in regard to instanced draw calls,
2991  *                   false otherwise.
2992  *
2993  *  @return As per description.
2994  **/
getRawArraysDataBuffer(bool instanced)2995 const void* GeometryShaderRenderingLinesCase::getRawArraysDataBuffer(bool instanced)
2996 {
2997 	return instanced ? m_raw_array_instanced_data : m_raw_array_noninstanced_data;
2998 }
2999 
3000 /** Retrieves resolution of off-screen rendering buffer that should be used for the test.
3001  *
3002  *  @param n_instances Amount of draw call instances this render target will be used for.
3003  *  @param out_width   Deref will be used to store rendertarget's width. Must not be NULL.
3004  *  @param out_height  Deref will be used to store rendertarget's height. Must not be NULL.
3005  **/
getRenderTargetSize(unsigned int n_instances,unsigned int * out_width,unsigned int * out_height)3006 void GeometryShaderRenderingLinesCase::getRenderTargetSize(unsigned int n_instances, unsigned int* out_width,
3007 														   unsigned int* out_height)
3008 {
3009 	switch (m_output_type)
3010 	{
3011 	case SHADER_OUTPUT_TYPE_LINE_STRIP:
3012 	case SHADER_OUTPUT_TYPE_POINTS:
3013 	case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
3014 	{
3015 		/* For SHADER_OUTPUT_TYPE_POINTS:
3016 		 * An edge size of 45px should be used. Given that each input will generate a 3x3 block,
3017 		 * this should give us a delta of 3px between the "quads".
3018 		 *
3019 		 * For instanced draw calls, use a delta of 3px as well.
3020 		 *
3021 		 * For SHADER_OUTPUT_TYPE_LINE_STRIP:
3022 		 * Each rectangle outline will take a 45x45 block. No vertical delta needs to be used.
3023 		 *
3024 		 * For SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
3025 		 * Each combination of 4 triangles makes up a triangles that takes 45x45 area.
3026 		 * No vertical delta needs to be used.
3027 		 */
3028 		*out_width  = 3 /* 'pixel' size */ * 8 + 3 /* Delta size */ * 7;
3029 		*out_height = (3 /* 'pixel' size */ * 8 + 3 /* Delta size */ * 7) * n_instances;
3030 
3031 		break;
3032 	}
3033 
3034 	default:
3035 	{
3036 		TCU_FAIL("Unsupported shader output type");
3037 	}
3038 	} /* switch (m_output_type) */
3039 }
3040 
3041 /** Returns amount of bytes that should be allocated for a buffer object to hold
3042  *  vertex data to be used for glDrawElements*() calls.
3043  *
3044  *  @param instanced true if the call is being made for an instanced draw call, false otherwise.
3045  *
3046  *  @return As per description.
3047  **/
getUnorderedArraysDataBufferSize(bool instanced)3048 glw::GLuint GeometryShaderRenderingLinesCase::getUnorderedArraysDataBufferSize(bool instanced)
3049 {
3050 	return (instanced) ? m_unordered_array_instanced_data_size : m_unordered_array_noninstanced_data_size;
3051 }
3052 
3053 /** Returns vertex data for the test. Only to be used for glDrawElements*() calls.
3054  *
3055  *  @param instanced true if the call is being made for an instanced draw call, false otherwise.
3056  *
3057  *  @return As per description.
3058  **/
getUnorderedArraysDataBuffer(bool instanced)3059 const void* GeometryShaderRenderingLinesCase::getUnorderedArraysDataBuffer(bool instanced)
3060 {
3061 	return instanced ? m_unordered_array_instanced_data : m_unordered_array_noninstanced_data;
3062 }
3063 
3064 /** Returns amount of bytes that should be allocated for a buffer object to hold
3065  *  index data to be used for glDrawElements*() calls.
3066  *
3067  *  @param instanced true if the call is being made for an instanced draw call, false otherwise.
3068  *
3069  *  @return As per description.
3070  **/
getUnorderedElementsDataBufferSize(bool instanced)3071 glw::GLuint GeometryShaderRenderingLinesCase::getUnorderedElementsDataBufferSize(bool instanced)
3072 {
3073 	return instanced ? m_unordered_elements_instanced_data_size : m_unordered_elements_noninstanced_data_size;
3074 }
3075 
3076 /** Returns index data for the test. Only to be used for glDrawElements*() calls.
3077  *
3078  *  @param instanced true if the call is being made for an instanced draw call, false otherwise.
3079  *
3080  **/
getUnorderedElementsDataBuffer(bool instanced)3081 const void* GeometryShaderRenderingLinesCase::getUnorderedElementsDataBuffer(bool instanced)
3082 {
3083 	return instanced ? m_unordered_elements_instanced_data : m_unordered_elements_noninstanced_data;
3084 }
3085 
3086 /** Returns type of the index, to be used for glDrawElements*() calls.
3087  *
3088  *  @return As per description.
3089  **/
getUnorderedElementsDataType()3090 glw::GLenum GeometryShaderRenderingLinesCase::getUnorderedElementsDataType()
3091 {
3092 	return GL_UNSIGNED_BYTE;
3093 }
3094 
3095 /** Retrieves maximum index value. To be used for glDrawRangeElements() test only.
3096  *
3097  *  @return As per description.
3098  **/
getUnorderedElementsMaxIndex()3099 glw::GLubyte GeometryShaderRenderingLinesCase::getUnorderedElementsMaxIndex()
3100 {
3101 	return m_unordered_elements_max_index;
3102 }
3103 
3104 /** Retrieves minimum index value. To be used for glDrawRangeElements() test only.
3105  *
3106  *  @return As per description.
3107  **/
getUnorderedElementsMinIndex()3108 glw::GLubyte GeometryShaderRenderingLinesCase::getUnorderedElementsMinIndex()
3109 {
3110 	return m_unordered_elements_min_index;
3111 }
3112 
3113 /** Retrieves vertex shader code to be used for the test.
3114  *
3115  *  @return As per description.
3116  **/
getVertexShaderCode()3117 std::string GeometryShaderRenderingLinesCase::getVertexShaderCode()
3118 {
3119 	static std::string vs_code =
3120 		"${VERSION}\n"
3121 		"\n"
3122 		"     in      vec4  position;\n"
3123 		"     uniform bool  is_indexed_draw_call;\n"
3124 		"     uniform bool  is_gl_lines_adjacency_draw_call;\n"
3125 		"     uniform bool  is_gl_line_strip_adjacency_draw_call;\n"
3126 		"     uniform bool  is_gl_lines_draw_call;\n"
3127 		"     uniform bool  is_gl_line_loop_draw_call;\n"
3128 		"     uniform ivec2 renderingTargetSize;\n"
3129 		"flat out     int   instance_id;\n"
3130 		"     out     vec4  vs_gs_color;\n"
3131 		"\n"
3132 		"void main()\n"
3133 		"{\n"
3134 		"    instance_id = gl_InstanceID;\n"
3135 		"\n"
3136 		/* non-instanced */
3137 		"    if (renderingTargetSize.y == 45 /* block size */)\n"
3138 		"    {\n"
3139 		"        gl_Position = position;\n"
3140 		"    }\n"
3141 		"    else\n"
3142 		"    {\n"
3143 		"        bool  represents_top_edge = (position.z == 0.0);\n"
3144 		"        float delta               = position.w;\n"
3145 		"        float y                   = 0.0;\n"
3146 		"\n"
3147 		"        if (represents_top_edge)\n"
3148 		"        {\n"
3149 		/* top vertices */
3150 		"            y = position.y + float(gl_InstanceID) * delta * 2.0 - 1.0;\n"
3151 		"        }\n"
3152 		"        else\n"
3153 		"        {\n"
3154 		"            y = position.y + float(gl_InstanceID) * delta * 2.0 - 1.0 + delta * 2.0;\n"
3155 		/* bottom vertices */
3156 		"        }\n"
3157 		"\n"
3158 		"        gl_Position = vec4(position.x,\n"
3159 		"                           y,\n"
3160 		"                           position.z,\n"
3161 		"                           1.0);\n"
3162 		"    }\n"
3163 		"\n"
3164 		"    vs_gs_color = vec4(0, 0, 0, 0);\n"
3165 		"\n"
3166 		"    if (is_gl_line_loop_draw_call)\n"
3167 		"    {\n"
3168 		/* GL_LINE_LOOP */
3169 		"        if (!is_indexed_draw_call)\n"
3170 		"        {\n"
3171 		"            switch(gl_VertexID)\n"
3172 		"            {\n"
3173 		"                case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3174 		"                case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3175 		"                case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3176 		"                case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3177 		"            }\n"
3178 		"        }\n"
3179 		"        else\n"
3180 		"        {\n"
3181 		"            switch(gl_VertexID)\n"
3182 		"            {\n"
3183 		"                case 3: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3184 		"                case 0: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3185 		"                case 1: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3186 		"                case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3187 		"            }\n"
3188 		"        }\n"
3189 		"    }\n"
3190 		"    else\n"
3191 		"    if (is_gl_line_strip_adjacency_draw_call)\n"
3192 		"    {\n"
3193 		/* GL_LINE_STRIP_ADJACENCY_EXT */
3194 		"        if (!is_indexed_draw_call)\n"
3195 		"        {\n"
3196 		"            switch(gl_VertexID)\n"
3197 		"            {\n"
3198 		"                case 1:\n"
3199 		"                case 5: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3200 		"                case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3201 		"                case 3: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3202 		"                case 0:\n"
3203 		"                case 4: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3204 		"            }\n"
3205 		"        }\n"
3206 		"        else\n"
3207 		"        {\n"
3208 		"            switch(gl_VertexID)\n"
3209 		"            {\n"
3210 		"                case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3211 		"                case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3212 		"                case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3213 		"                case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3214 		"            }\n"
3215 		"        }\n"
3216 		"    }\n"
3217 		"    else\n"
3218 		"    if (is_gl_lines_adjacency_draw_call)\n"
3219 		"    {\n"
3220 		/* GL_LINES_ADJACENCY_EXT */
3221 		"        if (!is_indexed_draw_call)\n"
3222 		"        {\n"
3223 		"            switch(gl_VertexID)\n"
3224 		"            {\n"
3225 		"                case 1:\n"
3226 		"                case 14: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3227 		"\n"
3228 		"                case 2:\n"
3229 		"                case 5: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3230 
3231 		"                case 6:\n"
3232 		"                case 9: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3233 
3234 		"                case 10:\n"
3235 		"                case 13: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3236 		"            }\n"
3237 		"        }\n"
3238 		"        else\n"
3239 		"        {\n"
3240 		"            switch(gl_VertexID)\n"
3241 		"            {\n"
3242 		"                case 0: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3243 		"                case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3244 		"                case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3245 		"                case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3246 		"            }\n"
3247 		"        }\n"
3248 		"    }\n"
3249 		"    else\n"
3250 		"    if (is_gl_lines_draw_call)\n"
3251 		"    {\n"
3252 		/* GL_LINES */
3253 		"        if (!is_indexed_draw_call)\n"
3254 		"        {\n"
3255 		"            switch(gl_VertexID)\n"
3256 		"            {\n"
3257 		"                case 0:\n"
3258 		"                case 7: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3259 		"\n"
3260 		"                case 1:\n"
3261 		"                case 2: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3262 
3263 		"                case 3:\n"
3264 		"                case 4: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3265 
3266 		"                case 5:\n"
3267 		"                case 6: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3268 		"            }\n"
3269 		"        }\n"
3270 		"        else\n"
3271 		"        {\n"
3272 		"            switch(gl_VertexID)\n"
3273 		"            {\n"
3274 		"                case 6:\n"
3275 		"                case 1: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3276 		"\n"
3277 		"                case 7:\n"
3278 		"                case 4: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3279 
3280 		"                case 5:\n"
3281 		"                case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3282 
3283 		"                case 3:\n"
3284 		"                case 0: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3285 		"            }\n"
3286 		"        }\n"
3287 		"    }\n"
3288 		"    else\n"
3289 		"    {\n"
3290 		/* GL_LINE_STRIP */
3291 		"        if (!is_indexed_draw_call)\n"
3292 		"        {\n"
3293 		"            switch(gl_VertexID)\n"
3294 		"            {\n"
3295 		"                case 0:\n"
3296 		"                case 4: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3297 		"                case 1: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3298 		"                case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3299 		"                case 3: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3300 		"            }\n"
3301 		"        }\n"
3302 		"        else\n"
3303 		"        {\n"
3304 		"            switch(gl_VertexID)\n"
3305 		"            {\n"
3306 		"                case 0:\n"
3307 		"                case 4: vs_gs_color = vec4(1, 0, 0, 0); break;\n"
3308 		"                case 1: vs_gs_color = vec4(0, 0, 0, 1); break;\n"
3309 		"                case 2: vs_gs_color = vec4(0, 0, 1, 0); break;\n"
3310 		"                case 3: vs_gs_color = vec4(0, 1, 0, 0); break;\n"
3311 		"            }\n"
3312 		"        }\n"
3313 		"    }\n"
3314 		"}\n";
3315 
3316 	std::string result;
3317 
3318 	switch (m_output_type)
3319 	{
3320 	case SHADER_OUTPUT_TYPE_LINE_STRIP:
3321 	case SHADER_OUTPUT_TYPE_POINTS:
3322 	case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
3323 	{
3324 		result = vs_code;
3325 
3326 		break;
3327 	}
3328 
3329 	default:
3330 	{
3331 		TCU_FAIL("Unsupported shader output type used");
3332 	}
3333 	} /* switch (m_output_type) */
3334 
3335 	return result;
3336 }
3337 
3338 /** Sets test-specific uniforms for a program object that is then used for the draw call.
3339  *
3340  *  @param drawcall_type Type of the draw call that is to follow right after this function is called.
3341  **/
setUniformsBeforeDrawCall(_draw_call_type drawcall_type)3342 void GeometryShaderRenderingLinesCase::setUniformsBeforeDrawCall(_draw_call_type drawcall_type)
3343 {
3344 	const glw::Functions& gl							  = m_context.getRenderContext().getFunctions();
3345 	glw::GLint is_gl_line_loop_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_gl_line_loop_draw_call");
3346 	glw::GLint is_gl_line_strip_adjacency_draw_call_uniform_location =
3347 		gl.getUniformLocation(m_po_id, "is_gl_line_strip_adjacency_draw_call");
3348 	glw::GLint is_gl_lines_adjacency_draw_call_uniform_location =
3349 		gl.getUniformLocation(m_po_id, "is_gl_lines_adjacency_draw_call");
3350 	glw::GLint is_gl_lines_draw_call_uniform_location = gl.getUniformLocation(m_po_id, "is_gl_lines_draw_call");
3351 	glw::GLint is_indexed_draw_call_uniform_location  = gl.getUniformLocation(m_po_id, "is_indexed_draw_call");
3352 
3353 	TCU_CHECK(is_gl_line_loop_draw_call_uniform_location != -1);
3354 	TCU_CHECK(is_gl_line_strip_adjacency_draw_call_uniform_location != -1);
3355 	TCU_CHECK(is_gl_lines_adjacency_draw_call_uniform_location != -1);
3356 	TCU_CHECK(is_gl_lines_draw_call_uniform_location != -1);
3357 	TCU_CHECK(is_indexed_draw_call_uniform_location != -1);
3358 
3359 	gl.uniform1i(is_indexed_draw_call_uniform_location, (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
3360 														 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED ||
3361 														 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS));
3362 	gl.uniform1i(is_gl_line_loop_draw_call_uniform_location, (m_drawcall_mode == GL_LINE_LOOP));
3363 	gl.uniform1i(is_gl_line_strip_adjacency_draw_call_uniform_location,
3364 				 (m_drawcall_mode == GL_LINE_STRIP_ADJACENCY_EXT));
3365 	gl.uniform1i(is_gl_lines_adjacency_draw_call_uniform_location, (m_drawcall_mode == GL_LINES_ADJACENCY_EXT));
3366 	gl.uniform1i(is_gl_lines_draw_call_uniform_location, (m_drawcall_mode == GL_LINES));
3367 }
3368 
3369 /** Verifies that the rendered data is correct.
3370  *
3371  *  @param drawcall_type Type of the draw call that was used to render the geometry.
3372  *  @param instance_id   Instance ID to be verified. Use 0 for non-instanced draw calls.
3373  *  @param data          Contents of the rendertarget after the test has finished rendering.
3374  **/
verify(_draw_call_type drawcall_type,unsigned int instance_id,const unsigned char * data)3375 void GeometryShaderRenderingLinesCase::verify(_draw_call_type drawcall_type, unsigned int instance_id,
3376 											  const unsigned char* data)
3377 {
3378 	const float  epsilon		  = 1.0f / 256.0f;
3379 	unsigned int rt_height		  = 0;
3380 	unsigned int rt_width		  = 0;
3381 	unsigned int single_rt_height = 0;
3382 	unsigned int single_rt_width  = 0;
3383 
3384 	if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED ||
3385 		drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED)
3386 	{
3387 		getRenderTargetSize(getAmountOfDrawInstances(), &rt_width, &rt_height);
3388 	}
3389 	else
3390 	{
3391 		getRenderTargetSize(1, &rt_width, &rt_height);
3392 	}
3393 
3394 	getRenderTargetSize(1, &single_rt_width, &single_rt_height);
3395 
3396 	/* Verification is output type-specific */
3397 	const unsigned int row_width = rt_width * 4 /* components */;
3398 
3399 	switch (m_output_type)
3400 	{
3401 	case SHADER_OUTPUT_TYPE_LINE_STRIP:
3402 	{
3403 		/* The test renders a rectangle outline with 3 line segments for each edge.
3404 		 * The verification checks color of each edge's middle line segment.
3405 		 *
3406 		 * Corners are skipped to keep the implementation simple. */
3407 		for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge)
3408 		{
3409 			/* Determine edge-specific properties:
3410 			 *
3411 			 * Edge 0 - top edge;
3412 			 * Edge 1 - right edge;
3413 			 * Edge 2 - bottom edge;
3414 			 * Edge 3 - left edge.
3415 			 *
3416 			 **/
3417 			int		  end_x = 0;
3418 			int		  end_y = 0;
3419 			tcu::Vec4 expected_rgba;
3420 			int		  start_x = 0;
3421 			int		  start_y = 0;
3422 
3423 			switch (n_edge)
3424 			{
3425 			case 0:
3426 			{
3427 				/* Top edge */
3428 				start_x = 3;								  /* skip the corner */
3429 				start_y = 1 + instance_id * single_rt_height; /* middle segment */
3430 
3431 				end_x = single_rt_width - 3; /* skip the corner */
3432 				end_y = start_y;
3433 
3434 				expected_rgba = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f) +
3435 								tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f);
3436 
3437 				break;
3438 			}
3439 
3440 			case 1:
3441 			{
3442 				/* Right edge */
3443 				start_x = single_rt_width - 2;				  /* middle segment */
3444 				start_y = 3 + instance_id * single_rt_height; /* skip the corner */
3445 
3446 				end_x = start_x;
3447 				end_y = start_y + single_rt_height - 6; /* skip the corners */
3448 
3449 				expected_rgba = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f) +
3450 								tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f) * tcu::Vec4(0.5f);
3451 
3452 				break;
3453 			}
3454 
3455 			case 2:
3456 			{
3457 				/* Bottom edge */
3458 				start_x = 3;													 /* skip the corner */
3459 				start_y = single_rt_height - 3 + instance_id * single_rt_height; /* middle segment */
3460 
3461 				end_x = single_rt_width - 6; /* skip the corners */
3462 				end_y = start_y;
3463 
3464 				expected_rgba = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f) * tcu::Vec4(0.5f) +
3465 								tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * tcu::Vec4(0.5f);
3466 
3467 				break;
3468 			}
3469 
3470 			case 3:
3471 			{
3472 				/* Left edge */
3473 				start_x = 1;								  /* middle segment */
3474 				start_y = 3 + instance_id * single_rt_height; /* skip the corner */
3475 
3476 				end_x = start_x;
3477 				end_y = start_y + single_rt_height - 6; /* skip the corners */
3478 
3479 				expected_rgba = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * tcu::Vec4(0.5f) +
3480 								tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f) * tcu::Vec4(0.5f);
3481 
3482 				break;
3483 			}
3484 
3485 			default:
3486 			{
3487 				TCU_FAIL("Unrecognized edge index");
3488 			}
3489 			} /* switch(n_edge) */
3490 
3491 			/* Move over the edge and make sure the rendered pixels are valid */
3492 			int dx		 = (end_x != start_x) ? 1 : 0;
3493 			int dy		 = (end_y != start_y) ? 1 : 0;
3494 			int n_pixels = (end_x - start_x) + (end_y - start_y);
3495 
3496 			for (int n_pixel = 0; n_pixel < n_pixels; ++n_pixel)
3497 			{
3498 				int cur_x = start_x + n_pixel * dx;
3499 				int cur_y = start_y + n_pixel * dy;
3500 
3501 				/* Calculate expected and rendered pixel color */
3502 				const unsigned char* read_data		  = data + cur_y * row_width + cur_x * 4 /* components */;
3503 				float				 rendered_rgba[4] = { 0 };
3504 
3505 				for (unsigned int n_channel = 0; n_channel < 4 /* RGBA */; ++n_channel)
3506 				{
3507 					rendered_rgba[n_channel] = float(read_data[n_channel]) / 255.0f;
3508 				}
3509 
3510 				/* Compare the data */
3511 				if (de::abs(rendered_rgba[0] - expected_rgba[0]) > epsilon ||
3512 					de::abs(rendered_rgba[1] - expected_rgba[1]) > epsilon ||
3513 					de::abs(rendered_rgba[2] - expected_rgba[2]) > epsilon ||
3514 					de::abs(rendered_rgba[3] - expected_rgba[3]) > epsilon)
3515 				{
3516 					m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << cur_x << ", " << cur_y
3517 									   << ") "
3518 									   << "equal (" << rendered_rgba[0] << ", " << rendered_rgba[1] << ", "
3519 									   << rendered_rgba[2] << ", " << rendered_rgba[3] << ") "
3520 									   << "exceeds allowed epsilon when compared to reference data equal ("
3521 									   << expected_rgba[0] << ", " << expected_rgba[1] << ", " << expected_rgba[2]
3522 									   << ", " << expected_rgba[3] << ")." << tcu::TestLog::EndMessage;
3523 
3524 					TCU_FAIL("Data comparison failed");
3525 				} /* if (data comparison failed) */
3526 			}	 /* for (all points) */
3527 		}		  /* for (all edges) */
3528 
3529 		break;
3530 	} /* case SHADER_OUTPUT_TYPE_LINE_STRIP: */
3531 
3532 	case SHADER_OUTPUT_TYPE_POINTS:
3533 	{
3534 		/* Verify centers of the points generated by geometry shader */
3535 		int dx = 0;
3536 		int dy = 0;
3537 
3538 		bool ignore_first_point = false;
3539 		int  start_x			= 0;
3540 		int  start_y			= 0;
3541 
3542 		tcu::Vec4 end_color;
3543 		tcu::Vec4 start_color;
3544 
3545 		for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge)
3546 		{
3547 			/* Determine edge-specific properties:
3548 			 *
3549 			 * Edge 0 - top edge; NOTE: the test should skip point at (1px, 1px) as it is overwritten by
3550 			 *          edge 3!
3551 			 * Edge 1 - right edge;
3552 			 * Edge 2 - bottom edge;
3553 			 * Edge 3 - left edge.
3554 			 *
3555 			 **/
3556 			switch (n_edge)
3557 			{
3558 			case 0:
3559 			{
3560 				dx				   = 6;
3561 				dy				   = 0;
3562 				ignore_first_point = true;
3563 				start_x			   = 1;
3564 				start_y			   = 1 + instance_id * single_rt_height;
3565 
3566 				end_color   = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f);
3567 				start_color = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
3568 
3569 				break;
3570 			}
3571 
3572 			case 1:
3573 			{
3574 				dx				   = 0;
3575 				dy				   = 6;
3576 				ignore_first_point = false;
3577 				start_x			   = single_rt_width - 1;
3578 				start_y			   = 1 + instance_id * single_rt_height;
3579 
3580 				end_color   = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f);
3581 				start_color = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f);
3582 
3583 				break;
3584 			}
3585 
3586 			case 2:
3587 			{
3588 				dx				   = -6;
3589 				dy				   = 0;
3590 				ignore_first_point = false;
3591 				start_x			   = single_rt_width - 1;
3592 				start_y			   = single_rt_height - 1 + instance_id * single_rt_height;
3593 
3594 				end_color   = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
3595 				start_color = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f);
3596 
3597 				break;
3598 			}
3599 
3600 			case 3:
3601 			{
3602 				dx				   = 0;
3603 				dy				   = -6;
3604 				ignore_first_point = false;
3605 				start_x			   = 1;
3606 				start_y			   = single_rt_height - 1 + instance_id * single_rt_height;
3607 
3608 				end_color   = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
3609 				start_color = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
3610 
3611 				break;
3612 			}
3613 
3614 			default:
3615 			{
3616 				TCU_FAIL("Unrecognized edge index");
3617 			}
3618 			} /* switch(n_edge) */
3619 
3620 			for (unsigned int n_point = 0; n_point < 8 /* points */; ++n_point)
3621 			{
3622 				int cur_x = start_x + n_point * dx;
3623 				int cur_y = start_y + n_point * dy;
3624 
3625 				/* Skip the iteration if we're dealing with a first point, for which
3626 				 * the comparison should be skipped */
3627 				if (ignore_first_point && n_point == 0)
3628 				{
3629 					continue;
3630 				}
3631 
3632 				/* Calculate expected and rendered pixel color */
3633 				const unsigned char* read_data		   = data + cur_y * row_width + cur_x * 4 /* components */;
3634 				float				 reference_rgba[4] = { 0 };
3635 				float				 rendered_rgba[4]  = { 0 };
3636 
3637 				for (unsigned int n_channel = 0; n_channel < 4 /* RGBA */; ++n_channel)
3638 				{
3639 					reference_rgba[n_channel] = start_color[n_channel] +
3640 												(end_color[n_channel] - start_color[n_channel]) * float(n_point) / 7.0f;
3641 					rendered_rgba[n_channel] = (float)(read_data[n_channel]) / 255.0f;
3642 				}
3643 
3644 				/* Compare the data */
3645 				if (de::abs(rendered_rgba[0] - reference_rgba[0]) > epsilon ||
3646 					de::abs(rendered_rgba[1] - reference_rgba[1]) > epsilon ||
3647 					de::abs(rendered_rgba[2] - reference_rgba[2]) > epsilon ||
3648 					de::abs(rendered_rgba[3] - reference_rgba[3]) > epsilon)
3649 				{
3650 					m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << cur_x << ", " << cur_y
3651 									   << ") "
3652 									   << "equal (" << rendered_rgba[0] << ", " << rendered_rgba[1] << ", "
3653 									   << rendered_rgba[2] << ", " << rendered_rgba[3] << ") "
3654 									   << "exceeds allowed epsilon when compared to reference data equal ("
3655 									   << reference_rgba[0] << ", " << reference_rgba[1] << ", " << reference_rgba[2]
3656 									   << ", " << reference_rgba[3] << ")." << tcu::TestLog::EndMessage;
3657 
3658 					TCU_FAIL("Data comparison failed");
3659 				} /* if (data comparison failed) */
3660 
3661 			} /* for (all points) */
3662 		}	 /* for (all edges) */
3663 
3664 		/* Done */
3665 		break;
3666 	} /* case SHADER_OUTPUT_TYPE_POINTS: */
3667 
3668 	case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
3669 	{
3670 		/* The test renders four triangles - two vertices are taken from each edge and the third
3671 		 * one is set at (0, 0, 0, 1) (screen-space). The rendering output is verified by
3672 		 * sampling centroids off each triangle */
3673 		for (unsigned int n_edge = 0; n_edge < 4 /* edges */; ++n_edge)
3674 		{
3675 			/* Determine edge-specific properties */
3676 			tcu::Vec2 centroid;
3677 			tcu::Vec4 reference_rgba;
3678 			tcu::Vec2 v1;
3679 			tcu::Vec2 v2;
3680 			tcu::Vec2 v3 = tcu::Vec2(0.5f, 0.5f + float(instance_id));
3681 
3682 			switch (n_edge)
3683 			{
3684 			case 0:
3685 			{
3686 				/* Top edge */
3687 				v1 = tcu::Vec2(0.0f, float(instance_id) + 0.0f);
3688 				v2 = tcu::Vec2(1.0f, float(instance_id) + 0.0f);
3689 
3690 				reference_rgba = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
3691 
3692 				break;
3693 			}
3694 
3695 			case 1:
3696 			{
3697 				/* Right edge */
3698 				v1 = tcu::Vec2(1.0f, float(instance_id) + 0.0f);
3699 				v2 = tcu::Vec2(1.0f, float(instance_id) + 1.0f);
3700 
3701 				reference_rgba = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f);
3702 
3703 				break;
3704 			}
3705 
3706 			case 2:
3707 			{
3708 				/* Bottom edge */
3709 				v1 = tcu::Vec2(0.0f, float(instance_id) + 1.0f);
3710 				v2 = tcu::Vec2(1.0f, float(instance_id) + 1.0f);
3711 
3712 				reference_rgba = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f);
3713 
3714 				break;
3715 			}
3716 
3717 			case 3:
3718 			{
3719 				/* Left edge */
3720 				v1 = tcu::Vec2(0.0f, float(instance_id) + 0.0f);
3721 				v2 = tcu::Vec2(0.0f, float(instance_id) + 1.0f);
3722 
3723 				reference_rgba = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
3724 
3725 				break;
3726 			}
3727 
3728 			default:
3729 			{
3730 				TCU_FAIL("Unrecognized edge index");
3731 			}
3732 			} /* switch (n_edge) */
3733 
3734 			/* Calculate centroid of the triangle. */
3735 			centroid[0] = (v1[0] + v2[0] + v3[0]) / 3.0f;
3736 			centroid[1] = (v1[1] + v2[1] + v3[1]) / 3.0f;
3737 
3738 			/* Retrieve the sample */
3739 			int centroid_xy[2] = { int(centroid[0] * float(single_rt_width)),
3740 								   int(centroid[1] * float(single_rt_height)) };
3741 			const unsigned char* rendered_rgba_ubyte =
3742 				data + centroid_xy[1] * row_width + centroid_xy[0] * 4 /* components */;
3743 			const float rendered_rgba_float[] = {
3744 				float(rendered_rgba_ubyte[0]) / 255.0f, float(rendered_rgba_ubyte[1]) / 255.0f,
3745 				float(rendered_rgba_ubyte[2]) / 255.0f, float(rendered_rgba_ubyte[3]) / 255.0f,
3746 			};
3747 
3748 			/* Compare the reference and rendered pixels */
3749 			if (de::abs(rendered_rgba_float[0] - reference_rgba[0]) > epsilon ||
3750 				de::abs(rendered_rgba_float[1] - reference_rgba[1]) > epsilon ||
3751 				de::abs(rendered_rgba_float[2] - reference_rgba[2]) > epsilon ||
3752 				de::abs(rendered_rgba_float[3] - reference_rgba[3]) > epsilon)
3753 			{
3754 				m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << centroid_xy[0] << ", "
3755 								   << centroid_xy[1] << ") "
3756 								   << "equal (" << rendered_rgba_float[0] << ", " << rendered_rgba_float[1] << ", "
3757 								   << rendered_rgba_float[2] << ", " << rendered_rgba_float[3] << ") "
3758 								   << "exceeds allowed epsilon when compared to reference data equal ("
3759 								   << reference_rgba[0] << ", " << reference_rgba[1] << ", " << reference_rgba[2]
3760 								   << ", " << reference_rgba[3] << ")." << tcu::TestLog::EndMessage;
3761 
3762 				TCU_FAIL("Data comparison failed");
3763 			} /* if (data comparison failed) */
3764 		}	 /* for (all edges) */
3765 
3766 		break;
3767 	}
3768 
3769 	default:
3770 	{
3771 		TCU_FAIL("Unsupported shader output type used");
3772 	}
3773 	} /* switch (m_output_type) */
3774 }
3775 
3776 /** Constructor.
3777  *
3778  *  @param use_adjacency_data true  if the test case is being instantiated for draw call modes that will
3779  *                                  features adjacency data,
3780  *                            false otherwise.
3781  *  @param drawcall_mode      GL draw call mode that will be used for the tests.
3782  *  @param output_type        Shader output type that the test case is being instantiated for.
3783  *  @param context            Rendering context;
3784  *  @param testContext        Test context;
3785  *  @param name               Test name.
3786  **/
GeometryShaderRenderingTrianglesCase(Context & context,const ExtParameters & extParams,const char * name,bool use_adjacency_data,glw::GLenum drawcall_mode,_shader_output_type output_type)3787 GeometryShaderRenderingTrianglesCase::GeometryShaderRenderingTrianglesCase(Context&				context,
3788 																		   const ExtParameters& extParams,
3789 																		   const char* name, bool use_adjacency_data,
3790 																		   glw::GLenum		   drawcall_mode,
3791 																		   _shader_output_type output_type)
3792 	: GeometryShaderRenderingCase(
3793 		  context, extParams, name,
3794 		  "Verifies all draw calls work correctly for specific input+output+draw call mode combination")
3795 	, m_output_type(output_type)
3796 	, m_drawcall_mode(drawcall_mode)
3797 	, m_use_adjacency_data(use_adjacency_data)
3798 	, m_raw_array_instanced_data(0)
3799 	, m_raw_array_instanced_data_size(0)
3800 	, m_raw_array_noninstanced_data(0)
3801 	, m_raw_array_noninstanced_data_size(0)
3802 	, m_unordered_array_instanced_data(0)
3803 	, m_unordered_array_instanced_data_size(0)
3804 	, m_unordered_array_noninstanced_data(0)
3805 	, m_unordered_array_noninstanced_data_size(0)
3806 	, m_unordered_elements_instanced_data(0)
3807 	, m_unordered_elements_instanced_data_size(0)
3808 	, m_unordered_elements_noninstanced_data(0)
3809 	, m_unordered_elements_noninstanced_data_size(0)
3810 	, m_unordered_elements_max_index(24) /* maximum amount of vertices generated by this test case */
3811 	, m_unordered_elements_min_index(0)
3812 {
3813 	/* Sanity checks */
3814 	if (!m_use_adjacency_data)
3815 	{
3816 		if (drawcall_mode != GL_TRIANGLES && drawcall_mode != GL_TRIANGLE_STRIP && drawcall_mode != GL_TRIANGLE_FAN)
3817 		{
3818 			TCU_FAIL("Only GL_TRIANGLES or GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN draw call modes are supported for "
3819 					 "'triangles' geometry shader input layout qualifier test implementation");
3820 		}
3821 	}
3822 	else
3823 	{
3824 		if (drawcall_mode != GL_TRIANGLES_ADJACENCY_EXT && drawcall_mode != GL_TRIANGLE_STRIP_ADJACENCY_EXT)
3825 		{
3826 			TCU_FAIL("Only GL_TRIANGLES_ADJACENCY_EXT or GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call modes are supported "
3827 					 "for 'triangles_adjacency' geometry shader input layout qualifier test implementation");
3828 		}
3829 	}
3830 
3831 	if (output_type != SHADER_OUTPUT_TYPE_POINTS && output_type != SHADER_OUTPUT_TYPE_LINE_STRIP &&
3832 		output_type != SHADER_OUTPUT_TYPE_TRIANGLE_STRIP)
3833 	{
3834 		TCU_FAIL("Unsupported output layout qualifier type requested for 'triangles' geometry shader input layout "
3835 				 "qualifier test implementation");
3836 	}
3837 
3838 	/* Generate data in two flavors - one for non-instanced case, the other one for instanced case */
3839 	for (int n_case = 0; n_case < 2 /* cases */; ++n_case)
3840 	{
3841 		bool			is_instanced					 = (n_case != 0);
3842 		int				n_instances						 = 0;
3843 		float**			raw_arrays_data_ptr				 = NULL;
3844 		unsigned int*   raw_arrays_data_size_ptr		 = NULL;
3845 		unsigned int	rendertarget_height				 = 0;
3846 		unsigned int	rendertarget_width				 = 0;
3847 		float**			unordered_arrays_data_ptr		 = NULL;
3848 		unsigned int*   unordered_arrays_data_size_ptr   = NULL;
3849 		unsigned char** unordered_elements_data_ptr		 = NULL;
3850 		unsigned int*   unordered_elements_data_size_ptr = NULL;
3851 
3852 		if (!is_instanced)
3853 		{
3854 			/* Non-instanced case */
3855 			n_instances						 = 1;
3856 			raw_arrays_data_ptr				 = &m_raw_array_noninstanced_data;
3857 			raw_arrays_data_size_ptr		 = &m_raw_array_noninstanced_data_size;
3858 			unordered_arrays_data_ptr		 = &m_unordered_array_noninstanced_data;
3859 			unordered_arrays_data_size_ptr   = &m_unordered_array_noninstanced_data_size;
3860 			unordered_elements_data_ptr		 = &m_unordered_elements_noninstanced_data;
3861 			unordered_elements_data_size_ptr = &m_unordered_elements_noninstanced_data_size;
3862 		}
3863 		else
3864 		{
3865 			/* Instanced case */
3866 			n_instances						 = getAmountOfDrawInstances();
3867 			raw_arrays_data_ptr				 = &m_raw_array_instanced_data;
3868 			raw_arrays_data_size_ptr		 = &m_raw_array_instanced_data_size;
3869 			unordered_arrays_data_ptr		 = &m_unordered_array_instanced_data;
3870 			unordered_arrays_data_size_ptr   = &m_unordered_array_instanced_data_size;
3871 			unordered_elements_data_ptr		 = &m_unordered_elements_instanced_data;
3872 			unordered_elements_data_size_ptr = &m_unordered_elements_instanced_data_size;
3873 		}
3874 
3875 		getRenderTargetSize(n_instances, &rendertarget_width, &rendertarget_height);
3876 
3877 		/* Store full-screen quad coordinates that will be used for actual array data generation. */
3878 		float dx = 2.0f / float(rendertarget_width);
3879 		float dy = 2.0f / float(rendertarget_height);
3880 
3881 		/* Generate raw vertex array data */
3882 		unsigned int single_rt_height = 0;
3883 		unsigned int single_rt_width  = 0;
3884 		unsigned int whole_rt_width   = 0;
3885 		unsigned int whole_rt_height  = 0;
3886 
3887 		*raw_arrays_data_size_ptr =
3888 			static_cast<unsigned int>(getAmountOfVerticesPerInstance() * 4 /* components */ * sizeof(float));
3889 		*raw_arrays_data_ptr = new float[*raw_arrays_data_size_ptr / sizeof(float)];
3890 
3891 		getRenderTargetSize(1, &single_rt_width, &single_rt_height);
3892 		getRenderTargetSize(getAmountOfDrawInstances(), &whole_rt_width, &whole_rt_height);
3893 
3894 		/* Generate the general coordinates storage first.
3895 		 *
3896 		 * For non-instanced draw calls, we only need to draw a single instance, hence we are free
3897 		 * to use screen-space coordinates.
3898 		 * For instanced draw calls, we'll have the vertex shader add gl_InstanceID-specific deltas
3899 		 * to make sure the vertices are laid out correctly, so map <-1, 1> range to <0, screen_space_height_of_single_instance>
3900 		 */
3901 		std::vector<tcu::Vec4> data_coordinates;
3902 		float				   dx_multiplier = 0.0f;
3903 		float				   dy_multiplier = 0.0f;
3904 		float				   end_y		 = 0.0f;
3905 		float				   mid_y		 = 0.0f;
3906 		float				   start_y		 = 0.0f;
3907 
3908 		if (is_instanced)
3909 		{
3910 			start_y = -1.0f;
3911 			end_y   = start_y + float(single_rt_height) / float(whole_rt_height) * 2.0f;
3912 			mid_y   = start_y + (end_y - start_y) * 0.5f;
3913 		}
3914 		else
3915 		{
3916 			end_y   = 1.0f;
3917 			mid_y   = 0.0f;
3918 			start_y = -1.0f;
3919 		}
3920 
3921 		if (output_type == SHADER_OUTPUT_TYPE_POINTS)
3922 		{
3923 			dx_multiplier = 1.5f;
3924 			dy_multiplier = 1.5f;
3925 		}
3926 		else if (output_type == SHADER_OUTPUT_TYPE_LINE_STRIP)
3927 		{
3928 			dx_multiplier = 1.5f;
3929 			dy_multiplier = 1.5f;
3930 		}
3931 
3932 		/* W stores information whether given vertex is the middle vertex */
3933 		data_coordinates.push_back(tcu::Vec4(0, mid_y, 0, 1));						  /* Middle vertex */
3934 		data_coordinates.push_back(tcu::Vec4(-1 + dx * dx_multiplier, mid_y, 0, 0));  /* Left vertex */
3935 		data_coordinates.push_back(tcu::Vec4(0, start_y + dy * dy_multiplier, 0, 0)); /* Top vertex */
3936 		data_coordinates.push_back(tcu::Vec4(1 - dx * dx_multiplier, mid_y, 0, 0));   /* Right vertex */
3937 		data_coordinates.push_back(tcu::Vec4(0, end_y - dy * dy_multiplier, 0, 0));   /* Bottom vertex */
3938 
3939 		/* Now that we have the general storage ready, we can generate raw array data for specific draw
3940 		 * call that this specific test instance will be verifying */
3941 		int	n_raw_array_indices	 = 0;
3942 		int	raw_array_indices[24]   = { -1 }; /* 12 is a max for all supported input geometry */
3943 		float* raw_array_traveller_ptr = *raw_arrays_data_ptr;
3944 
3945 		for (unsigned int n = 0; n < sizeof(raw_array_indices) / sizeof(raw_array_indices[0]); ++n)
3946 		{
3947 			raw_array_indices[n] = -1;
3948 		}
3949 
3950 		switch (m_drawcall_mode)
3951 		{
3952 		case GL_TRIANGLES:
3953 		{
3954 			/* ABC triangle */
3955 			raw_array_indices[0] = 0;
3956 			raw_array_indices[1] = 1;
3957 			raw_array_indices[2] = 2;
3958 
3959 			/* ACD triangle */
3960 			raw_array_indices[3] = 0;
3961 			raw_array_indices[4] = 2;
3962 			raw_array_indices[5] = 3;
3963 
3964 			/* ADE triangle */
3965 			raw_array_indices[6] = 0;
3966 			raw_array_indices[7] = 3;
3967 			raw_array_indices[8] = 4;
3968 
3969 			/* AEB triangle */
3970 			raw_array_indices[9]  = 0;
3971 			raw_array_indices[10] = 4;
3972 			raw_array_indices[11] = 1;
3973 
3974 			n_raw_array_indices = 12;
3975 
3976 			break;
3977 		} /* case GL_TRIANGLES: */
3978 
3979 		case GL_TRIANGLES_ADJACENCY_EXT:
3980 		{
3981 			/* Note: Geometry shader used by this test does not rely on adjacency data
3982 			 *       so we will fill corresponding indices with meaningless information
3983 			 *       (always first vertex data) */
3984 			/* ABC triangle */
3985 			raw_array_indices[0] = 0;
3986 			raw_array_indices[1] = 0;
3987 			raw_array_indices[2] = 1;
3988 			raw_array_indices[3] = 0;
3989 			raw_array_indices[4] = 2;
3990 			raw_array_indices[5] = 0;
3991 
3992 			/* ACD triangle */
3993 			raw_array_indices[6]  = 0;
3994 			raw_array_indices[7]  = 0;
3995 			raw_array_indices[8]  = 2;
3996 			raw_array_indices[9]  = 0;
3997 			raw_array_indices[10] = 3;
3998 			raw_array_indices[11] = 0;
3999 
4000 			/* ADE triangle */
4001 			raw_array_indices[12] = 0;
4002 			raw_array_indices[13] = 0;
4003 			raw_array_indices[14] = 3;
4004 			raw_array_indices[15] = 0;
4005 			raw_array_indices[16] = 4;
4006 			raw_array_indices[17] = 0;
4007 
4008 			/* AEB triangle */
4009 			raw_array_indices[18] = 0;
4010 			raw_array_indices[19] = 0;
4011 			raw_array_indices[20] = 4;
4012 			raw_array_indices[21] = 0;
4013 			raw_array_indices[22] = 1;
4014 			raw_array_indices[23] = 0;
4015 
4016 			n_raw_array_indices = 24;
4017 
4018 			break;
4019 		} /* case GL_TRIANGLES_ADJACENCY_EXT:*/
4020 
4021 		case GL_TRIANGLE_FAN:
4022 		{
4023 			/* ABCDEB */
4024 			raw_array_indices[0] = 0;
4025 			raw_array_indices[1] = 1;
4026 			raw_array_indices[2] = 2;
4027 			raw_array_indices[3] = 3;
4028 			raw_array_indices[4] = 4;
4029 			raw_array_indices[5] = 1;
4030 
4031 			n_raw_array_indices = 6;
4032 
4033 			break;
4034 		} /* case GL_TRIANGLE_FAN: */
4035 
4036 		case GL_TRIANGLE_STRIP:
4037 		{
4038 			/* BACDAEB.
4039 			 *
4040 			 * Note that this will generate a degenerate triangle (ACD & CDA) but that's fine
4041 			 * since we only sample triangle centroids in this test.
4042 			 */
4043 			raw_array_indices[0] = 1;
4044 			raw_array_indices[1] = 0;
4045 			raw_array_indices[2] = 2;
4046 			raw_array_indices[3] = 3;
4047 			raw_array_indices[4] = 0;
4048 			raw_array_indices[5] = 4;
4049 			raw_array_indices[6] = 1;
4050 
4051 			n_raw_array_indices = 7;
4052 
4053 			break;
4054 		} /* case GL_TRIANGLE_STRIP: */
4055 
4056 		case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4057 		{
4058 			/* Order as in GL_TRIANGLE_STRIP case. Adjacency data not needed for the test,
4059 			 * hence any data can be used.
4060 			 */
4061 			raw_array_indices[0]  = 1;
4062 			raw_array_indices[1]  = 0;
4063 			raw_array_indices[2]  = 0;
4064 			raw_array_indices[3]  = 0;
4065 			raw_array_indices[4]  = 2;
4066 			raw_array_indices[5]  = 0;
4067 			raw_array_indices[6]  = 3;
4068 			raw_array_indices[7]  = 0;
4069 			raw_array_indices[8]  = 0;
4070 			raw_array_indices[9]  = 0;
4071 			raw_array_indices[10] = 4;
4072 			raw_array_indices[11] = 0;
4073 			raw_array_indices[12] = 1;
4074 			raw_array_indices[13] = 0;
4075 
4076 			n_raw_array_indices = 14;
4077 			break;
4078 		} /* case GL_TRIANGLE_STRIP_ADJACENCY_EXT: */
4079 
4080 		default:
4081 		{
4082 			TCU_FAIL("Unsupported draw call mode");
4083 		}
4084 		} /* switch (m_drawcall_mode) */
4085 
4086 		for (int index = 0; index < n_raw_array_indices; ++index)
4087 		{
4088 			if (raw_array_indices[index] != -1)
4089 			{
4090 				*raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].x();
4091 				raw_array_traveller_ptr++;
4092 				*raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].y();
4093 				raw_array_traveller_ptr++;
4094 				*raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].z();
4095 				raw_array_traveller_ptr++;
4096 				*raw_array_traveller_ptr = data_coordinates[raw_array_indices[index]].w();
4097 				raw_array_traveller_ptr++;
4098 			}
4099 		}
4100 
4101 		/* Generate unordered data:
4102 		 *
4103 		 * Store vertices in reversed order and configure indices so that the pipeline receives
4104 		 * vertex data in original order */
4105 		*unordered_arrays_data_size_ptr   = *raw_arrays_data_size_ptr;
4106 		*unordered_arrays_data_ptr		  = new float[*unordered_arrays_data_size_ptr];
4107 		*unordered_elements_data_size_ptr = static_cast<unsigned int>(n_raw_array_indices * sizeof(unsigned char));
4108 		*unordered_elements_data_ptr	  = new unsigned char[*unordered_elements_data_size_ptr];
4109 
4110 		/* Set unordered array data first */
4111 		for (int index = 0; index < n_raw_array_indices; ++index)
4112 		{
4113 			memcpy(*unordered_arrays_data_ptr + 4 /* components */ * (n_raw_array_indices - 1 - index),
4114 				   *raw_arrays_data_ptr + 4 /* components */ * index, sizeof(float) * 4 /* components */);
4115 		}
4116 
4117 		/* Followed by index data */
4118 		for (int n = 0; n < n_raw_array_indices; ++n)
4119 		{
4120 			(*unordered_elements_data_ptr)[n] = (unsigned char)(n_raw_array_indices - 1 - n);
4121 		}
4122 	} /* for (both cases) */
4123 }
4124 
4125 /** Destructor. */
~GeometryShaderRenderingTrianglesCase()4126 GeometryShaderRenderingTrianglesCase::~GeometryShaderRenderingTrianglesCase()
4127 {
4128 	if (m_raw_array_instanced_data != NULL)
4129 	{
4130 		delete[] m_raw_array_instanced_data;
4131 
4132 		m_raw_array_instanced_data = NULL;
4133 	}
4134 
4135 	if (m_raw_array_noninstanced_data != NULL)
4136 	{
4137 		delete[] m_raw_array_noninstanced_data;
4138 
4139 		m_raw_array_noninstanced_data = NULL;
4140 	}
4141 
4142 	if (m_unordered_array_instanced_data != NULL)
4143 	{
4144 		delete[] m_unordered_array_instanced_data;
4145 
4146 		m_unordered_array_instanced_data = NULL;
4147 	}
4148 
4149 	if (m_unordered_array_noninstanced_data != NULL)
4150 	{
4151 		delete[] m_unordered_array_noninstanced_data;
4152 
4153 		m_unordered_array_noninstanced_data = NULL;
4154 	}
4155 
4156 	if (m_unordered_elements_instanced_data != NULL)
4157 	{
4158 		delete[] m_unordered_elements_instanced_data;
4159 
4160 		m_unordered_elements_instanced_data = NULL;
4161 	}
4162 
4163 	if (m_unordered_elements_noninstanced_data != NULL)
4164 	{
4165 		delete[] m_unordered_elements_noninstanced_data;
4166 
4167 		m_unordered_elements_noninstanced_data = NULL;
4168 	}
4169 }
4170 
4171 /** Retrieves amount of instances that should be drawn with glDraw*Elements() calls.
4172  *
4173  *  @return As per description.
4174  **/
getAmountOfDrawInstances()4175 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfDrawInstances()
4176 {
4177 	return 8;
4178 }
4179 
4180 /** Retrieves amount of indices that should be used for rendering a single instance
4181  *  (glDraw*Elements() calls only)
4182  *
4183  *  @return As per description.
4184  */
getAmountOfElementsPerInstance()4185 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfElementsPerInstance()
4186 {
4187 	/* No difference between instanced and non-instanced case. */
4188 	return static_cast<unsigned int>(m_unordered_elements_instanced_data_size / sizeof(unsigned char));
4189 }
4190 
4191 /** Retrieves amount of vertices that should be used for rendering a single instance
4192  *  (glDrawArrays*() calls only)
4193  *
4194  *  @return As per description.
4195  **/
getAmountOfVerticesPerInstance()4196 unsigned int GeometryShaderRenderingTrianglesCase::getAmountOfVerticesPerInstance()
4197 {
4198 	unsigned int result = 0;
4199 
4200 	switch (m_drawcall_mode)
4201 	{
4202 	case GL_TRIANGLES:
4203 	{
4204 		result = 3 /* vertices making up a single triangle */ * 4 /* triangles */;
4205 
4206 		break;
4207 	}
4208 
4209 	case GL_TRIANGLES_ADJACENCY_EXT:
4210 	{
4211 		result = 3 /* vertices making up a single triangle */ * 4 /* triangles */ * 2 /* adjacency data */;
4212 
4213 		break;
4214 	}
4215 
4216 	case GL_TRIANGLE_FAN:
4217 	{
4218 		result = 6 /* vertices in total */;
4219 
4220 		break;
4221 	}
4222 
4223 	case GL_TRIANGLE_STRIP:
4224 	{
4225 		result = 7 /* vertices in total */;
4226 
4227 		break;
4228 	}
4229 
4230 	case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4231 	{
4232 		/* As per extension specification */
4233 		result = (5 /* triangles */ + 2) * 2;
4234 
4235 		break;
4236 	}
4237 
4238 	default:
4239 	{
4240 		TCU_FAIL("Unrecognized draw call mode");
4241 	}
4242 	} /* switch (m_drawcall_mode) */
4243 
4244 	return result;
4245 }
4246 
4247 /** Draw call mode that should be used glDraw*() calls.
4248  *
4249  *  @return As per description.
4250  **/
getDrawCallMode()4251 glw::GLenum GeometryShaderRenderingTrianglesCase::getDrawCallMode()
4252 {
4253 	return m_drawcall_mode;
4254 }
4255 
4256 /** Source code for a fragment shader that should be used for the test.
4257  *
4258  *  @return As per description.
4259  **/
getFragmentShaderCode()4260 std::string GeometryShaderRenderingTrianglesCase::getFragmentShaderCode()
4261 {
4262 	static std::string fs_code = "${VERSION}\n"
4263 								 "\n"
4264 								 "precision highp float;\n"
4265 								 "\n"
4266 								 "in  vec4 gs_fs_color;\n"
4267 								 "out vec4 result;\n"
4268 								 "\n"
4269 								 "void main()\n"
4270 								 "{\n"
4271 								 "    result = gs_fs_color;\n"
4272 								 "}\n";
4273 
4274 	return fs_code;
4275 }
4276 
4277 /** Source code for a geometry shader that should be used for the test.
4278  *
4279  *  @return As per description.
4280  **/
getGeometryShaderCode()4281 std::string GeometryShaderRenderingTrianglesCase::getGeometryShaderCode()
4282 {
4283 	static const char* gs_triangles_in_lines_out_preamble = "${VERSION}\n"
4284 															"\n"
4285 															"${GEOMETRY_SHADER_ENABLE}\n"
4286 															"\n"
4287 															"layout(triangles)                   in;\n"
4288 															"layout(line_strip, max_vertices=24) out;\n"
4289 															"\n"
4290 															"#define N_VERTICES (3)\n"
4291 															"#define N_VERTEX0  (0)\n"
4292 															"#define N_VERTEX1  (1)\n"
4293 															"#define N_VERTEX2  (2)\n"
4294 															"\n";
4295 
4296 	static const char* gs_triangles_adjacency_in_lines_out_preamble = "${VERSION}\n"
4297 																	  "\n"
4298 																	  "${GEOMETRY_SHADER_ENABLE}\n"
4299 																	  "\n"
4300 																	  "layout(triangles_adjacency)         in;\n"
4301 																	  "layout(line_strip, max_vertices=24) out;\n"
4302 																	  "\n"
4303 																	  "#define N_VERTICES (6)\n"
4304 																	  "#define N_VERTEX0  (0)\n"
4305 																	  "#define N_VERTEX1  (2)\n"
4306 																	  "#define N_VERTEX2  (4)\n"
4307 																	  "\n";
4308 
4309 	static const char* gs_lines_code =
4310 		"uniform ivec2 renderingTargetSize;\n"
4311 		"\n"
4312 		"in  vec4 vs_gs_color[N_VERTICES];\n"
4313 		"out vec4 gs_fs_color;\n"
4314 		"\n"
4315 		"void main()\n"
4316 		"{\n"
4317 		"    float dx = 2.0 / float(renderingTargetSize.x);\n"
4318 		"    float dy = 2.0 / float(renderingTargetSize.y);\n"
4319 		"\n"
4320 		"    vec2 min_xy = gl_in[N_VERTEX0].gl_Position.xy;\n"
4321 		"    vec2 max_xy = gl_in[N_VERTEX0].gl_Position.xy;\n"
4322 		"\n"
4323 		"    min_xy[0] = min(gl_in[N_VERTEX1].gl_Position.x, min_xy[0]);\n"
4324 		"    min_xy[0] = min(gl_in[N_VERTEX2].gl_Position.x, min_xy[0]);\n"
4325 		"    min_xy[1] = min(gl_in[N_VERTEX1].gl_Position.y, min_xy[1]);\n"
4326 		"    min_xy[1] = min(gl_in[N_VERTEX2].gl_Position.y, min_xy[1]);\n"
4327 		"\n"
4328 		"    max_xy[0] = max(gl_in[N_VERTEX1].gl_Position.x, max_xy[0]);\n"
4329 		"    max_xy[0] = max(gl_in[N_VERTEX2].gl_Position.x, max_xy[0]);\n"
4330 		"    max_xy[1] = max(gl_in[N_VERTEX1].gl_Position.y, max_xy[1]);\n"
4331 		"    max_xy[1] = max(gl_in[N_VERTEX2].gl_Position.y, max_xy[1]);\n"
4332 		"\n"
4333 		"    for (int n = 0; n < 3 /* segment \"sub\"-line */; ++n)\n"
4334 		"    {\n"
4335 		"        float hor_line_delta = 0.0;\n"
4336 		"        float ver_line_delta = 0.0;\n"
4337 		"\n"
4338 		"        switch(n)\n"
4339 		"        {\n"
4340 		"            case 0: hor_line_delta = -dx; ver_line_delta = -dy; break;\n"
4341 		"            case 1:                                             break;\n"
4342 		"            case 2: hor_line_delta =  dx; ver_line_delta =  dy; break;\n"
4343 		"        }\n"
4344 		"\n"
4345 		/* BL->TL */
4346 		"        gl_Position = vec4(min_xy[0] - hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n"
4347 		"        gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4348 		"        EmitVertex();\n"
4349 		"        gl_Position = vec4(min_xy[0] - hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n"
4350 		"        gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4351 		"        EmitVertex();\n"
4352 		"        EndPrimitive();\n"
4353 		/* TL->TR */
4354 		"        gl_Position = vec4(max_xy[0] + hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n"
4355 		"        gs_fs_color = vs_gs_color[N_VERTEX1];\n"
4356 		"        EmitVertex();\n"
4357 		"        gl_Position = vec4(min_xy[0] - hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n"
4358 		"        gs_fs_color = vs_gs_color[N_VERTEX1];\n"
4359 		"        EmitVertex();\n"
4360 		"        EndPrimitive();\n"
4361 		/* TR->BR */
4362 		"        gl_Position = vec4(max_xy[0] + hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n"
4363 		"        gs_fs_color = vs_gs_color[N_VERTEX2];\n"
4364 		"        EmitVertex();\n"
4365 		"        gl_Position = vec4(max_xy[0] + hor_line_delta, min_xy[1] - ver_line_delta, 0, 1);\n"
4366 		"        gs_fs_color = vs_gs_color[N_VERTEX2];\n"
4367 		"        EmitVertex();\n"
4368 		"        EndPrimitive();\n"
4369 		/* BR->BL */
4370 		"        gl_Position = vec4(min_xy[0] - hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n"
4371 		"        gs_fs_color = vec4(vs_gs_color[N_VERTEX0].r, vs_gs_color[N_VERTEX1].g, vs_gs_color[N_VERTEX2].b, "
4372 		"vs_gs_color[N_VERTEX0].a);\n"
4373 		"        EmitVertex();\n"
4374 		"        gl_Position = vec4(max_xy[0] + hor_line_delta, max_xy[1] + ver_line_delta, 0, 1);\n"
4375 		"        gs_fs_color = vec4(vs_gs_color[N_VERTEX0].r, vs_gs_color[N_VERTEX1].g, vs_gs_color[N_VERTEX2].b, "
4376 		"vs_gs_color[N_VERTEX0].a);\n"
4377 		"        EmitVertex();\n"
4378 		"        EndPrimitive();\n"
4379 		"    }\n"
4380 		"}\n";
4381 
4382 	static const char* gs_triangles_in_points_out_preamble = "${VERSION}\n"
4383 															 "\n"
4384 															 "${GEOMETRY_SHADER_ENABLE}\n"
4385 															 "\n"
4386 															 "layout(triangles)               in;\n"
4387 															 "layout(points, max_vertices=27) out;\n"
4388 															 "\n"
4389 															 "#define N_VERTICES (3)\n"
4390 															 "#define N_VERTEX0  (0)\n"
4391 															 "#define N_VERTEX1  (1)\n"
4392 															 "#define N_VERTEX2  (2)\n"
4393 															 "\n";
4394 
4395 	static const char* gs_triangles_adjacency_in_points_out_preamble = "${VERSION}\n"
4396 																	   "\n"
4397 																	   "${GEOMETRY_SHADER_ENABLE}\n"
4398 																	   "\n"
4399 																	   "layout(triangles_adjacency)     in;\n"
4400 																	   "layout(points, max_vertices=27) out;\n"
4401 																	   "\n"
4402 																	   "#define N_VERTICES (6)\n"
4403 																	   "#define N_VERTEX0  (0)\n"
4404 																	   "#define N_VERTEX1  (2)\n"
4405 																	   "#define N_VERTEX2  (4)\n"
4406 																	   "\n";
4407 
4408 	static const char* gs_points_code =
4409 		"uniform ivec2 renderingTargetSize;\n"
4410 		"\n"
4411 		"in  vec4 vs_gs_color[N_VERTICES];\n"
4412 		"out vec4 gs_fs_color;\n"
4413 		"\n"
4414 		"void main()\n"
4415 		"{\n"
4416 		"    float dx = 2.0 / float(renderingTargetSize.x);\n"
4417 		"    float dy = 2.0 / float(renderingTargetSize.y);\n"
4418 		"\n"
4419 		"    for (int n = 0; n < 3 /* vertices */; ++n)\n"
4420 		"    {\n"
4421 		"        int vertex_index = (n == 0) ? N_VERTEX0 : \n"
4422 		"                           (n == 1) ? N_VERTEX1 : \n"
4423 		"                                      N_VERTEX2;\n"
4424 		/* TL */
4425 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, -dy, 0, 0);\n"
4426 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4427 		"        EmitVertex();\n"
4428 		/* TM */
4429 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, -dy, 0, 0);\n"
4430 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4431 		"        EmitVertex();\n"
4432 		/* TR */
4433 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, -dy, 0, 0);\n"
4434 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4435 		"        EmitVertex();\n"
4436 		/* ML */
4437 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, 0, 0, 0);\n"
4438 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4439 		"        EmitVertex();\n"
4440 		/* MM */
4441 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, 0, 0, 0);\n"
4442 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4443 		"        EmitVertex();\n"
4444 		/* MR */
4445 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, 0, 0, 0);\n"
4446 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4447 		"        EmitVertex();\n"
4448 		/* BL */
4449 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(-dx, dy, 0, 0);\n"
4450 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4451 		"        EmitVertex();\n"
4452 		/* BM */
4453 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(0, dy, 0, 0);\n"
4454 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4455 		"        EmitVertex();\n"
4456 		/* BR */
4457 		"        gl_Position = vec4(gl_in[vertex_index].gl_Position.xyz, 1) + vec4(dx, dy, 0, 0);\n"
4458 		"        gs_fs_color = vs_gs_color[vertex_index];\n"
4459 		"        EmitVertex();\n"
4460 		"    }\n"
4461 		"}\n";
4462 
4463 	static const char* gs_triangles_in_triangles_out_preamble = "${VERSION}\n"
4464 																"\n"
4465 																"${GEOMETRY_SHADER_ENABLE}\n"
4466 																"\n"
4467 																"layout(triangles)                      in;\n"
4468 																"layout(triangle_strip, max_vertices=6) out;\n"
4469 																"\n"
4470 																"#define N_VERTICES (3)\n"
4471 																"#define N_VERTEX0  (0)\n"
4472 																"#define N_VERTEX1  (1)\n"
4473 																"#define N_VERTEX2  (2)\n"
4474 																"\n";
4475 
4476 	static const char* gs_triangles_adjacency_in_triangles_out_preamble =
4477 		"${VERSION}\n"
4478 		"\n"
4479 		"${GEOMETRY_SHADER_ENABLE}\n"
4480 		"\n"
4481 		"layout(triangles_adjacency)            in;\n"
4482 		"layout(triangle_strip, max_vertices=6) out;\n"
4483 		"\n"
4484 		"#define N_VERTICES (6)\n"
4485 		"#define N_VERTEX0  (0)\n"
4486 		"#define N_VERTEX1  (2)\n"
4487 		"#define N_VERTEX2  (4)\n"
4488 		"\n";
4489 
4490 	static const char* gs_triangles_code = "uniform ivec2 renderingTargetSize;\n"
4491 										   "\n"
4492 										   "in  vec4 vs_gs_color[N_VERTICES];\n"
4493 										   "out vec4 gs_fs_color;\n"
4494 										   "\n"
4495 										   "void main()\n"
4496 										   "{\n"
4497 										   "    float dx = 2.0 / float(renderingTargetSize.x);\n"
4498 										   "    float dy = 2.0 / float(renderingTargetSize.y);\n"
4499 										   "\n"
4500 										   "    vec4 v0 = gl_in[N_VERTEX0].gl_Position;\n"
4501 										   "    vec4 v1 = gl_in[N_VERTEX1].gl_Position;\n"
4502 										   "    vec4 v2 = gl_in[N_VERTEX2].gl_Position;\n"
4503 										   "    vec4 a  = v0;\n"
4504 										   "    vec4 b;\n"
4505 										   "    vec4 c;\n"
4506 										   "    vec4 d;\n"
4507 										   "\n"
4508 										   /* Sort incoming vertices:
4509 		 *
4510 		 * a) a - vertex in origin.
4511 		 * b) b - vertex located on the same height as a.
4512 		 * c) c - remaining vertex.
4513 		 */
4514 										   "    if (abs(v1.w) >= 1.0)\n"
4515 										   "    {\n"
4516 										   "        a = v1;\n"
4517 										   "    \n"
4518 										   "        if (abs(v0.x - a.x) < dx)\n"
4519 										   "        {\n"
4520 										   "            b = v0;\n"
4521 										   "            c = v2;\n"
4522 										   "        }\n"
4523 										   "        else\n"
4524 										   "        {\n"
4525 										   "            b = v2;\n"
4526 										   "            c = v0;\n"
4527 										   "        }\n"
4528 										   "    }\n"
4529 										   "    else\n"
4530 										   "    if (abs(v2.w) >= 1.0)\n"
4531 										   "    {\n"
4532 										   "        a = v2;\n"
4533 										   "    \n"
4534 										   "        if (abs(v0.x - a.x) < dx)\n"
4535 										   "        {\n"
4536 										   "            b = v0;\n"
4537 										   "            c = v1;\n"
4538 										   "        }\n"
4539 										   "        else\n"
4540 										   "        {\n"
4541 										   "            b = v1;\n"
4542 										   "            c = v0;\n"
4543 										   "        }\n"
4544 										   "    }\n"
4545 										   "    else\n"
4546 										   "    {\n"
4547 										   "        if (abs(v1.x - a.x) < dx)\n"
4548 										   "        {\n"
4549 										   "            b = v1;\n"
4550 										   "            c = v2;\n"
4551 										   "        }\n"
4552 										   "        else\n"
4553 										   "        {\n"
4554 										   "            b = v2;\n"
4555 										   "            c = v1;\n"
4556 										   "        }\n"
4557 										   "    }\n"
4558 										   "    \n"
4559 										   "    d = (b + c) * vec4(0.5);\n"
4560 										   /* Now given the following configuration: (orientation does not matter)
4561 		 *
4562 		 * B
4563 		 * |\
4564                                                 * | D
4565 		 * |  \
4566                                                 * A---C
4567 		 *
4568 		 * emit ABD and ACD triangles */
4569 
4570 										   /* First sub-triangle */
4571 										   "    gl_Position = vec4(a.xyz, 1);\n"
4572 										   "    gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4573 										   "    EmitVertex();\n"
4574 										   "\n"
4575 										   "    gl_Position = vec4(b.xyz, 1);\n"
4576 										   "    gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4577 										   "    EmitVertex();\n"
4578 										   "\n"
4579 										   "    gl_Position = vec4(d.xyz, 1);\n"
4580 										   "    gs_fs_color = vs_gs_color[N_VERTEX0];\n"
4581 										   "    EmitVertex();\n"
4582 										   "    EndPrimitive();\n"
4583 										   /* Second sub-triangle */
4584 										   "    gl_Position = vec4(a.xyz, 1);\n"
4585 										   "    gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n"
4586 										   "    EmitVertex();\n"
4587 										   "\n"
4588 										   "    gl_Position = vec4(c.xyz, 1);\n"
4589 										   "    gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n"
4590 										   "    EmitVertex();\n"
4591 										   "\n"
4592 										   "    gl_Position = vec4(d.xyz, 1);\n"
4593 										   "    gs_fs_color = vec4(2.0, 1.0, 1.0, 1.0) * vs_gs_color[N_VERTEX2];\n"
4594 										   "    EmitVertex();\n"
4595 										   "    EndPrimitive();\n"
4596 										   "}\n";
4597 
4598 	std::string result;
4599 
4600 	switch (m_output_type)
4601 	{
4602 	case SHADER_OUTPUT_TYPE_POINTS:
4603 	{
4604 		std::stringstream gs_triangles_code_stringstream;
4605 		std::string		  gs_triangles_code_string;
4606 		std::stringstream gs_triangles_adjacency_code_stringstream;
4607 		std::string		  gs_triangles_adjacency_code_string;
4608 
4609 		switch (m_drawcall_mode)
4610 		{
4611 		case GL_TRIANGLE_FAN:
4612 		case GL_TRIANGLE_STRIP:
4613 		case GL_TRIANGLES:
4614 		{
4615 			gs_triangles_code_stringstream << gs_triangles_in_points_out_preamble << gs_points_code;
4616 
4617 			gs_triangles_code_string = gs_triangles_code_stringstream.str();
4618 			result					 = gs_triangles_code_string;
4619 
4620 			break;
4621 		}
4622 
4623 		case GL_TRIANGLES_ADJACENCY_EXT:
4624 		case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4625 		{
4626 			gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_points_out_preamble << gs_points_code;
4627 
4628 			gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str();
4629 			result							   = gs_triangles_adjacency_code_string;
4630 
4631 			break;
4632 		}
4633 
4634 		default:
4635 		{
4636 			TCU_FAIL("Unrecognized draw call mode");
4637 		}
4638 		}
4639 
4640 		break;
4641 	}
4642 
4643 	case SHADER_OUTPUT_TYPE_LINE_STRIP:
4644 	{
4645 		std::stringstream gs_triangles_code_stringstream;
4646 		std::string		  gs_triangles_code_string;
4647 		std::stringstream gs_triangles_adjacency_code_stringstream;
4648 		std::string		  gs_triangles_adjacency_code_string;
4649 
4650 		switch (m_drawcall_mode)
4651 		{
4652 		case GL_TRIANGLE_FAN:
4653 		case GL_TRIANGLE_STRIP:
4654 		case GL_TRIANGLES:
4655 		{
4656 			gs_triangles_code_stringstream << gs_triangles_in_lines_out_preamble << gs_lines_code;
4657 
4658 			gs_triangles_code_string = gs_triangles_code_stringstream.str();
4659 			result					 = gs_triangles_code_string;
4660 
4661 			break;
4662 		}
4663 
4664 		case GL_TRIANGLES_ADJACENCY_EXT:
4665 		case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4666 		{
4667 			gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_lines_out_preamble << gs_lines_code;
4668 
4669 			gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str();
4670 			result							   = gs_triangles_adjacency_code_string;
4671 
4672 			break;
4673 		}
4674 
4675 		default:
4676 		{
4677 			TCU_FAIL("Unrecognized draw call mode");
4678 		}
4679 		}
4680 
4681 		break;
4682 	}
4683 
4684 	case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
4685 	{
4686 		std::stringstream gs_triangles_code_stringstream;
4687 		std::string		  gs_triangles_code_string;
4688 		std::stringstream gs_triangles_adjacency_code_stringstream;
4689 		std::string		  gs_triangles_adjacency_code_string;
4690 
4691 		switch (m_drawcall_mode)
4692 		{
4693 		case GL_TRIANGLE_FAN:
4694 		case GL_TRIANGLE_STRIP:
4695 		case GL_TRIANGLES:
4696 		{
4697 			gs_triangles_code_stringstream << gs_triangles_in_triangles_out_preamble << gs_triangles_code;
4698 
4699 			gs_triangles_code_string = gs_triangles_code_stringstream.str();
4700 			result					 = gs_triangles_code_string;
4701 
4702 			break;
4703 		} /* case GL_TRIANGLES: */
4704 
4705 		case GL_TRIANGLES_ADJACENCY_EXT:
4706 		case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
4707 		{
4708 			gs_triangles_adjacency_code_stringstream << gs_triangles_adjacency_in_triangles_out_preamble
4709 													 << gs_triangles_code;
4710 
4711 			gs_triangles_adjacency_code_string = gs_triangles_adjacency_code_stringstream.str();
4712 			result							   = gs_triangles_adjacency_code_string;
4713 
4714 			break;
4715 		}
4716 
4717 		default:
4718 		{
4719 			TCU_FAIL("Unrecognized draw call mode");
4720 		}
4721 		} /* switch (m_drawcall_mode) */
4722 
4723 		break;
4724 	} /* case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP: */
4725 
4726 	default:
4727 	{
4728 		TCU_FAIL("Unsupported shader output type");
4729 	}
4730 	} /* switch (drawcall_mode) */
4731 
4732 	return result;
4733 }
4734 
4735 /** Returns amount of bytes that should be allocated for a buffer object to hold
4736  *  vertex data to be used for glDrawArrays*() calls.
4737  *
4738  *  @param instanced True if the data is to be used in regard to instanced draw calls,
4739  *                   false otherwise.
4740  *
4741  *  @return As per description.
4742  **/
getRawArraysDataBufferSize(bool instanced)4743 glw::GLuint GeometryShaderRenderingTrianglesCase::getRawArraysDataBufferSize(bool instanced)
4744 {
4745 	return instanced ? m_raw_array_instanced_data_size : m_raw_array_noninstanced_data_size;
4746 }
4747 
4748 /** Returns vertex data for the test. Only to be used for glDrawArrays*() calls.
4749  *
4750  *  @param instanced True if the data is to be used in regard to instanced draw calls,
4751  *                   false otherwise.
4752  *
4753  *  @return As per description.
4754  **/
getRawArraysDataBuffer(bool instanced)4755 const void* GeometryShaderRenderingTrianglesCase::getRawArraysDataBuffer(bool instanced)
4756 {
4757 	return instanced ? m_raw_array_instanced_data : m_raw_array_noninstanced_data;
4758 }
4759 
4760 /** Retrieves resolution of off-screen rendering buffer that should be used for the test.
4761  *
4762  *  @param n_instances Amount of draw call instances this render target will be used for.
4763  *  @param out_width   Deref will be used to store rendertarget's width. Must not be NULL.
4764  *  @param out_height  Deref will be used to store rendertarget's height. Must not be NULL.
4765  **/
getRenderTargetSize(unsigned int n_instances,unsigned int * out_width,unsigned int * out_height)4766 void GeometryShaderRenderingTrianglesCase::getRenderTargetSize(unsigned int n_instances, unsigned int* out_width,
4767 															   unsigned int* out_height)
4768 {
4769 	switch (m_output_type)
4770 	{
4771 	case SHADER_OUTPUT_TYPE_LINE_STRIP:
4772 	case SHADER_OUTPUT_TYPE_POINTS:
4773 	case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
4774 	{
4775 		*out_width  = 29;				/* as per test spec */
4776 		*out_height = 29 * n_instances; /* as per test spec */
4777 
4778 		break;
4779 	}
4780 
4781 	default:
4782 	{
4783 		TCU_FAIL("Unsupported output type");
4784 	}
4785 	}
4786 }
4787 
4788 /** Returns amount of bytes that should be allocated for a buffer object to hold
4789  *  vertex data to be used for glDrawElements*() calls.
4790  *
4791  *  @param instanced true if the call is being made for an instanced draw call, false otherwise.
4792  *
4793  *  @return As per description.
4794  **/
getUnorderedArraysDataBufferSize(bool instanced)4795 glw::GLuint GeometryShaderRenderingTrianglesCase::getUnorderedArraysDataBufferSize(bool instanced)
4796 {
4797 	return (instanced) ? m_unordered_array_instanced_data_size : m_unordered_array_noninstanced_data_size;
4798 }
4799 
4800 /** Returns vertex data for the test. Only to be used for glDrawElements*() calls.
4801  *
4802  *  @param instanced true if the call is being made for an instanced draw call, false otherwise.
4803  *
4804  *  @return As per description.
4805  **/
getUnorderedArraysDataBuffer(bool instanced)4806 const void* GeometryShaderRenderingTrianglesCase::getUnorderedArraysDataBuffer(bool instanced)
4807 {
4808 	return instanced ? m_unordered_array_instanced_data : m_unordered_array_noninstanced_data;
4809 }
4810 
4811 /** Returns amount of bytes that should be allocated for a buffer object to hold
4812  *  index data to be used for glDrawElements*() calls.
4813  *
4814  *  @param instanced true if the call is being made for an instanced draw call, false otherwise.
4815  *
4816  *  @return As per description.
4817  **/
getUnorderedElementsDataBufferSize(bool instanced)4818 glw::GLuint GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataBufferSize(bool instanced)
4819 {
4820 	return instanced ? m_unordered_elements_instanced_data_size : m_unordered_elements_noninstanced_data_size;
4821 }
4822 
4823 /** Returns index data for the test. Only to be used for glDrawElements*() calls.
4824  *
4825  *  @param instanced true if the call is being made for an instanced draw call, false otherwise.
4826  *
4827  *  @return As per description.
4828  **/
getUnorderedElementsDataBuffer(bool instanced)4829 const void* GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataBuffer(bool instanced)
4830 {
4831 	return instanced ? m_unordered_elements_instanced_data : m_unordered_elements_noninstanced_data;
4832 }
4833 
4834 /** Returns type of the index, to be used for glDrawElements*() calls.
4835  *
4836  *  @return As per description.
4837  **/
getUnorderedElementsDataType()4838 glw::GLenum GeometryShaderRenderingTrianglesCase::getUnorderedElementsDataType()
4839 {
4840 	return GL_UNSIGNED_BYTE;
4841 }
4842 
4843 /** Retrieves maximum index value. To be used for glDrawRangeElements() test only.
4844  *
4845  *  @return As per description.
4846  **/
getUnorderedElementsMaxIndex()4847 glw::GLubyte GeometryShaderRenderingTrianglesCase::getUnorderedElementsMaxIndex()
4848 {
4849 	return m_unordered_elements_max_index;
4850 }
4851 
4852 /** Retrieves minimum index value. To be used for glDrawRangeElements() test only.
4853  *
4854  *  @return As per description.
4855  **/
getUnorderedElementsMinIndex()4856 glw::GLubyte GeometryShaderRenderingTrianglesCase::getUnorderedElementsMinIndex()
4857 {
4858 	return m_unordered_elements_min_index;
4859 }
4860 
4861 /** Retrieves vertex shader code to be used for the test.
4862  *
4863  *  @return As per description.
4864  **/
getVertexShaderCode()4865 std::string GeometryShaderRenderingTrianglesCase::getVertexShaderCode()
4866 {
4867 	static std::string vs_code =
4868 		"${VERSION}\n"
4869 		"\n"
4870 		"in  vec4 position;\n"
4871 		"out vec4 vs_gs_color;\n"
4872 		"\n"
4873 		"uniform bool  is_lines_output;\n"
4874 		"uniform bool  is_indexed_draw_call;\n"
4875 		"uniform bool  is_instanced_draw_call;\n"
4876 		"uniform bool  is_points_output;\n"
4877 		"uniform bool  is_triangle_fan_input;\n"
4878 		"uniform bool  is_triangle_strip_input;\n"
4879 		"uniform bool  is_triangle_strip_adjacency_input;\n"
4880 		"uniform bool  is_triangles_adjacency_input;\n"
4881 		"uniform bool  is_triangles_input;\n"
4882 		"uniform bool  is_triangles_output;\n"
4883 		"uniform ivec2 renderingTargetSize;\n"
4884 		"uniform ivec2 singleRenderingTargetSize;\n"
4885 		"\n"
4886 		"void main()\n"
4887 		"{\n"
4888 		"    gl_Position = position + vec4(float(gl_InstanceID) ) * vec4(0, float(singleRenderingTargetSize.y) / "
4889 		"float(renderingTargetSize.y), 0, 0) * vec4(2.0);\n"
4890 		"    vs_gs_color = vec4(1.0, 0.0, 0.0, 0.0);\n"
4891 		"\n"
4892 		/*********************************** LINES OUTPUT *******************************/
4893 		"    if (is_lines_output)\n"
4894 		"    {\n"
4895 		"        if (!is_indexed_draw_call)\n"
4896 		"        {\n"
4897 		/* Non-indiced draw calls: */
4898 		/*  GL_TRIANGLE_FAN draw call mode */
4899 		"            if (is_triangle_fan_input)\n"
4900 		"            {\n"
4901 		"                switch(gl_VertexID)\n"
4902 		"                {\n"
4903 		"                   case 0:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4904 		"                   case 1:\n"
4905 		"                   case 5:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4906 		"                   case 2:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4907 		"                   case 3:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4908 		"                   case 4:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4909 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
4910 		"                }\n" /* switch(gl_VertexID) */
4911 		"            }\n"	 /* if (is_triangle_fan_input) */
4912 		"            else\n"
4913 		/* GL_TRIANGLE_STRIP draw call mode */
4914 		"            if (is_triangle_strip_input)\n"
4915 		"            {\n"
4916 		"                switch(gl_VertexID)\n"
4917 		"                {\n"
4918 		"                   case 1:\n"
4919 		"                   case 6: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4920 		"                   case 0:\n"
4921 		"                   case 4:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4922 		"                   case 2:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4923 		"                   case 3:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4924 		"                   case 5:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4925 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
4926 		"                }\n" /* switch(gl_VertexID) */
4927 		"            }\n"	 /* if (is_triangle_strip_input) */
4928 		"            else\n"
4929 		/* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */
4930 		"            if (is_triangle_strip_adjacency_input)\n"
4931 		"            {\n"
4932 		"                switch(gl_VertexID)\n"
4933 		"                {\n"
4934 		"                   case 2:\n"
4935 		"                   case 12: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4936 		"                   case 0:\n"
4937 		"                   case 8:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4938 		"                   case 4:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4939 		"                   case 6:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4940 		"                   case 10: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4941 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
4942 		"                }\n" /* switch(gl_VertexID) */
4943 		"            }\n"	 /* if (is_triangle_strip_adjacency_input) */
4944 		"            else\n"
4945 		"            if (is_triangles_input)\n"
4946 		"            {\n"
4947 		/* GL_TRIANGLES draw call mode */
4948 		"                switch(gl_VertexID)\n"
4949 		"                {\n"
4950 		"                   case 0: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4951 		"                   case 1: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4952 		"                   case 2: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4953 		"                   case 3: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4954 		"                   case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4955 		"                   case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4956 		"                   case 6: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4957 		"                   case 7: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4958 		"                   case 8: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4959 		"                   case 9:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4960 		"                   case 10: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4961 		"                   case 11: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4962 		"                }\n" /* switch(gl_VertexID) */
4963 		"            }\n"	 /* if (is_triangles_input) */
4964 		"            else\n"
4965 		"            if (is_triangles_adjacency_input)\n"
4966 		"            {\n"
4967 		/* GL_TRIANGLES_ADJACENCY_EXT draw call mode */
4968 		"                vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
4969 		"\n"
4970 		"                switch(gl_VertexID)\n"
4971 		"                {\n"
4972 		/* TL triangle */
4973 		"                    case 0: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4974 		"                    case 2: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4975 		"                    case 4: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4976 		/* TR triangle */
4977 		"                    case 6: vs_gs_color  = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4978 		"                    case 8: vs_gs_color  = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
4979 		"                    case 10: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4980 		/* BR triangle */
4981 		"                    case 12: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4982 		"                    case 14: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
4983 		"                    case 16: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4984 		/* BL triangle */
4985 		"                    case 18: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
4986 		"                    case 20: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
4987 		"                    case 22: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
4988 		"                }\n" /* switch (gl_VertexID) */
4989 		"            }\n"	 /* if (is_triangles_adjacency_input) */
4990 		"        }\n"		  /* if (!is_indexed_draw_call) */
4991 		"        else\n"
4992 		"        {\n"
4993 		/* Indiced draw call: */
4994 		"            if (is_triangles_input)\n"
4995 		"            {\n"
4996 		/* GL_TRIANGLES draw call mode */
4997 		"                switch(gl_VertexID)\n"
4998 		"                {\n"
4999 		"                    case 11: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5000 		"                    case 10: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5001 		"                    case 9:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5002 		"                    case 8:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5003 		"                    case 7:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5004 		"                    case 6:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5005 		"                    case 5:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5006 		"                    case 4:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5007 		"                    case 3:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5008 		"                    case 2:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5009 		"                    case 1:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5010 		"                    case 0:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5011 		"                }\n" /* switch(gl_VertexID) */
5012 		"            }\n"	 /* if (is_triangles_input) */
5013 		"            else\n"
5014 		"            if (is_triangle_fan_input)\n"
5015 		"            {\n"
5016 		/* GL_TRIANGLE_FAN draw call mode */
5017 		"                switch(gl_VertexID)\n"
5018 		"                {\n"
5019 		"                   case 5:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5020 		"                   case 4:\n"
5021 		"                   case 0:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5022 		"                   case 3:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5023 		"                   case 2:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5024 		"                   case 1:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5025 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5026 		"                }\n" /* switch(gl_VertexID) */
5027 		"            }\n"	 /*( if (is_triangle_fan_input) */
5028 		"            else\n"
5029 		"            if (is_triangle_strip_input)\n"
5030 		"            {\n"
5031 		/* GL_TRIANGLE_STRIP draw call mode */
5032 		"                switch (gl_VertexID)\n"
5033 		"                {\n"
5034 		"                   case 5:\n"
5035 		"                   case 0: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5036 		"                   case 6:\n"
5037 		"                   case 2:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5038 		"                   case 4:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5039 		"                   case 3:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5040 		"                   case 1:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5041 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5042 		"                }\n" /* switch(gl_VertexID) */
5043 		"            }\n"	 /* if (is_triangle_strip_input) */
5044 		"            else\n"
5045 		"            if (is_triangle_strip_adjacency_input)\n"
5046 		"            {\n"
5047 		/* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */
5048 		"                switch(gl_VertexID)\n"
5049 		"                {\n"
5050 		"                   case 11:\n"
5051 		"                   case 1:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5052 		"                   case 13:\n"
5053 		"                   case 5:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5054 		"                   case 9:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5055 		"                   case 7:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5056 		"                   case 3:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5057 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5058 		"                }\n" /* switch(gl_VertexID) */
5059 		"            }\n"	 /* if (is_triangle_strip_adjacency_input) */
5060 		"            else\n"
5061 		"            if (is_triangles_adjacency_input)\n"
5062 		"            {\n"
5063 		/* GL_TRIANGLES_ADJACENCY_EXT draw call mode */
5064 		"                vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
5065 		"\n"
5066 		"                switch(gl_VertexID)\n"
5067 		"                {\n"
5068 		/* TL triangle */
5069 		"                    case 23: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5070 		"                    case 21: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5071 		"                    case 19: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5072 		/* TR triangle */
5073 		"                    case 17: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5074 		"                    case 15: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5075 		"                    case 13: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5076 		/* BR triangle */
5077 		"                    case 11: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5078 		"                    case 9:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5079 		"                    case 7:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5080 		/* BL triangle */
5081 		"                    case 5: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5082 		"                    case 3: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5083 		"                    case 1: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5084 		"                }\n" /* switch(gl_VertexID) */
5085 		"            }\n"	 /* if (is_triangles_adjacency_input) */
5086 		"        }\n"
5087 		"    }\n" /* if (is_lines_output) */
5088 		"    else\n"
5089 		/*********************************** POINTS OUTPUT *******************************/
5090 		"    if (is_points_output)\n"
5091 		"    {\n"
5092 		"        if (!is_indexed_draw_call)\n"
5093 		"        {\n"
5094 		/* Non-indiced draw calls */
5095 		"            if (is_triangles_adjacency_input)\n"
5096 		"            {\n"
5097 		/* GL_TRIANGLES_ADJACENCY_EXT draw call mode */
5098 		"                vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
5099 		"\n"
5100 		"                switch (gl_VertexID)\n"
5101 		"                {\n"
5102 		"                    case 0:\n"
5103 		"                    case 6:\n"
5104 		"                    case 12:\n"
5105 		"                    case 18: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5106 		"                    case 2:\n"
5107 		"                    case 22: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5108 		"                    case 4:\n"
5109 		"                    case 8: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5110 		"                    case 10:\n"
5111 		"                    case 14: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5112 		"                    case 16:\n"
5113 		"                    case 20: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5114 		"                }\n" /* switch (gl_VertexID) */
5115 		"            }\n"	 /* if (is_triangles_adjacency_input) */
5116 		"            else\n"
5117 		"            if (is_triangle_fan_input)\n"
5118 		"            {\n"
5119 		/* GL_TRIANGLE_FAN draw call mode */
5120 		"                switch(gl_VertexID)\n"
5121 		"                {\n"
5122 		"                   case 0:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5123 		"                   case 1:\n"
5124 		"                   case 5:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5125 		"                   case 2:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5126 		"                   case 3:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5127 		"                   case 4:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5128 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5129 		"                }\n" /* switch(gl_VertexID) */
5130 		"            }\n"	 /* if (is_triangle_fan_input) */
5131 		"            else\n"
5132 		"            if (is_triangle_strip_input)\n"
5133 		"            {\n"
5134 		/* GL_TRIANGLE_STRIP draw call mode */
5135 		"                switch (gl_VertexID)\n"
5136 		"                {\n"
5137 		"                   case 1:\n"
5138 		"                   case 4:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5139 		"                   case 0:\n"
5140 		"                   case 6:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5141 		"                   case 2:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5142 		"                   case 3:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5143 		"                   case 5:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5144 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5145 		"                }\n" /* switch(gl_VertexID) */
5146 		"            }\n"	 /* if (is_triangle_strip_input) */
5147 		"            else\n"
5148 		"            if (is_triangle_strip_adjacency_input)\n"
5149 		"            {\n"
5150 		/* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */
5151 		"                switch (gl_VertexID)\n"
5152 		"                {\n"
5153 		"                   case 2:\n"
5154 		"                   case 8:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5155 		"                   case 0:\n"
5156 		"                   case 12: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5157 		"                   case 4:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5158 		"                   case 6:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5159 		"                   case 10: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5160 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5161 		"                }\n" /* switch(gl_VertexID) */
5162 		"            }\n"	 /* if (is_triangle_strip_input) */
5163 		"            else\n"
5164 		"            if (is_triangles_input)\n"
5165 		"            {\n"
5166 		/* GL_TRIANGLES draw call mode */
5167 		"                switch (gl_VertexID)\n"
5168 		"                {\n"
5169 		/* A */
5170 		"                    case 0:\n"
5171 		"                    case 3:\n"
5172 		"                    case 6:\n"
5173 		"                    case 9: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5174 		/* B */
5175 		"                    case 1:\n"
5176 		"                    case 11: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5177 		/* C */
5178 		"                    case 2:\n"
5179 		"                    case 4: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5180 		/* D */
5181 		"                    case 5:\n"
5182 		"                    case 7: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5183 		/* E */
5184 		"                    case 8:\n"
5185 		"                    case 10: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5186 		"                }\n" /* switch (gl_VertexID) */
5187 		"            }\n"	 /* if (is_triangles_input) */
5188 		"        }\n"		  /* if (!is_indexed_draw_call) "*/
5189 		"        else\n"
5190 		"        {\n"
5191 		/* Indiced draw calls: */
5192 		"            if (is_triangle_fan_input)\n"
5193 		"            {\n"
5194 		/* GL_TRIANGLE_FAN input */
5195 		"                switch (gl_VertexID)\n"
5196 		"                {\n"
5197 		"                   case 5:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5198 		"                   case 4:\n"
5199 		"                   case 0:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5200 		"                   case 3:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5201 		"                   case 2:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5202 		"                   case 1:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5203 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5204 		"                }\n" /* switch(gl_VertexID) */
5205 		"            }\n"	 /* if (is_triangle_fan_input) */
5206 		"            else\n"
5207 		"            if (is_triangle_strip_input)\n"
5208 		"            {\n"
5209 		"                switch (gl_VertexID)\n"
5210 		"                {\n"
5211 		"                   case 5:\n"
5212 		"                   case 2:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5213 		"                   case 6:\n"
5214 		"                   case 0:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5215 		"                   case 4:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5216 		"                   case 3:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5217 		"                   case 1:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5218 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5219 		"                }\n" /* switch(gl_VertexID) */
5220 		"            }\n"	 /* if (is_triangle_strip_input) */
5221 		"            else\n"
5222 		"            if (is_triangle_strip_adjacency_input)\n"
5223 		"            {\n"
5224 		/* GL_TRIANGLE_STRIP_ADJACENCY_EXT draw call mode */
5225 		"                switch (gl_VertexID)\n"
5226 		"                {\n"
5227 		"                   case 11:\n"
5228 		"                   case 5:  vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5229 		"                   case 13:\n"
5230 		"                   case 1:  vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5231 		"                   case 9:  vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5232 		"                   case 7:  vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5233 		"                   case 3:  vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5234 		"                   default: vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0); break;\n"
5235 		"                }\n" /* switch(gl_VertexID) */
5236 		"            }\n"	 /* if (is_triangle_strip_adjacency_input) */
5237 		"            else\n"
5238 		"            if (is_triangles_adjacency_input)\n"
5239 		"            {\n"
5240 		"                vs_gs_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
5241 		/* GL_TRIANGLES_ADJACENCY_EXT input */
5242 		"                switch (gl_VertexID)\n"
5243 		"                {\n"
5244 		/* A */
5245 		"                    case 23:\n"
5246 		"                    case 17:\n"
5247 		"                    case 11:\n"
5248 		"                    case 5: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5249 		/* B */
5250 		"                    case 21:\n"
5251 		"                    case 1: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5252 		/* C */
5253 		"                    case 19:\n"
5254 		"                    case 15: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5255 		/* D */
5256 		"                    case 13:\n"
5257 		"                    case 9: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5258 		/* E */
5259 		"                    case 7:\n"
5260 		"                    case 3: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5261 		"                }\n" /* switch (gl_VertexID) */
5262 		"            }\n"	 /* if (is_triangles_adjacency_input) */
5263 		"            else\n"
5264 		"            if (is_triangles_input)\n"
5265 		"            {\n"
5266 		/* GL_TRIANGLES input */
5267 		"                switch (gl_VertexID)\n"
5268 		"                {\n"
5269 		"                    case 11:\n"
5270 		"                    case 8:\n"
5271 		"                    case 5:\n"
5272 		"                    case 2: vs_gs_color = vec4(0.4, 0.5, 0.6, 0.7); break;\n"
5273 		"                    case 10:\n"
5274 		"                    case 0: vs_gs_color = vec4(0.5, 0.6, 0.7, 0.8); break;\n"
5275 		"                    case 9:\n"
5276 		"                    case 7: vs_gs_color = vec4(0.1, 0.2, 0.3, 0.4); break;\n"
5277 		"                    case 6:\n"
5278 		"                    case 4: vs_gs_color = vec4(0.2, 0.3, 0.4, 0.5); break;\n"
5279 		"                    case 3:\n"
5280 		"                    case 1: vs_gs_color = vec4(0.3, 0.4, 0.5, 0.6); break;\n"
5281 		"                }\n" /* switch (gl_VertexID) */
5282 		"            }\n"	 /* if (is_triangles_input) */
5283 		"        }\n"
5284 		"    }\n" /* if (is_points_output) */
5285 		"    else\n"
5286 		/*********************************** TRIANGLES OUTPUT *******************************/
5287 		"    if (is_triangles_output)\n"
5288 		"    {\n"
5289 		"        int vertex_id = 0;\n"
5290 		"\n"
5291 		"        if (!is_indexed_draw_call && is_triangles_adjacency_input && (gl_VertexID % 2 == 0) )\n"
5292 		"        {\n"
5293 		"            vertex_id = gl_VertexID / 2 + 1;\n"
5294 		"        }\n"
5295 		"        else\n"
5296 		"        {\n"
5297 		"            vertex_id = gl_VertexID + 1;\n"
5298 		"        }\n"
5299 		"\n"
5300 		"        vs_gs_color = vec4(float(vertex_id) / 48.0, float(vertex_id % 3) / 2.0, float(vertex_id % 4) / 3.0, "
5301 		"float(vertex_id % 5) / 4.0);\n"
5302 		"    }\n"
5303 		"}\n";
5304 	std::string result;
5305 
5306 	switch (m_output_type)
5307 	{
5308 	case SHADER_OUTPUT_TYPE_LINE_STRIP:
5309 	case SHADER_OUTPUT_TYPE_POINTS:
5310 	case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
5311 	{
5312 		result = vs_code;
5313 
5314 		break;
5315 	}
5316 
5317 	default:
5318 	{
5319 		TCU_FAIL("Unrecognized output type");
5320 	}
5321 	} /* switch (m_output_type) */
5322 
5323 	return result;
5324 }
5325 
5326 /** Sets test-specific uniforms for a program object that is then used for the draw call.
5327  *
5328  *  @param drawcall_type Type of the draw call that is to follow right after this function is called.
5329  **/
setUniformsBeforeDrawCall(_draw_call_type drawcall_type)5330 void GeometryShaderRenderingTrianglesCase::setUniformsBeforeDrawCall(_draw_call_type drawcall_type)
5331 {
5332 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5333 
5334 	glw::GLint is_lines_output_uniform_location			= gl.getUniformLocation(m_po_id, "is_lines_output");
5335 	glw::GLint is_indexed_draw_call_uniform_location	= gl.getUniformLocation(m_po_id, "is_indexed_draw_call");
5336 	glw::GLint is_instanced_draw_call_uniform_location  = gl.getUniformLocation(m_po_id, "is_instanced_draw_call");
5337 	glw::GLint is_points_output_uniform_location		= gl.getUniformLocation(m_po_id, "is_points_output");
5338 	glw::GLint is_triangle_fan_input_uniform_location   = gl.getUniformLocation(m_po_id, "is_triangle_fan_input");
5339 	glw::GLint is_triangle_strip_input_uniform_location = gl.getUniformLocation(m_po_id, "is_triangle_strip_input");
5340 	glw::GLint is_triangle_strip_adjacency_input_uniform_location =
5341 		gl.getUniformLocation(m_po_id, "is_triangle_strip_adjacency_input");
5342 	glw::GLint is_triangles_adjacency_input_uniform_location =
5343 		gl.getUniformLocation(m_po_id, "is_triangles_adjacency_input");
5344 	glw::GLint is_triangles_input_uniform_location  = gl.getUniformLocation(m_po_id, "is_triangles_input");
5345 	glw::GLint is_triangles_output_uniform_location = gl.getUniformLocation(m_po_id, "is_triangles_output");
5346 
5347 	gl.uniform1i(is_lines_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_LINE_STRIP);
5348 	gl.uniform1i(is_points_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_POINTS);
5349 	gl.uniform1i(is_triangle_fan_input_uniform_location, m_drawcall_mode == GL_TRIANGLE_FAN);
5350 	gl.uniform1i(is_triangle_strip_input_uniform_location, m_drawcall_mode == GL_TRIANGLE_STRIP);
5351 	gl.uniform1i(is_triangles_adjacency_input_uniform_location, m_drawcall_mode == GL_TRIANGLES_ADJACENCY_EXT);
5352 	gl.uniform1i(is_triangle_strip_adjacency_input_uniform_location,
5353 				 m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT);
5354 	gl.uniform1i(is_triangles_input_uniform_location, m_drawcall_mode == GL_TRIANGLES);
5355 	gl.uniform1i(is_triangles_output_uniform_location, m_output_type == SHADER_OUTPUT_TYPE_TRIANGLE_STRIP);
5356 	gl.uniform1i(is_indexed_draw_call_uniform_location, (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
5357 														 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED ||
5358 														 drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS));
5359 	gl.uniform1i(is_instanced_draw_call_uniform_location,
5360 				 (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED) ||
5361 					 (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED));
5362 }
5363 
5364 /** Verifies that the rendered data is correct.
5365  *
5366  *  @param drawcall_type Type of the draw call that was used to render the geometry.
5367  *  @param instance_id   Instance ID to be verified. Use 0 for non-instanced draw calls.
5368  *  @param data          Contents of the rendertarget after the test has finished rendering.
5369  **/
verify(_draw_call_type drawcall_type,unsigned int instance_id,const unsigned char * data)5370 void GeometryShaderRenderingTrianglesCase::verify(_draw_call_type drawcall_type, unsigned int instance_id,
5371 												  const unsigned char* data)
5372 {
5373 	const float  epsilon		  = 1.0f / 256.0f;
5374 	float		 dx				  = 0.0f;
5375 	float		 dy				  = 0.0f;
5376 	unsigned int single_rt_height = 0;
5377 	unsigned int single_rt_width  = 0;
5378 
5379 	getRenderTargetSize(1, &single_rt_width, &single_rt_height);
5380 
5381 	dx = 2.0f / float(single_rt_width);
5382 	dy = 2.0f / float(single_rt_height);
5383 
5384 	switch (m_output_type)
5385 	{
5386 	case SHADER_OUTPUT_TYPE_LINE_STRIP:
5387 	{
5388 		/* Reference color data, taken directly from vertex shader. These are assigned
5389 		 * to subsequent vertex ids, starting from 0.
5390 		 */
5391 		const float ref_color_data[] = { /* TL triangle */
5392 										 0.1f, 0.2f, 0.3f, 0.4f, 0.2f, 0.3f, 0.4f, 0.5f, 0.3f, 0.4f, 0.5f, 0.6f,
5393 										 /* TR triangle */
5394 										 0.1f, 0.2f, 0.3f, 0.4f, 0.3f, 0.4f, 0.5f, 0.6f, 0.4f, 0.5f, 0.6f, 0.7f,
5395 										 /* BR triangle */
5396 										 0.1f, 0.2f, 0.3f, 0.4f, 0.4f, 0.5f, 0.6f, 0.7f, 0.5f, 0.6f, 0.7f, 0.8f,
5397 										 /* BL triangle */
5398 										 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.2f, 0.3f, 0.4f, 0.5f
5399 		};
5400 
5401 		/* Assuming single-instanced case, the test divides the screen-space into four adjacent quads.
5402 		 * Internal edges will overlap. Given their different coloring, we exclude them from verification.
5403 		 * This means we're only interested in checking the quad exteriors.
5404 		 *
5405 		 * GS takes a single triangle (ABC), calculates max & min XY of the BB and:
5406 		 * - uses (A.r, A.g, A.b, A.a) for left line segment   (bottom left->top-left)     (line segment index in code:0)
5407 		 * - uses (B.r, B.g, B.b, B.a) for top line segment    (top-left->top-right)       (line segment index in code:1)
5408 		 * - uses (C.r, C.g, C.b, C.a) for right line segment  (top-right->bottom-right)   (line segment index in code:2)
5409 		 * - uses (A.r, B.g, C.b, A.a) for bottom line segment (bottom-right->bottom-left) (line segment index in code:3)
5410 		 *
5411 		 * The test feeds input triangles arranged in the following order:
5412 		 * 1) Top-left corner;     (quarter index in code:0);
5413 		 * 2) Top-right corner;    (quarter index in code:1);
5414 		 * 3) Bottom-right corner; (quarter index in code:2);
5415 		 * 4) Bottom-left corner;  (quarter index in code:3);
5416 		 *
5417 		 * The test renders line segments of width 3 by rendering three lines of width 1 next to each other.
5418 		 *
5419 		 * Sample locations are precomputed - they are centers of line segments being considered.
5420 		 *
5421 		 * Expected color is computed on-the-fly in code, to ease investigation for driver developers,
5422 		 * in case this test fails on any ES (or GL) implementation.
5423 		 */
5424 		int   ref_line_segment_index = -1;
5425 		int   ref_quarter_index		 = -1;
5426 		float ref_sample_rgba[4]	 = { 0, 0, 0, 0 };
5427 		float ref_sample_xy_float[2] = { 0 };
5428 		int   ref_sample_xy_int[2]   = { 0 };
5429 		int   ref_triangle_index	 = -1;
5430 
5431 		for (int n_edge = 0; n_edge < 8 /* edges */; ++n_edge)
5432 		{
5433 			switch (n_edge)
5434 			{
5435 			case 0:
5436 			{
5437 				/* Top left half, left edge */
5438 				ref_line_segment_index = 0;
5439 				ref_quarter_index	  = 0;
5440 				ref_triangle_index	 = 0;
5441 
5442 				break;
5443 			}
5444 
5445 			case 1:
5446 			{
5447 				/* Top-left half, top edge. */
5448 				ref_line_segment_index = 1;
5449 				ref_quarter_index	  = 0;
5450 				ref_triangle_index	 = 0;
5451 
5452 				break;
5453 			}
5454 
5455 			case 2:
5456 			{
5457 				/* Top-right half, top edge. */
5458 				ref_line_segment_index = 1;
5459 				ref_quarter_index	  = 1;
5460 				ref_triangle_index	 = 1;
5461 
5462 				break;
5463 			}
5464 
5465 			case 3:
5466 			{
5467 				/* Top-right half, right edge. */
5468 				ref_line_segment_index = 2;
5469 				ref_quarter_index	  = 1;
5470 				ref_triangle_index	 = 1;
5471 
5472 				break;
5473 			}
5474 
5475 			case 4:
5476 			{
5477 				/* Bottom-right half, right edge. */
5478 				ref_line_segment_index = 2;
5479 				ref_quarter_index	  = 2;
5480 				ref_triangle_index	 = 2;
5481 
5482 				break;
5483 			}
5484 
5485 			case 5:
5486 			{
5487 				/* Bottom-right half, bottom edge. */
5488 				ref_line_segment_index = 3;
5489 				ref_quarter_index	  = 2;
5490 				ref_triangle_index	 = 2;
5491 
5492 				break;
5493 			}
5494 
5495 			case 6:
5496 			{
5497 				/* Bottom-left half, bottom edge. */
5498 				ref_line_segment_index = 3;
5499 				ref_quarter_index	  = 3;
5500 				ref_triangle_index	 = 3;
5501 
5502 				break;
5503 			}
5504 
5505 			case 7:
5506 			{
5507 				/* Bottom-left half, left edge. */
5508 				ref_line_segment_index = 0;
5509 				ref_quarter_index	  = 3;
5510 				ref_triangle_index	 = 3;
5511 
5512 				break;
5513 			}
5514 
5515 			default:
5516 			{
5517 				TCU_FAIL("Unrecognized edge index");
5518 			}
5519 			} /* switch (n_edge) */
5520 
5521 			/* Compute reference color.
5522 			 *
5523 			 * When drawing with GL_TRIANGLE_STRIP data or GL_TRIANGLE_STRIP_ADJACENCY_EXT, top-right triangle is drawn two times.
5524 			 * During second re-draw, a different combination of vertex colors is used.
5525 			 * Take this into account.
5526 			 */
5527 			switch (ref_line_segment_index)
5528 			{
5529 			case 0:
5530 			{
5531 				/* Left segment */
5532 				memcpy(ref_sample_rgba,
5533 					   ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5534 						   0 /* first vertex data */,
5535 					   sizeof(float) * 4 /* components */);
5536 
5537 				if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) &&
5538 					ref_triangle_index == 1 /* top-right triangle */)
5539 				{
5540 					/* First vertex */
5541 					ref_sample_rgba[0] = 0.3f;
5542 					ref_sample_rgba[1] = 0.4f;
5543 					ref_sample_rgba[2] = 0.5f;
5544 					ref_sample_rgba[3] = 0.6f;
5545 				}
5546 
5547 				break;
5548 			}
5549 
5550 			case 1:
5551 			{
5552 				/* Top segment */
5553 				memcpy(ref_sample_rgba,
5554 					   ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5555 						   4 /* second vertex data */,
5556 					   sizeof(float) * 4 /* components */);
5557 
5558 				if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) &&
5559 					ref_triangle_index == 1 /* top-right triangle */)
5560 				{
5561 					/* Second vertex */
5562 					ref_sample_rgba[0] = 0.4f;
5563 					ref_sample_rgba[1] = 0.5f;
5564 					ref_sample_rgba[2] = 0.6f;
5565 					ref_sample_rgba[3] = 0.7f;
5566 				}
5567 				break;
5568 			}
5569 
5570 			case 2:
5571 			{
5572 				/* Right segment */
5573 				memcpy(ref_sample_rgba,
5574 					   ref_color_data + ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5575 						   8 /* third vertex data */,
5576 					   sizeof(float) * 4 /* components */);
5577 
5578 				if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) &&
5579 					ref_triangle_index == 1 /* top-right triangle */)
5580 				{
5581 					/* Third vertex */
5582 					ref_sample_rgba[0] = 0.1f;
5583 					ref_sample_rgba[1] = 0.2f;
5584 					ref_sample_rgba[2] = 0.3f;
5585 					ref_sample_rgba[3] = 0.4f;
5586 				}
5587 
5588 				break;
5589 			}
5590 
5591 			case 3:
5592 			{
5593 				/* Bottom segment */
5594 				ref_sample_rgba[0] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5595 													0 /* 1st vertex, red */];
5596 				ref_sample_rgba[1] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5597 													5 /* 2nd vertex, green */];
5598 				ref_sample_rgba[2] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5599 													10 /* 3rd vertex, blue */];
5600 				ref_sample_rgba[3] = ref_color_data[ref_triangle_index * 4 /* components */ * 3 /* reference colors */ +
5601 													3 /* 1st vertex, alpha */];
5602 
5603 				if ((m_drawcall_mode == GL_TRIANGLE_STRIP || m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT) &&
5604 					ref_triangle_index == 1 /* top-right triangle */)
5605 				{
5606 					/* Combination of components of three vertices */
5607 					ref_sample_rgba[0] = 0.3f;
5608 					ref_sample_rgba[1] = 0.5f;
5609 					ref_sample_rgba[2] = 0.3f;
5610 					ref_sample_rgba[3] = 0.6f;
5611 				}
5612 
5613 				break;
5614 			}
5615 
5616 			default:
5617 			{
5618 				TCU_FAIL("Unrecognized line segment index");
5619 			}
5620 			}
5621 
5622 			/* Retrieve quad coordinates */
5623 			float quad_x1y1x2y2[4] = { 0 };
5624 
5625 			switch (ref_quarter_index)
5626 			{
5627 			case 0:
5628 			{
5629 				/* Top-left quarter */
5630 				quad_x1y1x2y2[0] = 0.0f;
5631 				quad_x1y1x2y2[1] = 0.0f;
5632 				quad_x1y1x2y2[2] = 0.5f;
5633 				quad_x1y1x2y2[3] = 0.5f;
5634 
5635 				break;
5636 			}
5637 
5638 			case 1:
5639 			{
5640 				/* Top-right quarter */
5641 				quad_x1y1x2y2[0] = 0.5f;
5642 				quad_x1y1x2y2[1] = 0.0f;
5643 				quad_x1y1x2y2[2] = 1.0f;
5644 				quad_x1y1x2y2[3] = 0.5f;
5645 
5646 				break;
5647 			}
5648 
5649 			case 2:
5650 			{
5651 				/* Bottom-right quarter */
5652 				quad_x1y1x2y2[0] = 0.5f;
5653 				quad_x1y1x2y2[1] = 0.5f;
5654 				quad_x1y1x2y2[2] = 1.0f;
5655 				quad_x1y1x2y2[3] = 1.0f;
5656 
5657 				break;
5658 			}
5659 
5660 			case 3:
5661 			{
5662 				/* Bottom-left quarter */
5663 				quad_x1y1x2y2[0] = 0.0f;
5664 				quad_x1y1x2y2[1] = 0.5f;
5665 				quad_x1y1x2y2[2] = 0.5f;
5666 				quad_x1y1x2y2[3] = 1.0f;
5667 
5668 				break;
5669 			}
5670 
5671 			default:
5672 			{
5673 				TCU_FAIL("Unrecognized quarter index");
5674 			}
5675 			} /* switch (ref_quarter_index) */
5676 
5677 			/* Reduce quad coordinates to line segment coordinates */
5678 			switch (ref_line_segment_index)
5679 			{
5680 			case 0:
5681 			{
5682 				/* Left segment */
5683 				quad_x1y1x2y2[2] = quad_x1y1x2y2[0];
5684 
5685 				break;
5686 			}
5687 
5688 			case 1:
5689 			{
5690 				/* Top segment */
5691 				quad_x1y1x2y2[3] = quad_x1y1x2y2[1];
5692 
5693 				break;
5694 			}
5695 
5696 			case 2:
5697 			{
5698 				/* Right segment */
5699 				quad_x1y1x2y2[0] = quad_x1y1x2y2[2];
5700 
5701 				break;
5702 			}
5703 
5704 			case 3:
5705 			{
5706 				/* Bottom segment */
5707 				quad_x1y1x2y2[1] = quad_x1y1x2y2[3];
5708 
5709 				break;
5710 			}
5711 
5712 			default:
5713 			{
5714 				TCU_FAIL("Unrecognized line segment index");
5715 			}
5716 			}
5717 
5718 			/* Compute sample location. Move one pixel ahead in direction of the bottom-right corner to make
5719 			 * sure we sample from the center of the line segment.
5720 			 **/
5721 			ref_sample_xy_float[0] = quad_x1y1x2y2[0] + (quad_x1y1x2y2[2] - quad_x1y1x2y2[0]) * 0.5f;
5722 			ref_sample_xy_float[1] = quad_x1y1x2y2[1] + (quad_x1y1x2y2[3] - quad_x1y1x2y2[1]) * 0.5f;
5723 
5724 			ref_sample_xy_int[0] = int(ref_sample_xy_float[0] * float(single_rt_width - 1));
5725 			ref_sample_xy_int[1] = int(ref_sample_xy_float[1] * float(single_rt_height - 1));
5726 
5727 			/* If this is n-th instance, offset sample locations so that they point to rendering results specific
5728 			 * to instance of our concern */
5729 			ref_sample_xy_int[1] += instance_id * single_rt_height;
5730 
5731 			/* Compare the rendered data with reference data */
5732 			const int			 pixel_size = 4 /* components */;
5733 			const int			 row_width  = single_rt_width * pixel_size;
5734 			const unsigned char* rendered_data_ptr =
5735 				data + row_width * ref_sample_xy_int[1] + ref_sample_xy_int[0] * pixel_size;
5736 			const float rendered_data[4] = { float(rendered_data_ptr[0]) / 255.0f, float(rendered_data_ptr[1]) / 255.0f,
5737 											 float(rendered_data_ptr[2]) / 255.0f,
5738 											 float(rendered_data_ptr[3]) / 255.0f };
5739 
5740 			if (de::abs(rendered_data[0] - ref_sample_rgba[0]) > epsilon ||
5741 				de::abs(rendered_data[1] - ref_sample_rgba[1]) > epsilon ||
5742 				de::abs(rendered_data[2] - ref_sample_rgba[2]) > epsilon ||
5743 				de::abs(rendered_data[3] - ref_sample_rgba[3]) > epsilon)
5744 			{
5745 				m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << ref_sample_xy_int[0] << ", "
5746 								   << ref_sample_xy_int[1] << ") "
5747 								   << "equal (" << rendered_data[0] << ", " << rendered_data[1] << ", "
5748 								   << rendered_data[2] << ", " << rendered_data[3] << ") "
5749 								   << "exceeds allowed epsilon when compared to reference data equal ("
5750 								   << ref_sample_rgba[0] << ", " << ref_sample_rgba[1] << ", " << ref_sample_rgba[2]
5751 								   << ", " << ref_sample_rgba[3] << ")." << tcu::TestLog::EndMessage;
5752 
5753 				TCU_FAIL("Data comparison failed");
5754 			} /* if (data comparison failed) */
5755 		}	 /* for (all edges) */
5756 
5757 		/* All done */
5758 		break;
5759 	}
5760 
5761 	case SHADER_OUTPUT_TYPE_POINTS:
5762 	{
5763 		/* In this case, the test should have rendered 6 large points.
5764 		 * Verification checks if centers of these blobs carry valid values.
5765 		 */
5766 		const float ref_data[] = {
5767 			/* Position (<-1, 1> x <-1, 1>) */
5768 			0.0f,		-1.0f + float(instance_id) * 2.0f + dy, /* top */
5769 			0.1f,		0.2f,
5770 			0.3f,		0.4f, /* rgba */
5771 
5772 			0.0f,		0.0f + float(instance_id) * 2.0f, /* middle */
5773 			0.4f,		0.5f,
5774 			0.6f,		0.7f, /* rgba */
5775 
5776 			-1.0f + dx, 0.0f + float(instance_id) * 2.0f, /* left */
5777 			0.5f,		0.6f,
5778 			0.7f,		0.8f, /* rgba */
5779 
5780 			1.0f - dx,  0.0f + float(instance_id) * 2.0f, /* right */
5781 			0.2f,		0.3f,
5782 			0.4f,		0.5f, /* rgba */
5783 
5784 			0.0f,		1.0f + float(instance_id) * 2.0f - dy, /* bottom */
5785 			0.3f,		0.4f,
5786 			0.5f,		0.6f, /* rgba */
5787 		};
5788 		const unsigned int n_points = 5; /* total number of points to check */
5789 
5790 		for (unsigned int n_point = 0; n_point < n_points; ++n_point)
5791 		{
5792 			/* Retrieve data from the array */
5793 			tcu::Vec4 color_float = tcu::Vec4(ref_data[n_point * 6 + 2], ref_data[n_point * 6 + 3],
5794 											  ref_data[n_point * 6 + 4], ref_data[n_point * 6 + 5]);
5795 			tcu::Vec2 position_float = tcu::Vec2(ref_data[n_point * 6 + 0], ref_data[n_point * 6 + 1]);
5796 
5797 			/* Convert position data to texture space */
5798 			int position[] = { int((position_float[0] * 0.5f + 0.5f) * float(single_rt_width)),
5799 							   int((position_float[1] * 0.5f + 0.5f) * float(single_rt_height)) };
5800 
5801 			/* Compare the data */
5802 			const int			 pixel_size	= 4 /* components */;
5803 			const int			 row_width	 = single_rt_width * pixel_size;
5804 			const unsigned char* rendered_data = data + row_width * position[1] + position[0] * pixel_size;
5805 			float rendered_data_float[]		   = { float(rendered_data[0]) / 255.0f, float(rendered_data[1]) / 255.0f,
5806 											float(rendered_data[2]) / 255.0f, float(rendered_data[3]) / 255.0f };
5807 
5808 			if (de::abs(rendered_data_float[0] - color_float[0]) > epsilon ||
5809 				de::abs(rendered_data_float[1] - color_float[1]) > epsilon ||
5810 				de::abs(rendered_data_float[2] - color_float[2]) > epsilon ||
5811 				de::abs(rendered_data_float[3] - color_float[3]) > epsilon)
5812 			{
5813 				m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << position[0] << ", "
5814 								   << position[1] << ") "
5815 								   << "equal (" << rendered_data_float[0] << ", " << rendered_data_float[1] << ", "
5816 								   << rendered_data_float[2] << ", " << rendered_data_float[3] << ") "
5817 								   << "exceeds allowed epsilon when compared to reference data equal ("
5818 								   << color_float[0] << ", " << color_float[1] << ", " << color_float[2] << ", "
5819 								   << color_float[3] << ")." << tcu::TestLog::EndMessage;
5820 
5821 				TCU_FAIL("Data comparison failed");
5822 			}
5823 		} /* for (all points) */
5824 
5825 		break;
5826 	}
5827 
5828 	case SHADER_OUTPUT_TYPE_TRIANGLE_STRIP:
5829 	{
5830 		/* The test feeds the rendering pipeline with 4 triangles (per instance), which should
5831 		 * be converted to 8 differently colored triangles at the geometry shader stage.
5832 		 */
5833 		for (unsigned int n_triangle = 0; n_triangle < 8 /* triangles */; ++n_triangle)
5834 		{
5835 			/* Retrieve base triangle-specific properties */
5836 			tcu::Vec2 base_triangle_v1;
5837 			tcu::Vec2 base_triangle_v2;
5838 			tcu::Vec2 base_triangle_v3;
5839 
5840 			switch (n_triangle / 2)
5841 			/* two sub-triangles per a triangle must be checked */
5842 			{
5843 			case 0:
5844 			{
5845 				/* Top-left triangle */
5846 				base_triangle_v1[0] = 0.5f;
5847 				base_triangle_v1[1] = 0.5f;
5848 				base_triangle_v2[0] = 0.0f;
5849 				base_triangle_v2[1] = 0.5f;
5850 				base_triangle_v3[0] = 0.5f;
5851 				base_triangle_v3[1] = 0.0f;
5852 
5853 				break;
5854 			}
5855 
5856 			case 1:
5857 			{
5858 				/* Top-right triangle */
5859 				base_triangle_v1[0] = 0.5f;
5860 				base_triangle_v1[1] = 0.5f;
5861 				base_triangle_v2[0] = 0.5f;
5862 				base_triangle_v2[1] = 0.0f;
5863 				base_triangle_v3[0] = 1.0f;
5864 				base_triangle_v3[1] = 0.5f;
5865 
5866 				break;
5867 			}
5868 
5869 			case 2:
5870 			{
5871 				/* Bottom-right triangle */
5872 				base_triangle_v1[0] = 0.5f;
5873 				base_triangle_v1[1] = 0.5f;
5874 				base_triangle_v2[0] = 1.0f;
5875 				base_triangle_v2[1] = 0.5f;
5876 				base_triangle_v3[0] = 0.5f;
5877 				base_triangle_v3[1] = 1.0f;
5878 
5879 				break;
5880 			}
5881 
5882 			case 3:
5883 			{
5884 				/* Bottom-left triangle */
5885 				base_triangle_v1[0] = 0.5f;
5886 				base_triangle_v1[1] = 0.5f;
5887 				base_triangle_v2[0] = 0.0f;
5888 				base_triangle_v2[1] = 0.5f;
5889 				base_triangle_v3[0] = 0.5f;
5890 				base_triangle_v3[1] = 1.0f;
5891 
5892 				break;
5893 			}
5894 			} /* switch (n_triangle) */
5895 
5896 			/* Compute coordinates of the iteration-specific triangle. This logic has been
5897 			 * ported directly from the geometry shader */
5898 			tcu::Vec4   expected_sample_color_rgba;
5899 			glw::GLuint expected_sample_color_vertex_id = 0;
5900 			tcu::Vec2   triangle_vertex1;
5901 			tcu::Vec2   triangle_vertex2;
5902 			tcu::Vec2   triangle_vertex3;
5903 			tcu::Vec2   a = base_triangle_v1;
5904 			tcu::Vec2   b;
5905 			tcu::Vec2   c;
5906 			tcu::Vec2   d;
5907 
5908 			if (base_triangle_v2.x() == 0.5f && base_triangle_v2.y() == 0.5f)
5909 			{
5910 				a = base_triangle_v2;
5911 
5912 				if (de::abs(base_triangle_v1.x() - a.x()) < dx * 0.5f)
5913 				{
5914 					b = base_triangle_v1;
5915 					c = base_triangle_v3;
5916 				}
5917 				else
5918 				{
5919 					b = base_triangle_v3;
5920 					c = base_triangle_v1;
5921 				}
5922 			}
5923 			else if (base_triangle_v3.x() == 0.5f && base_triangle_v3.y() == 0.5f)
5924 			{
5925 				a = base_triangle_v3;
5926 
5927 				if (de::abs(base_triangle_v1.x() - a.x()) < dx * 0.5f)
5928 				{
5929 					b = base_triangle_v1;
5930 					c = base_triangle_v2;
5931 				}
5932 				else
5933 				{
5934 					b = base_triangle_v2;
5935 					c = base_triangle_v1;
5936 				}
5937 			}
5938 			else
5939 			{
5940 				if (de::abs(base_triangle_v2.x() - a.x()) < dx * 0.5f)
5941 				{
5942 					b = base_triangle_v2;
5943 					c = base_triangle_v3;
5944 				}
5945 				else
5946 				{
5947 					b = base_triangle_v3;
5948 					c = base_triangle_v2;
5949 				}
5950 			}
5951 
5952 			d = (b + c) * tcu::Vec2(0.5f);
5953 
5954 			if (n_triangle % 2 == 0)
5955 			{
5956 				switch (m_drawcall_mode)
5957 				{
5958 				case GL_TRIANGLES:
5959 				case GL_TRIANGLES_ADJACENCY_EXT:
5960 				{
5961 					/* First sub-triangle */
5962 					expected_sample_color_vertex_id = 3 /* vertices per triangle */ * (n_triangle / 2) + 0;
5963 
5964 					break;
5965 				} /* GL_TRIANGLEs or GL_TRIANGLES_ADJACENCY_EXT cases */
5966 
5967 				case GL_TRIANGLE_FAN:
5968 				{
5969 					/* First sub-triangle in this case is always assigned vertex id of 0, as 0 stands for
5970 					 * the hub vertex */
5971 					expected_sample_color_vertex_id = 0;
5972 
5973 					break;
5974 				}
5975 
5976 				case GL_TRIANGLE_STRIP:
5977 				case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
5978 				{
5979 					bool is_adjacency_data_present = (m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT);
5980 
5981 					/* These vertex ids correspond to index of vertex A which changes between triangle
5982 					 * orientations, hence the repeated expected vertex ID for cases 4 and 6 */
5983 					switch (n_triangle)
5984 					{
5985 					/* Top-left triangle, first sub-triangle */
5986 					case 0:
5987 					{
5988 						expected_sample_color_vertex_id = 0;
5989 
5990 						break;
5991 					}
5992 
5993 					/* Top-right triangle, first sub-triangle */
5994 					case 2:
5995 					{
5996 						expected_sample_color_vertex_id = 2 * (is_adjacency_data_present ? 2 : 1);
5997 
5998 						break;
5999 					}
6000 
6001 					/* Bottom-right triangle, first sub-triangle */
6002 					case 4:
6003 					{
6004 						expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1);
6005 
6006 						break;
6007 					}
6008 
6009 					/* Bottom-left triangle, first sub-triangle */
6010 					case 6:
6011 					{
6012 						expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1);
6013 
6014 						break;
6015 					}
6016 
6017 					default:
6018 					{
6019 						TCU_FAIL("Unrecognized triangle index");
6020 					}
6021 					}
6022 
6023 					break;
6024 				}
6025 
6026 				default:
6027 				{
6028 					TCU_FAIL("Unrecognized draw call mode");
6029 				}
6030 				} /* switch (m_drawcall_mode) */
6031 
6032 				triangle_vertex1 = a;
6033 				triangle_vertex2 = b;
6034 				triangle_vertex3 = d;
6035 			} /* if (n_triangle % 2 == 0) */
6036 			else
6037 			{
6038 				/* Second sub-triangle */
6039 				switch (m_drawcall_mode)
6040 				{
6041 				case GL_TRIANGLES:
6042 				case GL_TRIANGLES_ADJACENCY_EXT:
6043 				{
6044 					expected_sample_color_vertex_id = 3 /* vertices per triangle */ * (n_triangle / 2) + 2;
6045 
6046 					break;
6047 				}
6048 
6049 				case GL_TRIANGLE_FAN:
6050 				{
6051 					expected_sample_color_vertex_id = 2 + n_triangle / 2;
6052 
6053 					break;
6054 				}
6055 
6056 				case GL_TRIANGLE_STRIP:
6057 				case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
6058 				{
6059 					bool is_adjacency_data_present = (m_drawcall_mode == GL_TRIANGLE_STRIP_ADJACENCY_EXT);
6060 
6061 					switch (n_triangle)
6062 					{
6063 					/* Top-left triangle, second sub-triangle */
6064 					case 1:
6065 					{
6066 						expected_sample_color_vertex_id = 2 * (is_adjacency_data_present ? 2 : 1);
6067 
6068 						break;
6069 					}
6070 
6071 					/* Top-right triangle, second sub-triangle */
6072 					case 3:
6073 					{
6074 						expected_sample_color_vertex_id = 4 * (is_adjacency_data_present ? 2 : 1);
6075 
6076 						break;
6077 					}
6078 
6079 					/* Bottom-right triangle, second sub-triangle */
6080 					case 5:
6081 					{
6082 						expected_sample_color_vertex_id = 5 * (is_adjacency_data_present ? 2 : 1);
6083 
6084 						break;
6085 					}
6086 
6087 					/* Bottom-left triangle, second sub-triangle */
6088 					case 7:
6089 					{
6090 						expected_sample_color_vertex_id = 6 * (is_adjacency_data_present ? 2 : 1);
6091 
6092 						break;
6093 					}
6094 
6095 					default:
6096 					{
6097 						TCU_FAIL("Unrecognized triangle index");
6098 					}
6099 					}
6100 
6101 					break;
6102 				}
6103 
6104 				default:
6105 				{
6106 					TCU_FAIL("UNrecognized draw call mode");
6107 				}
6108 				} /* switch (m_drawcall_mode) */
6109 
6110 				triangle_vertex1 = a;
6111 				triangle_vertex2 = c;
6112 				triangle_vertex3 = d;
6113 			}
6114 
6115 			if (drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS ||
6116 				drawcall_type == DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED ||
6117 				drawcall_type == DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS)
6118 			{
6119 				switch (m_drawcall_mode)
6120 				{
6121 				case GL_TRIANGLE_FAN:
6122 				case GL_TRIANGLE_STRIP:
6123 				case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
6124 				case GL_TRIANGLES:
6125 				{
6126 					expected_sample_color_vertex_id =
6127 						(getAmountOfVerticesPerInstance() - 1) - expected_sample_color_vertex_id;
6128 
6129 					break;
6130 				}
6131 
6132 				case GL_TRIANGLES_ADJACENCY_EXT:
6133 				{
6134 					/* In adjacency input, every even vertex is used for rendering. */
6135 					expected_sample_color_vertex_id =
6136 						(getAmountOfVerticesPerInstance() - 1) - expected_sample_color_vertex_id * 2;
6137 
6138 					break;
6139 				}
6140 
6141 				default:
6142 				{
6143 					TCU_FAIL("Unrecognized draw call mode");
6144 				}
6145 				}
6146 			}
6147 
6148 			/* Compute sample's reference color - logic as in vertex shader */
6149 			expected_sample_color_rgba[0] = float((expected_sample_color_vertex_id + 1)) / 48.0f;
6150 			expected_sample_color_rgba[1] = float((expected_sample_color_vertex_id + 1) % 3) / 2.0f;
6151 			expected_sample_color_rgba[2] = float((expected_sample_color_vertex_id + 1) % 4) / 3.0f;
6152 			expected_sample_color_rgba[3] = float((expected_sample_color_vertex_id + 1) % 5) / 4.0f;
6153 
6154 			if (n_triangle % 2 == 1)
6155 			{
6156 				expected_sample_color_rgba[0] *= 2.0f;
6157 			}
6158 
6159 			/* Compute sample location */
6160 			tcu::Vec2 sample_location;
6161 			int		  sample_location_int[2]; /* X & Y coordinates */
6162 
6163 			sample_location		   = (triangle_vertex1 + triangle_vertex2 + triangle_vertex3) / 3.0f;
6164 			sample_location_int[0] = int(sample_location[0] * static_cast<float>(single_rt_width - 1) + 0.5f);
6165 			sample_location_int[1] = int(sample_location[1] * static_cast<float>(single_rt_height - 1) + 0.5f) +
6166 									 instance_id * single_rt_height;
6167 
6168 			/* Retrieve rendered data */
6169 			const unsigned int   pixel_size = 4 /* components */;
6170 			const unsigned int   row_width  = single_rt_width * pixel_size;
6171 			const unsigned char* rendered_data =
6172 				data + row_width * sample_location_int[1] + sample_location_int[0] * pixel_size;
6173 
6174 			tcu::Vec4 rendered_data_rgba =
6175 				tcu::Vec4(float(rendered_data[0]) / 255.0f, float(rendered_data[1]) / 255.0f,
6176 						  float(rendered_data[2]) / 255.0f, float(rendered_data[3]) / 255.0f);
6177 
6178 			/* Compare rendered data with reference color information */
6179 			if (de::abs(rendered_data_rgba[0] - expected_sample_color_rgba[0]) > epsilon ||
6180 				de::abs(rendered_data_rgba[1] - expected_sample_color_rgba[1]) > epsilon ||
6181 				de::abs(rendered_data_rgba[2] - expected_sample_color_rgba[2]) > epsilon ||
6182 				de::abs(rendered_data_rgba[3] - expected_sample_color_rgba[3]) > epsilon)
6183 			{
6184 				m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data at (" << sample_location[0] << ", "
6185 								   << sample_location[1] << ") "
6186 								   << "equal (" << rendered_data_rgba[0] << ", " << rendered_data_rgba[1] << ", "
6187 								   << rendered_data_rgba[2] << ", " << rendered_data_rgba[3] << ") "
6188 								   << "exceeds allowed epsilon when compared to reference data equal ("
6189 								   << expected_sample_color_rgba[0] << ", " << expected_sample_color_rgba[1] << ", "
6190 								   << expected_sample_color_rgba[2] << ", " << expected_sample_color_rgba[3] << ")."
6191 								   << tcu::TestLog::EndMessage;
6192 
6193 				TCU_FAIL("Data comparison failed");
6194 			} /* if (data comparison failed) */
6195 		}	 /* for (all triangles) */
6196 		/* All done */
6197 		break;
6198 	}
6199 
6200 	default:
6201 	{
6202 		TCU_FAIL("Unrecognized output type");
6203 	}
6204 	}
6205 }
6206 
6207 } // namespace glcts
6208