• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "esextcTessellationShaderTCTE.hpp"
25 #include "esextcTessellationShaderUtils.hpp"
26 #include "gluContextInfo.hpp"
27 #include "gluDefs.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuTestLog.hpp"
31 #include <algorithm>
32 
33 namespace glcts
34 {
35 /** Constructor
36  *
37  * @param context Test context
38  **/
TessellationShaderTCTETests(glcts::Context & context,const ExtParameters & extParams)39 TessellationShaderTCTETests::TessellationShaderTCTETests(glcts::Context& context, const ExtParameters& extParams)
40 	: TestCaseGroupBase(context, extParams, "tessellation_control_to_tessellation_evaluation",
41 						"Verifies various aspects of communication between tessellation "
42 						"control and tessellation evaluation stages")
43 {
44 	/* No implementation needed */
45 }
46 
47 /**
48  * Initializes test groups for geometry shader tests
49  **/
init(void)50 void TessellationShaderTCTETests::init(void)
51 {
52 	addChild(new glcts::TessellationShaderTCTEDataPassThrough(m_context, m_extParams));
53 	addChild(new glcts::TessellationShaderTCTEgl_in(m_context, m_extParams));
54 	addChild(new glcts::TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize(m_context, m_extParams));
55 	addChild(new glcts::TessellationShaderTCTEgl_PatchVerticesIn(m_context, m_extParams));
56 	addChild(new glcts::TessellationShaderTCTEgl_TessLevel(m_context, m_extParams));
57 }
58 
59 /** Constructor
60  *
61  * @param context Test context
62  **/
TessellationShaderTCTEDataPassThrough(Context & context,const ExtParameters & extParams)63 TessellationShaderTCTEDataPassThrough::TessellationShaderTCTEDataPassThrough(Context&			  context,
64 																			 const ExtParameters& extParams)
65 	: TestCaseBase(context, extParams, "data_pass_through",
66 				   "Verifies data is correctly passed down the VS->TC->TS->(GS) pipeline.")
67 	, m_bo_id(0)
68 	, m_n_input_vertices_per_run(4)
69 	, m_utils_ptr(DE_NULL)
70 	, m_vao_id(0)
71 {
72 	/* Left blank on purpose */
73 }
74 
75 /** Deinitializes all ES objects created for the test. */
deinit()76 void TessellationShaderTCTEDataPassThrough::deinit()
77 {
78 	/** Call base class' deinit() function */
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 	/* Revert GL_PATCH_VERTICES_EXT value to the default setting */
89 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
90 
91 	/* Disable GL_RASTERIZER_DISCARD mode */
92 	gl.disable(GL_RASTERIZER_DISCARD);
93 
94 	/* Revert TF buffer object bindings */
95 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
96 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
97 
98 	/* Unbind vertex array object */
99 	gl.bindVertexArray(0);
100 
101 	/* Release all objects we might've created */
102 	if (m_bo_id != 0)
103 	{
104 		gl.deleteBuffers(1, &m_bo_id);
105 
106 		m_bo_id = 0;
107 	}
108 
109 	if (m_vao_id != 0)
110 	{
111 		gl.deleteVertexArrays(1, &m_vao_id);
112 
113 		m_vao_id = 0;
114 	}
115 
116 	for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it)
117 	{
118 		deinitTestRun(*it);
119 	}
120 	m_runs.clear();
121 
122 	/* Release Utils instance */
123 	if (m_utils_ptr != DE_NULL)
124 	{
125 		delete m_utils_ptr;
126 
127 		m_utils_ptr = DE_NULL;
128 	}
129 }
130 
131 /** Deinitializes all ES object created for a specific test run. **/
deinitTestRun(_run & run)132 void TessellationShaderTCTEDataPassThrough::deinitTestRun(_run& run)
133 {
134 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
135 
136 	if (run.fs_id != 0)
137 	{
138 		gl.deleteShader(run.fs_id);
139 
140 		run.fs_id = 0;
141 	}
142 
143 	if (run.gs_id != 0)
144 	{
145 		gl.deleteShader(run.gs_id);
146 
147 		run.gs_id = 0;
148 	}
149 
150 	if (run.po_id != 0)
151 	{
152 		gl.deleteProgram(run.po_id);
153 
154 		run.po_id = 0;
155 	}
156 
157 	if (run.tcs_id != 0)
158 	{
159 		gl.deleteShader(run.tcs_id);
160 
161 		run.tcs_id = 0;
162 	}
163 
164 	if (run.tes_id != 0)
165 	{
166 		gl.deleteShader(run.tes_id);
167 
168 		run.tes_id = 0;
169 	}
170 
171 	if (run.vs_id != 0)
172 	{
173 		gl.deleteShader(run.vs_id);
174 
175 		run.vs_id = 0;
176 	}
177 }
178 
179 /** Initializes all ES objects that will be used for the test. */
initTest()180 void TessellationShaderTCTEDataPassThrough::initTest()
181 {
182 	/* The test requires EXT_tessellation_shader */
183 	if (!m_is_tessellation_shader_supported)
184 	{
185 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
186 	}
187 
188 	/* Create an Utils instance */
189 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
190 
191 	m_utils_ptr = new TessellationShaderUtils(gl, this);
192 
193 	/* Initialize vertex array object */
194 	gl.genVertexArrays(1, &m_vao_id);
195 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
196 
197 	gl.bindVertexArray(m_vao_id);
198 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
199 
200 	/* Our program objects take a single vertex per patch */
201 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
202 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed");
203 
204 	/* Disable rasterization */
205 	gl.enable(GL_RASTERIZER_DISCARD);
206 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed");
207 
208 	/* Create a buffer object we will use for XFB */
209 	gl.genBuffers(1, &m_bo_id);
210 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
211 
212 	/* Set up XFB buffer object bindings */
213 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
214 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed");
215 
216 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
217 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed");
218 
219 	/* Prepare all the runs */
220 	const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES,
221 															 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
222 															 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
223 	const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
224 
225 	/* Iterate over all supported primitive modes */
226 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode)
227 	{
228 		_tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode];
229 
230 		/* If geometry shaders are supported, include a separate iteration to include them
231 		 * in the pipeline
232 		 */
233 		for (int n_gs_stage_usage = 0; n_gs_stage_usage < ((m_is_geometry_shader_extension_supported) ? 2 : 1);
234 			 ++n_gs_stage_usage)
235 		{
236 			bool use_gs_stage = (n_gs_stage_usage == 1);
237 
238 			/* If geometry shaders support gl_PointSize, include a separate iteration to pass
239 			 * point size data as well */
240 			for (int n_gs_pointsize_usage = 0;
241 				 n_gs_pointsize_usage < ((m_is_geometry_shader_point_size_supported) ? 2 : 1); ++n_gs_pointsize_usage)
242 			{
243 				bool use_gs_pointsize_data = (n_gs_pointsize_usage == 1);
244 
245 				/* If tessellation shaders support gl_PointSize, include a separate iteration to pass
246 				 * point size data as well */
247 				for (int n_ts_pointsize_usage = 0;
248 					 n_ts_pointsize_usage < ((m_is_tessellation_shader_point_size_supported) ? 2 : 1);
249 					 ++n_ts_pointsize_usage)
250 				{
251 					bool use_ts_pointsize_data = (n_ts_pointsize_usage == 1);
252 
253 					/* Note: it does not make sense to try to pass gl_PointSize data
254 					 *       in geometry stage if tessellation stage did not provide it.
255 					 */
256 					if (!use_ts_pointsize_data && use_gs_pointsize_data)
257 					{
258 						continue;
259 					}
260 
261 					/* Initialize test run data */
262 					_run run;
263 
264 					executeTestRun(run, primitive_mode, use_gs_stage, use_gs_pointsize_data, use_ts_pointsize_data);
265 
266 					/* Store the run for later usage */
267 					m_runs.push_back(run);
268 				} /* for (tessellation point size data usage off and on cases) */
269 			}	 /* for (geometry point size data usage off and on cases) */
270 		}		  /* for (GS stage usage) */
271 	}			  /* for (all primitive modes) */
272 }
273 
274 /** Initializes a test run, executes it and gathers all the rendered data for further
275  *  processing. Extracted data is stored in the run descriptor.
276  *
277  *  @param run                               Test run descriptor to fill with ES object data,
278  *                                           as well as generated data.
279  *  @param primitive_mode                    Primitive mode to use for the test run.
280  *  @param should_use_geometry_shader        true  if the test run should use Geometry Shader stage,
281  *                                           false otherwise.
282  *  @param should_pass_point_size_data_in_gs true if the test run should define two output variables
283  *                                           in Geometry Shader, later set to gl_PointSize values from
284  *                                           TC and TE stages. False to skip them.
285  *                                           Only set to true if GL_EXT_geometry_point_size extension
286  *                                           is supported.
287  *  @param should_pass_point_size_data_in_ts true if the test run should define two output variables
288  *                                           in both Tessellation Shader types, set to gl_PointSize values
289  *                                           as accessible during execution. False to skip the definitions.
290  *                                           Only set to true if GL_EXT_tessellation_point_size extension
291  *                                           is supported.
292  */
executeTestRun(_run & run,_tessellation_primitive_mode primitive_mode,bool should_use_geometry_shader,bool should_pass_point_size_data_in_gs,bool should_pass_point_size_data_in_ts)293 void TessellationShaderTCTEDataPassThrough::executeTestRun(_run& run, _tessellation_primitive_mode primitive_mode,
294 														   bool should_use_geometry_shader,
295 														   bool should_pass_point_size_data_in_gs,
296 														   bool should_pass_point_size_data_in_ts)
297 {
298 	run.primitive_mode = primitive_mode;
299 
300 	/* Retrieve ES entry-points before we start */
301 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
302 
303 	/* Create a program object first */
304 	run.po_id = gl.createProgram();
305 
306 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
307 
308 	/* Create all shader objects we wil be later attaching to the program object */
309 	run.fs_id  = gl.createShader(GL_FRAGMENT_SHADER);
310 	run.tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
311 	run.tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
312 	run.vs_id  = gl.createShader(GL_VERTEX_SHADER);
313 
314 	if (should_use_geometry_shader)
315 	{
316 		run.gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
317 	}
318 
319 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
320 
321 	/* Attach the shader objects to the program object */
322 	gl.attachShader(run.po_id, run.fs_id);
323 	gl.attachShader(run.po_id, run.tcs_id);
324 	gl.attachShader(run.po_id, run.tes_id);
325 	gl.attachShader(run.po_id, run.vs_id);
326 
327 	if (should_use_geometry_shader)
328 	{
329 		gl.attachShader(run.po_id, run.gs_id);
330 	}
331 
332 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed");
333 
334 	/* Set vertex shader's body */
335 	const char* vs_body = "${VERSION}\n"
336 						  "\n"
337 						  "${SHADER_IO_BLOCKS_REQUIRE}\n"
338 						  "\n"
339 						  "out OUT_VS\n"
340 						  "{\n"
341 						  "    vec4  value1;\n"
342 						  "    ivec4 value2;\n"
343 						  "} out_data;\n"
344 						  "\n"
345 						  "void main()\n"
346 						  "{\n"
347 						  "    gl_Position     = vec4( float(gl_VertexID) );\n"
348 						  "    gl_PointSize    = 1.0 / float(gl_VertexID + 1);\n"
349 						  "    out_data.value1 =  vec4(float(gl_VertexID),        float(gl_VertexID) * 0.5,\n"
350 						  "                            float(gl_VertexID) * 0.25, float(gl_VertexID) * 0.125);\n"
351 						  "    out_data.value2 = ivec4(gl_VertexID,               gl_VertexID + 1,\n"
352 						  "                            gl_VertexID + 2,           gl_VertexID + 3);\n"
353 						  "}\n";
354 
355 	shaderSourceSpecialized(run.vs_id, 1 /* count */, &vs_body);
356 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for vertex shader");
357 
358 	/* Set minimal fragment shader's body */
359 	const char* fs_body = "${VERSION}\n"
360 						  "\n"
361 						  "void main()\n"
362 						  "{\n"
363 						  "}\n";
364 
365 	shaderSourceSpecialized(run.fs_id, 1 /* count */, &fs_body);
366 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for fragment shader");
367 
368 	/* Set tessellation control shader's body */
369 	{
370 		std::stringstream body_sstream;
371 		std::string		  body_string;
372 		const char*		  body_raw_ptr = DE_NULL;
373 
374 		body_sstream << "${VERSION}\n"
375 						"\n"
376 						"${TESSELLATION_SHADER_REQUIRE}\n";
377 
378 		if (should_pass_point_size_data_in_ts)
379 		{
380 			body_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n";
381 		}
382 
383 		body_sstream << "\n"
384 						"layout(vertices = 2) out;\n"
385 						"\n"
386 						"in OUT_VS\n"
387 						"{\n"
388 						"    vec4  value1;\n"
389 						"    ivec4 value2;\n"
390 						"} in_vs_data[];\n"
391 						"\n"
392 						"out OUT_TC\n"
393 						"{\n";
394 
395 		if (should_pass_point_size_data_in_ts)
396 		{
397 			body_sstream << "    float tc_pointSize;\n";
398 		}
399 
400 		body_sstream << "     vec4  tc_position;\n"
401 						"     vec4  tc_value1;\n"
402 						"    ivec4  tc_value2;\n"
403 						"} out_data[];\n"
404 						"\n"
405 						"patch out vec4 tc_patch_data;\n"
406 						"\n"
407 						"void main()\n"
408 						"{\n"
409 						"    int multiplier = 1;\n"
410 						"\n"
411 						"    if (gl_InvocationID == 0)\n"
412 						"    {\n"
413 						"        multiplier = 2;\n"
414 						"    }\n";
415 
416 		if (should_pass_point_size_data_in_ts)
417 		{
418 			body_sstream << "    out_data         [gl_InvocationID].tc_pointSize = gl_in[0].gl_PointSize;\n"
419 							"    gl_out           [gl_InvocationID].gl_PointSize = gl_in[0].gl_PointSize * 2.0;\n";
420 		}
421 
422 		body_sstream << "    out_data         [gl_InvocationID].tc_position  = gl_in     [0].gl_Position;\n"
423 						"    out_data         [gl_InvocationID].tc_value1    = in_vs_data[0].value1      *  "
424 						"vec4(float(multiplier) );\n"
425 						"    out_data         [gl_InvocationID].tc_value2    = in_vs_data[0].value2      * ivec4(      "
426 						"multiplier);\n"
427 						"    gl_out           [gl_InvocationID].gl_Position  = gl_in     [0].gl_Position + vec4(3.0);\n"
428 						"    gl_TessLevelInner[0]                            = 4.0;\n"
429 						"    gl_TessLevelInner[1]                            = 4.0;\n"
430 						"    gl_TessLevelOuter[0]                            = 4.0;\n"
431 						"    gl_TessLevelOuter[1]                            = 4.0;\n"
432 						"    gl_TessLevelOuter[2]                            = 4.0;\n"
433 						"    gl_TessLevelOuter[3]                            = 4.0;\n"
434 						"\n"
435 						"    if (gl_InvocationID == 0)\n"
436 						"    {\n"
437 						"        tc_patch_data = in_vs_data[0].value1 *  vec4(float(multiplier) );\n"
438 						"    }\n"
439 						"}\n";
440 
441 		body_string  = body_sstream.str();
442 		body_raw_ptr = body_string.c_str();
443 
444 		shaderSourceSpecialized(run.tcs_id, 1 /* count */, &body_raw_ptr);
445 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation control shader");
446 	}
447 
448 	/* Set tessellation evaluation shader's body */
449 	{
450 		std::stringstream body_sstream;
451 		std::string		  body_string;
452 		const char*		  body_raw_ptr = DE_NULL;
453 
454 		/* Preamble */
455 		body_sstream << "${VERSION}\n"
456 						"\n"
457 						"${TESSELLATION_SHADER_REQUIRE}\n";
458 
459 		if (should_pass_point_size_data_in_ts)
460 		{
461 			body_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n";
462 		}
463 
464 		/* Layout qualifiers */
465 		body_sstream << "\n"
466 						"layout(PRIMITIVE_MODE, point_mode) in;\n"
467 						"\n"
468 
469 						/* Input block definition starts here: */
470 						"in OUT_TC\n"
471 						"{\n";
472 
473 		if (should_pass_point_size_data_in_ts)
474 		{
475 			body_sstream << "    float tc_pointSize;\n";
476 		}
477 
478 		body_sstream << "    vec4  tc_position;\n"
479 						"    vec4  tc_value1;\n"
480 						"   ivec4  tc_value2;\n"
481 						"} in_data[];\n"
482 						"\n"
483 						"patch in vec4 tc_patch_data;\n"
484 						"\n";
485 		/* Input block definition ends here. */
486 
487 		/* Output block definition (only defined if GS stage is present) starts here: */
488 		if (should_use_geometry_shader)
489 		{
490 			body_sstream << "out OUT_TE\n"
491 							"{\n";
492 
493 			/* Output block contents */
494 			if (should_pass_point_size_data_in_ts)
495 			{
496 				body_sstream << "    float tc_pointSize;\n"
497 								"    float te_pointSize;\n";
498 			}
499 
500 			body_sstream << "    vec4  tc_position;\n"
501 							"    vec4  tc_value1;\n"
502 							"   ivec4  tc_value2;\n"
503 							"    vec4  te_position;\n"
504 							"} out_data;\n";
505 		}
506 		/* Output block definition ends here. */
507 		else
508 		{
509 			if (should_pass_point_size_data_in_ts)
510 			{
511 				body_sstream << "out float tc_pointSize;\n"
512 								"out float te_pointSize;\n";
513 			}
514 
515 			body_sstream << "out  vec4  tc_position;\n"
516 							"out  vec4  tc_value1;\n"
517 							"flat out ivec4  tc_value2;\n"
518 							"out  vec4  te_position;\n"
519 							"out  vec4  te_patch_data;\n";
520 		}
521 
522 		body_sstream << "\n"
523 						"void main()\n"
524 						"{\n";
525 
526 		if (should_use_geometry_shader)
527 		{
528 			body_sstream << "#define OUTPUT_VARIABLE(x) out_data.x\n";
529 		}
530 		else
531 		{
532 			body_sstream << "#define OUTPUT_VARIABLE(x) x\n";
533 		}
534 
535 		if (should_pass_point_size_data_in_ts)
536 		{
537 			body_sstream << "    OUTPUT_VARIABLE(tc_pointSize) = in_data[1].tc_pointSize;\n"
538 							"    OUTPUT_VARIABLE(te_pointSize) = gl_in[1].gl_PointSize;\n";
539 		}
540 
541 		body_sstream << "    OUTPUT_VARIABLE(tc_position)   = in_data[1].tc_position;\n"
542 						"    OUTPUT_VARIABLE(tc_value1)     = in_data[0].tc_value1;\n"
543 						"    OUTPUT_VARIABLE(tc_value2)     = in_data[1].tc_value2;\n"
544 						"    OUTPUT_VARIABLE(te_position)   = gl_in[0].gl_Position;\n";
545 
546 		if (!should_use_geometry_shader)
547 		{
548 			body_sstream << "    OUTPUT_VARIABLE(te_patch_data) = tc_patch_data;\n";
549 		}
550 		body_sstream << "}\n";
551 
552 		body_string = body_sstream.str();
553 
554 		/* Replace PRIMITIVE_MODE token with user-requested primitive mode */
555 		std::string primitive_mode_replacement	= TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode);
556 		std::string primitive_mode_token		  = "PRIMITIVE_MODE";
557 		std::size_t primitive_mode_token_position = std::string::npos;
558 
559 		primitive_mode_token_position = body_string.find(primitive_mode_token);
560 
561 		while (primitive_mode_token_position != std::string::npos)
562 		{
563 			body_string = body_string.replace(primitive_mode_token_position, primitive_mode_token.length(),
564 											  primitive_mode_replacement);
565 
566 			primitive_mode_token_position = body_string.find(primitive_mode_token);
567 		}
568 
569 		body_raw_ptr = body_string.c_str();
570 
571 		shaderSourceSpecialized(run.tes_id, 1 /* count */, &body_raw_ptr);
572 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation evaluation shader");
573 	}
574 
575 	/* Set geometry shader's body (if requested) */
576 	if (should_use_geometry_shader)
577 	{
578 		std::stringstream body_sstream;
579 		std::string		  body_string;
580 		const char*		  body_raw_ptr = DE_NULL;
581 
582 		body_sstream << "${VERSION}\n"
583 						"\n"
584 						"${GEOMETRY_SHADER_REQUIRE}\n";
585 
586 		if (should_pass_point_size_data_in_gs)
587 		{
588 			body_sstream << "${GEOMETRY_POINT_SIZE_REQUIRE}\n";
589 		}
590 
591 		body_sstream << "${SHADER_IO_BLOCKS_REQUIRE}\n"
592 						"\n"
593 						"layout(points)                   in;\n"
594 						"layout(max_vertices = 2, points) out;\n"
595 						"\n"
596 						"in OUT_TE\n"
597 						"{\n";
598 
599 		if (should_pass_point_size_data_in_ts)
600 		{
601 			body_sstream << "    float tc_pointSize;\n"
602 							"    float te_pointSize;\n";
603 		}
604 
605 		body_sstream << "    vec4  tc_position;\n"
606 						"    vec4  tc_value1;\n"
607 						"   ivec4  tc_value2;\n"
608 						"    vec4  te_position;\n"
609 						"} in_data[1];\n"
610 						"\n"
611 						"out float gs_tc_pointSize;\n"
612 						"out float gs_te_pointSize;\n"
613 						"out  vec4 gs_tc_position;\n"
614 						"out  vec4 gs_tc_value1;\n"
615 						"flat out ivec4 gs_tc_value2;\n"
616 						"out  vec4 gs_te_position;\n"
617 						"\n"
618 						"void main()\n"
619 						"{\n";
620 
621 		if (should_pass_point_size_data_in_gs)
622 		{
623 			body_sstream << "    gs_tc_pointSize = in_data[0].tc_pointSize;\n"
624 							"    gs_te_pointSize = in_data[0].te_pointSize;\n";
625 		}
626 
627 		body_sstream << "    gs_tc_position = in_data[0].tc_position;\n"
628 						"    gs_tc_value1   = in_data[0].tc_value1;\n"
629 						"    gs_tc_value2   = in_data[0].tc_value2;\n"
630 						"    gs_te_position = in_data[0].te_position;\n"
631 						"    EmitVertex();\n";
632 
633 		if (should_pass_point_size_data_in_gs)
634 		{
635 			body_sstream << "    gs_tc_pointSize = in_data[0].tc_pointSize + 1.0;\n"
636 							"    gs_te_pointSize = in_data[0].te_pointSize + 1.0;\n";
637 		}
638 
639 		body_sstream << "    gs_tc_position = in_data[0].tc_position +  vec4(1.0);\n"
640 						"    gs_tc_value1   = in_data[0].tc_value1   +  vec4(1.0);\n"
641 						"    gs_tc_value2   = in_data[0].tc_value2   + ivec4(1);\n"
642 						"    gs_te_position = in_data[0].te_position +  vec4(1.0);\n"
643 						"\n"
644 						"    EmitVertex();\n"
645 						"\n"
646 						"}\n";
647 
648 		body_string  = body_sstream.str();
649 		body_raw_ptr = body_string.c_str();
650 
651 		shaderSourceSpecialized(run.gs_id, 1 /* count */, &body_raw_ptr);
652 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for geometry shader");
653 	}
654 
655 	/* Configure varyings */
656 	unsigned int	   n_varyings					= 0;
657 	int				   varying_tc_pointSize_offset  = -1;
658 	int				   varying_tc_position_offset   = -1;
659 	int				   varying_tc_value1_offset		= -1;
660 	int				   varying_tc_value2_offset		= -1;
661 	int				   varying_te_patch_data_offset = -1;
662 	int				   varying_te_pointSize_offset  = -1;
663 	int				   varying_te_position_offset   = -1;
664 	const unsigned int varying_patch_data_size		= sizeof(float) * 4; /*  vec4 */
665 	const unsigned int varying_pointSize_size		= sizeof(float);
666 	const unsigned int varying_position_size		= sizeof(float) * 4; /*  vec4 */
667 	const unsigned int varying_value1_size			= sizeof(float) * 4; /*  vec4 */
668 	const unsigned int varying_value2_size			= sizeof(int) * 4;   /* ivec4 */
669 	const char**	   varyings						= DE_NULL;
670 	unsigned int	   varyings_size				= 0;
671 
672 	const char* gs_non_point_size_varyings[] = { "gs_tc_position", "gs_tc_value1", "gs_tc_value2", "gs_te_position" };
673 	const char* gs_point_size_varyings[]	 = { "gs_tc_position", "gs_tc_value1",	"gs_tc_value2",
674 											 "gs_te_position", "gs_tc_pointSize", "gs_te_pointSize" };
675 	const char* non_gs_non_point_size_varyings[] = { "tc_position", "tc_value1", "tc_value2", "te_position",
676 													 "te_patch_data" };
677 	const char* non_gs_point_size_varyings[] = { "tc_position",  "tc_value1",	"tc_value2",	"te_position",
678 												 "tc_pointSize", "te_pointSize", "te_patch_data" };
679 
680 	if (should_use_geometry_shader)
681 	{
682 		if (should_pass_point_size_data_in_gs)
683 		{
684 			n_varyings	= sizeof(gs_point_size_varyings) / sizeof(gs_point_size_varyings[0]);
685 			varyings	  = gs_point_size_varyings;
686 			varyings_size = varying_position_size +  /* gs_tc_position  */
687 							varying_value1_size +	/* gs_tc_value1    */
688 							varying_value2_size +	/* gs_tc_value2    */
689 							varying_position_size +  /* gs_te_position  */
690 							varying_pointSize_size + /* gs_tc_pointSize */
691 							varying_pointSize_size;  /* gs_te_pointSize */
692 
693 			varying_tc_position_offset  = 0;
694 			varying_tc_value1_offset	= varying_tc_position_offset + varying_position_size;
695 			varying_tc_value2_offset	= varying_tc_value1_offset + varying_value1_size;
696 			varying_te_position_offset  = varying_tc_value2_offset + varying_value2_size;
697 			varying_tc_pointSize_offset = varying_te_position_offset + varying_position_size;
698 			varying_te_pointSize_offset = varying_tc_pointSize_offset + varying_pointSize_size;
699 		}
700 		else
701 		{
702 			n_varyings	= sizeof(gs_non_point_size_varyings) / sizeof(gs_non_point_size_varyings[0]);
703 			varyings	  = gs_non_point_size_varyings;
704 			varyings_size = varying_position_size + /* gs_tc_position */
705 							varying_value1_size +   /* gs_tc_value1   */
706 							varying_value2_size +   /* gs_tc_value2   */
707 							varying_position_size;  /* gs_te_position */
708 
709 			varying_tc_position_offset = 0;
710 			varying_tc_value1_offset   = varying_tc_position_offset + varying_position_size;
711 			varying_tc_value2_offset   = varying_tc_value1_offset + varying_value1_size;
712 			varying_te_position_offset = varying_tc_value2_offset + varying_value2_size;
713 		}
714 	} /* if (should_use_geometry_shader) */
715 	else
716 	{
717 		if (should_pass_point_size_data_in_ts)
718 		{
719 			n_varyings	= sizeof(non_gs_point_size_varyings) / sizeof(non_gs_point_size_varyings[0]);
720 			varyings	  = non_gs_point_size_varyings;
721 			varyings_size = varying_position_size +  /* tc_position   */
722 							varying_value1_size +	/* tc_value1     */
723 							varying_value2_size +	/* tc_value2     */
724 							varying_position_size +  /* te_position   */
725 							varying_pointSize_size + /* tc_pointSize  */
726 							varying_pointSize_size + /* te_pointSize  */
727 							varying_patch_data_size; /* tc_patch_data */
728 
729 			varying_tc_position_offset   = 0;
730 			varying_tc_value1_offset	 = varying_tc_position_offset + varying_position_size;
731 			varying_tc_value2_offset	 = varying_tc_value1_offset + varying_value1_size;
732 			varying_te_position_offset   = varying_tc_value2_offset + varying_value2_size;
733 			varying_tc_pointSize_offset  = varying_te_position_offset + varying_position_size;
734 			varying_te_pointSize_offset  = varying_tc_pointSize_offset + varying_pointSize_size;
735 			varying_te_patch_data_offset = varying_te_pointSize_offset + varying_pointSize_size;
736 		}
737 		else
738 		{
739 			n_varyings	= sizeof(non_gs_non_point_size_varyings) / sizeof(non_gs_non_point_size_varyings[0]);
740 			varyings	  = non_gs_non_point_size_varyings;
741 			varyings_size = varying_position_size +  /* tc_position   */
742 							varying_value1_size +	/* tc_value1     */
743 							varying_value2_size +	/* tc_value2     */
744 							varying_position_size +  /* te_position   */
745 							varying_patch_data_size; /* tc_patch_data */
746 
747 			varying_tc_position_offset   = 0;
748 			varying_tc_value1_offset	 = varying_tc_position_offset + varying_position_size;
749 			varying_tc_value2_offset	 = varying_tc_value1_offset + varying_value1_size;
750 			varying_te_position_offset   = varying_tc_value2_offset + varying_value2_size;
751 			varying_te_patch_data_offset = varying_te_position_offset + varying_position_size;
752 		}
753 	}
754 
755 	gl.transformFeedbackVaryings(run.po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
756 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
757 
758 	/* Compile all the shader objects */
759 	const glw::GLuint  shaders[] = { run.fs_id, run.gs_id, run.tcs_id, run.tes_id, run.vs_id };
760 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
761 
762 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
763 	{
764 		glw::GLuint shader = shaders[n_shader];
765 
766 		if (shader != 0)
767 		{
768 			m_utils_ptr->compileShaders(1 /* n_shaders */, &shader, true);
769 		}
770 	}
771 
772 	/* Link the program object */
773 	gl.linkProgram(run.po_id);
774 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
775 
776 	/* Make sure the linking has succeeded */
777 	glw::GLint link_status = GL_FALSE;
778 
779 	gl.getProgramiv(run.po_id, GL_LINK_STATUS, &link_status);
780 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
781 
782 	if (link_status != GL_TRUE)
783 	{
784 		TCU_FAIL("Program linking failed");
785 	}
786 
787 	/* Now that we have a linked program object, it's time to determine how much space
788 	 * we will need to hold XFB data.
789 	 */
790 	unsigned int bo_size			  = 0;
791 	unsigned int n_result_tess_coords = 0;
792 	const float  tess_levels[]		  = /* as per shaders constructed by the test */
793 		{ 4.0f, 4.0f, 4.0f, 4.0f };
794 
795 	n_result_tess_coords = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
796 		run.primitive_mode, tess_levels, tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL,
797 		true); /* is_point_mode_enabled */
798 
799 	if (should_use_geometry_shader)
800 	{
801 		/* Geometry shader will output twice as many vertices */
802 		n_result_tess_coords *= 2;
803 	}
804 
805 	run.n_result_vertices_per_patch = n_result_tess_coords;
806 	n_result_tess_coords *= m_n_input_vertices_per_run;
807 	bo_size = n_result_tess_coords * varyings_size;
808 
809 	/* Proceed with buffer object storage allocation */
810 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, /* data */
811 				  GL_STATIC_DRAW);
812 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
813 
814 	/* Great, time to actually render the data! */
815 	glw::GLenum tf_mode =
816 		TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, true); /* is_point_mode_enabled */
817 
818 	gl.useProgram(run.po_id);
819 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed");
820 
821 	gl.beginTransformFeedback(tf_mode);
822 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed");
823 	{
824 		gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, m_n_input_vertices_per_run);
825 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
826 	}
827 	gl.endTransformFeedback();
828 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
829 
830 	/* The data should have landed in the buffer object storage by now. Map the BO into
831 	 * process space. */
832 	const void* bo_ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
833 										   bo_size, GL_MAP_READ_BIT);
834 
835 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed");
836 
837 	/* Extract varyings' data */
838 	for (unsigned int n_tess_coord = 0; n_tess_coord < n_result_tess_coords; ++n_tess_coord)
839 	{
840 		const char* data = (const char*)bo_ptr + n_tess_coord * varyings_size;
841 
842 		if (varying_tc_position_offset != -1)
843 		{
844 			const float* position_data((const float*)(data + varying_tc_position_offset));
845 			_vec4		 new_entry(position_data[0], position_data[1], position_data[2], position_data[3]);
846 
847 			run.result_tc_position_data.push_back(new_entry);
848 		}
849 
850 		if (varying_tc_value1_offset != -1)
851 		{
852 			const float* value1_data((const float*)(data + varying_tc_value1_offset));
853 			_vec4		 new_entry(value1_data[0], value1_data[1], value1_data[2], value1_data[3]);
854 
855 			run.result_tc_value1_data.push_back(new_entry);
856 		}
857 
858 		if (varying_tc_value2_offset != -1)
859 		{
860 			const int* value2_data((const int*)(data + varying_tc_value2_offset));
861 			_ivec4	 new_entry(value2_data[0], value2_data[1], value2_data[2], value2_data[3]);
862 
863 			run.result_tc_value2_data.push_back(new_entry);
864 		}
865 
866 		if (varying_te_position_offset != -1)
867 		{
868 			const float* position_data((const float*)(data + varying_te_position_offset));
869 			_vec4		 new_entry(position_data[0], position_data[1], position_data[2], position_data[3]);
870 
871 			run.result_te_position_data.push_back(new_entry);
872 		}
873 
874 		if (varying_tc_pointSize_offset != -1)
875 		{
876 			const float* pointSize_ptr((const float*)(data + varying_tc_pointSize_offset));
877 
878 			run.result_tc_pointSize_data.push_back(*pointSize_ptr);
879 		}
880 
881 		if (varying_te_pointSize_offset != -1)
882 		{
883 			const float* pointSize_ptr((const float*)(data + varying_te_pointSize_offset));
884 
885 			run.result_te_pointSize_data.push_back(*pointSize_ptr);
886 		}
887 
888 		if (varying_te_patch_data_offset != -1)
889 		{
890 			const float* patch_data_ptr((const float*)(data + varying_te_patch_data_offset));
891 			_vec4		 new_entry(patch_data_ptr[0], patch_data_ptr[1], patch_data_ptr[2], patch_data_ptr[3]);
892 
893 			run.result_te_patch_data.push_back(new_entry);
894 		}
895 	} /* for (all XFB data associated with tessellated coordinates) */
896 
897 	/* Now that we're done extracting the data we need, we're fine to unmap the buffer object */
898 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
899 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed");
900 }
901 
902 /** Executes the test.
903  *
904  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
905  *
906  *  Note the function throws exception should an error occur!
907  *
908  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
909  **/
iterate(void)910 tcu::TestNode::IterateResult TessellationShaderTCTEDataPassThrough::iterate(void)
911 {
912 	const float epsilon = 1e-5f;
913 
914 	/* Initialize ES test objects */
915 	initTest();
916 
917 	/* Iterate over all runs */
918 	for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); ++run_iterator)
919 	{
920 		const _run& run = *run_iterator;
921 
922 		/* Check result tc_pointSize data if available */
923 		unsigned int n_vertex = 0;
924 
925 		for (std::vector<glw::GLfloat>::const_iterator data_iterator = run.result_tc_pointSize_data.begin();
926 			 data_iterator != run.result_tc_pointSize_data.end(); data_iterator++, n_vertex++)
927 		{
928 			const glw::GLfloat data			  = *data_iterator;
929 			unsigned int	   vertex_id	  = n_vertex / run.n_result_vertices_per_patch;
930 			float			   expected_value = 1.0f / (float(vertex_id) + 1.0f);
931 
932 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
933 			{
934 				/* Odd vertices emitted by geometry shader add 1 to all components */
935 				expected_value += 1.0f;
936 			}
937 
938 			if (de::abs(data - expected_value) > epsilon)
939 			{
940 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_pointSize value found at index [" << n_vertex
941 								   << "];"
942 									  " expected:["
943 								   << expected_value << "], "
944 														" found:["
945 								   << data << "]." << tcu::TestLog::EndMessage;
946 
947 				TCU_FAIL("Invalid tc_pointSize value found");
948 			}
949 		}
950 
951 		/* Check result tc_position data if available */
952 		n_vertex -= n_vertex;
953 
954 		for (std::vector<_vec4>::const_iterator data_iterator = run.result_tc_position_data.begin();
955 			 data_iterator != run.result_tc_position_data.end(); data_iterator++, n_vertex++)
956 		{
957 			const _vec4& data			= *data_iterator;
958 			float		 expected_value = (float)(n_vertex / run.n_result_vertices_per_patch);
959 
960 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
961 			{
962 				/* Odd vertices emitted by geometry shader add 1 to all components */
963 				expected_value += 1.0f;
964 			}
965 
966 			if (de::abs(data.x - expected_value) > epsilon || de::abs(data.y - expected_value) > epsilon ||
967 				de::abs(data.z - expected_value) > epsilon || de::abs(data.w - expected_value) > epsilon)
968 			{
969 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_position value found at index [" << n_vertex
970 								   << "];"
971 									  " expected:"
972 									  " ["
973 								   << expected_value << ", " << expected_value << ", " << expected_value << ", "
974 								   << expected_value << "], found:"
975 														" ["
976 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
977 								   << tcu::TestLog::EndMessage;
978 
979 				TCU_FAIL("Invalid tc_position value found");
980 			}
981 		}
982 
983 		/* Check result tc_value1 data if available */
984 		n_vertex -= n_vertex;
985 
986 		for (std::vector<_vec4>::const_iterator data_iterator = run.result_tc_value1_data.begin();
987 			 data_iterator != run.result_tc_value1_data.end(); data_iterator++, n_vertex++)
988 		{
989 			const _vec4& data			= *data_iterator;
990 			unsigned int vertex_id		= n_vertex / run.n_result_vertices_per_patch;
991 			_vec4		 expected_value = _vec4((float)vertex_id, ((float)vertex_id) * 0.5f, ((float)vertex_id) * 0.25f,
992 										 ((float)vertex_id) * 0.125f);
993 
994 			/* TE uses an even vertex outputted by TC, so we need
995 			 * to multiply the expected value by 2.
996 			 */
997 			expected_value.x *= 2.0f;
998 			expected_value.y *= 2.0f;
999 			expected_value.z *= 2.0f;
1000 			expected_value.w *= 2.0f;
1001 
1002 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
1003 			{
1004 				/* Odd vertices emitted by geometry shader add 1 to all components */
1005 				expected_value.x += 1.0f;
1006 				expected_value.y += 1.0f;
1007 				expected_value.z += 1.0f;
1008 				expected_value.w += 1.0f;
1009 			}
1010 
1011 			if (de::abs(data.x - expected_value.x) > epsilon || de::abs(data.y - expected_value.y) > epsilon ||
1012 				de::abs(data.z - expected_value.z) > epsilon || de::abs(data.w - expected_value.w) > epsilon)
1013 			{
1014 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_value1 value found at index [" << n_vertex
1015 								   << "];"
1016 									  " expected:"
1017 									  " ["
1018 								   << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", "
1019 								   << expected_value.w << "], found:"
1020 														  " ["
1021 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
1022 								   << tcu::TestLog::EndMessage;
1023 
1024 				TCU_FAIL("Invalid tc_value1 value found");
1025 			}
1026 		}
1027 
1028 		/* Check result tc_value2 data if available */
1029 		n_vertex -= n_vertex;
1030 
1031 		for (std::vector<_ivec4>::const_iterator data_iterator = run.result_tc_value2_data.begin();
1032 			 data_iterator != run.result_tc_value2_data.end(); data_iterator++, n_vertex++)
1033 		{
1034 			const _ivec4& data			 = *data_iterator;
1035 			unsigned int  vertex_id		 = n_vertex / run.n_result_vertices_per_patch;
1036 			_ivec4		  expected_value = _ivec4(vertex_id, vertex_id + 1, vertex_id + 2, vertex_id + 3);
1037 
1038 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
1039 			{
1040 				/* Odd vertices emitted by geometry shader add 1 to all components */
1041 				expected_value.x++;
1042 				expected_value.y++;
1043 				expected_value.z++;
1044 				expected_value.w++;
1045 			}
1046 
1047 			if (data.x != expected_value.x || data.y != expected_value.y || data.z != expected_value.z ||
1048 				data.w != expected_value.w)
1049 			{
1050 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_value2 value found at index [" << n_vertex
1051 								   << "];"
1052 									  " expected:"
1053 									  " ["
1054 								   << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", "
1055 								   << expected_value.w << "], found:"
1056 														  " ["
1057 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
1058 								   << tcu::TestLog::EndMessage;
1059 
1060 				TCU_FAIL("Invalid tc_value2 value found");
1061 			}
1062 		}
1063 
1064 		/* Check result te_pointSize data if available */
1065 		n_vertex -= n_vertex;
1066 
1067 		for (std::vector<glw::GLfloat>::const_iterator data_iterator = run.result_te_pointSize_data.begin();
1068 			 data_iterator != run.result_te_pointSize_data.end(); data_iterator++, n_vertex++)
1069 		{
1070 			const glw::GLfloat data			  = *data_iterator;
1071 			unsigned int	   vertex_id	  = n_vertex / run.n_result_vertices_per_patch;
1072 			float			   expected_value = 2.0f / (float(vertex_id) + 1.0f);
1073 
1074 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
1075 			{
1076 				/* Odd vertices emitted by geometry shader add 1 to all components */
1077 				expected_value += 1.0f;
1078 			}
1079 
1080 			if (de::abs(data - expected_value) > epsilon)
1081 			{
1082 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid te_pointSize value found at index [" << n_vertex
1083 								   << "];"
1084 									  " expected:["
1085 								   << expected_value << "], "
1086 														" found:["
1087 								   << data << "]." << tcu::TestLog::EndMessage;
1088 
1089 				TCU_FAIL("Invalid te_pointSize value found");
1090 			}
1091 		}
1092 
1093 		/* Check result te_position data if available */
1094 		n_vertex -= n_vertex;
1095 
1096 		for (std::vector<_vec4>::const_iterator data_iterator = run.result_te_position_data.begin();
1097 			 data_iterator != run.result_te_position_data.end(); data_iterator++, n_vertex++)
1098 		{
1099 			const _vec4& data			= *data_iterator;
1100 			float		 expected_value = (float)(n_vertex / run.n_result_vertices_per_patch);
1101 
1102 			/* te_position should be equal to tc_position, with 3 added to all components */
1103 			expected_value += 3.0f;
1104 
1105 			if (run.gs_id != 0 && (n_vertex % 2) != 0)
1106 			{
1107 				/* Odd vertices emitted by geometry shader add 1 to all components */
1108 				expected_value += 1.0f;
1109 			}
1110 
1111 			if (de::abs(data.x - expected_value) > epsilon || de::abs(data.y - expected_value) > epsilon ||
1112 				de::abs(data.z - expected_value) > epsilon || de::abs(data.w - expected_value) > epsilon)
1113 			{
1114 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid te_position value found at index [" << n_vertex
1115 								   << "];"
1116 									  " expected:"
1117 									  " ["
1118 								   << expected_value << ", " << expected_value << ", " << expected_value << ", "
1119 								   << expected_value << "], found:"
1120 														" ["
1121 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
1122 								   << tcu::TestLog::EndMessage;
1123 
1124 				TCU_FAIL("Invalid te_position value found");
1125 			}
1126 		}
1127 
1128 		/* Check result tc_patch_data data if available */
1129 		n_vertex -= n_vertex;
1130 
1131 		for (std::vector<_vec4>::const_iterator data_iterator = run.result_te_patch_data.begin();
1132 			 data_iterator != run.result_te_patch_data.end(); data_iterator++, n_vertex++)
1133 		{
1134 			const _vec4& data			= *data_iterator;
1135 			unsigned int vertex_id		= n_vertex / run.n_result_vertices_per_patch;
1136 			_vec4		 expected_value = _vec4((float)vertex_id, ((float)vertex_id) * 0.5f, ((float)vertex_id) * 0.25f,
1137 										 ((float)vertex_id) * 0.125f);
1138 
1139 			/* TE uses an even vertex outputted by TC, so we need
1140 			 * to multiply the expected value by 2.
1141 			 */
1142 			expected_value.x *= 2.0f;
1143 			expected_value.y *= 2.0f;
1144 			expected_value.z *= 2.0f;
1145 			expected_value.w *= 2.0f;
1146 
1147 			if (de::abs(data.x - expected_value.x) > epsilon || de::abs(data.y - expected_value.y) > epsilon ||
1148 				de::abs(data.z - expected_value.z) > epsilon || de::abs(data.w - expected_value.w) > epsilon)
1149 			{
1150 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid tc_patch_data value found at index ["
1151 								   << n_vertex << "];"
1152 												  " expected:"
1153 												  " ["
1154 								   << expected_value.x << ", " << expected_value.y << ", " << expected_value.z << ", "
1155 								   << expected_value.w << "], found:"
1156 														  " ["
1157 								   << data.x << ", " << data.y << ", " << data.z << ", " << data.w << "]."
1158 								   << tcu::TestLog::EndMessage;
1159 
1160 				TCU_FAIL("Invalid tc_patch_data value found");
1161 			}
1162 		}
1163 	} /* for (all runs) */
1164 
1165 	/* All done */
1166 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1167 	return STOP;
1168 }
1169 
1170 /** Constructor
1171  *
1172  * @param context Test context
1173  **/
TessellationShaderTCTEgl_in(Context & context,const ExtParameters & extParams)1174 TessellationShaderTCTEgl_in::TessellationShaderTCTEgl_in(Context& context, const ExtParameters& extParams)
1175 	: TestCaseBase(context, extParams, "gl_in", "Verifies values of gl_in[] in a tessellation evaluation shader "
1176 												"are taken from output variables of a tessellation control shader"
1177 												"if one is present.")
1178 	, m_bo_id(0)
1179 	, m_fs_id(0)
1180 	, m_po_id(0)
1181 	, m_tcs_id(0)
1182 	, m_tes_id(0)
1183 	, m_vao_id(0)
1184 	, m_vs_id(0)
1185 {
1186 	/* Left blank on purpose */
1187 }
1188 
1189 /** Deinitializes all ES objects created for the test. */
deinit()1190 void TessellationShaderTCTEgl_in::deinit()
1191 {
1192 	/** Call base class' deinit() function */
1193 	TestCaseBase::deinit();
1194 
1195 	if (!m_is_tessellation_shader_supported)
1196 	{
1197 		return;
1198 	}
1199 
1200 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1201 
1202 	/* Revert TF buffer object bindings */
1203 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
1204 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
1205 
1206 	/* Reset GL_PATCH_VERTICES_EXT value to the default setting */
1207 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
1208 
1209 	/* Disable GL_RASTERIZER_DISCARD mdoe */
1210 	gl.disable(GL_RASTERIZER_DISCARD);
1211 
1212 	/* Unbind vertex array object */
1213 	gl.bindVertexArray(0);
1214 
1215 	/* Release all objects we might've created */
1216 	if (m_bo_id != 0)
1217 	{
1218 		gl.deleteBuffers(1, &m_bo_id);
1219 
1220 		m_bo_id = 0;
1221 	}
1222 
1223 	if (m_fs_id != 0)
1224 	{
1225 		gl.deleteShader(m_fs_id);
1226 
1227 		m_fs_id = 0;
1228 	}
1229 
1230 	if (m_po_id != 0)
1231 	{
1232 		gl.deleteProgram(m_po_id);
1233 
1234 		m_po_id = 0;
1235 	}
1236 
1237 	if (m_tcs_id != 0)
1238 	{
1239 		gl.deleteShader(m_tcs_id);
1240 
1241 		m_tcs_id = 0;
1242 	}
1243 
1244 	if (m_tes_id != 0)
1245 	{
1246 		gl.deleteShader(m_tes_id);
1247 
1248 		m_tes_id = 0;
1249 	}
1250 
1251 	if (m_vs_id != 0)
1252 	{
1253 		gl.deleteShader(m_vs_id);
1254 
1255 		m_vs_id = 0;
1256 	}
1257 
1258 	if (m_vao_id != 0)
1259 	{
1260 		gl.deleteVertexArrays(1, &m_vao_id);
1261 
1262 		m_vao_id = 0;
1263 	}
1264 }
1265 
1266 /** Initializes all ES objects that will be used for the test. */
initTest()1267 void TessellationShaderTCTEgl_in::initTest()
1268 {
1269 	/* The test requires EXT_tessellation_shader */
1270 	if (!m_is_tessellation_shader_supported)
1271 	{
1272 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
1273 	}
1274 
1275 	/* Generate a program object we will later configure */
1276 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1277 
1278 	/* Initialize vertex array object */
1279 	gl.genVertexArrays(1, &m_vao_id);
1280 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
1281 
1282 	gl.bindVertexArray(m_vao_id);
1283 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
1284 
1285 	/* Create program object */
1286 	m_po_id = gl.createProgram();
1287 
1288 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
1289 
1290 	/* Generate shader objects the test will use */
1291 	m_fs_id  = gl.createShader(GL_FRAGMENT_SHADER);
1292 	m_tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
1293 	m_tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
1294 	m_vs_id  = gl.createShader(GL_VERTEX_SHADER);
1295 
1296 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
1297 
1298 	/* Configure fragment shader */
1299 	const char* fs_body = "${VERSION}\n"
1300 						  "\n"
1301 						  "void main()\n"
1302 						  "{\n"
1303 						  "}\n";
1304 
1305 	shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body);
1306 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object");
1307 
1308 	/* Configure tessellation control shader */
1309 	const char* tc_body = "${VERSION}\n"
1310 						  "\n"
1311 						  /* Required EXT_tessellation_shader functionality */
1312 						  "${TESSELLATION_SHADER_REQUIRE}\n"
1313 						  "\n"
1314 						  "layout (vertices = 1) out;\n"
1315 						  "\n"
1316 						  "out float out_float[];\n"
1317 						  "out int   out_int[];\n"
1318 						  "out ivec3 out_ivec3[];\n"
1319 						  "out mat2  out_mat2[];\n"
1320 						  "out uint  out_uint[];\n"
1321 						  "out uvec2 out_uvec2[];\n"
1322 						  "out vec4  out_vec4[];\n"
1323 						  "\n"
1324 						  "out struct\n"
1325 						  "{\n"
1326 						  "    int   test1;\n"
1327 						  "    float test2;\n"
1328 						  "} out_struct[];\n"
1329 						  /* Body */
1330 						  "void main()\n"
1331 						  "{\n"
1332 						  "    gl_out           [gl_InvocationID].gl_Position = vec4(5.0, 6.0, 7.0, 8.0);\n"
1333 						  "    gl_TessLevelOuter[0]                           = 1.0;\n"
1334 						  "    gl_TessLevelOuter[1]                           = 1.0;\n"
1335 						  "\n"
1336 						  "    out_float[gl_InvocationID] = 22.0;\n"
1337 						  "    out_int  [gl_InvocationID] = 23;\n"
1338 						  "    out_ivec3[gl_InvocationID] = ivec3(24, 25, 26);\n"
1339 						  "    out_mat2 [gl_InvocationID] = mat2(vec2(27.0, 28.0), vec2(29.0, 30.0) );\n"
1340 						  "    out_uint [gl_InvocationID] = 31u;\n"
1341 						  "    out_uvec2[gl_InvocationID] = uvec2(32, 33);\n"
1342 						  "    out_vec4 [gl_InvocationID] = vec4(34.0, 35.0, 36.0, 37.0);\n"
1343 						  "\n"
1344 						  "    out_struct[gl_InvocationID].test1 = 38;\n"
1345 						  "    out_struct[gl_InvocationID].test2 = 39.0;\n"
1346 						  "}\n";
1347 
1348 	shaderSourceSpecialized(m_tcs_id, 1 /* count */, &tc_body);
1349 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object");
1350 
1351 	/* Configure tessellation evaluation shader */
1352 	const char* te_body = "${VERSION}\n"
1353 						  "\n"
1354 						  "${TESSELLATION_SHADER_REQUIRE}\n"
1355 						  "\n"
1356 						  "layout (isolines, point_mode) in;\n"
1357 						  "\n"
1358 						  "in float out_float[];\n"
1359 						  "in int   out_int[];\n"
1360 						  "in ivec3 out_ivec3[];\n"
1361 						  "in mat2  out_mat2[];\n"
1362 						  "in uint  out_uint[];\n"
1363 						  "in uvec2 out_uvec2[];\n"
1364 						  "in vec4  out_vec4[];\n"
1365 						  "in struct\n"
1366 						  "{\n"
1367 						  "    int   test1;\n"
1368 						  "    float test2;\n"
1369 						  "} out_struct[];\n"
1370 						  "\n"
1371 						  "out float result_float;\n"
1372 						  "flat out int   result_int;\n"
1373 						  "flat out ivec3 result_ivec3;\n"
1374 						  "out mat2  result_mat2;\n"
1375 						  "flat out int   result_struct_test1;\n"
1376 						  "out float result_struct_test2;\n"
1377 						  "flat out uint  result_uint;\n"
1378 						  "flat out uvec2 result_uvec2;\n"
1379 						  "out vec4  result_vec4;\n"
1380 						  "\n"
1381 						  "void main()\n"
1382 						  "{\n"
1383 						  "    gl_Position = gl_in[0].gl_Position;\n"
1384 						  "\n"
1385 						  "    result_float        = out_float [0];\n"
1386 						  "    result_int          = out_int   [0];\n"
1387 						  "    result_ivec3        = out_ivec3 [0];\n"
1388 						  "    result_mat2         = out_mat2  [0];\n"
1389 						  "    result_struct_test1 = out_struct[0].test1;\n"
1390 						  "    result_struct_test2 = out_struct[0].test2;\n"
1391 						  "    result_uint         = out_uint  [0];\n"
1392 						  "    result_uvec2        = out_uvec2 [0];\n"
1393 						  "    result_vec4         = out_vec4  [0];\n"
1394 						  "}\n";
1395 
1396 	shaderSourceSpecialized(m_tes_id, 1 /* count */, &te_body);
1397 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object");
1398 
1399 	/* Configure vertex shader */
1400 	const char* vs_body = "${VERSION}\n"
1401 						  "\n"
1402 						  "${SHADER_IO_BLOCKS_ENABLE}\n"
1403 						  "\n"
1404 						  "out float out_float;\n"
1405 						  "flat out int   out_int;\n"
1406 						  "flat out ivec3 out_ivec3;\n"
1407 						  "out mat2  out_mat2;\n"
1408 						  "flat out uint  out_uint;\n"
1409 						  "flat out uvec2 out_uvec2;\n"
1410 						  "out vec4  out_vec4;\n"
1411 						  "\n"
1412 						  "flat out struct\n"
1413 						  "{\n"
1414 						  "    int   test1;\n"
1415 						  "    float test2;\n"
1416 						  "} out_struct;\n"
1417 						  "\n"
1418 						  "void main()\n"
1419 						  "{\n"
1420 						  "    gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n"
1421 						  "\n"
1422 						  "    out_float        = 1.0;\n"
1423 						  "    out_int          = 2;\n"
1424 						  "    out_ivec3        = ivec3(3, 4, 5);\n"
1425 						  "    out_mat2         = mat2(vec2(6.0, 7.0), vec2(8.0, 9.0) );\n"
1426 						  "    out_uint         = 10u;\n"
1427 						  "    out_uvec2        = uvec2(11u, 12u);\n"
1428 						  "    out_vec4         = vec4(12.0, 13.0, 14.0, 15.0);\n"
1429 						  "    out_struct.test1 = 20;\n"
1430 						  "    out_struct.test2 = 21.0;\n"
1431 						  "}\n";
1432 
1433 	shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body);
1434 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object");
1435 
1436 	/* Compile all shaders of our interest */
1437 	const glw::GLuint  shaders[] = { m_fs_id, m_tcs_id, m_tes_id, m_vs_id };
1438 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
1439 
1440 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
1441 	{
1442 		glw::GLint  compile_status = GL_FALSE;
1443 		glw::GLuint shader		   = shaders[n_shader];
1444 
1445 		gl.compileShader(shader);
1446 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
1447 
1448 		gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
1449 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
1450 
1451 		if (compile_status != GL_TRUE)
1452 		{
1453 			const char* src[] = { fs_body, tc_body, te_body, vs_body };
1454 			m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader
1455 							   << " failed.\n"
1456 							   << "Info log:\n"
1457 							   << getCompilationInfoLog(shader) << "Shader:\n"
1458 							   << src[n_shader] << tcu::TestLog::EndMessage;
1459 
1460 			TCU_FAIL("Shader compilation failed");
1461 		}
1462 	} /* for (all shaders) */
1463 
1464 	/* Attach the shaders to the test program object, set up XFB and then link the program */
1465 	glw::GLint			link_status	= GL_FALSE;
1466 	glw::GLint			n_xfb_varyings = 0;
1467 	const glw::GLchar** xfb_varyings   = NULL;
1468 	glw::GLint			xfb_size	   = 0;
1469 
1470 	getXFBProperties(&xfb_varyings, &n_xfb_varyings, &xfb_size);
1471 
1472 	gl.transformFeedbackVaryings(m_po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
1473 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
1474 
1475 	gl.attachShader(m_po_id, m_fs_id);
1476 	gl.attachShader(m_po_id, m_tcs_id);
1477 	gl.attachShader(m_po_id, m_tes_id);
1478 	gl.attachShader(m_po_id, m_vs_id);
1479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
1480 
1481 	gl.linkProgram(m_po_id);
1482 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1483 
1484 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1485 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
1486 
1487 	if (link_status != GL_TRUE)
1488 	{
1489 		TCU_FAIL("Program linking failed");
1490 	}
1491 
1492 	/* Generate and set up a buffer object we will use to hold XFBed data. */
1493 	gl.genBuffers(1, &m_bo_id);
1494 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1495 
1496 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
1497 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
1498 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
1499 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
1500 
1501 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_size, NULL /* data */, GL_STATIC_DRAW);
1502 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
1503 
1504 	/* We're good to execute the test! */
1505 }
1506 
1507 /** Retrieves XFB-specific properties that are used in various locations of
1508  *  this test implementation.
1509  *
1510  *  @param out_names    Deref will be used to store location of an array keeping
1511  *                      names of varyings that should be used for TF. Can be NULL,
1512  *                      in which case nothing will be stored under *out_names.
1513  *  @param out_n_names  Deref will be used to store number of strings the @param
1514  *                      out_names array holds. Can be NULL, in which case nothing
1515  *                      will be stored under *out_n_names.
1516  *  @param out_xfb_size Deref will be used to store amount of bytes needed to hold
1517  *                      all data generated by a draw call used by this test. Can be
1518  *                      NULL, in which case nothing will be stored under *out_xfb_size.
1519  **/
getXFBProperties(const glw::GLchar *** out_names,glw::GLint * out_n_names,glw::GLint * out_xfb_size)1520 void TessellationShaderTCTEgl_in::getXFBProperties(const glw::GLchar*** out_names, glw::GLint* out_n_names,
1521 												   glw::GLint* out_xfb_size)
1522 {
1523 	static const glw::GLchar* xfb_varyings[] = { "result_float", "result_int",			"result_ivec3",
1524 												 "result_mat2",  "result_struct_test1", "result_struct_test2",
1525 												 "result_uint",  "result_uvec2",		"result_vec4",
1526 												 "gl_Position" };
1527 	static const unsigned int xfb_size = (sizeof(float) +	  /* result_float */
1528 										  sizeof(int) +		   /* result_int */
1529 										  sizeof(int) * 3 +	/* result_ivec3 */
1530 										  sizeof(float) * 4 +  /* result_mat2 */
1531 										  sizeof(int) +		   /* result_struct_test1 */
1532 										  sizeof(float) +	  /* result_struct_test2 */
1533 										  sizeof(int) +		   /* result_uint */
1534 										  sizeof(int) * 2 +	/* result_uvec2 */
1535 										  sizeof(float) * 4 +  /* result_vec4 */
1536 										  sizeof(float) * 4) * /* gl_Position */
1537 										 2;					   /* two points will be generated by tessellation */
1538 
1539 	static const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
1540 
1541 	if (out_names != NULL)
1542 	{
1543 		*out_names = xfb_varyings;
1544 	}
1545 
1546 	if (out_n_names != NULL)
1547 	{
1548 		*out_n_names = n_xfb_varyings;
1549 	}
1550 
1551 	if (out_xfb_size != NULL)
1552 	{
1553 		/* NOTE: Tessellator is expected to generate two points for the purpose of
1554 		 *       this test, which is why we need to multiply the amount of bytes store
1555 		 *       in xfb_size by two.
1556 		 */
1557 		*out_xfb_size = xfb_size * 2;
1558 	}
1559 }
1560 
1561 /** Executes the test.
1562  *
1563  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1564  *
1565  *  Note the function throws exception should an error occur!
1566  *
1567  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
1568  **/
iterate(void)1569 tcu::TestNode::IterateResult TessellationShaderTCTEgl_in::iterate(void)
1570 {
1571 	/* Initialize ES test objects */
1572 	initTest();
1573 
1574 	/* Our program object takes a single vertex per patch */
1575 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1576 
1577 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
1578 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed");
1579 
1580 	/* Render the geometry. We're only interested in XFB data, not the visual outcome,
1581 	 * so disable rasterization before we fire a draw call.
1582 	 */
1583 	gl.useProgram(m_po_id);
1584 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
1585 
1586 	gl.enable(GL_RASTERIZER_DISCARD);
1587 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed");
1588 
1589 	gl.beginTransformFeedback(GL_POINTS);
1590 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_POINTS) call failed");
1591 	{
1592 		gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* count */);
1593 
1594 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
1595 	}
1596 	gl.endTransformFeedback();
1597 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
1598 
1599 	/* Download the data we stored with TF */
1600 	glw::GLint			n_xfb_names   = 0;
1601 	void*				rendered_data = NULL;
1602 	const glw::GLchar** xfb_names	 = NULL;
1603 	glw::GLint			xfb_size	  = 0;
1604 
1605 	getXFBProperties(&xfb_names, &n_xfb_names, &xfb_size);
1606 
1607 	rendered_data = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, xfb_size, GL_MAP_READ_BIT);
1608 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
1609 
1610 	/* Move through the result buffer and make sure the values we retrieved are valid.
1611 	 * Note that two points will be generated by the tessellator, so run the checks
1612 	 * twice.
1613 	 */
1614 	typedef enum {
1615 		XFB_VARYING_TYPE_FLOAT,
1616 		XFB_VARYING_TYPE_INT,
1617 
1618 		XFB_VARYING_TYPE_UNKNOWN
1619 	} _xfb_varying_type;
1620 
1621 	unsigned char* traveller_ptr = (unsigned char*)rendered_data;
1622 
1623 	for (glw::GLint n_point = 0; n_point < 2 /* points */; ++n_point)
1624 	{
1625 		for (glw::GLint n_xfb_name = 0; n_xfb_name < n_xfb_names; ++n_xfb_name)
1626 		{
1627 			glw::GLfloat	  expected_value_float[4] = { 0.0f };
1628 			glw::GLint		  expected_value_int[4]   = { 0 };
1629 			std::string		  name					  = xfb_names[n_xfb_name];
1630 			unsigned int	  n_varying_components	= 0;
1631 			_xfb_varying_type varying_type			  = XFB_VARYING_TYPE_UNKNOWN;
1632 
1633 			if (name.compare("result_float") == 0)
1634 			{
1635 				expected_value_float[0] = 22.0f;
1636 				n_varying_components	= 1;
1637 				varying_type			= XFB_VARYING_TYPE_FLOAT;
1638 			}
1639 			else if (name.compare("result_int") == 0)
1640 			{
1641 				expected_value_int[0] = 23;
1642 				n_varying_components  = 1;
1643 				varying_type		  = XFB_VARYING_TYPE_INT;
1644 			}
1645 			else if (name.compare("result_ivec3") == 0)
1646 			{
1647 				expected_value_int[0] = 24;
1648 				expected_value_int[1] = 25;
1649 				expected_value_int[2] = 26;
1650 				n_varying_components  = 3;
1651 				varying_type		  = XFB_VARYING_TYPE_INT;
1652 			}
1653 			else if (name.compare("result_mat2") == 0)
1654 			{
1655 				expected_value_float[0] = 27.0f;
1656 				expected_value_float[1] = 28.0f;
1657 				expected_value_float[2] = 29.0f;
1658 				expected_value_float[3] = 30.0f;
1659 				n_varying_components	= 4;
1660 				varying_type			= XFB_VARYING_TYPE_FLOAT;
1661 			}
1662 			else if (name.compare("result_struct_test1") == 0)
1663 			{
1664 				expected_value_int[0] = 38;
1665 				n_varying_components  = 1;
1666 				varying_type		  = XFB_VARYING_TYPE_INT;
1667 			}
1668 			else if (name.compare("result_struct_test2") == 0)
1669 			{
1670 				expected_value_float[0] = 39.0f;
1671 				n_varying_components	= 1;
1672 				varying_type			= XFB_VARYING_TYPE_FLOAT;
1673 			}
1674 			else if (name.compare("result_uint") == 0)
1675 			{
1676 				expected_value_int[0] = 31;
1677 				n_varying_components  = 1;
1678 				varying_type		  = XFB_VARYING_TYPE_INT;
1679 			}
1680 			else if (name.compare("result_uvec2") == 0)
1681 			{
1682 				expected_value_int[0] = 32;
1683 				expected_value_int[1] = 33;
1684 				n_varying_components  = 2;
1685 				varying_type		  = XFB_VARYING_TYPE_INT;
1686 			}
1687 			else if (name.compare("result_vec4") == 0)
1688 			{
1689 				expected_value_float[0] = 34.0f;
1690 				expected_value_float[1] = 35.0f;
1691 				expected_value_float[2] = 36.0f;
1692 				expected_value_float[3] = 37.0f;
1693 				n_varying_components	= 4;
1694 				varying_type			= XFB_VARYING_TYPE_FLOAT;
1695 			}
1696 			else if (name.compare("gl_Position") == 0)
1697 			{
1698 				expected_value_float[0] = 5.0f;
1699 				expected_value_float[1] = 6.0f;
1700 				expected_value_float[2] = 7.0f;
1701 				expected_value_float[3] = 8.0f;
1702 				n_varying_components	= 4;
1703 				varying_type			= XFB_VARYING_TYPE_FLOAT;
1704 			}
1705 			else
1706 			{
1707 				TCU_FAIL("Unrecognized XFB name");
1708 			}
1709 
1710 			/* Move through the requested amount of components and perform type-specific
1711 			 * comparison.
1712 			 */
1713 			const float epsilon = (float)1e-5;
1714 
1715 			for (unsigned int n_component = 0; n_component < n_varying_components; ++n_component)
1716 			{
1717 				switch (varying_type)
1718 				{
1719 				case XFB_VARYING_TYPE_FLOAT:
1720 				{
1721 					glw::GLfloat* rendered_value = (glw::GLfloat*)traveller_ptr;
1722 
1723 					if (de::abs(*rendered_value - expected_value_float[n_component]) > epsilon)
1724 					{
1725 						m_testCtx.getLog()
1726 							<< tcu::TestLog::Message << "Invalid component at index [" << n_component << "] "
1727 							<< "(found:" << *rendered_value << " expected:" << expected_value_float[n_component]
1728 							<< ") for varying [" << name.c_str() << "]" << tcu::TestLog::EndMessage;
1729 					}
1730 
1731 					traveller_ptr += sizeof(glw::GLfloat);
1732 
1733 					break;
1734 				}
1735 
1736 				case XFB_VARYING_TYPE_INT:
1737 				{
1738 					glw::GLint* rendered_value = (glw::GLint*)traveller_ptr;
1739 
1740 					if (*rendered_value != expected_value_int[n_component])
1741 					{
1742 						m_testCtx.getLog()
1743 							<< tcu::TestLog::Message << "Invalid component at index [" << n_component << "] "
1744 							<< "(found:" << *rendered_value << " expected:" << expected_value_int[n_component]
1745 							<< ") for varying [" << name.c_str() << "]" << tcu::TestLog::EndMessage;
1746 
1747 						TCU_FAIL("Invalid rendered value");
1748 					}
1749 
1750 					traveller_ptr += sizeof(glw::GLint);
1751 
1752 					break;
1753 				}
1754 
1755 				default:
1756 				{
1757 					TCU_FAIL("Unrecognized varying type");
1758 				}
1759 				} /* switch(varying_type) */
1760 
1761 			} /* for (all components) */
1762 		}	 /* for (all XFBed variables) */
1763 	}		  /* for (both points) */
1764 
1765 	/* Unmap the BO */
1766 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1767 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
1768 
1769 	/* All done */
1770 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1771 	return STOP;
1772 }
1773 
1774 /** Constructor
1775  *
1776  * @param context Test context
1777  **/
1778 TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::
TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize(Context & context,const ExtParameters & extParams)1779 	TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize(Context& context, const ExtParameters& extParams)
1780 	: TestCaseBase(context, extParams, "gl_MaxPatchVertices_Position_PointSize",
1781 				   "Verifies gl_Position and gl_PointSize (if supported) "
1782 				   "are set to correct values in TE stage. Checks if up to "
1783 				   "gl_MaxPatchVertices input block values can be accessed "
1784 				   "from TE stage. Also verifies if TC/TE stage properties "
1785 				   "can be correctly queried for both regular and separate "
1786 				   "program objects.")
1787 	, m_bo_id(0)
1788 	, m_gl_max_patch_vertices_value(0)
1789 	, m_gl_max_tess_gen_level_value(0)
1790 	, m_utils_ptr(DE_NULL)
1791 	, m_vao_id(0)
1792 {
1793 	/* Left blank on purpose */
1794 }
1795 
1796 /** Deinitializes all ES objects created for the test. */
deinit()1797 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::deinit()
1798 {
1799 	/** Call base class' deinit() function */
1800 	TestCaseBase::deinit();
1801 
1802 	if (!m_is_tessellation_shader_supported)
1803 	{
1804 		return;
1805 	}
1806 
1807 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1808 
1809 	/* Revert TF buffer object bindings */
1810 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
1811 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
1812 
1813 	/* Reset GL_PATCH_VERTICES_EXT value to the default setting */
1814 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
1815 
1816 	/* Disable GL_RASTERIZER_DISCARD mode */
1817 	gl.disable(GL_RASTERIZER_DISCARD);
1818 
1819 	/* Unbind vertex array object */
1820 	gl.bindVertexArray(0);
1821 
1822 	/* Release all objects we might've created */
1823 	if (m_bo_id != 0)
1824 	{
1825 		gl.deleteBuffers(1, &m_bo_id);
1826 
1827 		m_bo_id = 0;
1828 	}
1829 	if (m_vao_id != 0)
1830 	{
1831 		gl.deleteVertexArrays(1, &m_vao_id);
1832 
1833 		m_vao_id = 0;
1834 	}
1835 
1836 	if (m_utils_ptr != DE_NULL)
1837 	{
1838 		delete m_utils_ptr;
1839 
1840 		m_utils_ptr = DE_NULL;
1841 	}
1842 
1843 	/* Release all test runs */
1844 	for (_runs::iterator it = m_runs.begin(); it != m_runs.end(); ++it)
1845 	{
1846 		deinitTestRun(*it);
1847 	}
1848 	m_runs.clear();
1849 }
1850 
1851 /** Deinitializes all ES objects generated for a test run */
deinitTestRun(_run & run)1852 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::deinitTestRun(_run& run)
1853 {
1854 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1855 
1856 	if (run.fs_id != 0)
1857 	{
1858 		gl.deleteShader(run.fs_id);
1859 
1860 		run.fs_id = 0;
1861 	}
1862 
1863 	if (run.fs_program_id != 0)
1864 	{
1865 		gl.deleteProgram(run.fs_program_id);
1866 
1867 		run.fs_program_id = 0;
1868 	}
1869 
1870 	if (run.pipeline_object_id != 0)
1871 	{
1872 		gl.deleteProgramPipelines(1, &run.pipeline_object_id);
1873 
1874 		run.pipeline_object_id = 0;
1875 	}
1876 
1877 	if (run.po_id != 0)
1878 	{
1879 		gl.deleteProgram(run.po_id);
1880 
1881 		run.po_id = 0;
1882 	}
1883 
1884 	if (run.tc_id != 0)
1885 	{
1886 		gl.deleteShader(run.tc_id);
1887 
1888 		run.tc_id = 0;
1889 	}
1890 
1891 	if (run.tc_program_id != 0)
1892 	{
1893 		gl.deleteProgram(run.tc_program_id);
1894 
1895 		run.tc_program_id = 0;
1896 	}
1897 
1898 	if (run.te_id != 0)
1899 	{
1900 		gl.deleteShader(run.te_id);
1901 
1902 		run.te_id = 0;
1903 	}
1904 
1905 	if (run.te_program_id != 0)
1906 	{
1907 		gl.deleteProgram(run.te_program_id);
1908 
1909 		run.te_program_id = 0;
1910 	}
1911 
1912 	if (run.vs_id != 0)
1913 	{
1914 		gl.deleteShader(run.vs_id);
1915 
1916 		run.vs_id = 0;
1917 	}
1918 
1919 	if (run.vs_program_id != 0)
1920 	{
1921 		gl.deleteProgram(run.vs_program_id);
1922 
1923 		run.vs_program_id = 0;
1924 	}
1925 }
1926 
1927 /** Retrieves a minimal fragment shader code to be used for forming program objects
1928  *  used by the test.
1929  *
1930  *  @return As per description.
1931  **/
getFragmentShaderCode(bool should_accept_pointsize_data)1932 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getFragmentShaderCode(
1933 	bool should_accept_pointsize_data)
1934 {
1935 	// Requires input to match previous stage's output
1936 	std::stringstream result_code;
1937 
1938 	result_code << "${VERSION}\n"
1939 				   "\n"
1940 				   "${SHADER_IO_BLOCKS_REQUIRE}\n"
1941 				   "\n"
1942 				   "precision highp float;\n"
1943 				   "precision highp int;\n"
1944 				   "out layout (location = 0) vec4 col;\n";
1945 
1946 	if (should_accept_pointsize_data)
1947 	{
1948 		result_code << "in      float te_pointsize;\n";
1949 	}
1950 
1951 	result_code << "in       vec4 te_position;\n"
1952 				   "in       vec2 te_value1;\n"
1953 				   "in flat ivec4 te_value2;\n"
1954 				   "\n"
1955 				   "void main()\n"
1956 				   "{\n"
1957 				   "  col = vec4(1.0, 1.0, 1.0, 1.0);\n"
1958 				   "}\n";
1959 
1960 	return result_code.str();
1961 }
1962 
1963 /** Retrieves tessellation control shader source code, given user-provided arguments.
1964  *
1965  *  @param should_pass_pointsize_data true if Tessellation Control shader should configure
1966  *                                    gl_PointSize value. This should be only set to true
1967  *                                    if the tested ES implementation reports support of
1968  *                                    GL_EXT_tessellation_point_size extension.
1969  *  @param inner_tess_levels          Two FP values defining inner tessellation level values.
1970  *                                    Must not be NULL.
1971  *  @param outer_tess_levels          Four FP values defining outer tessellation level values.
1972  *                                    Must not be NULL.
1973  *
1974  *  @return As per description.
1975  **/
getTessellationControlShaderCode(bool should_pass_pointsize_data,const glw::GLfloat * inner_tess_levels,const glw::GLfloat * outer_tess_levels)1976 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getTessellationControlShaderCode(
1977 	bool should_pass_pointsize_data, const glw::GLfloat* inner_tess_levels, const glw::GLfloat* outer_tess_levels)
1978 {
1979 	std::stringstream result_code;
1980 
1981 	result_code << "${VERSION}\n"
1982 				   "\n"
1983 				   "${TESSELLATION_SHADER_REQUIRE}\n";
1984 
1985 	if (should_pass_pointsize_data)
1986 	{
1987 		result_code << "${TESSELLATION_POINT_SIZE_REQUIRE}\n";
1988 	}
1989 
1990 	result_code << "\n"
1991 				   "layout(vertices = "
1992 				<< m_gl_max_patch_vertices_value << ") out;\n"
1993 													"\n";
1994 	if (should_pass_pointsize_data)
1995 	{
1996 		result_code << "${IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE}";
1997 		result_code << "${OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE}";
1998 	}
1999 	else
2000 	{
2001 		result_code << "${IN_PER_VERTEX_DECL_ARRAY}";
2002 		result_code << "${OUT_PER_VERTEX_DECL_ARRAY}";
2003 	}
2004 	result_code << "out OUT_TC\n"
2005 				   "{\n"
2006 				   "     vec2 value1;\n"
2007 				   "    ivec4 value2;\n"
2008 				   "} result[];\n"
2009 				   "\n"
2010 				   "void main()\n"
2011 				   "{\n";
2012 
2013 	if (should_pass_pointsize_data)
2014 	{
2015 		result_code << "    gl_out[gl_InvocationID].gl_PointSize = 1.0 / float(gl_InvocationID + 1);\n";
2016 	}
2017 
2018 	result_code << "    gl_out[gl_InvocationID].gl_Position =  vec4(      float(gl_InvocationID * 4 + 0),   "
2019 				   "float(gl_InvocationID * 4 + 1),\n"
2020 				   "                                                      float(gl_InvocationID * 4 + 2),   "
2021 				   "float(gl_InvocationID * 4 + 3));\n"
2022 				   "    result[gl_InvocationID].value1      =  vec2(1.0 / float(gl_InvocationID + 1), 1.0 / "
2023 				   "float(gl_InvocationID + 2) );\n"
2024 				   "    result[gl_InvocationID].value2      = ivec4(            gl_InvocationID + 1,              "
2025 				   "gl_InvocationID + 2,\n"
2026 				   "                                                            gl_InvocationID + 3,              "
2027 				   "gl_InvocationID + 4);\n"
2028 				   "\n"
2029 				   "    gl_TessLevelInner[0] = float("
2030 				<< inner_tess_levels[0] << ");\n"
2031 										   "    gl_TessLevelInner[1] = float("
2032 				<< inner_tess_levels[1] << ");\n"
2033 										   "    gl_TessLevelOuter[0] = float("
2034 				<< outer_tess_levels[0] << ");\n"
2035 										   "    gl_TessLevelOuter[1] = float("
2036 				<< outer_tess_levels[1] << ");\n"
2037 										   "    gl_TessLevelOuter[2] = float("
2038 				<< outer_tess_levels[2] << ");\n"
2039 										   "    gl_TessLevelOuter[3] = float("
2040 				<< outer_tess_levels[3] << ");\n"
2041 										   "}\n";
2042 
2043 	return result_code.str();
2044 }
2045 
2046 /** Retrieves tessellation evaluation shader source code, given user-provided arguments.
2047  *
2048  *  @param should_pass_pointsize_data true if Tessellation Evaluation shader should set
2049  *                                    gl_PointSize to the value set by Tessellation Control
2050  *                                    stage. This should be only set to true if the tested
2051  *                                    ES implementation reports support of GL_EXT_tessellation_point_size
2052  *                                    extension, and TC stage assigns a value to gl_PointSize.
2053  *  @param primitive_mode             Primitive mode to use for the stage.
2054  *  @param vertex_ordering            Vertex ordering to use for the stage.
2055  *  @param vertex_spacing             Vertex spacing to use for the stage.
2056  *  @param is_point_mode_enabled      true to make the TE stage work in point mode, false otherwise.
2057  *
2058  *  @return As per description.
2059  **/
getTessellationEvaluationShaderCode(bool should_pass_pointsize_data,_tessellation_primitive_mode primitive_mode,_tessellation_shader_vertex_ordering vertex_ordering,_tessellation_shader_vertex_spacing vertex_spacing,bool is_point_mode_enabled)2060 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getTessellationEvaluationShaderCode(
2061 	bool should_pass_pointsize_data, _tessellation_primitive_mode primitive_mode,
2062 	_tessellation_shader_vertex_ordering vertex_ordering, _tessellation_shader_vertex_spacing vertex_spacing,
2063 	bool is_point_mode_enabled)
2064 {
2065 	std::stringstream result_sstream;
2066 	std::string		  result;
2067 
2068 	result_sstream << "${VERSION}\n"
2069 					  "\n"
2070 					  "${TESSELLATION_SHADER_REQUIRE}\n";
2071 
2072 	if (should_pass_pointsize_data)
2073 	{
2074 		result_sstream << "${TESSELLATION_POINT_SIZE_REQUIRE}\n";
2075 	}
2076 
2077 	result_sstream << "\n"
2078 					  "layout (TESSELLATOR_PRIMITIVE_MODE VERTEX_SPACING_MODE VERTEX_ORDERING POINT_MODE) in;\n"
2079 					  "\n";
2080 	if (should_pass_pointsize_data)
2081 	{
2082 		result_sstream << "${IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE}";
2083 		result_sstream << "${OUT_PER_VERTEX_DECL_POINT_SIZE}";
2084 	}
2085 	else
2086 	{
2087 		result_sstream << "${IN_PER_VERTEX_DECL_ARRAY}";
2088 		result_sstream << "${OUT_PER_VERTEX_DECL}";
2089 	}
2090 	result_sstream << "in OUT_TC\n"
2091 					  "{\n"
2092 					  "     vec2 value1;\n"
2093 					  "    ivec4 value2;\n"
2094 					  "} tc_data[];\n"
2095 					  "\n";
2096 
2097 	if (should_pass_pointsize_data)
2098 	{
2099 		result_sstream << "out      float te_pointsize;\n";
2100 	}
2101 
2102 	result_sstream << "out       vec4 te_position;\n"
2103 					  "out       vec2 te_value1;\n"
2104 					  "out flat ivec4 te_value2;\n"
2105 					  "\n"
2106 					  "void main()\n"
2107 					  "{\n";
2108 
2109 	if (should_pass_pointsize_data)
2110 	{
2111 		result_sstream << "    te_pointsize = 0.0;\n";
2112 	}
2113 
2114 	result_sstream << "    te_position  = vec4 (0.0);\n"
2115 					  "    te_value1    = vec2 (0.0);\n"
2116 					  "    te_value2    = ivec4(0);\n"
2117 					  "\n"
2118 					  "    for (int n = 0; n < "
2119 				   << m_gl_max_patch_vertices_value << "; ++n)\n"
2120 													   "    {\n";
2121 
2122 	if (should_pass_pointsize_data)
2123 	{
2124 		result_sstream << "        te_pointsize += gl_in[n].gl_PointSize;\n";
2125 	}
2126 
2127 	result_sstream << "        te_position += gl_in  [n].gl_Position;\n"
2128 					  "        te_value1   += tc_data[n].value1;\n"
2129 					  "        te_value2   += tc_data[n].value2;\n"
2130 					  "    }\n"
2131 					  "}\n";
2132 
2133 	result = result_sstream.str();
2134 
2135 	/* Replace the tokens */
2136 	const char* point_mode_token		   = "POINT_MODE";
2137 	std::size_t point_mode_token_index	 = std::string::npos;
2138 	std::string primitive_mode_string	  = TessellationShaderUtils::getESTokenForPrimitiveMode(primitive_mode);
2139 	const char* primitive_mode_token	   = "TESSELLATOR_PRIMITIVE_MODE";
2140 	std::size_t primitive_mode_token_index = std::string::npos;
2141 	std::string vertex_ordering_string;
2142 	const char* vertex_ordering_token		= "VERTEX_ORDERING";
2143 	std::size_t vertex_ordering_token_index = std::string::npos;
2144 	std::string vertex_spacing_mode_string;
2145 	const char* vertex_spacing_token	   = "VERTEX_SPACING_MODE";
2146 	std::size_t vertex_spacing_token_index = std::string::npos;
2147 
2148 	/* Prepare the vertex ordering token. We need to do this manually, because the default vertex spacing
2149 	 * mode translates to empty string and the shader would fail to compile if we hadn't taken care of the
2150 	 * comma
2151 	 */
2152 	if (vertex_ordering == TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT)
2153 	{
2154 		vertex_ordering_string = TessellationShaderUtils::getESTokenForVertexOrderingMode(vertex_ordering);
2155 	}
2156 	else
2157 	{
2158 		std::stringstream helper_sstream;
2159 
2160 		helper_sstream << ", " << TessellationShaderUtils::getESTokenForVertexOrderingMode(vertex_ordering);
2161 
2162 		vertex_ordering_string = helper_sstream.str();
2163 	}
2164 
2165 	/* Do the same for vertex spacing token */
2166 	if (vertex_spacing == TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT)
2167 	{
2168 		vertex_spacing_mode_string = TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing);
2169 	}
2170 	else
2171 	{
2172 		std::stringstream helper_sstream;
2173 
2174 		helper_sstream << ", " << TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing);
2175 
2176 		vertex_spacing_mode_string = helper_sstream.str();
2177 	}
2178 
2179 	/* Primitive mode */
2180 	while ((primitive_mode_token_index = result.find(primitive_mode_token)) != std::string::npos)
2181 	{
2182 		result = result.replace(primitive_mode_token_index, strlen(primitive_mode_token), primitive_mode_string);
2183 
2184 		primitive_mode_token_index = result.find(primitive_mode_token);
2185 	}
2186 
2187 	/* Vertex ordering */
2188 	while ((vertex_ordering_token_index = result.find(vertex_ordering_token)) != std::string::npos)
2189 	{
2190 		result = result.replace(vertex_ordering_token_index, strlen(vertex_ordering_token), vertex_ordering_string);
2191 
2192 		vertex_ordering_token_index = result.find(vertex_ordering_token);
2193 	}
2194 
2195 	/* Vertex spacing */
2196 	while ((vertex_spacing_token_index = result.find(vertex_spacing_token)) != std::string::npos)
2197 	{
2198 		result = result.replace(vertex_spacing_token_index, strlen(vertex_spacing_token), vertex_spacing_mode_string);
2199 
2200 		vertex_spacing_token_index = result.find(vertex_spacing_token);
2201 	}
2202 
2203 	/* Point mode */
2204 	while ((point_mode_token_index = result.find(point_mode_token)) != std::string::npos)
2205 	{
2206 		result = result.replace(point_mode_token_index, strlen(point_mode_token),
2207 								(is_point_mode_enabled) ? ", point_mode" : "");
2208 
2209 		point_mode_token_index = result.find(point_mode_token);
2210 	}
2211 
2212 	return result;
2213 }
2214 
2215 /** Retrieves a minimal vertex shader code to be used for forming program objects
2216  *  used by the test.
2217  *
2218  *  @return As per description.
2219  **/
getVertexShaderCode(bool should_pass_pointsize_data)2220 std::string TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::getVertexShaderCode(
2221 	bool should_pass_pointsize_data)
2222 {
2223 	std::stringstream result_sstream;
2224 	result_sstream << "${VERSION}\n\n";
2225 	if (should_pass_pointsize_data)
2226 	{
2227 		result_sstream << "${OUT_PER_VERTEX_DECL_POINT_SIZE}";
2228 	}
2229 	else
2230 	{
2231 		result_sstream << "${OUT_PER_VERTEX_DECL}";
2232 	}
2233 	result_sstream << "\n"
2234 					  "void main()\n"
2235 					  "{\n"
2236 					  "}\n";
2237 
2238 	return result_sstream.str();
2239 }
2240 
2241 /** Initializes all ES objects that will be used for the test. */
initTest()2242 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::initTest()
2243 {
2244 	/* The test requires EXT_tessellation_shader */
2245 	if (!m_is_tessellation_shader_supported)
2246 	{
2247 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
2248 	}
2249 
2250 	/* Retrieve ES entry-points */
2251 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2252 
2253 	/* Initialize vertex array object */
2254 	gl.genVertexArrays(1, &m_vao_id);
2255 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
2256 
2257 	gl.bindVertexArray(m_vao_id);
2258 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
2259 
2260 	/* Generate a buffer object we will use to hold XFB data */
2261 	gl.genBuffers(1, &m_bo_id);
2262 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
2263 
2264 	/* Configure XFB buffer object bindings */
2265 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
2266 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
2267 
2268 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() / glBindBufferBase() call(s) failed");
2269 
2270 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
2271 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &m_gl_max_tess_gen_level_value);
2272 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
2273 
2274 	/* Retrieve GL_MAX_PATCH_VERTICES_EXT value */
2275 	gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices_value);
2276 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_PATCH_VERTICES_EXT pname");
2277 
2278 	/* We only need 1 vertex per input patch */
2279 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
2280 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname");
2281 
2282 	/* Disable rasterization */
2283 	gl.enable(GL_RASTERIZER_DISCARD);
2284 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed");
2285 
2286 	/* Spawn utilities class instance */
2287 	m_utils_ptr = new TessellationShaderUtils(gl, this);
2288 
2289 	/* Initialize all test iterations */
2290 	bool							   point_mode_enabled_flags[] = { false, true };
2291 	const _tessellation_primitive_mode primitive_modes[]		  = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES,
2292 															 TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
2293 															 TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES };
2294 	const _tessellation_shader_vertex_ordering vertex_ordering_modes[] = {
2295 		TESSELLATION_SHADER_VERTEX_ORDERING_CCW, TESSELLATION_SHADER_VERTEX_ORDERING_CW,
2296 		TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT
2297 	};
2298 	const _tessellation_shader_vertex_spacing vertex_spacing_modes[] = {
2299 		TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
2300 		TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD, TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT
2301 	};
2302 	const unsigned int n_point_mode_enabled_flags =
2303 		sizeof(point_mode_enabled_flags) / sizeof(point_mode_enabled_flags[0]);
2304 	const unsigned int n_primitive_modes	   = sizeof(primitive_modes) / sizeof(primitive_modes[0]);
2305 	const unsigned int n_vertex_ordering_modes = sizeof(vertex_ordering_modes) / sizeof(vertex_ordering_modes[0]);
2306 	const unsigned int n_vertex_spacing_modes  = sizeof(vertex_spacing_modes) / sizeof(vertex_spacing_modes[0]);
2307 
2308 	bool deleteResources = false;
2309 
2310 	for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; n_primitive_mode++)
2311 	{
2312 		_tessellation_primitive_mode primitive_mode  = primitive_modes[n_primitive_mode];
2313 		_tessellation_levels_set tessellation_levels = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode(
2314 			primitive_mode, m_gl_max_tess_gen_level_value, TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE);
2315 
2316 		for (_tessellation_levels_set_const_iterator tessellation_levels_iterator = tessellation_levels.begin();
2317 			 tessellation_levels_iterator != tessellation_levels.end(); tessellation_levels_iterator++)
2318 		{
2319 			const _tessellation_levels& tess_levels = *tessellation_levels_iterator;
2320 
2321 			for (unsigned int n_vertex_ordering_mode = 0; n_vertex_ordering_mode < n_vertex_ordering_modes;
2322 				 ++n_vertex_ordering_mode)
2323 			{
2324 				_tessellation_shader_vertex_ordering vertex_ordering = vertex_ordering_modes[n_vertex_ordering_mode];
2325 
2326 				for (unsigned int n_vertex_spacing_mode = 0; n_vertex_spacing_mode < n_vertex_spacing_modes;
2327 					 ++n_vertex_spacing_mode)
2328 				{
2329 					_tessellation_shader_vertex_spacing vertex_spacing = vertex_spacing_modes[n_vertex_spacing_mode];
2330 
2331 					for (unsigned int n_point_mode_enabled_flag = 0;
2332 						 n_point_mode_enabled_flag < n_point_mode_enabled_flags; ++n_point_mode_enabled_flag)
2333 					{
2334 						bool is_point_mode_enabled = point_mode_enabled_flags[n_point_mode_enabled_flag];
2335 
2336 						/* Only create gl_PointSize-enabled runs if the implementation supports
2337 						 * GL_EXT_tessellation_point_size extension
2338 						 */
2339 						if (!m_is_tessellation_shader_point_size_supported && is_point_mode_enabled)
2340 						{
2341 							continue;
2342 						}
2343 
2344 						/* Execute the test run */
2345 						_run run;
2346 
2347 						memcpy(run.inner, tess_levels.inner, sizeof(run.inner));
2348 						memcpy(run.outer, tess_levels.outer, sizeof(run.outer));
2349 
2350 						run.point_mode		= is_point_mode_enabled;
2351 						run.primitive_mode  = primitive_mode;
2352 						run.vertex_ordering = vertex_ordering;
2353 						run.vertex_spacing  = vertex_spacing;
2354 
2355 						initTestRun(run);
2356 
2357 						if (deleteResources)
2358 						{
2359 							deinitTestRun(run);
2360 						}
2361 
2362 						deleteResources = true;
2363 
2364 						/* Store it for further processing */
2365 						m_runs.push_back(run);
2366 					} /* for (all 'point mode' enabled flags) */
2367 				}	 /* for (all vertex spacing modes) */
2368 			}		  /* for (all vertex ordering modes) */
2369 		}			  /* for (all tessellation levels for active primitive mode) */
2370 	}				  /* for (all primitive modes) */
2371 }
2372 
2373 /** Initializes all ES objects used by the test, captures the tessellation coordinates
2374  *  and stores them in the descriptor.
2375  *  Also performs a handful of other minor checks, as described by test specification.
2376  *
2377  *  @param run Run descriptor to operate on.
2378  **/
initTestRun(_run & run)2379 void TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::initTestRun(_run& run)
2380 {
2381 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2382 
2383 	/* Build shader objects */
2384 	run.fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2385 	run.tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
2386 	run.te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
2387 	run.vs_id = gl.createShader(GL_VERTEX_SHADER);
2388 
2389 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
2390 
2391 	/* Generate fragment shader (or stand-alone program) */
2392 	std::string fs_code_string  = getFragmentShaderCode(run.point_mode);
2393 	const char* fs_code_raw_ptr = fs_code_string.c_str();
2394 
2395 	shaderSourceSpecialized(run.fs_id, 1 /* count */, &fs_code_raw_ptr);
2396 
2397 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for fragment shader");
2398 
2399 	/* Generate tessellation control shader (or stand-alone program) */
2400 	std::string tc_code_string  = getTessellationControlShaderCode(run.point_mode, run.inner, run.outer);
2401 	const char* tc_code_raw_ptr = tc_code_string.c_str();
2402 
2403 	shaderSourceSpecialized(run.tc_id, 1 /* count */, &tc_code_raw_ptr);
2404 
2405 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation control shader");
2406 
2407 	/* Generate tessellation evaluation shader (or stand-alone program) */
2408 	std::string te_code_string = getTessellationEvaluationShaderCode(
2409 		run.point_mode, run.primitive_mode, run.vertex_ordering, run.vertex_spacing, run.point_mode);
2410 	const char* te_code_raw_ptr = te_code_string.c_str();
2411 
2412 	shaderSourceSpecialized(run.te_id, 1 /* count */, &te_code_raw_ptr);
2413 
2414 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for tessellation evaluation shader");
2415 
2416 	/* Generate vertex shader (or stand-alone program) */
2417 	std::string vs_code_string  = getVertexShaderCode(run.point_mode);
2418 	const char* vs_code_raw_ptr = vs_code_string.c_str();
2419 
2420 	shaderSourceSpecialized(run.vs_id, 1 /* count */, &vs_code_raw_ptr);
2421 
2422 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for vertex shader");
2423 
2424 	/* Compile all shaders first. Also make sure the shader objects we have
2425 	 * attached are correctly reported.
2426 	 */
2427 	const glw::GLuint  shaders[] = { run.fs_id, run.tc_id, run.te_id, run.vs_id };
2428 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
2429 
2430 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
2431 	{
2432 		glw::GLint compile_status = GL_FALSE;
2433 		glw::GLint shader		  = shaders[n_shader];
2434 
2435 		gl.compileShader(shader);
2436 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
2437 
2438 		gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
2439 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
2440 
2441 		if (compile_status != GL_TRUE)
2442 		{
2443 			m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n"
2444 							   << getCompilationInfoLog(shader) << "\nShader:\n"
2445 							   << getShaderSource(shader) << tcu::TestLog::EndMessage;
2446 			TCU_FAIL("Shader compilation failed");
2447 		}
2448 	}
2449 
2450 	/* Run two iterations:
2451 	 *
2452 	 * 1) First, using a program object;
2453 	 * 2) The other one using pipeline objects;
2454 	 */
2455 	for (unsigned int n_iteration = 0; n_iteration < 2 /* program / pipeline objects */; ++n_iteration)
2456 	{
2457 		bool should_use_program_object = (n_iteration == 0);
2458 
2459 		/* Generate container object(s) first */
2460 		if (!should_use_program_object)
2461 		{
2462 			gl.genProgramPipelines(1, &run.pipeline_object_id);
2463 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() failed");
2464 
2465 			/* As per test spec, make sure no tessellation stages are defined for
2466 			 * a pipeline object by default */
2467 			glw::GLint program_tc_id = 1;
2468 			glw::GLint program_te_id = 1;
2469 
2470 			gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER, &program_tc_id);
2471 			gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER, &program_te_id);
2472 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() failed");
2473 
2474 			if (program_tc_id != 0 || program_te_id != 0)
2475 			{
2476 				GLU_EXPECT_NO_ERROR(gl.getError(), "A pipeline object returned a non-zero ID of "
2477 												   "a separate program object when asked for TC/TE"
2478 												   " program ID.");
2479 			}
2480 		}
2481 		else
2482 		{
2483 			run.po_id = gl.createProgram();
2484 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
2485 		}
2486 
2487 		if (!should_use_program_object)
2488 		{
2489 			run.fs_program_id = gl.createProgram();
2490 			run.tc_program_id = gl.createProgram();
2491 			run.te_program_id = gl.createProgram();
2492 			run.vs_program_id = gl.createProgram();
2493 
2494 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed");
2495 		}
2496 
2497 		/* Link program object(s) (and configure the pipeline object, if necessary) */
2498 		const glw::GLuint programs_for_pipeline_iteration[] = { run.fs_program_id, run.tc_program_id, run.te_program_id,
2499 																run.vs_program_id };
2500 		const glw::GLuint  programs_for_program_iteration[] = { run.po_id };
2501 		const unsigned int n_programs_for_pipeline_iteration =
2502 			sizeof(programs_for_pipeline_iteration) / sizeof(programs_for_pipeline_iteration[0]);
2503 		const unsigned int n_programs_for_program_iteration =
2504 			sizeof(programs_for_program_iteration) / sizeof(programs_for_program_iteration[0]);
2505 
2506 		unsigned int	   n_programs				 = 0;
2507 		const glw::GLuint* programs					 = DE_NULL;
2508 		int				   xfb_pointsize_data_offset = -1;
2509 		int				   xfb_position_data_offset  = -1;
2510 		int				   xfb_value1_data_offset	= -1;
2511 		int				   xfb_value2_data_offset	= -1;
2512 		int				   xfb_varyings_size		 = 0;
2513 
2514 		if (should_use_program_object)
2515 		{
2516 			n_programs = n_programs_for_program_iteration;
2517 			programs   = programs_for_program_iteration;
2518 		}
2519 		else
2520 		{
2521 			n_programs = n_programs_for_pipeline_iteration;
2522 			programs   = programs_for_pipeline_iteration;
2523 		}
2524 
2525 		/* Attach and verify shader objects */
2526 		for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
2527 		{
2528 			glw::GLuint parent_po_id = 0;
2529 			glw::GLuint shader		 = shaders[n_shader];
2530 
2531 			if (should_use_program_object)
2532 			{
2533 				gl.attachShader(run.po_id, shader);
2534 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
2535 
2536 				parent_po_id = run.po_id;
2537 			}
2538 			else
2539 			{
2540 				if (shader == run.fs_id)
2541 				{
2542 					gl.attachShader(run.fs_program_id, run.fs_id);
2543 
2544 					parent_po_id = run.fs_program_id;
2545 				}
2546 				else if (shader == run.tc_id)
2547 				{
2548 					gl.attachShader(run.tc_program_id, run.tc_id);
2549 
2550 					parent_po_id = run.tc_program_id;
2551 				}
2552 				else if (shader == run.te_id)
2553 				{
2554 					gl.attachShader(run.te_program_id, run.te_id);
2555 
2556 					parent_po_id = run.te_program_id;
2557 				}
2558 				else
2559 				{
2560 					DE_ASSERT(shader == run.vs_id);
2561 
2562 					gl.attachShader(run.vs_program_id, run.vs_id);
2563 
2564 					parent_po_id = run.vs_program_id;
2565 				}
2566 
2567 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
2568 			}
2569 
2570 			/* Make sure the shader object we've attached is reported as a part
2571 			 * of the program object.
2572 			 */
2573 			unsigned int attached_shaders[n_shaders] = { 0 };
2574 			bool		 has_found_attached_shader   = false;
2575 			glw::GLsizei n_attached_shaders			 = 0;
2576 
2577 			memset(attached_shaders, 0, sizeof(attached_shaders));
2578 
2579 			gl.getAttachedShaders(parent_po_id, n_shaders, &n_attached_shaders, attached_shaders);
2580 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttachedShaders() failed");
2581 
2582 			for (glw::GLsizei n_attached_shader = 0; n_attached_shader < n_attached_shaders; n_attached_shader++)
2583 			{
2584 				if (attached_shaders[n_attached_shader] == shader)
2585 				{
2586 					has_found_attached_shader = true;
2587 
2588 					break;
2589 				}
2590 			} /* for (all attached shader object IDs) */
2591 
2592 			if (!has_found_attached_shader)
2593 			{
2594 				TCU_FAIL("A shader object that was successfully attached to a program "
2595 						 "object was not reported as one by subsequent glGetAttachedShaders() "
2596 						 "call");
2597 			}
2598 		}
2599 
2600 		/* Set up XFB */
2601 		const char* xfb_varyings_w_pointsize[]  = { "te_position", "te_value1", "te_value2", "te_pointsize" };
2602 		const char* xfb_varyings_wo_pointsize[] = {
2603 			"te_position", "te_value1", "te_value2",
2604 		};
2605 		const char** xfb_varyings   = DE_NULL;
2606 		unsigned int n_xfb_varyings = 0;
2607 
2608 		if (run.point_mode)
2609 		{
2610 			xfb_varyings   = xfb_varyings_w_pointsize;
2611 			n_xfb_varyings = sizeof(xfb_varyings_w_pointsize) / sizeof(xfb_varyings_w_pointsize[0]);
2612 
2613 			xfb_position_data_offset = 0;
2614 			xfb_value1_data_offset =
2615 				static_cast<unsigned int>(xfb_position_data_offset + sizeof(float) * 4); /* size of te_position */
2616 			xfb_value2_data_offset =
2617 				static_cast<unsigned int>(xfb_value1_data_offset + sizeof(float) * 2); /* size of te_value1 */
2618 			xfb_pointsize_data_offset =
2619 				static_cast<unsigned int>(xfb_value2_data_offset + sizeof(int) * 4); /* size of te_value2 */
2620 
2621 			xfb_varyings_size = sizeof(float) * 4 + /* size of te_position */
2622 								sizeof(float) * 2 + /* size of te_value1 */
2623 								sizeof(int) * 4 +   /* size of te_value2 */
2624 								sizeof(int);		/* size of te_pointsize */
2625 		}
2626 		else
2627 		{
2628 			xfb_varyings   = xfb_varyings_wo_pointsize;
2629 			n_xfb_varyings = sizeof(xfb_varyings_wo_pointsize) / sizeof(xfb_varyings_wo_pointsize[0]);
2630 
2631 			xfb_position_data_offset = 0;
2632 			xfb_value1_data_offset =
2633 				static_cast<unsigned int>(xfb_position_data_offset + sizeof(float) * 4); /* size of te_position */
2634 			xfb_value2_data_offset =
2635 				static_cast<unsigned int>(xfb_value1_data_offset + sizeof(float) * 2); /* size of te_value1 */
2636 
2637 			xfb_varyings_size = sizeof(float) * 4 + /* size of te_position */
2638 								sizeof(float) * 2 + /* size of te_value1 */
2639 								sizeof(int) * 4;
2640 		}
2641 
2642 		if (!should_use_program_object)
2643 		{
2644 			gl.transformFeedbackVaryings(run.te_program_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
2645 
2646 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed");
2647 		}
2648 		else
2649 		{
2650 			gl.transformFeedbackVaryings(run.po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
2651 
2652 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed");
2653 		}
2654 
2655 		/* Mark all program objects as separable for pipeline run */
2656 		if (!should_use_program_object)
2657 		{
2658 			for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
2659 			{
2660 				glw::GLuint program = programs[n_program];
2661 
2662 				gl.programParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
2663 				GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() failed.");
2664 			}
2665 		}
2666 
2667 		/* Link the program object(s) */
2668 		for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
2669 		{
2670 			glw::GLint  link_status = GL_FALSE;
2671 			glw::GLuint program		= programs[n_program];
2672 
2673 			gl.linkProgram(program);
2674 			GLU_EXPECT_NO_ERROR(gl.getError(), "Program linking failed");
2675 
2676 			gl.getProgramiv(program, GL_LINK_STATUS, &link_status);
2677 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
2678 
2679 			if (link_status != GL_TRUE)
2680 			{
2681 				m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n"
2682 								   << getLinkingInfoLog(program) << tcu::TestLog::EndMessage;
2683 				TCU_FAIL("Program linking failed");
2684 			}
2685 
2686 			/* Make sure glGetProgramiv() reports correct tessellation properties for
2687 			 * the program object we've just linked successfully */
2688 			if (program == run.po_id || program == run.tc_program_id || program == run.te_program_id)
2689 			{
2690 				glw::GLenum expected_tess_gen_mode_value		 = GL_NONE;
2691 				glw::GLenum expected_tess_gen_spacing_value		 = GL_NONE;
2692 				glw::GLenum expected_tess_gen_vertex_order_value = GL_NONE;
2693 				glw::GLint  tess_control_output_vertices_value   = GL_NONE;
2694 				glw::GLint  tess_gen_mode_value					 = GL_NONE;
2695 				glw::GLint  tess_gen_point_mode_value			 = GL_NONE;
2696 				glw::GLint  tess_gen_spacing_value				 = GL_NONE;
2697 				glw::GLint  tess_gen_vertex_order_value			 = GL_NONE;
2698 
2699 				switch (run.primitive_mode)
2700 				{
2701 				case TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES:
2702 					expected_tess_gen_mode_value = m_glExtTokens.ISOLINES;
2703 					break;
2704 				case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS:
2705 					expected_tess_gen_mode_value = m_glExtTokens.QUADS;
2706 					break;
2707 				case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES:
2708 					expected_tess_gen_mode_value = GL_TRIANGLES;
2709 					break;
2710 
2711 				default:
2712 				{
2713 					/* Unrecognized primitive mode? */
2714 					DE_ASSERT(false);
2715 				}
2716 				} /* switch (run.primitive_mode) */
2717 
2718 				switch (run.vertex_spacing)
2719 				{
2720 				case TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT:
2721 				case TESSELLATION_SHADER_VERTEX_SPACING_EQUAL:
2722 					expected_tess_gen_spacing_value = GL_EQUAL;
2723 					break;
2724 				case TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN:
2725 					expected_tess_gen_spacing_value = m_glExtTokens.FRACTIONAL_EVEN;
2726 					break;
2727 				case TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD:
2728 					expected_tess_gen_spacing_value = m_glExtTokens.FRACTIONAL_ODD;
2729 					break;
2730 
2731 				default:
2732 				{
2733 					/* Unrecognized vertex spacing mode? */
2734 					DE_ASSERT(false);
2735 				}
2736 				} /* switch (run.vertex_spacing) */
2737 
2738 				switch (run.vertex_ordering)
2739 				{
2740 				case TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT:
2741 				case TESSELLATION_SHADER_VERTEX_ORDERING_CCW:
2742 					expected_tess_gen_vertex_order_value = GL_CCW;
2743 					break;
2744 				case TESSELLATION_SHADER_VERTEX_ORDERING_CW:
2745 					expected_tess_gen_vertex_order_value = GL_CW;
2746 					break;
2747 
2748 				default:
2749 				{
2750 					/* Unrecognized vertex ordering mode? */
2751 					DE_ASSERT(false);
2752 				}
2753 				} /* switch (run.vertex_ordering) */
2754 
2755 				if (program == run.po_id || program == run.tc_program_id)
2756 				{
2757 					gl.getProgramiv(program, m_glExtTokens.TESS_CONTROL_OUTPUT_VERTICES,
2758 									&tess_control_output_vertices_value);
2759 					GLU_EXPECT_NO_ERROR(gl.getError(),
2760 										"glGetProgramiv() failed for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT pname");
2761 
2762 					if (tess_control_output_vertices_value != m_gl_max_patch_vertices_value)
2763 					{
2764 						TCU_FAIL(
2765 							"Invalid value returned by glGetProgramiv() for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT query");
2766 					}
2767 				}
2768 
2769 				if (program == run.po_id || program == run.te_program_id)
2770 				{
2771 					gl.getProgramiv(program, m_glExtTokens.TESS_GEN_MODE, &tess_gen_mode_value);
2772 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_MODE_EXT pname");
2773 
2774 					if ((glw::GLuint)tess_gen_mode_value != expected_tess_gen_mode_value)
2775 					{
2776 						TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_MODE_EXT query");
2777 					}
2778 				}
2779 
2780 				if (program == run.po_id || program == run.te_program_id)
2781 				{
2782 					gl.getProgramiv(program, m_glExtTokens.TESS_GEN_SPACING, &tess_gen_spacing_value);
2783 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_SPACING_EXT pname");
2784 
2785 					if ((glw::GLuint)tess_gen_spacing_value != expected_tess_gen_spacing_value)
2786 					{
2787 						TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_SPACING_EXT query");
2788 					}
2789 				}
2790 
2791 				if (program == run.po_id || program == run.te_program_id)
2792 				{
2793 					gl.getProgramiv(program, m_glExtTokens.TESS_GEN_VERTEX_ORDER, &tess_gen_vertex_order_value);
2794 					GLU_EXPECT_NO_ERROR(gl.getError(),
2795 										"glGetProgramiv() failed for GL_TESS_GEN_VERTEX_ORDER_EXT pname");
2796 
2797 					if ((glw::GLuint)tess_gen_vertex_order_value != expected_tess_gen_vertex_order_value)
2798 					{
2799 						TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_VERTEX_ORDER_EXT query");
2800 					}
2801 				}
2802 
2803 				if (program == run.po_id || program == run.te_program_id)
2804 				{
2805 					gl.getProgramiv(program, m_glExtTokens.TESS_GEN_POINT_MODE, &tess_gen_point_mode_value);
2806 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_TESS_GEN_POINT_MODE_EXT pname");
2807 
2808 					if (tess_gen_point_mode_value != ((run.point_mode) ? GL_TRUE : GL_FALSE))
2809 					{
2810 						TCU_FAIL("Invalid value returned by glGetProgramiv() for GL_TESS_GEN_POINT_MODE_EXT query");
2811 					}
2812 				}
2813 			} /* if (program == run.po_id || program == run.tc_program_id || program == run.te_program_id) */
2814 		}	 /* for (all considered program objects) */
2815 
2816 		if (!should_use_program_object)
2817 		{
2818 			/* Attach all stages to the pipeline object */
2819 			gl.useProgramStages(run.pipeline_object_id, GL_FRAGMENT_SHADER_BIT, run.fs_program_id);
2820 			gl.useProgramStages(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER_BIT, run.tc_program_id);
2821 			gl.useProgramStages(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER_BIT, run.te_program_id);
2822 			gl.useProgramStages(run.pipeline_object_id, GL_VERTEX_SHADER_BIT, run.vs_program_id);
2823 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed");
2824 
2825 			/* Make sure the pipeline object validates correctly */
2826 			glw::GLint validate_status = GL_FALSE;
2827 
2828 			gl.validateProgramPipeline(run.pipeline_object_id);
2829 			GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed");
2830 
2831 			gl.getProgramPipelineiv(run.pipeline_object_id, GL_VALIDATE_STATUS, &validate_status);
2832 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed");
2833 
2834 			if (validate_status != GL_TRUE)
2835 			{
2836 				m_testCtx.getLog() << tcu::TestLog::Message << "Info log:\n"
2837 								   << getPipelineInfoLog(run.pipeline_object_id) << "\n\nVertex Shader:\n"
2838 								   << vs_code_raw_ptr << "\n\nTessellation Control Shader:\n"
2839 								   << tc_code_raw_ptr << "\n\nTessellation Evaluation Shader:\n"
2840 								   << te_code_raw_ptr << "\n\nFragment Shader:\n"
2841 								   << fs_code_raw_ptr << tcu::TestLog::EndMessage;
2842 				TCU_FAIL("Pipeline object was found to be invalid");
2843 			}
2844 		}
2845 
2846 		/* Determine how many vertices are going to be generated by the tessellator
2847 		 * for particular tessellation configuration.
2848 		 */
2849 		unsigned int n_vertices_generated = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
2850 			run.primitive_mode, run.inner, run.outer, run.vertex_spacing, run.point_mode);
2851 
2852 		/* Allocate enough space to hold the result XFB data */
2853 		const unsigned int bo_size = xfb_varyings_size * n_vertices_generated;
2854 
2855 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
2856 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
2857 
2858 		/* Use the pipeline or program object and render the data */
2859 		glw::GLenum tf_mode = TessellationShaderUtils::getTFModeForPrimitiveMode(run.primitive_mode, run.point_mode);
2860 
2861 		if (should_use_program_object)
2862 		{
2863 			gl.bindProgramPipeline(0);
2864 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed");
2865 
2866 			gl.useProgram(run.po_id);
2867 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
2868 		}
2869 		else
2870 		{
2871 			gl.bindProgramPipeline(run.pipeline_object_id);
2872 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed");
2873 
2874 			gl.useProgram(0);
2875 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
2876 		}
2877 
2878 		gl.beginTransformFeedback(tf_mode);
2879 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
2880 		{
2881 			gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, 1 /* count */);
2882 
2883 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
2884 		}
2885 		gl.endTransformFeedback();
2886 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
2887 
2888 		/* Map the buffer object contents into process space */
2889 		const char* xfb_data = (const char*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
2890 															  bo_size, GL_MAP_READ_BIT);
2891 
2892 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
2893 
2894 		/* Iterate through all vertices and extract all captured data. To reduce amount
2895 		 * of time necessary to verify the generated data, only store *unique* values.
2896 		 */
2897 		for (unsigned int n_vertex = 0; n_vertex < n_vertices_generated; ++n_vertex)
2898 		{
2899 			if (xfb_pointsize_data_offset != -1)
2900 			{
2901 				const float* data_ptr =
2902 					(const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_pointsize_data_offset);
2903 
2904 				if (std::find(run.result_pointsize_data.begin(), run.result_pointsize_data.end(), *data_ptr) ==
2905 					run.result_pointsize_data.end())
2906 				{
2907 					run.result_pointsize_data.push_back(*data_ptr);
2908 				}
2909 			}
2910 
2911 			if (xfb_position_data_offset != -1)
2912 			{
2913 				const float* data_ptr =
2914 					(const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_position_data_offset);
2915 				_vec4 new_item = _vec4(data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]);
2916 
2917 				if (std::find(run.result_position_data.begin(), run.result_position_data.end(), new_item) ==
2918 					run.result_position_data.end())
2919 				{
2920 					run.result_position_data.push_back(new_item);
2921 				}
2922 			}
2923 
2924 			if (xfb_value1_data_offset != -1)
2925 			{
2926 				const float* data_ptr =
2927 					(const float*)(xfb_data + xfb_varyings_size * n_vertex + xfb_value1_data_offset);
2928 				_vec2 new_item = _vec2(data_ptr[0], data_ptr[1]);
2929 
2930 				if (std::find(run.result_value1_data.begin(), run.result_value1_data.end(), new_item) ==
2931 					run.result_value1_data.end())
2932 				{
2933 					run.result_value1_data.push_back(new_item);
2934 				}
2935 			}
2936 
2937 			if (xfb_value2_data_offset != -1)
2938 			{
2939 				const int* data_ptr = (const int*)(xfb_data + xfb_varyings_size * n_vertex + xfb_value2_data_offset);
2940 				_ivec4	 new_item = _ivec4(data_ptr[0], data_ptr[1], data_ptr[2], data_ptr[3]);
2941 
2942 				if (std::find(run.result_value2_data.begin(), run.result_value2_data.end(), new_item) ==
2943 					run.result_value2_data.end())
2944 				{
2945 					run.result_value2_data.push_back(new_item);
2946 				}
2947 			}
2948 		} /* for (all result tessellation coordinates) */
2949 
2950 		/* Good to unmap the buffer object at this point */
2951 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2952 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
2953 	} /* for (two iterations) */
2954 }
2955 
2956 /** Executes the test.
2957  *
2958  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2959  *
2960  *  Note the function throws exception should an error occur!
2961  *
2962  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
2963  **/
iterate(void)2964 tcu::TestNode::IterateResult TessellationShaderTCTEgl_MaxPatchVertices_Position_PointSize::iterate(void)
2965 {
2966 	/* Initialize ES test objects */
2967 	initTest();
2968 
2969 	/* Calculate reference values that should be generated for all runs */
2970 	float		reference_result_pointsize(0);
2971 	_vec4		reference_result_position(0, 0, 0, 0);
2972 	_vec2		reference_result_value1(0, 0);
2973 	_ivec4		reference_result_value2(0, 0, 0, 0);
2974 	const float epsilon = (float)1e-5;
2975 
2976 	for (glw::GLint n_invocation = 0; n_invocation < m_gl_max_patch_vertices_value; ++n_invocation)
2977 	{
2978 		/* As per TC and TE shaders */
2979 		reference_result_pointsize += 1.0f / static_cast<float>(n_invocation + 1);
2980 
2981 		reference_result_position.x += static_cast<float>(n_invocation * 4 + 0);
2982 		reference_result_position.y += static_cast<float>(n_invocation * 4 + 1);
2983 		reference_result_position.z += static_cast<float>(n_invocation * 4 + 2);
2984 		reference_result_position.w += static_cast<float>(n_invocation * 4 + 3);
2985 
2986 		reference_result_value1.x += 1.0f / static_cast<float>(n_invocation + 1);
2987 		reference_result_value1.y += 1.0f / static_cast<float>(n_invocation + 2);
2988 
2989 		reference_result_value2.x += (n_invocation + 1);
2990 		reference_result_value2.y += (n_invocation + 2);
2991 		reference_result_value2.z += (n_invocation + 3);
2992 		reference_result_value2.w += (n_invocation + 4);
2993 	}
2994 
2995 	/* Iterate through test runs and analyse the result data */
2996 	for (_runs_const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++)
2997 	{
2998 		const _run& run = *run_iterator;
2999 
3000 		/* For the very first run, make sure that the type of tessellation shader objects
3001 		 * is reported correctly for both program and pipeline object cases.
3002 		 */
3003 		if (run_iterator == m_runs.begin())
3004 		{
3005 			const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
3006 			glw::GLint			  shader_type_tc = GL_NONE;
3007 			glw::GLint			  shader_type_te = GL_NONE;
3008 
3009 			/* Program objects first */
3010 			gl.getShaderiv(run.tc_id, GL_SHADER_TYPE, &shader_type_tc);
3011 			gl.getShaderiv(run.te_id, GL_SHADER_TYPE, &shader_type_te);
3012 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call(s) failed");
3013 
3014 			if ((glw::GLenum)shader_type_tc != m_glExtTokens.TESS_CONTROL_SHADER)
3015 			{
3016 				TCU_FAIL("Invalid shader type reported by glGetShaderiv() for a tessellation control shader");
3017 			}
3018 
3019 			if ((glw::GLenum)shader_type_te != m_glExtTokens.TESS_EVALUATION_SHADER)
3020 			{
3021 				TCU_FAIL("Invalid shader type reported by glGetShaderiv() for a tessellation evaluation shader");
3022 			}
3023 
3024 			/* Let's query the pipeline object now */
3025 			glw::GLint shader_id_tc = 0;
3026 			glw::GLint shader_id_te = 0;
3027 
3028 			gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_CONTROL_SHADER, &shader_id_tc);
3029 			gl.getProgramPipelineiv(run.pipeline_object_id, m_glExtTokens.TESS_EVALUATION_SHADER, &shader_id_te);
3030 
3031 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() failed for GL_TESS_CONTROL_SHADER_EXT / "
3032 											   "GL_TESS_EVALUATION_SHADER_EXT enum(s)");
3033 
3034 			if ((glw::GLuint)shader_id_tc != run.tc_program_id)
3035 			{
3036 				TCU_FAIL("Invalid separate program object ID reported for Tessellation Control stage");
3037 			}
3038 
3039 			if ((glw::GLuint)shader_id_te != run.te_program_id)
3040 			{
3041 				TCU_FAIL("Invalid separate program object ID reported for Tessellation Evaluation stage");
3042 			}
3043 		}
3044 
3045 		if ((run.point_mode && run.result_pointsize_data.size() != 1) ||
3046 			(run.point_mode && de::abs(run.result_pointsize_data[0] - reference_result_pointsize) > epsilon))
3047 		{
3048 			/* It is a test bug if result_pointsize_data.size() == 0 */
3049 			DE_ASSERT(run.result_pointsize_data.size() > 0);
3050 
3051 			m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set gl_PointSize value to "
3052 							   << run.result_pointsize_data[0] << " instead of expected value "
3053 							   << reference_result_pointsize << tcu::TestLog::EndMessage;
3054 
3055 			TCU_FAIL("Invalid gl_PointSize data exposed in TE stage");
3056 		}
3057 
3058 		if (run.result_position_data.size() != 1 || run.result_position_data[0] != reference_result_position)
3059 		{
3060 			/* It is a test bug if result_position_data.size() == 0 */
3061 			DE_ASSERT(run.result_position_data.size() > 0);
3062 
3063 			m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set gl_Position to "
3064 							   << " (" << run.result_position_data[0].x << ", " << run.result_position_data[0].y << ", "
3065 							   << run.result_position_data[0].z << ", " << run.result_position_data[0].w
3066 							   << " ) instead of expected value"
3067 								  " ("
3068 							   << reference_result_position.x << ", " << reference_result_position.y << ", "
3069 							   << reference_result_position.z << ", " << reference_result_position.w << ")"
3070 							   << tcu::TestLog::EndMessage;
3071 
3072 			TCU_FAIL("Invalid gl_Position data exposed in TE stage");
3073 		}
3074 
3075 		if (run.result_value1_data.size() != 1 ||
3076 			de::abs(run.result_value1_data[0].x - reference_result_value1.x) > epsilon ||
3077 			de::abs(run.result_value1_data[0].y - reference_result_value1.y) > epsilon)
3078 		{
3079 			/* It is a test bug if result_value1_data.size() == 0 */
3080 			DE_ASSERT(run.result_value1_data.size() > 0);
3081 
3082 			m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set te_value1 to "
3083 							   << " (" << run.result_value1_data[0].x << ", " << run.result_value1_data[0].y
3084 							   << " ) instead of expected value"
3085 								  " ("
3086 							   << reference_result_value1.x << ", " << reference_result_value1.y << ")"
3087 							   << tcu::TestLog::EndMessage;
3088 
3089 			TCU_FAIL("Invalid gl_Position data exposed in TE stage");
3090 		}
3091 
3092 		if (run.result_value2_data.size() != 1 || run.result_value2_data[0] != reference_result_value2)
3093 		{
3094 			/* It is a test bug if result_value2_data.size() == 0 */
3095 			DE_ASSERT(run.result_value2_data.size() > 0);
3096 
3097 			m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation Evaluation stage set te_value2 to "
3098 							   << " (" << run.result_value2_data[0].x << ", " << run.result_value2_data[0].y << ", "
3099 							   << run.result_value2_data[0].z << ", " << run.result_value2_data[0].w
3100 							   << " ) instead of expected value"
3101 								  " ("
3102 							   << reference_result_value2.x << ", " << reference_result_value2.y << ", "
3103 							   << reference_result_value2.z << ", " << reference_result_value2.w << ")"
3104 							   << tcu::TestLog::EndMessage;
3105 
3106 			TCU_FAIL("Invalid value2 data saved in TE stage");
3107 		}
3108 	} /* for (all runs) */
3109 
3110 	/* All done */
3111 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3112 	return STOP;
3113 }
3114 
3115 /** Constructor
3116  *
3117  * @param context Test context
3118  **/
TessellationShaderTCTEgl_TessLevel(Context & context,const ExtParameters & extParams)3119 TessellationShaderTCTEgl_TessLevel::TessellationShaderTCTEgl_TessLevel(Context& context, const ExtParameters& extParams)
3120 	: TestCaseBase(context, extParams, "gl_tessLevel",
3121 				   "Verifies gl_TessLevelOuter and gl_TessLevelInner patch variable "
3122 				   "values in a tessellation evaluation shader are valid and correspond"
3123 				   "to values configured in a tessellation control shader (should one be "
3124 				   "present) or to the default values, as set with glPatchParameterfv() calls")
3125 	, m_gl_max_tess_gen_level_value(0)
3126 	, m_bo_id(0)
3127 	, m_vao_id(0)
3128 {
3129 	/* Left blank on purpose */
3130 }
3131 
3132 /** Deinitializes all ES objects created for the test. */
deinit()3133 void TessellationShaderTCTEgl_TessLevel::deinit()
3134 {
3135 	/** Call base class' deinit() function */
3136 	TestCaseBase::deinit();
3137 
3138 	if (!m_is_tessellation_shader_supported)
3139 	{
3140 		return;
3141 	}
3142 
3143 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3144 
3145 	/* Reset TF buffer object bindings */
3146 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
3147 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
3148 
3149 	/* Reset GL_PATCH_VERTICES_EXT value to the default setting */
3150 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
3151 
3152 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3153 	{
3154 		/* Revert GL_PATCH_DEFAULT_INNER_LEVEL and GL_PATCH_DEFAULT_OUTER_LEVEL pname
3155 		 * values to the default settings */
3156 		const float default_levels[] = { 1.0f, 1.0f, 1.0f, 1.0f };
3157 		gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, default_levels);
3158 		gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, default_levels);
3159 	}
3160 
3161 	/* Disable GL_RASTERIZER_DISCARD mode */
3162 	gl.disable(GL_RASTERIZER_DISCARD);
3163 
3164 	/* Unbind vertex array object */
3165 	gl.bindVertexArray(0);
3166 
3167 	/* Release all objects we might've created */
3168 	if (m_bo_id != 0)
3169 	{
3170 		gl.deleteBuffers(1, &m_bo_id);
3171 
3172 		m_bo_id = 0;
3173 	}
3174 
3175 	if (m_vao_id != 0)
3176 	{
3177 		gl.deleteVertexArrays(1, &m_vao_id);
3178 
3179 		m_vao_id = 0;
3180 	}
3181 
3182 	for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
3183 	{
3184 		deinitTestDescriptor(&*it);
3185 	}
3186 	m_tests.clear();
3187 }
3188 
3189 /** Deinitializes ES objects created for particular test pass.
3190  *
3191  *  @param test_ptr Test run descriptor. Must not be NULL.
3192  *
3193  **/
deinitTestDescriptor(_test_descriptor * test_ptr)3194 void TessellationShaderTCTEgl_TessLevel::deinitTestDescriptor(_test_descriptor* test_ptr)
3195 {
3196 	/* Call base class' deinit() */
3197 	TestCaseBase::deinit();
3198 
3199 	/* Release all objects */
3200 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3201 
3202 	if (test_ptr->fs_id != 0)
3203 	{
3204 		gl.deleteShader(test_ptr->fs_id);
3205 
3206 		test_ptr->fs_id = 0;
3207 	}
3208 
3209 	if (test_ptr->po_id != 0)
3210 	{
3211 		gl.deleteProgram(test_ptr->po_id);
3212 
3213 		test_ptr->po_id = 0;
3214 	}
3215 
3216 	if (test_ptr->tcs_id != 0)
3217 	{
3218 		gl.deleteShader(test_ptr->tcs_id);
3219 
3220 		test_ptr->tcs_id = 0;
3221 	}
3222 
3223 	if (test_ptr->tes_id != 0)
3224 	{
3225 		gl.deleteShader(test_ptr->tes_id);
3226 
3227 		test_ptr->tes_id = 0;
3228 	}
3229 
3230 	if (test_ptr->vs_id != 0)
3231 	{
3232 		gl.deleteShader(test_ptr->vs_id);
3233 
3234 		test_ptr->vs_id = 0;
3235 	}
3236 }
3237 
3238 /** Initializes all ES objects that will be used for the test. */
initTest()3239 void TessellationShaderTCTEgl_TessLevel::initTest()
3240 {
3241 	/* The test requires EXT_tessellation_shader */
3242 	if (!m_is_tessellation_shader_supported)
3243 	{
3244 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
3245 	}
3246 
3247 	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value before we carry on */
3248 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3249 
3250 	/* Initialize vertex array object */
3251 	gl.genVertexArrays(1, &m_vao_id);
3252 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
3253 
3254 	gl.bindVertexArray(m_vao_id);
3255 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
3256 
3257 	/* Retrieve gen level */
3258 	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &m_gl_max_tess_gen_level_value);
3259 
3260 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() for GL_MAX_TESS_GEN_LEVEL_EXT pname failed");
3261 
3262 	/* Initialize test descriptors */
3263 	_test_descriptor test_tcs_tes_equal;
3264 	_test_descriptor test_tcs_tes_fe;
3265 	_test_descriptor test_tcs_tes_fo;
3266 	_test_descriptor test_tes_equal;
3267 	_test_descriptor test_tes_fe;
3268 	_test_descriptor test_tes_fo;
3269 
3270 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_equal, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL);
3271 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_fe,
3272 					   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN);
3273 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_fo,
3274 					   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD);
3275 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3276 	{
3277 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_equal, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL);
3278 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_fe,
3279 						   TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN);
3280 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_fo, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD);
3281 	}
3282 
3283 	m_tests.push_back(test_tcs_tes_equal);
3284 	m_tests.push_back(test_tcs_tes_fe);
3285 	m_tests.push_back(test_tcs_tes_fo);
3286 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3287 	{
3288 		m_tests.push_back(test_tes_equal);
3289 		m_tests.push_back(test_tes_fe);
3290 		m_tests.push_back(test_tes_fo);
3291 	}
3292 
3293 	/* Generate and set up a buffer object we will use to hold XFBed data.
3294 	 *
3295 	 * NOTE: We do not set the buffer object's storage here because its size
3296 	 *       is iteration-specific.
3297 	 **/
3298 	gl.genBuffers(1, &m_bo_id);
3299 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
3300 
3301 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
3302 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
3303 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
3304 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
3305 
3306 	/* We're good to execute the test! */
3307 }
3308 
3309 /** Initializes ES objects for a particular tess pass.
3310  *
3311  *  @param test_type           Determines test type to be used for initialization.
3312  *                             TEST_TYPE_TCS_TES will use both TC and TE stages,
3313  *                             TEST_TYPE_TES will assume only TE stage should be used.
3314  *  @param out_test_ptr        Deref will be used to store object data. Must not be NULL.
3315  *  @param vertex_spacing_mode Vertex spacing mode to use for the TE stage.
3316  *
3317  **/
initTestDescriptor(_tessellation_test_type test_type,_test_descriptor * out_test_ptr,_tessellation_shader_vertex_spacing vertex_spacing_mode)3318 void TessellationShaderTCTEgl_TessLevel::initTestDescriptor(_tessellation_test_type				test_type,
3319 															_test_descriptor*					out_test_ptr,
3320 															_tessellation_shader_vertex_spacing vertex_spacing_mode)
3321 {
3322 	out_test_ptr->type			 = test_type;
3323 	out_test_ptr->vertex_spacing = vertex_spacing_mode;
3324 
3325 	/* Generate a program object we will later configure */
3326 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3327 
3328 	out_test_ptr->po_id = gl.createProgram();
3329 
3330 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
3331 
3332 	/* Generate shader objects the test will use */
3333 	out_test_ptr->fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3334 	out_test_ptr->vs_id = gl.createShader(GL_VERTEX_SHADER);
3335 
3336 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES)
3337 	{
3338 		out_test_ptr->tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
3339 	}
3340 
3341 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
3342 	{
3343 		out_test_ptr->tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
3344 	}
3345 
3346 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
3347 
3348 	/* Configure fragment shader */
3349 	const char* fs_body = "${VERSION}\n"
3350 						  "\n"
3351 						  "void main()\n"
3352 						  "{\n"
3353 						  "}\n";
3354 
3355 	shaderSourceSpecialized(out_test_ptr->fs_id, 1 /* count */, &fs_body);
3356 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object");
3357 
3358 	/* Configure tessellation control shader */
3359 	const char* tc_body = "${VERSION}\n"
3360 						  "\n"
3361 						  /* Required EXT_tessellation_shader functionality */
3362 						  "${TESSELLATION_SHADER_REQUIRE}\n"
3363 						  "\n"
3364 						  "layout (vertices = 4) out;\n"
3365 						  "\n"
3366 						  "uniform vec2 inner_tess_levels;\n"
3367 						  "uniform vec4 outer_tess_levels;\n"
3368 						  "\n"
3369 						  "void main()\n"
3370 						  "{\n"
3371 						  "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
3372 						  "    if (gl_InvocationID == 0) {\n"
3373 						  "        gl_TessLevelInner[0]                           = inner_tess_levels[0];\n"
3374 						  "        gl_TessLevelInner[1]                           = inner_tess_levels[1];\n"
3375 						  "        gl_TessLevelOuter[0]                           = outer_tess_levels[0];\n"
3376 						  "        gl_TessLevelOuter[1]                           = outer_tess_levels[1];\n"
3377 						  "        gl_TessLevelOuter[2]                           = outer_tess_levels[2];\n"
3378 						  "        gl_TessLevelOuter[3]                           = outer_tess_levels[3];\n"
3379 						  "   }\n"
3380 						  "}\n";
3381 
3382 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
3383 	{
3384 		shaderSourceSpecialized(out_test_ptr->tcs_id, 1 /* count */, &tc_body);
3385 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object");
3386 	}
3387 
3388 	/* Configure tessellation evaluation shader */
3389 	const char* te_body = "${VERSION}\n"
3390 						  "\n"
3391 						  "${TESSELLATION_SHADER_REQUIRE}\n"
3392 						  "\n"
3393 						  "layout (quads, point_mode, VERTEX_SPACING_MODE) in;\n"
3394 						  "\n"
3395 						  "out vec2 result_tess_level_inner;\n"
3396 						  "out vec4 result_tess_level_outer;\n"
3397 						  "\n"
3398 						  "void main()\n"
3399 						  "{\n"
3400 						  "    vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
3401 						  "    vec4 p2 = mix(gl_in[2].gl_Position,gl_in[3].gl_Position,gl_TessCoord.x);\n"
3402 						  "    gl_Position = mix(p1, p2, gl_TessCoord.y);\n"
3403 						  "\n"
3404 						  "    result_tess_level_inner = vec2(gl_TessLevelInner[0],\n"
3405 						  "                                   gl_TessLevelInner[1]);\n"
3406 						  "    result_tess_level_outer = vec4(gl_TessLevelOuter[0],\n"
3407 						  "                                   gl_TessLevelOuter[1],\n"
3408 						  "                                   gl_TessLevelOuter[2],\n"
3409 						  "                                   gl_TessLevelOuter[3]);\n"
3410 						  "}\n";
3411 
3412 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES)
3413 	{
3414 		/* Replace VERTEX_SPACING_MODE with the mode provided by the caller */
3415 		std::stringstream te_body_stringstream;
3416 		std::string		  te_body_string;
3417 		const std::string token = "VERTEX_SPACING_MODE";
3418 		std::size_t		  token_index;
3419 		std::string		  vertex_spacing_string =
3420 			TessellationShaderUtils::getESTokenForVertexSpacingMode(vertex_spacing_mode);
3421 
3422 		te_body_stringstream << te_body;
3423 		te_body_string = te_body_stringstream.str();
3424 
3425 		token_index = te_body_string.find(token);
3426 
3427 		while (token_index != std::string::npos)
3428 		{
3429 			te_body_string = te_body_string.replace(token_index, token.length(), vertex_spacing_string.c_str());
3430 
3431 			token_index = te_body_string.find(token);
3432 		}
3433 
3434 		/* Set the shader source */
3435 		const char* te_body_string_raw = te_body_string.c_str();
3436 
3437 		shaderSourceSpecialized(out_test_ptr->tes_id, 1 /* count */, &te_body_string_raw);
3438 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object");
3439 	}
3440 
3441 	/* Configure vertex shader */
3442 	const char* vs_body = "${VERSION}\n"
3443 						  "\n"
3444 						  "void main()\n"
3445 						  "{\n"
3446 						  "    gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n"
3447 						  "}\n";
3448 
3449 	shaderSourceSpecialized(out_test_ptr->vs_id, 1 /* count */, &vs_body);
3450 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object");
3451 
3452 	/* Compile all shaders of our interest */
3453 	const glw::GLuint shaders[] = { out_test_ptr->fs_id, out_test_ptr->tcs_id, out_test_ptr->tes_id,
3454 									out_test_ptr->vs_id };
3455 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
3456 
3457 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
3458 	{
3459 		glw::GLint  compile_status = GL_FALSE;
3460 		glw::GLuint shader		   = shaders[n_shader];
3461 
3462 		if (shader != 0)
3463 		{
3464 			gl.compileShader(shader);
3465 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
3466 
3467 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
3468 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
3469 
3470 			if (compile_status != GL_TRUE)
3471 			{
3472 				m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader
3473 								   << " failed." << tcu::TestLog::EndMessage;
3474 
3475 				TCU_FAIL("Shader compilation failed");
3476 			}
3477 		} /* if (shader != 0) */
3478 	}	 /* for (all shaders) */
3479 
3480 	/* Attach the shaders to the test program object, set up XFB and then link the program */
3481 	glw::GLint		   link_status = GL_FALSE;
3482 	const char*		   varyings[]  = { "result_tess_level_inner", "result_tess_level_outer" };
3483 	const unsigned int n_varyings  = sizeof(varyings) / sizeof(varyings[0]);
3484 
3485 	gl.transformFeedbackVaryings(out_test_ptr->po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
3486 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
3487 
3488 	gl.attachShader(out_test_ptr->po_id, out_test_ptr->fs_id);
3489 	gl.attachShader(out_test_ptr->po_id, out_test_ptr->vs_id);
3490 
3491 	if (out_test_ptr->tcs_id != 0)
3492 	{
3493 		gl.attachShader(out_test_ptr->po_id, out_test_ptr->tcs_id);
3494 	}
3495 
3496 	if (out_test_ptr->tes_id != 0)
3497 	{
3498 		gl.attachShader(out_test_ptr->po_id, out_test_ptr->tes_id);
3499 	}
3500 
3501 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
3502 
3503 	gl.linkProgram(out_test_ptr->po_id);
3504 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
3505 
3506 	gl.getProgramiv(out_test_ptr->po_id, GL_LINK_STATUS, &link_status);
3507 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
3508 
3509 	if (link_status != GL_TRUE)
3510 	{
3511 		TCU_FAIL("Program linking failed");
3512 	}
3513 
3514 	/* Retrieve uniform locations */
3515 	out_test_ptr->inner_tess_levels_uniform_location = gl.getUniformLocation(out_test_ptr->po_id, "inner_tess_levels");
3516 	out_test_ptr->outer_tess_levels_uniform_location = gl.getUniformLocation(out_test_ptr->po_id, "outer_tess_levels");
3517 
3518 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed");
3519 
3520 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
3521 	{
3522 		DE_ASSERT(out_test_ptr->inner_tess_levels_uniform_location != -1);
3523 		DE_ASSERT(out_test_ptr->outer_tess_levels_uniform_location != -1);
3524 	}
3525 }
3526 
3527 /** Executes the test.
3528  *
3529  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3530  *
3531  *  Note the function throws exception should an error occur!
3532  *
3533  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
3534  **/
iterate(void)3535 tcu::TestNode::IterateResult TessellationShaderTCTEgl_TessLevel::iterate(void)
3536 {
3537 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3538 
3539 	/* Initialize ES test objects */
3540 	initTest();
3541 
3542 	/* Our program object takes a single quad per patch */
3543 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 4);
3544 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed");
3545 
3546 	/* Prepare for rendering */
3547 	gl.enable(GL_RASTERIZER_DISCARD);
3548 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
3549 
3550 	/* We will iterate through all added tests. */
3551 	for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); ++test_iterator)
3552 	{
3553 		/* Iterate through a few different inner/outer tessellation level combinations */
3554 		glw::GLfloat tessellation_level_combinations[] = {
3555 			/* inner[0] */ /* inner[1] */ /* outer[0] */ /* outer[1] */ /* outer[2] */ /* outer[3] */
3556 			1.1f, 1.4f, 2.7f, 3.1f, 4.4f, 5.7f, 64.2f, 32.5f, 16.8f, 8.2f, 4.5f, 2.8f, 3.3f, 6.6f, 9.9f, 12.3f, 15.6f,
3557 			18.9f
3558 		};
3559 		const unsigned int n_tessellation_level_combinations = sizeof(tessellation_level_combinations) /
3560 															   sizeof(tessellation_level_combinations[0]) /
3561 															   6; /* 2 inner + 4 outer levels */
3562 
3563 		for (unsigned int n_combination = 0; n_combination < n_tessellation_level_combinations; ++n_combination)
3564 		{
3565 			glw::GLfloat inner_tess_level[] = { tessellation_level_combinations[n_combination * 6 + 0],
3566 												tessellation_level_combinations[n_combination * 6 + 1] };
3567 
3568 			glw::GLfloat outer_tess_level[] = { tessellation_level_combinations[n_combination * 6 + 2],
3569 												tessellation_level_combinations[n_combination * 6 + 3],
3570 												tessellation_level_combinations[n_combination * 6 + 4],
3571 												tessellation_level_combinations[n_combination * 6 + 5] };
3572 
3573 			TessellationShaderUtils tessUtils(gl, this);
3574 			const unsigned int		n_rendered_vertices = tessUtils.getAmountOfVerticesGeneratedByTessellator(
3575 				TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, inner_tess_level, outer_tess_level,
3576 				test_iterator->vertex_spacing, true); /* is_point_mode_enabled */
3577 
3578 			/* Test type determines how the tessellation levels should be set. */
3579 			gl.useProgram(test_iterator->po_id);
3580 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
3581 
3582 			switch (test_iterator->type)
3583 			{
3584 			case TESSELLATION_TEST_TYPE_TCS_TES:
3585 			{
3586 				gl.uniform2fv(test_iterator->inner_tess_levels_uniform_location, 1, /* count */
3587 							  inner_tess_level);
3588 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2fv() call failed");
3589 
3590 				gl.uniform4fv(test_iterator->outer_tess_levels_uniform_location, 1, /* count */
3591 							  outer_tess_level);
3592 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed");
3593 
3594 				break;
3595 			}
3596 
3597 			case TESSELLATION_TEST_TYPE_TES:
3598 			{
3599 				if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3600 				{
3601 					gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, inner_tess_level);
3602 
3603 					GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() call failed for"
3604 													   " GL_PATCH_DEFAULT_INNER_LEVEL pname");
3605 
3606 					gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, outer_tess_level);
3607 
3608 					GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() call failed for"
3609 													   " GL_PATCH_DEFAULT_OUTER_LEVEL pname");
3610 				}
3611 				break;
3612 			}
3613 
3614 			default:
3615 			{
3616 				TCU_FAIL("Unrecognized test type");
3617 			}
3618 			} /* switch (test_iterator->type) */
3619 
3620 			/* Set up storage properties for the buffer object, to which XFBed data will be
3621 			 * written.
3622 			 */
3623 			const unsigned int n_bytes_needed =
3624 				static_cast<unsigned int>(n_rendered_vertices * (2 /* vec2 */ + 4 /* vec4 */) * sizeof(float));
3625 
3626 			gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL /* data */, GL_STATIC_DRAW);
3627 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
3628 
3629 			/* Render the test geometry */
3630 			gl.beginTransformFeedback(GL_POINTS);
3631 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
3632 			{
3633 				/* A single vertex will do, since we configured GL_PATCH_VERTICES_EXT to be 1 */
3634 				gl.drawArrays(GL_PATCHES_EXT, 0 /* first */, 4 /* count */);
3635 
3636 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
3637 			}
3638 			gl.endTransformFeedback();
3639 			GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
3640 
3641 			/* Now that the BO is filled with data, map it so we can check the storage's contents */
3642 			const float* mapped_data_ptr = (const float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
3643 																		   n_bytes_needed, GL_MAP_READ_BIT);
3644 
3645 			GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3646 
3647 			/* Verify the contents. For each result vertex, inner/outer tessellation levels should
3648 			 * be unchanged. */
3649 			const float		   epsilon = (float)1e-5;
3650 			const unsigned int n_result_points =
3651 				static_cast<unsigned int>(n_bytes_needed / sizeof(float) / (2 /* vec2 */ + 4 /* vec4 */));
3652 
3653 			for (unsigned int n_point = 0; n_point < n_result_points; ++n_point)
3654 			{
3655 				const float* point_data_ptr = mapped_data_ptr + (2 /* vec2 */ + 4 /* vec4 */) * n_point;
3656 
3657 				if (de::abs(point_data_ptr[2] - outer_tess_level[0]) > epsilon ||
3658 					de::abs(point_data_ptr[3] - outer_tess_level[1]) > epsilon)
3659 				{
3660 					std::string vertex_spacing_mode_string =
3661 						TessellationShaderUtils::getESTokenForVertexSpacingMode(test_iterator->vertex_spacing);
3662 
3663 					m_testCtx.getLog() << tcu::TestLog::Message
3664 									   << "Invalid inner/outer tessellation level used in TE stage;"
3665 									   << " expected outer:(" << outer_tess_level[0] << ", " << outer_tess_level[1]
3666 									   << ") "
3667 									   << " rendered outer:(" << point_data_ptr[2] << ", " << point_data_ptr[3] << ")"
3668 									   << " vertex spacing mode: " << vertex_spacing_mode_string.c_str()
3669 									   << tcu::TestLog::EndMessage;
3670 
3671 					TCU_FAIL("Invalid inner/outer tessellation level used in TE stage");
3672 				}
3673 			} /* for (all points) */
3674 
3675 			/* All done - unmap the storage */
3676 			gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3677 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3678 		} /* for (all tess level combinations) */
3679 	}	 /* for (all tests) */
3680 
3681 	/* All done */
3682 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3683 	return STOP;
3684 }
3685 
3686 /** Constructor
3687  *
3688  * @param context Test context
3689  **/
TessellationShaderTCTEgl_PatchVerticesIn(Context & context,const ExtParameters & extParams)3690 TessellationShaderTCTEgl_PatchVerticesIn::TessellationShaderTCTEgl_PatchVerticesIn(Context&				context,
3691 																				   const ExtParameters& extParams)
3692 	: TestCaseBase(context, extParams, "gl_PatchVerticesIn",
3693 				   "Verifies gl_PatchVerticesIn size is valid in a tessellation"
3694 				   " evaluation shader and corresponds to the value configured in"
3695 				   " a tessellation control shader (should one be present) or to"
3696 				   " the default value, as set with glPatchParameteriEXT() call")
3697 	, m_gl_max_patch_vertices_value(0)
3698 	, m_bo_id(0)
3699 	, m_vao_id(0)
3700 {
3701 	/* Left blank on purpose */
3702 }
3703 
3704 /** Deinitializes all ES objects created for the test. */
deinit()3705 void TessellationShaderTCTEgl_PatchVerticesIn::deinit()
3706 {
3707 	/** Call base class' deinit() function */
3708 	TestCaseBase::deinit();
3709 
3710 	if (!m_is_tessellation_shader_supported)
3711 	{
3712 		return;
3713 	}
3714 
3715 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3716 
3717 	/* Reset TF buffer object bindings */
3718 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
3719 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
3720 
3721 	/* Disable GL_RASTERIZER_DISCARD mode */
3722 	gl.disable(GL_RASTERIZER_DISCARD);
3723 
3724 	/* Reset GL_PATCH_VERTICES_EXT to the default setting */
3725 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
3726 
3727 	/* Unbind vertex array object */
3728 	gl.bindVertexArray(0);
3729 
3730 	/* Release all objects we might've created */
3731 	if (m_bo_id != 0)
3732 	{
3733 		gl.deleteBuffers(1, &m_bo_id);
3734 
3735 		m_bo_id = 0;
3736 	}
3737 
3738 	if (m_vao_id != 0)
3739 	{
3740 		gl.deleteVertexArrays(1, &m_vao_id);
3741 
3742 		m_vao_id = 0;
3743 	}
3744 
3745 	for (_tests::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
3746 	{
3747 		deinitTestDescriptor(&*it);
3748 	}
3749 	m_tests.clear();
3750 }
3751 
3752 /** Deinitializes ES objects created for particular test pass.
3753  *
3754  *  @param test_ptr Test run descriptor. Must not be NULL.
3755  *
3756  **/
deinitTestDescriptor(_test_descriptor * test_ptr)3757 void TessellationShaderTCTEgl_PatchVerticesIn::deinitTestDescriptor(_test_descriptor* test_ptr)
3758 {
3759 	/* Call base class' deinit() */
3760 	TestCaseBase::deinit();
3761 
3762 	/* Release all objects */
3763 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3764 
3765 	if (test_ptr->fs_id != 0)
3766 	{
3767 		gl.deleteShader(test_ptr->fs_id);
3768 
3769 		test_ptr->fs_id = 0;
3770 	}
3771 
3772 	if (test_ptr->po_id != 0)
3773 	{
3774 		gl.deleteProgram(test_ptr->po_id);
3775 
3776 		test_ptr->po_id = 0;
3777 	}
3778 
3779 	if (test_ptr->tcs_id != 0)
3780 	{
3781 		gl.deleteShader(test_ptr->tcs_id);
3782 
3783 		test_ptr->tcs_id = 0;
3784 	}
3785 
3786 	if (test_ptr->tes_id != 0)
3787 	{
3788 		gl.deleteShader(test_ptr->tes_id);
3789 
3790 		test_ptr->tes_id = 0;
3791 	}
3792 
3793 	if (test_ptr->vs_id != 0)
3794 	{
3795 		gl.deleteShader(test_ptr->vs_id);
3796 
3797 		test_ptr->vs_id = 0;
3798 	}
3799 }
3800 
3801 /** Initializes all ES objects that will be used for the test. */
initTest()3802 void TessellationShaderTCTEgl_PatchVerticesIn::initTest()
3803 {
3804 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3805 
3806 	/* The test requires EXT_tessellation_shader */
3807 	if (!m_is_tessellation_shader_supported)
3808 	{
3809 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
3810 	}
3811 
3812 	/* Initialize vertex array object */
3813 	gl.genVertexArrays(1, &m_vao_id);
3814 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
3815 
3816 	gl.bindVertexArray(m_vao_id);
3817 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
3818 
3819 	/* Retrieve GL_MAX_PATCH_VERTICES_EXT value before we carry on */
3820 	gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices_value);
3821 
3822 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() for GL_MAX_PATCH_VERTICES_EXT pname failed");
3823 
3824 	/* Initialize test descriptors.
3825 	 *
3826 	 * Make sure the values we use are multiples of 4 - this is because we're using isolines in the
3827 	 * tessellation stage, and in order to have the requested amount of line segments generated, we need
3828 	 * to use a multiply of 4 vertices per patch */
3829 	glw::GLint n_half_max_patch_vertices_mul_4 = m_gl_max_patch_vertices_value / 2;
3830 	glw::GLint n_max_patch_vertices_mul_4	  = m_gl_max_patch_vertices_value;
3831 
3832 	if ((n_half_max_patch_vertices_mul_4 % 4) != 0)
3833 	{
3834 		/* Round to nearest mul-of-4 integer */
3835 		n_half_max_patch_vertices_mul_4 += (4 - (m_gl_max_patch_vertices_value / 2) % 4);
3836 	}
3837 
3838 	if ((n_max_patch_vertices_mul_4 % 4) != 0)
3839 	{
3840 		/* Round to previous nearest mul-of-4 integer */
3841 		n_max_patch_vertices_mul_4 -= (m_gl_max_patch_vertices_value % 4);
3842 	}
3843 
3844 	_test_descriptor test_tcs_tes_4;
3845 	_test_descriptor test_tcs_tes_half_max_patch_vertices_mul_4;
3846 	_test_descriptor test_tcs_tes_max_patch_vertices_mul_4;
3847 	_test_descriptor test_tes_4;
3848 	_test_descriptor test_tes_half_max_patch_vertices_mul_4;
3849 	_test_descriptor test_tes_max_patch_vertices_mul_4;
3850 
3851 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_4, 4);
3852 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_half_max_patch_vertices_mul_4,
3853 					   n_half_max_patch_vertices_mul_4);
3854 	initTestDescriptor(TESSELLATION_TEST_TYPE_TCS_TES, &test_tcs_tes_max_patch_vertices_mul_4,
3855 					   n_max_patch_vertices_mul_4);
3856 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3857 	{
3858 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_4, 4);
3859 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_half_max_patch_vertices_mul_4,
3860 						   n_half_max_patch_vertices_mul_4);
3861 		initTestDescriptor(TESSELLATION_TEST_TYPE_TES, &test_tes_max_patch_vertices_mul_4, n_max_patch_vertices_mul_4);
3862 	}
3863 
3864 	m_tests.push_back(test_tcs_tes_4);
3865 	m_tests.push_back(test_tcs_tes_half_max_patch_vertices_mul_4);
3866 	m_tests.push_back(test_tcs_tes_max_patch_vertices_mul_4);
3867 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3868 	{
3869 		m_tests.push_back(test_tes_4);
3870 		m_tests.push_back(test_tes_half_max_patch_vertices_mul_4);
3871 		m_tests.push_back(test_tes_max_patch_vertices_mul_4);
3872 	}
3873 
3874 	/* Generate and set up a buffer object we will use to hold XFBed data.
3875 	 *
3876 	 * NOTE: We do not set the buffer object's storage here because its size
3877 	 *       is iteration-specific.
3878 	 **/
3879 	gl.genBuffers(1, &m_bo_id);
3880 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
3881 
3882 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
3883 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
3884 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
3885 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
3886 
3887 	/* We're good to execute the test! */
3888 }
3889 
3890 /** Initializes ES objects for a particular tess pass.
3891  *
3892  *  @param test_type        Determines test type to be used for initialization.
3893  *                          TEST_TYPE_TCS_TES will use both TC and TE stages,
3894  *                          TEST_TYPE_TES will assume only TE stage should be used.
3895  *  @param out_test_ptr     Deref will be used to store object data. Must not be NULL.
3896  *  @param input_patch_size Tells how many vertices should be used per patch for hte
3897  *                          result program object.
3898  **/
initTestDescriptor(_tessellation_test_type test_type,_test_descriptor * out_test_ptr,unsigned int input_patch_size)3899 void TessellationShaderTCTEgl_PatchVerticesIn::initTestDescriptor(_tessellation_test_type test_type,
3900 																  _test_descriptor*		  out_test_ptr,
3901 																  unsigned int			  input_patch_size)
3902 {
3903 	out_test_ptr->input_patch_size = input_patch_size;
3904 	out_test_ptr->type			   = test_type;
3905 
3906 	/* Generate a program object we will later configure */
3907 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3908 
3909 	out_test_ptr->po_id = gl.createProgram();
3910 
3911 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
3912 
3913 	/* Generate shader objects the test will use */
3914 	out_test_ptr->fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3915 	out_test_ptr->vs_id = gl.createShader(GL_VERTEX_SHADER);
3916 
3917 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES || test_type == TESSELLATION_TEST_TYPE_TES)
3918 	{
3919 		out_test_ptr->tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
3920 	}
3921 
3922 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
3923 	{
3924 		out_test_ptr->tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
3925 	}
3926 
3927 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
3928 
3929 	/* Configure fragment shader */
3930 	const char* fs_body = "${VERSION}\n"
3931 						  "\n"
3932 						  "void main()\n"
3933 						  "{\n"
3934 						  "}\n";
3935 
3936 	shaderSourceSpecialized(out_test_ptr->fs_id, 1 /* count */, &fs_body);
3937 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader object");
3938 
3939 	/* Configure tessellation control shader */
3940 	const char* tc_body = "${VERSION}\n"
3941 						  "\n"
3942 						  /* Required EXT_tessellation_shader functionality */
3943 						  "${TESSELLATION_SHADER_REQUIRE}\n"
3944 						  "\n"
3945 						  "layout (vertices = VERTICES_TOKEN) out;\n"
3946 						  "\n"
3947 						  "void main()\n"
3948 						  "{\n"
3949 						  "    gl_out           [gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
3950 						  "    gl_TessLevelOuter[0]                           = 1.0;\n"
3951 						  "    gl_TessLevelOuter[1]                           = 1.0;\n"
3952 						  "}\n";
3953 
3954 	if (test_type == TESSELLATION_TEST_TYPE_TCS_TES)
3955 	{
3956 		const char*		  result_body	= NULL;
3957 		std::string		  tc_body_string = tc_body;
3958 		std::size_t		  token_index	= -1;
3959 		const char*		  token_string   = "VERTICES_TOKEN";
3960 		std::stringstream vertices_stringstream;
3961 		std::string		  vertices_string;
3962 
3963 		vertices_stringstream << input_patch_size;
3964 		vertices_string = vertices_stringstream.str();
3965 
3966 		while ((token_index = tc_body_string.find(token_string)) != std::string::npos)
3967 		{
3968 			tc_body_string = tc_body_string.replace(token_index, strlen(token_string), vertices_string);
3969 		}
3970 
3971 		result_body = tc_body_string.c_str();
3972 
3973 		shaderSourceSpecialized(out_test_ptr->tcs_id, 1 /* count */, &result_body);
3974 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation control shader object");
3975 	}
3976 
3977 	/* Configure tessellation evaluation shader */
3978 	const char* te_body = "${VERSION}\n"
3979 						  "\n"
3980 						  "${TESSELLATION_SHADER_REQUIRE}\n"
3981 						  "\n"
3982 						  "layout (isolines, point_mode) in;\n"
3983 						  "\n"
3984 						  "flat out int result_PatchVerticesIn;\n"
3985 						  "\n"
3986 						  "void main()\n"
3987 						  "{\n"
3988 						  "    gl_Position = gl_in[0].gl_Position;\n"
3989 						  "\n"
3990 						  "    result_PatchVerticesIn = gl_PatchVerticesIn;\n"
3991 						  "}\n";
3992 
3993 	shaderSourceSpecialized(out_test_ptr->tes_id, 1 /* count */, &te_body);
3994 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for tessellation evaluation shader object");
3995 
3996 	/* Configure vertex shader */
3997 	const char* vs_body = "${VERSION}\n"
3998 						  "\n"
3999 						  "void main()\n"
4000 						  "{\n"
4001 						  "    gl_Position = vec4(float(gl_VertexID), 2.0, 3.0, 4.0);\n"
4002 						  "}\n";
4003 
4004 	shaderSourceSpecialized(out_test_ptr->vs_id, 1 /* count */, &vs_body);
4005 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader object");
4006 
4007 	/* Compile all shaders of our interest */
4008 	const glw::GLuint shaders[] = { out_test_ptr->fs_id, out_test_ptr->tcs_id, out_test_ptr->tes_id,
4009 									out_test_ptr->vs_id };
4010 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
4011 
4012 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
4013 	{
4014 		glw::GLint  compile_status = GL_FALSE;
4015 		glw::GLuint shader		   = shaders[n_shader];
4016 
4017 		if (shader != 0)
4018 		{
4019 			gl.compileShader(shader);
4020 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
4021 
4022 			gl.getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
4023 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
4024 
4025 			if (compile_status != GL_TRUE)
4026 			{
4027 				m_testCtx.getLog() << tcu::TestLog::Message << "Compilation of shader object at index " << n_shader
4028 								   << " failed." << tcu::TestLog::EndMessage;
4029 
4030 				TCU_FAIL("Shader compilation failed");
4031 			}
4032 		} /* if (shader != 0) */
4033 	}	 /* for (all shaders) */
4034 
4035 	/* Attach the shaders to the test program object, set up XFB and then link the program */
4036 	glw::GLint  link_status = GL_FALSE;
4037 	const char* varyings[]  = {
4038 		"result_PatchVerticesIn",
4039 	};
4040 	const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]);
4041 
4042 	gl.transformFeedbackVaryings(out_test_ptr->po_id, n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
4043 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
4044 
4045 	gl.attachShader(out_test_ptr->po_id, out_test_ptr->fs_id);
4046 	gl.attachShader(out_test_ptr->po_id, out_test_ptr->vs_id);
4047 
4048 	if (out_test_ptr->tcs_id != 0)
4049 	{
4050 		gl.attachShader(out_test_ptr->po_id, out_test_ptr->tcs_id);
4051 	}
4052 
4053 	if (out_test_ptr->tes_id != 0)
4054 	{
4055 		gl.attachShader(out_test_ptr->po_id, out_test_ptr->tes_id);
4056 	}
4057 
4058 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
4059 
4060 	gl.linkProgram(out_test_ptr->po_id);
4061 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
4062 
4063 	gl.getProgramiv(out_test_ptr->po_id, GL_LINK_STATUS, &link_status);
4064 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
4065 
4066 	if (link_status != GL_TRUE)
4067 	{
4068 		TCU_FAIL("Program linking failed");
4069 	}
4070 }
4071 
4072 /** Executes the test.
4073  *
4074  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4075  *
4076  *  Note the function throws exception should an error occur!
4077  *
4078  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
4079  **/
iterate(void)4080 tcu::TestNode::IterateResult TessellationShaderTCTEgl_PatchVerticesIn::iterate(void)
4081 {
4082 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4083 
4084 	/* Initialize ES test objects */
4085 	initTest();
4086 
4087 	/* Prepare for rendering */
4088 	gl.enable(GL_RASTERIZER_DISCARD);
4089 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
4090 
4091 	/* We will iterate through all added tests. */
4092 	for (_tests_const_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); ++test_iterator)
4093 	{
4094 		/* Activate test-specific program object first. */
4095 		gl.useProgram(test_iterator->po_id);
4096 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
4097 
4098 		/* Test type tells determines how the tessellation levels should be set.
4099 		 * We don't need to do anything specific if TCS+TES are in, but if no
4100 		 * TCS is present, we need to configure default amount of input patch-vertices
4101 		 * to the test-specific value.
4102 		 */
4103 		glw::GLint n_patch_vertices = 0;
4104 
4105 		switch (test_iterator->type)
4106 		{
4107 		case TESSELLATION_TEST_TYPE_TCS_TES:
4108 		{
4109 			/* We're using isolines mode which requires at least 4 input vertices per patch */
4110 			gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 4);
4111 			GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() for GL_PATCH_VERTICES_EXT failed.");
4112 
4113 			n_patch_vertices = 4;
4114 
4115 			break;
4116 		}
4117 
4118 		case TESSELLATION_TEST_TYPE_TES:
4119 		{
4120 			gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, test_iterator->input_patch_size);
4121 			GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() call failed");
4122 
4123 			n_patch_vertices = test_iterator->input_patch_size;
4124 
4125 			break;
4126 		}
4127 
4128 		default:
4129 		{
4130 			TCU_FAIL("Unrecognized test type");
4131 		}
4132 		} /* switch (test_iterator->type) */
4133 
4134 		/* Set up storage properties for the buffer object, to which XFBed data will be
4135 		 * written.
4136 		 **/
4137 		const unsigned int n_bytes_needed = sizeof(int) * 2; /* the tessellator will output two vertices */
4138 
4139 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, n_bytes_needed, NULL /* data */, GL_STATIC_DRAW);
4140 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
4141 
4142 		/* Render the test geometry */
4143 		gl.beginTransformFeedback(GL_POINTS);
4144 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
4145 		{
4146 			/* Pass a single patch only */
4147 			gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, n_patch_vertices);
4148 
4149 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
4150 		}
4151 		gl.endTransformFeedback();
4152 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
4153 
4154 		/* Now that the BO is filled with data, map it so we can check the storage's contents */
4155 		const int* mapped_data_ptr = (const int*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
4156 																   n_bytes_needed, GL_MAP_READ_BIT);
4157 
4158 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
4159 
4160 		/* Verify the contents. Make sure the value we retrieved is equal to the test-specific
4161 		 * amount of vertices per patch.
4162 		 */
4163 		for (unsigned int n_vertex = 0; n_vertex < 2 /* output vertices */; ++n_vertex)
4164 		{
4165 			unsigned int te_PatchVerticesInSize = mapped_data_ptr[n_vertex];
4166 
4167 			if (te_PatchVerticesInSize != test_iterator->input_patch_size)
4168 			{
4169 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid gl_PatchVerticesIn defined for TE stage "
4170 								   << " and result vertex index:" << n_vertex
4171 								   << " expected:" << test_iterator->input_patch_size
4172 								   << " rendered:" << te_PatchVerticesInSize << tcu::TestLog::EndMessage;
4173 
4174 				TCU_FAIL("Invalid gl_PatchVerticesIn size used in TE stage");
4175 			} /* if (comparison failed)  */
4176 		}
4177 
4178 		/* All done - unmap the storage */
4179 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4180 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
4181 	} /* for (all tests) */
4182 
4183 	/* All done */
4184 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4185 	return STOP;
4186 }
4187 
4188 } /* namespace glcts */
4189