Home | History | Annotate | Download | only in geometry_shader
      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  **/
     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  **/
     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. */
    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  **/
    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. */
    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  **/
    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. */
    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  */
    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  **/
   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. */
   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  **/
   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  */
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  */
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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. */
   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  **/
   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  */
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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. */
   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  **/
   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  */
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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