Home | History | Annotate | Download | only in tessellation_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 "esextcTessellationShaderTessellation.hpp"
     25 #include "gluContextInfo.hpp"
     26 #include "gluDefs.hpp"
     27 #include "glwEnums.hpp"
     28 #include "glwFunctions.hpp"
     29 #include "tcuTestLog.hpp"
     30 #include <cstdlib>
     31 
     32 namespace glcts
     33 {
     34 
     35 /** Vertex shader source code for max_in_out_attributes test. */
     36 const char* TessellationShaderTessellationMaxInOut::m_vs_code =
     37 	"${VERSION}\n"
     38 	"\n"
     39 	"${TESSELLATION_SHADER_REQUIRE}\n"
     40 	"${SHADER_IO_BLOCKS_ENABLE}\n"
     41 	"\n"
     42 	"precision highp float;\n"
     43 	"\n"
     44 	"layout(location = 0) in vec4 in_fv;\n"
     45 	"\n"
     46 	"out Vertex\n"
     47 	"{\n"
     48 	"    /* Note: we need to leave some space for gl_Position */\n"
     49 	"    vec4 value[(gl_MaxTessControlInputComponents) / 4 - 1];\n"
     50 	"} outVertex;\n"
     51 	"\n"
     52 	"void main()\n"
     53 	"{\n"
     54 	"    gl_Position = in_fv;\n"
     55 	"\n"
     56 	"    for (int i = 0 ; i < (gl_MaxTessControlInputComponents - "
     57 	"4) / 4 ; i++)\n" /* Max vec4 output attributes - gl_Position */
     58 	"    {\n"
     59 	"        outVertex.value[i] = vec4(float(4*i), float(4*i) + "
     60 	"1.0, float(4*i) + 2.0, float(4*i) + 3.0);\n"
     61 	"    }\n"
     62 	"}\n";
     63 
     64 /* Tessellation Control Shader code for max_in_out_attributes test */
     65 const char* TessellationShaderTessellationMaxInOut::m_tcs_code_1 =
     66 	"${VERSION}\n"
     67 	"\n"
     68 	"${TESSELLATION_SHADER_REQUIRE}\n"
     69 	"\n"
     70 	"precision highp float;\n"
     71 	"\n"
     72 	"layout(vertices = 2) out;\n"
     73 	"\n"
     74 	"in Vertex\n"
     75 	"{\n"
     76 	"    /* Note: we need to leave some space for gl_Position */\n"
     77 	"    vec4 value[(gl_MaxTessControlInputComponents - 4) / 4];\n"
     78 	"} inVertex[];\n"
     79 	"\n"
     80 	"out Vertex\n"
     81 	"{\n"
     82 	"    /* Note: we need to leave some space for gl_Position */\n"
     83 	"    vec4 value[(gl_MaxTessControlOutputComponents - 4) / 4];\n"
     84 	"} outVariables[];\n"
     85 	"\n"
     86 	"void main()\n"
     87 	"{\n"
     88 	"    gl_TessLevelInner[0] = 1.0;\n"
     89 	"    gl_TessLevelInner[1] = 1.0;\n"
     90 	"    gl_TessLevelOuter[0] = 1.0;\n"
     91 	"    gl_TessLevelOuter[1] = 1.0;\n"
     92 	"    gl_TessLevelOuter[2] = 1.0;\n"
     93 	"    gl_TessLevelOuter[3] = 1.0;\n"
     94 	"\n"
     95 	"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
     96 	"\n"
     97 	"    for (int j = 0; j < (gl_MaxTessControlOutputComponents - 4) / 4; j++)\n"
     98 	"    {\n"
     99 	"        outVariables[gl_InvocationID].value[j] = vec4(float(4*j), float(4*j) + 1.0, float(4*j) + 2.0, float(4*j) "
    100 	"+ 3.0);\n"
    101 	"\n"
    102 	"        for (int i = 0; i < (gl_MaxTessControlInputComponents-4)/4; i++)\n"
    103 	"        {\n"
    104 	"            outVariables[gl_InvocationID].value[j] += inVertex[gl_InvocationID].value[i];\n"
    105 	"        }\n"
    106 	"    }\n"
    107 	"}\n";
    108 
    109 /* Tessellation Control Shader code for max_in_out_attributes test */
    110 const char* TessellationShaderTessellationMaxInOut::m_tcs_code_2 =
    111 	"${VERSION}\n"
    112 	"\n"
    113 	"${TESSELLATION_SHADER_REQUIRE}\n"
    114 	"\n"
    115 	"precision highp float;\n"
    116 	"\n"
    117 	"layout(vertices = 2) out;\n"
    118 	"\n"
    119 	"patch out vec4 value[gl_MaxTessPatchComponents/4];\n"
    120 	"\n"
    121 	"void main()\n"
    122 	"{\n"
    123 	"    gl_TessLevelInner[0] = 1.0;\n"
    124 	"    gl_TessLevelInner[1] = 1.0;\n"
    125 	"    gl_TessLevelOuter[0] = 1.0;\n"
    126 	"    gl_TessLevelOuter[1] = 1.0;\n"
    127 	"    gl_TessLevelOuter[2] = 1.0;\n"
    128 	"    gl_TessLevelOuter[3] = 1.0;\n"
    129 	"\n"
    130 	"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
    131 	"\n"
    132 	"    for (int j = 0; j < gl_MaxTessPatchComponents / 4; j++)\n"
    133 	"    {\n"
    134 	"        value[j] = vec4(float(4*j), float(4*j) + 1.0, float(4*j) + 2.0, float(4*j) + 3.0);\n"
    135 	"    }\n"
    136 	"}\n";
    137 
    138 /* Tessellation Evaluation Shader code for max_in_out_attributes test */
    139 const char* TessellationShaderTessellationMaxInOut::m_tes_code_1 =
    140 	"${VERSION}\n"
    141 	"\n"
    142 	"${TESSELLATION_SHADER_REQUIRE}\n"
    143 	"\n"
    144 	"precision highp float;\n"
    145 	"\n"
    146 	"layout (isolines, point_mode) in;\n"
    147 	"\n"
    148 	"in Vertex\n"
    149 	"{\n"
    150 	"    vec4 value[(gl_MaxTessEvaluationInputComponents - 4) / 4];\n"
    151 	"} inVariables[];\n"
    152 	"\n"
    153 	"out Vertex\n"
    154 	"{\n"
    155 	"    vec4 value[(gl_MaxTessEvaluationOutputComponents - 4) / 4];\n"
    156 	"} outVariables;\n"
    157 	"\n"
    158 	"void main()\n"
    159 	"{\n"
    160 	"    gl_Position = gl_in[0].gl_Position;\n"
    161 	"\n"
    162 	"    for (int j = 0; j < (gl_MaxTessEvaluationOutputComponents - 4) / 4; j++)\n"
    163 	"    {\n"
    164 	"        outVariables.value[j] = vec4(float(4*j), float(4*j) + 1.0, float(4*j) + 2.0, float(4*j) + 3.0);\n"
    165 	"\n"
    166 	"        for (int i = 0 ; i < (gl_MaxTessEvaluationInputComponents - 4) / 4; i++)\n"
    167 	"        {\n"
    168 	"            outVariables.value[j] += inVariables[0].value[i];\n"
    169 	"        }\n"
    170 	"    }\n"
    171 	"}\n";
    172 
    173 /* Tessellation Evaluation Shader code for max_in_out_attributes test */
    174 const char* TessellationShaderTessellationMaxInOut::m_tes_code_2 =
    175 	"${VERSION}\n"
    176 	"\n"
    177 	"${TESSELLATION_SHADER_REQUIRE}\n"
    178 	"\n"
    179 	"precision highp float;\n"
    180 	"\n"
    181 	"layout (isolines, point_mode) in;\n"
    182 	"\n"
    183 	"patch in vec4 value[gl_MaxTessPatchComponents / 4];\n"
    184 	"\n"
    185 	"out vec4 out_value;\n"
    186 	"\n"
    187 	"void main()\n"
    188 	"{\n"
    189 	"    gl_Position    = gl_in[0].gl_Position;\n"
    190 	"    out_value = vec4(0.0);\n"
    191 	"\n"
    192 	"    for (int i = 0; i < gl_MaxTessPatchComponents / 4; i++)\n"
    193 	"    {\n"
    194 	"        out_value += value[i];\n"
    195 	"    }\n"
    196 	"}\n";
    197 
    198 /* Fragment Shader code for max_in_out_attributes test */
    199 const char* TessellationShaderTessellationMaxInOut::m_fs_code = "${VERSION}\n"
    200 																"\n"
    201 																"void main()\n"
    202 																"{\n"
    203 																"}\n";
    204 
    205 /** Constructor
    206  *
    207  * @param context Test context
    208  **/
    209 TessellationShaderTessellationTests::TessellationShaderTessellationTests(glcts::Context&	  context,
    210 																		 const ExtParameters& extParams)
    211 	: TestCaseGroupBase(context, extParams, "tessellation_shader_tessellation",
    212 						"Verifies general tessellation functionality")
    213 {
    214 	/* No implementation needed */
    215 }
    216 
    217 /**
    218  * Initializes test groups for geometry shader tests
    219  **/
    220 void TessellationShaderTessellationTests::init(void)
    221 {
    222 	addChild(
    223 		new glcts::TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID(m_context, m_extParams));
    224 	addChild(
    225 		new glcts::TessellationShaderTessellationgl_TessCoord(m_context, m_extParams, TESSELLATION_TEST_TYPE_TCS_TES));
    226 	addChild(new glcts::TessellationShaderTessellationgl_TessCoord(m_context, m_extParams, TESSELLATION_TEST_TYPE_TES));
    227 	addChild(new glcts::TessellationShaderTessellationInputPatchDiscard(m_context, m_extParams));
    228 	addChild(new glcts::TessellationShaderTessellationMaxInOut(m_context, m_extParams));
    229 }
    230 
    231 /** Constructor
    232  *
    233  * @param context Test context
    234  **/
    235 TessellationShaderTessellationInputPatchDiscard::TessellationShaderTessellationInputPatchDiscard(
    236 	Context& context, const ExtParameters& extParams)
    237 	: TestCaseBase(context, extParams, "input_patch_discard",
    238 				   "Verifies that patches, for which relevant outer tessellation levels have"
    239 				   " been defined to 0 or less, are discard by the tessellation primitive "
    240 				   " generator.")
    241 	, m_bo_id(0)
    242 	, m_fs_id(0)
    243 	, m_vs_id(0)
    244 	, m_vao_id(0)
    245 	, m_utils_ptr(0)
    246 {
    247 	/* Left blank on purpose */
    248 }
    249 
    250 /** Deinitializes ES objects created for the test. */
    251 void TessellationShaderTessellationInputPatchDiscard::deinit()
    252 {
    253 	/* Call base class' deinit() */
    254 	TestCaseBase::deinit();
    255 
    256 	if (!m_is_tessellation_shader_supported)
    257 	{
    258 		return;
    259 	}
    260 
    261 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    262 
    263 	/* Remove TF buffer object bindings */
    264 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
    265 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
    266 
    267 	/* Disable GL_RASTERIZER_DISCARD mode */
    268 	gl.disable(GL_RASTERIZER_DISCARD);
    269 
    270 	/* Restore GL_PATCH_VERTICES_EXT value */
    271 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
    272 
    273 	/* Unbind vertex array object */
    274 	gl.bindVertexArray(0);
    275 
    276 	/* Free all ES objects we allocated for the test */
    277 	if (m_bo_id != 0)
    278 	{
    279 		gl.deleteBuffers(1, &m_bo_id);
    280 
    281 		m_bo_id = 0;
    282 	}
    283 
    284 	if (m_fs_id != 0)
    285 	{
    286 		gl.deleteShader(m_fs_id);
    287 
    288 		m_fs_id = 0;
    289 	}
    290 
    291 	if (m_vs_id != 0)
    292 	{
    293 		gl.deleteShader(m_vs_id);
    294 
    295 		m_vs_id = 0;
    296 	}
    297 
    298 	if (m_vao_id != 0)
    299 	{
    300 		gl.deleteVertexArrays(1, &m_vao_id);
    301 
    302 		m_vao_id = 0;
    303 	}
    304 
    305 	/* Deinitialize all test descriptors */
    306 	for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it)
    307 	{
    308 		deinitRun(*it);
    309 	}
    310 	m_runs.clear();
    311 
    312 	/* Release tessellation shader test utilities instance */
    313 	if (m_utils_ptr != NULL)
    314 	{
    315 		delete m_utils_ptr;
    316 
    317 		m_utils_ptr = NULL;
    318 	}
    319 }
    320 
    321 /** Deinitialize all test pass-specific ES objects.
    322  *
    323  *  @param test Descriptor of a test pass to deinitialize.
    324  **/
    325 void TessellationShaderTessellationInputPatchDiscard::deinitRun(_run& run)
    326 {
    327 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    328 
    329 	if (run.po_id != 0)
    330 	{
    331 		gl.deleteProgram(run.po_id);
    332 
    333 		run.po_id = 0;
    334 	}
    335 
    336 	if (run.tc_id != 0)
    337 	{
    338 		gl.deleteShader(run.tc_id);
    339 
    340 		run.tc_id = 0;
    341 	}
    342 
    343 	if (run.te_id != 0)
    344 	{
    345 		gl.deleteShader(run.te_id);
    346 
    347 		run.te_id = 0;
    348 	}
    349 }
    350 
    351 /** Returns source code of a tessellation control shader for the test.
    352  *
    353  *  @return Requested string.
    354  **/
    355 std::string TessellationShaderTessellationInputPatchDiscard::getTCCode()
    356 {
    357 	std::string result;
    358 
    359 	result = "${VERSION}\n"
    360 			 "\n"
    361 			 "${TESSELLATION_SHADER_REQUIRE}\n"
    362 			 "\n"
    363 			 "layout(vertices = 2) out;\n"
    364 			 "\n"
    365 			 "out int tc_primitive_id[];\n"
    366 			 "\n"
    367 			 "void main()\n"
    368 			 "{\n"
    369 			 "    if ((gl_PrimitiveID % 4) == 0)\n"
    370 			 "    {\n"
    371 			 "        gl_TessLevelOuter[0] = 0.0;\n"
    372 			 "        gl_TessLevelOuter[1] = 0.0;\n"
    373 			 "        gl_TessLevelOuter[2] = 0.0;\n"
    374 			 "        gl_TessLevelOuter[3] = 0.0;\n"
    375 			 "    }\n"
    376 			 "    else\n"
    377 			 "    if ((gl_PrimitiveID % 4) == 2)\n"
    378 			 "    {\n"
    379 			 "        gl_TessLevelOuter[0] = -1.0;\n"
    380 			 "        gl_TessLevelOuter[1] = -1.0;\n"
    381 			 "        gl_TessLevelOuter[2] = -1.0;\n"
    382 			 "        gl_TessLevelOuter[3] = -1.0;\n"
    383 			 "    }\n"
    384 			 "    else\n"
    385 			 "    {\n"
    386 			 "        gl_TessLevelOuter[0] = 1.0;\n"
    387 			 "        gl_TessLevelOuter[1] = 1.0;\n"
    388 			 "        gl_TessLevelOuter[2] = 1.0;\n"
    389 			 "        gl_TessLevelOuter[3] = 1.0;\n"
    390 			 "    }\n"
    391 			 "\n"
    392 			 "    gl_TessLevelInner[0]                           = 1.0;\n"
    393 			 "    gl_TessLevelInner[1]                           = 1.0;\n"
    394 			 "    gl_out           [gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n"
    395 			 "    tc_primitive_id  [gl_InvocationID]             = gl_PrimitiveID;\n"
    396 			 "}\n";
    397 
    398 	return result;
    399 }
    400 
    401 /** Returns source code of a tessellation evaluation shader for the test,
    402  *  given user-specified vertex spacing and primitive modes.
    403  *
    404  *  Throws TestError exception if either of the arguments is invalid.
    405  *
    406  *  @param primitive_mode Primitive mode to use in the shader.
    407  *
    408  *  @return Requested string.
    409  **/
    410 std::string TessellationShaderTessellationInputPatchDiscard::getTECode(_tessellation_primitive_mode primitive_mode)
    411 {
    412 	std::string result = "${VERSION}\n"
    413 						 "\n"
    414 						 "${TESSELLATION_SHADER_REQUIRE}\n"
    415 						 "\n"
    416 						 "layout(PRIMITIVE_MODE) in;\n"
    417 						 "\n"
    418 						 "in  int   tc_primitive_id   [];\n"
    419 						 "out ivec2 te_tc_primitive_id;\n"
    420 						 "out int   te_primitive_id;\n"
    421 						 "\n"
    422 						 "void main()\n"
    423 						 "{\n"
    424 						 "    te_tc_primitive_id[0] = tc_primitive_id[0];\n"
    425 						 "    te_tc_primitive_id[1] = tc_primitive_id[1];\n"
    426 						 "    te_primitive_id       = gl_PrimitiveID;\n"
    427 						 "}\n";
    428 
    429 	/* Replace PRIMITIVE_MODE token with actual primitive_mode */
    430 	std::string primitive_mode_string	  = TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode);
    431 	const char* primitive_mode_token	   = "PRIMITIVE_MODE";
    432 	std::size_t primitive_mode_token_index = std::string::npos;
    433 
    434 	while ((primitive_mode_token_index = result.find(primitive_mode_token)) != std::string::npos)
    435 	{
    436 		result = result.replace(primitive_mode_token_index, strlen(primitive_mode_token), primitive_mode_string);
    437 
    438 		primitive_mode_token_index = result.find(primitive_mode_token);
    439 	}
    440 
    441 	/* Done */
    442 	return result;
    443 }
    444 
    445 /** Initializes ES objects necessary to run the test. */
    446 void TessellationShaderTessellationInputPatchDiscard::initTest()
    447 {
    448 	/* Skip if required extensions are not supported. */
    449 	if (!m_is_tessellation_shader_supported)
    450 	{
    451 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    452 	}
    453 
    454 	/* Generate all test-wide objects needed for test execution */
    455 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    456 	m_utils_ptr				 = new TessellationShaderUtils(gl, this);
    457 
    458 	gl.genVertexArrays(1, &m_vao_id);
    459 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
    460 
    461 	gl.bindVertexArray(m_vao_id);
    462 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
    463 
    464 	gl.genBuffers(1, &m_bo_id);
    465 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
    466 
    467 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
    468 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
    469 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
    470 
    471 	/* Configure fragment shader body */
    472 	const char* fs_body = "${VERSION}\n"
    473 						  "\n"
    474 						  "void main()\n"
    475 						  "{\n"
    476 						  "}\n";
    477 
    478 	shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body);
    479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader");
    480 
    481 	/* Configure vertex shader body */
    482 	const char* vs_body = "${VERSION}\n"
    483 						  "\n"
    484 						  "void main()\n"
    485 						  "{\n"
    486 						  "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
    487 						  "}\n";
    488 
    489 	shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body);
    490 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader");
    491 
    492 	/* Compile all the shaders */
    493 	const glw::GLuint  shaders[] = { m_fs_id, m_vs_id };
    494 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
    495 
    496 	m_utils_ptr->compileShaders(n_shaders, shaders, true);
    497 
    498 	/* Initialize all the runs. */
    499 	const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES,
    500 															 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
    501 															 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
    502 	const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
    503 
    504 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
    505 	{
    506 		/* Initialize the run */
    507 		_tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode];
    508 		_run						 run;
    509 
    510 		initRun(run, primitive_mode);
    511 
    512 		/* Store the run */
    513 		m_runs.push_back(run);
    514 	} /* for (all primitive modes) */
    515 
    516 	/* Set up buffer object bindings. Storage size will be determined on
    517 	 * a per-iteration basis.
    518 	 **/
    519 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
    520 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
    521 
    522 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
    523 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed");
    524 }
    525 
    526 /** Initializes all ES objects necessary to run a specific test pass.
    527  *
    528  *  Throws TestError exception if any of the arguments is found invalid.
    529  *
    530  *  @param run              Run descriptor to fill with IDs of initialized objects.
    531  *  @param primitive_mode   Primitive mode to use for the pass.
    532  **/
    533 void TessellationShaderTessellationInputPatchDiscard::initRun(_run& run, _tessellation_primitive_mode primitive_mode)
    534 {
    535 	run.primitive_mode = primitive_mode;
    536 
    537 	/* Set up a program object for the descriptor */
    538 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    539 
    540 	run.po_id = gl.createProgram();
    541 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
    542 
    543 	/* Set up tessellation shader objects. */
    544 	run.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
    545 	run.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
    546 
    547 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
    548 
    549 	/* Configure tessellation control shader body */
    550 	std::string tc_body			= getTCCode();
    551 	const char* tc_body_raw_ptr = tc_body.c_str();
    552 
    553 	shaderSourceSpecialized(run.tc_id, 1 /* count */, &tc_body_raw_ptr);
    554 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader");
    555 
    556 	/* Configure tessellation evaluation shader body */
    557 	std::string te_body			= getTECode(primitive_mode);
    558 	const char* te_body_raw_ptr = te_body.c_str();
    559 
    560 	shaderSourceSpecialized(run.te_id, 1 /* count */, &te_body_raw_ptr);
    561 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader");
    562 
    563 	/* Compile the tessellation evaluation shader */
    564 	glw::GLuint		   shaders[] = { run.tc_id, run.te_id };
    565 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
    566 
    567 	m_utils_ptr->compileShaders(n_shaders, shaders, true);
    568 
    569 	/* Attach all shader to the program object */
    570 	gl.attachShader(run.po_id, m_fs_id);
    571 	gl.attachShader(run.po_id, run.tc_id);
    572 	gl.attachShader(run.po_id, run.te_id);
    573 	gl.attachShader(run.po_id, m_vs_id);
    574 
    575 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
    576 
    577 	/* Set up XFB */
    578 	const char*		   varyings[] = { "te_tc_primitive_id", "te_primitive_id" };
    579 	const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]);
    580 
    581 	gl.transformFeedbackVaryings(run.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
    582 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed");
    583 
    584 	/* Link the program object */
    585 	glw::GLint link_status = GL_FALSE;
    586 
    587 	gl.linkProgram(run.po_id);
    588 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
    589 
    590 	gl.getProgramiv(run.po_id, GL_LINK_STATUS, &link_status);
    591 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
    592 
    593 	if (link_status != GL_TRUE)
    594 	{
    595 		TCU_FAIL("Program linking failed");
    596 	}
    597 }
    598 
    599 /** Executes the test.
    600  *
    601  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    602  *
    603  *  Note the function throws exception should an error occur!
    604  *
    605  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
    606  **/
    607 tcu::TestNode::IterateResult TessellationShaderTessellationInputPatchDiscard::iterate(void)
    608 {
    609 	/* Do not execute if required extensions are not supported. */
    610 	if (!m_is_tessellation_shader_supported)
    611 	{
    612 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    613 	}
    614 
    615 	/* Initialize ES test objects */
    616 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    617 
    618 	initTest();
    619 
    620 	/* We don't need rasterization for this test */
    621 	gl.enable(GL_RASTERIZER_DISCARD);
    622 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed.");
    623 
    624 	/* Configure amount of vertices per input patch */
    625 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
    626 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname");
    627 
    628 	/* Iterate through all tests configured */
    629 	for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++)
    630 	{
    631 		const _run& run = *run_iterator;
    632 
    633 		/* Set up XFB target BO storage size. Each input patch will generate:
    634 		 *
    635 		 * a) 1 ivec2 and 1 int IF it is an odd patch;
    636 		 * b) 0 bytes otherwise.
    637 		 *
    638 		 * This gives us a total of 2 * (sizeof(int)*2 + sizeof(int)) = 24 bytes per result coordinate,
    639 		 * assuming it does not get discarded along the way.
    640 		 *
    641 		 * Amount of vertices that TE processes is mode-dependent. Note that for 'quads' we use 6 instead
    642 		 * of 4 because the geometry will be broken down to triangles (1 quad = 2 triangles = 6 vertices)
    643 		 * later in the pipeline.
    644 		 */
    645 		const unsigned int n_total_primitives = 4;
    646 		const unsigned int n_vertices_per_patch =
    647 			((run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES) ?
    648 				 2 :
    649 				 (run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS) ? 6 : 3);
    650 		const unsigned int n_bytes_per_result_vertex = sizeof(int) + 2 * sizeof(int);
    651 		const unsigned int n_bytes_needed = (n_total_primitives / 2) * n_vertices_per_patch * n_bytes_per_result_vertex;
    652 
    653 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL, /* data */
    654 					  GL_STATIC_DRAW);
    655 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
    656 
    657 		/* Activate the program object */
    658 		gl.useProgram(run.po_id);
    659 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
    660 
    661 		/* Draw the test geometry. */
    662 		glw::GLenum tf_mode =
    663 			TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, false); /* is_point_mode_enabled */
    664 
    665 		gl.beginTransformFeedback(tf_mode);
    666 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed.");
    667 
    668 		gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* vertices per patch */ * n_total_primitives);
    669 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
    670 
    671 		gl.endTransformFeedback();
    672 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
    673 
    674 		/* Map the BO with result data into user space */
    675 		int* result_data = (int*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
    676 												   n_bytes_needed, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
    677 
    678 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
    679 
    680 		/* Verification is based on the following reasoning:
    681 		 *
    682 		 * a) Both TC and TE stages should operate on the same primitive IDs (no re-ordering
    683 		 *    of the IDs is allowed)
    684 		 * b) Under test-specific configuration, tessellator will output 2 line segments (4 coordinates).
    685 		 *    Two first two coordinates will be generated during tessellation of the second primitive,
    686 		 *    and the other two coordinates will be generated during tessellation of the fourth primitive
    687 		 *    (out of all four primitives that will enter the pipeline).
    688 		 * c) In case of quads, 6 first coordinates will be generated during tessellation of the second primitive,
    689 		 *    and the other six will be generated during tessellation of the fourth primitive.
    690 		 * d) Finally, tessellator will output 2 triangles (6 coordinates). The first three coordinates will
    691 		 *    be generated during tessellation of the second primitive, and the other two for the fourth
    692 		 *    primitive.
    693 		 * */
    694 		const int expected_primitive_ids[] = {
    695 			1, /* second primitive */
    696 			3  /* fourth primitive */
    697 		};
    698 		const unsigned int n_expected_primitive_ids =
    699 			sizeof(expected_primitive_ids) / sizeof(expected_primitive_ids[0]);
    700 		const unsigned int n_expected_repetitions =
    701 			(run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES) ?
    702 				2 :
    703 				(run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS) ? 6 : 3;
    704 		const int* traveller_ptr = result_data;
    705 
    706 		for (unsigned int n_primitive_id = 0; n_primitive_id < n_expected_primitive_ids; ++n_primitive_id)
    707 		{
    708 			int expected_primitive_id = expected_primitive_ids[n_primitive_id];
    709 
    710 			for (unsigned int n_repetition = 0; n_repetition < n_expected_repetitions; ++n_repetition)
    711 			{
    712 				for (unsigned int n_integer = 0; n_integer < 3 /* ivec2 + int */; ++n_integer)
    713 				{
    714 					if (*traveller_ptr != expected_primitive_id)
    715 					{
    716 						std::string primitive_mode_string =
    717 							TessellationShaderUtils::getESTokenForPrimitiveMode(run.primitive_mode);
    718 
    719 						m_testCtx.getLog() << tcu::TestLog::Message << "For primitive mode: " << primitive_mode_string
    720 										   << " invalid gl_PrimitiveID of value " << *traveller_ptr
    721 										   << " was found instead of expected " << expected_primitive_id
    722 										   << " at index:" << n_primitive_id * 3 /* ivec2 + int */ + n_integer
    723 										   << tcu::TestLog::EndMessage;
    724 
    725 						TCU_FAIL("Discard mechanism failed");
    726 					}
    727 
    728 					traveller_ptr++;
    729 				} /* for (all captured integers) */
    730 			}	 /* for (all repetitions) */
    731 		}		  /* for (all non-discarded primitive ids) */
    732 
    733 		/* Clear the buffer storage space before we unmap it */
    734 		memset(result_data, 0, n_bytes_needed);
    735 
    736 		/* Unmap the BO */
    737 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
    738 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
    739 	}
    740 
    741 	/* All done */
    742 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    743 	return STOP;
    744 }
    745 
    746 /** Constructor
    747  *
    748  * @param context Test context
    749  **/
    750 TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::
    751 	TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID(Context&			   context,
    752 																			  const ExtParameters& extParams)
    753 	: TestCaseBase(context, extParams, "gl_InvocationID_PatchVerticesIn_PrimitiveID",
    754 				   "Verifies that gl_InvocationID, gl_PatchVerticesIn and gl_PrimitiveID "
    755 				   "are assigned correct values in TC and TE stages (where appropriate), "
    756 				   "when invoked with arrayed and indiced draw calls. Also verifies that "
    757 				   "restarting primitive topology does not restart primitive ID counter.")
    758 	, m_bo_id(0)
    759 	, m_fs_id(0)
    760 	, m_vs_id(0)
    761 	, m_vao_id(0)
    762 	, m_utils_ptr(0)
    763 {
    764 	/* Left blank on purpose */
    765 }
    766 
    767 /** Deinitializes ES objects created for the test. */
    768 void TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::deinit()
    769 {
    770 	/* Call base class' deinit() */
    771 	TestCaseBase::deinit();
    772 
    773 	if (!m_is_tessellation_shader_supported)
    774 	{
    775 		return;
    776 	}
    777 
    778 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    779 
    780 	/* Disable modes this test has enabled */
    781 	gl.disable(GL_RASTERIZER_DISCARD);
    782 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_RASTERIZER_DISCARD) failed");
    783 
    784 	gl.disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
    785 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX) failed");
    786 
    787 	/* Remove TF buffer object bindings */
    788 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
    789 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
    790 
    791 	/* Restore GL_PATCH_VERTICES_EXT value */
    792 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
    793 
    794 	/* Unbind vertex array object */
    795 	gl.bindVertexArray(0);
    796 
    797 	/* Free all ES objects we allocated for the test */
    798 	if (m_bo_id != 0)
    799 	{
    800 		gl.deleteBuffers(1, &m_bo_id);
    801 
    802 		m_bo_id = 0;
    803 	}
    804 
    805 	if (m_fs_id != 0)
    806 	{
    807 		gl.deleteShader(m_fs_id);
    808 
    809 		m_fs_id = 0;
    810 	}
    811 
    812 	if (m_vs_id != 0)
    813 	{
    814 		gl.deleteShader(m_vs_id);
    815 
    816 		m_vs_id = 0;
    817 	}
    818 
    819 	if (m_vao_id != 0)
    820 	{
    821 		gl.deleteVertexArrays(1, &m_vao_id);
    822 
    823 		m_vao_id = 0;
    824 	}
    825 
    826 	/* Deinitialize all run descriptors */
    827 	for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it)
    828 	{
    829 		deinitRun(*it);
    830 	}
    831 	m_runs.clear();
    832 
    833 	/* Release tessellation shader test utilities instance */
    834 	if (m_utils_ptr != NULL)
    835 	{
    836 		delete m_utils_ptr;
    837 
    838 		m_utils_ptr = NULL;
    839 	}
    840 }
    841 
    842 /** Deinitialize all test pass-specific ES objects.
    843  *
    844  *  @param test Descriptor of a test pass to deinitialize.
    845  **/
    846 void TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::deinitRun(_run& run)
    847 {
    848 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    849 
    850 	if (run.bo_indices_id != 0)
    851 	{
    852 		gl.deleteBuffers(1, &run.bo_indices_id);
    853 
    854 		run.bo_indices_id = 0;
    855 	}
    856 
    857 	if (run.po_id != 0)
    858 	{
    859 		gl.deleteProgram(run.po_id);
    860 
    861 		run.po_id = 0;
    862 	}
    863 
    864 	if (run.tc_id != 0)
    865 	{
    866 		gl.deleteShader(run.tc_id);
    867 
    868 		run.tc_id = 0;
    869 	}
    870 
    871 	if (run.te_id != 0)
    872 	{
    873 		gl.deleteShader(run.te_id);
    874 
    875 		run.te_id = 0;
    876 	}
    877 }
    878 
    879 /** Returns source code of a tessellation control shader.
    880  *
    881  *  @param n_patch_vertices Amount of vertices per patch to
    882  *                          output in TC stage;
    883  *
    884  *  @return Requested string.
    885  **/
    886 std::string TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::getTCCode(
    887 	glw::GLuint n_patch_vertices)
    888 {
    889 	static const char* tc_body =
    890 		"${VERSION}\n"
    891 		"\n"
    892 		"${TESSELLATION_SHADER_REQUIRE}\n"
    893 		"\n"
    894 		"layout(vertices = N_PATCH_VERTICES) out;\n"
    895 		"\n"
    896 		"out TC_OUT\n"
    897 		"{\n"
    898 		"    int tc_invocation_id;\n"
    899 		"    int tc_patch_vertices_in;\n"
    900 		"    int tc_primitive_id;\n"
    901 		"} out_te[];\n"
    902 		"\n"
    903 		"void main()\n"
    904 		"{\n"
    905 		"    gl_out[gl_InvocationID].gl_Position          = gl_in[gl_InvocationID].gl_Position;\n"
    906 		"    out_te[gl_InvocationID].tc_invocation_id     = gl_InvocationID;\n"
    907 		"    out_te[gl_InvocationID].tc_patch_vertices_in = gl_PatchVerticesIn;\n"
    908 		"    out_te[gl_InvocationID].tc_primitive_id      = gl_PrimitiveID;\n"
    909 		"\n"
    910 		"    gl_TessLevelInner[0] = 4.0;\n"
    911 		"    gl_TessLevelInner[1] = 4.0;\n"
    912 		"    gl_TessLevelOuter[0] = 4.0;\n"
    913 		"    gl_TessLevelOuter[1] = 4.0;\n"
    914 		"    gl_TessLevelOuter[2] = 4.0;\n"
    915 		"    gl_TessLevelOuter[3] = 4.0;\n"
    916 		"}\n";
    917 
    918 	/* Construct a string out of user-provided integer value */
    919 	std::stringstream n_patch_vertices_sstream;
    920 	std::string		  n_patch_vertices_string;
    921 
    922 	n_patch_vertices_sstream << n_patch_vertices;
    923 	n_patch_vertices_string = n_patch_vertices_sstream.str();
    924 
    925 	/* Replace N_PATCH_VERTICES with user-provided value */
    926 	std::string		  result	  = tc_body;
    927 	const std::string token		  = "N_PATCH_VERTICES";
    928 	std::size_t		  token_index = std::string::npos;
    929 
    930 	while ((token_index = result.find(token)) != std::string::npos)
    931 	{
    932 		result = result.replace(token_index, token.length(), n_patch_vertices_string.c_str());
    933 
    934 		token_index = result.find(token);
    935 	}
    936 
    937 	return result;
    938 }
    939 
    940 /** Returns source code of a tessellation evaluation shader for the test,
    941  *  given user-specified primitive mode.
    942  *
    943  *  Throws TestError exception if either of the arguments is invalid.
    944  *
    945  *  @param primitive_mode Primitive mode to use in the shader.
    946  *
    947  *  @return Requested string.
    948  **/
    949 std::string TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::getTECode(
    950 	_tessellation_primitive_mode primitive_mode)
    951 {
    952 	static const char* te_body = "${VERSION}\n"
    953 								 "\n"
    954 								 "${TESSELLATION_SHADER_REQUIRE}\n"
    955 								 "\n"
    956 								 "layout(PRIMITIVE_MODE) in;\n"
    957 								 "\n"
    958 								 "in TC_OUT\n"
    959 								 "{\n"
    960 								 "    int tc_invocation_id;\n"
    961 								 "    int tc_patch_vertices_in;\n"
    962 								 "    int tc_primitive_id;\n"
    963 								 "} in_tc[];\n"
    964 								 "\n"
    965 								 "out int te_tc_invocation_id;\n"
    966 								 "out int te_tc_patch_vertices_in;\n"
    967 								 "out int te_tc_primitive_id;\n"
    968 								 "out int te_patch_vertices_in;\n"
    969 								 "out int te_primitive_id;\n"
    970 								 "\n"
    971 								 "void main()\n"
    972 								 "{\n"
    973 								 "    te_tc_invocation_id     = in_tc[gl_PatchVerticesIn-1].tc_invocation_id;\n"
    974 								 "    te_tc_patch_vertices_in = in_tc[gl_PatchVerticesIn-1].tc_patch_vertices_in;\n"
    975 								 "    te_tc_primitive_id      = in_tc[gl_PatchVerticesIn-1].tc_primitive_id;\n"
    976 								 "    te_patch_vertices_in    = gl_PatchVerticesIn;\n"
    977 								 "    te_primitive_id         = gl_PrimitiveID;\n"
    978 								 "}";
    979 
    980 	/* Replace PRIMITIVE_MODE with user-provided value */
    981 	std::string		  primitive_mode_string = TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode);
    982 	std::string		  result				= te_body;
    983 	const std::string token					= "PRIMITIVE_MODE";
    984 	std::size_t		  token_index			= std::string::npos;
    985 
    986 	while ((token_index = result.find(token)) != std::string::npos)
    987 	{
    988 		result = result.replace(token_index, token.length(), primitive_mode_string.c_str());
    989 
    990 		token_index = result.find(token);
    991 	}
    992 
    993 	return result;
    994 }
    995 
    996 /** Initializes ES objects necessary to run the test. */
    997 void TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::initTest()
    998 {
    999 	/* Skip if required extensions are not supported. */
   1000 	if (!m_is_tessellation_shader_supported)
   1001 	{
   1002 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   1003 	}
   1004 
   1005 	/* Set up Utils instance */
   1006 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1007 
   1008 	m_utils_ptr = new TessellationShaderUtils(gl, this);
   1009 
   1010 	/* Initialize vertex array object */
   1011 	gl.genVertexArrays(1, &m_vao_id);
   1012 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
   1013 
   1014 	gl.bindVertexArray(m_vao_id);
   1015 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
   1016 
   1017 	/* Generate all test-wide objects needed for test execution */
   1018 	gl.genBuffers(1, &m_bo_id);
   1019 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
   1020 
   1021 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   1022 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   1023 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
   1024 
   1025 	/* Configure fragment shader body */
   1026 	const char* fs_body = "${VERSION}\n"
   1027 						  "\n"
   1028 						  "void main()\n"
   1029 						  "{\n"
   1030 						  "}\n";
   1031 
   1032 	shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body);
   1033 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader");
   1034 
   1035 	/* Configure vertex shader body */
   1036 	const char* vs_body = "${VERSION}\n"
   1037 						  "\n"
   1038 						  "in vec4 vertex_data;\n"
   1039 						  "\n"
   1040 						  "void main()\n"
   1041 						  "{\n"
   1042 						  "    gl_Position = vertex_data;\n"
   1043 						  "}\n";
   1044 
   1045 	shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body);
   1046 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader");
   1047 
   1048 	/* Compile all the shaders */
   1049 	const glw::GLuint  shaders[] = { m_fs_id, m_vs_id };
   1050 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
   1051 
   1052 	m_utils_ptr->compileShaders(n_shaders, shaders, true /* should_succeed */);
   1053 
   1054 	/* Retrieve GL_MAX_PATCH_VERTICES_EXT value before we continue */
   1055 	glw::GLint gl_max_patch_vertices_value = 0;
   1056 
   1057 	gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &gl_max_patch_vertices_value);
   1058 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_PATCH_VERTICES_EXT pname");
   1059 
   1060 	/* Initialize all test passes */
   1061 	const unsigned int drawcall_count_multipliers[] = { 3, 6 };
   1062 	const bool		   is_indiced_draw_call_flags[] = { false, true };
   1063 	const glw::GLint   n_instances[]				= { 1, 4 };
   1064 	const glw::GLint   n_patch_vertices[] = { 4, gl_max_patch_vertices_value / 2, gl_max_patch_vertices_value };
   1065 	const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES,
   1066 															 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
   1067 															 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
   1068 	const unsigned int n_drawcall_count_multipliers =
   1069 		sizeof(drawcall_count_multipliers) / sizeof(drawcall_count_multipliers[0]);
   1070 	const unsigned int n_is_indiced_draw_call_flags =
   1071 		sizeof(is_indiced_draw_call_flags) / sizeof(is_indiced_draw_call_flags[0]);
   1072 	const unsigned int n_n_instances	  = sizeof(n_instances) / sizeof(n_instances[0]);
   1073 	const unsigned int n_n_patch_vertices = sizeof(n_patch_vertices) / sizeof(n_patch_vertices[0]);
   1074 	const unsigned int n_primitive_modes  = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
   1075 
   1076 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
   1077 	{
   1078 		_tessellation_primitive_mode current_primitive_mode = primitive_modes[n_primitive_mode];
   1079 
   1080 		for (unsigned int n_patch_vertices_item = 0; n_patch_vertices_item < n_n_patch_vertices;
   1081 			 ++n_patch_vertices_item)
   1082 		{
   1083 			glw::GLint current_n_patch_vertices = n_patch_vertices[n_patch_vertices_item];
   1084 
   1085 			for (unsigned int n_is_indiced_draw_call_flag = 0;
   1086 				 n_is_indiced_draw_call_flag < n_is_indiced_draw_call_flags; ++n_is_indiced_draw_call_flag)
   1087 			{
   1088 				bool current_is_indiced_draw_call = is_indiced_draw_call_flags[n_is_indiced_draw_call_flag];
   1089 
   1090 				for (unsigned int n_instances_item = 0; n_instances_item < n_n_instances; ++n_instances_item)
   1091 				{
   1092 					glw::GLint current_n_instances = n_instances[n_instances_item];
   1093 
   1094 					for (unsigned int n_drawcall_count_multiplier = 0;
   1095 						 n_drawcall_count_multiplier < n_drawcall_count_multipliers; ++n_drawcall_count_multiplier)
   1096 					{
   1097 						const unsigned int drawcall_count_multiplier =
   1098 							drawcall_count_multipliers[n_drawcall_count_multiplier];
   1099 
   1100 						/* Form the run descriptor */
   1101 						_run run;
   1102 
   1103 						initRun(run, current_primitive_mode, current_n_patch_vertices, current_is_indiced_draw_call,
   1104 								current_n_instances, drawcall_count_multiplier);
   1105 
   1106 						/* Store the descriptor for later execution */
   1107 						m_runs.push_back(run);
   1108 					}
   1109 				} /* for (all 'number of instances' settings) */
   1110 			}	 /* for (all 'is indiced draw call' flags) */
   1111 		}		  /* for (all 'n patch vertices' settings) */
   1112 	}			  /* for (all primitive modes) */
   1113 
   1114 	/* Set up buffer object bindings. Storage size will be determined on
   1115 	 * a per-iteration basis.
   1116 	 **/
   1117 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
   1118 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
   1119 
   1120 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
   1121 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed");
   1122 }
   1123 
   1124 /** Initializes all ES objects necessary to run a specific test pass.
   1125  *
   1126  *  Throws TestError exception if any of the arguments is found invalid.
   1127  *
   1128  *  @param run                       Test run descriptor to fill with IDs of initialized objects.
   1129  *  @param primitive_mode            Primitive mode to use for the pass.
   1130  *  @param n_patch_vertices          Amount of output patch vertices to use for the pass.
   1131  *  @param is_indiced                true  if the draw call to be used for the test run should be indiced;
   1132  *                                   false to use the non-indiced one.
   1133  *  @param n_instances               Amount of instances to use for the draw call. Set to 1 if the draw
   1134  *                                   call should be non-instanced.
   1135  *  @param drawcall_count_multiplier Will be used to multiply the "count" argument of the draw call API
   1136  *                                   function, effectively multiplying amount of primitives that will be
   1137  *                                   generated by the tessellator.
   1138  **/
   1139 void TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::initRun(
   1140 	_run& run, _tessellation_primitive_mode primitive_mode, glw::GLint n_patch_vertices, bool is_indiced,
   1141 	glw::GLint n_instances, unsigned int drawcall_count_multiplier)
   1142 {
   1143 	run.drawcall_count_multiplier = drawcall_count_multiplier;
   1144 	run.drawcall_is_indiced		  = is_indiced;
   1145 	run.n_instances				  = n_instances;
   1146 	run.n_patch_vertices		  = n_patch_vertices;
   1147 	run.primitive_mode			  = primitive_mode;
   1148 
   1149 	/* Set up a program object for the descriptor */
   1150 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1151 
   1152 	run.po_id = gl.createProgram();
   1153 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
   1154 
   1155 	/* Set up tessellation control shader object */
   1156 	std::string tc_body			= getTCCode(n_patch_vertices);
   1157 	const char* tc_body_raw_ptr = tc_body.c_str();
   1158 
   1159 	run.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
   1160 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
   1161 
   1162 	shaderSourceSpecialized(run.tc_id, 1 /* count */, &tc_body_raw_ptr);
   1163 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader");
   1164 
   1165 	/* Set up tessellation evaluation shader object. */
   1166 	std::string te_body			= getTECode(primitive_mode);
   1167 	const char* te_body_raw_ptr = te_body.c_str();
   1168 
   1169 	run.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   1170 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
   1171 
   1172 	shaderSourceSpecialized(run.te_id, 1 /* count */, &te_body_raw_ptr);
   1173 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader");
   1174 
   1175 	/* Compile the shaders */
   1176 	const glw::GLuint  shader_ids[] = { run.tc_id, run.te_id };
   1177 	const unsigned int n_shader_ids = sizeof(shader_ids) / sizeof(shader_ids[0]);
   1178 
   1179 	m_utils_ptr->compileShaders(n_shader_ids, shader_ids, true /* should_succeed */);
   1180 
   1181 	/* Attach all shader to the program object */
   1182 	gl.attachShader(run.po_id, m_fs_id);
   1183 	gl.attachShader(run.po_id, run.te_id);
   1184 	gl.attachShader(run.po_id, m_vs_id);
   1185 	gl.attachShader(run.po_id, run.tc_id);
   1186 
   1187 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
   1188 
   1189 	/* Set up XFB */
   1190 	const char* varyings[] = { "te_tc_invocation_id", "te_tc_patch_vertices_in", "te_tc_primitive_id",
   1191 							   "te_patch_vertices_in", "te_primitive_id" };
   1192 	const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]);
   1193 
   1194 	gl.transformFeedbackVaryings(run.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
   1195 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed");
   1196 
   1197 	/* Link the program object */
   1198 	glw::GLint link_status = GL_FALSE;
   1199 
   1200 	gl.linkProgram(run.po_id);
   1201 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
   1202 
   1203 	gl.getProgramiv(run.po_id, GL_LINK_STATUS, &link_status);
   1204 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
   1205 
   1206 	if (link_status != GL_TRUE)
   1207 	{
   1208 		TCU_FAIL("Program linking failed");
   1209 	}
   1210 
   1211 	/* If this is going to be an indiced draw call, we need to initialize a buffer
   1212 	 * object that will hold index data. GL_UNSIGNED_BYTE index type will be always
   1213 	 * used for the purpose of this test.
   1214 	 */
   1215 	if (is_indiced)
   1216 	{
   1217 		gl.genBuffers(1, &run.bo_indices_id);
   1218 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
   1219 
   1220 		/* Implementations are allowed NOT to support primitive restarting for patches.
   1221 		 * Take this into account and do not insert restart indices, if ES reports no
   1222 		 * support.
   1223 		 */
   1224 		glw::GLboolean is_primitive_restart_supported = GL_TRUE;
   1225 
   1226 		gl.getBooleanv(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED, &is_primitive_restart_supported);
   1227 		GLU_EXPECT_NO_ERROR(gl.getError(),
   1228 							"glGetIntegerv() failed for GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED pname");
   1229 
   1230 		/* Set up index buffer storage. Note that we're not using any attributes
   1231 		 * in any stage - our goal is just to make sure the primitive counter does
   1232 		 * not restart whenever restart index is encountered during a draw call */
   1233 		DE_ASSERT(run.n_patch_vertices > 3);
   1234 		DE_ASSERT(run.drawcall_count_multiplier > 1);
   1235 
   1236 		const unsigned int interleave_rate = run.n_patch_vertices * 2;
   1237 		unsigned char*	 bo_contents	 = DE_NULL;
   1238 		unsigned int	   bo_size =
   1239 			static_cast<unsigned int>(sizeof(unsigned char) * run.n_patch_vertices * run.drawcall_count_multiplier);
   1240 
   1241 		/* Count in restart indices if necessary */
   1242 		if (is_primitive_restart_supported)
   1243 		{
   1244 			run.n_restart_indices = (bo_size / interleave_rate);
   1245 			bo_size += 1 /* restart index */ * run.n_restart_indices;
   1246 		}
   1247 
   1248 		/* Allocate space for the index buffer */
   1249 		bo_contents = new unsigned char[bo_size];
   1250 
   1251 		/* Interleave the restart index every two complete sets of vertices, each set
   1252 		 * making up a full set of vertices. Fill all other indices with zeros. The
   1253 		 * indices don't really matter since test shaders do not use any attributes -
   1254 		 * what we want to verify is that the restart index does not break the primitive
   1255 		 * id counter.
   1256 		 *
   1257 		 * NOTE: Our interleave rate is just an arbitrary value that makes
   1258 		 *       sense, given the multipliers we use for the test */
   1259 		const unsigned char restart_index = 0xFF;
   1260 
   1261 		memset(bo_contents, 0, bo_size);
   1262 
   1263 		if (is_primitive_restart_supported)
   1264 		{
   1265 			for (unsigned int n_index = interleave_rate; n_index < bo_size; n_index += interleave_rate)
   1266 			{
   1267 				bo_contents[n_index] = restart_index;
   1268 
   1269 				/* Move one index ahead */
   1270 				n_index++;
   1271 			}
   1272 		}
   1273 
   1274 		/* Set up the buffer object storage */
   1275 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, run.bo_indices_id);
   1276 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
   1277 
   1278 		gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, bo_size, bo_contents, GL_STATIC_DRAW);
   1279 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
   1280 
   1281 		/* Release the buffer */
   1282 		delete[] bo_contents;
   1283 
   1284 		bo_contents = NULL;
   1285 	}
   1286 
   1287 	/* Retrieve amount of tessellation coordinates.
   1288 	 *
   1289 	 * Note: this test assumes a constant tessellation level value of 4 for all
   1290 	 *       inner/outer tessellation levels */
   1291 	const glw::GLfloat tess_levels[] = { 4.0f, 4.0f, 4.0f, 4.0f };
   1292 
   1293 	run.n_result_vertices = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   1294 		run.primitive_mode, tess_levels, tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   1295 		false); /* is_point_mode_enabled */
   1296 
   1297 	/* The value we have at this point is for single patch only. To end up
   1298 	 * with actual amount of coordinates that will be generated by the tessellator,
   1299 	 * we need to multiply it by drawcall_count_multiplier * n_instances */
   1300 	run.n_result_vertices *= run.drawcall_count_multiplier * run.n_instances;
   1301 
   1302 	/* We're done! */
   1303 }
   1304 
   1305 /** Executes the test.
   1306  *
   1307  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   1308  *
   1309  *  Note the function throws exception should an error occur!
   1310  *
   1311  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
   1312  **/
   1313 tcu::TestNode::IterateResult TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID::iterate(void)
   1314 {
   1315 	/* Do not execute if required extensions are not supported. */
   1316 	if (!m_is_tessellation_shader_supported)
   1317 	{
   1318 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   1319 	}
   1320 
   1321 	/* Initialize ES test objects */
   1322 	initTest();
   1323 
   1324 	/* Initialize tessellation shader utilities */
   1325 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1326 
   1327 	/* We don't need rasterization for this test */
   1328 	gl.enable(GL_RASTERIZER_DISCARD);
   1329 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed.");
   1330 
   1331 	/* Enable GL_PRIMITIVE_RESTART_FIXED_INDEX mode for indiced draw calls. */
   1332 	gl.enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
   1333 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX) failed.");
   1334 
   1335 	/* Iterate through all test runs configured */
   1336 	for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++)
   1337 	{
   1338 		const _run& run = *run_iterator;
   1339 
   1340 		/* Configure run-specific amount of vertices per patch */
   1341 		gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, run.n_patch_vertices);
   1342 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname");
   1343 
   1344 		/* Activate run-specific program object */
   1345 		gl.useProgram(run.po_id);
   1346 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
   1347 
   1348 		/* Update GL_ELEMENT_ARRAY_BUFFER binding, depending on run properties */
   1349 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, (run.drawcall_is_indiced) ? run.bo_indices_id : 0);
   1350 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not update GL_ELEMENT_ARRAY_BUFFER binding");
   1351 
   1352 		/* Update transform feedback buffer bindings */
   1353 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
   1354 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
   1355 
   1356 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
   1357 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed");
   1358 
   1359 		/* Update the transform feedback buffer object storage. For each generated
   1360 		 * tessellated coordinate, TE stage will output 5 integers. */
   1361 		glw::GLint bo_size = static_cast<glw::GLint>(run.n_result_vertices * 5 /* ints */ * sizeof(int));
   1362 
   1363 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, GL_STATIC_DRAW);
   1364 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
   1365 
   1366 		/* Render the geometry */
   1367 		glw::GLint  drawcall_count = run.n_patch_vertices * run.drawcall_count_multiplier + run.n_restart_indices;
   1368 		glw::GLenum tf_mode =
   1369 			TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, false); /* is_point_mode_enabled */
   1370 
   1371 		gl.beginTransformFeedback(tf_mode);
   1372 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed");
   1373 		{
   1374 			if (run.drawcall_is_indiced)
   1375 			{
   1376 				if (run.n_instances != 1)
   1377 				{
   1378 					gl.drawElementsInstanced(m_glExtTokens.PATCHES, drawcall_count, GL_UNSIGNED_BYTE,
   1379 											 DE_NULL, /* indices */
   1380 											 run.n_instances);
   1381 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstanced() failed");
   1382 				} /* if (run.n_instances != 0) */
   1383 				else
   1384 				{
   1385 					gl.drawElements(m_glExtTokens.PATCHES, drawcall_count, GL_UNSIGNED_BYTE, DE_NULL); /* indices */
   1386 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() failed");
   1387 				}
   1388 			} /* if (run.drawcall_is_indiced) */
   1389 			else
   1390 			{
   1391 				if (run.n_instances != 1)
   1392 				{
   1393 					gl.drawArraysInstanced(m_glExtTokens.PATCHES, 0, /* first */
   1394 										   drawcall_count, run.n_instances);
   1395 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArraysInstanced() failed");
   1396 				}
   1397 				else
   1398 				{
   1399 					gl.drawArrays(m_glExtTokens.PATCHES, 0, /* first */
   1400 								  drawcall_count);
   1401 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
   1402 				}
   1403 			}
   1404 		}
   1405 		gl.endTransformFeedback();
   1406 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
   1407 
   1408 		/* Map the result buffer object */
   1409 		const int* result_data = (const int*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
   1410 															   bo_size, GL_MAP_READ_BIT);
   1411 
   1412 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed");
   1413 
   1414 		/* Verify gl_InvocationID values used in both stages were correct. In TE:
   1415 		 *
   1416 		 * te_tc_invocation_id = in_tc[gl_PatchVerticesIn-1].tc_invocation_id;
   1417 		 *
   1418 		 * In the list of varyings passed to glTransformFeedbackVaryings(),
   1419 		 * te_tc_invocation_id is the very first item, so no need to offset
   1420 		 * result_data when initializing result_traveller_ptr below.
   1421 		 */
   1422 		const unsigned int n_int_varyings_per_tess_coordinate = 5;
   1423 		const int*		   result_traveller_ptr				  = result_data;
   1424 
   1425 		for (unsigned int n_coordinate = 0; n_coordinate < run.n_result_vertices;
   1426 			 ++n_coordinate, result_traveller_ptr += n_int_varyings_per_tess_coordinate)
   1427 		{
   1428 			const int expected_invocation_id = run.n_patch_vertices - 1;
   1429 			const int invocation_id_value	= *result_traveller_ptr;
   1430 
   1431 			if (invocation_id_value != expected_invocation_id)
   1432 			{
   1433 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_InvocationID value (" << invocation_id_value
   1434 								   << ") "
   1435 									  "was found for result coordinate at index "
   1436 								   << n_coordinate << " "
   1437 													  "instead of expected value ("
   1438 								   << expected_invocation_id << ")." << tcu::TestLog::EndMessage;
   1439 
   1440 				TCU_FAIL("Invalid gl_InvocationID value used in TC stage");
   1441 			}
   1442 		} /* for (all result coordinates) */
   1443 
   1444 		/* Verify gl_PrimitiveID values used in both stages were correct. In TE:
   1445 		 *
   1446 		 * te_tc_primitive_id = in_tc[gl_PatchVerticesIn-1].tc_primitive_id;
   1447 		 * te_primitive_id    = gl_PrimitiveID;
   1448 		 *
   1449 		 * In the list of varyings passed to glTransformFeedbackVaryings(),
   1450 		 * te_tc_primitive_id is passed as 3rd string and te_primitive_id is located on
   1451 		 * 5th location.
   1452 		 */
   1453 		const unsigned int n_result_vertices_per_patch_vertex_batch =
   1454 			run.n_result_vertices / run.drawcall_count_multiplier / run.n_instances;
   1455 		const unsigned int n_result_vertices_per_instance = run.n_result_vertices / run.n_instances;
   1456 
   1457 		for (unsigned int n_coordinate = 0; n_coordinate < run.n_result_vertices; ++n_coordinate)
   1458 		{
   1459 			unsigned int actual_n_coordinate = n_coordinate;
   1460 
   1461 			/* Subsequent instances reset gl_PrimitiveID counter */
   1462 			while (actual_n_coordinate >= n_result_vertices_per_instance)
   1463 			{
   1464 				actual_n_coordinate -= n_result_vertices_per_instance;
   1465 			}
   1466 
   1467 			/* Calculate expected gl_PrimitiveID value */
   1468 			const int expected_primitive_id = actual_n_coordinate / n_result_vertices_per_patch_vertex_batch;
   1469 
   1470 			/* te_tc_primitive_id */
   1471 			result_traveller_ptr =
   1472 				result_data + n_coordinate * n_int_varyings_per_tess_coordinate + 2; /* as per comment */
   1473 
   1474 			if (*result_traveller_ptr != expected_primitive_id)
   1475 			{
   1476 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PrimitiveID value (" << *result_traveller_ptr
   1477 								   << ") "
   1478 									  "was used in TC stage instead of expected value ("
   1479 								   << expected_primitive_id << ") "
   1480 															   " as stored for result coordinate at index "
   1481 								   << n_coordinate << "." << tcu::TestLog::EndMessage;
   1482 
   1483 				TCU_FAIL("Invalid gl_PrimitiveID value used in TC stage");
   1484 			}
   1485 
   1486 			/* te_primitive_id */
   1487 			result_traveller_ptr =
   1488 				result_data + n_coordinate * n_int_varyings_per_tess_coordinate + 4; /* as per comment */
   1489 
   1490 			if (*result_traveller_ptr != expected_primitive_id)
   1491 			{
   1492 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PrimitiveID value (" << *result_traveller_ptr
   1493 								   << ") "
   1494 									  "was used in TE stage instead of expected value ("
   1495 								   << expected_primitive_id << ") "
   1496 															   " as stored for result coordinate at index "
   1497 								   << n_coordinate << "." << tcu::TestLog::EndMessage;
   1498 
   1499 				TCU_FAIL("Invalid gl_PrimitiveID value used in TE stage");
   1500 			}
   1501 		} /* for (all result coordinates) */
   1502 
   1503 		/* Verify gl_PatchVerticesIn values used in both stages were correct. In TE:
   1504 		 *
   1505 		 * te_tc_patch_vertices_in = in_tc[gl_PatchVerticesIn-1].tc_patch_vertices_in;
   1506 		 * te_patch_vertices_in    = gl_PatchVerticesIn;
   1507 		 *
   1508 		 * In the list of varyings passed to glTransformFeedbackVaryings(),
   1509 		 * te_tc_patch_vertices_in takes 2nd location and te_patch_vertices_in is
   1510 		 * located at 4th position.
   1511 		 *
   1512 		 **/
   1513 		for (unsigned int n_coordinate = 0; n_coordinate < run.n_result_vertices; ++n_coordinate)
   1514 		{
   1515 			const int expected_patch_vertices_in_value = run.n_patch_vertices;
   1516 
   1517 			/* te_tc_patch_vertices_in */
   1518 			result_traveller_ptr =
   1519 				result_data + n_coordinate * n_int_varyings_per_tess_coordinate + 1; /* as per comment */
   1520 
   1521 			if (*result_traveller_ptr != expected_patch_vertices_in_value)
   1522 			{
   1523 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PatchVerticesIn value ("
   1524 								   << *result_traveller_ptr << ") "
   1525 															   "was used in TC stage instead of expected value ("
   1526 								   << expected_patch_vertices_in_value << ") "
   1527 																		  " as stored for result coordinate at index "
   1528 								   << n_coordinate << "." << tcu::TestLog::EndMessage;
   1529 
   1530 				TCU_FAIL("Invalid gl_PatchVerticesIn value used in TC stage");
   1531 			}
   1532 
   1533 			/* te_patch_vertices_in */
   1534 			result_traveller_ptr =
   1535 				result_data + n_coordinate * n_int_varyings_per_tess_coordinate + 3; /* as per comment */
   1536 
   1537 			if (*result_traveller_ptr != expected_patch_vertices_in_value)
   1538 			{
   1539 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PatchVerticesIn value ("
   1540 								   << *result_traveller_ptr << ") "
   1541 															   "was used in TE stage instead of expected value ("
   1542 								   << expected_patch_vertices_in_value << ") "
   1543 																		  " as stored for result coordinate at index "
   1544 								   << n_coordinate << "." << tcu::TestLog::EndMessage;
   1545 			}
   1546 		} /* for (all result coordinates) */
   1547 
   1548 		/* Unmap the buffer object - we're done with this iteration */
   1549 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   1550 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed");
   1551 	} /* for (all runs) */
   1552 
   1553 	/* All done */
   1554 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1555 	return STOP;
   1556 }
   1557 
   1558 std::string TessellationShaderTessellationgl_TessCoord::getTypeName(_tessellation_test_type test_type)
   1559 {
   1560 	static const char* names[2] = { "TCS_TES", "TES" };
   1561 	DE_ASSERT(0 <= test_type && test_type <= DE_LENGTH_OF_ARRAY(names));
   1562 	DE_STATIC_ASSERT(0 == TESSELLATION_TEST_TYPE_TCS_TES && 1 == TESSELLATION_TEST_TYPE_TES);
   1563 	return names[test_type];
   1564 }
   1565 
   1566 /** Constructor
   1567  *
   1568  * @param context Test context
   1569  **/
   1570 TessellationShaderTessellationgl_TessCoord::TessellationShaderTessellationgl_TessCoord(
   1571 	Context& context, const ExtParameters& extParams, _tessellation_test_type test_type)
   1572 	: TestCaseBase(context, extParams, getTypeName(test_type).c_str(),
   1573 				   "Verifies that u, v, w components of gl_TessCoord are within "
   1574 				   "range for a variety of input/outer tessellation level combinations "
   1575 				   "for all primitive modes. Verifies each component is within valid "
   1576 				   " range. Also checks that w is always equal to 0 for isolines mode.")
   1577 	, m_test_type(test_type)
   1578 	, m_bo_id(0)
   1579 	, m_broken_ts_id(0)
   1580 	, m_fs_id(0)
   1581 	, m_vs_id(0)
   1582 	, m_vao_id(0)
   1583 	, m_utils_ptr(0)
   1584 {
   1585 	/* Left blank on purpose */
   1586 }
   1587 
   1588 /** Deinitializes ES objects created for the test. */
   1589 void TessellationShaderTessellationgl_TessCoord::deinit()
   1590 {
   1591 	/* Call base class' deinit() */
   1592 	TestCaseBase::deinit();
   1593 
   1594 	if (!m_is_tessellation_shader_supported)
   1595 	{
   1596 		return;
   1597 	}
   1598 
   1599 	if (glu::isContextTypeES(m_context.getRenderContext().getType()) && m_test_type == TESSELLATION_TEST_TYPE_TES)
   1600 	{
   1601 		return;
   1602 	}
   1603 
   1604 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1605 
   1606 	/* Revert buffer object bindings */
   1607 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
   1608 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
   1609 
   1610 	/* Disable GL_RASTERIZER_DISCARD mode */
   1611 	gl.disable(GL_RASTERIZER_DISCARD);
   1612 
   1613 	/* Restore GL_PATCH_VERTICES_EXT, GL_PATCH_DEFAULT_INNER_LEVEL and
   1614 	 * GL_PATCH_DEFAULT_OUTER_LEVEL values */
   1615 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
   1616 	{
   1617 		const float default_tess_levels[] = { 1.0f, 1.0f, 1.0f, 1.0f };
   1618 		gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, default_tess_levels);
   1619 		gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, default_tess_levels);
   1620 	}
   1621 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
   1622 
   1623 	/* Unbind vertex array object */
   1624 	gl.bindVertexArray(0);
   1625 
   1626 	/* Free all ES objects we allocated for the test */
   1627 	if (m_bo_id != 0)
   1628 	{
   1629 		gl.deleteBuffers(1, &m_bo_id);
   1630 
   1631 		m_bo_id = 0;
   1632 	}
   1633 
   1634 	if (m_broken_ts_id != 0)
   1635 	{
   1636 		gl.deleteShader(m_broken_ts_id);
   1637 
   1638 		m_broken_ts_id = 0;
   1639 	}
   1640 
   1641 	if (m_fs_id != 0)
   1642 	{
   1643 		gl.deleteShader(m_fs_id);
   1644 
   1645 		m_fs_id = 0;
   1646 	}
   1647 
   1648 	if (m_vs_id != 0)
   1649 	{
   1650 		gl.deleteShader(m_vs_id);
   1651 
   1652 		m_vs_id = 0;
   1653 	}
   1654 
   1655 	if (m_vao_id != 0)
   1656 	{
   1657 		gl.deleteVertexArrays(1, &m_vao_id);
   1658 
   1659 		m_vao_id = 0;
   1660 	}
   1661 
   1662 	/* Deinitialize all test descriptors */
   1663 	for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
   1664 	{
   1665 		deinitTestDescriptor(*it);
   1666 	}
   1667 	m_tests.clear();
   1668 
   1669 	/* Release tessellation shader test utilities instance */
   1670 	if (m_utils_ptr != NULL)
   1671 	{
   1672 		delete m_utils_ptr;
   1673 
   1674 		m_utils_ptr = NULL;
   1675 	}
   1676 }
   1677 
   1678 /** Deinitialize all test pass-specific ES objects.
   1679  *
   1680  *  @param test Descriptor of a test pass to deinitialize.
   1681  **/
   1682 void TessellationShaderTessellationgl_TessCoord::deinitTestDescriptor(_test_descriptor& test)
   1683 {
   1684 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1685 
   1686 	if (test.po_id != 0)
   1687 	{
   1688 		gl.deleteProgram(test.po_id);
   1689 
   1690 		test.po_id = 0;
   1691 	}
   1692 
   1693 	if (test.tc_id != 0)
   1694 	{
   1695 		gl.deleteShader(test.tc_id);
   1696 
   1697 		test.tc_id = 0;
   1698 	}
   1699 
   1700 	if (test.te_id != 0)
   1701 	{
   1702 		gl.deleteShader(test.te_id);
   1703 
   1704 		test.te_id = 0;
   1705 	}
   1706 }
   1707 
   1708 /** Returns source code of a tessellation control shader for the test,
   1709  *  given user-specified amount of output patch vertices.
   1710  *
   1711  *  @param n_patch_vertices Amount of output patch vertices for TC stage.
   1712  *
   1713  *  @return Requested string.
   1714  **/
   1715 std::string TessellationShaderTessellationgl_TessCoord::getTCCode(glw::GLint n_patch_vertices)
   1716 {
   1717 	return TessellationShaderUtils::getGenericTCCode(n_patch_vertices, true);
   1718 }
   1719 
   1720 /** Returns source code of a tessellation evaluation shader for the test,
   1721  *  given user-specified vertex spacing and primitive modes.
   1722  *
   1723  *  Throws TestError exception if either of the arguments is invalid.
   1724  *
   1725  *  @param vertex_spacing Vertex spacing mode to use in the shader.
   1726  *  @param primitive_mode Primitive mode to use in the shader.
   1727  *
   1728  *  @return Requested string.
   1729  **/
   1730 std::string TessellationShaderTessellationgl_TessCoord::getTECode(_tessellation_shader_vertex_spacing vertex_spacing,
   1731 																  _tessellation_primitive_mode		  primitive_mode)
   1732 {
   1733 	return TessellationShaderUtils::getGenericTECode(vertex_spacing, primitive_mode,
   1734 													 TESSELLATION_SHADER_VERTEX_ORDERING_CCW, false);
   1735 }
   1736 
   1737 /** Initializes ES objects necessary to run the test. */
   1738 void TessellationShaderTessellationgl_TessCoord::initTest()
   1739 {
   1740 	/* Skip if required extensions are not supported. */
   1741 	if (!m_is_tessellation_shader_supported)
   1742 	{
   1743 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   1744 	}
   1745 
   1746 	if (glu::isContextTypeES(m_context.getRenderContext().getType()) && m_test_type == TESSELLATION_TEST_TYPE_TES)
   1747 	{
   1748 		throw tcu::NotSupportedError("Test can't be run in ES context");
   1749 	}
   1750 
   1751 	/* Generate all test-wide objects needed for test execution */
   1752 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1753 
   1754 	gl.genVertexArrays(1, &m_vao_id);
   1755 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
   1756 
   1757 	gl.bindVertexArray(m_vao_id);
   1758 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
   1759 
   1760 	gl.genBuffers(1, &m_bo_id);
   1761 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
   1762 
   1763 	m_broken_ts_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   1764 	m_fs_id		   = gl.createShader(GL_FRAGMENT_SHADER);
   1765 	m_vs_id		   = gl.createShader(GL_VERTEX_SHADER);
   1766 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
   1767 
   1768 	/* Configure fragment shader body */
   1769 	const char* fs_body = "${VERSION}\n"
   1770 						  "\n"
   1771 						  "void main()\n"
   1772 						  "{\n"
   1773 						  "}\n";
   1774 
   1775 	shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body);
   1776 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader");
   1777 
   1778 	/* Configure vertex shader body */
   1779 	const char* vs_body = "${VERSION}\n"
   1780 						  "\n"
   1781 						  "void main()\n"
   1782 						  "{\n"
   1783 						  "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
   1784 						  "}\n";
   1785 
   1786 	shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body);
   1787 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader");
   1788 
   1789 	/* Compile all the shaders */
   1790 	const glw::GLuint  shaders[] = { m_fs_id, m_vs_id };
   1791 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
   1792 
   1793 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
   1794 	{
   1795 		glw::GLuint shader = shaders[n_shader];
   1796 
   1797 		if (shader != 0)
   1798 		{
   1799 			glw::GLint compile_status = GL_FALSE;
   1800 
   1801 			gl.compileShader(shader);
   1802 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
   1803 
   1804 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
   1805 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
   1806 
   1807 			if (compile_status != GL_TRUE)
   1808 			{
   1809 				TCU_FAIL("Shader compilation failed");
   1810 			}
   1811 		}
   1812 	} /* for (all shaders) */
   1813 
   1814 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value before we start looping */
   1815 	glw::GLint gl_max_tess_gen_level_value = 0;
   1816 
   1817 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
   1818 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
   1819 
   1820 	/* Initialize all test passes - iterate over all primitive modes supported.. */
   1821 	for (int primitive_mode = static_cast<int>(TESSELLATION_SHADER_PRIMITIVE_MODE_FIRST);
   1822 		 primitive_mode != static_cast<int>(TESSELLATION_SHADER_PRIMITIVE_MODE_COUNT); primitive_mode++)
   1823 	{
   1824 		/* Iterate over all tessellation level combinations defined for current primitive mode */
   1825 		_tessellation_levels_set tessellation_levels = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
   1826 			static_cast<_tessellation_primitive_mode>(primitive_mode), gl_max_tess_gen_level_value,
   1827 			TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
   1828 
   1829 		for (_tessellation_levels_set_const_iterator levels_iterator = tessellation_levels.begin();
   1830 			 levels_iterator != tessellation_levels.end(); levels_iterator++)
   1831 		{
   1832 			const _tessellation_levels& levels = *levels_iterator;
   1833 			_test_descriptor			test;
   1834 
   1835 			initTestDescriptor(test, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   1836 							   static_cast<_tessellation_primitive_mode>(primitive_mode), 1, /* n_patch_vertices */
   1837 							   levels.inner, levels.outer, m_test_type);
   1838 
   1839 			/* Store the test descriptor */
   1840 			m_tests.push_back(test);
   1841 		} /* for (all tessellation level combinations for current primitive mode) */
   1842 	}	 /* for (all primitive modes) */
   1843 
   1844 	/* Set up buffer object bindings. Storage size will be determined on
   1845 	 * a per-iteration basis.
   1846 	 **/
   1847 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
   1848 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
   1849 
   1850 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
   1851 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed");
   1852 }
   1853 
   1854 /** Initializes all ES objects necessary to run a specific test pass.
   1855  *
   1856  *  Throws TestError exception if any of the arguments is found invalid.
   1857  *
   1858  *  @param test             Test descriptor to fill with IDs of initialized objects.
   1859  *  @param vertex_spacing   Vertex spacing mode to use for the pass.
   1860  *  @param primitive_mode   Primitive mode to use for the pass.
   1861  *  @param n_patch_vertices Amount of output patch vertices to use for the pass.
   1862  *  @param inner_tess_level Inner tessellation level values to be used for the pass.
   1863  *                          Must not be NULL.
   1864  *  @param outer_tess_level Outer tessellation level values to be used for the pass.
   1865  *                          Must not be NULL.
   1866  *  @param test_type        Defines which tessellation stages should be defined for the pass.
   1867  **/
   1868 void TessellationShaderTessellationgl_TessCoord::initTestDescriptor(
   1869 	_test_descriptor& test, _tessellation_shader_vertex_spacing vertex_spacing,
   1870 	_tessellation_primitive_mode primitive_mode, glw::GLint n_patch_vertices, const float* inner_tess_level,
   1871 	const float* outer_tess_level, _tessellation_test_type test_type)
   1872 {
   1873 	test.n_patch_vertices = n_patch_vertices;
   1874 	test.primitive_mode   = primitive_mode;
   1875 	test.type			  = test_type;
   1876 	test.vertex_spacing   = vertex_spacing;
   1877 
   1878 	memcpy(test.tess_level_inner, inner_tess_level, sizeof(float) * 2 /* components */);
   1879 	memcpy(test.tess_level_outer, outer_tess_level, sizeof(float) * 4 /* components */);
   1880 
   1881 	/* Set up a program object for the descriptor */
   1882 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1883 
   1884 	test.po_id = gl.createProgram();
   1885 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
   1886 
   1887 	/* Set up a pass-specific tessellation shader objects. */
   1888 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
   1889 	{
   1890 		test.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
   1891 	}
   1892 
   1893 	test.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   1894 
   1895 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
   1896 
   1897 	/* Configure tessellation control shader body */
   1898 	if (test.tc_id != 0)
   1899 	{
   1900 		std::string tc_body			= getTCCode(n_patch_vertices);
   1901 		const char* tc_body_raw_ptr = tc_body.c_str();
   1902 
   1903 		shaderSourceSpecialized(test.tc_id, 1 /* count */, &tc_body_raw_ptr);
   1904 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader");
   1905 	}
   1906 
   1907 	/* Configure tessellation evaluation shader body */
   1908 	std::string te_body			= getTECode(vertex_spacing, primitive_mode);
   1909 	const char* te_body_raw_ptr = te_body.c_str();
   1910 
   1911 	shaderSourceSpecialized(test.te_id, 1 /* count */, &te_body_raw_ptr);
   1912 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader");
   1913 
   1914 	/* Compile the tessellation evaluation shader */
   1915 	glw::GLint		   compile_status = GL_FALSE;
   1916 	glw::GLuint		   shaders[]	  = { test.tc_id, test.te_id };
   1917 	const unsigned int n_shaders	  = sizeof(shaders) / sizeof(shaders[0]);
   1918 
   1919 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
   1920 	{
   1921 		glw::GLuint shader = shaders[n_shader];
   1922 
   1923 		if (shader != 0)
   1924 		{
   1925 			gl.compileShader(shader);
   1926 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed for tessellation shader");
   1927 
   1928 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
   1929 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed for tessellation shader");
   1930 
   1931 			if (compile_status != GL_TRUE)
   1932 			{
   1933 				TCU_FAIL("Tessellation shader compilation failed");
   1934 			}
   1935 		}
   1936 	} /* for (all shaders) */
   1937 
   1938 	/* Attach all shader to the program object */
   1939 	gl.attachShader(test.po_id, m_fs_id);
   1940 	gl.attachShader(test.po_id, test.te_id);
   1941 	gl.attachShader(test.po_id, m_vs_id);
   1942 
   1943 	if (test.tc_id != 0)
   1944 	{
   1945 		gl.attachShader(test.po_id, test.tc_id);
   1946 	}
   1947 
   1948 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
   1949 
   1950 	/* Set up XFB */
   1951 	const char*		   varyings[] = { "result_uvw" };
   1952 	const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]);
   1953 
   1954 	gl.transformFeedbackVaryings(test.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
   1955 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed");
   1956 
   1957 	/* Link the program object */
   1958 	glw::GLint link_status = GL_FALSE;
   1959 
   1960 	gl.linkProgram(test.po_id);
   1961 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
   1962 
   1963 	gl.getProgramiv(test.po_id, GL_LINK_STATUS, &link_status);
   1964 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
   1965 
   1966 	if (link_status != GL_TRUE)
   1967 	{
   1968 		TCU_FAIL("Program linking failed");
   1969 	}
   1970 
   1971 	/* If TCS stage is present, set up the corresponding uniforms as needed */
   1972 	if (test.type == TESSELLATION_TEST_TYPE_TCS_TES)
   1973 	{
   1974 		test.inner_tess_level_uniform_location = gl.getUniformLocation(test.po_id, "inner_tess_level");
   1975 		test.outer_tess_level_uniform_location = gl.getUniformLocation(test.po_id, "outer_tess_level");
   1976 
   1977 		DE_ASSERT(test.inner_tess_level_uniform_location != -1);
   1978 		DE_ASSERT(test.outer_tess_level_uniform_location != -1);
   1979 
   1980 		/* Now that we have the locations, let's configure the uniforms */
   1981 		gl.useProgram(test.po_id);
   1982 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
   1983 
   1984 		gl.uniform2fv(test.inner_tess_level_uniform_location, 1, /* count */
   1985 					  test.tess_level_inner);
   1986 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2fv() call failed");
   1987 
   1988 		gl.uniform4fv(test.outer_tess_level_uniform_location, 1, /* count */
   1989 					  test.tess_level_outer);
   1990 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed");
   1991 	}
   1992 }
   1993 
   1994 /** Executes the test.
   1995  *
   1996  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   1997  *
   1998  *  Note the function throws exception should an error occur!
   1999  *
   2000  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
   2001  **/
   2002 tcu::TestNode::IterateResult TessellationShaderTessellationgl_TessCoord::iterate(void)
   2003 {
   2004 	/* Do not execute if required extensions are not supported. */
   2005 	if (!m_is_geometry_shader_extension_supported || !m_is_tessellation_shader_supported)
   2006 	{
   2007 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   2008 	}
   2009 
   2010 	/* On ES skip test configurations that don't have TCS. */
   2011 	if (isContextTypeES(m_context.getRenderContext().getType()) && (m_test_type == TESSELLATION_TEST_TYPE_TES))
   2012 	{
   2013 		throw tcu::NotSupportedError("Implementation requires TCS and TES be used together; skipping.");
   2014 	}
   2015 
   2016 	/* Initialize ES test objects */
   2017 	initTest();
   2018 
   2019 	/* Initialize tessellation shader utilities */
   2020 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2021 
   2022 	m_utils_ptr = new TessellationShaderUtils(gl, this);
   2023 
   2024 	/* We don't need rasterization for this test */
   2025 	gl.enable(GL_RASTERIZER_DISCARD);
   2026 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed.");
   2027 
   2028 	/* Iterate through all tests configured */
   2029 	for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); test_iterator++)
   2030 	{
   2031 		const _test_descriptor& test = *test_iterator;
   2032 
   2033 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
   2034 		{
   2035 			/* If there is no TCS defined, define inner/outer tessellation levels */
   2036 			if (test.type == TESSELLATION_TEST_TYPE_TES)
   2037 			{
   2038 				gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, test.tess_level_inner);
   2039 				GLU_EXPECT_NO_ERROR(gl.getError(),
   2040 									"glPatchParameterfv() failed for GL_PATCH_DEFAULT_INNER_LEVEL pname");
   2041 
   2042 				gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, test.tess_level_outer);
   2043 				GLU_EXPECT_NO_ERROR(gl.getError(),
   2044 									"glPatchParameterfv() failed for GL_PATCH_DEFAULT_OUTER_LEVEL pname");
   2045 			}
   2046 		}
   2047 
   2048 		/* Configure amount of vertices per patch */
   2049 		gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, test.n_patch_vertices);
   2050 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname");
   2051 
   2052 		/* Set up XFB target BO storage size. We will be capturing a total of 12 FP components per
   2053 		 * result vertex.
   2054 		 */
   2055 		unsigned int n_bytes_needed	= 0;
   2056 		unsigned int n_result_vertices = 0;
   2057 
   2058 		n_result_vertices = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   2059 			test.primitive_mode, test.tess_level_inner, test.tess_level_outer, test.vertex_spacing, false);
   2060 		n_bytes_needed = static_cast<unsigned int>(n_result_vertices * sizeof(float) * 12 /* components */);
   2061 
   2062 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL, /* data */
   2063 					  GL_STATIC_DRAW);
   2064 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
   2065 
   2066 		/* Activate the program object */
   2067 		gl.useProgram(test.po_id);
   2068 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
   2069 
   2070 		/* Draw the test geometry. */
   2071 		glw::GLenum tf_mode = TessellationShaderUtils::getTFModeForPrimitiveMode(test.primitive_mode, false);
   2072 
   2073 		gl.beginTransformFeedback(tf_mode);
   2074 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_PATCHES_EXT) failed.");
   2075 
   2076 		gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, test.n_patch_vertices);
   2077 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
   2078 
   2079 		gl.endTransformFeedback();
   2080 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
   2081 
   2082 		/* Map the BO with result data into user space */
   2083 		const float* vertex_data = (const float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
   2084 																   n_bytes_needed, GL_MAP_READ_BIT);
   2085 
   2086 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
   2087 
   2088 		/* (test 1): Make sure that u+v+w == 1 (applicable for triangles only) */
   2089 		const float epsilon = 1e-5f;
   2090 
   2091 		if (test.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES)
   2092 		{
   2093 			for (unsigned int n_vertex = 0; n_vertex < n_result_vertices; ++n_vertex)
   2094 			{
   2095 				const float* vertex_uvw = vertex_data + 3 /* components */ * n_vertex;
   2096 				float		 sum_uvw	= vertex_uvw[0] + vertex_uvw[1] + vertex_uvw[2];
   2097 
   2098 				if (de::abs(sum_uvw - 1.0f) > epsilon)
   2099 				{
   2100 					m_testCtx.getLog() << tcu::TestLog::Message << "For triangles, U+V+W coordinates outputted "
   2101 																   "by tessellator should sum up to 1.0. Instead, the "
   2102 																   "following coordinates:"
   2103 									   << " (" << vertex_uvw[0] << ", " << vertex_uvw[1] << ", " << vertex_uvw[2]
   2104 									   << ") "
   2105 										  "sum up to "
   2106 									   << sum_uvw << "." << tcu::TestLog::EndMessage;
   2107 
   2108 					TCU_FAIL("U+V+W coordinates do not add up to 1, even though triangle/tessellation"
   2109 							 " was requested");
   2110 				}
   2111 			} /* for (all vertices) */
   2112 		}	 /* if (we're dealing with triangles or quads) */
   2113 
   2114 		/* (test 2): Make sure that u, v, w e <0, 1> (always applicable) */
   2115 		for (unsigned int n_vertex = 0; n_vertex < n_result_vertices; ++n_vertex)
   2116 		{
   2117 			const float* vertex_uvw = vertex_data + 3 /* components */ * n_vertex;
   2118 
   2119 			if (!(vertex_uvw[0] >= 0.0f && vertex_uvw[0] <= 1.0f && vertex_uvw[1] >= 0.0f && vertex_uvw[1] <= 1.0f &&
   2120 				  vertex_uvw[2] >= 0.0f && vertex_uvw[2] <= 1.0f))
   2121 			{
   2122 				m_testCtx.getLog() << tcu::TestLog::Message
   2123 								   << "U, V and W coordinates outputted by the tessellator should "
   2124 									  "be within <0, 1> range. However, "
   2125 								   << "vertex at index: " << n_vertex << "is defined by the following triple:"
   2126 								   << " (" << vertex_uvw[0] << ", " << vertex_uvw[1] << ", " << vertex_uvw[2] << ")."
   2127 								   << tcu::TestLog::EndMessage;
   2128 
   2129 				TCU_FAIL("U/V/W coordinate outputted by the tessellator is outside allowed range.");
   2130 			}
   2131 		} /* for (all vertices) */
   2132 
   2133 		/* (test 3): Make sure w is always zero (applicable to quads and isolines) */
   2134 		if (test.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS ||
   2135 			test.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES)
   2136 		{
   2137 			for (unsigned int n_vertex = 0; n_vertex < n_result_vertices; ++n_vertex)
   2138 			{
   2139 				const float* vertex_uvw = vertex_data + 3 /* components */ * n_vertex;
   2140 
   2141 				if (de::abs(vertex_uvw[2]) > epsilon)
   2142 				{
   2143 					m_testCtx.getLog() << tcu::TestLog::Message
   2144 									   << "W coordinate should be zero for all vertices outputted "
   2145 										  "for isolines and quads; for at least one vertex, W was "
   2146 										  "found to be equal to: "
   2147 									   << vertex_uvw[2] << tcu::TestLog::EndMessage;
   2148 
   2149 					TCU_FAIL("W coordinate was found to be non-zero for at least one tessellation coordinate"
   2150 							 " generated in either quads or isolines primitive mode");
   2151 				}
   2152 			} /* for (all vertices) */
   2153 		}	 /* if (we're dealing with quads or isolines) */
   2154 
   2155 		/* Unmap the BO */
   2156 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   2157 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
   2158 	}
   2159 
   2160 	/* All done */
   2161 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2162 	return STOP;
   2163 }
   2164 
   2165 /** Constructor
   2166  *
   2167  * @param context     Test context
   2168  * @param name        Test case's name
   2169  * @param description Test case's desricption
   2170  **/
   2171 TessellationShaderTessellationMaxInOut::TessellationShaderTessellationMaxInOut(Context&				context,
   2172 																			   const ExtParameters& extParams)
   2173 	: TestCaseBase(context, extParams, "max_in_out_attributes",
   2174 				   "Make sure it is possible to use up GL_MAX_TESS_*_COMPONENTS_EXT.")
   2175 	, m_po_id_1(0)
   2176 	, m_po_id_2(0)
   2177 	, m_fs_id(0)
   2178 	, m_tcs_id_1(0)
   2179 	, m_tcs_id_2(0)
   2180 	, m_tes_id_1(0)
   2181 	, m_tes_id_2(0)
   2182 	, m_vs_id_1(0)
   2183 	, m_vs_id_2(0)
   2184 	, m_tf_bo_id_1(0)
   2185 	, m_tf_bo_id_2(0)
   2186 	, m_patch_data_bo_id(0)
   2187 	, m_vao_id(0)
   2188 	, m_gl_max_tess_control_input_components_value(0)
   2189 	, m_gl_max_tess_control_output_components_value(0)
   2190 	, m_gl_max_tess_evaluation_input_components_value(0)
   2191 	, m_gl_max_tess_evaluation_output_components_value(0)
   2192 	, m_gl_max_transform_feedback_interleaved_components_value(0)
   2193 	, m_gl_max_tess_patch_components_value(0)
   2194 	, m_gl_max_vertex_output_components_value(0)
   2195 	, m_ref_vertex_attributes(DE_NULL)
   2196 	, m_tf_varyings_names(DE_NULL)
   2197 {
   2198 	m_ref_patch_attributes[0] = 0.0f;
   2199 	m_ref_patch_attributes[1] = 0.0f;
   2200 	m_ref_patch_attributes[2] = 0.0f;
   2201 	m_ref_patch_attributes[3] = 0.0f;
   2202 }
   2203 
   2204 /** Deinitializes all ES objects created for the test. */
   2205 void TessellationShaderTessellationMaxInOut::deinit(void)
   2206 {
   2207 	/* Call base class deinitialization routine */
   2208 	TestCaseBase::deinit();
   2209 
   2210 	if (!m_is_tessellation_shader_supported)
   2211 	{
   2212 		return;
   2213 	}
   2214 
   2215 	/* Deallocate dynamic arrays */
   2216 	if (m_ref_vertex_attributes != DE_NULL)
   2217 	{
   2218 		free(m_ref_vertex_attributes);
   2219 
   2220 		m_ref_vertex_attributes = DE_NULL;
   2221 	}
   2222 
   2223 	/* Deallocate the varyings array */
   2224 	if (m_tf_varyings_names != DE_NULL)
   2225 	{
   2226 		for (int i = 0; i < (m_gl_max_tess_evaluation_output_components_value) / 4 - 1 /* gl_Position */; i++)
   2227 		{
   2228 			if (m_tf_varyings_names[i] != DE_NULL)
   2229 			{
   2230 				free(m_tf_varyings_names[i]);
   2231 
   2232 				m_tf_varyings_names[i] = DE_NULL;
   2233 			}
   2234 		}
   2235 
   2236 		free(m_tf_varyings_names);
   2237 
   2238 		m_tf_varyings_names = DE_NULL;
   2239 	}
   2240 
   2241 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2242 
   2243 	/* Reset GL_PATCH_VERTICES_EXT pname value */
   2244 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
   2245 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed!");
   2246 
   2247 	/* Unbind vertex array object */
   2248 	gl.bindVertexArray(0);
   2249 
   2250 	/* Release ES objects */
   2251 	if (m_fs_id != 0)
   2252 	{
   2253 		gl.deleteShader(m_fs_id);
   2254 
   2255 		m_fs_id = 0;
   2256 	}
   2257 
   2258 	if (m_po_id_1 != 0)
   2259 	{
   2260 		gl.deleteProgram(m_po_id_1);
   2261 
   2262 		m_po_id_1 = 0;
   2263 	}
   2264 
   2265 	if (m_po_id_2 != 0)
   2266 	{
   2267 		gl.deleteProgram(m_po_id_2);
   2268 
   2269 		m_po_id_2 = 0;
   2270 	}
   2271 
   2272 	if (m_tcs_id_1 != 0)
   2273 	{
   2274 		gl.deleteShader(m_tcs_id_1);
   2275 
   2276 		m_tcs_id_1 = 0;
   2277 	}
   2278 
   2279 	if (m_tcs_id_2 != 0)
   2280 	{
   2281 		gl.deleteShader(m_tcs_id_2);
   2282 
   2283 		m_tcs_id_2 = 0;
   2284 	}
   2285 
   2286 	if (m_tes_id_1 != 0)
   2287 	{
   2288 		gl.deleteShader(m_tes_id_1);
   2289 
   2290 		m_tes_id_1 = 0;
   2291 	}
   2292 
   2293 	if (m_tes_id_2 != 0)
   2294 	{
   2295 		gl.deleteShader(m_tes_id_2);
   2296 
   2297 		m_tes_id_2 = 0;
   2298 	}
   2299 
   2300 	if (m_vs_id_1 != 0)
   2301 	{
   2302 		gl.deleteShader(m_vs_id_1);
   2303 
   2304 		m_vs_id_1 = 0;
   2305 	}
   2306 
   2307 	if (m_vs_id_2 != 0)
   2308 	{
   2309 		gl.deleteShader(m_vs_id_2);
   2310 
   2311 		m_vs_id_2 = 0;
   2312 	}
   2313 
   2314 	if (m_tf_bo_id_1 != 0)
   2315 	{
   2316 		gl.deleteBuffers(1, &m_tf_bo_id_1);
   2317 
   2318 		m_tf_bo_id_1 = 0;
   2319 	}
   2320 
   2321 	if (m_tf_bo_id_2 != 0)
   2322 	{
   2323 		gl.deleteBuffers(1, &m_tf_bo_id_2);
   2324 
   2325 		m_tf_bo_id_2 = 0;
   2326 	}
   2327 
   2328 	if (m_patch_data_bo_id != 0)
   2329 	{
   2330 		gl.deleteBuffers(1, &m_patch_data_bo_id);
   2331 
   2332 		m_patch_data_bo_id = 0;
   2333 	}
   2334 
   2335 	if (m_vao_id != 0)
   2336 	{
   2337 		gl.deleteVertexArrays(1, &m_vao_id);
   2338 
   2339 		m_vao_id = 0;
   2340 	}
   2341 }
   2342 
   2343 /** Executes the test.
   2344  *
   2345  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   2346  *
   2347  *  Note the function throws exception should an error occur!
   2348  *
   2349  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   2350  **/
   2351 tcu::TestNode::IterateResult TessellationShaderTessellationMaxInOut::iterate(void)
   2352 {
   2353 	/* Retrieve ES entry-points. */
   2354 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2355 
   2356 	/* Initialize test-specific ES objects. */
   2357 	initTest();
   2358 
   2359 	/* Execute test case 1 */
   2360 	gl.useProgram(m_po_id_1);
   2361 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
   2362 
   2363 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
   2364 					  m_tf_bo_id_1);
   2365 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed!");
   2366 
   2367 	gl.beginTransformFeedback(GL_POINTS);
   2368 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed");
   2369 
   2370 	gl.drawArrays(m_glExtTokens.PATCHES, 0, /* first */
   2371 				  2);						/* count */
   2372 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
   2373 
   2374 	gl.endTransformFeedback();
   2375 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
   2376 
   2377 	/* Verify the rendered data. */
   2378 	bool test_passed = true;
   2379 
   2380 	test_passed &= compareValues("Per-vertex components test ", m_ref_vertex_attributes,
   2381 								 m_gl_max_tess_evaluation_output_components_value / 4);
   2382 
   2383 	/* Execute test case 2 */
   2384 	gl.useProgram(m_po_id_2);
   2385 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
   2386 
   2387 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
   2388 					  m_tf_bo_id_2);
   2389 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed!");
   2390 
   2391 	gl.beginTransformFeedback(GL_POINTS);
   2392 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed");
   2393 
   2394 	gl.drawArrays(m_glExtTokens.PATCHES, 0, /* first */
   2395 				  2);						/* count */
   2396 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
   2397 
   2398 	gl.endTransformFeedback();
   2399 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
   2400 
   2401 	/* Verify the rendered data */
   2402 	test_passed &=
   2403 		compareValues("Per-patch components test ", m_ref_patch_attributes, 1 /* amount of output vectors */);
   2404 
   2405 	/* Test passed. */
   2406 	if (test_passed)
   2407 	{
   2408 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2409 	}
   2410 	else
   2411 	{
   2412 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   2413 	}
   2414 
   2415 	return STOP;
   2416 }
   2417 
   2418 /** Sets up buffer objects.
   2419  *
   2420  *   Note the function throws exception should an error occur!
   2421  **/
   2422 void TessellationShaderTessellationMaxInOut::initBufferObjects(void)
   2423 {
   2424 	/* Retrieve ES entry-points. */
   2425 	glw::GLint			  bo_size = 0;
   2426 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
   2427 
   2428 	/* Transform feedback buffer object for case 1 */
   2429 	gl.genBuffers(1, &m_tf_bo_id_1);
   2430 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!");
   2431 
   2432 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_tf_bo_id_1);
   2433 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
   2434 
   2435 	bo_size = static_cast<glw::GLint>(2														 /* vertices       */
   2436 									  * 4													 /* components     */
   2437 									  * m_gl_max_tess_evaluation_output_components_value / 4 /* attributes     */
   2438 									  * sizeof(glw::GLfloat));								 /* attribute size */
   2439 
   2440 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, NULL, GL_STATIC_DRAW);
   2441 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
   2442 
   2443 	/* Transform feedback buffer object for case 2 */
   2444 	bo_size = 2 *						/* vertices */
   2445 			  sizeof(glw::GLfloat) * 4; /* components */
   2446 
   2447 	gl.genBuffers(1, &m_tf_bo_id_2);
   2448 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!");
   2449 
   2450 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_tf_bo_id_2);
   2451 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
   2452 
   2453 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, NULL, GL_STATIC_DRAW);
   2454 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
   2455 
   2456 	/* Set up vertex data buffer storage */
   2457 	glw::GLfloat vertices[2 /* vertices */ * 4 /* components */];
   2458 
   2459 	bo_size		= sizeof(vertices);
   2460 	vertices[0] = 0.f;
   2461 	vertices[1] = 0.f;
   2462 	vertices[2] = 0.f;
   2463 	vertices[3] = 1.f;
   2464 	vertices[4] = 1.f;
   2465 	vertices[5] = 1.f;
   2466 	vertices[6] = 1.f;
   2467 	vertices[7] = 1.f;
   2468 
   2469 	gl.genBuffers(1, &m_patch_data_bo_id);
   2470 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!");
   2471 
   2472 	gl.bindBuffer(GL_ARRAY_BUFFER, m_patch_data_bo_id);
   2473 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
   2474 
   2475 	gl.bufferData(GL_ARRAY_BUFFER, bo_size, vertices, GL_STATIC_DRAW);
   2476 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed!");
   2477 
   2478 	gl.enableVertexAttribArray(0);
   2479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() failed!");
   2480 
   2481 	gl.vertexAttribPointer(0,				   /* index */
   2482 						   4,				   /* size */
   2483 						   GL_FLOAT, GL_FALSE, /* normalized */
   2484 						   0,				   /* stride */
   2485 						   0);				   /* pointer */
   2486 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() failed!");
   2487 }
   2488 
   2489 /** Initializes the test.
   2490  *
   2491  *  Note the function throws exception should an error occur!
   2492  **/
   2493 void TessellationShaderTessellationMaxInOut::initProgramObjects(void)
   2494 {
   2495 	/* Retrieve ES entry-points */
   2496 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2497 
   2498 	/* Create program objects. */
   2499 	m_po_id_1 = gl.createProgram();
   2500 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
   2501 
   2502 	m_po_id_2 = gl.createProgram();
   2503 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
   2504 
   2505 	/* Set up all the shader objects that will be used for the test */
   2506 	m_vs_id_1 = gl.createShader(GL_VERTEX_SHADER);
   2507 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_VERTEX_SHADER) failed!");
   2508 
   2509 	m_vs_id_2 = gl.createShader(GL_VERTEX_SHADER);
   2510 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_VERTEX_SHADER) failed!");
   2511 
   2512 	m_tcs_id_1 = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
   2513 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_CONTROL_SHADER_EXT) failed!");
   2514 
   2515 	m_tcs_id_2 = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
   2516 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_CONTROL_SHADER_EXT) failed!");
   2517 
   2518 	m_tes_id_1 = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   2519 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_EVALUATION_SHADER_EXT) failed!");
   2520 
   2521 	m_tes_id_2 = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
   2522 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_TESS_EVALUATION_SHADER_EXT) failed!");
   2523 
   2524 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   2525 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(GL_FRAGMENT_SHADER) failed!");
   2526 
   2527 	/* Transform Feedback setup for case 1
   2528 	 *
   2529 	 * Varyings array: m_tf_varyings_names[i <  m_gl_max_tess_evaluation_output_components_value / 4-1] == "Vertex.value[i]"
   2530 	 *                 m_tf_varyings_names[i == m_gl_max_tess_evaluation_output_components_value / 4-1] == "gl_Position"
   2531 	 */
   2532 	const char position_varying[] = "gl_Position";
   2533 
   2534 	m_tf_varyings_names = (char**)malloc((m_gl_max_tess_evaluation_output_components_value / 4) * sizeof(char*));
   2535 
   2536 	if (m_tf_varyings_names == DE_NULL)
   2537 	{
   2538 		throw tcu::ResourceError("Unable to allocate memory!");
   2539 	}
   2540 
   2541 	for (int i = 0; i < (m_gl_max_tess_evaluation_output_components_value) / 4 /* attributes */ - 1 /* gl_Position */;
   2542 		 i++)
   2543 	{
   2544 		std::stringstream tf_varying_stream;
   2545 		const char*		  tf_varying_raw_ptr = DE_NULL;
   2546 		std::string		  tf_varying_string;
   2547 
   2548 		tf_varying_stream << "Vertex.value[" << i << "]";
   2549 		tf_varying_string  = tf_varying_stream.str();
   2550 		tf_varying_raw_ptr = tf_varying_string.c_str();
   2551 
   2552 		m_tf_varyings_names[i] = (char*)malloc(strlen(tf_varying_raw_ptr) + 1 /* '\0' */);
   2553 		if (m_tf_varyings_names[i] == DE_NULL)
   2554 		{
   2555 			throw tcu::ResourceError("Unable to allocate memory!");
   2556 		}
   2557 
   2558 		memcpy(m_tf_varyings_names[i], tf_varying_raw_ptr, strlen(tf_varying_raw_ptr) + 1);
   2559 	}
   2560 
   2561 	m_tf_varyings_names[m_gl_max_tess_evaluation_output_components_value / 4 - 1 /* gl_Position */] =
   2562 		(char*)malloc(sizeof(position_varying));
   2563 	if (m_tf_varyings_names[m_gl_max_tess_evaluation_output_components_value / 4 - 1 /* gl_Position */] == DE_NULL)
   2564 	{
   2565 		throw tcu::ResourceError("Unable to allocate memory!");
   2566 	}
   2567 
   2568 	memcpy(m_tf_varyings_names[m_gl_max_tess_evaluation_output_components_value / 4 - 1 /* gl_Position */],
   2569 		   position_varying, sizeof(position_varying));
   2570 
   2571 	/* Set up XFB */
   2572 	gl.transformFeedbackVaryings(m_po_id_1, m_gl_max_tess_evaluation_output_components_value / 4, m_tf_varyings_names,
   2573 								 GL_INTERLEAVED_ATTRIBS);
   2574 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!");
   2575 
   2576 	/* Set up program objects */
   2577 	const char* vs_code_raw_ptr	= m_vs_code;
   2578 	const char* tcs_code_1_raw_ptr = m_tcs_code_1;
   2579 	const char* tes_code_1_raw_ptr = m_tes_code_1;
   2580 	const char* tcs_code_2_raw_ptr = m_tcs_code_2;
   2581 	const char* tes_code_2_raw_ptr = m_tes_code_2;
   2582 
   2583 	/* Build a program object to test case 1. */
   2584 	if (!TessellationShaderTessellationMaxInOut::buildProgram(m_po_id_1, m_vs_id_1, 1, &vs_code_raw_ptr, m_tcs_id_1, 1,
   2585 															  &tcs_code_1_raw_ptr, m_tes_id_1, 1, &tes_code_1_raw_ptr,
   2586 															  m_fs_id, 1, &m_fs_code))
   2587 	{
   2588 		TCU_FAIL("Could not build first test program object");
   2589 	}
   2590 
   2591 	/* Tranform Feedback setup for case 2 */
   2592 	const char* const tf_varying_2 = "out_value";
   2593 
   2594 	gl.transformFeedbackVaryings(m_po_id_2, 1 /* count */, &tf_varying_2, GL_INTERLEAVED_ATTRIBS);
   2595 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!");
   2596 
   2597 	/* Build a program object for case 2 */
   2598 	if (!(TessellationShaderTessellationMaxInOut::buildProgram(m_po_id_2, m_vs_id_2, 1, &vs_code_raw_ptr, m_tcs_id_2, 1,
   2599 															   &tcs_code_2_raw_ptr, m_tes_id_2, 1, &tes_code_2_raw_ptr,
   2600 															   m_fs_id, 1, &m_fs_code)))
   2601 	{
   2602 		TCU_FAIL("Could not link second test program object");
   2603 	}
   2604 }
   2605 
   2606 /** Initializes the test.
   2607  *
   2608  *  Note the function throws exception should an error occur!
   2609  **/
   2610 void TessellationShaderTessellationMaxInOut::initTest(void)
   2611 {
   2612 	/* Render state setup */
   2613 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2614 
   2615 	/* Skip if required extensions are not supported. */
   2616 	if (!m_is_tessellation_shader_supported)
   2617 	{
   2618 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
   2619 	}
   2620 
   2621 	/* Initialize vertex array object */
   2622 	gl.genVertexArrays(1, &m_vao_id);
   2623 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
   2624 
   2625 	gl.bindVertexArray(m_vao_id);
   2626 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
   2627 
   2628 	/* All tessellation control shaders used by this test assume two
   2629 	 * vertices are going to be provided per input patch. */
   2630 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 2);
   2631 
   2632 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed!");
   2633 
   2634 	/* Carry on with initialization */
   2635 	retrieveGLConstantValues();
   2636 	initProgramObjects();
   2637 	initBufferObjects();
   2638 	initReferenceValues();
   2639 
   2640 	gl.enable(GL_RASTERIZER_DISCARD);
   2641 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(RASTERIZER_DISCARD) failed!");
   2642 }
   2643 
   2644 /** Initializes reference values that will be compared against
   2645  *  values generated by the program object.
   2646  *  Fills m_ref_vertex_attributes and m_ref_patch_attributes arrays.
   2647  *  These arrays are later used by compareValues() function.
   2648  **/
   2649 void TessellationShaderTessellationMaxInOut::initReferenceValues(void)
   2650 {
   2651 	/* Allocate vertex attribute array data needed for reference values preparation. */
   2652 	int max_array_size = de::max(m_gl_max_tess_control_input_components_value,
   2653 								 de::max(m_gl_max_tess_control_output_components_value,
   2654 										 de::max(m_gl_max_tess_evaluation_input_components_value,
   2655 												 m_gl_max_tess_evaluation_output_components_value)));
   2656 
   2657 	m_ref_vertex_attributes = (glw::GLfloat*)malloc(sizeof(glw::GLfloat) * (max_array_size));
   2658 	if (m_ref_vertex_attributes == DE_NULL)
   2659 	{
   2660 		throw tcu::ResourceError("Unable to allocate memory!");
   2661 	}
   2662 
   2663 	/* We need to create an array consisting of gl_max_tess_evaluation_output_components items.
   2664 	 * The array will be filled with the following values:
   2665 	 *
   2666 	 * reference_value[0],
   2667 	 * (...)
   2668 	 * reference_value[gl_max_tess_evaluation_output_components / 4 - 2],
   2669 	 * reference_gl_Position
   2670 	 *
   2671 	 * which corresponds to output block defined for Tessellation Evaluation Stage:
   2672 	 *
   2673 	 * out Vertex
   2674 	 * {
   2675 	 *     vec4 value[(gl_MaxTessControlInputComponents) / 4 - 1];
   2676 	 * } outVertex;
   2677 	 *
   2678 	 * + gl_Position.
   2679 	 */
   2680 	glw::GLfloat sumInTCS[] = { 0.0f, 0.0f, 0.0f, 0.0f };
   2681 	glw::GLfloat sumInTES[] = { 0.0f, 0.0f, 0.0f, 0.0f };
   2682 
   2683 	for (int i = 0; i < m_gl_max_tess_control_input_components_value - 4; /* gl_Position */
   2684 		 i++)
   2685 	{
   2686 		m_ref_vertex_attributes[i] = (glw::GLfloat)i;
   2687 	}
   2688 
   2689 	for (int i = 0; i < m_gl_max_tess_control_input_components_value - 4; /* gl_Position */
   2690 		 i++)
   2691 	{
   2692 		sumInTCS[i % 4 /* component selector */] += m_ref_vertex_attributes[i];
   2693 	}
   2694 
   2695 	for (int i = 0; i < m_gl_max_tess_control_output_components_value - 4; /* gl_Position */
   2696 		 i++)
   2697 	{
   2698 		m_ref_vertex_attributes[i] = sumInTCS[i % 4] + (glw::GLfloat)i;
   2699 	}
   2700 
   2701 	for (int i = m_gl_max_tess_control_input_components_value - 4; /* gl_Position */
   2702 		 i < m_gl_max_tess_control_output_components_value - 4;	/* gl_Position */
   2703 		 i++)
   2704 	{
   2705 		m_ref_vertex_attributes[i] = (glw::GLfloat)i;
   2706 	}
   2707 
   2708 	for (int i = 0; i < m_gl_max_tess_evaluation_input_components_value - 4; /* gl_Position */
   2709 		 i++)
   2710 	{
   2711 		sumInTES[i % 4 /* component selector */] += m_ref_vertex_attributes[i];
   2712 	}
   2713 
   2714 	for (int i = 0; i < m_gl_max_tess_evaluation_output_components_value - 4; /* gl_Position */
   2715 		 i++)
   2716 	{
   2717 		m_ref_vertex_attributes[i] = sumInTES[i % 4 /* component selector */] + (glw::GLfloat)i;
   2718 	}
   2719 
   2720 	for (int i = m_gl_max_tess_evaluation_input_components_value - 4; /* gl_Position */
   2721 		 i < m_gl_max_tess_evaluation_output_components_value - 4;	/* gl_Position */
   2722 		 i++)
   2723 	{
   2724 		m_ref_vertex_attributes[i] = (glw::GLfloat)i;
   2725 	}
   2726 
   2727 	/* Store gl_Position reference values (only first vertex will be compared) */
   2728 	m_ref_vertex_attributes[m_gl_max_tess_evaluation_output_components_value - 4] = 0.0f;
   2729 	m_ref_vertex_attributes[m_gl_max_tess_evaluation_output_components_value - 3] = 0.0f;
   2730 	m_ref_vertex_attributes[m_gl_max_tess_evaluation_output_components_value - 2] = 0.0f;
   2731 	m_ref_vertex_attributes[m_gl_max_tess_evaluation_output_components_value - 1] = 1.0f;
   2732 
   2733 	/* Set up reference data for case 2
   2734 	 *
   2735 	 * Only one output vector will be needed for comparison.
   2736 	 */
   2737 	m_ref_patch_attributes[0] = 0.0f;
   2738 	m_ref_patch_attributes[1] = 0.0f;
   2739 	m_ref_patch_attributes[2] = 0.0f;
   2740 	m_ref_patch_attributes[3] = 0.0f;
   2741 
   2742 	for (int i = 0; i < m_gl_max_tess_patch_components_value; i++)
   2743 	{
   2744 		m_ref_patch_attributes[i % 4] += (glw::GLfloat)i;
   2745 	}
   2746 }
   2747 
   2748 /** Retrieve OpenGL state and implementation values.
   2749  *
   2750  *  Note the function throws exception should an error occur!
   2751  **/
   2752 void TessellationShaderTessellationMaxInOut::retrieveGLConstantValues(void)
   2753 {
   2754 	/* Retrieve ES entry-points. */
   2755 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2756 
   2757 	/* Query implementation constants */
   2758 	gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &m_gl_max_vertex_output_components_value);
   2759 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_VERTEX_OUTPUT_COMPONENTS pname!");
   2760 
   2761 	gl.getIntegerv(m_glExtTokens.MAX_TESS_CONTROL_INPUT_COMPONENTS, &m_gl_max_tess_control_input_components_value);
   2762 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT pname!");
   2763 
   2764 	gl.getIntegerv(m_glExtTokens.MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &m_gl_max_tess_control_output_components_value);
   2765 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT pname!");
   2766 
   2767 	gl.getIntegerv(m_glExtTokens.MAX_TESS_PATCH_COMPONENTS, &m_gl_max_tess_patch_components_value);
   2768 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_PATCH_COMPONENTS_EXT pname!");
   2769 
   2770 	gl.getIntegerv(m_glExtTokens.MAX_TESS_EVALUATION_INPUT_COMPONENTS,
   2771 				   &m_gl_max_tess_evaluation_input_components_value);
   2772 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT pname!");
   2773 
   2774 	gl.getIntegerv(m_glExtTokens.MAX_TESS_EVALUATION_OUTPUT_COMPONENTS,
   2775 				   &m_gl_max_tess_evaluation_output_components_value);
   2776 	GLU_EXPECT_NO_ERROR(gl.getError(),
   2777 						"glGetIntegerv() failed for GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT pname!");
   2778 
   2779 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
   2780 				   &m_gl_max_transform_feedback_interleaved_components_value);
   2781 	GLU_EXPECT_NO_ERROR(gl.getError(),
   2782 						"glGetIntegerv() failed for GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS pname!");
   2783 
   2784 	/* Sanity checks */
   2785 	DE_ASSERT(m_gl_max_vertex_output_components_value != 0);
   2786 	DE_ASSERT(m_gl_max_tess_control_input_components_value != 0);
   2787 	DE_ASSERT(m_gl_max_tess_control_output_components_value != 0);
   2788 	DE_ASSERT(m_gl_max_tess_patch_components_value != 0);
   2789 	DE_ASSERT(m_gl_max_tess_evaluation_input_components_value != 0);
   2790 	DE_ASSERT(m_gl_max_tess_evaluation_output_components_value != 0);
   2791 	DE_ASSERT(m_gl_max_transform_feedback_interleaved_components_value != 0);
   2792 
   2793 	/* Make sure it is possible to transfer all components through all the stages.
   2794 	 * If not, the test may fail, so we throw not supported. */
   2795 	if (m_gl_max_vertex_output_components_value < m_gl_max_tess_control_input_components_value)
   2796 	{
   2797 		m_testCtx.getLog() << tcu::TestLog::Message << "Warning: GL_MAX_VERTEX_OUTPUT_COMPONENTS value:"
   2798 						   << m_gl_max_vertex_output_components_value
   2799 						   << " is less than GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT: "
   2800 						   << m_gl_max_tess_control_input_components_value
   2801 						   << ". It may not be possible to pass all GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT "
   2802 							  "per-vertex components from Vertex Shader to Tessellation Control Shader."
   2803 						   << tcu::TestLog::EndMessage;
   2804 		throw tcu::NotSupportedError("GL_MAX_VERTEX_OUTPUT_COMPONENTS < GL_MAX_TESS_CONTROL_INPUT_COMPONENTS");
   2805 	}
   2806 
   2807 	if (m_gl_max_tess_control_output_components_value != m_gl_max_tess_evaluation_input_components_value)
   2808 	{
   2809 		m_testCtx.getLog() << tcu::TestLog::Message << "Warning: GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT:"
   2810 						   << m_gl_max_tess_control_output_components_value
   2811 						   << " is not equal to GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT:"
   2812 						   << m_gl_max_tess_evaluation_input_components_value
   2813 						   << ". It may not be possible to pass all GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT "
   2814 							  "per-vertex components from Tessellation Control Shader to Tessellation "
   2815 							  "Evaluation Shader."
   2816 						   << tcu::TestLog::EndMessage;
   2817 		throw tcu::NotSupportedError("GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS != "
   2818 									 "GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS");
   2819 	}
   2820 
   2821 	if (m_gl_max_tess_evaluation_output_components_value > m_gl_max_transform_feedback_interleaved_components_value)
   2822 	{
   2823 		m_testCtx.getLog() << tcu::TestLog::Message << "Warning: GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT:"
   2824 						   << m_gl_max_tess_evaluation_output_components_value
   2825 						   << " is greater than GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:"
   2826 						   << m_gl_max_transform_feedback_interleaved_components_value
   2827 						   << ". It may not be possible to check all GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT "
   2828 							  "per-vertex components from Tessellation Evaluation Shader."
   2829 						   << tcu::TestLog::EndMessage;
   2830 		throw tcu::NotSupportedError("GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS > "
   2831 									 "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS");
   2832 	}
   2833 }
   2834 
   2835 /** Maps buffer object storage bound to GL_TRANSFORM_FEEDBACK_BUFFER binding point into process space
   2836  *  and verifies the downloaded data matches the user-provided reference data.
   2837  *
   2838  *  Note the function throws exception should an error occur!
   2839  *
   2840  *  @param description        Case description;
   2841  *  @param reference_values   Array storing reference data;
   2842  *  @param n_reference_values Number of vec4s available for reading under @param reference_values;
   2843  *
   2844  *  @return false if the comparison failed, or true otherwise.
   2845  **/
   2846 bool TessellationShaderTessellationMaxInOut::compareValues(char const* description, glw::GLfloat* reference_values,
   2847 														   int n_reference_values)
   2848 {
   2849 	/* Retrieve ES entry-points */
   2850 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2851 
   2852 	/* Map the buffer storage into process space. */
   2853 	glw::GLint bo_size = static_cast<glw::GLint>(2 /* number of vertices */ * sizeof(glw::GLfloat) *
   2854 												 n_reference_values * 4); /* number of components */
   2855 	glw::GLfloat* resultFloats =
   2856 		(glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_size, GL_MAP_READ_BIT);
   2857 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed");
   2858 
   2859 	/* Verify the data */
   2860 	const glw::GLfloat epsilon	 = (glw::GLfloat)1e-5f;
   2861 	bool			   test_passed = true;
   2862 
   2863 	for (int i = 0; i < n_reference_values * 4 /* number of components */; i += 4 /* number of components */)
   2864 	{
   2865 		if ((de::abs(resultFloats[i] - reference_values[i]) > epsilon) ||
   2866 			(de::abs(resultFloats[i + 1] - reference_values[i + 1]) > epsilon) ||
   2867 			(de::abs(resultFloats[i + 2] - reference_values[i + 2]) > epsilon) ||
   2868 			(de::abs(resultFloats[i + 3] - reference_values[i + 3]) > epsilon))
   2869 		{
   2870 			m_testCtx.getLog() << tcu::TestLog::Message << description << ": captured results "
   2871 							   << "vec4(" << resultFloats[i + 0] << ", " << resultFloats[i + 1] << ", "
   2872 							   << resultFloats[i + 2] << ", " << resultFloats[i + 3] << ") "
   2873 							   << "are different from the expected values "
   2874 							   << "vec4(" << reference_values[i + 0] << ", " << reference_values[i + 1] << ", "
   2875 							   << reference_values[i + 2] << ", " << reference_values[i + 3] << ")."
   2876 							   << tcu::TestLog::EndMessage;
   2877 
   2878 			test_passed = false;
   2879 			break;
   2880 		}
   2881 	}
   2882 
   2883 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   2884 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed!");
   2885 
   2886 	return test_passed;
   2887 }
   2888 
   2889 } /* namespace glcts */
   2890