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