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 "esextcTessellationShaderInvariance.hpp"
     25 #include "gluContextInfo.hpp"
     26 #include "gluDefs.hpp"
     27 #include "glwEnums.hpp"
     28 #include "glwFunctions.hpp"
     29 #include "tcuTestLog.hpp"
     30 
     31 namespace glcts
     32 {
     33 
     34 /* Defines a single vertex in tessellation space */
     35 typedef struct _vertex
     36 {
     37 	float u;
     38 	float v;
     39 	float w;
     40 
     41 	_vertex()
     42 	{
     43 		u = 0.0f;
     44 		v = 0.0f;
     45 		w = 0.0f;
     46 	}
     47 } _vertex;
     48 
     49 /** Constructor
     50  *
     51  * @param context Test context
     52  **/
     53 TessellationShaderInvarianceTests::TessellationShaderInvarianceTests(glcts::Context&	  context,
     54 																	 const ExtParameters& extParams)
     55 	: TestCaseGroupBase(context, extParams, "tessellation_invariance",
     56 						"Verifies the implementation conforms to invariance rules.")
     57 {
     58 	/* No implementation needed */
     59 }
     60 
     61 /**
     62  * Initializes test groups for geometry shader tests
     63  **/
     64 void TessellationShaderInvarianceTests::init(void)
     65 {
     66 	addChild(new glcts::TessellationShaderInvarianceRule1Test(m_context, m_extParams));
     67 	addChild(new glcts::TessellationShaderInvarianceRule2Test(m_context, m_extParams));
     68 	addChild(new glcts::TessellationShaderInvarianceRule3Test(m_context, m_extParams));
     69 	addChild(new glcts::TessellationShaderInvarianceRule4Test(m_context, m_extParams));
     70 	addChild(new glcts::TessellationShaderInvarianceRule5Test(m_context, m_extParams));
     71 	addChild(new glcts::TessellationShaderInvarianceRule6Test(m_context, m_extParams));
     72 	addChild(new glcts::TessellationShaderInvarianceRule7Test(m_context, m_extParams));
     73 }
     74 
     75 /** Constructor
     76  *
     77  * @param context     Test context
     78  * @param name        Test name
     79  * @param description Test description
     80  **/
     81 TessellationShaderInvarianceBaseTest::TessellationShaderInvarianceBaseTest(Context&				context,
     82 																		   const ExtParameters& extParams,
     83 																		   const char* name, const char* description)
     84 	: TestCaseBase(context, extParams, name, description)
     85 	, m_utils_ptr(DE_NULL)
     86 	, m_bo_id(0)
     87 	, m_qo_tfpw_id(0)
     88 	, m_vao_id(0)
     89 {
     90 	/* Left blank on purpose */
     91 }
     92 
     93 /** Deinitializes ES objects created for the test. */
     94 void TessellationShaderInvarianceBaseTest::deinit()
     95 {
     96 	/* Call base class' deinit() */
     97 	TestCaseBase::deinit();
     98 
     99 	if (!m_is_tessellation_shader_supported)
    100 	{
    101 		return;
    102 	}
    103 
    104 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    105 
    106 	/* Revert buffer object bindings */
    107 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
    108 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
    109 
    110 	/* Disable GL_RASTERIZER_DISCARD mode */
    111 	gl.disable(GL_RASTERIZER_DISCARD);
    112 
    113 	/* Reset GL_PATCH_VERTICES_EXT to default value */
    114 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
    115 
    116 	/* Unbind vertex array object */
    117 	gl.bindVertexArray(0);
    118 
    119 	/* Deinitialize all ES objects that were created for test purposes */
    120 	if (m_bo_id != 0)
    121 	{
    122 		gl.deleteBuffers(1, &m_bo_id);
    123 
    124 		m_bo_id = 0;
    125 	}
    126 
    127 	for (_programs_iterator it = m_programs.begin(); it != m_programs.end(); ++it)
    128 	{
    129 		_test_program& program = *it;
    130 
    131 		if (program.po_id != 0)
    132 		{
    133 			gl.deleteProgram(program.po_id);
    134 		}
    135 	}
    136 	m_programs.clear();
    137 
    138 	if (m_qo_tfpw_id != 0)
    139 	{
    140 		gl.deleteQueries(1, &m_qo_tfpw_id);
    141 
    142 		m_qo_tfpw_id = 0;
    143 	}
    144 
    145 	if (m_vao_id != 0)
    146 	{
    147 		gl.deleteVertexArrays(1, &m_vao_id);
    148 
    149 		m_vao_id = 0;
    150 	}
    151 
    152 	/* Deinitialize TS utils instance */
    153 	if (m_utils_ptr != NULL)
    154 	{
    155 		delete m_utils_ptr;
    156 
    157 		m_utils_ptr = NULL;
    158 	}
    159 }
    160 
    161 /** Executes a single-counted GL_PATCHES_EXT draw call.
    162  *
    163  *  Throws TestError exception if an error occurs.
    164  *
    165  *  @param n_iteration Not used.
    166  *
    167  **/
    168 void TessellationShaderInvarianceBaseTest::executeDrawCall(unsigned int n_iteration)
    169 {
    170 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    171 
    172 	DE_UNREF(n_iteration);
    173 
    174 	gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, getDrawCallCountArgument());
    175 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
    176 }
    177 
    178 /** Returns a value that should be used for the draw call's "count" argument.
    179  *
    180  *  @param Always 1
    181  **/
    182 unsigned int TessellationShaderInvarianceBaseTest::getDrawCallCountArgument()
    183 {
    184 	return 1;
    185 }
    186 
    187 /** Returns source code for fragment shader stage which does
    188  *  not do anything.
    189  *
    190  *  @param n_iteration Not used.
    191  *
    192  *  @return Requested string.
    193  **/
    194 std::string TessellationShaderInvarianceBaseTest::getFSCode(unsigned int n_iteration)
    195 {
    196 	DE_UNREF(n_iteration);
    197 
    198 	std::string result = "${VERSION}\n"
    199 						 "\n"
    200 						 "void main()\n"
    201 						 "{\n"
    202 						 "}\n";
    203 
    204 	return result;
    205 }
    206 
    207 /** Retrieves name of a vec2 uniform that stores inner tesselaton level information,
    208  *  later assigned to gl_TessLevelInner in tessellation evaluation shader.
    209  *
    210  *  @return Requested name.
    211  **/
    212 const char* TessellationShaderInvarianceBaseTest::getInnerTessLevelUniformName()
    213 {
    214 	static const char* result = "inner_tess_level";
    215 
    216 	return result;
    217 }
    218 
    219 /** Retrieves name of a vec4 uniform that stores outer tesselation level information,
    220  *  later assigned to gl_TessLevelOuter in tessellation evaluation shader.
    221  *
    222  *  @return Requested name.
    223  **/
    224 const char* TessellationShaderInvarianceBaseTest::getOuterTessLevelUniformName()
    225 {
    226 	static const char* result = "outer_tess_level";
    227 
    228 	return result;
    229 }
    230 
    231 /** Returns generic tessellation control shader code, which sends 4 output patch
    232  *  to tessellation evaluation shader stage and uses the very first input patch
    233  *  vertex only.
    234  *
    235  *  @return Tessellation control source code.
    236  */
    237 std::string TessellationShaderInvarianceBaseTest::getTCCode(unsigned int n_iteration)
    238 {
    239 	DE_UNREF(n_iteration);
    240 
    241 	/* In order to support all three primitive types, our generic tessellation
    242 	 * control shader will pass 4 vertices to TE stage */
    243 	return TessellationShaderUtils::getGenericTCCode(4, /* n_patch_vertices */
    244 													 false);
    245 }
    246 
    247 /** Retrieves XFB properties for the test pass.
    248  *
    249  *  @param n_iteration Not used.
    250  *  @param out_n_names Deref will be used to store amount of strings @param *out_n_names
    251  *                     offers.
    252  *  @param out_names   Deref will be used to store pointer to an array of strings holding
    253  *                     names of varyings that should be captured via transform feedback.
    254  *                     Must not be NULL.
    255  *
    256  **/
    257 void TessellationShaderInvarianceBaseTest::getXFBProperties(unsigned int n_iteration, unsigned int* out_n_names,
    258 															const char*** out_names)
    259 {
    260 	static const char* names[] = { "result_uvw" };
    261 
    262 	DE_UNREF(n_iteration);
    263 
    264 	*out_n_names = 1;
    265 	*out_names   = names;
    266 }
    267 
    268 /** Returns vertex shader source code. The shader sets gl_Position to
    269  *  vec4(1, 2, 3, 0).
    270  *
    271  *  @return Vertex shader source code.
    272  **/
    273 std::string TessellationShaderInvarianceBaseTest::getVSCode(unsigned int n_iteration)
    274 {
    275 	DE_UNREF(n_iteration);
    276 
    277 	std::string result = "${VERSION}\n"
    278 						 "\n"
    279 						 "void main()\n"
    280 						 "{\n"
    281 						 "    gl_Position = vec4(1.0, 2.0, 3.0, 0.0);\n"
    282 						 "}\n";
    283 
    284 	return result;
    285 }
    286 
    287 /** Initializes ES objects required to execute the test.
    288  *
    289  *  Throws TestError exception if an error occurs.
    290  *
    291  **/
    292 void TessellationShaderInvarianceBaseTest::initTest()
    293 {
    294 	const glw::Functions& gl		   = m_context.getRenderContext().getFunctions();
    295 	glw::GLuint			  shared_fs_id = 0;
    296 	glw::GLuint			  shared_tc_id = 0;
    297 	glw::GLuint			  shared_te_id = 0;
    298 	glw::GLuint			  shared_vs_id = 0;
    299 
    300 	gl.genVertexArrays(1, &m_vao_id);
    301 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
    302 
    303 	gl.bindVertexArray(m_vao_id);
    304 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
    305 
    306 	/* Initialize GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query object */
    307 	gl.genQueries(1, &m_qo_tfpw_id);
    308 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed");
    309 
    310 	/* Initialize tessellation shader utils */
    311 	m_utils_ptr = new TessellationShaderUtils(gl, this);
    312 
    313 	/* Initialize a buffer object we will use to store XFB data.
    314 	 * Note: we intentionally skip a glBufferData() call here,
    315 	 *       the actual buffer storage size is iteration-specific.
    316 	 **/
    317 	gl.genBuffers(1, &m_bo_id);
    318 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
    319 
    320 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
    321 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
    322 
    323 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
    324 					  m_bo_id);
    325 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
    326 
    327 	/* Iterate through all iterations */
    328 	const unsigned int n_iterations = getAmountOfIterations();
    329 	m_programs.reserve(n_iterations);
    330 
    331 	const glw::GLenum SHADER_TYPE_FRAGMENT				  = GL_FRAGMENT_SHADER;
    332 	const glw::GLenum SHADER_TYPE_TESSELLATION_CONTROL	= m_glExtTokens.TESS_CONTROL_SHADER;
    333 	const glw::GLenum SHADER_TYPE_TESSELLATION_EVALUATION = m_glExtTokens.TESS_EVALUATION_SHADER;
    334 	const glw::GLenum SHADER_TYPE_VERTEX				  = GL_VERTEX_SHADER;
    335 
    336 	for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration)
    337 	{
    338 		_test_program program;
    339 
    340 		/* Create an iteration-specific program object */
    341 		program.po_id = gl.createProgram();
    342 
    343 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
    344 
    345 		/* Query the implementation on which shader types should be compiled on
    346 		 * a per-iteration basis, and which can be initialized only once */
    347 		static const glw::GLenum shader_types[] = { SHADER_TYPE_FRAGMENT, SHADER_TYPE_TESSELLATION_CONTROL,
    348 													SHADER_TYPE_TESSELLATION_EVALUATION, SHADER_TYPE_VERTEX };
    349 		static const unsigned int n_shader_types = sizeof(shader_types) / sizeof(shader_types[0]);
    350 
    351 		for (unsigned int n_shader_type = 0; n_shader_type < n_shader_types; ++n_shader_type)
    352 		{
    353 			std::string shader_body;
    354 			const char* shader_body_ptr = DE_NULL;
    355 			glw::GLuint shader_id		= 0;
    356 			glw::GLenum shader_type		= shader_types[n_shader_type];
    357 			glw::GLenum shader_type_es  = (glw::GLenum)shader_type;
    358 
    359 			// Check whether the test should use a separate program objects for each iteration.
    360 			bool is_shader_iteration_specific = false;
    361 			if (shader_type == SHADER_TYPE_TESSELLATION_EVALUATION)
    362 			{
    363 				is_shader_iteration_specific = true;
    364 			}
    365 			else if ((shader_type != SHADER_TYPE_FRAGMENT) && (shader_type != SHADER_TYPE_TESSELLATION_CONTROL) &&
    366 					 (shader_type != SHADER_TYPE_VERTEX))
    367 			{
    368 				TCU_FAIL("Unrecognized shader type");
    369 			}
    370 
    371 			/* We need to initialize the shader object if:
    372 			 *
    373 			 * - its body differs between iterations;
    374 			 * - its body is shared by all iterations AND this is the first iteration
    375 			 */
    376 			bool has_shader_been_generated = false;
    377 
    378 			if ((!is_shader_iteration_specific && n_iteration == 0) || is_shader_iteration_specific)
    379 			{
    380 				/* Create the shader object */
    381 				has_shader_been_generated = true;
    382 				shader_id				  = gl.createShader(shader_type_es);
    383 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
    384 
    385 				/* Assign shader body to the object */
    386 				if (shader_type == SHADER_TYPE_FRAGMENT)
    387 				{
    388 					shader_body = getFSCode(n_iteration);
    389 				}
    390 				else if (shader_type == SHADER_TYPE_TESSELLATION_CONTROL)
    391 				{
    392 					shader_body = getTCCode(n_iteration);
    393 				}
    394 				else if (shader_type == SHADER_TYPE_TESSELLATION_EVALUATION)
    395 				{
    396 					shader_body = getTECode(n_iteration);
    397 				}
    398 				else if (shader_type == SHADER_TYPE_VERTEX)
    399 				{
    400 					shader_body = getVSCode(n_iteration);
    401 				}
    402 				else
    403 				{
    404 					TCU_FAIL("Unrecognized shader type");
    405 				}
    406 
    407 				shader_body_ptr = shader_body.c_str();
    408 
    409 				shaderSourceSpecialized(shader_id, 1, &shader_body_ptr);
    410 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
    411 
    412 				/* Compile the shader object */
    413 				m_utils_ptr->compileShaders(1,				   /* n_shaders */
    414 											&shader_id, true); /* should_succeed */
    415 
    416 				/* If this is a shader object that will be shared by all iterations, cache it
    417 				 * in a dedicated variable */
    418 				if (!is_shader_iteration_specific)
    419 				{
    420 					if (shader_type == SHADER_TYPE_FRAGMENT)
    421 					{
    422 						shared_fs_id = shader_id;
    423 					}
    424 					else if (shader_type == SHADER_TYPE_TESSELLATION_CONTROL)
    425 					{
    426 						shared_tc_id = shader_id;
    427 					}
    428 					else if (shader_type == SHADER_TYPE_TESSELLATION_EVALUATION)
    429 					{
    430 						shared_te_id = shader_id;
    431 					}
    432 					else if (shader_type == SHADER_TYPE_VERTEX)
    433 					{
    434 						shared_vs_id = shader_id;
    435 					}
    436 					else
    437 					{
    438 						TCU_FAIL("Unrecognized shader type");
    439 					}
    440 				} /* if (!is_shader_iteration_specific) */
    441 			}	 /* if (shader object needs to be initialized) */
    442 			else
    443 			{
    444 				shader_id = (shader_type == SHADER_TYPE_FRAGMENT) ?
    445 								shared_fs_id :
    446 								(shader_type == SHADER_TYPE_TESSELLATION_CONTROL) ?
    447 								shared_tc_id :
    448 								(shader_type == SHADER_TYPE_TESSELLATION_EVALUATION) ? shared_te_id : shared_vs_id;
    449 			}
    450 
    451 			/* Attach the shader object to iteration-specific program object */
    452 			gl.attachShader(program.po_id, shader_id);
    453 
    454 			GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
    455 
    456 			/* Now that the object has been attached, we can flag it for deletion */
    457 			if (has_shader_been_generated)
    458 			{
    459 				gl.deleteShader(shader_id);
    460 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed");
    461 			}
    462 		} /* for (all shader types) */
    463 
    464 		/* Set up transform feed-back */
    465 		unsigned int n_xfb_names = 0;
    466 		const char** xfb_names   = NULL;
    467 
    468 		getXFBProperties(n_iteration, &n_xfb_names, &xfb_names);
    469 
    470 		gl.transformFeedbackVaryings(program.po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
    471 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
    472 
    473 		/* Try to link the program object */
    474 		glw::GLint link_status = GL_FALSE;
    475 
    476 		gl.linkProgram(program.po_id);
    477 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
    478 
    479 		gl.getProgramiv(program.po_id, GL_LINK_STATUS, &link_status);
    480 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
    481 
    482 		if (link_status != GL_TRUE)
    483 		{
    484 			TCU_FAIL("Program linking failed");
    485 		}
    486 
    487 		/* Retrieve inner/outer tess level uniform locations */
    488 		program.inner_tess_level_uniform_location =
    489 			gl.getUniformLocation(program.po_id, getInnerTessLevelUniformName());
    490 		program.outer_tess_level_uniform_location =
    491 			gl.getUniformLocation(program.po_id, getOuterTessLevelUniformName());
    492 
    493 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed");
    494 
    495 		/* Store the program object */
    496 		m_programs.push_back(program);
    497 	} /* for (all iterations) */
    498 }
    499 
    500 /** Executes the test.
    501  *
    502  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    503  *
    504  *  Note the function throws exception should an error occur!
    505  *
    506  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
    507  **/
    508 tcu::TestNode::IterateResult TessellationShaderInvarianceBaseTest::iterate(void)
    509 {
    510 	/* Do not execute if required extensions are not supported. */
    511 	if (!m_is_tessellation_shader_supported)
    512 	{
    513 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    514 	}
    515 
    516 	/* Initialize all objects needed to run the test */
    517 	initTest();
    518 
    519 	/* Do a general set-up */
    520 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    521 
    522 	gl.enable(GL_RASTERIZER_DISCARD);
    523 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed.");
    524 
    525 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
    526 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname");
    527 
    528 	/* There are two types of verification supported by this base test implementation:
    529 	 *
    530 	 * - iteration-specific (verifyResultDataForIteration() )
    531 	 * - global             (verifyResultData() )
    532 	 *
    533 	 * It is up to test implementation to decide which of the two (or perhaps both)
    534 	 * entry-points it should overload and use for validating the result data.
    535 	 */
    536 	const unsigned int n_iterations   = getAmountOfIterations();
    537 	char**			   iteration_data = new char*[n_iterations];
    538 
    539 	/* Execute the test */
    540 	for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration)
    541 	{
    542 		_test_program& program = m_programs[n_iteration];
    543 
    544 		/* Retrieve iteration properties for current iteration */
    545 		unsigned int						 bo_size			  = 0;
    546 		float								 inner_tess_levels[2] = { 0 };
    547 		bool								 is_point_mode		  = false;
    548 		float								 outer_tess_levels[4] = { 0 };
    549 		_tessellation_primitive_mode		 primitive_mode		  = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
    550 		_tessellation_shader_vertex_ordering vertex_ordering	  = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN;
    551 
    552 		getIterationProperties(n_iteration, inner_tess_levels, outer_tess_levels, &is_point_mode, &primitive_mode,
    553 							   &vertex_ordering, &bo_size);
    554 
    555 		DE_ASSERT(bo_size != 0);
    556 
    557 		/* Activate iteration-specific program */
    558 		gl.useProgram(program.po_id);
    559 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed.");
    560 
    561 		/* Set up buffer object storage */
    562 		{
    563 			char* zero_bo_data = new char[bo_size];
    564 
    565 			memset(zero_bo_data, 0, bo_size);
    566 
    567 			gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, zero_bo_data, GL_STATIC_DRAW);
    568 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
    569 
    570 			delete[] zero_bo_data;
    571 			zero_bo_data = NULL;
    572 		}
    573 
    574 		/* Allocate space for iteration-specific data */
    575 		iteration_data[n_iteration] = new char[bo_size];
    576 
    577 		/* Configure inner/outer tessellation levels as requested for the iteration */
    578 		gl.uniform2fv(program.inner_tess_level_uniform_location, 1, /* count */
    579 					  inner_tess_levels);
    580 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2fv() call failed");
    581 
    582 		gl.uniform4fv(program.outer_tess_level_uniform_location, 1, /* count */
    583 					  outer_tess_levels);
    584 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed");
    585 
    586 		/* Launch the TFPW query */
    587 		gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_qo_tfpw_id);
    588 		GLU_EXPECT_NO_ERROR(gl.getError(),
    589 							"glBeginQuery() for GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN target failed.");
    590 
    591 		/* Prepare for TF */
    592 		glw::GLenum tf_mode = TessellationShaderUtils::getTFModeForPrimitiveMode(primitive_mode, is_point_mode);
    593 
    594 		gl.beginTransformFeedback(tf_mode);
    595 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
    596 		{
    597 			/* Execute the draw call */
    598 			executeDrawCall(n_iteration);
    599 
    600 			GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed");
    601 		}
    602 		gl.endTransformFeedback();
    603 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
    604 
    605 		gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
    606 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) call failed");
    607 
    608 		/* Make sure that we had sufficient amount of space in a buffer object we used to
    609 		 * capture XFB data.
    610 		 **/
    611 		glw::GLuint n_tf_primitives_written = 0;
    612 		glw::GLuint used_tf_bo_size			= 0;
    613 
    614 		gl.getQueryObjectuiv(m_qo_tfpw_id, GL_QUERY_RESULT, &n_tf_primitives_written);
    615 		GLU_EXPECT_NO_ERROR(gl.getError(),
    616 							"Could not retrieve GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query object result");
    617 
    618 		if (is_point_mode)
    619 		{
    620 			used_tf_bo_size = static_cast<glw::GLuint>(n_tf_primitives_written * sizeof(float) * 3 /* components */);
    621 		}
    622 		else if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES)
    623 		{
    624 			used_tf_bo_size = static_cast<glw::GLuint>(n_tf_primitives_written * sizeof(float) * 2 /* vertices */ *
    625 													   3 /* components */);
    626 		}
    627 		else
    628 		{
    629 			used_tf_bo_size = static_cast<glw::GLuint>(n_tf_primitives_written * sizeof(float) * 3 /* vertices */ *
    630 													   3 /* components */);
    631 		}
    632 
    633 		if (used_tf_bo_size != bo_size)
    634 		{
    635 			m_testCtx.getLog() << tcu::TestLog::Message << "Expected " << bo_size
    636 							   << " to be filled with tessellation data, "
    637 								  "only "
    638 							   << used_tf_bo_size << "was used." << tcu::TestLog::EndMessage;
    639 
    640 			TCU_FAIL("Amount of primitives generated during TF does not match amount of primitives that were expected"
    641 					 " to be generated by the tessellator");
    642 		}
    643 
    644 		/* Map the buffer object we earlier bound to GL_TRANSFORM_FEEDBACK_BUFFER
    645 		 * target into process space. */
    646 		const void* xfb_data = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
    647 												 bo_size, GL_MAP_READ_BIT);
    648 
    649 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
    650 
    651 		memcpy(iteration_data[n_iteration], xfb_data, bo_size);
    652 
    653 		/* Unmap the buffer object */
    654 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
    655 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
    656 
    657 		/* Ask the test implementation to verify the results */
    658 		verifyResultDataForIteration(n_iteration, iteration_data[n_iteration]);
    659 	} /* for (all iterations) */
    660 
    661 	/* Now that we've executed all iterations, we can call a global verification
    662 	 * entry-point */
    663 	verifyResultData((const void**)iteration_data);
    664 
    665 	/* At this point we're safe to release space allocated for data coming from
    666 	 * all the iterations */
    667 	for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration)
    668 	{
    669 		char* iter_data = (char*)iteration_data[n_iteration];
    670 		delete[] iter_data;
    671 
    672 		iteration_data[n_iteration] = DE_NULL;
    673 	} /* for (all iterations) */
    674 
    675 	delete[] iteration_data;
    676 	iteration_data = DE_NULL;
    677 
    678 	/* All done */
    679 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    680 	return STOP;
    681 }
    682 
    683 /* Does nothing (stub implementation)
    684  *
    685  * @param n_iteration Not used.
    686  * @param data        Not used.
    687  *
    688  **/
    689 void TessellationShaderInvarianceBaseTest::verifyResultDataForIteration(unsigned int n_iteration, const void* data)
    690 {
    691 	DE_UNREF(n_iteration && data);
    692 
    693 	/* Do nothing - this is just a stub. */
    694 }
    695 
    696 /* Does nothing (stub implementation)
    697  *
    698  * @param all_iterations_data Not used.
    699  *
    700  **/
    701 void TessellationShaderInvarianceBaseTest::verifyResultData(const void** all_iterations_data)
    702 {
    703 	DE_UNREF(all_iterations_data);
    704 
    705 	/* Do nothing - this is just a stub. */
    706 }
    707 
    708 /** Constructor.
    709  *
    710  *  @param context Rendering context.
    711  *
    712  **/
    713 TessellationShaderInvarianceRule1Test::TessellationShaderInvarianceRule1Test(Context&			  context,
    714 																			 const ExtParameters& extParams)
    715 	: TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule1",
    716 										   "Verifies conformance with first invariance rule")
    717 {
    718 	/* Left blank intentionally */
    719 }
    720 
    721 /** Destructor. */
    722 TessellationShaderInvarianceRule1Test::~TessellationShaderInvarianceRule1Test()
    723 {
    724 	/* Left blank intentionally */
    725 }
    726 
    727 /** Retrieves amount of iterations the base test implementation should run before
    728  *  calling global verification routine.
    729  *
    730  *  @return Always 6.
    731  **/
    732 unsigned int TessellationShaderInvarianceRule1Test::getAmountOfIterations()
    733 {
    734 	return 6;
    735 }
    736 
    737 /** Returns a value that should be used for the draw call's "count" argument.
    738  *
    739  *  @param Always 3
    740  **/
    741 unsigned int TessellationShaderInvarianceRule1Test::getDrawCallCountArgument()
    742 {
    743 	return 3;
    744 }
    745 
    746 /** Retrieves iteration-specific tessellation properties.
    747  *
    748  *  @param n_iteration            Iteration index to retrieve the properties for.
    749  *  @param out_inner_tess_levels  Deref will be used to store iteration-specific inner
    750  *                                tessellation level values. Must not be NULL.
    751  *  @param out_outer_tess_levels  Deref will be used to store iteration-specific outer
    752  *                                tessellation level values. Must not be NULL.
    753  *  @param out_point_mode         Deref will be used to store iteration-specific flag
    754  *                                telling whether point mode should be enabled for given pass.
    755  *                                Must not be NULL.
    756  *  @param out_primitive_mode     Deref will be used to store iteration-specific primitive
    757  *                                mode. Must not be NULL.
    758  *  @param out_vertex_ordering    Deref will be used to store iteration-specific vertex ordering.
    759  *                                Must not be NULL.
    760  *  @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object
    761  *                                storage should offer for the draw call to succeed. Must not
    762  *                                be NULL.
    763  **/
    764 void TessellationShaderInvarianceRule1Test::getIterationProperties(
    765 	unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode,
    766 	_tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering,
    767 	unsigned int* out_result_buffer_size)
    768 {
    769 	*out_vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_CCW;
    770 
    771 	switch (n_iteration)
    772 	{
    773 	case 0:
    774 	case 5:
    775 	{
    776 		/* Triangles (point mode) */
    777 		out_inner_tess_levels[0] = 1.0f;
    778 		out_outer_tess_levels[0] = 1.0f;
    779 		out_outer_tess_levels[1] = 1.0f;
    780 		out_outer_tess_levels[2] = 1.0f;
    781 
    782 		*out_point_mode		= true;
    783 		*out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES;
    784 
    785 		break;
    786 	}
    787 
    788 	case 1:
    789 	case 3:
    790 	{
    791 		/* Lines */
    792 		out_outer_tess_levels[0] = 1.0f;
    793 		out_outer_tess_levels[1] = 1.0f;
    794 
    795 		*out_point_mode		= false;
    796 		*out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES;
    797 
    798 		break;
    799 	}
    800 
    801 	case 2:
    802 	case 4:
    803 	{
    804 		/* Triangles */
    805 		out_inner_tess_levels[0] = 1.0f;
    806 		out_outer_tess_levels[0] = 1.0f;
    807 		out_outer_tess_levels[1] = 1.0f;
    808 		out_outer_tess_levels[2] = 1.0f;
    809 
    810 		*out_point_mode		= false;
    811 		*out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES;
    812 
    813 		break;
    814 	}
    815 
    816 	default:
    817 	{
    818 		TCU_FAIL("Unrecognzied iteration index");
    819 	}
    820 	}
    821 
    822 	*out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
    823 		*out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
    824 		*out_point_mode);
    825 
    826 	*out_result_buffer_size = static_cast<unsigned int>(*out_result_buffer_size * getDrawCallCountArgument() *
    827 														3 /* components */ * sizeof(float));
    828 
    829 	DE_ASSERT(*out_result_buffer_size != 0);
    830 }
    831 
    832 /** Retrieves iteration-specific tessellation evaluation shader code.
    833  *
    834  *  @param n_iteration Iteration index, for which the source code is being obtained.
    835  *
    836  *  @return Requested source code.
    837  **/
    838 std::string TessellationShaderInvarianceRule1Test::getTECode(unsigned int n_iteration)
    839 {
    840 	unsigned int						 bo_size			  = 0;
    841 	float								 inner_tess_levels[2] = { 0 };
    842 	float								 outer_tess_levels[4] = { 0 };
    843 	bool								 point_mode			  = false;
    844 	_tessellation_primitive_mode		 primitive_mode		  = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
    845 	_tessellation_shader_vertex_ordering vertex_ordering	  = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN;
    846 
    847 	getIterationProperties(n_iteration, inner_tess_levels, outer_tess_levels, &point_mode, &primitive_mode,
    848 						   &vertex_ordering, &bo_size);
    849 
    850 	return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, primitive_mode,
    851 													 vertex_ordering, point_mode);
    852 }
    853 
    854 /** Verifies result data. Accesses data generated by all iterations.
    855  *
    856  *  Throws TestError exception if an error occurs.
    857  *
    858  *  @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord
    859  *                             data generated by subsequent iterations.
    860  **/
    861 void TessellationShaderInvarianceRule1Test::verifyResultData(const void** all_iterations_data)
    862 {
    863 	const float* lines_vertex_data_1 = (const float*)all_iterations_data[1];
    864 	const float* lines_vertex_data_2 = (const float*)all_iterations_data[3];
    865 	const float* point_vertex_data_1 = (const float*)all_iterations_data[0];
    866 	const float* point_vertex_data_2 = (const float*)all_iterations_data[5];
    867 	const float* tris_vertex_data_1  = (const float*)all_iterations_data[2];
    868 	const float* tris_vertex_data_2  = (const float*)all_iterations_data[4];
    869 
    870 	const unsigned int n_line_vertices  = 2 /* vertices per line segment */ * getDrawCallCountArgument(); /* lines */
    871 	const unsigned int n_point_vertices = 1 /* vertices per point */ * getDrawCallCountArgument();		  /* points */
    872 	const unsigned int n_tri_vertices   = 3 /* vertices per triangle */ * getDrawCallCountArgument(); /* triangles */
    873 	const unsigned int vertex_size		= sizeof(float) * 3;										  /* components */
    874 
    875 	/* Make sure the data sets match, given different draw call ordering */
    876 	for (int n_type = 0; n_type < 3 /* lines, points, tris */; ++n_type)
    877 	{
    878 		const float* data1_ptr = DE_NULL;
    879 		const float* data2_ptr = DE_NULL;
    880 		std::string  data_type_string;
    881 		unsigned int n_vertices = 0;
    882 
    883 		switch (n_type)
    884 		{
    885 		case 0:
    886 		{
    887 			data1_ptr		 = lines_vertex_data_1;
    888 			data2_ptr		 = lines_vertex_data_2;
    889 			data_type_string = "Line";
    890 			n_vertices		 = n_line_vertices;
    891 
    892 			break;
    893 		}
    894 
    895 		case 1:
    896 		{
    897 			data1_ptr		 = point_vertex_data_1;
    898 			data2_ptr		 = point_vertex_data_2;
    899 			data_type_string = "Point";
    900 			n_vertices		 = n_point_vertices;
    901 
    902 			break;
    903 		}
    904 
    905 		case 2:
    906 		{
    907 			data1_ptr		 = tris_vertex_data_1;
    908 			data2_ptr		 = tris_vertex_data_2;
    909 			data_type_string = "Triangle";
    910 			n_vertices		 = n_tri_vertices;
    911 
    912 			break;
    913 		}
    914 
    915 		default:
    916 		{
    917 			TCU_FAIL("Internal error: type index was not recognized");
    918 		}
    919 		} /* switch (n_type) */
    920 
    921 		/* Make sure the buffer storage in both cases has been modified */
    922 		{
    923 			unsigned int zero_bo_size = vertex_size * n_vertices;
    924 			char*		 zero_bo_data = new char[vertex_size * n_vertices];
    925 
    926 			memset(zero_bo_data, 0, zero_bo_size);
    927 
    928 			if (memcmp(data1_ptr, zero_bo_data, zero_bo_size) == 0 ||
    929 				memcmp(data2_ptr, zero_bo_data, zero_bo_size) == 0)
    930 			{
    931 				TCU_FAIL("One of the draw calls has not outputted any data to XFB buffer object storage");
    932 			}
    933 
    934 			delete[] zero_bo_data;
    935 			zero_bo_data = NULL;
    936 		}
    937 
    938 		/* Compare the data */
    939 		if (memcmp(data1_ptr, data2_ptr, vertex_size * n_vertices) != 0)
    940 		{
    941 			std::stringstream logMessage;
    942 
    943 			logMessage << data_type_string << " data rendered in pass 1: (";
    944 
    945 			for (unsigned int n_vertex = 0; n_vertex < n_vertices; ++n_vertex)
    946 			{
    947 				logMessage << data1_ptr[n_vertex];
    948 
    949 				if (n_vertex != (n_vertices - 1))
    950 				{
    951 					logMessage << ", ";
    952 				}
    953 				else
    954 				{
    955 					logMessage << ") ";
    956 				}
    957 			} /* for (all vertices) */
    958 
    959 			logMessage << "and in pass 2: (";
    960 
    961 			for (unsigned int n_vertex = 0; n_vertex < n_vertices; ++n_vertex)
    962 			{
    963 				logMessage << data2_ptr[n_vertex];
    964 
    965 				if (n_vertex != (n_vertices - 1))
    966 				{
    967 					logMessage << ", ";
    968 				}
    969 				else
    970 				{
    971 					logMessage << ") ";
    972 				}
    973 			} /* for (all vertices) */
    974 
    975 			logMessage << "do not match";
    976 
    977 			m_testCtx.getLog() << tcu::TestLog::Message << logMessage.str().c_str() << tcu::TestLog::EndMessage;
    978 
    979 			TCU_FAIL("Data mismatch");
    980 		} /* if (data mismatch) */
    981 	}	 /* for (all primitive types) */
    982 }
    983 
    984 /** Constructor.
    985  *
    986  *  @param context Rendering context.
    987  *
    988  **/
    989 TessellationShaderInvarianceRule2Test::TessellationShaderInvarianceRule2Test(Context&			  context,
    990 																			 const ExtParameters& extParams)
    991 	: TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule2",
    992 										   "Verifies conformance with second invariance rule")
    993 {
    994 	memset(m_n_tessellated_vertices, 0, sizeof(m_n_tessellated_vertices));
    995 }
    996 
    997 /** Destructor. */
    998 TessellationShaderInvarianceRule2Test::~TessellationShaderInvarianceRule2Test()
    999 {
   1000 	/* Left blank intentionally */
   1001 }
   1002 
   1003 /** Retrieves amount of iterations the base test implementation should run before
   1004  *  calling global verification routine.
   1005  *
   1006  *  @return Always 4.
   1007  **/
   1008 unsigned int TessellationShaderInvarianceRule2Test::getAmountOfIterations()
   1009 {
   1010 	return 4;
   1011 }
   1012 
   1013 /** Retrieves iteration-specific tessellation properties.
   1014  *
   1015  *  @param n_iteration            Iteration index to retrieve the properties for.
   1016  *  @param out_inner_tess_levels  Deref will be used to store iteration-specific inner
   1017  *                                tessellation level values. Must not be NULL.
   1018  *  @param out_outer_tess_levels  Deref will be used to store iteration-specific outer
   1019  *                                tessellation level values. Must not be NULL.
   1020  *  @param out_point_mode         Deref will be used to store iteration-specific flag
   1021  *                                telling whether point mode should be enabled for given pass.
   1022  *                                Must not be NULL.
   1023  *  @param out_primitive_mode     Deref will be used to store iteration-specific primitive
   1024  *                                mode. Must not be NULL.
   1025  *  @param out_vertex_ordering    Deref will be used to store iteration-specific vertex
   1026  *                                ordering. Must not be NULL.
   1027  *  @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object
   1028  *                                storage should offer for the draw call to succeed. Can
   1029  *                                be NULL.
   1030  **/
   1031 void TessellationShaderInvarianceRule2Test::getIterationProperties(
   1032 	unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode,
   1033 	_tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering,
   1034 	unsigned int* out_result_buffer_size)
   1035 {
   1036 	*out_vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_CCW;
   1037 
   1038 	switch (n_iteration)
   1039 	{
   1040 	case 0:
   1041 	case 1:
   1042 	{
   1043 		/* Triangles */
   1044 		out_outer_tess_levels[0] = 2.0f;
   1045 		out_outer_tess_levels[1] = 3.0f;
   1046 		out_outer_tess_levels[2] = 4.0f;
   1047 
   1048 		if (n_iteration == 0)
   1049 		{
   1050 			out_inner_tess_levels[0] = 4.0f;
   1051 			out_inner_tess_levels[1] = 5.0f;
   1052 		}
   1053 		else
   1054 		{
   1055 			out_inner_tess_levels[0] = 3.0f;
   1056 			out_inner_tess_levels[1] = 4.0f;
   1057 		}
   1058 
   1059 		*out_point_mode		= false;
   1060 		*out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES;
   1061 
   1062 		break;
   1063 	}
   1064 
   1065 	case 2:
   1066 	case 3:
   1067 	{
   1068 		/* Quads */
   1069 		out_outer_tess_levels[0] = 2.0f;
   1070 		out_outer_tess_levels[1] = 3.0f;
   1071 		out_outer_tess_levels[2] = 4.0f;
   1072 		out_outer_tess_levels[3] = 5.0f;
   1073 
   1074 		if (n_iteration == 2)
   1075 		{
   1076 			out_inner_tess_levels[0] = 2.0f;
   1077 			out_inner_tess_levels[1] = 3.0f;
   1078 		}
   1079 		else
   1080 		{
   1081 			out_inner_tess_levels[0] = 4.0f;
   1082 			out_inner_tess_levels[1] = 5.0f;
   1083 		}
   1084 
   1085 		*out_point_mode		= false;
   1086 		*out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS;
   1087 
   1088 		break;
   1089 	}
   1090 
   1091 	default:
   1092 	{
   1093 		TCU_FAIL("Unrecognized iteration index");
   1094 	}
   1095 	}
   1096 
   1097 	if (out_result_buffer_size != DE_NULL)
   1098 	{
   1099 		*out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   1100 			*out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   1101 			*out_point_mode);
   1102 
   1103 		m_n_tessellated_vertices[n_iteration] = *out_result_buffer_size;
   1104 		*out_result_buffer_size =
   1105 			static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float));
   1106 
   1107 		DE_ASSERT(*out_result_buffer_size != 0);
   1108 	}
   1109 }
   1110 
   1111 /** Retrieves iteration-specific tessellation evaluation shader code.
   1112  *
   1113  *  @param n_iteration Iteration index, for which the source code is being obtained.
   1114  *
   1115  *  @return Requested source code.
   1116  **/
   1117 std::string TessellationShaderInvarianceRule2Test::getTECode(unsigned int n_iteration)
   1118 {
   1119 	unsigned int						 bo_size			  = 0;
   1120 	float								 inner_tess_levels[2] = { 0 };
   1121 	float								 outer_tess_levels[4] = { 0 };
   1122 	bool								 point_mode			  = false;
   1123 	_tessellation_primitive_mode		 primitive_mode		  = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
   1124 	_tessellation_shader_vertex_ordering vertex_ordering	  = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN;
   1125 
   1126 	getIterationProperties(n_iteration, inner_tess_levels, outer_tess_levels, &point_mode, &primitive_mode,
   1127 						   &vertex_ordering, &bo_size);
   1128 
   1129 	return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, primitive_mode,
   1130 													 vertex_ordering, point_mode);
   1131 }
   1132 
   1133 /** Verifies result data. Accesses data generated by all iterations.
   1134  *
   1135  *  Throws TestError exception if an error occurs.
   1136  *
   1137  *  @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord
   1138  *                             data generated by subsequent iterations.
   1139  **/
   1140 void TessellationShaderInvarianceRule2Test::verifyResultData(const void** all_iterations_data)
   1141 {
   1142 	/* Iterate through one tessellated set of vertices for a given primitive type
   1143 	 * and identify outer vertices. Make sure exactly the same vertices can be
   1144 	 * found in the other set of vertices, generated with different input tessellation
   1145 	 * level.
   1146 	 */
   1147 	for (int n_primitive_type = 0; n_primitive_type < 2; /* triangles / quads */
   1148 		 ++n_primitive_type)
   1149 	{
   1150 		const float*				 data1_ptr		= (const float*)all_iterations_data[n_primitive_type * 2 + 0];
   1151 		const float*				 data2_ptr		= (const float*)all_iterations_data[n_primitive_type * 2 + 1];
   1152 		_tessellation_primitive_mode primitive_mode = (n_primitive_type == 0) ?
   1153 														  TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES :
   1154 														  TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS;
   1155 		std::vector<_vertex> outer_vertices;
   1156 
   1157 		/* Iterate through all data1 vertices.. */
   1158 		for (unsigned int n_vertex = 0; n_vertex < m_n_tessellated_vertices[n_primitive_type * 2]; ++n_vertex)
   1159 		{
   1160 			/* Check if any of the components is equal to 0 or 1. If so, this could
   1161 			 * be an edge vertex.
   1162 			 */
   1163 			const float* vertex_ptr = data1_ptr + n_vertex * 3; /* components */
   1164 
   1165 			if (TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, vertex_ptr))
   1166 			{
   1167 				/* Only add the vertex if it has not been added already to the vector */
   1168 				bool has_already_been_added = false;
   1169 
   1170 				for (std::vector<_vertex>::const_iterator vertex_iterator = outer_vertices.begin();
   1171 					 vertex_iterator != outer_vertices.end(); vertex_iterator++)
   1172 				{
   1173 					if (vertex_iterator->u == vertex_ptr[0] && vertex_iterator->v == vertex_ptr[1] &&
   1174 						vertex_iterator->w == vertex_ptr[2])
   1175 					{
   1176 						has_already_been_added = true;
   1177 
   1178 						break;
   1179 					}
   1180 				} /* for (all outer vertices stored so far) */
   1181 
   1182 				if (!has_already_been_added)
   1183 				{
   1184 					_vertex vertex;
   1185 
   1186 					vertex.u = vertex_ptr[0];
   1187 					vertex.v = vertex_ptr[1];
   1188 					vertex.w = vertex_ptr[2];
   1189 
   1190 					outer_vertices.push_back(vertex);
   1191 				}
   1192 			} /* if (input vertex is located on outer edge) */
   1193 		}	 /* for (all input vertices) */
   1194 
   1195 		DE_ASSERT(outer_vertices.size() != 0);
   1196 
   1197 		/* Now that we know where outer vertices are, make sure they are present in the other data set */
   1198 		for (std::vector<_vertex>::const_iterator ref_vertex_iterator = outer_vertices.begin();
   1199 			 ref_vertex_iterator != outer_vertices.end(); ref_vertex_iterator++)
   1200 		{
   1201 			bool		   has_been_found = false;
   1202 			const _vertex& ref_vertex	 = *ref_vertex_iterator;
   1203 
   1204 			for (unsigned int n_vertex = 0; n_vertex < m_n_tessellated_vertices[n_primitive_type * 2 + 1]; ++n_vertex)
   1205 			{
   1206 				const float* vertex_ptr = data2_ptr + n_vertex * 3; /* components */
   1207 
   1208 				if (vertex_ptr[0] == ref_vertex.u && vertex_ptr[1] == ref_vertex.v && vertex_ptr[2] == ref_vertex.w)
   1209 				{
   1210 					has_been_found = true;
   1211 
   1212 					break;
   1213 				}
   1214 			} /* for (all vertices in the other data set) */
   1215 
   1216 			if (!has_been_found)
   1217 			{
   1218 				float								 cmp_inner_tess_levels[2];
   1219 				float								 cmp_outer_tess_levels[4];
   1220 				bool								 cmp_point_mode;
   1221 				_tessellation_primitive_mode		 cmp_primitive_mode;
   1222 				_tessellation_shader_vertex_ordering cmp_vertex_ordering;
   1223 				std::string							 primitive_type = (n_primitive_type == 0) ? "triangles" : "quads";
   1224 				float								 ref_inner_tess_levels[2];
   1225 				float								 ref_outer_tess_levels[4];
   1226 				bool								 ref_point_mode;
   1227 				_tessellation_primitive_mode		 ref_primitive_mode;
   1228 				_tessellation_shader_vertex_ordering ref_vertex_ordering;
   1229 
   1230 				getIterationProperties(n_primitive_type * 2, ref_inner_tess_levels, ref_outer_tess_levels,
   1231 									   &ref_point_mode, &ref_primitive_mode, &ref_vertex_ordering, NULL);
   1232 				getIterationProperties(n_primitive_type * 2 + 1, cmp_inner_tess_levels, cmp_outer_tess_levels,
   1233 									   &cmp_point_mode, &cmp_primitive_mode, &cmp_vertex_ordering, NULL);
   1234 
   1235 				m_testCtx.getLog() << tcu::TestLog::Message << "Outer vertex"
   1236 								   << " (" << ref_vertex.u << ", " << ref_vertex.v << ", " << ref_vertex.w << ")"
   1237 								   << " was not found in tessellated data coordinate set generated"
   1238 								   << " for primitive type: " << primitive_type.c_str()
   1239 								   << ". Reference inner tessellation level:"
   1240 								   << " (" << ref_inner_tess_levels[0] << ", " << ref_inner_tess_levels[1]
   1241 								   << "), reference outer tessellation level:"
   1242 								   << " (" << ref_outer_tess_levels[0] << ", " << ref_outer_tess_levels[1] << ", "
   1243 								   << ref_outer_tess_levels[2] << ", " << ref_outer_tess_levels[3]
   1244 								   << "), test inner tessellation level:"
   1245 								   << " (" << cmp_inner_tess_levels[0] << ", " << cmp_inner_tess_levels[1]
   1246 								   << "), reference outer tessellation level:"
   1247 								   << " (" << cmp_outer_tess_levels[0] << ", " << cmp_outer_tess_levels[1] << ", "
   1248 								   << cmp_outer_tess_levels[2] << ", " << cmp_outer_tess_levels[3] << ")."
   1249 								   << tcu::TestLog::EndMessage;
   1250 
   1251 				TCU_FAIL("Outer edge vertex was not found in tessellated coordinate set generated for "
   1252 						 "the same outer tessellation levels and vertex spacing, but different inner "
   1253 						 "tessellation levels");
   1254 			} /* if (outer edge vertex was not found in the other set) */
   1255 		}	 /* for (all outer edge vertices) */
   1256 	}		  /* for (both primitive types) */
   1257 }
   1258 
   1259 /** Constructor.
   1260  *
   1261  *  @param context Rendering context.
   1262  *
   1263  **/
   1264 TessellationShaderInvarianceRule3Test::TessellationShaderInvarianceRule3Test(Context&			  context,
   1265 																			 const ExtParameters& extParams)
   1266 	: TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule3",
   1267 										   "Verifies conformance with third invariance rule")
   1268 {
   1269 }
   1270 
   1271 /** Destructor. */
   1272 TessellationShaderInvarianceRule3Test::~TessellationShaderInvarianceRule3Test()
   1273 {
   1274 	/* Left blank intentionally */
   1275 }
   1276 
   1277 /** Retrieves amount of iterations the base test implementation should run before
   1278  *  calling global verification routine.
   1279  *
   1280  *  @return A value that depends on initTestIterations() behavior.
   1281  **/
   1282 unsigned int TessellationShaderInvarianceRule3Test::getAmountOfIterations()
   1283 {
   1284 	if (m_test_iterations.size() == 0)
   1285 	{
   1286 		initTestIterations();
   1287 	}
   1288 
   1289 	return (unsigned int)m_test_iterations.size();
   1290 }
   1291 
   1292 /** Retrieves iteration-specific tessellation properties.
   1293  *
   1294  *  @param n_iteration            Iteration index to retrieve the properties for.
   1295  *  @param out_inner_tess_levels  Deref will be used to store iteration-specific inner
   1296  *                                tessellation level values. Must not be NULL.
   1297  *  @param out_outer_tess_levels  Deref will be used to store iteration-specific outer
   1298  *                                tessellation level values. Must not be NULL.
   1299  *  @param out_point_mode         Deref will be used to store iteration-specific flag
   1300  *                                telling whether point mode should be enabled for given pass.
   1301  *                                Must not be NULL.
   1302  *  @param out_primitive_mode     Deref will be used to store iteration-specific primitive
   1303  *                                mode. Must not be NULL.
   1304  *  @param out_vertex_ordering    Deref will be used to store iteration-specific vertex
   1305  *                                ordering. Must not be NULL.
   1306  *  @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object
   1307  *                                storage should offer for the draw call to succeed. Can
   1308  *                                be NULL.
   1309  **/
   1310 void TessellationShaderInvarianceRule3Test::getIterationProperties(
   1311 	unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode,
   1312 	_tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering,
   1313 	unsigned int* out_result_buffer_size)
   1314 {
   1315 	DE_ASSERT(m_test_iterations.size() > n_iteration);
   1316 
   1317 	_test_iteration& test_iteration = m_test_iterations[n_iteration];
   1318 
   1319 	memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels));
   1320 	memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels));
   1321 
   1322 	*out_point_mode		 = false;
   1323 	*out_primitive_mode  = test_iteration.primitive_mode;
   1324 	*out_vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_CCW;
   1325 
   1326 	if (out_result_buffer_size != DE_NULL)
   1327 	{
   1328 		*out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   1329 			*out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, test_iteration.vertex_spacing,
   1330 			*out_point_mode);
   1331 		test_iteration.n_vertices = *out_result_buffer_size;
   1332 		*out_result_buffer_size =
   1333 			static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float));
   1334 
   1335 		DE_ASSERT(*out_result_buffer_size != 0);
   1336 	}
   1337 }
   1338 
   1339 /** Retrieves iteration-specific tessellation evaluation shader code.
   1340  *
   1341  *  @param n_iteration Iteration index, for which the source code is being obtained.
   1342  *
   1343  *  @return Requested source code.
   1344  **/
   1345 std::string TessellationShaderInvarianceRule3Test::getTECode(unsigned int n_iteration)
   1346 {
   1347 	DE_ASSERT(m_test_iterations.size() > n_iteration);
   1348 
   1349 	const _test_iteration& test_iteration = m_test_iterations[n_iteration];
   1350 
   1351 	return TessellationShaderUtils::getGenericTECode(test_iteration.vertex_spacing, test_iteration.primitive_mode,
   1352 													 TESSELLATION_SHADER_VERTEX_ORDERING_CCW, false); /* point mode */
   1353 }
   1354 
   1355 /** Initializes test iterations for the test. The following modes and inner/outer tess level
   1356  *  configurations are used to form the test set:
   1357  *
   1358  *  - Inner/outer tessellation level combinations as returned by
   1359  *    TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode()
   1360  *  - All primitive modes;
   1361  *  - All vertex spacing modes;
   1362  *
   1363  *  All permutations are used to generate the test set.
   1364  **/
   1365 void TessellationShaderInvarianceRule3Test::initTestIterations()
   1366 {
   1367 	DE_ASSERT(m_test_iterations.size() == 0);
   1368 
   1369 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
   1370 	const glw::Functions& gl						  = m_context.getRenderContext().getFunctions();
   1371 	glw::GLint			  gl_max_tess_gen_level_value = 0;
   1372 
   1373 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
   1374 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
   1375 
   1376 	/* Iterate through all primitive and vertex spacing modes */
   1377 	_tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES,
   1378 													   TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
   1379 													   TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
   1380 	_tessellation_shader_vertex_spacing vs_modes[] = { TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   1381 													   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
   1382 													   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD };
   1383 
   1384 	const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
   1385 	const unsigned int n_vs_modes		 = sizeof(vs_modes) / sizeof(vs_modes[0]);
   1386 
   1387 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
   1388 	{
   1389 		_tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode];
   1390 
   1391 		for (unsigned int n_vs_mode = 0; n_vs_mode < n_vs_modes; ++n_vs_mode)
   1392 		{
   1393 			_tessellation_shader_vertex_spacing vs_mode = vs_modes[n_vs_mode];
   1394 
   1395 			/* Retrieve inner/outer tessellation level combinations we want the tests to be run for */
   1396 			_tessellation_levels_set levels_set;
   1397 
   1398 			levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
   1399 				primitive_mode, gl_max_tess_gen_level_value,
   1400 				TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
   1401 
   1402 			/* Iterate through all configurations */
   1403 			for (_tessellation_levels_set_const_iterator levels_iterator = levels_set.begin();
   1404 				 levels_iterator != levels_set.end(); levels_iterator++)
   1405 			{
   1406 				const _tessellation_levels& levels = *levels_iterator;
   1407 
   1408 				/* Create a test descriptor for all the parameters we now have */
   1409 				_test_iteration test;
   1410 
   1411 				memcpy(test.inner_tess_levels, levels.inner, sizeof(test.inner_tess_levels));
   1412 				memcpy(test.outer_tess_levels, levels.outer, sizeof(test.outer_tess_levels));
   1413 
   1414 				test.primitive_mode = primitive_mode;
   1415 				test.vertex_spacing = vs_mode;
   1416 
   1417 				m_test_iterations.push_back(test);
   1418 			} /* for (all inner/outer tessellation levels) */
   1419 		}	 /* for (all vertex spacing modes) */
   1420 	}		  /* for (all primitive modes) */
   1421 }
   1422 
   1423 /** Verifies result data on per-iteration basis.
   1424  *
   1425  *  Throws TestError exception if an error occurs.
   1426  *
   1427  *  @param n_iteration Index of iteration the check should be performed for.
   1428  *  @param data        Points to array of vec3s storing the vertices as
   1429  *                     generated by tessellation
   1430  **/
   1431 void TessellationShaderInvarianceRule3Test::verifyResultDataForIteration(unsigned int n_iteration, const void* data)
   1432 {
   1433 	DE_ASSERT(m_test_iterations.size() > n_iteration);
   1434 
   1435 	const glw::GLfloat*	data_float	 = (const glw::GLfloat*)data;
   1436 	const _test_iteration& test_iteration = m_test_iterations[n_iteration];
   1437 
   1438 	/* Iterate through all generated vertices.. */
   1439 	for (unsigned int n_vertex = 0; n_vertex < test_iteration.n_vertices; ++n_vertex)
   1440 	{
   1441 		_vertex				expected_vertex;
   1442 		const glw::GLfloat* vertex_data = data_float + 3 /* components */ * n_vertex;
   1443 
   1444 		expected_vertex.u = -1.0f;
   1445 		expected_vertex.v = -1.0f;
   1446 		expected_vertex.w = -1.0f;
   1447 
   1448 		/* Make sure that for each vertex, the following language from the extension
   1449 		 * spec is followed:
   1450 		 */
   1451 		switch (test_iteration.primitive_mode)
   1452 		{
   1453 		case TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES:
   1454 		{
   1455 			/* For isoline tessellation, if it generates vertices at (0,x) and (1,x)
   1456 			 * where <x> is not zero, it will also generate vertices at exactly (0,1-x)
   1457 			 * and (1,1-x), respectively.
   1458 			 */
   1459 			if (vertex_data[0] == 0.0f && vertex_data[1] != 0.0f)
   1460 			{
   1461 				expected_vertex.u = vertex_data[0];
   1462 				expected_vertex.v = 1.0f - vertex_data[1];
   1463 				expected_vertex.w = -1.0f;
   1464 			}
   1465 			else if (vertex_data[0] == 1.0f && vertex_data[1] != 0.0f)
   1466 			{
   1467 				expected_vertex.u = vertex_data[0];
   1468 				expected_vertex.v = 1.0f - vertex_data[1];
   1469 				expected_vertex.w = -1.0f;
   1470 			}
   1471 
   1472 			break;
   1473 		} /* case TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES: */
   1474 
   1475 		case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS:
   1476 		{
   1477 			/* For quad tessellation, if the subdivision generates a vertex with
   1478 			 * coordinates of (x,0) or (0,x), it will also generate a vertex with
   1479 			 * coordinates of exactly (1-x,0) or (0,1-x), respectively.
   1480 			 */
   1481 			if (vertex_data[0] != 0.0f && vertex_data[1] == 0.0f)
   1482 			{
   1483 				expected_vertex.u = 1.0f - vertex_data[0];
   1484 				expected_vertex.v = vertex_data[1];
   1485 				expected_vertex.w = -1.0f;
   1486 			}
   1487 			else if (vertex_data[0] == 0.0f && vertex_data[1] != 0.0f)
   1488 			{
   1489 				expected_vertex.u = vertex_data[0];
   1490 				expected_vertex.v = 1.0f - vertex_data[1];
   1491 				expected_vertex.w = -1.0f;
   1492 			}
   1493 
   1494 			break;
   1495 		} /* case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS: */
   1496 
   1497 		case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES:
   1498 		{
   1499 			/* For triangle tessellation, if the subdivision generates a vertex with
   1500 			 * tessellation coordinates of the form (0,x,1-x), (x,0,1-x), or (x,1-x,0),
   1501 			 * it will also generate a vertex with coordinates of exactly (0,1-x,x),
   1502 			 * (1-x,0,x), or (1-x,x,0), respectively.
   1503 			 */
   1504 			if (vertex_data[0] == 0.0f && vertex_data[1] != 0.0f && vertex_data[2] == (1.0f - vertex_data[1]))
   1505 			{
   1506 				expected_vertex.u = vertex_data[0];
   1507 				expected_vertex.v = vertex_data[2];
   1508 				expected_vertex.w = vertex_data[1];
   1509 			}
   1510 			else if (vertex_data[0] != 0.0f && vertex_data[1] == 0.0f && vertex_data[2] == (1.0f - vertex_data[0]))
   1511 			{
   1512 				expected_vertex.u = vertex_data[2];
   1513 				expected_vertex.v = vertex_data[1];
   1514 				expected_vertex.w = vertex_data[0];
   1515 			}
   1516 			else if (vertex_data[0] != 0.0f && vertex_data[1] == (1.0f - vertex_data[0]) && vertex_data[2] == 0.0f)
   1517 			{
   1518 				expected_vertex.u = vertex_data[1];
   1519 				expected_vertex.v = vertex_data[0];
   1520 				expected_vertex.w = vertex_data[2];
   1521 			}
   1522 
   1523 			break;
   1524 		} /* case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES: */
   1525 
   1526 		default:
   1527 		{
   1528 			TCU_FAIL("Primitive mode unrecognized");
   1529 		}
   1530 		} /* switch (test_iteration.primitive_mode) */
   1531 
   1532 		/* If any of the "expected vertex"'s components is no longer negative,
   1533 		 * make sure the vertex can be found in the result data */
   1534 		if (expected_vertex.u >= 0.0f || expected_vertex.v >= 0.0f || expected_vertex.w >= 0.0f)
   1535 		{
   1536 			bool has_been_found = false;
   1537 
   1538 			for (unsigned int n_find_vertex = 0; n_find_vertex < test_iteration.n_vertices; ++n_find_vertex)
   1539 			{
   1540 				const glw::GLfloat* current_vertex_data = data_float + 3 /* components */ * n_find_vertex;
   1541 
   1542 				const glw::GLfloat epsilon	 = 1e-4f;
   1543 				glw::GLfloat	   absDelta[3] = { de::abs(current_vertex_data[0] - expected_vertex.u),
   1544 											 de::abs(current_vertex_data[1] - expected_vertex.v),
   1545 											 de::abs(current_vertex_data[2] - expected_vertex.w) };
   1546 
   1547 				if (absDelta[0] < epsilon && absDelta[1] < epsilon &&
   1548 					((expected_vertex.w < 0.0f) || (expected_vertex.w >= 0.0f && absDelta[2] < epsilon)))
   1549 				{
   1550 					has_been_found = true;
   1551 
   1552 					break;
   1553 				} /* if (the vertex data matches the expected vertex data) */
   1554 			}	 /* for (all generated vertices)*/
   1555 
   1556 			if (!has_been_found)
   1557 			{
   1558 				TCU_FAIL("Expected symmetrical vertex data was not generated by the tessellator.");
   1559 			}
   1560 		} /* if (any of the components of expected_vertex is no longer negative) */
   1561 	}	 /* for (all generated vertices) */
   1562 }
   1563 
   1564 /** Constructor.
   1565  *
   1566  *  @param context Rendering context.
   1567  *
   1568  **/
   1569 TessellationShaderInvarianceRule4Test::TessellationShaderInvarianceRule4Test(Context&			  context,
   1570 																			 const ExtParameters& extParams)
   1571 	: TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule4",
   1572 										   "Verifies conformance with fourth invariance rule")
   1573 {
   1574 }
   1575 
   1576 /** Destructor. */
   1577 TessellationShaderInvarianceRule4Test::~TessellationShaderInvarianceRule4Test()
   1578 {
   1579 	/* Left blank intentionally */
   1580 }
   1581 
   1582 /** Retrieves amount of iterations the base test implementation should run before
   1583  *  calling global verification routine.
   1584  *
   1585  *  @return A value that depends on initTestIterations() behavior.
   1586  **/
   1587 unsigned int TessellationShaderInvarianceRule4Test::getAmountOfIterations()
   1588 {
   1589 	if (m_test_iterations.size() == 0)
   1590 	{
   1591 		initTestIterations();
   1592 	}
   1593 
   1594 	return (unsigned int)m_test_iterations.size();
   1595 }
   1596 
   1597 /** Retrieves iteration-specific tessellation properties.
   1598  *
   1599  *  @param n_iteration            Iteration index to retrieve the properties for.
   1600  *  @param out_inner_tess_levels  Deref will be used to store iteration-specific inner
   1601  *                                tessellation level values. Must not be NULL.
   1602  *  @param out_outer_tess_levels  Deref will be used to store iteration-specific outer
   1603  *                                tessellation level values. Must not be NULL.
   1604  *  @param out_point_mode         Deref will be used to store iteration-specific flag
   1605  *                                telling whether point mode should be enabled for given pass.
   1606  *                                Must not be NULL.
   1607  *  @param out_primitive_mode     Deref will be used to store iteration-specific primitive
   1608  *                                mode. Must not be NULL.
   1609  *  @param out_vertex_ordering    Deref will be used to store iteration-specific vertex
   1610  *                                ordering. Must not be NULL.
   1611  *  @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object
   1612  *                                storage should offer for the draw call to succeed. Can
   1613  *                                be NULL.
   1614  **/
   1615 void TessellationShaderInvarianceRule4Test::getIterationProperties(
   1616 	unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode,
   1617 	_tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering,
   1618 	unsigned int* out_result_buffer_size)
   1619 {
   1620 	DE_ASSERT(m_test_iterations.size() > n_iteration);
   1621 
   1622 	_test_iteration& test_iteration = m_test_iterations[n_iteration];
   1623 
   1624 	memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels));
   1625 	memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels));
   1626 
   1627 	*out_point_mode		 = false;
   1628 	*out_primitive_mode  = test_iteration.primitive_mode;
   1629 	*out_vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_CCW;
   1630 
   1631 	if (out_result_buffer_size != DE_NULL)
   1632 	{
   1633 		*out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   1634 			*out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, test_iteration.vertex_spacing,
   1635 			*out_point_mode);
   1636 		test_iteration.n_vertices = *out_result_buffer_size;
   1637 		*out_result_buffer_size =
   1638 			static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float));
   1639 
   1640 		DE_ASSERT(*out_result_buffer_size != 0);
   1641 	}
   1642 }
   1643 
   1644 /** Retrieves iteration-specific tessellation evaluation shader code.
   1645  *
   1646  *  @param n_iteration Iteration index, for which the source code is being obtained.
   1647  *
   1648  *  @return Requested source code.
   1649  **/
   1650 std::string TessellationShaderInvarianceRule4Test::getTECode(unsigned int n_iteration)
   1651 {
   1652 	DE_ASSERT(m_test_iterations.size() > n_iteration);
   1653 
   1654 	const _test_iteration& test_iteration = m_test_iterations[n_iteration];
   1655 
   1656 	return TessellationShaderUtils::getGenericTECode(test_iteration.vertex_spacing, test_iteration.primitive_mode,
   1657 													 TESSELLATION_SHADER_VERTEX_ORDERING_CCW, false); /* point mode */
   1658 }
   1659 
   1660 /** Initializes test iterations for the test. The following modes and inner/outer tess level
   1661  *  configurations are used to form the test set:
   1662  *
   1663  *  - Inner/outer tessellation level combinations as returned by
   1664  *    TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode()
   1665  *  - 'Quads' and 'Triangles' primitive modes;
   1666  *  - All vertex spacing modes;
   1667  *
   1668  *  All permutations are used to generate the test set.
   1669  **/
   1670 void TessellationShaderInvarianceRule4Test::initTestIterations()
   1671 {
   1672 	DE_ASSERT(m_test_iterations.size() == 0);
   1673 
   1674 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
   1675 	const glw::Functions& gl						  = m_context.getRenderContext().getFunctions();
   1676 	glw::GLint			  gl_max_tess_gen_level_value = 0;
   1677 
   1678 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
   1679 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
   1680 
   1681 	/* Iterate through all primitive and vertex spacing modes relevant to the test */
   1682 	_tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
   1683 													   TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
   1684 	_tessellation_shader_vertex_spacing vs_modes[] = { TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   1685 													   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
   1686 													   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD };
   1687 
   1688 	const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
   1689 	const unsigned int n_vs_modes		 = sizeof(vs_modes) / sizeof(vs_modes[0]);
   1690 
   1691 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
   1692 	{
   1693 		_tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode];
   1694 
   1695 		for (unsigned int n_vs_mode = 0; n_vs_mode < n_vs_modes; ++n_vs_mode)
   1696 		{
   1697 			_tessellation_shader_vertex_spacing vs_mode = vs_modes[n_vs_mode];
   1698 
   1699 			/* Retrieve inner/outer tessellation level combinations we want the tests to be run for */
   1700 			_tessellation_levels_set levels;
   1701 
   1702 			levels = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
   1703 				primitive_mode, gl_max_tess_gen_level_value,
   1704 				TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
   1705 
   1706 			/* Iterate through all configurations */
   1707 			for (_tessellation_levels_set_const_iterator levels_iterator = levels.begin();
   1708 				 levels_iterator != levels.end(); levels_iterator++)
   1709 			{
   1710 				const _tessellation_levels& current_levels = *levels_iterator;
   1711 
   1712 				/* Create a test descriptor for all the parameters we now have.
   1713 				 *
   1714 				 * The set we're operating on uses different outer tessellation level values, so we
   1715 				 * need to make sure the levels are set to the same FP values in order for the test
   1716 				 * to succeed. */
   1717 				_test_iteration test;
   1718 
   1719 				memcpy(test.inner_tess_levels, current_levels.inner, sizeof(test.inner_tess_levels));
   1720 
   1721 				for (int n = 0; n < 4 /* outer tess levels */; ++n)
   1722 				{
   1723 					test.outer_tess_levels[n] = current_levels.outer[0];
   1724 				}
   1725 
   1726 				test.primitive_mode = primitive_mode;
   1727 				test.vertex_spacing = vs_mode;
   1728 
   1729 				m_test_iterations.push_back(test);
   1730 			} /* for (all inner/outer tessellation levels) */
   1731 		}	 /* for (all vertex spacing modes) */
   1732 	}		  /* for (all primitive modes) */
   1733 }
   1734 
   1735 /** Verifies user-provided vertex data can be found in the provided vertex data array.
   1736  *
   1737  *  @param vertex_data                     Vertex data array the requested vertex data are to be found in.
   1738  *  @param n_vertices                      Amount of vertices declared in @param vertex_data;
   1739  *  @param vertex_data_seeked              Vertex data to be found in @param vertex_data;
   1740  *  @param n_vertex_data_seeked_components Amount of components to take into account.
   1741  *
   1742  *  @return true if the vertex data was found, false otherwise.
   1743  **/
   1744 bool TessellationShaderInvarianceRule4Test::isVertexDefined(const float* vertex_data, unsigned int n_vertices,
   1745 															const float* vertex_data_seeked,
   1746 															unsigned int n_vertex_data_seeked_components)
   1747 {
   1748 	bool result = false;
   1749 
   1750 	DE_ASSERT(n_vertex_data_seeked_components >= 2);
   1751 
   1752 	for (unsigned int n_vertex = 0; n_vertex < n_vertices; ++n_vertex)
   1753 	{
   1754 		const float* current_vertex_data = vertex_data + 3 /* components */ * n_vertex;
   1755 
   1756 		if ((vertex_data_seeked[0] == current_vertex_data[0]) && (vertex_data_seeked[1] == current_vertex_data[1]) &&
   1757 			((n_vertex_data_seeked_components < 3) ||
   1758 			 (n_vertex_data_seeked_components >= 3 && (vertex_data_seeked[2] == current_vertex_data[2]))))
   1759 		{
   1760 			result = true;
   1761 
   1762 			break;
   1763 		} /* if (components match) */
   1764 	}	 /* for (all vertices) */
   1765 
   1766 	return result;
   1767 }
   1768 
   1769 /** Verifies result data on per-iteration basis.
   1770  *
   1771  *  Throws TestError exception if an error occurs.
   1772  *
   1773  *  @param n_iteration Index of iteration the check should be performed for.
   1774  *  @param data        Points to array of vec3s storing the vertices as
   1775  *                     generated by tessellation
   1776  **/
   1777 void TessellationShaderInvarianceRule4Test::verifyResultDataForIteration(unsigned int n_iteration, const void* data)
   1778 {
   1779 	DE_ASSERT(m_test_iterations.size() > n_iteration);
   1780 
   1781 	const glw::GLfloat*	data_float	 = (const glw::GLfloat*)data;
   1782 	const _test_iteration& test_iteration = m_test_iterations[n_iteration];
   1783 
   1784 	/* Iterate through all generated vertices.. */
   1785 	for (unsigned int n_vertex = 0; n_vertex < test_iteration.n_vertices; ++n_vertex)
   1786 	{
   1787 		std::vector<_vertex> expected_vertices;
   1788 		const glw::GLfloat*  vertex_data = data_float + 3 /* components */ * n_vertex;
   1789 
   1790 		/* Make sure that for each vertex, the following language from the extension
   1791 		 * spec is followed:
   1792 		 */
   1793 		switch (test_iteration.primitive_mode)
   1794 		{
   1795 		case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS:
   1796 		{
   1797 			/* For quad tessellation, if vertices at (x,0) and (1-x,0) are generated
   1798 			 * when subdividing the v==0 edge, vertices must be generated at (0,x) and
   1799 			 * (0,1-x) when subdividing an otherwise identical u==0 edge.
   1800 			 */
   1801 			if (vertex_data[0] != 0.0f && vertex_data[1] == 0.0f)
   1802 			{
   1803 				const float paired_vertex_data[] = { 1.0f - vertex_data[0], vertex_data[1] };
   1804 
   1805 				if (isVertexDefined(data_float, test_iteration.n_vertices, paired_vertex_data, 2)) /* components */
   1806 				{
   1807 					_vertex expected_vertex;
   1808 
   1809 					/* First expected vertex */
   1810 					expected_vertex.u = vertex_data[1];
   1811 					expected_vertex.v = vertex_data[0];
   1812 					expected_vertex.w = -1.0f;
   1813 
   1814 					expected_vertices.push_back(expected_vertex);
   1815 
   1816 					/* The other expected vertex */
   1817 					expected_vertex.u = vertex_data[1];
   1818 					expected_vertex.v = 1.0f - vertex_data[0];
   1819 
   1820 					expected_vertices.push_back(expected_vertex);
   1821 				} /* if (the other required vertex is defined) */
   1822 			}	 /* if (the first required vertex is defined) */
   1823 
   1824 			break;
   1825 		} /* case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS: */
   1826 
   1827 		case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES:
   1828 		{
   1829 			/* For triangular tessellation, if vertices at (x,1-x,0) and (1-x,x,0) are
   1830 			 * generated when subdividing the w==0 edge, vertices must be generated at
   1831 			 * (x,0,1-x) and (1-x,0,x) when subdividing an otherwise identical v==0
   1832 			 * edge.
   1833 			 */
   1834 			if (vertex_data[0] != 0.0f && vertex_data[1] == (1.0f - vertex_data[0]) && vertex_data[2] == 0)
   1835 			{
   1836 				const float paired_vertex_data[] = { vertex_data[1], vertex_data[0], vertex_data[2] };
   1837 
   1838 				if (isVertexDefined(data_float, test_iteration.n_vertices, paired_vertex_data, 3)) /* components */
   1839 				{
   1840 					_vertex expected_vertex;
   1841 
   1842 					/* First expected vertex */
   1843 					expected_vertex.u = vertex_data[0];
   1844 					expected_vertex.v = vertex_data[2];
   1845 					expected_vertex.w = vertex_data[1];
   1846 
   1847 					expected_vertices.push_back(expected_vertex);
   1848 
   1849 					/* The other expected vertex */
   1850 					expected_vertex.u = vertex_data[1];
   1851 					expected_vertex.v = vertex_data[2];
   1852 					expected_vertex.w = vertex_data[0];
   1853 
   1854 					expected_vertices.push_back(expected_vertex);
   1855 				} /* if (the other required vertex is defined) */
   1856 			}	 /* if (the firsst required vertex is defined) */
   1857 
   1858 			break;
   1859 		} /* case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES: */
   1860 
   1861 		default:
   1862 		{
   1863 			TCU_FAIL("Primitive mode unrecognized");
   1864 		}
   1865 		} /* switch (test_iteration.primitive_mode) */
   1866 
   1867 		/* Iterate through all expected vertices */
   1868 		for (std::vector<_vertex>::const_iterator expected_vertex_iterator = expected_vertices.begin();
   1869 			 expected_vertex_iterator != expected_vertices.end(); expected_vertex_iterator++)
   1870 		{
   1871 			const _vertex& expected_vertex		 = *expected_vertex_iterator;
   1872 			const float	expected_vertex_raw[] = { expected_vertex.u, expected_vertex.v, expected_vertex.w };
   1873 			bool		   has_been_found		 = false;
   1874 
   1875 			has_been_found = isVertexDefined(data_float, test_iteration.n_vertices, expected_vertex_raw,
   1876 											 (expected_vertex.w < 0) ? 2 : 3);
   1877 
   1878 			if (!has_been_found)
   1879 			{
   1880 				std::stringstream expected_vertex_sstream;
   1881 
   1882 				expected_vertex_sstream << expected_vertex.u << ", " << expected_vertex.v;
   1883 
   1884 				if (expected_vertex.w >= 0.0f)
   1885 				{
   1886 					expected_vertex_sstream << ", " << expected_vertex.w;
   1887 				}
   1888 
   1889 				m_testCtx.getLog() << tcu::TestLog::Message << "For primitive mode:"
   1890 								   << "["
   1891 								   << TessellationShaderUtils::getESTokenForPrimitiveMode(test_iteration.primitive_mode)
   1892 								   << "]"
   1893 								   << "and vertex spacing mode:"
   1894 								   << "[" << TessellationShaderUtils::getESTokenForVertexSpacingMode(
   1895 												 test_iteration.vertex_spacing)
   1896 								   << "]"
   1897 								   << " and inner tessellation levels:[" << test_iteration.inner_tess_levels[0] << ", "
   1898 								   << test_iteration.inner_tess_levels[1] << ") "
   1899 								   << " and outer tessellation levels:[" << test_iteration.outer_tess_levels[0] << ", "
   1900 								   << test_iteration.outer_tess_levels[1] << ", " << test_iteration.outer_tess_levels[2]
   1901 								   << ", " << test_iteration.outer_tess_levels[3] << ") "
   1902 								   << " the following vertex was expected:[" << expected_vertex_sstream.str().c_str()
   1903 								   << "] but was not found in the tessellated cooordinate data set"
   1904 								   << tcu::TestLog::EndMessage;
   1905 
   1906 				TCU_FAIL("Expected symmetrical vertex data was not generated by the tessellator.");
   1907 			} /* if (the expected vertex data was not found) */
   1908 		}	 /* for (all expected vertices) */
   1909 	}		  /* for (all generated vertices) */
   1910 }
   1911 
   1912 /** Constructor.
   1913  *
   1914  *  @param context Rendering context.
   1915  *
   1916  **/
   1917 TessellationShaderInvarianceRule5Test::TessellationShaderInvarianceRule5Test(Context&			  context,
   1918 																			 const ExtParameters& extParams)
   1919 	: TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule5",
   1920 										   "Verifies conformance with fifth invariance rule")
   1921 {
   1922 }
   1923 
   1924 /** Destructor. */
   1925 TessellationShaderInvarianceRule5Test::~TessellationShaderInvarianceRule5Test()
   1926 {
   1927 	/* Left blank intentionally */
   1928 }
   1929 
   1930 /** Retrieves amount of iterations the base test implementation should run before
   1931  *  calling global verification routine.
   1932  *
   1933  *  @return A value that depends on initTestIterations() behavior.
   1934  **/
   1935 unsigned int TessellationShaderInvarianceRule5Test::getAmountOfIterations()
   1936 {
   1937 	if (m_test_quads_iterations.size() == 0 || m_test_triangles_iterations.size() == 0)
   1938 	{
   1939 		initTestIterations();
   1940 	}
   1941 
   1942 	return (unsigned int)(m_test_quads_iterations.size() + m_test_triangles_iterations.size());
   1943 }
   1944 
   1945 /** Retrieves _test_iteration instance specific for user-specified iteration index.
   1946  *
   1947  *  @param n_iteration Iteration index to retrieve _test_iteration instance for.
   1948  *
   1949  * @return Iteration-specific _test_iteration instance.
   1950  *
   1951  **/
   1952 TessellationShaderInvarianceRule5Test::_test_iteration& TessellationShaderInvarianceRule5Test::getTestForIteration(
   1953 	unsigned int n_iteration)
   1954 {
   1955 	unsigned int	 n_triangles_tests = (unsigned int)m_test_triangles_iterations.size();
   1956 	_test_iteration& test_iteration	= (n_iteration < n_triangles_tests) ?
   1957 										  m_test_triangles_iterations[n_iteration] :
   1958 										  m_test_quads_iterations[n_iteration - n_triangles_tests];
   1959 
   1960 	return test_iteration;
   1961 }
   1962 
   1963 /** Retrieves iteration-specific tessellation properties.
   1964  *
   1965  *  @param n_iteration            Iteration index to retrieve the properties for.
   1966  *  @param out_inner_tess_levels  Deref will be used to store iteration-specific inner
   1967  *                                tessellation level values. Must not be NULL.
   1968  *  @param out_outer_tess_levels  Deref will be used to store iteration-specific outer
   1969  *                                tessellation level values. Must not be NULL.
   1970  *  @param out_point_mode         Deref will be used to store iteration-specific flag
   1971  *                                telling whether point mode should be enabled for given pass.
   1972  *                                Must not be NULL.
   1973  *  @param out_primitive_mode     Deref will be used to store iteration-specific primitive
   1974  *                                mode. Must not be NULL.
   1975  *  @param out_vertex_ordering    Deref will be used to store iteration-specific vertex
   1976  *                                ordering. Must not be NULL.
   1977  *  @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object
   1978  *                                storage should offer for the draw call to succeed. Can
   1979  *                                be NULL.
   1980  **/
   1981 void TessellationShaderInvarianceRule5Test::getIterationProperties(
   1982 	unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode,
   1983 	_tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering,
   1984 	unsigned int* out_result_buffer_size)
   1985 {
   1986 	DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration);
   1987 
   1988 	_test_iteration& test_iteration = getTestForIteration(n_iteration);
   1989 
   1990 	memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels));
   1991 	memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels));
   1992 
   1993 	*out_point_mode		 = false;
   1994 	*out_primitive_mode  = test_iteration.primitive_mode;
   1995 	*out_vertex_ordering = test_iteration.vertex_ordering;
   1996 
   1997 	if (out_result_buffer_size != DE_NULL)
   1998 	{
   1999 		*out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   2000 			*out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   2001 			*out_point_mode);
   2002 		test_iteration.n_vertices = *out_result_buffer_size;
   2003 		*out_result_buffer_size =
   2004 			static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float));
   2005 
   2006 		DE_ASSERT(*out_result_buffer_size != 0);
   2007 	}
   2008 }
   2009 
   2010 /** Retrieves iteration-specific tessellation evaluation shader code.
   2011  *
   2012  *  @param n_iteration Iteration index, for which the source code is being obtained.
   2013  *
   2014  *  @return Requested source code.
   2015  **/
   2016 std::string TessellationShaderInvarianceRule5Test::getTECode(unsigned int n_iteration)
   2017 {
   2018 	DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration);
   2019 
   2020 	const _test_iteration& test_iteration = getTestForIteration(n_iteration);
   2021 
   2022 	return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   2023 													 test_iteration.primitive_mode, test_iteration.vertex_ordering,
   2024 													 false); /* point mode */
   2025 }
   2026 
   2027 /** Initializes test iterations for the test. The following modes and inner/outer tess level
   2028  *  configurations are used to form the test set:
   2029  *
   2030  *  - Last inner/outer tessellation level combination as returned by
   2031  *    TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode()
   2032  *  - All primitive modes;
   2033  *  - All vertex spacing modes;
   2034  *
   2035  *  All permutations are used to generate the test set.
   2036  **/
   2037 void TessellationShaderInvarianceRule5Test::initTestIterations()
   2038 {
   2039 	DE_ASSERT(m_test_quads_iterations.size() == 0 && m_test_triangles_iterations.size() == 0);
   2040 
   2041 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
   2042 	const glw::Functions& gl						  = m_context.getRenderContext().getFunctions();
   2043 	glw::GLint			  gl_max_tess_gen_level_value = 0;
   2044 
   2045 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
   2046 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
   2047 
   2048 	/* Iterate through all primitive and vertex spacing modes relevant to the test */
   2049 	_tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
   2050 													   TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
   2051 	_tessellation_shader_vertex_ordering vo_modes[] = {
   2052 		TESSELLATION_SHADER_VERTEX_ORDERING_CCW, TESSELLATION_SHADER_VERTEX_ORDERING_CW,
   2053 	};
   2054 
   2055 	const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
   2056 	const unsigned int n_vo_modes		 = sizeof(vo_modes) / sizeof(vo_modes[0]);
   2057 
   2058 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
   2059 	{
   2060 		_tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode];
   2061 
   2062 		for (unsigned int n_vo_mode = 0; n_vo_mode < n_vo_modes; ++n_vo_mode)
   2063 		{
   2064 			_tessellation_shader_vertex_ordering vertex_ordering = vo_modes[n_vo_mode];
   2065 
   2066 			/* Retrieve inner/outer tessellation level combinations we want the tests to be run for */
   2067 			_tessellation_levels_set levels_set;
   2068 
   2069 			levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
   2070 				primitive_mode, gl_max_tess_gen_level_value,
   2071 				TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
   2072 
   2073 			/* Only use the last inner/outer level configuration, as reported by the utils function. */
   2074 			const _tessellation_levels& levels = levels_set[levels_set.size() - 1];
   2075 
   2076 			/* Create a test descriptor for all the parameters we now have */
   2077 			_test_iteration test;
   2078 
   2079 			memcpy(test.inner_tess_levels, levels.inner, sizeof(test.inner_tess_levels));
   2080 			memcpy(test.outer_tess_levels, levels.outer, sizeof(test.outer_tess_levels));
   2081 
   2082 			test.primitive_mode  = primitive_mode;
   2083 			test.vertex_ordering = vertex_ordering;
   2084 
   2085 			if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES)
   2086 			{
   2087 				m_test_triangles_iterations.push_back(test);
   2088 			}
   2089 			else
   2090 			{
   2091 				m_test_quads_iterations.push_back(test);
   2092 			}
   2093 		} /* for (all vertex spacing modes) */
   2094 	}	 /* for (all primitive modes) */
   2095 }
   2096 
   2097 /** Verifies user-provided vertex data can be found in the provided vertex data array.
   2098  *
   2099  *  @param vertex_data                     Vertex data array the requested vertex data are to be found in.
   2100  *  @param n_vertices                      Amount of vertices declared in @param vertex_data;
   2101  *  @param vertex_data_seeked              Vertex data to be found in @param vertex_data;
   2102  *  @param n_vertex_data_seeked_components Amount of components to take into account.
   2103  *
   2104  *  @return true if the vertex data was found, false otherwise.
   2105  **/
   2106 bool TessellationShaderInvarianceRule5Test::isVertexDefined(const float* vertex_data, unsigned int n_vertices,
   2107 															const float* vertex_data_seeked,
   2108 															unsigned int n_vertex_data_seeked_components)
   2109 {
   2110 	const float epsilon = 1e-5f;
   2111 	bool		result  = false;
   2112 
   2113 	DE_ASSERT(n_vertex_data_seeked_components >= 2);
   2114 
   2115 	for (unsigned int n_vertex = 0; n_vertex < n_vertices; ++n_vertex)
   2116 	{
   2117 		const float* current_vertex_data = vertex_data + 3 /* components */ * n_vertex;
   2118 
   2119 		if (de::abs(vertex_data_seeked[0] - current_vertex_data[0]) < epsilon &&
   2120 			de::abs(vertex_data_seeked[1] - current_vertex_data[1]) < epsilon &&
   2121 			((n_vertex_data_seeked_components < 3) ||
   2122 			 (n_vertex_data_seeked_components >= 3 &&
   2123 			  de::abs(vertex_data_seeked[2] - current_vertex_data[2]) < epsilon)))
   2124 		{
   2125 			result = true;
   2126 
   2127 			break;
   2128 		} /* if (components match) */
   2129 	}	 /* for (all vertices) */
   2130 
   2131 	return result;
   2132 }
   2133 
   2134 /** Verifies result data. Accesses data generated by all iterations.
   2135  *
   2136  *  Throws TestError exception if an error occurs.
   2137  *
   2138  *  @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord
   2139  *                             data generated by subsequent iterations.
   2140  **/
   2141 void TessellationShaderInvarianceRule5Test::verifyResultData(const void** all_iterations_data)
   2142 {
   2143 	/* Run two separate iterations:
   2144 	 *
   2145 	 * a) triangles
   2146 	 * b) quads
   2147 	 */
   2148 	for (unsigned int n_iteration = 0; n_iteration < 2 /* quads, triangles */; ++n_iteration)
   2149 	{
   2150 		const unsigned int n_base_iteration =
   2151 			(n_iteration == 0) ? 0 : (const unsigned int)m_test_triangles_iterations.size();
   2152 		const unsigned int set_size = (n_iteration == 0) ? (const unsigned int)m_test_triangles_iterations.size() :
   2153 														   (const unsigned int)m_test_quads_iterations.size();
   2154 		const _test_iterations& test_iterations =
   2155 			(n_iteration == 0) ? m_test_triangles_iterations : m_test_quads_iterations;
   2156 
   2157 		DE_ASSERT(test_iterations.size() != 0);
   2158 
   2159 		/* For each iteration, verify that all vertices generated for all three vertex spacing modes.
   2160 		 * are exactly the same (but in different order) */
   2161 		const float* base_vertex_data = (const float*)all_iterations_data[n_base_iteration + 0];
   2162 
   2163 		for (unsigned int n_set = 1; n_set < set_size; ++n_set)
   2164 		{
   2165 			const float* set_vertex_data = (const float*)all_iterations_data[n_base_iteration + n_set];
   2166 
   2167 			/* Amount of vertices should not differ between sets */
   2168 			DE_ASSERT(test_iterations[0].n_vertices == test_iterations[n_set].n_vertices);
   2169 
   2170 			/* Run through all vertices in base set and make sure they can be found in currently
   2171 			 * processed set */
   2172 			for (unsigned int n_base_vertex = 0; n_base_vertex < test_iterations[0].n_vertices; ++n_base_vertex)
   2173 			{
   2174 				const float* base_vertex = base_vertex_data + 3 /* components */ * n_base_vertex;
   2175 
   2176 				if (!isVertexDefined(set_vertex_data, test_iterations[n_set].n_vertices, base_vertex,
   2177 									 3)) /* components */
   2178 				{
   2179 					const char* primitive_mode = (n_iteration == 0) ? "triangles" : "quads";
   2180 
   2181 					m_testCtx.getLog() << tcu::TestLog::Message << "For primitive mode [" << primitive_mode << "] "
   2182 									   << "a vertex with tessellation coordinates:[" << base_vertex[0] << ", "
   2183 									   << base_vertex[1] << ", " << base_vertex[2] << ") "
   2184 									   << "could not have been found for both vertex orderings."
   2185 									   << tcu::TestLog::EndMessage;
   2186 
   2187 					TCU_FAIL("Implementation does not follow Rule 5.");
   2188 				}
   2189 			} /* for (all base set's vertices) */
   2190 		}	 /* for (all sets) */
   2191 	}		  /* for (both primitive types) */
   2192 }
   2193 
   2194 /** Constructor.
   2195  *
   2196  *  @param context Rendering context.
   2197  *
   2198  **/
   2199 TessellationShaderInvarianceRule6Test::TessellationShaderInvarianceRule6Test(Context&			  context,
   2200 																			 const ExtParameters& extParams)
   2201 	: TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule6",
   2202 										   "Verifies conformance with sixth invariance rule")
   2203 {
   2204 }
   2205 
   2206 /** Destructor. */
   2207 TessellationShaderInvarianceRule6Test::~TessellationShaderInvarianceRule6Test()
   2208 {
   2209 	/* Left blank intentionally */
   2210 }
   2211 
   2212 /** Retrieves amount of iterations the base test implementation should run before
   2213  *  calling global verification routine.
   2214  *
   2215  *  @return A value that depends on initTestIterations() behavior.
   2216  **/
   2217 unsigned int TessellationShaderInvarianceRule6Test::getAmountOfIterations()
   2218 {
   2219 	if (m_test_quads_iterations.size() == 0 || m_test_triangles_iterations.size() == 0)
   2220 	{
   2221 		initTestIterations();
   2222 	}
   2223 
   2224 	return (unsigned int)(m_test_quads_iterations.size() + m_test_triangles_iterations.size());
   2225 }
   2226 
   2227 /** Retrieves _test_iteration instance specific for user-specified iteration index.
   2228  *
   2229  *  @param n_iteration Iteration index to retrieve _test_iteration instance for.
   2230  *
   2231  * @return Iteration-specific _test_iteration instance.
   2232  *
   2233  **/
   2234 TessellationShaderInvarianceRule6Test::_test_iteration& TessellationShaderInvarianceRule6Test::getTestForIteration(
   2235 	unsigned int n_iteration)
   2236 {
   2237 	unsigned int	 n_triangles_tests = (unsigned int)m_test_triangles_iterations.size();
   2238 	_test_iteration& test_iteration	= (n_iteration < n_triangles_tests) ?
   2239 										  m_test_triangles_iterations[n_iteration] :
   2240 										  m_test_quads_iterations[n_iteration - n_triangles_tests];
   2241 
   2242 	return test_iteration;
   2243 }
   2244 
   2245 /** Retrieves iteration-specific tessellation properties.
   2246  *
   2247  *  @param n_iteration            Iteration index to retrieve the properties for.
   2248  *  @param out_inner_tess_levels  Deref will be used to store iteration-specific inner
   2249  *                                tessellation level values. Must not be NULL.
   2250  *  @param out_outer_tess_levels  Deref will be used to store iteration-specific outer
   2251  *                                tessellation level values. Must not be NULL.
   2252  *  @param out_point_mode         Deref will be used to store iteration-specific flag
   2253  *                                telling whether point mode should be enabled for given pass.
   2254  *                                Must not be NULL.
   2255  *  @param out_primitive_mode     Deref will be used to store iteration-specific primitive
   2256  *                                mode. Must not be NULL.
   2257  *  @param out_vertex_ordering    Deref will be used to store iteration-specific vertex
   2258  *                                ordering. Must not be NULL.
   2259  *  @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object
   2260  *                                storage should offer for the draw call to succeed. Can
   2261  *                                be NULL.
   2262  **/
   2263 void TessellationShaderInvarianceRule6Test::getIterationProperties(
   2264 	unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode,
   2265 	_tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering,
   2266 	unsigned int* out_result_buffer_size)
   2267 {
   2268 	DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration);
   2269 
   2270 	_test_iteration& test_iteration = getTestForIteration(n_iteration);
   2271 
   2272 	memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels));
   2273 	memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels));
   2274 
   2275 	*out_point_mode		 = false;
   2276 	*out_primitive_mode  = test_iteration.primitive_mode;
   2277 	*out_vertex_ordering = test_iteration.vertex_ordering;
   2278 
   2279 	if (out_result_buffer_size != DE_NULL)
   2280 	{
   2281 		*out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   2282 			*out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   2283 			*out_point_mode);
   2284 		test_iteration.n_vertices = *out_result_buffer_size;
   2285 		*out_result_buffer_size =
   2286 			static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float));
   2287 
   2288 		DE_ASSERT(*out_result_buffer_size != 0);
   2289 	}
   2290 }
   2291 
   2292 /** Retrieves iteration-specific tessellation evaluation shader code.
   2293  *
   2294  *  @param n_iteration Iteration index, for which the source code is being obtained.
   2295  *
   2296  *  @return Requested source code.
   2297  **/
   2298 std::string TessellationShaderInvarianceRule6Test::getTECode(unsigned int n_iteration)
   2299 {
   2300 	DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration);
   2301 
   2302 	const _test_iteration& test_iteration = getTestForIteration(n_iteration);
   2303 
   2304 	return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   2305 													 test_iteration.primitive_mode, test_iteration.vertex_ordering,
   2306 													 false); /* point mode */
   2307 }
   2308 
   2309 /** Initializes test iterations for the test. The following modes and inner/outer tess level
   2310  *  configurations are used to form the test set:
   2311  *
   2312  *  - Tessellation level combinations as returned by
   2313  *    TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode() (however, the inner
   2314  *    tessellation level values are all set to values corresponding to last item returned for
   2315  *    the set)
   2316  *  - All primitive modes;
   2317  *  - All vertex ordering modes;
   2318  *
   2319  *  All permutations are used to generate the test set.
   2320  **/
   2321 void TessellationShaderInvarianceRule6Test::initTestIterations()
   2322 {
   2323 	DE_ASSERT(m_test_quads_iterations.size() == 0 && m_test_triangles_iterations.size() == 0);
   2324 
   2325 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
   2326 	const glw::Functions& gl						  = m_context.getRenderContext().getFunctions();
   2327 	glw::GLint			  gl_max_tess_gen_level_value = 0;
   2328 
   2329 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
   2330 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
   2331 
   2332 	/* Iterate through all primitive and vertex spacing modes relevant to the test */
   2333 	_tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES,
   2334 													   TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS };
   2335 	_tessellation_shader_vertex_ordering vertex_ordering_modes[] = { TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
   2336 																	 TESSELLATION_SHADER_VERTEX_ORDERING_CW };
   2337 
   2338 	const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
   2339 	const unsigned int n_vo_modes		 = sizeof(vertex_ordering_modes) / sizeof(vertex_ordering_modes[0]);
   2340 
   2341 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
   2342 	{
   2343 		_tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode];
   2344 
   2345 		for (unsigned int n_vo_mode = 0; n_vo_mode < n_vo_modes; ++n_vo_mode)
   2346 		{
   2347 			_tessellation_shader_vertex_ordering vertex_ordering = vertex_ordering_modes[n_vo_mode];
   2348 
   2349 			/* Retrieve inner/outer tessellation level combinations we want the tests to be run for.
   2350 			 * Since each level set we will be provided by getTessellationLevelSetForPrimitiveMode()
   2351 			 * is unique and does not repeat, we'll just make sure the inner level values are set to
   2352 			 * the same set of values, so that the conditions the test must meet are actually met.
   2353 			 */
   2354 			float*					 inner_levels_to_use = DE_NULL;
   2355 			_tessellation_levels_set levels_set;
   2356 			unsigned int			 n_levels_sets = 0;
   2357 
   2358 			levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
   2359 				primitive_mode, gl_max_tess_gen_level_value,
   2360 				TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
   2361 
   2362 			n_levels_sets		= (unsigned int)levels_set.size();
   2363 			inner_levels_to_use = levels_set[n_levels_sets - 1].inner;
   2364 
   2365 			for (unsigned int n_levels_set = 0; n_levels_set < n_levels_sets - 1; n_levels_set++)
   2366 			{
   2367 				/* Make sure the Utils function was not changed and that inner level values
   2368 				 * are actually unique across the whole set */
   2369 				DE_ASSERT(levels_set[n_levels_set].inner[0] != levels_set[n_levels_sets - 1].inner[0] &&
   2370 						  levels_set[n_levels_set].inner[1] != levels_set[n_levels_sets - 1].inner[1]);
   2371 
   2372 				/* Force the last set's inner values to all level combinations we'll be using */
   2373 				memcpy(levels_set[n_levels_set].inner, inner_levels_to_use, sizeof(levels_set[n_levels_set].inner));
   2374 			} /* for (all sets retrieved from Utils function */
   2375 
   2376 			for (_tessellation_levels_set_const_iterator set_iterator = levels_set.begin();
   2377 				 set_iterator != levels_set.end(); set_iterator++)
   2378 			{
   2379 				const _tessellation_levels& levels = *set_iterator;
   2380 
   2381 				/* Create a test descriptor for all the parameters we now have */
   2382 				_test_iteration test;
   2383 
   2384 				memcpy(test.inner_tess_levels, levels.inner, sizeof(test.inner_tess_levels));
   2385 				memcpy(test.outer_tess_levels, levels.outer, sizeof(test.outer_tess_levels));
   2386 
   2387 				test.primitive_mode  = primitive_mode;
   2388 				test.vertex_ordering = vertex_ordering;
   2389 
   2390 				if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES)
   2391 				{
   2392 					m_test_triangles_iterations.push_back(test);
   2393 				}
   2394 				else
   2395 				{
   2396 					m_test_quads_iterations.push_back(test);
   2397 				}
   2398 			} /* for (all level sets) */
   2399 		}	 /* for (all vertex ordering modes) */
   2400 	}		  /* for (all primitive modes) */
   2401 }
   2402 
   2403 /** Verifies result data. Accesses data generated by all iterations.
   2404  *
   2405  *  Throws TestError exception if an error occurs.
   2406  *
   2407  *  @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord
   2408  *                             data generated by subsequent iterations.
   2409  **/
   2410 void TessellationShaderInvarianceRule6Test::verifyResultData(const void** all_iterations_data)
   2411 {
   2412 	/* Run two separate iterations:
   2413 	 *
   2414 	 * a) triangles
   2415 	 * b) quads
   2416 	 */
   2417 
   2418 	for (unsigned int n_iteration = 0; n_iteration < 2 /* quads, triangles */; ++n_iteration)
   2419 	{
   2420 		const unsigned int n_base_iteration =
   2421 			(n_iteration == 0) ? 0 : (const unsigned int)m_test_triangles_iterations.size();
   2422 
   2423 		const unsigned int n_sets = (n_iteration == 0) ? (const unsigned int)m_test_triangles_iterations.size() :
   2424 														 (const unsigned int)m_test_quads_iterations.size();
   2425 
   2426 		_tessellation_primitive_mode primitive_mode = (n_iteration == 0) ?
   2427 														  TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES :
   2428 														  TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS;
   2429 
   2430 		const _test_iterations& test_iterations =
   2431 			(n_iteration == 0) ? m_test_triangles_iterations : m_test_quads_iterations;
   2432 
   2433 		const unsigned int n_triangles_in_base_set = test_iterations[0].n_vertices / 3 /* vertices per triangle */;
   2434 
   2435 		DE_ASSERT(test_iterations.size() != 0);
   2436 
   2437 		/* For each iteration, verify that all vertices generated for all three vertex spacing modes.
   2438 		 * are exactly the same (but in different order) */
   2439 		const _test_iteration& base_test		= test_iterations[0];
   2440 		const float*		   base_vertex_data = (const float*)all_iterations_data[n_base_iteration + 0];
   2441 
   2442 		for (unsigned int n_set = 1; n_set < n_sets; ++n_set)
   2443 		{
   2444 			const _test_iteration& set_test		   = test_iterations[n_set];
   2445 			const float*		   set_vertex_data = (const float*)all_iterations_data[n_base_iteration + n_set];
   2446 
   2447 			/* We're operating on triangles so make sure the amount of vertices we're dealing with is
   2448 			 * divisible by 3 */
   2449 			DE_ASSERT((test_iterations[n_set].n_vertices % 3) == 0);
   2450 
   2451 			const unsigned int n_triangles_in_curr_set = test_iterations[n_set].n_vertices / 3;
   2452 
   2453 			/* Take base triangles and make sure they can be found in iteration-specific set.
   2454 			 * Now, thing to keep in mind here is that we must not assume any specific vertex
   2455 			 * and triangle order which is why the slow search. */
   2456 			for (unsigned int n_base_triangle = 0; n_base_triangle < n_triangles_in_base_set; ++n_base_triangle)
   2457 			{
   2458 				/* Extract base triangle data first */
   2459 				const float* base_triangle_vertex1 = base_vertex_data +
   2460 													 n_base_triangle * 3 *		/* vertices per triangle */
   2461 														 3;						/* components */
   2462 				const float* base_triangle_vertex2 = base_triangle_vertex1 + 3; /* components */
   2463 				const float* base_triangle_vertex3 = base_triangle_vertex2 + 3; /* components */
   2464 
   2465 				/* Only interior triangles should be left intact. Is this an interior triangle? */
   2466 				if (!TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex1) &&
   2467 					!TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex2) &&
   2468 					!TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex3))
   2469 				{
   2470 					/* Iterate through all triangles in considered set */
   2471 					bool has_base_set_triangle_been_found = false;
   2472 
   2473 					for (unsigned int n_curr_set_triangle = 0; n_curr_set_triangle < n_triangles_in_curr_set;
   2474 						 ++n_curr_set_triangle)
   2475 					{
   2476 						const float* curr_triangle = set_vertex_data +
   2477 													 n_curr_set_triangle * 3 * /* vertices per triangle */
   2478 														 3;					   /* components */
   2479 
   2480 						if (TessellationShaderUtils::isTriangleDefined(base_triangle_vertex1, curr_triangle))
   2481 						{
   2482 							has_base_set_triangle_been_found = true;
   2483 
   2484 							break;
   2485 						}
   2486 					} /* for (all triangles in currently processed set) */
   2487 
   2488 					if (!has_base_set_triangle_been_found)
   2489 					{
   2490 						std::string primitive_mode_str =
   2491 							TessellationShaderUtils::getESTokenForPrimitiveMode(base_test.primitive_mode);
   2492 
   2493 						m_testCtx.getLog()
   2494 							<< tcu::TestLog::Message << "For primitive mode [" << primitive_mode_str << "]"
   2495 							<< ", base inner tessellation levels:"
   2496 							<< "[" << base_test.inner_tess_levels[0] << ", " << base_test.inner_tess_levels[1] << "]"
   2497 							<< ", base outer tessellation levels:"
   2498 							<< "[" << base_test.outer_tess_levels[0] << ", " << base_test.outer_tess_levels[1] << ", "
   2499 							<< base_test.outer_tess_levels[2] << ", " << base_test.outer_tess_levels[3] << "]"
   2500 							<< ", reference inner tessellation levels:"
   2501 							<< "[" << set_test.inner_tess_levels[0] << ", " << set_test.inner_tess_levels[1] << "]"
   2502 							<< ", reference outer tessellation levels:"
   2503 							<< "[" << set_test.outer_tess_levels[0] << ", " << set_test.outer_tess_levels[1] << ", "
   2504 							<< set_test.outer_tess_levels[2] << ", " << set_test.outer_tess_levels[3] << "]"
   2505 							<< ", the following triangle formed during base tessellation run was not found in "
   2506 							   "reference run:"
   2507 							<< "[" << base_triangle_vertex1[0] << ", " << base_triangle_vertex1[1] << ", "
   2508 							<< base_triangle_vertex1[2] << "]x"
   2509 							<< "[" << base_triangle_vertex2[0] << ", " << base_triangle_vertex2[1] << ", "
   2510 							<< base_triangle_vertex2[2] << "]x"
   2511 							<< "[" << base_triangle_vertex3[0] << ", " << base_triangle_vertex3[1] << ", "
   2512 							<< base_triangle_vertex3[2]
   2513 
   2514 							<< tcu::TestLog::EndMessage;
   2515 
   2516 						TCU_FAIL("Implementation does not appear to be rule 6-conformant");
   2517 					} /* if (triangle created during base run was not found in reference run) */
   2518 				}	 /* if (base triangle is interior) */
   2519 			}		  /* for (all base set's vertices) */
   2520 		}			  /* for (all sets) */
   2521 	}				  /* for (both primitive types) */
   2522 }
   2523 
   2524 /** Constructor.
   2525  *
   2526  *  @param context Rendering context.
   2527  *
   2528  **/
   2529 TessellationShaderInvarianceRule7Test::TessellationShaderInvarianceRule7Test(Context&			  context,
   2530 																			 const ExtParameters& extParams)
   2531 	: TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule7",
   2532 										   "Verifies conformance with seventh invariance rule")
   2533 {
   2534 }
   2535 
   2536 /** Destructor. */
   2537 TessellationShaderInvarianceRule7Test::~TessellationShaderInvarianceRule7Test()
   2538 {
   2539 	/* Left blank intentionally */
   2540 }
   2541 
   2542 /** Retrieves amount of iterations the base test implementation should run before
   2543  *  calling global verification routine.
   2544  *
   2545  *  @return A value that depends on initTestIterations() behavior.
   2546  **/
   2547 unsigned int TessellationShaderInvarianceRule7Test::getAmountOfIterations()
   2548 {
   2549 	if (m_test_quads_iterations.size() == 0 || m_test_triangles_iterations.size() == 0)
   2550 	{
   2551 		initTestIterations();
   2552 	}
   2553 
   2554 	return (unsigned int)(m_test_quads_iterations.size() + m_test_triangles_iterations.size());
   2555 }
   2556 
   2557 /** Retrieves index of a test iteration that was initialized with user-provided
   2558  *  properties.
   2559  *
   2560  *  @param is_triangles_iteration      true if the seeked test iteration should have
   2561  *                                     been run for 'triangles' primitive mode', false
   2562  *                                     if 'quads' primitive mode run is seeked.
   2563  *  @param inner_tess_levels           Two FP values describing inner tessellation level
   2564  *                                     values the seeked run should have used.
   2565  *  @param outer_tess_levels           Four FP values describing outer tessellation level
   2566  *                                     values the seeked run should have used.
   2567  *  @param vertex_ordering             Vertex ordering mode the seeked run should have used.
   2568  *  @param n_modified_outer_tess_level Tells which outer tessellation level should be
   2569  *                                     excluded from checking.
   2570  *
   2571  *  @return 0xFFFFFFFF if no test iteration was run for user-provided properties,
   2572  *          actual index otherwise.
   2573  *
   2574  **/
   2575 unsigned int TessellationShaderInvarianceRule7Test::getTestIterationIndex(
   2576 	bool is_triangles_iteration, const float* inner_tess_levels, const float* outer_tess_levels,
   2577 	_tessellation_shader_vertex_ordering vertex_ordering, unsigned int n_modified_outer_tess_level)
   2578 {
   2579 	const float				epsilon = 1e-5f;
   2580 	unsigned int			result  = 0xFFFFFFFF;
   2581 	const _test_iterations& test_iterations =
   2582 		(is_triangles_iteration) ? m_test_triangles_iterations : m_test_quads_iterations;
   2583 	const unsigned int n_test_iterations = (const unsigned int)test_iterations.size();
   2584 
   2585 	for (unsigned int n_test_iteration = 0; n_test_iteration < n_test_iterations; ++n_test_iteration)
   2586 	{
   2587 		_test_iteration test_iteration = test_iterations[n_test_iteration];
   2588 
   2589 		if (de::abs(test_iteration.inner_tess_levels[0] - inner_tess_levels[0]) < epsilon &&
   2590 			de::abs(test_iteration.inner_tess_levels[1] - inner_tess_levels[1]) < epsilon &&
   2591 			test_iteration.vertex_ordering == vertex_ordering &&
   2592 			test_iteration.n_modified_outer_tess_level == n_modified_outer_tess_level)
   2593 		{
   2594 			/* Only compare outer tessellation levels that have not been modified */
   2595 			if (((n_modified_outer_tess_level == 0) ||
   2596 				 (n_modified_outer_tess_level != 0 &&
   2597 				  de::abs(test_iteration.outer_tess_levels[0] - outer_tess_levels[0]) < epsilon)) &&
   2598 				((n_modified_outer_tess_level == 1) ||
   2599 				 (n_modified_outer_tess_level != 1 &&
   2600 				  de::abs(test_iteration.outer_tess_levels[1] - outer_tess_levels[1]) < epsilon)) &&
   2601 				((n_modified_outer_tess_level == 2) ||
   2602 				 (n_modified_outer_tess_level != 2 &&
   2603 				  de::abs(test_iteration.outer_tess_levels[2] - outer_tess_levels[2]) < epsilon)) &&
   2604 				((n_modified_outer_tess_level == 3) ||
   2605 				 (n_modified_outer_tess_level != 3 &&
   2606 				  de::abs(test_iteration.outer_tess_levels[3] - outer_tess_levels[3]) < epsilon)))
   2607 			{
   2608 				result = n_test_iteration;
   2609 
   2610 				break;
   2611 			}
   2612 		}
   2613 	} /* for (all test iterations) */
   2614 
   2615 	return result;
   2616 }
   2617 
   2618 /** Retrieves _test_iteration instance specific for user-specified iteration index.
   2619  *
   2620  *  @param n_iteration Iteration index to retrieve _test_iteration instance for.
   2621  *
   2622  * @return Iteration-specific _test_iteration instance.
   2623  *
   2624  **/
   2625 TessellationShaderInvarianceRule7Test::_test_iteration& TessellationShaderInvarianceRule7Test::getTestForIteration(
   2626 	unsigned int n_iteration)
   2627 {
   2628 	unsigned int	 n_triangles_tests = (unsigned int)m_test_triangles_iterations.size();
   2629 	_test_iteration& test_iteration	= (n_iteration < n_triangles_tests) ?
   2630 										  m_test_triangles_iterations[n_iteration] :
   2631 										  m_test_quads_iterations[n_iteration - n_triangles_tests];
   2632 
   2633 	return test_iteration;
   2634 }
   2635 
   2636 /** Retrieves iteration-specific tessellation properties.
   2637  *
   2638  *  @param n_iteration            Iteration index to retrieve the properties for.
   2639  *  @param out_inner_tess_levels  Deref will be used to store iteration-specific inner
   2640  *                                tessellation level values. Must not be NULL.
   2641  *  @param out_outer_tess_levels  Deref will be used to store iteration-specific outer
   2642  *                                tessellation level values. Must not be NULL.
   2643  *  @param out_point_mode         Deref will be used to store iteration-specific flag
   2644  *                                telling whether point mode should be enabled for given pass.
   2645  *                                Must not be NULL.
   2646  *  @param out_primitive_mode     Deref will be used to store iteration-specific primitive
   2647  *                                mode. Must not be NULL.
   2648  *  @param out_vertex_ordering    Deref will be used to store iteration-specific vertex
   2649  *                                ordering. Must not be NULL.
   2650  *  @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object
   2651  *                                storage should offer for the draw call to succeed. Can
   2652  *                                be NULL.
   2653  **/
   2654 void TessellationShaderInvarianceRule7Test::getIterationProperties(
   2655 	unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode,
   2656 	_tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering,
   2657 	unsigned int* out_result_buffer_size)
   2658 {
   2659 	DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration);
   2660 
   2661 	_test_iteration& test_iteration = getTestForIteration(n_iteration);
   2662 
   2663 	memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels));
   2664 	memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels));
   2665 
   2666 	*out_point_mode		 = false;
   2667 	*out_primitive_mode  = test_iteration.primitive_mode;
   2668 	*out_vertex_ordering = test_iteration.vertex_ordering;
   2669 
   2670 	if (out_result_buffer_size != DE_NULL)
   2671 	{
   2672 		*out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
   2673 			*out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   2674 			*out_point_mode);
   2675 		test_iteration.n_vertices = *out_result_buffer_size;
   2676 		*out_result_buffer_size =
   2677 			static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float));
   2678 
   2679 		DE_ASSERT(*out_result_buffer_size != 0);
   2680 	}
   2681 }
   2682 
   2683 /** Retrieves iteration-specific tessellation evaluation shader code.
   2684  *
   2685  *  @param n_iteration Iteration index, for which the source code is being obtained.
   2686  *
   2687  *  @return Requested source code.
   2688  **/
   2689 std::string TessellationShaderInvarianceRule7Test::getTECode(unsigned int n_iteration)
   2690 {
   2691 	DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration);
   2692 
   2693 	const _test_iteration& test_iteration = getTestForIteration(n_iteration);
   2694 
   2695 	return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
   2696 													 test_iteration.primitive_mode, test_iteration.vertex_ordering,
   2697 													 false); /* point mode */
   2698 }
   2699 
   2700 /** Initializes test iterations for the test. The following modes and inner/outer tess level
   2701  *  configurations are used to form the test set:
   2702  *
   2703  *  - All inner/outer tessellation level combinations as returned by
   2704  *    TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode()
   2705  *    times 3 (for triangles) or 4 (for quads). For each combination,
   2706  *    the test will capture tessellation coordinates multiple times, each
   2707  *    time changing a different outer tessellation level value and leaving
   2708  *    the rest intact.
   2709  *  - All primitive modes;
   2710  *  - All vertex spacing modes;
   2711  *
   2712  *  All permutations are used to generate the test set.
   2713  **/
   2714 void TessellationShaderInvarianceRule7Test::initTestIterations()
   2715 {
   2716 	DE_ASSERT(m_test_quads_iterations.size() == 0 && m_test_triangles_iterations.size() == 0);
   2717 
   2718 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
   2719 	const glw::Functions& gl						  = m_context.getRenderContext().getFunctions();
   2720 	glw::GLint			  gl_max_tess_gen_level_value = 0;
   2721 
   2722 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
   2723 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
   2724 
   2725 	/* Iterate through all primitive and vertex spacing modes relevant to the test */
   2726 	_tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
   2727 													   TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
   2728 	_tessellation_shader_vertex_ordering vo_modes[] = {
   2729 		TESSELLATION_SHADER_VERTEX_ORDERING_CCW, TESSELLATION_SHADER_VERTEX_ORDERING_CW,
   2730 	};
   2731 
   2732 	const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
   2733 	const unsigned int n_vo_modes		 = sizeof(vo_modes) / sizeof(vo_modes[0]);
   2734 
   2735 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
   2736 	{
   2737 		_tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode];
   2738 		const unsigned int			 n_relevant_outer_tess_levels =
   2739 			(primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS) ? 4 : 3;
   2740 
   2741 		for (unsigned int n_vo_mode = 0; n_vo_mode < n_vo_modes; ++n_vo_mode)
   2742 		{
   2743 			_tessellation_shader_vertex_ordering vertex_ordering = vo_modes[n_vo_mode];
   2744 
   2745 			/* Retrieve inner/outer tessellation level combinations we want the tests to be run for */
   2746 			_tessellation_levels_set levels_set;
   2747 
   2748 			levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
   2749 				primitive_mode, gl_max_tess_gen_level_value,
   2750 				TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
   2751 
   2752 			/* Create test descriptor for all inner/outer level configurations we received from the utils function. */
   2753 			for (_tessellation_levels_set_const_iterator levels_set_iterator = levels_set.begin();
   2754 				 levels_set_iterator != levels_set.end(); levels_set_iterator++)
   2755 			{
   2756 				const _tessellation_levels& levels = *levels_set_iterator;
   2757 
   2758 				for (unsigned int n_outer_level_to_change = 0;
   2759 					 n_outer_level_to_change < n_relevant_outer_tess_levels + 1 /* base iteration */;
   2760 					 ++n_outer_level_to_change)
   2761 				{
   2762 					/* Create a test descriptor for all the parameters we now have */
   2763 					_test_iteration test;
   2764 
   2765 					memcpy(test.inner_tess_levels, levels.inner, sizeof(test.inner_tess_levels));
   2766 					memcpy(test.outer_tess_levels, levels.outer, sizeof(test.outer_tess_levels));
   2767 
   2768 					test.primitive_mode  = primitive_mode;
   2769 					test.vertex_ordering = vertex_ordering;
   2770 
   2771 					/* Change iteration-specific outer tessellation level to a different value, but only
   2772 					 * if we're not preparing a base iteration*/
   2773 					if (n_outer_level_to_change != n_relevant_outer_tess_levels)
   2774 					{
   2775 						test.n_modified_outer_tess_level				= n_outer_level_to_change;
   2776 						test.outer_tess_levels[n_outer_level_to_change] = (float)(gl_max_tess_gen_level_value) / 3.0f;
   2777 					}
   2778 					else
   2779 					{
   2780 						test.is_base_iteration = true;
   2781 					}
   2782 
   2783 					if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES)
   2784 					{
   2785 						m_test_triangles_iterations.push_back(test);
   2786 					}
   2787 					else
   2788 					{
   2789 						m_test_quads_iterations.push_back(test);
   2790 					}
   2791 				}
   2792 			} /* for (all levels set entries) */
   2793 		}	 /* for (all vertex spacing modes) */
   2794 	}		  /* for (all primitive modes) */
   2795 }
   2796 
   2797 /** Tells whether a triangle is included in user-provided set of triangles.
   2798  *  The triangle is expected to use an undefined vertex ordering.
   2799  *
   2800  *  @param base_triangle_data     9 FP values defining 3 vertices of a triangle.
   2801  *  @param vertex_data            Vertex stream. It is expected these vertices
   2802  *                                form triangles. It is also assumed each vertex
   2803  *                                is expressed with 3 components.
   2804  *  @param vertex_data_n_vertices Amount of vertices that can be found in @param
   2805  *                                vertex_data
   2806  *
   2807  *  @return true if the triangle was found in user-provided triangle set,
   2808  *          false otherwise.
   2809  *
   2810  **/
   2811 bool TessellationShaderInvarianceRule7Test::isTriangleDefinedInVertexDataSet(const float* base_triangle_data,
   2812 																			 const float* vertex_data,
   2813 																			 unsigned int vertex_data_n_vertices)
   2814 {
   2815 	bool result = false;
   2816 
   2817 	for (unsigned int n_triangle = 0; n_triangle < vertex_data_n_vertices / 3 /* vertices per triangle */; n_triangle++)
   2818 	{
   2819 		const float* current_triangle_data = vertex_data +
   2820 											 n_triangle * 3 * /* vertices per triangle */
   2821 												 3;			  /* components */
   2822 
   2823 		if (TessellationShaderUtils::isTriangleDefined(current_triangle_data, base_triangle_data))
   2824 		{
   2825 			result = true;
   2826 
   2827 			break;
   2828 		}
   2829 	} /* for (all vertices) */
   2830 
   2831 	return result;
   2832 }
   2833 
   2834 /** Verifies result data. Accesses data generated by all iterations.
   2835  *
   2836  *  Throws TestError exception if an error occurs.
   2837  *
   2838  *  @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord
   2839  *                             data generated by subsequent iterations.
   2840  **/
   2841 void TessellationShaderInvarianceRule7Test::verifyResultData(const void** all_iterations_data)
   2842 {
   2843 	const float epsilon = 1e-5f;
   2844 
   2845 	/* Run two separate iterations:
   2846 	 *
   2847 	 * a) triangles
   2848 	 * b) quads
   2849 	 */
   2850 	for (unsigned int n_iteration = 0; n_iteration < 2 /* triangles, quads */; ++n_iteration)
   2851 	{
   2852 		bool			   is_triangles_iteration = (n_iteration == 0);
   2853 		const unsigned int n_base_iteration =
   2854 			(n_iteration == 0) ? 0 : (const unsigned int)m_test_triangles_iterations.size();
   2855 		const unsigned int n_relevant_outer_tess_levels = (is_triangles_iteration) ? 3 : 4;
   2856 
   2857 		_tessellation_primitive_mode primitive_mode = (n_iteration == 0) ?
   2858 														  TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES :
   2859 														  TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS;
   2860 
   2861 		const _test_iterations& test_iterations =
   2862 			(n_iteration == 0) ? m_test_triangles_iterations : m_test_quads_iterations;
   2863 
   2864 		DE_ASSERT(test_iterations.size() != 0);
   2865 
   2866 		/* Find a base iteration first */
   2867 		for (unsigned int n_base_test_iteration = 0; n_base_test_iteration < test_iterations.size();
   2868 			 n_base_test_iteration++)
   2869 		{
   2870 			const _test_iteration& base_iteration = test_iterations[n_base_test_iteration];
   2871 			std::vector<int>	   ref_iteration_indices;
   2872 
   2873 			if (!base_iteration.is_base_iteration)
   2874 			{
   2875 				continue;
   2876 			}
   2877 
   2878 			/* Retrieve reference test iterations */
   2879 			for (unsigned int n_reference_iteration = 0; n_reference_iteration < n_relevant_outer_tess_levels;
   2880 				 ++n_reference_iteration)
   2881 			{
   2882 				const unsigned int n_modified_outer_tess_level =
   2883 					(base_iteration.n_modified_outer_tess_level + n_reference_iteration + 1) %
   2884 					n_relevant_outer_tess_levels;
   2885 				const unsigned int ref_iteration_index = getTestIterationIndex(
   2886 					is_triangles_iteration, base_iteration.inner_tess_levels, base_iteration.outer_tess_levels,
   2887 					base_iteration.vertex_ordering, n_modified_outer_tess_level);
   2888 
   2889 				DE_ASSERT(ref_iteration_index != 0xFFFFFFFF);
   2890 				DE_ASSERT(ref_iteration_index != n_base_test_iteration);
   2891 
   2892 				ref_iteration_indices.push_back(ref_iteration_index);
   2893 			}
   2894 
   2895 			/* We can now start comparing base data with the information generated for
   2896 			 * reference iterations. */
   2897 			for (std::vector<int>::const_iterator ref_iteration_iterator = ref_iteration_indices.begin();
   2898 				 ref_iteration_iterator != ref_iteration_indices.end(); ref_iteration_iterator++)
   2899 			{
   2900 				const int&			   n_ref_test_iteration = *ref_iteration_iterator;
   2901 				const _test_iteration& ref_iteration		= test_iterations[n_ref_test_iteration];
   2902 
   2903 				/* Now move through all triangles generated for base test iteration. Focus on the ones
   2904 				 * that connect the outer edge with one of the inner ones */
   2905 				const float* base_iteration_vertex_data =
   2906 					(const float*)all_iterations_data[n_base_iteration + n_base_test_iteration];
   2907 				const float* ref_iteration_vertex_data =
   2908 					(const float*)all_iterations_data[n_base_iteration + n_ref_test_iteration];
   2909 
   2910 				for (unsigned int n_base_triangle = 0;
   2911 					 n_base_triangle < base_iteration.n_vertices / 3; /* vertices per triangle */
   2912 					 ++n_base_triangle)
   2913 				{
   2914 					const float* base_triangle_data =
   2915 						base_iteration_vertex_data + n_base_triangle * 3 /* vertices */ * 3; /* components */
   2916 
   2917 					/* Is that the triangle type we're after? */
   2918 					const float* base_triangle_vertex1 = base_triangle_data;
   2919 					const float* base_triangle_vertex2 = base_triangle_vertex1 + 3; /* components */
   2920 					const float* base_triangle_vertex3 = base_triangle_vertex2 + 3; /* components */
   2921 					bool		 is_base_triangle_vertex1_outer =
   2922 						TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex1);
   2923 					bool is_base_triangle_vertex2_outer =
   2924 						TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex2);
   2925 					bool is_base_triangle_vertex3_outer =
   2926 						TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex3);
   2927 					unsigned int n_outer_edge_vertices_found = 0;
   2928 
   2929 					n_outer_edge_vertices_found += (is_base_triangle_vertex1_outer == true);
   2930 					n_outer_edge_vertices_found += (is_base_triangle_vertex2_outer == true);
   2931 					n_outer_edge_vertices_found += (is_base_triangle_vertex3_outer == true);
   2932 
   2933 					if (n_outer_edge_vertices_found == 0)
   2934 					{
   2935 						/* This is an inner triangle, not really of our interest */
   2936 						continue;
   2937 					}
   2938 
   2939 					/* Which outer tessellation level describes the base data edge? */
   2940 					unsigned int n_base_tess_level = 0;
   2941 
   2942 					if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES)
   2943 					{
   2944 						if ((!is_base_triangle_vertex1_outer ||
   2945 							 (is_base_triangle_vertex1_outer && base_triangle_vertex1[0] == 0.0f)) &&
   2946 							(!is_base_triangle_vertex2_outer ||
   2947 							 (is_base_triangle_vertex2_outer && base_triangle_vertex2[0] == 0.0f)) &&
   2948 							(!is_base_triangle_vertex3_outer ||
   2949 							 (is_base_triangle_vertex3_outer && base_triangle_vertex3[0] == 0.0f)))
   2950 						{
   2951 							n_base_tess_level = 0;
   2952 						}
   2953 						else if ((!is_base_triangle_vertex1_outer ||
   2954 								  (is_base_triangle_vertex1_outer && base_triangle_vertex1[1] == 0.0f)) &&
   2955 								 (!is_base_triangle_vertex2_outer ||
   2956 								  (is_base_triangle_vertex2_outer && base_triangle_vertex2[1] == 0.0f)) &&
   2957 								 (!is_base_triangle_vertex3_outer ||
   2958 								  (is_base_triangle_vertex3_outer && base_triangle_vertex3[1] == 0.0f)))
   2959 						{
   2960 							n_base_tess_level = 1;
   2961 						}
   2962 						else
   2963 						{
   2964 							DE_ASSERT((!is_base_triangle_vertex1_outer ||
   2965 									   (is_base_triangle_vertex1_outer && base_triangle_vertex1[2] == 0.0f)) &&
   2966 									  (!is_base_triangle_vertex2_outer ||
   2967 									   (is_base_triangle_vertex2_outer && base_triangle_vertex2[2] == 0.0f)) &&
   2968 									  (!is_base_triangle_vertex3_outer ||
   2969 									   (is_base_triangle_vertex3_outer && base_triangle_vertex3[2] == 0.0f)));
   2970 
   2971 							n_base_tess_level = 2;
   2972 						}
   2973 					} /* if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES) */
   2974 					else
   2975 					{
   2976 						DE_ASSERT(primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS);
   2977 
   2978 						std::size_t				  n_outer_edge_vertices = 0;
   2979 						std::vector<const float*> outer_edge_vertices;
   2980 
   2981 						if (is_base_triangle_vertex1_outer)
   2982 						{
   2983 							outer_edge_vertices.push_back(base_triangle_vertex1);
   2984 						}
   2985 
   2986 						if (is_base_triangle_vertex2_outer)
   2987 						{
   2988 							outer_edge_vertices.push_back(base_triangle_vertex2);
   2989 						}
   2990 
   2991 						if (is_base_triangle_vertex3_outer)
   2992 						{
   2993 							outer_edge_vertices.push_back(base_triangle_vertex3);
   2994 						}
   2995 
   2996 						n_outer_edge_vertices = outer_edge_vertices.size();
   2997 
   2998 						DE_ASSERT(n_outer_edge_vertices >= 1 && n_outer_edge_vertices <= 2);
   2999 
   3000 						bool is_top_outer_edge	= true;
   3001 						bool is_right_outer_edge  = true;
   3002 						bool is_bottom_outer_edge = true;
   3003 						bool is_left_outer_edge   = true;
   3004 
   3005 						/* Find which outer edges the vertices don't belong to. If one is in a corner,
   3006 						 * the other will clarify to which edge both vertices belong. */
   3007 						for (unsigned int n_vertex = 0; n_vertex < n_outer_edge_vertices; ++n_vertex)
   3008 						{
   3009 							/* Y < 1, not top outer edge */
   3010 							if (de::abs(outer_edge_vertices[n_vertex][1] - 1.0f) > epsilon)
   3011 							{
   3012 								is_top_outer_edge = false;
   3013 							}
   3014 
   3015 							/* X < 1, not right outer edge */
   3016 							if (de::abs(outer_edge_vertices[n_vertex][0] - 1.0f) > epsilon)
   3017 							{
   3018 								is_right_outer_edge = false;
   3019 							}
   3020 
   3021 							/* Y > 0, not bottom outer edge */
   3022 							if (de::abs(outer_edge_vertices[n_vertex][1]) > epsilon)
   3023 							{
   3024 								is_bottom_outer_edge = false;
   3025 							}
   3026 
   3027 							/* X > 0, not left outer edge */
   3028 							if (de::abs(outer_edge_vertices[n_vertex][0]) > epsilon)
   3029 							{
   3030 								is_left_outer_edge = false;
   3031 							}
   3032 						}
   3033 
   3034 						if (n_outer_edge_vertices == 1)
   3035 						{
   3036 							/* A single vertex with corner-coordinates belongs to two edges. Choose one */
   3037 							bool x_is_0 = de::abs(outer_edge_vertices[0][0]) < epsilon;
   3038 							bool x_is_1 = de::abs(outer_edge_vertices[0][0] - 1.0f) < epsilon;
   3039 							bool y_is_0 = de::abs(outer_edge_vertices[0][1]) < epsilon;
   3040 							bool y_is_1 = de::abs(outer_edge_vertices[0][1] - 1.0f) < epsilon;
   3041 
   3042 							if (x_is_0 && y_is_0)
   3043 							{
   3044 								/* bottom edge */
   3045 								DE_ASSERT(is_left_outer_edge && is_bottom_outer_edge);
   3046 								is_left_outer_edge = false;
   3047 							}
   3048 							else if (x_is_0 && y_is_1)
   3049 							{
   3050 								/* left edge */
   3051 								DE_ASSERT(is_left_outer_edge && is_top_outer_edge);
   3052 								is_top_outer_edge = false;
   3053 							}
   3054 							else if (x_is_1 && y_is_0)
   3055 							{
   3056 								/* right edge */
   3057 								DE_ASSERT(is_right_outer_edge && is_bottom_outer_edge);
   3058 								is_bottom_outer_edge = false;
   3059 							}
   3060 							else if (x_is_1 && y_is_1)
   3061 							{
   3062 								/* top edge */
   3063 								DE_ASSERT(is_right_outer_edge && is_top_outer_edge);
   3064 								is_right_outer_edge = false;
   3065 							}
   3066 							else
   3067 							{
   3068 								/* Not a corner vertex, only one of the edge-flags is set */
   3069 							}
   3070 						}
   3071 
   3072 						/* Sanity checks */
   3073 						DE_UNREF(is_top_outer_edge);
   3074 						DE_ASSERT((is_left_outer_edge && !is_top_outer_edge && !is_bottom_outer_edge &&
   3075 								   !is_right_outer_edge) ||
   3076 								  (!is_left_outer_edge && is_top_outer_edge && !is_bottom_outer_edge &&
   3077 								   !is_right_outer_edge) ||
   3078 								  (!is_left_outer_edge && !is_top_outer_edge && is_bottom_outer_edge &&
   3079 								   !is_right_outer_edge) ||
   3080 								  (!is_left_outer_edge && !is_top_outer_edge && !is_bottom_outer_edge &&
   3081 								   is_right_outer_edge));
   3082 
   3083 						/* We have all the data needed to determine which tessellation level describes
   3084 						 * subdivision of the edge that the triangle touches */
   3085 						if (is_left_outer_edge)
   3086 						{
   3087 							n_base_tess_level = 0;
   3088 						}
   3089 						else if (is_bottom_outer_edge)
   3090 						{
   3091 							n_base_tess_level = 1;
   3092 						}
   3093 						else if (is_right_outer_edge)
   3094 						{
   3095 							n_base_tess_level = 2;
   3096 						}
   3097 						else
   3098 						{
   3099 							n_base_tess_level = 3;
   3100 						}
   3101 					}
   3102 
   3103 					/* We shouldn't perform the check if the edge we're processing was described
   3104 					 * by a different outer tessellation level in the reference data set */
   3105 					if (n_base_tess_level == ref_iteration.n_modified_outer_tess_level)
   3106 					{
   3107 						continue;
   3108 					}
   3109 
   3110 					/* This triangle should be present in both vertex data sets */
   3111 					if (!isTriangleDefinedInVertexDataSet(base_triangle_data, ref_iteration_vertex_data,
   3112 														  ref_iteration.n_vertices))
   3113 					{
   3114 						const char* primitive_mode_str = (is_triangles_iteration) ? "triangles" : "quads";
   3115 
   3116 						m_testCtx.getLog()
   3117 							<< tcu::TestLog::Message << "For primitive mode [" << primitive_mode_str << "] "
   3118 							<< ", inner tessellation levels:"
   3119 							<< "[" << base_iteration.inner_tess_levels[0] << ", " << base_iteration.inner_tess_levels[1]
   3120 							<< "], outer tessellation levels:"
   3121 							<< "[" << base_iteration.outer_tess_levels[0] << ", " << base_iteration.outer_tess_levels[1]
   3122 							<< ", " << base_iteration.outer_tess_levels[2] << ", "
   3123 							<< base_iteration.outer_tess_levels[3] << "], a triangle connecting inner & outer edges:"
   3124 							<< "[" << base_triangle_vertex1[0] << ", " << base_triangle_vertex1[1] << ", "
   3125 							<< base_triangle_vertex1[2] << "]x"
   3126 							<< "[" << base_triangle_vertex2[0] << ", " << base_triangle_vertex2[1] << ", "
   3127 							<< base_triangle_vertex2[2] << "]x"
   3128 							<< "[" << base_triangle_vertex3[0] << ", " << base_triangle_vertex3[1] << ", "
   3129 							<< base_triangle_vertex3[2] << "] was not found for runs using CW and CCW vertex ordering, "
   3130 														   "which is against the extension specification's rule 7."
   3131 							<< tcu::TestLog::EndMessage;
   3132 
   3133 						TCU_FAIL("Implementation is not conformant with Tessellation Rule 7");
   3134 					}
   3135 				} /* for (all triangles generated for base test iteration) */
   3136 			}	 /* for (all reference iterations) */
   3137 		}		  /* for (all base test iterations) */
   3138 	}			  /* for (both primitive types) */
   3139 }
   3140 
   3141 } /* namespace glcts */
   3142