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 "esextcTessellationShaderTriangles.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 /** Constructor
     35  *
     36  * @param context Test context
     37  **/
     38 TessellationShaderTrianglesTests::TessellationShaderTrianglesTests(glcts::Context&		context,
     39 																   const ExtParameters& extParams)
     40 	: TestCaseGroupBase(context, extParams, "tessellation_shader_triangles_tessellation",
     41 						"Verifies triangle tessellation functionality")
     42 {
     43 	/* No implementation needed */
     44 }
     45 
     46 /**
     47  * Initializes test groups for geometry shader tests
     48  **/
     49 void TessellationShaderTrianglesTests::init(void)
     50 {
     51 	addChild(new glcts::TessellationShaderTrianglesDegenerateTriangle(m_context, m_extParams));
     52 	addChild(new glcts::TessellationShaderTrianglesIdenticalTriangles(m_context, m_extParams));
     53 	addChild(new glcts::TessellationShaderTrianglesInnerTessellationLevelRounding(m_context, m_extParams));
     54 }
     55 
     56 /** Constructor
     57  *
     58  * @param context Test context
     59  **/
     60 TessellationShaderTrianglesDegenerateTriangle::TessellationShaderTrianglesDegenerateTriangle(
     61 	Context& context, const ExtParameters& extParams)
     62 	: TestCaseBase(context, extParams, "degenerate_triangle",
     63 				   "Verifies a degenerate triangle is generated by tessellator "
     64 				   "under a specific configuration of inner/outer tessellation "
     65 				   "levels & vertex spacing modes.")
     66 	, m_bo_id(0)
     67 	, m_fs_id(0)
     68 	, m_tc_id(0)
     69 	, m_vs_id(0)
     70 	, m_vao_id(0)
     71 {
     72 	/* Left blank on purpose */
     73 }
     74 
     75 /** Deinitializes ES objects created for the test. */
     76 void TessellationShaderTrianglesDegenerateTriangle::deinit()
     77 {
     78 	/* Call base class' deinit() */
     79 	TestCaseBase::deinit();
     80 
     81 	if (!m_is_tessellation_shader_supported)
     82 	{
     83 		return;
     84 	}
     85 
     86 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
     87 
     88 	/* Deinitialize TF buffer object bindings */
     89 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
     90 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
     91 
     92 	/* Reset GL_PATCH_VERTICES_EXT value */
     93 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
     94 
     95 	/* Unbind vertex array object */
     96 	gl.bindVertexArray(0);
     97 
     98 	/* Free all ES objects we allocated for the test */
     99 	if (m_bo_id != 0)
    100 	{
    101 		gl.deleteBuffers(1, &m_bo_id);
    102 
    103 		m_bo_id = 0;
    104 	}
    105 
    106 	if (m_fs_id != 0)
    107 	{
    108 		gl.deleteShader(m_fs_id);
    109 
    110 		m_fs_id = 0;
    111 	}
    112 
    113 	if (m_tc_id != 0)
    114 	{
    115 		gl.deleteShader(m_tc_id);
    116 
    117 		m_tc_id = 0;
    118 	}
    119 
    120 	if (m_vs_id != 0)
    121 	{
    122 		gl.deleteShader(m_vs_id);
    123 
    124 		m_vs_id = 0;
    125 	}
    126 
    127 	if (m_vao_id != 0)
    128 	{
    129 		gl.deleteVertexArrays(1, &m_vao_id);
    130 
    131 		m_vao_id = 0;
    132 	}
    133 
    134 	/* Deinitialize all test descriptors */
    135 	for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
    136 	{
    137 		deinitTestDescriptor(*it);
    138 	}
    139 	m_tests.clear();
    140 }
    141 
    142 /** Deinitialize all test pass-specific ES objects.
    143  *
    144  *  @param test Descriptor of a test pass to deinitialize.
    145  **/
    146 void TessellationShaderTrianglesDegenerateTriangle::deinitTestDescriptor(_test_descriptor& test)
    147 {
    148 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    149 
    150 	if (test.po_id != 0)
    151 	{
    152 		gl.deleteProgram(test.po_id);
    153 
    154 		test.po_id = 0;
    155 	}
    156 
    157 	if (test.te_id != 0)
    158 	{
    159 		gl.deleteShader(test.te_id);
    160 
    161 		test.te_id = 0;
    162 	}
    163 }
    164 
    165 /** Initializes ES objects necessary to run the test. */
    166 void TessellationShaderTrianglesDegenerateTriangle::initTest()
    167 {
    168 	/* Skip if required extensions are not supported. */
    169 	if (!m_is_tessellation_shader_supported)
    170 	{
    171 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    172 	}
    173 
    174 	/* Generate all test-wide objects needed for test execution */
    175 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    176 
    177 	gl.genVertexArrays(1, &m_vao_id);
    178 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
    179 
    180 	gl.bindVertexArray(m_vao_id);
    181 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
    182 
    183 	gl.genBuffers(1, &m_bo_id);
    184 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
    185 
    186 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
    187 	m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
    188 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
    189 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
    190 
    191 	/* Configure fragment shader body */
    192 	const char* fs_body = "${VERSION}\n"
    193 						  "\n"
    194 						  "void main()\n"
    195 						  "{\n"
    196 						  "}\n";
    197 
    198 	shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body);
    199 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader");
    200 
    201 	/* Configure tessellation control shader body */
    202 	const char* tc_body = "${VERSION}\n"
    203 						  "\n"
    204 						  "${TESSELLATION_SHADER_REQUIRE}\n"
    205 						  "\n"
    206 						  "layout (vertices=3) out;\n"
    207 						  "\n"
    208 						  "void main()\n"
    209 						  "{\n"
    210 						  "    gl_out [gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n"
    211 						  "\n"
    212 						  "    gl_TessLevelInner[0] = 1.0;\n"
    213 						  "    gl_TessLevelOuter[0] = 1.0;\n"
    214 						  "    gl_TessLevelOuter[1] = 1.0;\n"
    215 						  "    gl_TessLevelOuter[2] = 1.0;\n"
    216 						  "}\n";
    217 
    218 	shaderSourceSpecialized(m_tc_id, 1 /* count */, &tc_body);
    219 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader");
    220 
    221 	/* Configure vertex shader body */
    222 	const char* vs_body = "${VERSION}\n"
    223 						  "\n"
    224 						  "void main()\n"
    225 						  "{\n"
    226 						  "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
    227 						  "}\n";
    228 
    229 	shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body);
    230 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader");
    231 
    232 	/* Compile all the shaders */
    233 	const glw::GLuint  shaders[] = { m_fs_id, m_tc_id, m_vs_id };
    234 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
    235 
    236 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
    237 	{
    238 		glw::GLuint shader = shaders[n_shader];
    239 
    240 		if (shader != 0)
    241 		{
    242 			glw::GLint compile_status = GL_FALSE;
    243 
    244 			gl.compileShader(shader);
    245 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
    246 
    247 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
    248 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
    249 
    250 			if (compile_status != GL_TRUE)
    251 			{
    252 				TCU_FAIL("Shader compilation failed");
    253 			}
    254 		}
    255 	} /* for (all shaders) */
    256 
    257 	/* Initialize all test passes */
    258 	_test_descriptor test_equal_spacing;
    259 	_test_descriptor test_fractional_odd_spacing;
    260 
    261 	initTestDescriptor(test_equal_spacing, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL);
    262 	initTestDescriptor(test_fractional_odd_spacing, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD);
    263 
    264 	m_tests.push_back(test_equal_spacing);
    265 	m_tests.push_back(test_fractional_odd_spacing);
    266 
    267 	/* Set up buffer object storage */
    268 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
    269 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
    270 
    271 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 /* components */ * 3 /* UVW sets */, NULL, /* data */
    272 				  GL_STATIC_DRAW);
    273 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
    274 
    275 	/* Bind the buffer object to indiced TF binding point */
    276 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
    277 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed");
    278 }
    279 
    280 /** Initializes all ES objects necessary to run a specific test pass.
    281  *
    282  *  @param test           Test descriptor to fill with IDs of initialized objects.
    283  *  @param vertex_spacing Vertex spacing mode to use for the run.
    284  **/
    285 void TessellationShaderTrianglesDegenerateTriangle::initTestDescriptor(
    286 	_test_descriptor& test, _tessellation_shader_vertex_spacing vertex_spacing)
    287 {
    288 	test.vertex_spacing = vertex_spacing;
    289 
    290 	/* Set up a program object for the descriptor */
    291 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    292 
    293 	test.po_id = gl.createProgram();
    294 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
    295 
    296 	/* Set up a pass-specific tessellation evaluation shader object. */
    297 	test.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
    298 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
    299 
    300 	/* Configure tessellation evaluation shader body */
    301 	const char* te_template = "${VERSION}\n"
    302 							  "\n"
    303 							  "${TESSELLATION_SHADER_REQUIRE}\n"
    304 							  "\n"
    305 							  "layout (triangles, VERTEX_SPACING_MODE) in;\n"
    306 							  "\n"
    307 							  "out vec3 result_uvw;\n"
    308 							  "\n"
    309 							  "void main()\n"
    310 							  "{\n"
    311 							  "    gl_Position = gl_in[0].gl_Position;\n"
    312 							  "    result_uvw  = gl_TessCoord;\n"
    313 							  "}\n";
    314 
    315 	const char* te_body_raw_ptr = DE_NULL;
    316 	std::string te_body_string  = te_template;
    317 	std::string vertex_spacing_mode_string;
    318 	const char* vertex_spacing_token	   = "VERTEX_SPACING_MODE";
    319 	std::size_t vertex_spacing_token_index = std::string::npos;
    320 
    321 	switch (vertex_spacing)
    322 	{
    323 	case TESSELLATION_SHADER_VERTEX_SPACING_EQUAL:
    324 	{
    325 		vertex_spacing_mode_string = "equal_spacing";
    326 
    327 		break;
    328 	}
    329 
    330 	case TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD:
    331 	{
    332 		vertex_spacing_mode_string = "fractional_odd_spacing";
    333 
    334 		break;
    335 	}
    336 
    337 	default:
    338 	{
    339 		TCU_FAIL("Invalid vertex spacing mode requested");
    340 	}
    341 	}
    342 
    343 	while ((vertex_spacing_token_index = te_body_string.find(vertex_spacing_token)) != std::string::npos)
    344 	{
    345 		te_body_string = te_body_string.replace(vertex_spacing_token_index, strlen(vertex_spacing_token),
    346 												vertex_spacing_mode_string);
    347 
    348 		vertex_spacing_token_index = te_body_string.find(vertex_spacing_token);
    349 	}
    350 
    351 	te_body_raw_ptr = te_body_string.c_str();
    352 
    353 	shaderSourceSpecialized(test.te_id, 1 /* count */, &te_body_raw_ptr);
    354 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader");
    355 
    356 	/* Compile the tessellation evaluation shader */
    357 	glw::GLint compile_status = GL_FALSE;
    358 
    359 	gl.compileShader(test.te_id);
    360 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed for tessellation evaluation shader");
    361 
    362 	gl.getShaderiv(test.te_id, GL_COMPILE_STATUS, &compile_status);
    363 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed for tessellation evaluation shader");
    364 
    365 	if (compile_status != GL_TRUE)
    366 	{
    367 		TCU_FAIL("Tessellation evaluation shader compilation failed");
    368 	}
    369 
    370 	/* Attach all shader to the program object */
    371 	gl.attachShader(test.po_id, m_fs_id);
    372 	gl.attachShader(test.po_id, m_tc_id);
    373 	gl.attachShader(test.po_id, test.te_id);
    374 	gl.attachShader(test.po_id, m_vs_id);
    375 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
    376 
    377 	/* Set up XFB */
    378 	const char*		   varyings[] = { "result_uvw" };
    379 	const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]);
    380 
    381 	gl.transformFeedbackVaryings(test.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
    382 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed");
    383 
    384 	/* Link the program object */
    385 	glw::GLint link_status = GL_FALSE;
    386 
    387 	gl.linkProgram(test.po_id);
    388 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
    389 
    390 	gl.getProgramiv(test.po_id, GL_LINK_STATUS, &link_status);
    391 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
    392 
    393 	if (link_status != GL_TRUE)
    394 	{
    395 		TCU_FAIL("Program linking failed");
    396 	}
    397 }
    398 
    399 /** Executes the test.
    400  *
    401  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    402  *
    403  *  Note the function throws exception should an error occur!
    404  *
    405  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
    406  **/
    407 tcu::TestNode::IterateResult TessellationShaderTrianglesDegenerateTriangle::iterate(void)
    408 {
    409 	/* Do not execute if required extensions are not supported. */
    410 	if (!m_is_tessellation_shader_supported)
    411 	{
    412 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    413 	}
    414 
    415 	/* Initialize ES test objects */
    416 	initTest();
    417 
    418 	/* We only need to use one vertex per so go for it */
    419 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    420 
    421 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
    422 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname");
    423 
    424 	/* Iterate through all tests configured */
    425 	for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); test_iterator++)
    426 	{
    427 		const _test_descriptor& test = *test_iterator;
    428 
    429 		/* Run the iteration */
    430 		gl.useProgram(test.po_id);
    431 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
    432 
    433 		/* Draw the test geometry */
    434 		gl.beginTransformFeedback(GL_TRIANGLES);
    435 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_TRIANGLES) failed.");
    436 
    437 		gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* count */);
    438 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
    439 
    440 		gl.endTransformFeedback();
    441 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
    442 
    443 		/* Map the BO with result data into user space */
    444 		const float* triangle_vertex_data =
    445 			(const float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
    446 											sizeof(float) * 3 /* vec3 */ * 3 /* points */, GL_MAP_READ_BIT);
    447 
    448 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
    449 
    450 		/* Make sure the triangle data is correct. Since we cannot rely on any specific order
    451 		 * of the result vertices, raise corresponding flag for each of the expected vertices.
    452 		 */
    453 		const float epsilon					 = 1e-5f;
    454 		bool		is_zero_zero_one_present = false;
    455 		bool		is_zero_one_zero_present = false;
    456 		bool		is_one_zero_zero_present = false;
    457 
    458 		for (unsigned int n_vertex = 0; n_vertex < 3 /* vertices */; ++n_vertex)
    459 		{
    460 			const float* triangle_ptr = triangle_vertex_data + 3 * n_vertex;
    461 
    462 			if (de::abs(triangle_ptr[0]) < epsilon && de::abs(triangle_ptr[1]) < epsilon &&
    463 				de::abs(triangle_ptr[2] - 1.0f) < epsilon)
    464 			{
    465 				if (!is_zero_zero_one_present)
    466 				{
    467 					is_zero_zero_one_present = true;
    468 				}
    469 				else
    470 				{
    471 					TCU_FAIL("(0, 0, 1) vertex outputted more than once");
    472 				}
    473 			}
    474 			else if (de::abs(triangle_ptr[0]) < epsilon && de::abs(triangle_ptr[1] - 1.0f) < epsilon &&
    475 					 de::abs(triangle_ptr[2]) < epsilon)
    476 			{
    477 				if (!is_zero_one_zero_present)
    478 				{
    479 					is_zero_one_zero_present = true;
    480 				}
    481 				else
    482 				{
    483 					TCU_FAIL("(0, 1, 0) vertex outputted more than once");
    484 				}
    485 			}
    486 			else if (de::abs(triangle_ptr[0] - 1.0f) < epsilon && de::abs(triangle_ptr[1]) < epsilon &&
    487 					 de::abs(triangle_ptr[2]) < epsilon)
    488 			{
    489 				if (!is_one_zero_zero_present)
    490 				{
    491 					is_one_zero_zero_present = true;
    492 				}
    493 				else
    494 				{
    495 					TCU_FAIL("(1, 0, 0) vertex outputted more than once");
    496 				}
    497 			}
    498 			else
    499 			{
    500 				m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected vertex"
    501 								   << " (" << triangle_vertex_data[0] << ", " << triangle_vertex_data[1] << ", "
    502 								   << triangle_vertex_data[2] << ")"
    503 								   << " encountered for a degenerate triangle." << tcu::TestLog::EndMessage;
    504 
    505 				TCU_FAIL("Invalid vertex was generated by the tessellator");
    506 			}
    507 		} /* for (all vertices) */
    508 
    509 		/* Unmap the BO */
    510 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
    511 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
    512 	}
    513 
    514 	/* All done */
    515 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    516 	return STOP;
    517 }
    518 
    519 /** Constructor
    520  *
    521  * @param context Test context
    522  **/
    523 TessellationShaderTrianglesIdenticalTriangles::TessellationShaderTrianglesIdenticalTriangles(
    524 	Context& context, const ExtParameters& extParams)
    525 	: TestCaseBase(context, extParams, "identical_triangles",
    526 				   "Verifies that tessellation coordinates generated by the tessellator "
    527 				   "running in triangles mode do not change if second inner or fourth "
    528 				   "outer tessellation level is changed")
    529 	, m_vao_id(0)
    530 	, m_utils(DE_NULL)
    531 {
    532 	/* Left blank on purpose */
    533 }
    534 
    535 /** Deinitializes ES objects created for the test. */
    536 void TessellationShaderTrianglesIdenticalTriangles::deinit()
    537 {
    538 	/* Call base class' deinit() */
    539 	TestCaseBase::deinit();
    540 
    541 	if (!m_is_tessellation_shader_supported)
    542 	{
    543 		return;
    544 	}
    545 
    546 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    547 
    548 	/* Unbind vertex array object */
    549 	gl.bindVertexArray(0);
    550 
    551 	/* Deallocate test variables */
    552 	if (m_vao_id != 0)
    553 	{
    554 		gl.deleteVertexArrays(1, &m_vao_id);
    555 
    556 		m_vao_id = 0;
    557 	}
    558 
    559 	/* Deinitialize utils instance */
    560 	if (m_utils != DE_NULL)
    561 	{
    562 		delete m_utils;
    563 
    564 		m_utils = DE_NULL;
    565 	}
    566 }
    567 
    568 /** Initializes ES objects necessary to run the test. */
    569 void TessellationShaderTrianglesIdenticalTriangles::initTest()
    570 {
    571 	/* Skip if required extensions are not supported. */
    572 	if (!m_is_tessellation_shader_supported)
    573 	{
    574 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    575 	}
    576 
    577 	/* Initialize Utils instance */
    578 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    579 
    580 	m_utils = new TessellationShaderUtils(gl, this);
    581 
    582 	/* Initialize vertex array object */
    583 	gl.genVertexArrays(1, &m_vao_id);
    584 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
    585 
    586 	gl.bindVertexArray(m_vao_id);
    587 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
    588 
    589 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
    590 	glw::GLint gl_max_tess_gen_level_value = 0;
    591 
    592 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
    593 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
    594 
    595 	/* Initialize all test runs */
    596 	_tessellation_level_set_filter filter =
    597 		(_tessellation_level_set_filter)((int)TESSELLATION_LEVEL_SET_FILTER_ALL_COMBINATIONS |
    598 										 (int)TESSELLATION_LEVEL_SET_FILTER_EXCLUDE_NEGATIVE_BASE_VALUE);
    599 
    600 	_tessellation_levels_set levels_sets = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
    601 		TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, gl_max_tess_gen_level_value, filter);
    602 
    603 	for (_tessellation_levels_set_const_iterator set_iterator = levels_sets.begin(); set_iterator != levels_sets.end();
    604 		 set_iterator++)
    605 	{
    606 		_run						run;
    607 		const _tessellation_levels& set = *set_iterator;
    608 
    609 		memcpy(run.base_inner, set.inner, sizeof(run.base_inner));
    610 		memcpy(run.base_outer, set.outer, sizeof(run.base_outer));
    611 
    612 		run.reference_inner[0] = run.base_inner[0];
    613 		run.reference_inner[1] = run.base_inner[1] * 0.25f;
    614 
    615 		run.reference_outer[0] = run.base_outer[0];
    616 		run.reference_outer[1] = run.base_outer[1];
    617 		run.reference_outer[2] = run.base_outer[2];
    618 		run.reference_outer[3] = run.base_outer[3] * 0.25f;
    619 
    620 		/* Retrieve vertex data for both passes */
    621 		glw::GLint n_base_vertices		= 0;
    622 		glw::GLint n_reference_vertices = 0;
    623 
    624 		n_base_vertices = m_utils->getAmountOfVerticesGeneratedByTessellator(
    625 			TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, run.base_inner, run.base_outer,
    626 			TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, false);
    627 		n_reference_vertices = m_utils->getAmountOfVerticesGeneratedByTessellator(
    628 			TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, run.reference_inner, run.reference_outer,
    629 			TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, false); /* is_point_mode_enabled */
    630 
    631 		if (n_base_vertices == 0)
    632 		{
    633 			m_testCtx.getLog() << tcu::TestLog::Message << "No vertices were generated by tessellator for: "
    634 														   "inner tess levels:"
    635 														   "["
    636 							   << run.base_inner[0] << ", " << run.base_inner[1] << "]"
    637 																					", outer tess levels:"
    638 																					"["
    639 							   << run.base_outer[0] << ", " << run.base_outer[1] << ", " << run.base_outer[2] << ", "
    640 							   << run.base_outer[3] << "]"
    641 													   ", primitive mode: triangles, vertex spacing: equal."
    642 							   << tcu::TestLog::EndMessage;
    643 
    644 			TCU_FAIL("Zero vertices were generated by tessellator for base test pass");
    645 		}
    646 
    647 		if (n_reference_vertices == 0)
    648 		{
    649 			m_testCtx.getLog() << tcu::TestLog::Message << "No vertices were generated by tessellator for: "
    650 														   "inner tess levels:"
    651 														   "["
    652 							   << run.reference_inner[0] << ", " << run.reference_inner[1] << "]"
    653 																							  ", outer tess levels:"
    654 																							  "["
    655 							   << run.reference_outer[0] << ", " << run.reference_outer[1] << ", "
    656 							   << run.reference_outer[2] << ", " << run.reference_outer[3]
    657 							   << "]"
    658 								  ", primitive mode: triangles, vertex spacing: equal."
    659 							   << tcu::TestLog::EndMessage;
    660 
    661 			TCU_FAIL("Zero vertices were generated by tessellator for reference test pass");
    662 		}
    663 
    664 		if (n_base_vertices != n_reference_vertices)
    665 		{
    666 			m_testCtx.getLog() << tcu::TestLog::Message << "Amount of vertices generated by the tessellator differs"
    667 														   " for the following inner/outer configs: "
    668 														   "inner tess levels:"
    669 														   "["
    670 							   << run.base_inner[0] << ", " << run.base_inner[1] << "]"
    671 																					", outer tess levels:"
    672 																					"["
    673 							   << run.base_outer[0] << ", " << run.base_outer[1] << ", " << run.base_outer[2] << ", "
    674 							   << run.base_outer[3] << "]"
    675 													   " and inner tess levels:"
    676 													   "["
    677 							   << run.reference_inner[0] << ", " << run.reference_inner[1] << "]"
    678 																							  ", outer tess levels:"
    679 																							  "["
    680 							   << run.reference_outer[0] << ", " << run.reference_outer[1] << ", "
    681 							   << run.reference_outer[2] << ", " << run.reference_outer[3]
    682 							   << "]"
    683 								  ", primitive mode: triangles, vertex spacing: equal."
    684 							   << tcu::TestLog::EndMessage;
    685 
    686 			TCU_FAIL("Amount of vertices generated by tessellator differs between base and references passes");
    687 		}
    688 
    689 		run.n_vertices = n_base_vertices;
    690 
    691 		run.base_data = m_utils->getDataGeneratedByTessellator(
    692 			run.base_inner, false, /* is_point_mode_enabled */
    693 			TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
    694 			TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, run.base_outer);
    695 		run.reference_data = m_utils->getDataGeneratedByTessellator(
    696 			run.reference_inner, false, /* is_point_mode_enabled */
    697 			TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
    698 			TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, run.reference_outer);
    699 
    700 		/* Store the run data */
    701 		m_runs.push_back(run);
    702 	} /* for (all sets) */
    703 }
    704 
    705 /** Executes the test.
    706  *
    707  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    708  *
    709  *  Note the function throws exception should an error occur!
    710  *
    711  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
    712  **/
    713 tcu::TestNode::IterateResult TessellationShaderTrianglesIdenticalTriangles::iterate(void)
    714 {
    715 	/* Do not execute if required extensions are not supported. */
    716 	if (!m_is_tessellation_shader_supported)
    717 	{
    718 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    719 	}
    720 
    721 	/* Initialize the test */
    722 	initTest();
    723 
    724 	/* Iterate through all runs */
    725 
    726 	for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++)
    727 	{
    728 		const _run& run = *run_iterator;
    729 
    730 		/* Make sure the vertex data generated for two passes matches */
    731 		const glw::GLint n_triangles = run.n_vertices / 3 /* vertices per triangle */;
    732 
    733 		for (int n_triangle = 0; n_triangle < n_triangles; ++n_triangle)
    734 		{
    735 			const float* triangle_a = (const float*)(&run.base_data[0]) +
    736 									  n_triangle * 3 /* vertices */
    737 										  * 3;		 /* components */
    738 			const float* triangle_b = (const float*)(&run.reference_data[0]) +
    739 									  n_triangle * 3 /* vertices */
    740 										  * 3;		 /* components */
    741 
    742 			if (!TessellationShaderUtils::isTriangleDefined(triangle_a, triangle_b))
    743 			{
    744 				m_testCtx.getLog() << tcu::TestLog::Message
    745 								   << "The following triangle, generated in the first pass, was not "
    746 									  "generated in the other. "
    747 									  "First pass' configuration: inner tess levels:"
    748 									  "["
    749 								   << run.base_inner[0] << ", " << run.base_inner[1] << "]"
    750 																						", outer tess levels:"
    751 																						"["
    752 								   << run.base_outer[0] << ", " << run.base_outer[1] << ", " << run.base_outer[2]
    753 								   << ", " << run.base_outer[3] << "]"
    754 																   "; second pass' configuration: inner tess levels:"
    755 																   "["
    756 								   << run.reference_inner[0] << ", " << run.reference_inner[1] << "]"
    757 																								  ", outer tess levels:"
    758 																								  "["
    759 								   << run.reference_outer[0] << ", " << run.reference_outer[1] << ", "
    760 								   << run.reference_outer[2] << ", " << run.reference_outer[3]
    761 								   << "]"
    762 									  ", primitive mode: triangles, vertex spacing: equal."
    763 								   << tcu::TestLog::EndMessage;
    764 
    765 				TCU_FAIL("A triangle from base vertex data set was not found in reference vertex data set.");
    766 			}
    767 		} /* for (all vertices) */
    768 	}	 /* for (all runs) */
    769 
    770 	/* All done */
    771 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    772 	return STOP;
    773 }
    774 
    775 /** Constructor
    776  *
    777  * @param context Test context
    778  **/
    779 TessellationShaderTrianglesInnerTessellationLevelRounding::TessellationShaderTrianglesInnerTessellationLevelRounding(
    780 	Context& context, const ExtParameters& extParams)
    781 	: TestCaseBase(context, extParams, "inner_tessellation_level_rounding",
    782 				   "Verifies that inner tessellation level is rounded to 1 or 2,"
    783 				   " when the tessellator is run in triangles primitive mode and "
    784 				   "inner tessellation level is set to 1 and any of the outer "
    785 				   "tessellation levels is greater than one.")
    786 	, m_vao_id(0)
    787 	, m_utils(DE_NULL)
    788 {
    789 	/* Left blank on purpose */
    790 }
    791 
    792 /** Deinitializes ES objects created for the test. */
    793 void TessellationShaderTrianglesInnerTessellationLevelRounding::deinit()
    794 {
    795 	/* Call base class' deinit() */
    796 	TestCaseBase::deinit();
    797 
    798 	if (!m_is_tessellation_shader_supported)
    799 	{
    800 		return;
    801 	}
    802 
    803 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    804 
    805 	/* Unbind vertex array object */
    806 	gl.bindVertexArray(0);
    807 
    808 	/* Deallocate test variables */
    809 	if (m_vao_id != 0)
    810 	{
    811 		gl.deleteVertexArrays(1, &m_vao_id);
    812 
    813 		m_vao_id = 0;
    814 	}
    815 
    816 	/* Deinitialize utils instance */
    817 	if (m_utils != DE_NULL)
    818 	{
    819 		delete m_utils;
    820 
    821 		m_utils = DE_NULL;
    822 	}
    823 }
    824 
    825 /** Executes the test.
    826  *
    827  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    828  *
    829  *  Note the function throws exception should an error occur!
    830  *
    831  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
    832  **/
    833 tcu::TestNode::IterateResult TessellationShaderTrianglesInnerTessellationLevelRounding::iterate(void)
    834 {
    835 	/* Do not execute if required extensions are not supported. */
    836 	if (!m_is_tessellation_shader_supported)
    837 	{
    838 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    839 	}
    840 
    841 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    842 
    843 	/* Initialize vertex array object */
    844 	gl.genVertexArrays(1, &m_vao_id);
    845 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
    846 
    847 	gl.bindVertexArray(m_vao_id);
    848 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
    849 
    850 	/* Initialize and run test iterations. In later part, we will verify the generated data. */
    851 	runTestIterations();
    852 
    853 	/* Iterate through all runs */
    854 
    855 	for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++)
    856 	{
    857 		const _run& run = *run_iterator;
    858 
    859 		if (run.vertex_spacing == TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD &&
    860 			de::abs(run.set1_inner[0] - run.set2_inner[0]) > 1e-5f &&
    861 			de::min(run.set1_inner[0], run.set2_inner[0]) >= 1.0f)
    862 		{
    863 			/* In fractional_odd_spacing mode with inner level <f> >= 1.0f, the clamped
    864 			 and rounded integer level <n> is at least 3.
    865 
    866 			 These results in inner subdivision into at least <n>-2=1 segment and
    867 			 two additional, typically shorter segments.
    868 
    869 			 The length of these two additional segments relative to the others will
    870 			 decrease monotonically with the value of <n>-<f>, so if different <f> levels
    871 			 were used, we cannot proceed with matching the exact vertex data. */
    872 
    873 			continue;
    874 		}
    875 
    876 		/* Make sure the vertex data generated for two passes matches */
    877 		const glw::GLint n_triangles = run.n_vertices / 3 /* vertices per triangle */;
    878 
    879 		for (int n_triangle = 0; n_triangle < n_triangles; ++n_triangle)
    880 		{
    881 			const float* triangle_a = (const float*)(&run.set1_data[0]) +
    882 									  n_triangle * 3 /* vertices */
    883 										  * 3;		 /* components */
    884 			const float* triangle_b = (const float*)(&run.set2_data[0]) +
    885 									  n_triangle * 3 /* vertices */
    886 										  * 3;		 /* components */
    887 
    888 			if (!TessellationShaderUtils::isTriangleDefined(triangle_a, triangle_b))
    889 			{
    890 				std::string vs_mode_string =
    891 					TessellationShaderUtils::getESTokenForVertexSpacingMode(run.vertex_spacing);
    892 
    893 				m_testCtx.getLog() << tcu::TestLog::Message
    894 								   << "The following triangle, generated in the first pass, was not "
    895 									  "generated in the second one. "
    896 									  "First pass' configuration: inner tess levels:"
    897 									  "["
    898 								   << run.set1_inner[0] << ", " << run.set1_inner[1] << "]"
    899 																						", outer tess levels:"
    900 																						"["
    901 								   << run.set1_outer[0] << ", " << run.set1_outer[1] << ", " << run.set1_outer[2]
    902 								   << ", " << run.set1_outer[3] << "]"
    903 																   "; second pass' configuration: inner tess levels:"
    904 																   "["
    905 								   << run.set2_inner[0] << ", " << run.set2_inner[1] << "]"
    906 																						", outer tess levels:"
    907 																						"["
    908 								   << run.set2_outer[0] << ", " << run.set2_outer[1] << ", " << run.set2_outer[2]
    909 								   << ", " << run.set2_outer[3] << "]"
    910 																   ", primitive mode: triangles, vertex spacing: "
    911 								   << vs_mode_string << tcu::TestLog::EndMessage;
    912 
    913 				TCU_FAIL("A triangle from first pass' data set was not found in second pass' data set.");
    914 			}
    915 		} /* for (all vertices) */
    916 	}	 /* for (all runs) */
    917 
    918 	/* All done */
    919 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    920 	return STOP;
    921 }
    922 
    923 /** Runs all test iterations needed to generate data for later verification. */
    924 void TessellationShaderTrianglesInnerTessellationLevelRounding::runTestIterations()
    925 {
    926 	/* Skip if required extensions are not supported. */
    927 	if (!m_is_tessellation_shader_supported)
    928 	{
    929 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
    930 	}
    931 
    932 	/* Initialize Utils instance */
    933 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    934 
    935 	m_utils = new TessellationShaderUtils(gl, this);
    936 
    937 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
    938 	glw::GLint gl_max_tess_gen_level_value = 0;
    939 
    940 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
    941 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
    942 
    943 	/* Initialize all test runs */
    944 	const glw::GLint   tess_levels[] = { 2, gl_max_tess_gen_level_value / 2, gl_max_tess_gen_level_value };
    945 	const unsigned int n_tess_levels = sizeof(tess_levels) / sizeof(tess_levels[0]);
    946 
    947 	const _tessellation_shader_vertex_spacing vs_modes[] = { TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
    948 															 TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
    949 															 TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD };
    950 	const unsigned int n_vs_modes = sizeof(vs_modes) / sizeof(vs_modes[0]);
    951 
    952 	for (unsigned int n_vs_mode = 0; n_vs_mode < n_vs_modes; ++n_vs_mode)
    953 	{
    954 		_tessellation_shader_vertex_spacing vs_mode = vs_modes[n_vs_mode];
    955 
    956 		for (unsigned int n_tess_level = 0; n_tess_level < n_tess_levels; ++n_tess_level)
    957 		{
    958 			/* Set up the run descriptor */
    959 			glw::GLint tess_level = tess_levels[n_tess_level];
    960 			_run	   run;
    961 
    962 			run.set1_inner[0] = 1.0f;
    963 			run.set1_inner[1] = 0.0f;
    964 			run.set2_inner[1] = 0.0f;
    965 
    966 			TessellationShaderUtils::getTessellationLevelAfterVertexSpacing(vs_mode, 1.5f, gl_max_tess_gen_level_value,
    967 																			DE_NULL, /* out_clamped */
    968 																			run.set2_inner);
    969 			run.set1_outer[0] = (glw::GLfloat)tess_level;
    970 			run.set2_outer[0] = (glw::GLfloat)tess_level;
    971 			run.set1_outer[1] = (glw::GLfloat)tess_level;
    972 			run.set2_outer[1] = (glw::GLfloat)tess_level;
    973 			run.set1_outer[2] = (glw::GLfloat)tess_level;
    974 			run.set2_outer[2] = (glw::GLfloat)tess_level;
    975 			run.set1_outer[3] = (glw::GLfloat)tess_level;
    976 			run.set2_outer[3] = (glw::GLfloat)tess_level;
    977 
    978 			run.vertex_spacing = vs_mode;
    979 
    980 			/* Retrieve vertex data for both passes */
    981 			glw::GLint n_set1_vertices = 0;
    982 			glw::GLint n_set2_vertices = 0;
    983 
    984 			n_set1_vertices = m_utils->getAmountOfVerticesGeneratedByTessellator(
    985 				TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, run.set1_inner, run.set1_outer, run.vertex_spacing,
    986 				false); /* is_point_mode_enabled */
    987 			n_set2_vertices = m_utils->getAmountOfVerticesGeneratedByTessellator(
    988 				TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, run.set2_inner, run.set2_outer, run.vertex_spacing,
    989 				false); /* is_point_mode_enabled */
    990 
    991 			if (n_set1_vertices == 0)
    992 			{
    993 				std::string vs_mode_string = TessellationShaderUtils::getESTokenForVertexSpacingMode(vs_mode);
    994 
    995 				m_testCtx.getLog() << tcu::TestLog::Message << "No vertices were generated by tessellator for: "
    996 															   "inner tess levels:"
    997 															   "["
    998 								   << run.set1_inner[0] << ", " << run.set1_inner[1] << "]"
    999 																						", outer tess levels:"
   1000 																						"["
   1001 								   << run.set1_outer[0] << ", " << run.set1_outer[1] << ", " << run.set1_outer[2]
   1002 								   << ", " << run.set1_outer[3] << "]"
   1003 																   ", primitive mode: triangles, "
   1004 																   "vertex spacing: "
   1005 								   << vs_mode_string << tcu::TestLog::EndMessage;
   1006 
   1007 				TCU_FAIL("Zero vertices were generated by tessellator for first test pass");
   1008 			}
   1009 
   1010 			if (n_set2_vertices == 0)
   1011 			{
   1012 				std::string vs_mode_string = TessellationShaderUtils::getESTokenForVertexSpacingMode(vs_mode);
   1013 
   1014 				m_testCtx.getLog() << tcu::TestLog::Message << "No vertices were generated by tessellator for: "
   1015 															   "inner tess levels:"
   1016 															   "["
   1017 								   << run.set2_inner[0] << ", " << run.set2_inner[1] << "]"
   1018 																						", outer tess levels:"
   1019 																						"["
   1020 								   << run.set2_outer[0] << ", " << run.set2_outer[1] << ", " << run.set2_outer[2]
   1021 								   << ", " << run.set2_outer[3] << "]"
   1022 																   ", primitive mode: triangles, "
   1023 																   "vertex spacing: "
   1024 								   << vs_mode_string << tcu::TestLog::EndMessage;
   1025 
   1026 				TCU_FAIL("Zero vertices were generated by tessellator for second test pass");
   1027 			}
   1028 
   1029 			if (n_set1_vertices != n_set2_vertices)
   1030 			{
   1031 				std::string vs_mode_string = TessellationShaderUtils::getESTokenForVertexSpacingMode(vs_mode);
   1032 
   1033 				m_testCtx.getLog() << tcu::TestLog::Message << "Amount of vertices generated by the tessellator differs"
   1034 															   " for the following inner/outer configs: "
   1035 															   "inner tess levels:"
   1036 															   "["
   1037 								   << run.set1_inner[0] << ", " << run.set1_inner[1] << "]"
   1038 																						", outer tess levels:"
   1039 																						"["
   1040 								   << run.set1_outer[0] << ", " << run.set1_outer[1] << ", " << run.set1_outer[2]
   1041 								   << ", " << run.set1_outer[3] << "]"
   1042 																   " and inner tess levels:"
   1043 																   "["
   1044 								   << run.set2_inner[0] << ", " << run.set2_inner[1] << "]"
   1045 																						", outer tess levels:"
   1046 																						"["
   1047 								   << run.set2_outer[0] << ", " << run.set2_outer[1] << ", " << run.set2_outer[2]
   1048 								   << ", " << run.set2_outer[3] << "]"
   1049 																   ", primitive mode: triangles, vertex spacing: "
   1050 								   << vs_mode_string << tcu::TestLog::EndMessage;
   1051 
   1052 				TCU_FAIL("Amount of vertices generated by tessellator differs between base and references passes");
   1053 			}
   1054 
   1055 			run.n_vertices = n_set1_vertices;
   1056 
   1057 			run.set1_data = m_utils->getDataGeneratedByTessellator(run.set1_inner, false, /* is_point_mode_enabled */
   1058 																   TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES,
   1059 																   TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
   1060 																   run.vertex_spacing, run.set1_outer);
   1061 			run.set2_data = m_utils->getDataGeneratedByTessellator(run.set2_inner, false, /* is_point_mode_enabled */
   1062 																   TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES,
   1063 																   TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
   1064 																   run.vertex_spacing, run.set2_outer);
   1065 
   1066 			/* Store the run data */
   1067 			m_runs.push_back(run);
   1068 		} /* for (all sets) */
   1069 	}	 /* for (all vertex spacing modes) */
   1070 }
   1071 
   1072 } /* namespace glcts */
   1073