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 "esextcTessellationShaderMaxPatchVertices.hpp"
25 #include "gluContextInfo.hpp"
26 #include "gluDefs.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuTestLog.hpp"
30 #include <cstddef>
31 #include <cstdlib>
32 
33 /* The test creates a patch with max patch vertices count size.
34  * The output from the tesselation stage is a single segment (2 vertices).
35  * Use this define when allocating/using the output TF buffer.
36  */
37 #define OUTPUT_VERTEX_COUNT 2
38 
39 namespace glcts
40 {
41 
42 /* Vertex Shader code */
43 const char* TessellationShaderMaxPatchVertices::m_vs_code = "${VERSION}\n"
44 															"\n"
45 															"${SHADER_IO_BLOCKS_ENABLE}\n"
46 															"\n"
47 															"precision highp float;\n"
48 															"\n"
49 															"layout(location = 0) in vec4  in_fv;\n"
50 															"layout(location = 1) in ivec4 in_iv;\n"
51 															"\n"
52 															"out Vertex\n"
53 															"{\n"
54 															"    ivec4 iv;\n"
55 															"    vec4  fv;\n"
56 															"} outVertex;\n"
57 															"\n"
58 															"void main()\n"
59 															"{\n"
60 															"    gl_Position  = in_fv;\n"
61 															"    outVertex.iv = in_iv;\n"
62 															"    outVertex.fv = in_fv;\n"
63 															"}\n";
64 
65 /* Tessellation Control Shader code (for case with explicit array size) */
66 const char* TessellationShaderMaxPatchVertices::m_tc_code =
67 	"${VERSION}\n"
68 	"\n"
69 	"${TESSELLATION_SHADER_REQUIRE}\n"
70 	"\n"
71 	"precision highp float;\n"
72 	"\n"
73 	"in Vertex\n"
74 	"{\n"
75 	"    ivec4 iv;\n"
76 	"    vec4  fv;\n"
77 	"} inVertex[];\n"
78 	"\n"
79 	"layout(vertices = 2) out;\n" /* One segment only. */
80 	"\n"
81 	"out Vertex\n"
82 	"{\n"
83 	"    ivec4 iv;\n"
84 	"    vec4  fv;\n"
85 	"} outVertex[];\n"
86 	"\n"
87 	"void main()\n"
88 	"{\n"
89 	"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
90 	"    outVertex[gl_InvocationID].iv = ivec4(0);\n"
91 	"    outVertex[gl_InvocationID].fv = vec4(0);\n"
92 	"\n"
93 	"    for (int i = 0; i < gl_PatchVerticesIn; i++)\n"
94 	"    {\n"
95 	"        outVertex[gl_InvocationID].iv += inVertex[i].iv;\n"
96 	"        outVertex[gl_InvocationID].fv += inVertex[i].fv;\n"
97 	"    }\n"
98 	"\n"
99 	"    gl_TessLevelInner[0] = 1.0;\n"
100 	"    gl_TessLevelInner[1] = 1.0;\n"
101 	"    gl_TessLevelOuter[0] = 1.0;\n"
102 	"    gl_TessLevelOuter[1] = 1.0;\n"
103 	"    gl_TessLevelOuter[2] = 1.0;\n"
104 	"    gl_TessLevelOuter[3] = 1.0;\n"
105 	"}\n";
106 
107 /* Tessellation Evaluation Shader code (for case */
108 const char* TessellationShaderMaxPatchVertices::m_te_code = "${VERSION}\n"
109 															"\n"
110 															"${TESSELLATION_SHADER_REQUIRE}\n"
111 															"\n"
112 															"precision highp float;\n"
113 															"\n"
114 															"layout (isolines, point_mode) in;\n"
115 															"\n"
116 															"in Vertex\n"
117 															"{\n"
118 															"    ivec4 iv;\n"
119 															"    vec4  fv;\n"
120 															"} inVertex[];\n"
121 															"\n"
122 															"out  vec4 result_fv;\n"
123 															"out ivec4 result_iv;\n"
124 															"\n"
125 															"void main()\n"
126 															"{\n"
127 															"    gl_Position = gl_in[0].gl_Position;\n"
128 															"    result_iv   = ivec4(0);\n"
129 															"    result_fv   = vec4(0.0);\n"
130 															"\n"
131 															"    for (int i = 0 ; i < gl_PatchVerticesIn; i++)\n"
132 															"    {\n"
133 															"        result_iv += inVertex[i].iv;\n"
134 															"        result_fv += inVertex[i].fv;\n"
135 															"    }\n"
136 															"}\n";
137 
138 /* Fragment Shader code */
139 const char* TessellationShaderMaxPatchVertices::m_fs_code = "${VERSION}\n"
140 															"\n"
141 															"void main()\n"
142 															"{\n"
143 															"}\n";
144 
145 /* Transform Feedback varyings */
146 const char* const TessellationShaderMaxPatchVertices::m_tf_varyings[] = { "result_fv", "result_iv" };
147 
148 /** Constructor
149  *
150  * @param context     Test context
151  * @param name        Test case's name
152  * @param description Test case's description
153  **/
TessellationShaderMaxPatchVertices(Context & context,const ExtParameters & extParams)154 TessellationShaderMaxPatchVertices::TessellationShaderMaxPatchVertices(Context& context, const ExtParameters& extParams)
155 	: TestCaseBase(context, extParams, "max_patch_vertices",
156 				   "Make sure it is possible to use up to gl_MaxPatchVertices vertices."
157 				   " TCS must be able to correctly access all vertices in an input patch")
158 	, m_bo_id_f_1(0)
159 	, m_bo_id_f_2(0)
160 	, m_bo_id_i_1(0)
161 	, m_bo_id_i_2(0)
162 	, m_fs_id(0)
163 	, m_po_id_1(0)
164 	, m_po_id_2(0)
165 	, m_tc_id(0)
166 	, m_te_id(0)
167 	, m_tf_id_1(0)
168 	, m_tf_id_2(0)
169 	, m_vs_id(0)
170 	, m_vao_id(0)
171 	, m_gl_max_patch_vertices(0)
172 	, m_patch_vertices_bo_f_id(0)
173 	, m_patch_vertices_bo_i_id(0)
174 	, m_patch_vertices_f(DE_NULL)
175 	, m_patch_vertices_i(DE_NULL)
176 {
177 }
178 
179 /** Deinitializes all ES objects created for the test. */
deinit(void)180 void TessellationShaderMaxPatchVertices::deinit(void)
181 {
182 	/* Deinitialize parent. */
183 	TestCaseBase::deinit();
184 
185 	if (!m_is_tessellation_shader_supported)
186 	{
187 		return;
188 	}
189 
190 	/* Dealocate input array of patch vertices. */
191 	if (m_patch_vertices_f != DE_NULL)
192 	{
193 		free(m_patch_vertices_f);
194 
195 		m_patch_vertices_f = DE_NULL;
196 	}
197 
198 	if (m_patch_vertices_i != DE_NULL)
199 	{
200 		free(m_patch_vertices_i);
201 
202 		m_patch_vertices_i = DE_NULL;
203 	}
204 
205 	/* Retrieve ES entry-points. */
206 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
207 
208 	/* Set back to default program */
209 	gl.useProgram(0);
210 
211 	/* Revert GL_PATCH_VERTICES_EXT value to the default setting */
212 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
213 
214 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
215 	{
216 		/* Revert GL_PATCH_DEFAULT_INNER_LEVEL and GL_PATCH_DEFAULT_OUTER_LEVEL pname
217 		 * values to the default settings */
218 		const float default_levels[] = { 1.0f, 1.0f, 1.0f, 1.0f };
219 
220 		gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, default_levels);
221 		gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, default_levels);
222 	}
223 
224 	/* Disable vertex attribute arrays that may have been enabled for the test */
225 	gl.disableVertexAttribArray(0);
226 	gl.disableVertexAttribArray(1);
227 
228 	/* Unbind buffer objects from TF binding points */
229 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
230 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
231 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1 /* index */, 0 /* buffer */);
232 
233 	/* Unbind transform feedback object */
234 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0 /* id */);
235 
236 	/* Disable GL_RASTERIZER_DISCARD mode */
237 	gl.disable(GL_RASTERIZER_DISCARD);
238 
239 	/* Unbind vertex array object */
240 	gl.bindVertexArray(0);
241 
242 	/* Delete OpenGL objects */
243 	if (m_bo_id_f_1 != 0)
244 	{
245 		gl.deleteBuffers(1, &m_bo_id_f_1);
246 
247 		m_bo_id_f_1 = 0;
248 	}
249 
250 	if (m_bo_id_f_2 != 0)
251 	{
252 		gl.deleteBuffers(1, &m_bo_id_f_2);
253 
254 		m_bo_id_f_2 = 0;
255 	}
256 
257 	if (m_bo_id_i_1 != 0)
258 	{
259 		gl.deleteBuffers(1, &m_bo_id_i_1);
260 
261 		m_bo_id_i_1 = 0;
262 	}
263 
264 	if (m_bo_id_i_2 != 0)
265 	{
266 		gl.deleteBuffers(1, &m_bo_id_i_2);
267 
268 		m_bo_id_i_2 = 0;
269 	}
270 
271 	if (m_patch_vertices_bo_f_id != 0)
272 	{
273 		gl.deleteBuffers(1, &m_patch_vertices_bo_f_id);
274 
275 		m_patch_vertices_bo_f_id = 0;
276 	}
277 
278 	if (m_patch_vertices_bo_i_id != 0)
279 	{
280 		gl.deleteBuffers(1, &m_patch_vertices_bo_i_id);
281 
282 		m_patch_vertices_bo_i_id = 0;
283 	}
284 
285 	if (m_vs_id != 0)
286 	{
287 		gl.deleteShader(m_vs_id);
288 
289 		m_vs_id = 0;
290 	}
291 
292 	if (m_tc_id != 0)
293 	{
294 		gl.deleteShader(m_tc_id);
295 
296 		m_tc_id = 0;
297 	}
298 
299 	if (m_te_id != 0)
300 	{
301 		gl.deleteShader(m_te_id);
302 
303 		m_te_id = 0;
304 	}
305 
306 	if (m_fs_id != 0)
307 	{
308 		gl.deleteShader(m_fs_id);
309 
310 		m_fs_id = 0;
311 	}
312 
313 	if (m_tf_id_1 != 0)
314 	{
315 		gl.deleteTransformFeedbacks(1, &m_tf_id_1);
316 
317 		m_tf_id_1 = 0;
318 	}
319 
320 	if (m_tf_id_2 != 0)
321 	{
322 		gl.deleteTransformFeedbacks(1, &m_tf_id_2);
323 
324 		m_tf_id_2 = 0;
325 	}
326 
327 	if (m_po_id_1 != 0)
328 	{
329 		gl.deleteProgram(m_po_id_1);
330 
331 		m_po_id_1 = 0;
332 	}
333 
334 	if (m_po_id_2 != 0)
335 	{
336 		gl.deleteProgram(m_po_id_2);
337 
338 		m_po_id_2 = 0;
339 	}
340 
341 	if (m_vao_id != 0)
342 	{
343 		gl.deleteVertexArrays(1, &m_vao_id);
344 
345 		m_vao_id = 0;
346 	}
347 }
348 
349 /** Initializes all ES objects and reference values for the test. */
initTest(void)350 void TessellationShaderMaxPatchVertices::initTest(void)
351 {
352 	/* This test runs for two cases:
353 	 *
354 	 * 1) The patch size is explicitly defined to be equal to gl_MaxPatchVertices.
355 	 *    (The Tessellation Control Shader gets 32 vertices, then it access them
356 	 *    and it outputs 2 vertices to Tessllation Evaluation Shader. Next Tessllation
357 	 *    Evaluation Shader sends 1 segment of an isoline  to the output).
358 	 * 2) The patch size is implicitly defined to be equal to gl_MaxPatchVertices.
359 	 *    (There is no Tessellation Control Shader. Tessllation Evaluation Shader
360 	 *    gets 32 vertices, then it access them. Next (gl_MaxPatchVertices-1) segments
361 	 *    of the isoline are send to the output.)
362 	 */
363 
364 	/* Retrieve ES entry/state points. */
365 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
366 
367 	/* Initialize vertex array object */
368 	gl.genVertexArrays(1, &m_vao_id);
369 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
370 
371 	gl.bindVertexArray(m_vao_id);
372 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
373 
374 	/* Query GL_MAX_PATCH_VERTICES_EXT value */
375 	gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices);
376 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_PATCH_VERTICES_EXT pname!");
377 
378 	/* Set maximum number of vertices in the patch. */
379 	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, m_gl_max_patch_vertices);
380 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname!");
381 
382 	/* Build programs */
383 	initProgramObjects();
384 
385 	/* Initialize tessellation buffers */
386 	initTransformFeedbackBufferObjects();
387 
388 	/* Initialize input vertices */
389 	initVertexBufferObjects();
390 
391 	/* Reference values setup */
392 	initReferenceValues();
393 }
394 
395 /** Initializes buffer objects for the test. */
initVertexBufferObjects(void)396 void TessellationShaderMaxPatchVertices::initVertexBufferObjects(void)
397 {
398 	/* Retrieve ES entry/state points. */
399 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
400 
401 	/* Input patch vertices buffer setup. */
402 	m_patch_vertices_f = (glw::GLfloat*)malloc(m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLfloat));
403 
404 	if (m_patch_vertices_f == DE_NULL)
405 	{
406 		TCU_FAIL("Memory allocation failed!");
407 	}
408 
409 	m_patch_vertices_i = (glw::GLint*)malloc(m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLint));
410 
411 	if (m_patch_vertices_i == DE_NULL)
412 	{
413 		TCU_FAIL("Memory allocation failed!");
414 	}
415 
416 	for (int i = 0; i < m_gl_max_patch_vertices * 4 /* components */; i += 4 /* components */)
417 	{
418 		m_patch_vertices_f[i]	 = 1.0f;
419 		m_patch_vertices_f[i + 1] = 2.0f;
420 		m_patch_vertices_f[i + 2] = 3.0f;
421 		m_patch_vertices_f[i + 3] = 4.0f;
422 
423 		m_patch_vertices_i[i]	 = 1;
424 		m_patch_vertices_i[i + 1] = 2;
425 		m_patch_vertices_i[i + 2] = 3;
426 		m_patch_vertices_i[i + 3] = 4;
427 	}
428 
429 	/* Vec4 vertex attribute array setup. */
430 	gl.genBuffers(1, &m_patch_vertices_bo_f_id);
431 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!");
432 
433 	gl.bindBuffer(GL_ARRAY_BUFFER, m_patch_vertices_bo_f_id);
434 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
435 
436 	gl.bufferData(GL_ARRAY_BUFFER, m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLfloat),
437 				  m_patch_vertices_f, GL_STATIC_DRAW);
438 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed!");
439 
440 	gl.vertexAttribPointer(0,		 /* index */
441 						   4,		 /* size */
442 						   GL_FLOAT, /* type */
443 						   GL_FALSE, /* normalized */
444 						   0,		 /* stride */
445 						   0);		 /* pointer */
446 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer(fv) failed!");
447 
448 	gl.enableVertexAttribArray(0);
449 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray(fv) failed!");
450 
451 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
452 
453 	/* Ivec4 vertex attribute array setup. */
454 	gl.genBuffers(1, &m_patch_vertices_bo_i_id);
455 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers(ARRAY_BUFFER) failed!");
456 
457 	gl.bindBuffer(GL_ARRAY_BUFFER, m_patch_vertices_bo_i_id);
458 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer(ARRAY_BUFFER) failed!");
459 
460 	gl.bufferData(GL_ARRAY_BUFFER, m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLint),
461 				  m_patch_vertices_i, GL_STATIC_DRAW);
462 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData(ARRAY_BUFFER) failed!");
463 
464 	gl.vertexAttribIPointer(1,		   /* index */
465 							4,		   /* size */
466 							GL_INT, 0, /* stride */
467 							0);		   /* pointer */
468 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer(iv) failed!");
469 
470 	gl.enableVertexAttribArray(1);
471 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray(iv) failed!");
472 
473 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
474 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
475 }
476 
477 /** Initializes buffer objects for the test. */
initTransformFeedbackBufferObjects(void)478 void TessellationShaderMaxPatchVertices::initTransformFeedbackBufferObjects(void)
479 {
480 	/* Retrieve ES entry/state points. */
481 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
482 
483 	/* Creating Transform Feedback buffer objects. */
484 	gl.genBuffers(1, &m_bo_id_f_1);
485 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
486 
487 	gl.genBuffers(1, &m_bo_id_f_2);
488 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
489 
490 	gl.genBuffers(1, &m_bo_id_i_1);
491 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
492 
493 	gl.genBuffers(1, &m_bo_id_i_2);
494 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
495 
496 	/* Transform feedback buffers for case 1*/
497 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1);
498 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
499 
500 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_1);
501 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
502 
503 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
504 				  ((sizeof(glw::GLfloat)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL,
505 				  GL_STATIC_DRAW);
506 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
507 
508 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_1);
509 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
510 
511 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
512 				  ((sizeof(glw::GLint)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL,
513 				  GL_STATIC_DRAW);
514 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
515 
516 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
517 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback(0) failed");
518 
519 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
520 	{
521 		/* Transform feedback buffers for case 2*/
522 		gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2);
523 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
524 
525 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_2);
526 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
527 
528 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
529 					  ((sizeof(glw::GLfloat)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL,
530 					  GL_STATIC_DRAW);
531 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
532 
533 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_2);
534 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
535 
536 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
537 					  ((sizeof(glw::GLint)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL,
538 					  GL_STATIC_DRAW);
539 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
540 
541 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
542 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback(0) failed");
543 
544 		gl.transformFeedbackVaryings(m_po_id_2, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS);
545 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!");
546 	}
547 }
548 
549 /** Initializes program objects for the test. */
initProgramObjects(void)550 void TessellationShaderMaxPatchVertices::initProgramObjects(void)
551 {
552 	/* Retrieve ES entry/state points. */
553 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
554 
555 	/* Create and configure shader objects. */
556 	m_po_id_1 = gl.createProgram();
557 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
558 
559 	m_po_id_2 = gl.createProgram();
560 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
561 
562 	/* Creating Transform Feedback objects. */
563 	gl.genTransformFeedbacks(1, &m_tf_id_1);
564 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() failed!");
565 
566 	gl.genTransformFeedbacks(1, &m_tf_id_2);
567 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() failed!");
568 
569 	/* Create and configure shader objects. */
570 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
571 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(VERTEX_SHADER) failed!");
572 
573 	m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
574 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!");
575 
576 	m_te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
577 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!");
578 
579 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
580 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!");
581 
582 	/* Transform Feedback setup case 1 (explicit arrays).*/
583 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1);
584 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
585 
586 	gl.transformFeedbackVaryings(m_po_id_1, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS);
587 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!");
588 
589 	/* Build the program object case 1 (explicit arrays).*/
590 	if (!buildProgram(m_po_id_1, m_vs_id, 1, &m_vs_code, m_tc_id, 1, &m_tc_code, m_te_id, 1, &m_te_code, m_fs_id, 1,
591 					  &m_fs_code))
592 	{
593 		TCU_FAIL("Program linking failed!");
594 	}
595 
596 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
597 	{
598 		/* Transform Feedback setup case 2 (implicit arrays).*/
599 		gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2);
600 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
601 
602 		gl.transformFeedbackVaryings(m_po_id_2, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS);
603 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!");
604 
605 		/* Build the program object case 2 (implicit arrays). */
606 		if (!buildProgram(m_po_id_2, m_vs_id, 1, &m_vs_code, m_te_id, 1, &m_te_code, m_fs_id, 1, &m_fs_code))
607 		{
608 			TCU_FAIL("Program linking failed!");
609 		}
610 	}
611 }
612 
613 /** Initializes reference values for the test. */
initReferenceValues(void)614 void TessellationShaderMaxPatchVertices::initReferenceValues(void)
615 {
616 	/* Reference values setup. */
617 	m_ref_fv_case_1[0] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 1.0f);
618 	m_ref_fv_case_1[1] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 2.0f);
619 	m_ref_fv_case_1[2] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 3.0f);
620 	m_ref_fv_case_1[3] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 4.0f);
621 
622 	m_ref_iv_case_1[0] = (m_gl_max_patch_vertices * 2 * 1);
623 	m_ref_iv_case_1[1] = (m_gl_max_patch_vertices * 2 * 2);
624 	m_ref_iv_case_1[2] = (m_gl_max_patch_vertices * 2 * 3);
625 	m_ref_iv_case_1[3] = (m_gl_max_patch_vertices * 2 * 4);
626 
627 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
628 	{
629 		m_ref_fv_case_2[0] = ((glw::GLfloat)m_gl_max_patch_vertices * 1.0f);
630 		m_ref_fv_case_2[1] = ((glw::GLfloat)m_gl_max_patch_vertices * 2.0f);
631 		m_ref_fv_case_2[2] = ((glw::GLfloat)m_gl_max_patch_vertices * 3.0f);
632 		m_ref_fv_case_2[3] = ((glw::GLfloat)m_gl_max_patch_vertices * 4.0f);
633 
634 		m_ref_iv_case_2[0] = (m_gl_max_patch_vertices * 1);
635 		m_ref_iv_case_2[1] = (m_gl_max_patch_vertices * 2);
636 		m_ref_iv_case_2[2] = (m_gl_max_patch_vertices * 3);
637 		m_ref_iv_case_2[3] = (m_gl_max_patch_vertices * 4);
638 	}
639 }
640 
641 /** Compares values of vec4 results with the reference data.
642  *
643  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed.
644  *
645  *  Note the function throws exception should an error occur!
646  *
647  *  @param description Test case's description.
648  *  @param ref_fv      Reference value.
649  *
650  *  @return true       if test passed;
651  *          false      if test failed.
652  **/
compareResults(const char * description,glw::GLfloat ref_fv[4])653 bool TessellationShaderMaxPatchVertices::compareResults(const char* description, glw::GLfloat ref_fv[4])
654 {
655 	/* Retrieve ES entry/state points. */
656 	const glw::Functions& gl		   = m_context.getRenderContext().getFunctions();
657 	const glw::GLfloat*   resultFloats = DE_NULL;
658 
659 	resultFloats = (const glw::GLfloat*)gl.mapBufferRange(
660 		GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
661 		(sizeof(glw::GLfloat) /* GLfloat size */ * 4 /* components */ * OUTPUT_VERTEX_COUNT), GL_MAP_READ_BIT);
662 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(floats) failed");
663 
664 	/* Comparison of vec4. */
665 	const glw::GLfloat epsilon	 = (glw::GLfloat)1e-5f;
666 	bool			   test_failed = false;
667 
668 	for (int i = 0; i < 4 /* components */; i++)
669 	{
670 		if (de::abs(resultFloats[i] - ref_fv[i]) > epsilon)
671 		{
672 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
673 
674 			m_testCtx.getLog() << tcu::TestLog::Message << description << " captured results "
675 							   << "vec4(" << resultFloats[0] << ", " << resultFloats[1] << ", " << resultFloats[2]
676 							   << ", " << resultFloats[3] << ") "
677 							   << "are different from the expected values "
678 							   << "vec4(" << ref_fv[0] << ", " << ref_fv[1] << ", " << ref_fv[2] << ", " << ref_fv[3]
679 							   << ")." << tcu::TestLog::EndMessage;
680 
681 			test_failed = true;
682 			break;
683 		}
684 	}
685 
686 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
687 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed!");
688 
689 	return !test_failed;
690 }
691 
692 /** Compares values of ivec4 results with the reference data.
693  *
694  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed.
695  *
696  *  Note the function throws exception should an error occur!
697  *
698  *  @param description   Test case's description.
699  *  @param ref_iv        Reference value.
700  *
701  *  @return true         if test passed.
702  *          false        if test failed.
703  **/
compareResults(const char * description,glw::GLint ref_iv[4])704 bool TessellationShaderMaxPatchVertices::compareResults(const char* description, glw::GLint ref_iv[4])
705 {
706 	/* Retrieve ES entry/state points. */
707 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
708 	const glw::GLint*	 resultInts = DE_NULL;
709 
710 	resultInts = (const glw::GLint*)gl.mapBufferRange(
711 		GL_TRANSFORM_FEEDBACK_BUFFER, 0,
712 		(sizeof(glw::GLint) /* GLfloat size */ * 4 /* components */ * OUTPUT_VERTEX_COUNT), GL_MAP_READ_BIT);
713 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(ints) failed");
714 
715 	bool test_failed = false;
716 
717 	/* Comparison of ivec4. */
718 	for (int i = 0; i < 4 /* components */; i++)
719 	{
720 		if (resultInts[i] != ref_iv[i])
721 		{
722 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
723 
724 			m_testCtx.getLog() << tcu::TestLog::Message << description << " captured results ivec4(" << resultInts[0]
725 							   << ", " << resultInts[1] << ", " << resultInts[2] << ", " << resultInts[3] << ") "
726 							   << "are different from the expected values ivec4(" << ref_iv[0] << ", " << ref_iv[1]
727 							   << ", " << ref_iv[2] << ", " << ref_iv[3] << ")." << tcu::TestLog::EndMessage;
728 
729 			test_failed = true;
730 			break;
731 		}
732 	}
733 
734 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
735 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed!");
736 
737 	return !test_failed;
738 }
739 
740 /** Executes the test.
741  *
742  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
743  *
744  *  Note the function throws exception should an error occur!
745  *
746  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
747  **/
iterate(void)748 tcu::TestNode::IterateResult TessellationShaderMaxPatchVertices::iterate(void)
749 {
750 	/* Skip if required extensions are not supported. */
751 	if (!m_is_tessellation_shader_supported)
752 	{
753 		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
754 	}
755 
756 	/* Retrieve ES entry/state points. */
757 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
758 
759 	/* Initialization */
760 	initTest();
761 
762 	/* Render setup case 1. */
763 	gl.useProgram(m_po_id_1);
764 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
765 
766 	gl.enable(GL_RASTERIZER_DISCARD);
767 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(RASTERIZER_DISCARD) failed!");
768 
769 	gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1);
770 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
771 
772 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_f_1);
773 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!");
774 
775 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_i_1);
776 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!");
777 
778 	/* Rendering case 1 with transform feedback.*/
779 	gl.beginTransformFeedback(GL_POINTS);
780 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed");
781 
782 	gl.drawArrays(m_glExtTokens.PATCHES, 0, m_gl_max_patch_vertices);
783 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
784 
785 	gl.endTransformFeedback();
786 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
787 
788 	/* Compare vec4 results from transform feedback for case 1. */
789 	bool test_passed = true;
790 
791 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_1);
792 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
793 
794 	test_passed &= compareResults("Case 1 (explicit arrays)", m_ref_fv_case_1);
795 
796 	/* Compare ivec4 results from transform feedback for case 2. */
797 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_1);
798 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
799 
800 	test_passed &= compareResults("Case 1 (explicit arrays)", m_ref_iv_case_1);
801 
802 	// Case 2 tests with no TCS (default TCS is expected to be used).
803 	// Since this is not allowed by ES 3.1, just skip it.
804 	// Leaving the code for Desktop
805 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
806 	{
807 		/* Set up rendering for case 2. */
808 		gl.useProgram(m_po_id_2);
809 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
810 
811 		gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2);
812 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
813 
814 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id_f_2);
815 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!");
816 
817 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1 /* index */, m_bo_id_i_2);
818 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!");
819 
820 		/* Tessellation Control Levels setup. */
821 		const glw::GLfloat inner[] = { 1.0, 1.0 };
822 		const glw::GLfloat outer[] = { 1.0, 1.0, 1.0, 1.0 };
823 
824 		gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, outer);
825 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() failed!");
826 
827 		gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, inner);
828 		GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() failed!");
829 
830 		/* Rendering case 2 with transform feedback. */
831 		gl.beginTransformFeedback(GL_POINTS);
832 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_POINTS) failed");
833 
834 		gl.drawArrays(GL_PATCHES, 0, m_gl_max_patch_vertices);
835 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
836 
837 		gl.endTransformFeedback();
838 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
839 
840 		/* Compare vec4 results from transform feedback for case 2. */
841 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_2);
842 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
843 
844 		test_passed &= compareResults("Case 2 (implicit arrays)", m_ref_fv_case_2);
845 
846 		/* Compare ivec4 results from transform feedback for case 2. */
847 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_2);
848 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
849 
850 		test_passed &= compareResults("Case 2 (implicit arrays)", m_ref_iv_case_2);
851 	}
852 	/* All done */
853 	if (test_passed)
854 	{
855 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
856 	}
857 
858 	return STOP;
859 }
860 
861 } /* namespace glcts */
862