Home | History | Annotate | Download | only in tessellation_shader
      1 /*-------------------------------------------------------------------------
      2  * OpenGL Conformance Test Suite
      3  * -----------------------------
      4  *
      5  * Copyright (c) 2014-2016 The Khronos Group Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  */ /*!
     20  * \file
     21  * \brief
     22  */ /*-------------------------------------------------------------------*/
     23 
     24 #include "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  **/
    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. */
    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. */
    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. */
    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. */
    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. */
    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. */
    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  **/
    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  **/
    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  **/
    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