Home | History | Annotate | Download | only in geometry_shader
      1 /*-------------------------------------------------------------------------
      2  * OpenGL Conformance Test Suite
      3  * -----------------------------
      4  *
      5  * Copyright (c) 2015-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 #include "esextcGeometryShaderAPI.hpp"
     24 
     25 #include "gluDefs.hpp"
     26 #include "glwEnums.hpp"
     27 #include "glwFunctions.hpp"
     28 #include "tcuTestLog.hpp"
     29 #include <cstring>
     30 
     31 namespace glcts
     32 {
     33 
     34 static const char* dummy_fs_code = "${VERSION}\n"
     35 								   "\n"
     36 								   "precision highp float;\n"
     37 								   "\n"
     38 								   "out vec4 result;\n"
     39 								   "\n"
     40 								   "void main()\n"
     41 								   "{\n"
     42 								   "    result = vec4(1.0);\n"
     43 								   "}\n";
     44 
     45 static const char* dummy_gs_code = "${VERSION}\n"
     46 								   "${GEOMETRY_SHADER_REQUIRE}\n"
     47 								   "\n"
     48 								   "layout (points)                   in;\n"
     49 								   "layout (points, max_vertices = 1) out;\n"
     50 								   "\n"
     51 								   "${OUT_PER_VERTEX_DECL}"
     52 								   "${IN_DATA_DECL}"
     53 								   "void main()\n"
     54 								   "{\n"
     55 								   "${POSITION_WITH_IN_DATA}"
     56 								   "    EmitVertex();\n"
     57 								   "}\n";
     58 
     59 static const char* dummy_vs_code = "${VERSION}\n"
     60 								   "\n"
     61 								   "${OUT_PER_VERTEX_DECL}"
     62 								   "\n"
     63 								   "void main()\n"
     64 								   "{\n"
     65 								   "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
     66 								   "}\n";
     67 
     68 /* createShaderProgramv conformance test shaders */
     69 const char* GeometryShaderCreateShaderProgramvTest::fs_code = "${VERSION}\n"
     70 															  "\n"
     71 															  "precision highp float;\n"
     72 															  "\n"
     73 															  "out vec4 result;\n"
     74 															  "\n"
     75 															  "void main()\n"
     76 															  "{\n"
     77 															  "    result = vec4(0.0, 1.0, 0.0, 0.0);\n"
     78 															  "}\n";
     79 
     80 const char* GeometryShaderCreateShaderProgramvTest::gs_code = "${VERSION}\n"
     81 															  "${GEOMETRY_SHADER_REQUIRE}\n"
     82 															  "\n"
     83 															  "layout (points)                           in;\n"
     84 															  "layout (triangle_strip, max_vertices = 4) out;\n"
     85 															  "\n"
     86 															  "${OUT_PER_VERTEX_DECL}"
     87 															  "\n"
     88 															  "void main()\n"
     89 															  "{\n"
     90 															  "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
     91 															  "    EmitVertex();\n"
     92 															  "\n"
     93 															  "    gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
     94 															  "    EmitVertex();\n"
     95 															  "\n"
     96 															  "    gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
     97 															  "    EmitVertex();\n"
     98 															  "\n"
     99 															  "    gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
    100 															  "    EmitVertex();\n"
    101 															  "    EndPrimitive();\n"
    102 															  "}\n";
    103 
    104 const char* GeometryShaderCreateShaderProgramvTest::vs_code = "${VERSION}\n"
    105 															  "\n"
    106 															  "${OUT_PER_VERTEX_DECL}"
    107 															  "\n"
    108 															  "void main()\n"
    109 															  "{\n"
    110 															  "    gl_Position = vec4(-10.0, -10.0, -10.0, 0.0);\n"
    111 															  "}\n";
    112 
    113 const unsigned int GeometryShaderCreateShaderProgramvTest::m_to_height = 4;
    114 const unsigned int GeometryShaderCreateShaderProgramvTest::m_to_width  = 4;
    115 
    116 /** Constructor
    117  *
    118  * @param context       Test context
    119  * @param extParams     Not used.
    120  * @param name          Test case's name
    121  * @param description   Test case's description
    122  **/
    123 GeometryShaderCreateShaderProgramvTest::GeometryShaderCreateShaderProgramvTest(Context&				context,
    124 																			   const ExtParameters& extParams,
    125 																			   const char*			name,
    126 																			   const char*			description)
    127 	: TestCaseBase(context, extParams, name, description)
    128 	, m_fbo_id(0)
    129 	, m_fs_po_id(0)
    130 	, m_gs_po_id(0)
    131 	, m_pipeline_object_id(0)
    132 	, m_to_id(0)
    133 	, m_vao_id(0)
    134 	, m_vs_po_id(0)
    135 {
    136 }
    137 
    138 /** Deinitializes GLES objects created during the test. */
    139 void GeometryShaderCreateShaderProgramvTest::deinit()
    140 {
    141 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    142 
    143 	if (m_fbo_id != 0)
    144 	{
    145 		gl.deleteFramebuffers(1, &m_fbo_id);
    146 
    147 		m_fbo_id = 0;
    148 	}
    149 
    150 	if (m_fs_po_id != 0)
    151 	{
    152 		gl.deleteProgram(m_fs_po_id);
    153 
    154 		m_fs_po_id = 0;
    155 	}
    156 
    157 	if (m_gs_po_id != 0)
    158 	{
    159 		gl.deleteProgram(m_gs_po_id);
    160 
    161 		m_gs_po_id = 0;
    162 	}
    163 
    164 	if (m_pipeline_object_id != 0)
    165 	{
    166 		gl.deleteProgramPipelines(1, &m_pipeline_object_id);
    167 
    168 		m_pipeline_object_id = 0;
    169 	}
    170 
    171 	if (m_to_id != 0)
    172 	{
    173 		gl.deleteTextures(1, &m_to_id);
    174 
    175 		m_to_id = 0;
    176 	}
    177 
    178 	if (m_vao_id != 0)
    179 	{
    180 		gl.deleteVertexArrays(1, &m_vao_id);
    181 
    182 		m_vao_id = 0;
    183 	}
    184 
    185 	if (m_vs_po_id != 0)
    186 	{
    187 		gl.deleteProgram(m_vs_po_id);
    188 
    189 		m_vs_po_id = 0;
    190 	}
    191 
    192 	/* Release base class */
    193 	TestCaseBase::deinit();
    194 }
    195 
    196 /** Initializes a framebuffer object used by the conformance test. */
    197 void GeometryShaderCreateShaderProgramvTest::initFBO()
    198 {
    199 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    200 
    201 	/* Generate a FBO */
    202 	gl.genFramebuffers(1, &m_fbo_id);
    203 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
    204 
    205 	/* Generate a TO */
    206 	gl.genTextures(1, &m_to_id);
    207 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
    208 
    209 	/* Set the TO up */
    210 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
    211 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
    212 
    213 	gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
    214 					GL_RGBA8, m_to_width, m_to_height);
    215 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
    216 
    217 	/* Set up the FBO */
    218 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
    219 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
    220 
    221 	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0); /* level */
    222 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
    223 
    224 	/* Set up the viewport */
    225 	gl.viewport(0, /* x */
    226 				0, /* y */
    227 				m_to_width, m_to_height);
    228 
    229 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
    230 }
    231 
    232 /* Initializes a pipeline object used by the conformance test */
    233 void GeometryShaderCreateShaderProgramvTest::initPipelineObject()
    234 {
    235 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    236 
    237 	DE_ASSERT(m_fs_po_id != 0 && m_gs_po_id != 0 && m_vs_po_id != 0);
    238 
    239 	gl.genProgramPipelines(1, &m_pipeline_object_id);
    240 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
    241 
    242 	gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
    243 	gl.useProgramStages(m_pipeline_object_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
    244 	gl.useProgramStages(m_pipeline_object_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
    245 
    246 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
    247 }
    248 
    249 /** Executes the test.
    250  *
    251  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    252  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    253  *  Note the function throws exception should an error occur!
    254  **/
    255 tcu::TestNode::IterateResult GeometryShaderCreateShaderProgramvTest::iterate()
    256 {
    257 	const glw::Functions& gl		  = m_context.getRenderContext().getFunctions();
    258 	const unsigned int	n_so_po_ids = 3;
    259 	bool				  result	  = true;
    260 	glw::GLuint			  so_po_ids[n_so_po_ids];
    261 
    262 	/* This test should only run if EXT_geometry_shader is supported. */
    263 	if (!m_is_geometry_shader_extension_supported)
    264 	{
    265 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    266 	}
    267 
    268 	/* Initialize off-screen rendering */
    269 	initFBO();
    270 
    271 	/* Form shader sources */
    272 	std::string fs_specialized_code = specializeShader(1,
    273 													   /* parts */ &fs_code);
    274 	const char* fs_specialized_code_raw = fs_specialized_code.c_str();
    275 	std::string gs_specialized_code		= specializeShader(1,
    276 													   /* parts */ &gs_code);
    277 	const char* gs_specialized_code_raw = gs_specialized_code.c_str();
    278 	std::string vs_specialized_code		= specializeShader(1,
    279 													   /* parts */ &vs_code);
    280 	const char* vs_specialized_code_raw = vs_specialized_code.c_str();
    281 
    282 	/* Try to create an invalid geometry shader program first */
    283 	glw::GLint link_status = GL_TRUE;
    284 
    285 	m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
    286 										 &gs_code);
    287 
    288 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
    289 
    290 	if (m_gs_po_id == 0)
    291 	{
    292 		m_testCtx.getLog() << tcu::TestLog::Message << "glCreateShaderProgramv() call returned 0."
    293 						   << tcu::TestLog::EndMessage;
    294 
    295 		result = false;
    296 		goto end;
    297 	}
    298 
    299 	gl.getProgramiv(m_gs_po_id, GL_LINK_STATUS, &link_status);
    300 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
    301 
    302 	if (link_status != GL_FALSE)
    303 	{
    304 		m_testCtx.getLog() << tcu::TestLog::Message << "An invalid shader program was linked successfully."
    305 						   << tcu::TestLog::EndMessage;
    306 
    307 		result = false;
    308 		goto end;
    309 	}
    310 
    311 	gl.deleteProgram(m_gs_po_id);
    312 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed.");
    313 
    314 	/* Create shader programs */
    315 	m_fs_po_id = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, /* count */
    316 										 &fs_specialized_code_raw);
    317 	m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
    318 										 &gs_specialized_code_raw);
    319 	m_vs_po_id = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, /* count */
    320 										 &vs_specialized_code_raw);
    321 
    322 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call(s) failed.");
    323 
    324 	if (m_fs_po_id == 0 || m_gs_po_id == 0 || m_vs_po_id == 0)
    325 	{
    326 		m_testCtx.getLog() << tcu::TestLog::Message << "At least one glCreateShaderProgramv() call returned 0."
    327 						   << tcu::TestLog::EndMessage;
    328 
    329 		result = false;
    330 		goto end;
    331 	}
    332 
    333 	/* Make sure all shader programs were linked successfully */
    334 	so_po_ids[0] = m_fs_po_id;
    335 	so_po_ids[1] = m_gs_po_id;
    336 	so_po_ids[2] = m_vs_po_id;
    337 
    338 	for (unsigned int n_po_id = 0; n_po_id != n_so_po_ids; ++n_po_id)
    339 	{
    340 		gl.getProgramiv(so_po_ids[n_po_id], GL_LINK_STATUS, &link_status);
    341 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
    342 
    343 		if (link_status != GL_TRUE)
    344 		{
    345 			m_testCtx.getLog() << tcu::TestLog::Message << "A valid shader program with id [" << so_po_ids[n_po_id]
    346 							   << "] was not linked successfully." << tcu::TestLog::EndMessage;
    347 
    348 			result = false;
    349 			goto end;
    350 		}
    351 	}
    352 
    353 	/* Set up the vertex array object */
    354 	gl.genVertexArrays(1, &m_vao_id);
    355 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
    356 
    357 	gl.bindVertexArray(m_vao_id);
    358 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
    359 
    360 	/* Set up the pipeline object */
    361 	initPipelineObject();
    362 
    363 	/* Render a full-screen quad */
    364 	gl.bindProgramPipeline(m_pipeline_object_id);
    365 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
    366 
    367 	gl.drawArrays(GL_POINTS, 0, /* first */
    368 				  1);			/* count */
    369 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
    370 
    371 	/* Verify the rendering result */
    372 	unsigned char result_data[m_to_width * m_to_height * 4 /* rgba */];
    373 
    374 	gl.readPixels(0, /* x */
    375 				  0, /* y */
    376 				  m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, result_data);
    377 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
    378 
    379 	for (unsigned int y = 0; y < m_to_height; ++y)
    380 	{
    381 		unsigned char* traveller_ptr = result_data + 4 * y;
    382 
    383 		for (unsigned int x = 0; x < m_to_width; ++x)
    384 		{
    385 			if (traveller_ptr[0] != 0 || traveller_ptr[1] != 255 || traveller_ptr[2] != 0 || traveller_ptr[3] != 0)
    386 			{
    387 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid result texel found at (" << x << ", " << y
    388 								   << ")." << tcu::TestLog::EndMessage;
    389 
    390 				result = false;
    391 			}
    392 
    393 			traveller_ptr += 4; /* rgba */
    394 		}
    395 	}
    396 
    397 end:
    398 	if (result)
    399 	{
    400 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    401 	}
    402 	else
    403 	{
    404 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    405 	}
    406 
    407 	return STOP;
    408 }
    409 
    410 /** Constructor
    411  *
    412  * @param context       Test context
    413  * @param extParams     Not used.
    414  * @param name          Test case's name
    415  * @param description   Test case's description
    416  **/
    417 GeometryShaderGetShaderivTest::GeometryShaderGetShaderivTest(Context& context, const ExtParameters& extParams,
    418 															 const char* name, const char* description)
    419 	: TestCaseBase(context, extParams, name, description), m_gs_id(0)
    420 {
    421 }
    422 
    423 /** Deinitializes GLES objects created during the test. */
    424 void GeometryShaderGetShaderivTest::deinit()
    425 {
    426 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    427 
    428 	if (m_gs_id != 0)
    429 	{
    430 		gl.deleteShader(m_gs_id);
    431 
    432 		m_gs_id = 0;
    433 	}
    434 
    435 	/* Release base class */
    436 	TestCaseBase::deinit();
    437 }
    438 
    439 /** Executes the test.
    440  *
    441  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    442  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    443  *  Note the function throws exception should an error occur!
    444  **/
    445 tcu::TestNode::IterateResult GeometryShaderGetShaderivTest::iterate()
    446 {
    447 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
    448 	bool				  result = true;
    449 
    450 	/* This test should only run if EXT_geometry_shader is supported. */
    451 	if (!m_is_geometry_shader_extension_supported)
    452 	{
    453 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    454 	}
    455 
    456 	/* Create a GS */
    457 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
    458 
    459 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
    460 
    461 	/* Check the type reported for the SO */
    462 	glw::GLint shader_type = GL_NONE;
    463 
    464 	gl.getShaderiv(m_gs_id, GL_SHADER_TYPE, &shader_type);
    465 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
    466 
    467 	if ((glw::GLenum)shader_type != m_glExtTokens.GEOMETRY_SHADER)
    468 	{
    469 		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid shader type [" << shader_type
    470 						   << "] reported for a Geometry Shader" << tcu::TestLog::EndMessage;
    471 
    472 		result = false;
    473 	}
    474 
    475 	if (result)
    476 	{
    477 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    478 	}
    479 	else
    480 	{
    481 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    482 	}
    483 
    484 	return STOP;
    485 }
    486 
    487 /** Constructor
    488  *
    489  * @param context       Test context
    490  * @param extParams     Not used.
    491  * @param name          Test case's name
    492  * @param description   Test case's description
    493  **/
    494 GeometryShaderGetProgramivTest::GeometryShaderGetProgramivTest(Context& context, const ExtParameters& extParams,
    495 															   const char* name, const char* description)
    496 	: TestCaseBase(context, extParams, name, description), m_po_id(0)
    497 {
    498 }
    499 
    500 /** Deinitializes GLES objects created during the test. */
    501 void GeometryShaderGetProgramivTest::deinit()
    502 {
    503 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    504 
    505 	if (m_po_id != 0)
    506 	{
    507 		gl.deleteProgram(m_po_id);
    508 
    509 		m_po_id = 0;
    510 	}
    511 
    512 	/* Release base class */
    513 	TestCaseBase::deinit();
    514 }
    515 
    516 /** Executes the test.
    517  *
    518  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    519  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    520  *  Note the function throws exception should an error occur!
    521  **/
    522 tcu::TestNode::IterateResult GeometryShaderGetProgramivTest::iterate()
    523 {
    524 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
    525 	bool				  result = true;
    526 
    527 	/* This test should only run if EXT_geometry_shader is supported. */
    528 	if (!m_is_geometry_shader_extension_supported)
    529 	{
    530 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    531 	}
    532 
    533 	/* Create a program object */
    534 	m_po_id = gl.createProgram();
    535 
    536 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
    537 
    538 	/* Verify that GS-specific queries cause a GL_INVALID_OPERATION error */
    539 	const glw::GLenum pnames[] = { m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE,
    540 								   m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE,
    541 								   m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS };
    542 	const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
    543 
    544 	for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
    545 	{
    546 		glw::GLenum error_code = GL_NO_ERROR;
    547 		glw::GLenum pname	  = pnames[n_pname];
    548 		glw::GLint  rv		   = -1;
    549 
    550 		gl.getProgramiv(m_po_id, pname, &rv);
    551 
    552 		error_code = gl.getError();
    553 
    554 		if (error_code != GL_INVALID_OPERATION)
    555 		{
    556 			m_testCtx.getLog() << tcu::TestLog::Message << "No error generated by glGetProgramiv() for pname [" << pname
    557 							   << "]" << tcu::TestLog::EndMessage;
    558 
    559 			result = false;
    560 		}
    561 	} /* for (all pnames) */
    562 
    563 	if (result)
    564 	{
    565 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    566 	}
    567 	else
    568 	{
    569 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    570 	}
    571 
    572 	return STOP;
    573 }
    574 
    575 /** Constructor
    576  *
    577  * @param context       Test context
    578  * @param extParams     Not used.
    579  * @param name          Test case's name
    580  * @param description   Test case's description
    581  **/
    582 GeometryShaderGetProgramiv2Test::GeometryShaderGetProgramiv2Test(Context& context, const ExtParameters& extParams,
    583 																 const char* name, const char* description)
    584 	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_po_id(0), m_vs_id(0)
    585 {
    586 }
    587 
    588 /** Deinitializes GLES objects created during the test. */
    589 void GeometryShaderGetProgramiv2Test::deinit()
    590 {
    591 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    592 
    593 	if (m_fs_id != 0)
    594 	{
    595 		gl.deleteShader(m_fs_id);
    596 
    597 		m_fs_id = 0;
    598 	}
    599 
    600 	if (m_po_id != 0)
    601 	{
    602 		gl.deleteProgram(m_po_id);
    603 
    604 		m_po_id = 0;
    605 	}
    606 
    607 	if (m_vs_id != 0)
    608 	{
    609 		gl.deleteShader(m_vs_id);
    610 
    611 		m_vs_id = 0;
    612 	}
    613 
    614 	/* Release base class */
    615 	TestCaseBase::deinit();
    616 }
    617 
    618 /** Executes the test.
    619  *
    620  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    621  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    622  *  Note the function throws exception should an error occur!
    623  **/
    624 tcu::TestNode::IterateResult GeometryShaderGetProgramiv2Test::iterate()
    625 {
    626 	const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
    627 	const glw::GLenum pnames[] = { m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE,
    628 								   m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE,
    629 								   m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS };
    630 	const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
    631 	bool			   result   = true;
    632 
    633 	/* This test should only run if EXT_geometry_shader is supported. */
    634 	if (!m_is_geometry_shader_extension_supported)
    635 	{
    636 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    637 	}
    638 
    639 	/* Initialize the program object */
    640 	std::string specialized_dummy_fs = specializeShader(1,
    641 														/* parts */ &dummy_fs_code);
    642 	const char* specialized_dummy_fs_raw = specialized_dummy_fs.c_str();
    643 	std::string specialized_dummy_vs	 = specializeShader(1,
    644 														/* parts */ &dummy_vs_code);
    645 	const char* specialized_dummy_vs_raw = specialized_dummy_vs.c_str();
    646 
    647 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
    648 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
    649 
    650 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
    651 
    652 	m_po_id = gl.createProgram();
    653 
    654 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
    655 
    656 	if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1, &specialized_dummy_fs_raw, m_vs_id, 1,
    657 									&specialized_dummy_vs_raw))
    658 	{
    659 		m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build a dummy test program object"
    660 						   << tcu::TestLog::EndMessage;
    661 
    662 		result = false;
    663 		goto end;
    664 	}
    665 
    666 	/* Verify that GS-specific queries cause a GL_INVALID_OPERATION error
    667 	 * for a linked PO lacking the GS stage.
    668 	 */
    669 	for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
    670 	{
    671 		glw::GLenum error_code = GL_NO_ERROR;
    672 		glw::GLenum pname	  = pnames[n_pname];
    673 		glw::GLint  rv		   = -1;
    674 
    675 		gl.getProgramiv(m_po_id, pname, &rv);
    676 
    677 		error_code = gl.getError();
    678 
    679 		if (error_code != GL_INVALID_OPERATION)
    680 		{
    681 			m_testCtx.getLog() << tcu::TestLog::Message << "No error generated by glGetProgramiv() for pname [" << pname
    682 							   << "]" << tcu::TestLog::EndMessage;
    683 
    684 			result = false;
    685 		}
    686 	} /* for (all pnames) */
    687 
    688 end:
    689 	if (result)
    690 	{
    691 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    692 	}
    693 	else
    694 	{
    695 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    696 	}
    697 
    698 	return STOP;
    699 }
    700 
    701 /** Constructor
    702  *
    703  * @param context       Test context
    704  * @param extParams     Not used.
    705  * @param name          Test case's name
    706  * @param description   Test case's description
    707  **/
    708 GeometryShaderGetProgramiv3Test::GeometryShaderGetProgramiv3Test(Context& context, const ExtParameters& extParams,
    709 																 const char* name, const char* description)
    710 	: TestCaseBase(context, extParams, name, description)
    711 	, m_fs_id(0)
    712 	, m_fs_po_id(0)
    713 	, m_gs_id(0)
    714 	, m_gs_po_id(0)
    715 	, m_pipeline_object_id(0)
    716 	, m_po_id(0)
    717 	, m_vs_id(0)
    718 	, m_vs_po_id(0)
    719 {
    720 }
    721 
    722 /* Compiles a shader object using caller-specified data.
    723  *
    724  * @param so_id   ID of a Shader Object to compile.
    725  * @param so_body Body to use for the compilation process.
    726  *
    727  * @return true if the compilation succeeded, false otherwise */
    728 bool GeometryShaderGetProgramiv3Test::buildShader(glw::GLuint so_id, const char* so_body)
    729 {
    730 	glw::GLint			  compile_status = GL_FALSE;
    731 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
    732 	bool				  result		 = false;
    733 
    734 	gl.shaderSource(so_id, 1,			/* count */
    735 					&so_body, DE_NULL); /* length */
    736 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
    737 
    738 	gl.compileShader(so_id);
    739 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
    740 
    741 	gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
    742 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
    743 
    744 	result = (compile_status == GL_TRUE);
    745 
    746 	return result;
    747 }
    748 
    749 /** Builds a single shader program object using caller-specified data.
    750  *
    751  *  @param out_spo_id Deref will be set to the ID of the created shader program object.
    752  *                    Must not be NULL.
    753  *  @param spo_bits   Bits to be passed to the glCreateShaderProgramv() call.
    754  *  @param spo_body   Body to use for the glCreateShaderProgramv() call.
    755  *
    756  *  @return true if the shader program object was linked successfully, false otherwise.
    757  */
    758 bool GeometryShaderGetProgramiv3Test::buildShaderProgram(glw::GLuint* out_spo_id, glw::GLenum spo_bits,
    759 														 const char* spo_body)
    760 {
    761 	const glw::Functions& gl		  = m_context.getRenderContext().getFunctions();
    762 	glw::GLint			  link_status = GL_FALSE;
    763 	bool				  result	  = true;
    764 
    765 	*out_spo_id = gl.createShaderProgramv(spo_bits, 1, /* count */
    766 										  &spo_body);
    767 
    768 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
    769 
    770 	gl.getProgramiv(*out_spo_id, GL_LINK_STATUS, &link_status);
    771 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
    772 
    773 	result = (link_status == GL_TRUE);
    774 
    775 	return result;
    776 }
    777 
    778 /** Deinitializes GLES objects created during the test. */
    779 void GeometryShaderGetProgramiv3Test::deinit()
    780 {
    781 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    782 
    783 	deinitPO();
    784 	deinitSOs(true);
    785 	deinitSPOs(true);
    786 
    787 	if (m_pipeline_object_id != 0)
    788 	{
    789 		gl.deleteProgramPipelines(1, &m_pipeline_object_id);
    790 
    791 		m_pipeline_object_id = 0;
    792 	}
    793 
    794 	/* Release base class */
    795 	TestCaseBase::deinit();
    796 }
    797 
    798 /** Deinitializes a program object created for the conformance test. */
    799 void GeometryShaderGetProgramiv3Test::deinitPO()
    800 {
    801 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    802 
    803 	if (m_po_id != 0)
    804 	{
    805 		gl.deleteProgram(m_po_id);
    806 
    807 		m_po_id = 0;
    808 	}
    809 }
    810 
    811 /** Deinitializes shader objects created for the conformance test. */
    812 void GeometryShaderGetProgramiv3Test::deinitSOs(bool release_all_SOs)
    813 {
    814 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    815 
    816 	if (m_fs_id != 0 && release_all_SOs)
    817 	{
    818 		gl.deleteShader(m_fs_id);
    819 
    820 		m_fs_id = 0;
    821 	}
    822 
    823 	if (m_gs_id != 0)
    824 	{
    825 		gl.deleteShader(m_gs_id);
    826 
    827 		m_gs_id = 0;
    828 	}
    829 
    830 	if (m_vs_id != 0 && release_all_SOs)
    831 	{
    832 		gl.deleteShader(m_vs_id);
    833 
    834 		m_vs_id = 0;
    835 	}
    836 }
    837 
    838 /** Deinitializes shader program objects created for the conformance test. */
    839 void GeometryShaderGetProgramiv3Test::deinitSPOs(bool release_all_SPOs)
    840 {
    841 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    842 
    843 	if (m_fs_po_id != 0 && release_all_SPOs)
    844 	{
    845 		gl.deleteProgram(m_fs_po_id);
    846 
    847 		m_fs_po_id = 0;
    848 	}
    849 
    850 	if (m_gs_po_id != 0)
    851 	{
    852 		gl.deleteProgram(m_gs_po_id);
    853 
    854 		m_gs_po_id = 0;
    855 	}
    856 
    857 	if (m_vs_po_id != 0 && release_all_SPOs)
    858 	{
    859 		gl.deleteProgram(m_vs_po_id);
    860 
    861 		m_vs_po_id = 0;
    862 	}
    863 }
    864 
    865 /** Retrieves ES SL layout qualifier, corresponding to user-specified
    866  *  primitive type.
    867  *
    868  *  @param primitive_type Primitive type (described by a GLenum value)
    869  *                        to use for the query.
    870  *
    871  *  @return Requested layout qualifier.
    872  */
    873 std::string GeometryShaderGetProgramiv3Test::getLayoutQualifierForPrimitiveType(glw::GLenum primitive_type)
    874 {
    875 	std::string result;
    876 
    877 	switch (primitive_type)
    878 	{
    879 	case GL_LINE_STRIP:
    880 		result = "line_strip";
    881 		break;
    882 	case GL_LINES_ADJACENCY:
    883 		result = "lines_adjacency";
    884 		break;
    885 	case GL_POINTS:
    886 		result = "points";
    887 		break;
    888 	case GL_TRIANGLES:
    889 		result = "triangles";
    890 		break;
    891 	case GL_TRIANGLE_STRIP:
    892 		result = "triangle_strip";
    893 		break;
    894 
    895 	default:
    896 	{
    897 		DE_ASSERT(0);
    898 	}
    899 	} /* switch (primitive_type) */
    900 
    901 	return result;
    902 }
    903 
    904 /** Retrieves body of a geometry shadet to be used for the conformance test.
    905  *  The body is generated, according to the properties described by the
    906  *  run descriptor passed as an argument.
    907  *
    908  *  @param run Test run descriptor.
    909  *
    910  *  @return Requested string.
    911  */
    912 std::string GeometryShaderGetProgramiv3Test::getGSCode(const _run& run)
    913 {
    914 	std::stringstream code_sstream;
    915 
    916 	code_sstream << "${VERSION}\n"
    917 					"${GEOMETRY_SHADER_REQUIRE}\n"
    918 					"\n"
    919 					"layout("
    920 				 << getLayoutQualifierForPrimitiveType(run.input_primitive_type) << ", "
    921 																					"invocations = "
    922 				 << run.invocations << ") in;\n"
    923 									   "layout("
    924 				 << getLayoutQualifierForPrimitiveType(run.output_primitive_type) << ", "
    925 																					 "max_vertices = "
    926 				 << run.max_vertices << ") out;\n"
    927 										"\n"
    928 										"out gl_PerVertex {\n"
    929 										"    vec4 gl_Position;\n"
    930 										"};\n"
    931 										"\n"
    932 										"void main()\n"
    933 										"{\n"
    934 										"    for (int n = 0; n < "
    935 				 << run.max_vertices << "; ++n)\n"
    936 										"    {\n"
    937 										"        gl_Position = vec4(n, 0.0, 0.0, 1.0);\n"
    938 										"        EmitVertex();\n"
    939 										"    }\n"
    940 										"\n"
    941 										"    EndPrimitive();\n"
    942 										"}\n";
    943 
    944 	return code_sstream.str();
    945 }
    946 
    947 /** Initializes internal _runs member with test iteration settings for all test runs. */
    948 void GeometryShaderGetProgramiv3Test::initTestRuns()
    949 {
    950 	/*                   input primitive type | invocations | max vertices | output primitive type *
    951 	 *----------------------------------------+-------------+--------------+-----------------------*/
    952 	_runs.push_back(_run(GL_LINES_ADJACENCY, 3, 16, GL_POINTS));
    953 	_runs.push_back(_run(GL_TRIANGLES, 12, 37, GL_LINE_STRIP));
    954 	_runs.push_back(_run(GL_POINTS, 31, 75, GL_TRIANGLE_STRIP));
    955 }
    956 
    957 /** Executes the test.
    958  *
    959  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    960  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    961  *  Note the function throws exception should an error occur!
    962  **/
    963 tcu::TestNode::IterateResult GeometryShaderGetProgramiv3Test::iterate()
    964 {
    965 	const glw::Functions& gl					  = m_context.getRenderContext().getFunctions();
    966 	glw::GLint			  gs_spo_id				  = 0;
    967 	unsigned int		  n_run					  = 0;
    968 	unsigned int		  n_separable_object_case = 0;
    969 	bool				  result				  = true;
    970 
    971 	/* This test should only run if EXT_geometry_shader is supported. */
    972 	if (!m_is_geometry_shader_extension_supported)
    973 	{
    974 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    975 	}
    976 
    977 	/* Prepare specialized versions of dummy fragment & vertex shaders */
    978 	std::string dummy_fs_specialized = specializeShader(1,
    979 														/* parts */ &dummy_fs_code);
    980 	const char* dummy_fs_specialized_raw = dummy_fs_specialized.c_str();
    981 	std::string dummy_vs_specialized	 = specializeShader(1, &dummy_vs_code);
    982 	const char* dummy_vs_specialized_raw = dummy_vs_specialized.c_str();
    983 
    984 	/* Set up the fragment & the vertex shaders */
    985 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
    986 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
    987 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
    988 
    989 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
    990 
    991 	if (!buildShader(m_fs_id, dummy_fs_specialized_raw) || !buildShader(m_vs_id, dummy_vs_specialized_raw))
    992 	{
    993 		m_testCtx.getLog() << tcu::TestLog::Message << "Either FS or VS failed to build." << tcu::TestLog::EndMessage;
    994 
    995 		result = false;
    996 		goto end;
    997 	}
    998 
    999 	/* Set up the test program object */
   1000 	m_po_id = gl.createProgram();
   1001 
   1002 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   1003 
   1004 	gl.attachShader(m_po_id, m_fs_id);
   1005 	gl.attachShader(m_po_id, m_gs_id);
   1006 	gl.attachShader(m_po_id, m_vs_id);
   1007 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
   1008 
   1009 	/* Set up the fragment & the vertex shader programs */
   1010 	if (!buildShaderProgram(&m_fs_po_id, GL_FRAGMENT_SHADER, dummy_fs_specialized_raw) ||
   1011 		!buildShaderProgram(&m_vs_po_id, GL_VERTEX_SHADER, dummy_vs_specialized_raw))
   1012 	{
   1013 		m_testCtx.getLog() << tcu::TestLog::Message << "Either FS or VS SPOs failed to build."
   1014 						   << tcu::TestLog::EndMessage;
   1015 
   1016 		result = false;
   1017 		goto end;
   1018 	}
   1019 
   1020 	/* Set up test runs */
   1021 	initTestRuns();
   1022 
   1023 	/* The test should check both a geometry shader program object and a full-blown PO
   1024 	 * consisting of FS, GS and VS. */
   1025 	for (n_separable_object_case = 0; n_separable_object_case < 2; /* PO, SPO cases */
   1026 		 ++n_separable_object_case)
   1027 	{
   1028 		bool should_use_separable_object = (n_separable_object_case != 0);
   1029 
   1030 		/* Iterate over all test runs */
   1031 		for (n_run = 0; n_run < _runs.size(); ++n_run)
   1032 		{
   1033 			const _run& current_run			= _runs[n_run];
   1034 			std::string gs_code				= getGSCode(current_run);
   1035 			const char* gs_code_raw			= gs_code.c_str();
   1036 			std::string gs_code_specialized = specializeShader(1, /* parts */
   1037 															   &gs_code_raw);
   1038 			const char* gs_code_specialized_raw = gs_code_specialized.c_str();
   1039 
   1040 			if (should_use_separable_object)
   1041 			{
   1042 				/* Deinitialize any objects that may have been created in previous iterations */
   1043 				deinitSPOs(false);
   1044 
   1045 				/* Set up the geometry shader program object */
   1046 				if (!buildShaderProgram(&m_gs_po_id, GL_GEOMETRY_SHADER, gs_code_specialized_raw))
   1047 				{
   1048 					m_testCtx.getLog() << tcu::TestLog::Message << "Failed to compile a geometry shader program object"
   1049 									   << tcu::TestLog::EndMessage;
   1050 
   1051 					result = false;
   1052 					goto end;
   1053 				}
   1054 			} /* if (should_use_pipeline_object) */
   1055 			else
   1056 			{
   1057 				gl.bindProgramPipeline(0);
   1058 				GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
   1059 
   1060 				/* Set up the geometry shader object */
   1061 				if (!buildShader(m_gs_id, gs_code_specialized_raw))
   1062 				{
   1063 					m_testCtx.getLog() << tcu::TestLog::Message << "Failed to compile a geometry shader object."
   1064 									   << tcu::TestLog::EndMessage;
   1065 
   1066 					result = false;
   1067 					goto end;
   1068 				}
   1069 
   1070 				/* Set up the program object */
   1071 				glw::GLint link_status = GL_FALSE;
   1072 
   1073 				gl.linkProgram(m_po_id);
   1074 				GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
   1075 
   1076 				gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
   1077 
   1078 				if (link_status == GL_FALSE)
   1079 				{
   1080 					m_testCtx.getLog() << tcu::TestLog::Message << "Test program object failed to link"
   1081 									   << tcu::TestLog::EndMessage;
   1082 
   1083 					result = false;
   1084 					goto end;
   1085 				}
   1086 
   1087 				/* Bind the PO to the rendering context */
   1088 				gl.useProgram(m_po_id);
   1089 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   1090 			}
   1091 
   1092 			/* Execute the queries */
   1093 			glw::GLuint po_id								= (should_use_separable_object) ? m_gs_po_id : m_po_id;
   1094 			glw::GLint  result_geometry_linked_vertices_out = 0;
   1095 			glw::GLint  result_geometry_linked_input_type   = 0;
   1096 			glw::GLint  result_geometry_linked_output_type  = 0;
   1097 			glw::GLint  result_geometry_shader_invocations  = 0;
   1098 
   1099 			gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, &result_geometry_linked_vertices_out);
   1100 			GLU_EXPECT_NO_ERROR(gl.getError(),
   1101 								"glGetProgramiv() call failed for GL_GEOMETRY_LINKED_VERTICES_OUT_EXT query.");
   1102 
   1103 			gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE, &result_geometry_linked_input_type);
   1104 			GLU_EXPECT_NO_ERROR(gl.getError(),
   1105 								"glGetProgramiv() call failed for GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query.");
   1106 
   1107 			gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE, &result_geometry_linked_output_type);
   1108 			GLU_EXPECT_NO_ERROR(gl.getError(),
   1109 								"glGetProgramiv() call failed for GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT query.");
   1110 
   1111 			gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS, &result_geometry_shader_invocations);
   1112 			GLU_EXPECT_NO_ERROR(gl.getError(),
   1113 								"glGetProgramiv() call failed for GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query.");
   1114 
   1115 			if (current_run.input_primitive_type != (glw::GLenum)result_geometry_linked_input_type)
   1116 			{
   1117 				m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query value "
   1118 								   << "[" << result_geometry_linked_input_type
   1119 								   << "]"
   1120 									  " does not match the test run setting "
   1121 									  "["
   1122 								   << current_run.input_primitive_type << "]" << tcu::TestLog::EndMessage;
   1123 
   1124 				result = false;
   1125 			}
   1126 
   1127 			if (current_run.invocations != result_geometry_shader_invocations)
   1128 			{
   1129 				m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_SHADER_INVOCATIONS_EXT query value "
   1130 								   << "[" << result_geometry_shader_invocations
   1131 								   << "]"
   1132 									  " does not match the test run setting "
   1133 									  "["
   1134 								   << current_run.input_primitive_type << "]" << tcu::TestLog::EndMessage;
   1135 
   1136 				result = false;
   1137 			}
   1138 
   1139 			if (current_run.max_vertices != result_geometry_linked_vertices_out)
   1140 			{
   1141 				m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_VERTICES_OUT query value "
   1142 								   << "[" << result_geometry_linked_vertices_out
   1143 								   << "]"
   1144 									  " does not match the test run setting "
   1145 									  "["
   1146 								   << current_run.max_vertices << "]" << tcu::TestLog::EndMessage;
   1147 
   1148 				result = false;
   1149 			}
   1150 
   1151 			if (current_run.output_primitive_type != (glw::GLenum)result_geometry_linked_output_type)
   1152 			{
   1153 				m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT query value "
   1154 								   << "[" << result_geometry_linked_output_type
   1155 								   << "]"
   1156 									  " does not match the test run setting "
   1157 									  "["
   1158 								   << current_run.output_primitive_type << "]" << tcu::TestLog::EndMessage;
   1159 
   1160 				result = false;
   1161 			}
   1162 		} /* for (all test runs) */
   1163 	}	 /* for (PO & SPO cases) */
   1164 
   1165 	/* One more check: build a pipeline object which only defines a FS & VS stages,
   1166 	 *                 and check what GS SPO ID the object reports. */
   1167 	gl.genProgramPipelines(1, &m_pipeline_object_id);
   1168 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
   1169 
   1170 	gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
   1171 	gl.useProgramStages(m_pipeline_object_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
   1172 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
   1173 
   1174 	gl.getProgramPipelineiv(m_pipeline_object_id, m_glExtTokens.GEOMETRY_SHADER, &gs_spo_id);
   1175 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed.");
   1176 
   1177 	if (gs_spo_id != 0)
   1178 	{
   1179 		m_testCtx.getLog() << tcu::TestLog::Message << "Pipeline object reported [" << gs_spo_id << "]"
   1180 						   << " for GL_GEOMETRY_SHADER_EXT query, even though no GS SPO was bound."
   1181 						   << tcu::TestLog::EndMessage;
   1182 
   1183 		result = false;
   1184 	}
   1185 
   1186 end:
   1187 	if (result)
   1188 	{
   1189 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1190 	}
   1191 	else
   1192 	{
   1193 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   1194 	}
   1195 
   1196 	return STOP;
   1197 }
   1198 
   1199 /** Constructor
   1200  *
   1201  * @param context       Test context
   1202  * @param extParams     Not used.
   1203  * @param name          Test case's name
   1204  * @param description   Test case's description
   1205  **/
   1206 GeometryShaderDrawCallWithFSAndGS::GeometryShaderDrawCallWithFSAndGS(Context& context, const ExtParameters& extParams,
   1207 																	 const char* name, const char* description)
   1208 	: TestCaseBase(context, extParams, name, description)
   1209 	, m_fs_po_id(0)
   1210 	, m_gs_po_id(0)
   1211 	, m_pipeline_object_id(0)
   1212 	, m_vao_id(0)
   1213 {
   1214 }
   1215 
   1216 /** Deinitializes GLES objects created during the test. */
   1217 void GeometryShaderDrawCallWithFSAndGS::deinit()
   1218 {
   1219 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1220 
   1221 	if (m_fs_po_id != 0)
   1222 	{
   1223 		gl.deleteProgram(m_fs_po_id);
   1224 
   1225 		m_fs_po_id = 0;
   1226 	}
   1227 
   1228 	if (m_gs_po_id != 0)
   1229 	{
   1230 		gl.deleteProgram(m_gs_po_id);
   1231 
   1232 		m_gs_po_id = 0;
   1233 	}
   1234 
   1235 	if (m_pipeline_object_id != 0)
   1236 	{
   1237 		gl.deleteProgramPipelines(1, &m_pipeline_object_id);
   1238 
   1239 		m_pipeline_object_id = 0;
   1240 	}
   1241 
   1242 	if (m_vao_id != 0)
   1243 	{
   1244 		gl.deleteVertexArrays(1, &m_vao_id);
   1245 
   1246 		m_vao_id = 0;
   1247 	}
   1248 
   1249 	/* Release base class */
   1250 	TestCaseBase::deinit();
   1251 }
   1252 
   1253 /** Executes the test.
   1254  *
   1255  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   1256  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   1257  *  Note the function throws exception should an error occur!
   1258  **/
   1259 tcu::TestNode::IterateResult GeometryShaderDrawCallWithFSAndGS::iterate()
   1260 {
   1261 	glw::GLenum			  error_code = GL_NO_ERROR;
   1262 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
   1263 	bool				  result	 = true;
   1264 
   1265 	/* This test should only run if EXT_geometry_shader is supported. */
   1266 	if (!m_is_geometry_shader_extension_supported)
   1267 	{
   1268 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   1269 	}
   1270 
   1271 	/* Create & bind a VAO */
   1272 	gl.genVertexArrays(1, &m_vao_id);
   1273 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   1274 
   1275 	gl.bindVertexArray(m_vao_id);
   1276 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   1277 
   1278 	/* Create shader program objects */
   1279 	std::string code_fs_specialized = specializeShader(1, /* parts */
   1280 													   &dummy_fs_code);
   1281 	const char* code_fs_specialized_raw = code_fs_specialized.c_str();
   1282 	std::string code_gs_specialized		= specializeShader(1, /* parts */
   1283 													   &dummy_gs_code);
   1284 	const char* code_gs_specialized_raw = code_gs_specialized.c_str();
   1285 	glw::GLint  link_status				= GL_FALSE;
   1286 
   1287 	m_fs_po_id = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, /* count */
   1288 										 &code_fs_specialized_raw);
   1289 	m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
   1290 										 &code_gs_specialized_raw);
   1291 
   1292 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call(s) failed.");
   1293 
   1294 	gl.getProgramiv(m_fs_po_id, GL_LINK_STATUS, &link_status);
   1295 
   1296 	if (link_status != GL_TRUE)
   1297 	{
   1298 		m_testCtx.getLog() << tcu::TestLog::Message << "Dummy fragment shader program failed to link."
   1299 						   << tcu::TestLog::EndMessage;
   1300 
   1301 		result = false;
   1302 		goto end;
   1303 	}
   1304 
   1305 	gl.getProgramiv(m_gs_po_id, GL_LINK_STATUS, &link_status);
   1306 
   1307 	if (link_status != GL_TRUE)
   1308 	{
   1309 		m_testCtx.getLog() << tcu::TestLog::Message << "Dummy geometry shader program failed to link."
   1310 						   << tcu::TestLog::EndMessage;
   1311 
   1312 		result = false;
   1313 		goto end;
   1314 	}
   1315 
   1316 	/* Create & set up a pipeline object */
   1317 	gl.genProgramPipelines(1, &m_pipeline_object_id);
   1318 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
   1319 
   1320 	gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
   1321 	gl.useProgramStages(m_pipeline_object_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
   1322 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
   1323 
   1324 	gl.bindProgramPipeline(m_pipeline_object_id);
   1325 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
   1326 
   1327 	/* Try to do a draw call */
   1328 	gl.drawArrays(GL_POINTS, 0, /* first */
   1329 				  1);			/* count */
   1330 
   1331 	error_code = gl.getError();
   1332 	if (error_code != GL_INVALID_OPERATION)
   1333 	{
   1334 		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid draw call generated an error code [" << error_code
   1335 						   << "]"
   1336 							  " which is different from the expected GL_INVALID_OPERATION."
   1337 						   << tcu::TestLog::EndMessage;
   1338 
   1339 		result = false;
   1340 	}
   1341 
   1342 end:
   1343 	// m_pipeline_object_id is generated in this function, need to be freed
   1344 	if (m_pipeline_object_id)
   1345 	{
   1346 		gl.deleteProgramPipelines(1, &m_pipeline_object_id);
   1347 		m_pipeline_object_id = 0;
   1348 	}
   1349 
   1350 	// m_gs_po_id is generated in this function, need to be freed
   1351 	if (m_gs_po_id)
   1352 	{
   1353 		gl.deleteProgram(m_gs_po_id);
   1354 		m_gs_po_id = 0;
   1355 	}
   1356 
   1357 	// m_fs_po_id is generated in this function, need to be freed
   1358 	if (m_fs_po_id)
   1359 	{
   1360 		gl.deleteProgram(m_fs_po_id);
   1361 		m_fs_po_id = 0;
   1362 	}
   1363 
   1364 	// m_vao_id is generated in this function, need to be freed
   1365 	if (m_vao_id)
   1366 	{
   1367 		gl.deleteVertexArrays(1, &m_vao_id);
   1368 		m_vao_id = 0;
   1369 	}
   1370 
   1371 	/* All done */
   1372 	if (result)
   1373 	{
   1374 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1375 	}
   1376 	else
   1377 	{
   1378 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   1379 	}
   1380 
   1381 	return STOP;
   1382 }
   1383 
   1384 /** Constructor
   1385  *
   1386  * @param context       Test context
   1387  * @param extParams     Not used.
   1388  * @param name          Test case's name
   1389  * @param description   Test case's description
   1390  **/
   1391 GeometryShaderMaxImageUniformsTest::GeometryShaderMaxImageUniformsTest(Context& context, const ExtParameters& extParams,
   1392 																	   const char* name, const char* description)
   1393 	: TestCaseBase(context, extParams, name, description)
   1394 	, m_fs_id(0)
   1395 	, m_gl_max_geometry_image_uniforms_ext_value(0)
   1396 	, m_gs_id(0)
   1397 	, m_po_id(0)
   1398 	, m_texture_ids(NULL)
   1399 	, m_tfbo_id(0)
   1400 	, m_vao_id(0)
   1401 	, m_vs_id(0)
   1402 {
   1403 	//Bug-15063 Only GLSL 4.50 supports opaque types
   1404 	if (m_glslVersion >= glu::GLSL_VERSION_130)
   1405 	{
   1406 		m_glslVersion = glu::GLSL_VERSION_450;
   1407 	}
   1408 }
   1409 
   1410 /** Deinitializes GLES objects created during the test. */
   1411 void GeometryShaderMaxImageUniformsTest::deinit()
   1412 {
   1413 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1414 
   1415 	if (m_fs_id != 0)
   1416 	{
   1417 		gl.deleteShader(m_fs_id);
   1418 
   1419 		m_fs_id = 0;
   1420 	}
   1421 
   1422 	if (m_gs_id != 0)
   1423 	{
   1424 		gl.deleteShader(m_gs_id);
   1425 
   1426 		m_gs_id = 0;
   1427 	}
   1428 
   1429 	if (m_po_id != 0)
   1430 	{
   1431 		gl.deleteProgram(m_po_id);
   1432 
   1433 		m_po_id = 0;
   1434 	}
   1435 
   1436 	if (m_texture_ids != NULL)
   1437 	{
   1438 		gl.deleteTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids);
   1439 
   1440 		delete[] m_texture_ids;
   1441 		m_texture_ids = NULL;
   1442 	}
   1443 
   1444 	if (m_tfbo_id != 0)
   1445 	{
   1446 		gl.deleteBuffers(1, &m_tfbo_id);
   1447 		m_tfbo_id = 0;
   1448 	}
   1449 
   1450 	if (m_vao_id != 0)
   1451 	{
   1452 		gl.deleteVertexArrays(1, &m_vao_id);
   1453 		m_vao_id = 0;
   1454 	}
   1455 
   1456 	if (m_vs_id != 0)
   1457 	{
   1458 		gl.deleteShader(m_vs_id);
   1459 
   1460 		m_vs_id = 0;
   1461 	}
   1462 
   1463 	/* Set GL_PACK_ALIGNMENT to default value. */
   1464 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4 /*default value taken from specification*/);
   1465 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname.");
   1466 
   1467 	/* Release base class */
   1468 	TestCaseBase::deinit();
   1469 }
   1470 
   1471 /* Retrieves test-specific geometry shader source code.
   1472  *
   1473  * @return Requested string.
   1474  */
   1475 std::string GeometryShaderMaxImageUniformsTest::getGSCode()
   1476 {
   1477 	std::stringstream code_sstream;
   1478 
   1479 	/* Form the GS */
   1480 	code_sstream << "${VERSION}\n"
   1481 					"${GEOMETRY_SHADER_REQUIRE}\n"
   1482 					"\n"
   1483 					"layout (points)                   in;\n"
   1484 					"layout (points, max_vertices = 1) out;\n"
   1485 					"\n"
   1486 					"precision highp iimage2D;\n"
   1487 					"\n"
   1488 					"ivec4 counter = ivec4(0);\n"
   1489 					"\n";
   1490 
   1491 	for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
   1492 	{
   1493 		code_sstream << "layout(binding = " << n_img << ", r32i) uniform iimage2D img" << n_img << ";\n";
   1494 	}
   1495 
   1496 	code_sstream << "\n"
   1497 					"void main()\n"
   1498 					"{\n";
   1499 
   1500 	for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
   1501 	{
   1502 		code_sstream << "    counter += imageLoad(img" << n_img << ", ivec2(0, 0));\n";
   1503 	}
   1504 
   1505 	code_sstream << "\n"
   1506 					"    gl_Position = vec4(float(counter.x), 0.0, 0.0, 1.0);\n"
   1507 					"    EmitVertex();\n"
   1508 					"}\n";
   1509 
   1510 	/* Form a specialized version of the GS source code */
   1511 	std::string gs_code				= code_sstream.str();
   1512 	const char* gs_code_raw			= gs_code.c_str();
   1513 	std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw);
   1514 
   1515 	return gs_code_specialized;
   1516 }
   1517 
   1518 /** Executes the test.
   1519  *
   1520  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   1521  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   1522  *  Note the function throws exception should an error occur!
   1523  **/
   1524 tcu::TestNode::IterateResult GeometryShaderMaxImageUniformsTest::iterate()
   1525 {
   1526 	glw::GLint		   counter						 = 0;
   1527 	glw::GLint		   expectedValue				 = 0;
   1528 	bool			   has_shader_compilation_failed = true;
   1529 	glw::GLfloat*	  ptr							 = DE_NULL;
   1530 	bool			   result						 = true;
   1531 	const glw::GLchar* feedbackVaryings[]			 = { "gl_Position" };
   1532 
   1533 	std::string fs_code_specialized		= "";
   1534 	const char* fs_code_specialized_raw = DE_NULL;
   1535 	std::string gs_code_specialized		= "";
   1536 	const char* gs_code_specialized_raw = DE_NULL;
   1537 	std::string vs_code_specialized		= "";
   1538 	const char* vs_code_specialized_raw = DE_NULL;
   1539 
   1540 	/* This test should only run if EXT_geometry_shader is supported. */
   1541 	if (!m_is_geometry_shader_extension_supported)
   1542 	{
   1543 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   1544 	}
   1545 
   1546 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1547 
   1548 	/* Retrieve GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname value */
   1549 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_IMAGE_UNIFORMS, &m_gl_max_geometry_image_uniforms_ext_value);
   1550 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname");
   1551 
   1552 	/* Retrieve GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT pname value */
   1553 	glw::GLint m_gl_max_geometry_texture_image_units_ext_value = 0;
   1554 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &m_gl_max_geometry_texture_image_units_ext_value);
   1555 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname");
   1556 
   1557 	/* Check if m_gl_max_geometry_image_uniforms_value is less than or equal zero. */
   1558 	if (m_gl_max_geometry_image_uniforms_ext_value <= 0)
   1559 	{
   1560 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
   1561 						   << "[" << m_gl_max_geometry_image_uniforms_ext_value
   1562 						   << "]"
   1563 							  " is less than or equal zero. Image uniforms in Geometry Shader"
   1564 							  " are not supported."
   1565 						   << tcu::TestLog::EndMessage;
   1566 
   1567 		if (m_gl_max_geometry_image_uniforms_ext_value == 0)
   1568 		{
   1569 			throw tcu::NotSupportedError("GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT is 0");
   1570 		}
   1571 		else
   1572 		{
   1573 			result = false;
   1574 			goto end;
   1575 		}
   1576 	}
   1577 
   1578 	/* Check if m_gl_max_geometry_texture_image_units_value is less than m_gl_max_geometry_image_uniforms_value. */
   1579 	if (m_gl_max_geometry_texture_image_units_ext_value < m_gl_max_geometry_image_uniforms_ext_value)
   1580 	{
   1581 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
   1582 						   << "[" << m_gl_max_geometry_image_uniforms_ext_value
   1583 						   << "]"
   1584 							  " is greater than GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT query value "
   1585 							  "["
   1586 						   << m_gl_max_geometry_texture_image_units_ext_value << "]." << tcu::TestLog::EndMessage;
   1587 
   1588 		result = false;
   1589 		goto end;
   1590 	}
   1591 
   1592 	/* Create a program object. */
   1593 	m_po_id = gl.createProgram();
   1594 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   1595 
   1596 	/* Create shader objects. */
   1597 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   1598 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   1599 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   1600 
   1601 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   1602 
   1603 	/* Configure which outputs should be captured by Transform Feedback. */
   1604 	gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
   1605 
   1606 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
   1607 
   1608 	/* Try to link the test program object */
   1609 	fs_code_specialized		= specializeShader(1, &dummy_fs_code);
   1610 	fs_code_specialized_raw = fs_code_specialized.c_str();
   1611 
   1612 	gs_code_specialized		= getGSCode();
   1613 	gs_code_specialized_raw = gs_code_specialized.c_str();
   1614 
   1615 	vs_code_specialized		= specializeShader(1, &dummy_vs_code);
   1616 	vs_code_specialized_raw = vs_code_specialized.c_str();
   1617 
   1618 	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
   1619 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
   1620 									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
   1621 									&fs_code_specialized_raw, &has_shader_compilation_failed))
   1622 	{
   1623 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
   1624 
   1625 		result = false;
   1626 		goto end;
   1627 	}
   1628 
   1629 	/* Use program. */
   1630 	gl.useProgram(m_po_id);
   1631 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   1632 
   1633 	/* Allocate memory for m_max_image_units_value Texture Objects. */
   1634 	m_texture_ids = new glw::GLuint[m_gl_max_geometry_image_uniforms_ext_value];
   1635 
   1636 	/* Generate m_max_image_units_value Texture Objects. */
   1637 	gl.genTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids);
   1638 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
   1639 
   1640 	/* Set GL_PACK_ALIGNMENT to 1. */
   1641 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
   1642 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname.");
   1643 
   1644 	/* Bind integer 2D texture objects of resolution 1x1 to image units. */
   1645 	for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
   1646 	{
   1647 		glw::GLint texture = m_texture_ids[n_img];
   1648 		glw::GLint value   = n_img + 1;
   1649 
   1650 		gl.bindTexture(GL_TEXTURE_2D, texture);
   1651 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
   1652 
   1653 		gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_R32I, 1 /*width*/, 1 /*height*/);
   1654 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
   1655 
   1656 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /*level*/, 0 /*xoffset*/, 0 /*yoffset*/, 1 /*width*/, 1 /*height*/,
   1657 						 GL_RED_INTEGER, GL_INT, &value);
   1658 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
   1659 
   1660 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   1661 		GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
   1662 
   1663 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   1664 		GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
   1665 
   1666 		gl.bindImageTexture(n_img, texture, 0 /*level*/, GL_FALSE /*is layered?*/, 0 /*layer*/, GL_READ_ONLY, GL_R32I);
   1667 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed.");
   1668 	}
   1669 
   1670 	/* Configure VAO. */
   1671 	gl.genVertexArrays(1, &m_vao_id);
   1672 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   1673 
   1674 	gl.bindVertexArray(m_vao_id);
   1675 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   1676 
   1677 	/* Create a Buffer Object for Transform Feedback's outputs. */
   1678 	gl.genBuffers(1, &m_tfbo_id);
   1679 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
   1680 
   1681 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
   1682 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
   1683 
   1684 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, NULL, GL_STATIC_READ);
   1685 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   1686 
   1687 	/* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
   1688 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tfbo_id);
   1689 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
   1690 
   1691 	/* Disable rasterization and make a draw call. After that, turn on rasterization. */
   1692 	gl.enable(GL_RASTERIZER_DISCARD);
   1693 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
   1694 
   1695 	gl.beginTransformFeedback(GL_POINTS);
   1696 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
   1697 
   1698 	gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
   1699 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
   1700 
   1701 	gl.endTransformFeedback();
   1702 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
   1703 
   1704 	gl.disable(GL_RASTERIZER_DISCARD);
   1705 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
   1706 
   1707 	/* Retrieve value from Transform Feedback. */
   1708 	counter = 0;
   1709 	ptr		= (glw::GLfloat*)gl.mapBufferRange(
   1710 		GL_ARRAY_BUFFER, 0, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
   1711 
   1712 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   1713 
   1714 	counter = int(ptr[0] + 0.5f);
   1715 
   1716 	gl.unmapBuffer(GL_ARRAY_BUFFER);
   1717 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   1718 
   1719 	/* Calculate expected value. */
   1720 	expectedValue = m_gl_max_geometry_image_uniforms_ext_value * (m_gl_max_geometry_image_uniforms_ext_value + 1) / 2;
   1721 
   1722 	if (counter != expectedValue)
   1723 	{
   1724 		result = false;
   1725 	}
   1726 
   1727 end:
   1728 	if (result)
   1729 	{
   1730 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1731 	}
   1732 	else
   1733 	{
   1734 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   1735 	}
   1736 
   1737 	return STOP;
   1738 }
   1739 
   1740 /** Constructor
   1741  *
   1742  * @param context       Test context
   1743  * @param extParams     Not used.
   1744  * @param name          Test case's name
   1745  * @param description   Test case's description
   1746  **/
   1747 GeometryShaderMaxShaderStorageBlocksTest::GeometryShaderMaxShaderStorageBlocksTest(Context&				context,
   1748 																				   const ExtParameters& extParams,
   1749 																				   const char*			name,
   1750 																				   const char*			description)
   1751 	: TestCaseBase(context, extParams, name, description)
   1752 	, m_fs_id(0)
   1753 	, m_gl_max_geometry_shader_storage_blocks_ext_value(0)
   1754 	, m_gs_id(0)
   1755 	, m_po_id(0)
   1756 	, m_ssbo_id(0)
   1757 	, m_tfbo_id(0)
   1758 	, m_vao_id(0)
   1759 	, m_vs_id(0)
   1760 {
   1761 }
   1762 
   1763 /** Deinitializes GLES objects created during the test. */
   1764 void GeometryShaderMaxShaderStorageBlocksTest::deinit()
   1765 {
   1766 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1767 
   1768 	if (m_fs_id != 0)
   1769 	{
   1770 		gl.deleteShader(m_fs_id);
   1771 		m_fs_id = 0;
   1772 	}
   1773 
   1774 	if (m_gs_id != 0)
   1775 	{
   1776 		gl.deleteShader(m_gs_id);
   1777 		m_gs_id = 0;
   1778 	}
   1779 
   1780 	if (m_po_id != 0)
   1781 	{
   1782 		gl.deleteProgram(m_po_id);
   1783 		m_po_id = 0;
   1784 	}
   1785 
   1786 	if (m_ssbo_id != 0)
   1787 	{
   1788 		gl.deleteBuffers(1, &m_ssbo_id);
   1789 		m_ssbo_id = 0;
   1790 	}
   1791 
   1792 	if (m_tfbo_id != 0)
   1793 	{
   1794 		gl.deleteBuffers(1, &m_tfbo_id);
   1795 		m_tfbo_id = 0;
   1796 	}
   1797 
   1798 	if (m_vao_id != 0)
   1799 	{
   1800 		gl.deleteVertexArrays(1, &m_vao_id);
   1801 		m_vao_id = 0;
   1802 	}
   1803 
   1804 	if (m_vs_id != 0)
   1805 	{
   1806 		gl.deleteShader(m_vs_id);
   1807 		m_vs_id = 0;
   1808 	}
   1809 
   1810 	/* Release base class */
   1811 	TestCaseBase::deinit();
   1812 }
   1813 
   1814 /* Retrieves test-specific geometry shader source code.
   1815  *
   1816  * @return Requested string.
   1817  */
   1818 std::string GeometryShaderMaxShaderStorageBlocksTest::getGSCode()
   1819 {
   1820 	std::stringstream code_sstream;
   1821 
   1822 	/* Form the GS */
   1823 	code_sstream << "${VERSION}\n"
   1824 					"${GEOMETRY_SHADER_REQUIRE}\n"
   1825 					"\n"
   1826 					"layout (points)                   in;\n"
   1827 					"layout (points, max_vertices = 1) out;\n"
   1828 					"\n"
   1829 					"int counter = 0;\n"
   1830 					"\n";
   1831 
   1832 	for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
   1833 	{
   1834 		code_sstream << "layout(binding = " << n_ssb << ") buffer ssb" << n_ssb << " \n{\n"
   1835 					 << "    int value;\n"
   1836 					 << "} S_SSB" << n_ssb << ";\n\n";
   1837 	}
   1838 
   1839 	code_sstream << "\n"
   1840 					"void main()\n"
   1841 					"{\n";
   1842 
   1843 	for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
   1844 	{
   1845 		code_sstream << "    counter += S_SSB" << n_ssb << ".value++;\n";
   1846 	}
   1847 
   1848 	code_sstream << "\n"
   1849 					"    gl_Position = vec4(float(counter), 0.0, 0.0, 1.0);\n"
   1850 					"    EmitVertex();\n"
   1851 					"}\n";
   1852 
   1853 	/* Form a specialized version of the GS source code */
   1854 	std::string gs_code				= code_sstream.str();
   1855 	const char* gs_code_raw			= gs_code.c_str();
   1856 	std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw);
   1857 
   1858 	return gs_code_specialized;
   1859 }
   1860 
   1861 /** Executes the test.
   1862  *
   1863  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   1864  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   1865  *  Note the function throws exception should an error occur!
   1866  **/
   1867 tcu::TestNode::IterateResult GeometryShaderMaxShaderStorageBlocksTest::iterate()
   1868 {
   1869 	glw::GLint		   counter						 = 0;
   1870 	glw::GLint		   expectedValue				 = 0;
   1871 	const glw::GLchar* feedbackVaryings[]			 = { "gl_Position" };
   1872 	bool			   has_shader_compilation_failed = true;
   1873 	const glw::GLfloat initial_buffer_data[4]		 = { 0.0f, 0.0f, 0.0f, 0.0f };
   1874 	glw::GLint		   int_alignment				 = 0;
   1875 	const glw::GLint   int_size						 = sizeof(glw::GLint);
   1876 	glw::GLint*		   ptrSSBO_data					 = DE_NULL;
   1877 	glw::GLfloat*	  ptrTF_data					 = DE_NULL;
   1878 	bool			   result						 = true;
   1879 	glw::GLint		   ssbo_alignment				 = 0;
   1880 	glw::GLint*		   ssbo_data					 = DE_NULL;
   1881 	glw::GLint		   ssbo_data_size				 = 0;
   1882 
   1883 	std::string fs_code_specialized		= "";
   1884 	const char* fs_code_specialized_raw = DE_NULL;
   1885 	std::string gs_code_specialized		= "";
   1886 	const char* gs_code_specialized_raw = DE_NULL;
   1887 	std::string vs_code_specialized		= "";
   1888 	const char* vs_code_specialized_raw = DE_NULL;
   1889 
   1890 	/* This test should only run if EXT_geometry_shader is supported. */
   1891 	if (!m_is_geometry_shader_extension_supported)
   1892 	{
   1893 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   1894 	}
   1895 
   1896 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1897 
   1898 	/* Retrieve GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname value */
   1899 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
   1900 				   &m_gl_max_geometry_shader_storage_blocks_ext_value);
   1901 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname");
   1902 
   1903 	/* Retrieve GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname value */
   1904 	glw::GLint m_gl_max_shader_storage_buffer_bindings_value = 0;
   1905 
   1906 	gl.getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &m_gl_max_shader_storage_buffer_bindings_value);
   1907 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname");
   1908 
   1909 	/* Check if m_gl_max_shader_storage_blocks_value is less than or equal zero. */
   1910 	if (m_gl_max_geometry_shader_storage_blocks_ext_value <= 0)
   1911 	{
   1912 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
   1913 						   << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
   1914 						   << "]"
   1915 							  " is less than or equal zero. Shader Storage Blocks"
   1916 							  " in Geometry Shader are not supported."
   1917 						   << tcu::TestLog::EndMessage;
   1918 
   1919 		if (m_gl_max_geometry_shader_storage_blocks_ext_value == 0)
   1920 		{
   1921 			throw tcu::NotSupportedError("GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT is 0");
   1922 		}
   1923 		else
   1924 		{
   1925 			result = false;
   1926 			goto end;
   1927 		}
   1928 	}
   1929 
   1930 	/* Check if m_gl_max_shader_storage_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
   1931 	if (m_gl_max_shader_storage_buffer_bindings_value < m_gl_max_geometry_shader_storage_blocks_ext_value)
   1932 	{
   1933 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
   1934 						   << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
   1935 						   << "]"
   1936 							  " is greater than GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS query value "
   1937 							  "["
   1938 						   << m_gl_max_shader_storage_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
   1939 
   1940 		result = false;
   1941 		goto end;
   1942 	}
   1943 
   1944 	/* Create a program object. */
   1945 	m_po_id = gl.createProgram();
   1946 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   1947 
   1948 	/* Create shader objects. */
   1949 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   1950 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   1951 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   1952 
   1953 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   1954 
   1955 	/* Configure which outputs should be captured by Transform Feedback. */
   1956 	gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
   1957 
   1958 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
   1959 
   1960 	/* Try to link the test program object */
   1961 	fs_code_specialized		= specializeShader(1, &dummy_fs_code);
   1962 	fs_code_specialized_raw = fs_code_specialized.c_str();
   1963 
   1964 	gs_code_specialized		= getGSCode();
   1965 	gs_code_specialized_raw = gs_code_specialized.c_str();
   1966 
   1967 	vs_code_specialized		= specializeShader(1, &dummy_vs_code);
   1968 	vs_code_specialized_raw = vs_code_specialized.c_str();
   1969 
   1970 	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
   1971 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
   1972 									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
   1973 									&fs_code_specialized_raw, &has_shader_compilation_failed))
   1974 	{
   1975 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
   1976 
   1977 		result = false;
   1978 		goto end;
   1979 	}
   1980 
   1981 	/* Prepare data for Shader Storage Buffer Object. */
   1982 	gl.getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_alignment);
   1983 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
   1984 
   1985 	int_alignment  = ssbo_alignment / int_size;
   1986 	ssbo_data_size = m_gl_max_geometry_shader_storage_blocks_ext_value * ssbo_alignment;
   1987 	ssbo_data	  = new glw::GLint[ssbo_data_size];
   1988 
   1989 	if ((ssbo_alignment % int_size) != 0)
   1990 	{
   1991 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT query value "
   1992 													   "["
   1993 						   << ssbo_alignment << "]"
   1994 												"divide with remainder by the size of GLint "
   1995 												"["
   1996 						   << int_size << "]" << tcu::TestLog::EndMessage;
   1997 
   1998 		result = false;
   1999 		goto end;
   2000 	}
   2001 
   2002 	for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
   2003 	{
   2004 		ssbo_data[i * int_alignment] = i + 1;
   2005 	}
   2006 
   2007 	/* Create Shader Storage Buffer Object. */
   2008 	gl.genBuffers(1, &m_ssbo_id);
   2009 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
   2010 
   2011 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo_id);
   2012 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
   2013 
   2014 	gl.bufferData(GL_SHADER_STORAGE_BUFFER, ssbo_data_size, ssbo_data, GL_DYNAMIC_COPY);
   2015 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   2016 
   2017 	/* Free unused memory. */
   2018 	delete[] ssbo_data;
   2019 	ssbo_data = NULL;
   2020 
   2021 	/* Bind specific m_ssbo_id buffer region to a specific Shader Storage Buffer binding point. */
   2022 	for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
   2023 	{
   2024 		glw::GLuint offset = n_ssb * ssbo_alignment;
   2025 
   2026 		gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, n_ssb /*binding index*/, m_ssbo_id, offset, int_size);
   2027 		GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
   2028 	}
   2029 
   2030 	/* Configure VAO. */
   2031 	gl.genVertexArrays(1, &m_vao_id);
   2032 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   2033 
   2034 	gl.bindVertexArray(m_vao_id);
   2035 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   2036 
   2037 	/* Create a Buffer Object for Transform Feedback's outputs. */
   2038 	gl.genBuffers(1, &m_tfbo_id);
   2039 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
   2040 
   2041 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
   2042 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
   2043 
   2044 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, initial_buffer_data,
   2045 				  GL_STATIC_READ);
   2046 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   2047 
   2048 	/* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
   2049 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
   2050 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
   2051 
   2052 	/* Use program. */
   2053 	gl.useProgram(m_po_id);
   2054 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   2055 
   2056 	/* Disable rasterization and make a draw call. After that, turn on rasterization. */
   2057 	gl.enable(GL_RASTERIZER_DISCARD);
   2058 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
   2059 
   2060 	gl.beginTransformFeedback(GL_POINTS);
   2061 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
   2062 
   2063 	gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
   2064 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
   2065 
   2066 	gl.endTransformFeedback();
   2067 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
   2068 
   2069 	gl.disable(GL_RASTERIZER_DISCARD);
   2070 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
   2071 
   2072 	/* Retrieve value from Transform Feedback. */
   2073 	ptrTF_data = (glw::GLfloat*)gl.mapBufferRange(
   2074 		GL_ARRAY_BUFFER, 0 /*offset*/, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
   2075 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   2076 
   2077 	counter = int(ptrTF_data[0] + 0.5f);
   2078 
   2079 	gl.unmapBuffer(GL_ARRAY_BUFFER);
   2080 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   2081 
   2082 	ptrTF_data = NULL;
   2083 
   2084 	/* Retrieve values from Shader Storage Buffer Object. */
   2085 	ptrSSBO_data =
   2086 		(glw::GLint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /*offset*/, ssbo_data_size, GL_MAP_READ_BIT);
   2087 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   2088 
   2089 	for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
   2090 	{
   2091 		if (ptrSSBO_data[i * int_alignment] != i + 2)
   2092 		{
   2093 			result = false;
   2094 
   2095 			m_testCtx.getLog() << tcu::TestLog::Message << "Value read from Shader Storage Buffer "
   2096 														   "["
   2097 							   << ptrSSBO_data[i * int_alignment] << "] "
   2098 																	 "at index "
   2099 																	 "["
   2100 							   << i * int_alignment << "]"
   2101 													   "is not equal to expected value "
   2102 													   "["
   2103 							   << i + 2 << "]" << tcu::TestLog::EndMessage;
   2104 
   2105 			break;
   2106 		}
   2107 	}
   2108 
   2109 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
   2110 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   2111 
   2112 	ptrSSBO_data = NULL;
   2113 
   2114 	/* Calculate expected value. */
   2115 	expectedValue =
   2116 		m_gl_max_geometry_shader_storage_blocks_ext_value * (m_gl_max_geometry_shader_storage_blocks_ext_value + 1) / 2;
   2117 
   2118 	if (counter != expectedValue)
   2119 	{
   2120 		result = false;
   2121 	}
   2122 
   2123 end:
   2124 	if (result)
   2125 	{
   2126 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2127 	}
   2128 	else
   2129 	{
   2130 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   2131 	}
   2132 
   2133 	return STOP;
   2134 }
   2135 
   2136 /** Constructor
   2137  *
   2138  * @param context       Test context
   2139  * @param extParams     Not used.
   2140  * @param name          Test case's name
   2141  * @param description   Test case's description
   2142  **/
   2143 GeometryShaderMaxAtomicCountersTest::GeometryShaderMaxAtomicCountersTest(Context&			  context,
   2144 																		 const ExtParameters& extParams,
   2145 																		 const char* name, const char* description)
   2146 	: TestCaseBase(context, extParams, name, description)
   2147 	, m_acbo_id(0)
   2148 	, m_fs_id(0)
   2149 	, m_gl_max_geometry_atomic_counters_ext_value(0)
   2150 	, m_gs_id(0)
   2151 	, m_po_id(0)
   2152 	, m_vao_id(0)
   2153 	, m_vs_id(0)
   2154 {
   2155 }
   2156 
   2157 /** Deinitializes GLES objects created during the test. */
   2158 void GeometryShaderMaxAtomicCountersTest::deinit()
   2159 {
   2160 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2161 
   2162 	if (m_acbo_id != 0)
   2163 	{
   2164 		gl.deleteBuffers(1, &m_acbo_id);
   2165 		m_acbo_id = 0;
   2166 	}
   2167 
   2168 	if (m_fs_id != 0)
   2169 	{
   2170 		gl.deleteShader(m_fs_id);
   2171 		m_fs_id = 0;
   2172 	}
   2173 
   2174 	if (m_gs_id != 0)
   2175 	{
   2176 		gl.deleteShader(m_gs_id);
   2177 		m_gs_id = 0;
   2178 	}
   2179 
   2180 	if (m_po_id != 0)
   2181 	{
   2182 		gl.deleteProgram(m_po_id);
   2183 		m_po_id = 0;
   2184 	}
   2185 
   2186 	if (m_vao_id != 0)
   2187 	{
   2188 		gl.deleteVertexArrays(1, &m_vao_id);
   2189 		m_vao_id = 0;
   2190 	}
   2191 
   2192 	if (m_vs_id != 0)
   2193 	{
   2194 		gl.deleteShader(m_vs_id);
   2195 		m_vs_id = 0;
   2196 	}
   2197 
   2198 	/* Release base class */
   2199 	TestCaseBase::deinit();
   2200 }
   2201 
   2202 /* Retrieves test-specific geometry shader source code.
   2203  *
   2204  * @return Requested string.
   2205  */
   2206 std::string GeometryShaderMaxAtomicCountersTest::getGSCode()
   2207 {
   2208 	std::stringstream code_sstream;
   2209 
   2210 	/* Form the GS */
   2211 	code_sstream << "${VERSION}\n"
   2212 					"${GEOMETRY_SHADER_REQUIRE}\n"
   2213 					"\n"
   2214 					"layout (points)                   in;\n"
   2215 					"layout (points, max_vertices = 1) out;\n"
   2216 					"\n"
   2217 					"uniform int n_loop_iterations;\n"
   2218 					"flat in int vertex_id[];\n"
   2219 					"\n";
   2220 
   2221 	code_sstream << "layout(binding = 0) uniform atomic_uint acs[" << m_gl_max_geometry_atomic_counters_ext_value
   2222 				 << "];\n"
   2223 				 << "\n"
   2224 					"void main()\n"
   2225 					"{\n"
   2226 					"    for (int counter_id = 1;\n"
   2227 					"             counter_id <= n_loop_iterations;\n"
   2228 					"           ++counter_id)\n"
   2229 					"    {\n"
   2230 					"        if ((vertex_id[0] % counter_id) == 0)\n"
   2231 					"        {\n"
   2232 					"            atomicCounterIncrement(acs[counter_id - 1]);\n"
   2233 					"        }\n"
   2234 					"    }\n"
   2235 					"\n"
   2236 					"    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
   2237 					"    EmitVertex();\n"
   2238 					"}\n";
   2239 
   2240 	/* Form a specialized version of the GS source code */
   2241 	std::string gs_code				= code_sstream.str();
   2242 	const char* gs_code_raw			= gs_code.c_str();
   2243 	std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
   2244 
   2245 	return gs_code_specialized;
   2246 }
   2247 
   2248 /** Executes the test.
   2249  *
   2250  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   2251  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   2252  *  Note the function throws exception should an error occur!
   2253  **/
   2254 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCountersTest::iterate()
   2255 {
   2256 	/* Define Vertex Shader's code for the purpose of this test. */
   2257 	const char* vs_code = "${VERSION}\n"
   2258 						  "\n"
   2259 						  "flat out int vertex_id;\n"
   2260 						  "\n"
   2261 						  "void main()\n"
   2262 						  "{\n"
   2263 						  "    vertex_id    = gl_VertexID;\n"
   2264 						  "    gl_Position  = vec4(1.0, 0.0, 0.0, 1.0);\n"
   2265 						  "}\n";
   2266 
   2267 	bool			   has_shader_compilation_failed	  = true;
   2268 	glw::GLuint*	   initial_ac_data					  = DE_NULL;
   2269 	const unsigned int n_draw_call_vertices				  = 4;
   2270 	glw::GLint		   n_loop_iterations_uniform_location = -1;
   2271 	glw::GLuint*	   ptrACBO_data						  = DE_NULL;
   2272 	bool			   result							  = true;
   2273 
   2274 	std::string fs_code_specialized		= "";
   2275 	const char* fs_code_specialized_raw = DE_NULL;
   2276 	std::string gs_code_specialized		= "";
   2277 	const char* gs_code_specialized_raw = DE_NULL;
   2278 	std::string vs_code_specialized		= "";
   2279 	const char* vs_code_specialized_raw = DE_NULL;
   2280 
   2281 	/* This test should only run if EXT_geometry_shader is supported. */
   2282 	if (!m_is_geometry_shader_extension_supported)
   2283 	{
   2284 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   2285 	}
   2286 
   2287 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2288 
   2289 	/* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname value */
   2290 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTERS, &m_gl_max_geometry_atomic_counters_ext_value);
   2291 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname");
   2292 
   2293 	/* Check if m_gl_max_atomic_counters_value is less than or equal zero. */
   2294 	if (m_gl_max_geometry_atomic_counters_ext_value <= 0)
   2295 	{
   2296 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT query value "
   2297 						   << "[" << m_gl_max_geometry_atomic_counters_ext_value
   2298 						   << "]"
   2299 							  " is less than or equal to zero. Atomic Counters"
   2300 							  " in Geometry Shader are not supported."
   2301 						   << tcu::TestLog::EndMessage;
   2302 
   2303 		if (m_gl_max_geometry_atomic_counters_ext_value == 0)
   2304 		{
   2305 			throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT is 0");
   2306 		}
   2307 		else
   2308 		{
   2309 			result = false;
   2310 			goto end;
   2311 		}
   2312 	}
   2313 
   2314 	/* Create a program object. */
   2315 	m_po_id = gl.createProgram();
   2316 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   2317 
   2318 	/* Create shader objects. */
   2319 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   2320 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   2321 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   2322 
   2323 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   2324 
   2325 	/* Try to link the test program object */
   2326 	fs_code_specialized		= specializeShader(1, &dummy_fs_code);
   2327 	fs_code_specialized_raw = fs_code_specialized.c_str();
   2328 
   2329 	gs_code_specialized		= getGSCode();
   2330 	gs_code_specialized_raw = gs_code_specialized.c_str();
   2331 
   2332 	vs_code_specialized		= specializeShader(1, &vs_code);
   2333 	vs_code_specialized_raw = vs_code_specialized.c_str();
   2334 
   2335 	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
   2336 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
   2337 									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
   2338 									&fs_code_specialized_raw, &has_shader_compilation_failed))
   2339 	{
   2340 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
   2341 
   2342 		result = false;
   2343 		goto end;
   2344 	}
   2345 
   2346 	/* Create Atomic Counter Buffer Objects. */
   2347 	gl.genBuffers(1, &m_acbo_id);
   2348 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
   2349 
   2350 	/* Prepare initial data - zeroes - to fill the Atomic Counter Buffer Object. */
   2351 	initial_ac_data = new glw::GLuint[m_gl_max_geometry_atomic_counters_ext_value];
   2352 	memset(initial_ac_data, 0, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value);
   2353 
   2354 	gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_id);
   2355 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
   2356 
   2357 	gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value, NULL,
   2358 				  GL_DYNAMIC_COPY);
   2359 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   2360 
   2361 	gl.bufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
   2362 					 sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
   2363 					 initial_ac_data /*initialize with zeroes*/);
   2364 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
   2365 
   2366 	gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0 /*binding index*/, m_acbo_id /*buffer*/);
   2367 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
   2368 
   2369 	/* Configure VAO. */
   2370 	gl.genVertexArrays(1, &m_vao_id);
   2371 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   2372 
   2373 	gl.bindVertexArray(m_vao_id);
   2374 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   2375 
   2376 	/* Use program. */
   2377 	n_loop_iterations_uniform_location = gl.getUniformLocation(m_po_id, "n_loop_iterations");
   2378 
   2379 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
   2380 	if (n_loop_iterations_uniform_location == -1)
   2381 	{
   2382 		TCU_FAIL("n_loop_iterations uniform is considered inactive");
   2383 	}
   2384 	else
   2385 	{
   2386 		gl.useProgram(m_po_id);
   2387 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   2388 
   2389 		gl.uniform1i(n_loop_iterations_uniform_location, m_gl_max_geometry_atomic_counters_ext_value);
   2390 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
   2391 	}
   2392 
   2393 	/* Issue the draw call */
   2394 	gl.drawArrays(GL_POINTS, 0, n_draw_call_vertices);
   2395 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
   2396 
   2397 	/* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
   2398 	ptrACBO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
   2399 												   sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
   2400 												   GL_MAP_READ_BIT);
   2401 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   2402 
   2403 	for (glw::GLint n_ac = 0; n_ac < m_gl_max_geometry_atomic_counters_ext_value; ++n_ac)
   2404 	{
   2405 		unsigned int expected_value = 0;
   2406 
   2407 		for (unsigned int n_draw_call_vertex = 0; n_draw_call_vertex < n_draw_call_vertices; ++n_draw_call_vertex)
   2408 		{
   2409 			if ((n_draw_call_vertex % (n_ac + 1)) == 0)
   2410 			{
   2411 				++expected_value;
   2412 			}
   2413 		}
   2414 
   2415 		if (ptrACBO_data[n_ac] != expected_value)
   2416 		{
   2417 			result = false;
   2418 			break;
   2419 		}
   2420 	}
   2421 
   2422 	gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
   2423 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   2424 
   2425 	ptrACBO_data = NULL;
   2426 
   2427 end:
   2428 	if (result)
   2429 	{
   2430 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2431 	}
   2432 	else
   2433 	{
   2434 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   2435 	}
   2436 
   2437 	return STOP;
   2438 }
   2439 
   2440 /** Constructor
   2441  *
   2442  * @param context       Test context
   2443  * @param extParams     Not used.
   2444  * @param name          Test case's name
   2445  * @param description   Test case's description
   2446  **/
   2447 GeometryShaderMaxAtomicCounterBuffersTest::GeometryShaderMaxAtomicCounterBuffersTest(Context&			  context,
   2448 																					 const ExtParameters& extParams,
   2449 																					 const char*		  name,
   2450 																					 const char*		  description)
   2451 	: TestCaseBase(context, extParams, name, description)
   2452 	, m_acbo_ids(NULL)
   2453 	, m_fs_id(0)
   2454 	, m_gl_max_atomic_counter_buffer_bindings_value(0)
   2455 	, m_gl_max_geometry_atomic_counter_buffers_ext_value(0)
   2456 	, m_gs_id(0)
   2457 	, m_po_id(0)
   2458 	, m_vao_id(0)
   2459 	, m_vs_id(0)
   2460 {
   2461 }
   2462 
   2463 /** Deinitializes GLES objects created during the test. */
   2464 void GeometryShaderMaxAtomicCounterBuffersTest::deinit()
   2465 {
   2466 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2467 
   2468 	if (m_acbo_ids != NULL)
   2469 	{
   2470 		if (m_gl_max_geometry_atomic_counter_buffers_ext_value > 0)
   2471 		{
   2472 			gl.deleteBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
   2473 
   2474 			delete[] m_acbo_ids;
   2475 			m_acbo_ids = NULL;
   2476 		}
   2477 	}
   2478 
   2479 	if (m_fs_id != 0)
   2480 	{
   2481 		gl.deleteShader(m_fs_id);
   2482 		m_fs_id = 0;
   2483 	}
   2484 
   2485 	if (m_gs_id != 0)
   2486 	{
   2487 		gl.deleteShader(m_gs_id);
   2488 		m_gs_id = 0;
   2489 	}
   2490 
   2491 	if (m_po_id != 0)
   2492 	{
   2493 		gl.deleteProgram(m_po_id);
   2494 		m_po_id = 0;
   2495 	}
   2496 
   2497 	if (m_vao_id != 0)
   2498 	{
   2499 		gl.deleteVertexArrays(1, &m_vao_id);
   2500 		m_vao_id = 0;
   2501 	}
   2502 
   2503 	if (m_vs_id != 0)
   2504 	{
   2505 		gl.deleteShader(m_vs_id);
   2506 		m_vs_id = 0;
   2507 	}
   2508 
   2509 	/* Release base class */
   2510 	TestCaseBase::deinit();
   2511 }
   2512 
   2513 /* Retrieves test-specific geometry shader source code.
   2514  *
   2515  * @return Requested string.
   2516  */
   2517 std::string GeometryShaderMaxAtomicCounterBuffersTest::getGSCode()
   2518 {
   2519 	std::stringstream code_sstream;
   2520 
   2521 	/* Form the GS */
   2522 	code_sstream << "${VERSION}\n"
   2523 					"${GEOMETRY_SHADER_REQUIRE}\n"
   2524 					"\n"
   2525 					"layout (points)                   in;\n"
   2526 					"layout (points, max_vertices = 1) out;\n"
   2527 					"\n"
   2528 					"flat in int vertex_id[];\n"
   2529 					"\n";
   2530 
   2531 	for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
   2532 	{
   2533 		code_sstream << "layout(binding = " << n_ac << ") uniform atomic_uint ac" << n_ac << ";\n";
   2534 	}
   2535 
   2536 	code_sstream << "\n"
   2537 					"void main()\n"
   2538 					"{\n"
   2539 					"    for(int counter_id = 1; counter_id <= "
   2540 				 << m_gl_max_geometry_atomic_counter_buffers_ext_value
   2541 				 << "; ++counter_id)\n"
   2542 					"    {\n"
   2543 					"        if((vertex_id[0] % counter_id) == 0)\n"
   2544 					"        {\n";
   2545 
   2546 	for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
   2547 	{
   2548 		code_sstream << "            atomicCounterIncrement(ac" << n_ac << ");\n";
   2549 	}
   2550 
   2551 	code_sstream << "        }\n"
   2552 					"    }\n";
   2553 
   2554 	code_sstream << "\n"
   2555 					"    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
   2556 					"    EmitVertex();\n"
   2557 					"}\n";
   2558 
   2559 	/* Form a specialized version of the GS source code */
   2560 	std::string gs_code				= code_sstream.str();
   2561 	const char* gs_code_raw			= gs_code.c_str();
   2562 	std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
   2563 
   2564 	return gs_code_specialized;
   2565 }
   2566 
   2567 /** Executes the test.
   2568  *
   2569  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   2570  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   2571  *  Note the function throws exception should an error occur!
   2572  **/
   2573 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCounterBuffersTest::iterate()
   2574 {
   2575 	/* Define Vertex Shader's code for the purpose of this test. */
   2576 	const char* vs_code = "${VERSION}\n"
   2577 						  "\n"
   2578 						  "flat out int vertex_id;\n"
   2579 						  "\n"
   2580 						  "void main()\n"
   2581 						  "{\n"
   2582 						  "    vertex_id    = gl_VertexID;\n"
   2583 						  "    gl_Position  = vec4(1.0, 0.0, 0.0, 1.0);\n"
   2584 						  "}\n";
   2585 
   2586 	unsigned int		  expected_value				= 0;
   2587 	const glw::Functions& gl							= m_context.getRenderContext().getFunctions();
   2588 	bool				  has_shader_compilation_failed = true;
   2589 	const glw::GLuint	 initial_ac_data				= 0;
   2590 	const glw::GLuint	 number_of_indices				= 128 * m_gl_max_geometry_atomic_counter_buffers_ext_value;
   2591 	bool				  result						= true;
   2592 
   2593 	std::string fs_code_specialized		= "";
   2594 	const char* fs_code_specialized_raw = DE_NULL;
   2595 	std::string gs_code_specialized		= "";
   2596 	const char* gs_code_specialized_raw = DE_NULL;
   2597 	std::string vs_code_specialized		= "";
   2598 	const char* vs_code_specialized_raw = DE_NULL;
   2599 
   2600 	/* This test should only run if EXT_geometry_shader is supported. */
   2601 	if (!m_is_geometry_shader_extension_supported)
   2602 	{
   2603 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   2604 	}
   2605 
   2606 	/* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname value */
   2607 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS,
   2608 				   &m_gl_max_geometry_atomic_counter_buffers_ext_value);
   2609 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname");
   2610 
   2611 	/* Retrieve GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname value */
   2612 	gl.getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_gl_max_atomic_counter_buffer_bindings_value);
   2613 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname");
   2614 
   2615 	/* Check if m_gl_max_geometry_atomic_counter_buffers_ext_value is less than or equal zero. */
   2616 	if (m_gl_max_geometry_atomic_counter_buffers_ext_value <= 0)
   2617 	{
   2618 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
   2619 						   << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
   2620 						   << "]"
   2621 							  " is less than or equal to zero. Atomic Counter Buffers"
   2622 							  " are not supported."
   2623 						   << tcu::TestLog::EndMessage;
   2624 
   2625 		if (m_gl_max_geometry_atomic_counter_buffers_ext_value == 0)
   2626 		{
   2627 			throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT is 0");
   2628 		}
   2629 		else
   2630 		{
   2631 			result = false;
   2632 			goto end;
   2633 		}
   2634 	}
   2635 
   2636 	/* Check if m_gl_max_atomic_counter_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
   2637 	if (m_gl_max_atomic_counter_buffer_bindings_value < m_gl_max_geometry_atomic_counter_buffers_ext_value)
   2638 	{
   2639 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
   2640 						   << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
   2641 						   << "]"
   2642 							  " is greater than GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS query value "
   2643 							  "["
   2644 						   << m_gl_max_atomic_counter_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
   2645 
   2646 		result = false;
   2647 		goto end;
   2648 	}
   2649 
   2650 	/* Create a program object. */
   2651 	m_po_id = gl.createProgram();
   2652 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   2653 
   2654 	/* Create shader objects. */
   2655 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   2656 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   2657 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   2658 
   2659 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   2660 
   2661 	/* Try to link the test program object */
   2662 	fs_code_specialized		= specializeShader(1, &dummy_fs_code);
   2663 	fs_code_specialized_raw = fs_code_specialized.c_str();
   2664 
   2665 	gs_code_specialized		= getGSCode();
   2666 	gs_code_specialized_raw = gs_code_specialized.c_str();
   2667 
   2668 	vs_code_specialized		= specializeShader(1, &vs_code);
   2669 	vs_code_specialized_raw = vs_code_specialized.c_str();
   2670 
   2671 	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
   2672 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
   2673 									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
   2674 									&fs_code_specialized_raw, &has_shader_compilation_failed))
   2675 	{
   2676 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
   2677 
   2678 		result = false;
   2679 		goto end;
   2680 	}
   2681 
   2682 	/* Create Atomic Counter Buffer Objects. */
   2683 	m_acbo_ids = new glw::GLuint[m_gl_max_geometry_atomic_counter_buffers_ext_value];
   2684 
   2685 	gl.genBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
   2686 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
   2687 
   2688 	for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
   2689 	{
   2690 		gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
   2691 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
   2692 
   2693 		gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint), &initial_ac_data /*initialize with zeroes*/,
   2694 					  GL_DYNAMIC_COPY);
   2695 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   2696 
   2697 		gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, n_acb /*binding index*/, m_acbo_ids[n_acb] /*buffer*/);
   2698 		GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
   2699 	}
   2700 
   2701 	/* Configure VAO. */
   2702 	gl.genVertexArrays(1, &m_vao_id);
   2703 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   2704 
   2705 	gl.bindVertexArray(m_vao_id);
   2706 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   2707 
   2708 	/* Use program. */
   2709 	gl.useProgram(m_po_id);
   2710 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   2711 
   2712 	gl.drawArrays(GL_POINTS, 0 /*starting index*/, number_of_indices);
   2713 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
   2714 
   2715 	/* Calculate expected value. */
   2716 	/* For each point being processed by Geometry Shader. */
   2717 	for (glw::GLuint vertex_id = 0; vertex_id < number_of_indices; ++vertex_id)
   2718 	{
   2719 		/* And for each atomic counter ID. */
   2720 		for (int atomic_counter_id = 1; atomic_counter_id <= m_gl_max_geometry_atomic_counter_buffers_ext_value;
   2721 			 ++atomic_counter_id)
   2722 		{
   2723 			/* Check if (vertex_id % atomic_counter_id) == 0. If it is true, increment expected_value. */
   2724 			if (vertex_id % atomic_counter_id == 0)
   2725 			{
   2726 				++expected_value;
   2727 			}
   2728 		}
   2729 	}
   2730 
   2731 	/* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
   2732 	for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
   2733 	{
   2734 		gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
   2735 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
   2736 
   2737 		glw::GLuint* ptrABO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
   2738 																   sizeof(glw::GLuint) /*length*/, GL_MAP_READ_BIT);
   2739 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   2740 
   2741 		if (ptrABO_data[0] != expected_value)
   2742 		{
   2743 			result = false;
   2744 			break;
   2745 		}
   2746 
   2747 		gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
   2748 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   2749 
   2750 		ptrABO_data = NULL;
   2751 	}
   2752 
   2753 end:
   2754 	if (result)
   2755 	{
   2756 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2757 	}
   2758 	else
   2759 	{
   2760 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   2761 	}
   2762 
   2763 	return STOP;
   2764 }
   2765 
   2766 /** Constructor
   2767  *
   2768  * @param context       Test context
   2769  * @param extParams     Not used.
   2770  * @param name          Test case's name
   2771  * @param description   Test case's description
   2772  **/
   2773 GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::
   2774 	GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context& context, const ExtParameters& extParams,
   2775 																 const char* name, const char* description)
   2776 	: TestCaseBase(context, extParams, name, description)
   2777 	, m_fs_id(0)
   2778 	, m_fs_po_id(0)
   2779 	, m_gs_id(0)
   2780 	, m_gs_po_id(0)
   2781 	, m_ppo_id(0)
   2782 	, m_vao_id(0)
   2783 {
   2784 }
   2785 
   2786 /** Deinitializes GLES objects created during the test. */
   2787 void GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::deinit()
   2788 {
   2789 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2790 
   2791 	if (m_fs_id != 0)
   2792 	{
   2793 		gl.deleteShader(m_fs_id);
   2794 		m_fs_id = 0;
   2795 	}
   2796 
   2797 	if (m_fs_po_id != 0)
   2798 	{
   2799 		gl.deleteProgram(m_fs_po_id);
   2800 		m_fs_po_id = 0;
   2801 	}
   2802 
   2803 	if (m_gs_id != 0)
   2804 	{
   2805 		gl.deleteShader(m_gs_id);
   2806 		m_gs_id = 0;
   2807 	}
   2808 
   2809 	if (m_gs_po_id != 0)
   2810 	{
   2811 		gl.deleteProgram(m_gs_po_id);
   2812 		m_gs_po_id = 0;
   2813 	}
   2814 
   2815 	if (m_ppo_id != 0)
   2816 	{
   2817 		gl.deleteProgramPipelines(1, &m_ppo_id);
   2818 		m_ppo_id = 0;
   2819 	}
   2820 
   2821 	if (m_vao_id != 0)
   2822 	{
   2823 		gl.deleteVertexArrays(1, &m_vao_id);
   2824 		m_vao_id = 0;
   2825 	}
   2826 
   2827 	/* Release base class */
   2828 	TestCaseBase::deinit();
   2829 }
   2830 
   2831 /** Executes the test.
   2832  *
   2833  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   2834  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   2835  *  Note the function throws exception should an error occur!
   2836  **/
   2837 tcu::TestNode::IterateResult GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::iterate()
   2838 {
   2839 	bool		has_shader_compilation_failed = true;
   2840 	bool		result						  = true;
   2841 	glw::GLenum error						  = GL_NO_ERROR;
   2842 
   2843 	/* This test should only run if EXT_geometry_shader is supported. */
   2844 	if (!m_is_geometry_shader_extension_supported)
   2845 	{
   2846 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   2847 	}
   2848 
   2849 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2850 
   2851 	/* Create separable program objects. */
   2852 	m_fs_po_id = gl.createProgram();
   2853 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   2854 
   2855 	gl.programParameteri(m_fs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
   2856 	GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
   2857 
   2858 	m_gs_po_id = gl.createProgram();
   2859 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   2860 
   2861 	gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
   2862 	GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
   2863 
   2864 	/* Create shader objects. */
   2865 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   2866 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   2867 
   2868 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   2869 
   2870 	/* Try to link the test program object */
   2871 	std::string fs_code_specialized		= specializeShader(1, &dummy_fs_code);
   2872 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
   2873 	std::string gs_code_specialized		= specializeShader(1, &dummy_gs_code);
   2874 	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
   2875 
   2876 	if (!TestCaseBase::buildProgram(m_fs_po_id, m_fs_id, 1,			/* n_sh1_body_parts */
   2877 									&fs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
   2878 									NULL, 0, 0,						/* n_sh3_body_parts */
   2879 									NULL, &has_shader_compilation_failed))
   2880 	{
   2881 		m_testCtx.getLog() << tcu::TestLog::Message << "Fragment Shader Program object linking failed."
   2882 						   << tcu::TestLog::EndMessage;
   2883 
   2884 		result = false;
   2885 		goto end;
   2886 	}
   2887 
   2888 	if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1,			/* n_sh1_body_parts */
   2889 									&gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
   2890 									NULL, 0, 0,						/* n_sh3_body_parts */
   2891 									NULL, &has_shader_compilation_failed))
   2892 	{
   2893 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
   2894 						   << tcu::TestLog::EndMessage;
   2895 
   2896 		result = false;
   2897 		goto end;
   2898 	}
   2899 
   2900 	/* Configure Pipeline Object. */
   2901 	gl.genProgramPipelines(1, &m_ppo_id);
   2902 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
   2903 
   2904 	gl.useProgramStages(m_ppo_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
   2905 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
   2906 
   2907 	gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
   2908 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
   2909 
   2910 	/* Configure VAO. */
   2911 	gl.genVertexArrays(1, &m_vao_id);
   2912 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   2913 
   2914 	gl.bindVertexArray(m_vao_id);
   2915 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   2916 
   2917 	/* Use Program Pipeline Object. */
   2918 	gl.bindProgramPipeline(m_ppo_id);
   2919 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
   2920 
   2921 	gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
   2922 
   2923 	error = gl.getError();
   2924 
   2925 	/* Check if correct error was generated. */
   2926 	if (GL_INVALID_OPERATION != error)
   2927 	{
   2928 		result = false;
   2929 
   2930 		m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
   2931 						   << tcu::TestLog::EndMessage;
   2932 	}
   2933 
   2934 end:
   2935 	if (result)
   2936 	{
   2937 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2938 	}
   2939 	else
   2940 	{
   2941 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   2942 	}
   2943 
   2944 	return STOP;
   2945 }
   2946 
   2947 /** Constructor
   2948  *
   2949  * @param context       Test context
   2950  * @param extParams     Not used.
   2951  * @param name          Test case's name
   2952  * @param description   Test case's description
   2953  **/
   2954 GeometryShaderIncompatibleDrawCallModeTest::GeometryShaderIncompatibleDrawCallModeTest(Context&				context,
   2955 																					   const ExtParameters& extParams,
   2956 																					   const char*			name,
   2957 																					   const char*			description)
   2958 	: TestCaseBase(context, extParams, name, description)
   2959 	, m_fs_id(0)
   2960 	, m_gs_ids(NULL)
   2961 	, m_number_of_gs(5 /*taken from test spec*/)
   2962 	, m_po_ids(NULL)
   2963 {
   2964 	m_vao_id = 0;
   2965 	m_vs_id  = 0;
   2966 }
   2967 
   2968 /** Deinitializes GLES objects created during the test. */
   2969 void GeometryShaderIncompatibleDrawCallModeTest::deinit()
   2970 {
   2971 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   2972 
   2973 	if (m_fs_id != 0)
   2974 	{
   2975 		gl.deleteShader(m_fs_id);
   2976 		m_fs_id = 0;
   2977 	}
   2978 
   2979 	if (m_gs_ids != 0)
   2980 	{
   2981 		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
   2982 		{
   2983 			gl.deleteShader(m_gs_ids[i]);
   2984 			m_gs_ids[i] = 0;
   2985 		}
   2986 
   2987 		delete[] m_gs_ids;
   2988 		m_gs_ids = NULL;
   2989 	}
   2990 
   2991 	if (m_po_ids != 0)
   2992 	{
   2993 		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
   2994 		{
   2995 			gl.deleteProgram(m_po_ids[i]);
   2996 			m_po_ids[i] = 0;
   2997 		}
   2998 
   2999 		delete[] m_po_ids;
   3000 		m_po_ids = NULL;
   3001 	}
   3002 
   3003 	if (m_vao_id != 0)
   3004 	{
   3005 		gl.deleteVertexArrays(1, &m_vao_id);
   3006 		m_vao_id = 0;
   3007 	}
   3008 
   3009 	if (m_vs_id != 0)
   3010 	{
   3011 		gl.deleteShader(m_vs_id);
   3012 		m_vs_id = 0;
   3013 	}
   3014 
   3015 	/* Release base class */
   3016 	TestCaseBase::deinit();
   3017 }
   3018 
   3019 /** Executes the test.
   3020  *
   3021  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   3022  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   3023  *  Note the function throws exception should an error occur!
   3024  **/
   3025 tcu::TestNode::IterateResult GeometryShaderIncompatibleDrawCallModeTest::iterate()
   3026 {
   3027 	/* Define 5 Geometry Shaders for purpose of this test. */
   3028 	const char* gs_code_points = "${VERSION}\n"
   3029 								 "${GEOMETRY_SHADER_REQUIRE}\n"
   3030 								 "\n"
   3031 								 "layout (points)                   in;\n"
   3032 								 "layout (points, max_vertices = 1) out;\n"
   3033 								 "\n"
   3034 								 "${IN_PER_VERTEX_DECL_ARRAY}"
   3035 								 "\n"
   3036 								 "void main()\n"
   3037 								 "{\n"
   3038 								 "    gl_Position = gl_in[0].gl_Position;\n"
   3039 								 "    EmitVertex();\n"
   3040 								 "}\n";
   3041 
   3042 	const char* gs_code_lines = "${VERSION}\n"
   3043 								"${GEOMETRY_SHADER_REQUIRE}\n"
   3044 								"\n"
   3045 								"layout (lines)                    in;\n"
   3046 								"layout (points, max_vertices = 1) out;\n"
   3047 								"\n"
   3048 								"${IN_PER_VERTEX_DECL_ARRAY}"
   3049 								"\n"
   3050 								"void main()\n"
   3051 								"{\n"
   3052 								"    gl_Position = gl_in[0].gl_Position;\n"
   3053 								"    EmitVertex();\n"
   3054 								"}\n";
   3055 
   3056 	const char* gs_code_lines_adjacency = "${VERSION}\n"
   3057 										  "${GEOMETRY_SHADER_REQUIRE}\n"
   3058 										  "\n"
   3059 										  "layout (lines_adjacency)          in;\n"
   3060 										  "layout (points, max_vertices = 1) out;\n"
   3061 										  "\n"
   3062 										  "${IN_PER_VERTEX_DECL_ARRAY}"
   3063 										  "\n"
   3064 										  "void main()\n"
   3065 										  "{\n"
   3066 										  "    gl_Position = gl_in[0].gl_Position;\n"
   3067 										  "    EmitVertex();\n"
   3068 										  "}\n";
   3069 
   3070 	const char* gs_code_triangles = "${VERSION}\n"
   3071 									"${GEOMETRY_SHADER_REQUIRE}\n"
   3072 									"\n"
   3073 									"layout (triangles)                in;\n"
   3074 									"layout (points, max_vertices = 1) out;\n"
   3075 									"\n"
   3076 									"${IN_PER_VERTEX_DECL_ARRAY}"
   3077 									"\n"
   3078 									"void main()\n"
   3079 									"{\n"
   3080 									"    gl_Position = gl_in[0].gl_Position;\n"
   3081 									"    EmitVertex();\n"
   3082 									"}\n";
   3083 
   3084 	const char* gs_code_triangles_adjacency = "${VERSION}\n"
   3085 											  "${GEOMETRY_SHADER_REQUIRE}\n"
   3086 											  "\n"
   3087 											  "layout (triangles_adjacency)      in;\n"
   3088 											  "layout (points, max_vertices = 1) out;\n"
   3089 											  "\n"
   3090 											  "${IN_PER_VERTEX_DECL_ARRAY}"
   3091 											  "\n"
   3092 											  "void main()\n"
   3093 											  "{\n"
   3094 											  "    gl_Position = gl_in[0].gl_Position;\n"
   3095 											  "    EmitVertex();\n"
   3096 											  "}\n";
   3097 
   3098 	bool has_shader_compilation_failed = true;
   3099 	bool result						   = true;
   3100 
   3101 	m_gs_ids = new glw::GLuint[m_number_of_gs];
   3102 	m_po_ids = new glw::GLuint[m_number_of_gs];
   3103 
   3104 	/* This test should only run if EXT_geometry_shader is supported. */
   3105 	if (!m_is_geometry_shader_extension_supported)
   3106 	{
   3107 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   3108 	}
   3109 
   3110 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3111 
   3112 	/* Create program objects & geometry shader objects. */
   3113 	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
   3114 	{
   3115 		m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
   3116 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   3117 
   3118 		m_po_ids[i] = gl.createProgram();
   3119 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   3120 	}
   3121 
   3122 	/* Create shader object. */
   3123 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   3124 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   3125 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   3126 
   3127 	/* Try to link the test program object */
   3128 	std::string fs_code_specialized		= specializeShader(1, &dummy_fs_code);
   3129 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
   3130 
   3131 	std::string gs_codes_specialized[] = { specializeShader(1, &gs_code_points), specializeShader(1, &gs_code_lines),
   3132 										   specializeShader(1, &gs_code_lines_adjacency),
   3133 										   specializeShader(1, &gs_code_triangles),
   3134 										   specializeShader(1, &gs_code_triangles_adjacency) };
   3135 
   3136 	const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str(),
   3137 											   gs_codes_specialized[2].c_str(), gs_codes_specialized[3].c_str(),
   3138 											   gs_codes_specialized[4].c_str() };
   3139 	std::string vs_code_specialized		= specializeShader(1, &dummy_vs_code);
   3140 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
   3141 
   3142 	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
   3143 	{
   3144 		if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,				  /* n_sh1_body_parts */
   3145 										&fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
   3146 										&gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
   3147 										&vs_code_specialized_raw, &has_shader_compilation_failed))
   3148 		{
   3149 			m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
   3150 							   << "[" << i << "]." << tcu::TestLog::EndMessage;
   3151 
   3152 			result = false;
   3153 			break;
   3154 		}
   3155 	}
   3156 
   3157 	if (result)
   3158 	{
   3159 		/* Configure VAO. */
   3160 		gl.genVertexArrays(1, &m_vao_id);
   3161 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   3162 
   3163 		gl.bindVertexArray(m_vao_id);
   3164 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   3165 
   3166 		for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
   3167 		{
   3168 			/* Use Program Object. */
   3169 			gl.useProgram(m_po_ids[po]);
   3170 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   3171 
   3172 			if (po != 0)
   3173 			{
   3174 				gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
   3175 
   3176 				if (GL_INVALID_OPERATION != gl.getError())
   3177 				{
   3178 					result = false;
   3179 
   3180 					m_testCtx.getLog() << tcu::TestLog::Message
   3181 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3182 									   << tcu::TestLog::EndMessage;
   3183 
   3184 					break;
   3185 				}
   3186 			}
   3187 
   3188 			if (po != 1)
   3189 			{
   3190 				gl.drawArrays(GL_LINES, 0 /*starting index*/, 2 /*number of indices*/);
   3191 
   3192 				if (GL_INVALID_OPERATION != gl.getError())
   3193 				{
   3194 					result = false;
   3195 
   3196 					m_testCtx.getLog() << tcu::TestLog::Message
   3197 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3198 									   << tcu::TestLog::EndMessage;
   3199 
   3200 					break;
   3201 				}
   3202 
   3203 				gl.drawArrays(GL_LINE_LOOP, 0 /*starting index*/, 2 /*number of indices*/);
   3204 
   3205 				if (GL_INVALID_OPERATION != gl.getError())
   3206 				{
   3207 					result = false;
   3208 
   3209 					m_testCtx.getLog() << tcu::TestLog::Message
   3210 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3211 									   << tcu::TestLog::EndMessage;
   3212 
   3213 					break;
   3214 				}
   3215 
   3216 				gl.drawArrays(GL_LINE_STRIP, 0 /*starting index*/, 2 /*number of indices*/);
   3217 
   3218 				if (GL_INVALID_OPERATION != gl.getError())
   3219 				{
   3220 					result = false;
   3221 
   3222 					m_testCtx.getLog() << tcu::TestLog::Message
   3223 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3224 									   << tcu::TestLog::EndMessage;
   3225 
   3226 					break;
   3227 				}
   3228 			}
   3229 
   3230 			if (po != 2)
   3231 			{
   3232 				gl.drawArrays(GL_LINES_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
   3233 
   3234 				if (GL_INVALID_OPERATION != gl.getError())
   3235 				{
   3236 					result = false;
   3237 
   3238 					m_testCtx.getLog() << tcu::TestLog::Message
   3239 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3240 									   << tcu::TestLog::EndMessage;
   3241 
   3242 					break;
   3243 				}
   3244 
   3245 				gl.drawArrays(GL_LINE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
   3246 
   3247 				if (GL_INVALID_OPERATION != gl.getError())
   3248 				{
   3249 					result = false;
   3250 
   3251 					m_testCtx.getLog() << tcu::TestLog::Message
   3252 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3253 									   << tcu::TestLog::EndMessage;
   3254 
   3255 					break;
   3256 				}
   3257 			}
   3258 
   3259 			if (po != 3)
   3260 			{
   3261 				gl.drawArrays(GL_TRIANGLES, 0 /*starting index*/, 3 /*number of indices*/);
   3262 
   3263 				if (GL_INVALID_OPERATION != gl.getError())
   3264 				{
   3265 					result = false;
   3266 
   3267 					m_testCtx.getLog() << tcu::TestLog::Message
   3268 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3269 									   << tcu::TestLog::EndMessage;
   3270 
   3271 					break;
   3272 				}
   3273 
   3274 				gl.drawArrays(GL_TRIANGLE_FAN, 0 /*starting index*/, 3 /*number of indices*/);
   3275 
   3276 				if (GL_INVALID_OPERATION != gl.getError())
   3277 				{
   3278 					result = false;
   3279 
   3280 					m_testCtx.getLog() << tcu::TestLog::Message
   3281 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3282 									   << tcu::TestLog::EndMessage;
   3283 
   3284 					break;
   3285 				}
   3286 
   3287 				gl.drawArrays(GL_TRIANGLE_STRIP, 0 /*starting index*/, 3 /*number of indices*/);
   3288 
   3289 				if (GL_INVALID_OPERATION != gl.getError())
   3290 				{
   3291 					result = false;
   3292 
   3293 					m_testCtx.getLog() << tcu::TestLog::Message
   3294 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3295 									   << tcu::TestLog::EndMessage;
   3296 
   3297 					break;
   3298 				}
   3299 			}
   3300 
   3301 			if (po != 4)
   3302 			{
   3303 				gl.drawArrays(GL_TRIANGLES_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
   3304 
   3305 				if (GL_INVALID_OPERATION != gl.getError())
   3306 				{
   3307 					result = false;
   3308 
   3309 					m_testCtx.getLog() << tcu::TestLog::Message
   3310 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3311 									   << tcu::TestLog::EndMessage;
   3312 
   3313 					break;
   3314 				}
   3315 
   3316 				gl.drawArrays(GL_TRIANGLE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
   3317 
   3318 				if (GL_INVALID_OPERATION != gl.getError())
   3319 				{
   3320 					result = false;
   3321 
   3322 					m_testCtx.getLog() << tcu::TestLog::Message
   3323 									   << "Error different than GL_INVALID_OPEARATION was generated."
   3324 									   << tcu::TestLog::EndMessage;
   3325 
   3326 					break;
   3327 				}
   3328 			}
   3329 		}
   3330 	}
   3331 
   3332 	if (result)
   3333 	{
   3334 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   3335 	}
   3336 	else
   3337 	{
   3338 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   3339 	}
   3340 
   3341 	return STOP;
   3342 }
   3343 
   3344 /** Constructor
   3345  *
   3346  * @param context       Test context
   3347  * @param extParams     Not used.
   3348  * @param name          Test case's name
   3349  * @param description   Test case's description
   3350  **/
   3351 GeometryShaderInsufficientEmittedVerticesTest::GeometryShaderInsufficientEmittedVerticesTest(
   3352 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
   3353 	: TestCaseBase(context, extParams, name, description)
   3354 	, m_fbo_id(0)
   3355 	, m_fs_id(0)
   3356 	, m_gs_ids(NULL)
   3357 	, m_number_of_color_components(4)
   3358 	, m_number_of_gs(2 /*taken from test spec*/)
   3359 	, m_po_ids(NULL)
   3360 	, m_texture_height(16)
   3361 	, m_texture_id(0)
   3362 	, m_texture_width(16)
   3363 {
   3364 	m_vao_id = 0;
   3365 	m_vs_id  = 0;
   3366 
   3367 	/* Allocate enough memory for glReadPixels() data which is respectively: width, height, RGBA components number. */
   3368 	m_pixels = new glw::GLubyte[m_texture_height * m_texture_width * m_number_of_color_components];
   3369 }
   3370 
   3371 /** Deinitializes GLES objects created during the test. */
   3372 void GeometryShaderInsufficientEmittedVerticesTest::deinit()
   3373 {
   3374 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3375 
   3376 	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
   3377 
   3378 	if (m_pixels != NULL)
   3379 	{
   3380 		delete[] m_pixels;
   3381 		m_pixels = NULL;
   3382 	}
   3383 
   3384 	if (m_fbo_id != 0)
   3385 	{
   3386 		gl.deleteFramebuffers(1, &m_fbo_id);
   3387 		m_fbo_id = 0;
   3388 	}
   3389 
   3390 	if (m_fs_id != 0)
   3391 	{
   3392 		gl.deleteShader(m_fs_id);
   3393 		m_fs_id = 0;
   3394 	}
   3395 
   3396 	if (m_gs_ids != 0)
   3397 	{
   3398 		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
   3399 		{
   3400 			gl.deleteShader(m_gs_ids[i]);
   3401 			m_gs_ids[i] = 0;
   3402 		}
   3403 
   3404 		delete[] m_gs_ids;
   3405 		m_gs_ids = NULL;
   3406 	}
   3407 
   3408 	if (m_po_ids != 0)
   3409 	{
   3410 		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
   3411 		{
   3412 			gl.deleteProgram(m_po_ids[i]);
   3413 			m_po_ids[i] = 0;
   3414 		}
   3415 
   3416 		delete[] m_po_ids;
   3417 		m_po_ids = NULL;
   3418 	}
   3419 
   3420 	if (m_texture_id != 0)
   3421 	{
   3422 		gl.deleteTextures(1, &m_texture_id);
   3423 		m_texture_id = 0;
   3424 	}
   3425 
   3426 	if (m_vao_id != 0)
   3427 	{
   3428 		gl.deleteVertexArrays(1, &m_vao_id);
   3429 		m_vao_id = 0;
   3430 	}
   3431 
   3432 	if (m_vs_id != 0)
   3433 	{
   3434 		gl.deleteShader(m_vs_id);
   3435 		m_vs_id = 0;
   3436 	}
   3437 
   3438 	/* Release base class */
   3439 	TestCaseBase::deinit();
   3440 }
   3441 
   3442 /** Executes the test.
   3443  *
   3444  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   3445  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   3446  *  Note the function throws exception should an error occur!
   3447  **/
   3448 tcu::TestNode::IterateResult GeometryShaderInsufficientEmittedVerticesTest::iterate()
   3449 {
   3450 	/* Define Fragment Shader for purpose of this test. */
   3451 	const char* fs_code = "${VERSION}\n"
   3452 						  "\n"
   3453 						  "precision highp float;\n"
   3454 						  "\n"
   3455 						  "out vec4 result;\n"
   3456 						  "\n"
   3457 						  "void main()\n"
   3458 						  "{\n"
   3459 						  "    result = vec4(1.0, 0.0, 0.0, 0.0);\n"
   3460 						  "}\n";
   3461 
   3462 	/* Define 2 Geometry Shaders for purpose of this test. */
   3463 	const char* gs_line_strip = "${VERSION}\n"
   3464 								"${GEOMETRY_SHADER_REQUIRE}\n"
   3465 								"\n"
   3466 								"layout (points)                       in;\n"
   3467 								"layout (line_strip, max_vertices = 2) out;\n"
   3468 								"\n"
   3469 								"${IN_PER_VERTEX_DECL_ARRAY}"
   3470 								"\n"
   3471 								"void main()\n"
   3472 								"{\n"
   3473 								"    gl_Position    = gl_in[0].gl_Position;\n"
   3474 								"    gl_Position.zw = vec2(0.0, 1.0);\n"
   3475 								"    EmitVertex();\n"
   3476 								"}\n";
   3477 
   3478 	const char* gs_triangle_strip = "${VERSION}\n"
   3479 									"${GEOMETRY_SHADER_REQUIRE}\n"
   3480 									"\n"
   3481 									"layout (points)                           in;\n"
   3482 									"layout (triangle_strip, max_vertices = 3) out;\n"
   3483 									"\n"
   3484 									"${IN_PER_VERTEX_DECL_ARRAY}"
   3485 									"\n"
   3486 									"void main()\n"
   3487 									"{\n"
   3488 									"    gl_Position    = gl_in[0].gl_Position;\n"
   3489 									"    gl_Position.zw = vec2(0.0, 1.0);\n"
   3490 									"    EmitVertex();\n"
   3491 
   3492 									"    gl_Position    = gl_in[0].gl_Position;\n"
   3493 									"    gl_Position.zw = vec2(0.0, 1.0);\n"
   3494 									"    EmitVertex();\n"
   3495 									"}\n";
   3496 
   3497 	bool has_shader_compilation_failed = true;
   3498 	bool result						   = true;
   3499 
   3500 	m_gs_ids = new glw::GLuint[m_number_of_gs];
   3501 	m_po_ids = new glw::GLuint[m_number_of_gs];
   3502 
   3503 	/* This test should only run if EXT_geometry_shader is supported. */
   3504 	if (!m_is_geometry_shader_extension_supported)
   3505 	{
   3506 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   3507 	}
   3508 
   3509 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3510 
   3511 	/* Create program objects & geometry shader objects. */
   3512 	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
   3513 	{
   3514 		m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
   3515 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   3516 
   3517 		m_po_ids[i] = gl.createProgram();
   3518 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   3519 	}
   3520 
   3521 	/* Create shader object. */
   3522 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   3523 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   3524 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   3525 
   3526 	/* Try to link the test program object */
   3527 	std::string fs_code_specialized		= specializeShader(1, &fs_code);
   3528 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
   3529 
   3530 	std::string gs_codes_specialized[] = { specializeShader(1, &gs_line_strip),
   3531 										   specializeShader(1, &gs_triangle_strip) };
   3532 
   3533 	const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str() };
   3534 
   3535 	std::string vs_code_specialized		= specializeShader(1, &dummy_vs_code);
   3536 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
   3537 
   3538 	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
   3539 	{
   3540 		if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,				  /* n_sh1_body_parts */
   3541 										&fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
   3542 										&gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
   3543 										&vs_code_specialized_raw, &has_shader_compilation_failed))
   3544 		{
   3545 			m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
   3546 							   << "[" << i << "]." << tcu::TestLog::EndMessage;
   3547 
   3548 			result = false;
   3549 			break;
   3550 		}
   3551 	}
   3552 
   3553 	if (result)
   3554 	{
   3555 		/* Create a 2D texture. */
   3556 		gl.genTextures(1, &m_texture_id);
   3557 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
   3558 
   3559 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
   3560 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
   3561 
   3562 		gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_RGBA8, 16 /*width taken from spec*/,
   3563 						16 /*height taken from spec*/);
   3564 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
   3565 
   3566 		/* Configure FBO. */
   3567 		gl.genFramebuffers(1, &m_fbo_id);
   3568 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
   3569 
   3570 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
   3571 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
   3572 
   3573 		gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /*level*/);
   3574 		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
   3575 
   3576 		/* Configure VAO. */
   3577 		gl.genVertexArrays(1, &m_vao_id);
   3578 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   3579 
   3580 		gl.bindVertexArray(m_vao_id);
   3581 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   3582 
   3583 		gl.clearColor(0.0f, 1.0f, 0.0f, 0.0f);
   3584 		GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
   3585 
   3586 		for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
   3587 		{
   3588 			/* Use Program Object. */
   3589 			gl.useProgram(m_po_ids[po]);
   3590 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   3591 
   3592 			gl.clear(GL_COLOR_BUFFER_BIT);
   3593 			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
   3594 
   3595 			gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
   3596 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
   3597 
   3598 			gl.readPixels(0 /*x*/, 0 /*y*/, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
   3599 			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
   3600 
   3601 			for (glw::GLuint pixel = 0; pixel < (m_texture_width * m_texture_height * m_number_of_color_components -
   3602 												 m_number_of_color_components);
   3603 				 pixel += m_number_of_color_components)
   3604 			{
   3605 				if (m_pixels[pixel] != 0 && m_pixels[pixel + 1] != 255 && m_pixels[pixel + 2] != 0 &&
   3606 					m_pixels[pixel + 3] != 0)
   3607 				{
   3608 					result = false;
   3609 
   3610 					m_testCtx.getLog() << tcu::TestLog::Message << "Pixel [" << pixel << "] has color = ["
   3611 									   << m_pixels[pixel] << ", " << m_pixels[pixel + 1] << ", " << m_pixels[pixel + 2]
   3612 									   << ", " << m_pixels[pixel + 3] << "] "
   3613 									   << "instead of [0, 255, 0, 0]." << tcu::TestLog::EndMessage;
   3614 
   3615 					break;
   3616 				}
   3617 			}
   3618 		}
   3619 	}
   3620 
   3621 	if (result)
   3622 	{
   3623 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   3624 	}
   3625 	else
   3626 	{
   3627 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   3628 	}
   3629 
   3630 	return STOP;
   3631 }
   3632 
   3633 /** Constructor
   3634  *
   3635  * @param context       Test context
   3636  * @param extParams     Not used.
   3637  * @param name          Test case's name
   3638  * @param description   Test case's description
   3639  **/
   3640 GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::
   3641 	GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context&			 context,
   3642 																					const ExtParameters& extParams,
   3643 																					const char*			 name,
   3644 																					const char*			 description)
   3645 	: TestCaseBase(context, extParams, name, description)
   3646 	, m_gs_id(0)
   3647 	, m_gs_po_id(0)
   3648 	, m_ppo_id(0)
   3649 	, m_tfbo_id(0)
   3650 	, m_vao_id(0)
   3651 	, m_vs_id(0)
   3652 	, m_vs_po_id(0)
   3653 {
   3654 }
   3655 
   3656 /** Deinitializes GLES objects created during the test. */
   3657 void GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::deinit()
   3658 {
   3659 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3660 
   3661 	if (m_gs_id != 0)
   3662 	{
   3663 		gl.deleteShader(m_gs_id);
   3664 		m_gs_id = 0;
   3665 	}
   3666 
   3667 	if (m_gs_po_id != 0)
   3668 	{
   3669 		gl.deleteProgram(m_gs_po_id);
   3670 		m_gs_po_id = 0;
   3671 	}
   3672 
   3673 	if (m_ppo_id != 0)
   3674 	{
   3675 		gl.deleteProgramPipelines(1, &m_ppo_id);
   3676 		m_ppo_id = 0;
   3677 	}
   3678 
   3679 	if (m_tfbo_id != 0)
   3680 	{
   3681 		gl.deleteBuffers(1, &m_tfbo_id);
   3682 		m_tfbo_id = 0;
   3683 	}
   3684 
   3685 	if (m_vao_id != 0)
   3686 	{
   3687 		gl.deleteVertexArrays(1, &m_vao_id);
   3688 		m_vao_id = 0;
   3689 	}
   3690 
   3691 	if (m_vs_id != 0)
   3692 	{
   3693 		gl.deleteShader(m_vs_id);
   3694 		m_vs_id = 0;
   3695 	}
   3696 
   3697 	if (m_vs_po_id != 0)
   3698 	{
   3699 		gl.deleteProgram(m_vs_po_id);
   3700 		m_vs_po_id = 0;
   3701 	}
   3702 
   3703 	/* Release base class */
   3704 	TestCaseBase::deinit();
   3705 }
   3706 
   3707 /** Executes the test.
   3708  *
   3709  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   3710  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   3711  *  Note the function throws exception should an error occur!
   3712  **/
   3713 tcu::TestNode::IterateResult GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::iterate()
   3714 {
   3715 	/* Define Geometry Shader for purpose of this test. */
   3716 	const char* gs_code =
   3717 		"${VERSION}\n"
   3718 		"${GEOMETRY_SHADER_REQUIRE}\n"
   3719 		"${IN_PER_VERTEX_DECL_ARRAY}\n"
   3720 		"${OUT_PER_VERTEX_DECL}\n"
   3721 		"\n"
   3722 		"layout (points)                   in;\n"
   3723 		"layout (points, max_vertices = 1) out;\n"
   3724 		"\n"
   3725 		"flat in int   vertexID[];\n"
   3726 		"flat in ivec4 out_vs_1[];\n"
   3727 		"\n"
   3728 		"out vec4 out_gs_1;\n"
   3729 		"\n"
   3730 		"void main()\n"
   3731 		"{\n"
   3732 		"    out_gs_1 = vec4(vertexID[0] * 2, vertexID[0] * 2 + 1, vertexID[0] * 2 + 2, vertexID[0] * 2 + 3);\n"
   3733 		"    gl_Position = vec4(0, 0, 0, 1);\n"
   3734 		"    EmitVertex();\n"
   3735 		"}\n";
   3736 
   3737 	/* Define Vertex Shader for purpose of this test. */
   3738 	const char* vs_code = "${VERSION}\n"
   3739 						  "${OUT_PER_VERTEX_DECL}\n"
   3740 						  "\n"
   3741 						  "flat out ivec4 out_vs_1;\n"
   3742 						  "flat out int vertexID;\n"
   3743 						  "\n"
   3744 						  "void main()\n"
   3745 						  "{\n"
   3746 						  "    vertexID = gl_VertexID;\n"
   3747 						  "    out_vs_1 = ivec4(gl_VertexID, gl_VertexID + 1, gl_VertexID + 2, gl_VertexID + 3);\n"
   3748 						  "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
   3749 						  "}\n";
   3750 
   3751 	bool		  has_shader_compilation_failed = true;
   3752 	bool		  result						= true;
   3753 	glw::GLfloat* ptrTF_data_f					= NULL;
   3754 	glw::GLuint*  ptrTF_data_ui					= NULL;
   3755 	glw::GLfloat  expected_geom_results[]		= { 0.0f, 1.0f, 2.0f, 3.0f };
   3756 	glw::GLuint   expected_vertex_results[]		= { 0, 1, 2, 3 };
   3757 	glw::GLfloat  epsilon						= 1e-5f;
   3758 
   3759 	/* This test should only run if EXT_geometry_shader is supported. */
   3760 	if (!m_is_geometry_shader_extension_supported)
   3761 	{
   3762 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   3763 	}
   3764 
   3765 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3766 
   3767 	/* Create separable program objects. */
   3768 	m_gs_po_id = gl.createProgram();
   3769 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   3770 
   3771 	gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
   3772 	GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
   3773 
   3774 	m_vs_po_id = gl.createProgram();
   3775 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   3776 
   3777 	gl.programParameteri(m_vs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
   3778 	GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
   3779 
   3780 	/* Create shader objects. */
   3781 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   3782 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   3783 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   3784 
   3785 	/* Try to link the test program object */
   3786 	std::string gs_code_specialized		= specializeShader(1, &gs_code);
   3787 	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
   3788 
   3789 	std::string vs_code_specialized		= specializeShader(1, &vs_code);
   3790 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
   3791 
   3792 	/* Specify output variables to be captured. */
   3793 	const char* tf_varyings[2] = { "out_gs_1", "out_vs_1" };
   3794 
   3795 	gl.transformFeedbackVaryings(m_gs_po_id, 1 /*count*/, &tf_varyings[0], GL_INTERLEAVED_ATTRIBS);
   3796 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
   3797 
   3798 	gl.transformFeedbackVaryings(m_vs_po_id, 1 /*count*/, &tf_varyings[1], GL_INTERLEAVED_ATTRIBS);
   3799 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
   3800 
   3801 	if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1,			/* n_sh1_body_parts */
   3802 									&gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
   3803 									NULL, 0, 0,						/* n_sh3_body_parts */
   3804 									NULL, &has_shader_compilation_failed))
   3805 	{
   3806 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
   3807 						   << tcu::TestLog::EndMessage;
   3808 
   3809 		result = false;
   3810 		goto end;
   3811 	}
   3812 
   3813 	if (!TestCaseBase::buildProgram(m_vs_po_id, m_vs_id, 1,			/* n_sh1_body_parts */
   3814 									&vs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
   3815 									NULL, 0, 0,						/* n_sh3_body_parts */
   3816 									NULL, &has_shader_compilation_failed))
   3817 	{
   3818 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
   3819 						   << tcu::TestLog::EndMessage;
   3820 
   3821 		result = false;
   3822 		goto end;
   3823 	}
   3824 
   3825 	/* Create and configure Program Pipeline Object. */
   3826 	gl.genProgramPipelines(1, &m_ppo_id);
   3827 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call(s) failed.");
   3828 
   3829 	gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
   3830 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
   3831 
   3832 	gl.useProgramStages(m_ppo_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
   3833 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
   3834 
   3835 	/* Create Vertex Array Object. */
   3836 	gl.genVertexArrays(1, &m_vao_id);
   3837 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
   3838 
   3839 	gl.bindVertexArray(m_vao_id);
   3840 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
   3841 
   3842 	/* Create Buffer Object for Transform Feedback data. */
   3843 	gl.genBuffers(1, &m_tfbo_id);
   3844 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
   3845 
   3846 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
   3847 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
   3848 
   3849 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4, NULL, GL_STREAM_READ);
   3850 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
   3851 
   3852 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
   3853 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
   3854 
   3855 	/* Ensure that there is no program object already bound and bind program pipeline. */
   3856 	gl.useProgram(0);
   3857 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
   3858 
   3859 	gl.bindProgramPipeline(m_ppo_id);
   3860 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
   3861 
   3862 	gl.enable(GL_RASTERIZER_DISCARD);
   3863 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
   3864 
   3865 	/* First pass - Vertex and Geometry Shaders On. */
   3866 	gl.beginTransformFeedback(GL_POINTS);
   3867 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
   3868 
   3869 	gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
   3870 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
   3871 
   3872 	gl.endTransformFeedback();
   3873 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
   3874 
   3875 	/* Retrieve data and check if it is correct. */
   3876 	ptrTF_data_f =
   3877 		(glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
   3878 										 sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
   3879 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   3880 
   3881 	for (size_t i = 0; i < 4; ++i)
   3882 	{
   3883 		if (fabs(ptrTF_data_f[i] - expected_geom_results[i]) >= epsilon)
   3884 		{
   3885 			result = false;
   3886 			break;
   3887 		}
   3888 	}
   3889 
   3890 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   3891 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   3892 
   3893 	ptrTF_data_f = NULL;
   3894 
   3895 	if (!result)
   3896 	{
   3897 		goto end;
   3898 	}
   3899 
   3900 	/* Deactivate Geometry Shader Program Object from Program Pipeline Object. */
   3901 	gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, 0 /* program */);
   3902 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
   3903 
   3904 	/* Second pass - only Vertex Shader Program On. */
   3905 	gl.beginTransformFeedback(GL_POINTS);
   3906 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
   3907 
   3908 	gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
   3909 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
   3910 
   3911 	gl.endTransformFeedback();
   3912 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
   3913 
   3914 	gl.disable(GL_RASTERIZER_DISCARD);
   3915 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
   3916 
   3917 	/* Retrieve data and check if it is correct. */
   3918 	ptrTF_data_ui =
   3919 		(glw::GLuint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
   3920 										sizeof(glw::GLuint) * 4 /* four float vector components */, GL_MAP_READ_BIT);
   3921 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
   3922 
   3923 	for (size_t i = 0; i < 4; ++i)
   3924 	{
   3925 		if (ptrTF_data_ui[i] != expected_vertex_results[i])
   3926 		{
   3927 			result = false;
   3928 			break;
   3929 		}
   3930 	}
   3931 
   3932 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   3933 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   3934 
   3935 	ptrTF_data_ui = NULL;
   3936 
   3937 end:
   3938 	if (result)
   3939 	{
   3940 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   3941 	}
   3942 	else
   3943 	{
   3944 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   3945 	}
   3946 
   3947 	return STOP;
   3948 }
   3949 
   3950 /** Constructor
   3951  *
   3952  * @param context       Test context
   3953  * @param extParams     Not used.
   3954  * @param name          Test case's name
   3955  * @param description   Test case's description
   3956  **/
   3957 GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives(
   3958 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
   3959 	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_tfbo_id(0)
   3960 {
   3961 	m_vao_id = 0;
   3962 	m_vs_id  = 0;
   3963 }
   3964 
   3965 /** Deinitializes GLES objects created during the test. */
   3966 void GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::deinit()
   3967 {
   3968 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   3969 
   3970 	if (m_fs_id != 0)
   3971 	{
   3972 		gl.deleteShader(m_fs_id);
   3973 		m_fs_id = 0;
   3974 	}
   3975 
   3976 	if (m_gs_id != 0)
   3977 	{
   3978 		gl.deleteShader(m_gs_id);
   3979 		m_gs_id = 0;
   3980 	}
   3981 
   3982 	if (m_po_id != 0)
   3983 	{
   3984 		gl.deleteProgram(m_po_id);
   3985 		m_po_id = 0;
   3986 	}
   3987 
   3988 	if (m_tfbo_id != 0)
   3989 	{
   3990 		gl.deleteBuffers(1, &m_tfbo_id);
   3991 		m_tfbo_id = 0;
   3992 	}
   3993 
   3994 	if (m_vao_id != 0)
   3995 	{
   3996 		gl.deleteVertexArrays(1, &m_vao_id);
   3997 		m_vao_id = 0;
   3998 	}
   3999 
   4000 	if (m_vs_id != 0)
   4001 	{
   4002 		gl.deleteShader(m_vs_id);
   4003 		m_vs_id = 0;
   4004 	}
   4005 
   4006 	/* Release base class */
   4007 	TestCaseBase::deinit();
   4008 }
   4009 
   4010 /** Executes the test.
   4011  *
   4012  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   4013  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   4014  *  Note the function throws exception should an error occur!
   4015  **/
   4016 tcu::TestNode::IterateResult GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::iterate()
   4017 {
   4018 	/* Define Geometry Shader for purpose of this test. */
   4019 	const char* gs_code = "${VERSION}\n"
   4020 						  "${GEOMETRY_SHADER_REQUIRE}\n"
   4021 						  "\n"
   4022 						  "layout (lines)                            in;\n"
   4023 						  "layout (triangle_strip, max_vertices = 3) out;\n"
   4024 						  "\n"
   4025 						  "out vec4 out_gs_1;\n"
   4026 						  "\n"
   4027 						  "void main()\n"
   4028 						  "{\n"
   4029 						  "    out_gs_1 = vec4(4.0, 3.0, 2.0, 1.0);\n"
   4030 						  "\n"
   4031 						  "    gl_Position = vec4(0, 0, 0, 1);\n"
   4032 						  "    EmitVertex();\n"
   4033 						  "\n"
   4034 						  "    gl_Position = vec4(1, 0, 0, 1);\n"
   4035 						  "    EmitVertex();\n"
   4036 						  "\n"
   4037 						  "    gl_Position = vec4(1, 1, 0, 1);\n"
   4038 						  "    EmitVertex();\n"
   4039 						  "\n"
   4040 						  "    EndPrimitive();"
   4041 						  "}\n";
   4042 
   4043 	bool		has_shader_compilation_failed = true;
   4044 	bool		result						  = true;
   4045 	glw::GLenum error						  = GL_NO_ERROR;
   4046 
   4047 	/* This test should only run if EXT_geometry_shader is supported. */
   4048 	if (!m_is_geometry_shader_extension_supported)
   4049 	{
   4050 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   4051 	}
   4052 
   4053 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   4054 
   4055 	/* Create program object. */
   4056 	m_po_id = gl.createProgram();
   4057 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   4058 
   4059 	/* Specify output variables to be captured. */
   4060 	const char* tf_varyings[] = { "out_gs_1" };
   4061 
   4062 	gl.transformFeedbackVaryings(m_po_id, 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
   4063 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
   4064 
   4065 	/* Create shader objects. */
   4066 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   4067 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   4068 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   4069 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   4070 
   4071 	/* Try to link the test program object */
   4072 	std::string fs_code_specialized		= specializeShader(1, &dummy_fs_code);
   4073 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
   4074 
   4075 	std::string gs_code_specialized		= specializeShader(1, &gs_code);
   4076 	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
   4077 
   4078 	std::string vs_code_specialized		= specializeShader(1, &dummy_vs_code);
   4079 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
   4080 
   4081 	if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1,				  /* n_sh1_body_parts */
   4082 									&fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
   4083 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
   4084 									&vs_code_specialized_raw, &has_shader_compilation_failed))
   4085 	{
   4086 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed whereas a success was expected."
   4087 						   << tcu::TestLog::EndMessage;
   4088 
   4089 		result = false;
   4090 		goto end;
   4091 	}
   4092 
   4093 	/* Create Vertex Array Object. */
   4094 	gl.genVertexArrays(1, &m_vao_id);
   4095 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
   4096 
   4097 	gl.bindVertexArray(m_vao_id);
   4098 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
   4099 
   4100 	/* Create Buffer Object for Transform Feedback data. */
   4101 	gl.genBuffers(1, &m_tfbo_id);
   4102 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
   4103 
   4104 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
   4105 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
   4106 
   4107 	gl.bufferData(GL_ARRAY_BUFFER,
   4108 				  sizeof(glw::GLfloat) * 4 * 3 /* capture 4 float vector components times 3 triangle vertices */, NULL,
   4109 				  GL_STREAM_READ);
   4110 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
   4111 
   4112 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
   4113 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
   4114 
   4115 	/* Turn on program object. */
   4116 	gl.useProgram(m_po_id);
   4117 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
   4118 
   4119 	gl.enable(GL_RASTERIZER_DISCARD);
   4120 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
   4121 
   4122 	gl.beginTransformFeedback(GL_LINES);
   4123 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
   4124 
   4125 	gl.drawArrays(GL_TRIANGLES, 0 /*first*/, 3 /*count*/);
   4126 
   4127 	error = gl.getError();
   4128 
   4129 	if (error != GL_INVALID_OPERATION)
   4130 	{
   4131 		result = false;
   4132 
   4133 		m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
   4134 						   << tcu::TestLog::EndMessage;
   4135 	}
   4136 
   4137 	gl.endTransformFeedback();
   4138 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
   4139 
   4140 	gl.disable(GL_RASTERIZER_DISCARD);
   4141 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
   4142 
   4143 end:
   4144 
   4145 	if (result)
   4146 	{
   4147 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   4148 	}
   4149 	else
   4150 	{
   4151 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   4152 	}
   4153 
   4154 	return STOP;
   4155 }
   4156 
   4157 /** Constructor
   4158  *
   4159  * @param context       Test context
   4160  * @param extParams     Not used.
   4161  * @param name          Test case's name
   4162  * @param description   Test case's description
   4163  **/
   4164 GeometryShaderDrawCallsWhileTFPaused::GeometryShaderDrawCallsWhileTFPaused(Context&				context,
   4165 																		   const ExtParameters& extParams,
   4166 																		   const char* name, const char* description)
   4167 	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_tfbo_id(0)
   4168 {
   4169 	m_vao_id = 0;
   4170 	m_vs_id  = 0;
   4171 }
   4172 
   4173 /** Deinitializes GLES objects created during the test. */
   4174 void GeometryShaderDrawCallsWhileTFPaused::deinit()
   4175 {
   4176 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   4177 
   4178 	if (m_fs_id != 0)
   4179 	{
   4180 		gl.deleteShader(m_fs_id);
   4181 		m_fs_id = 0;
   4182 	}
   4183 
   4184 	if (m_gs_id != 0)
   4185 	{
   4186 		gl.deleteShader(m_gs_id);
   4187 		m_gs_id = 0;
   4188 	}
   4189 
   4190 	for (int i = 0; i < 15 /* All combinations of possible inputs and outputs in GS */; ++i)
   4191 	{
   4192 		if (m_po_ids[i] != 0)
   4193 		{
   4194 			gl.deleteProgram(m_po_ids[i]);
   4195 			m_po_ids[i] = 0;
   4196 		}
   4197 	}
   4198 
   4199 	if (m_tfbo_id != 0)
   4200 	{
   4201 		gl.deleteBuffers(1, &m_tfbo_id);
   4202 		m_tfbo_id = 0;
   4203 	}
   4204 
   4205 	if (m_vao_id != 0)
   4206 	{
   4207 		gl.deleteVertexArrays(1, &m_vao_id);
   4208 		m_vao_id = 0;
   4209 	}
   4210 
   4211 	if (m_vs_id != 0)
   4212 	{
   4213 		gl.deleteShader(m_vs_id);
   4214 		m_vs_id = 0;
   4215 	}
   4216 
   4217 	/* Release base class */
   4218 	TestCaseBase::deinit();
   4219 }
   4220 
   4221 /** Executes the test.
   4222  *
   4223  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   4224  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   4225  *  Note the function throws exception should an error occur!
   4226  **/
   4227 tcu::TestNode::IterateResult GeometryShaderDrawCallsWhileTFPaused::iterate()
   4228 {
   4229 	/* Define 15 (all combinations of possible inputs and outputs in geometry shader) Geometry Shaders for purpose of this test. */
   4230 	const std::string gs_inputs[]  = { "points", "lines", "lines_adjacency", "triangles", "triangles_adjacency" };
   4231 	const std::string gs_outputs[] = { "points", "line_strip", "triangle_strip" };
   4232 	const std::string gs_max_output_vertices[] = { "1", "2", "3" };
   4233 
   4234 	const unsigned short number_of_combinations =
   4235 		(sizeof(gs_inputs) / sizeof(gs_inputs[0]) * (sizeof(gs_outputs) / sizeof(gs_outputs[0])));
   4236 
   4237 	std::string gs_codes[number_of_combinations];
   4238 	glw::GLenum errorCode;
   4239 
   4240 	for (size_t i = 0; i < (sizeof(gs_inputs) / sizeof(gs_inputs[0])) /*5 possible GS inputs*/; ++i)
   4241 	{
   4242 		for (size_t j = 0; j < (sizeof(gs_outputs) / sizeof(gs_outputs[0])) /*3 possible GS outputs*/; ++j)
   4243 		{
   4244 			/* This shader will not emit primitives for anything but points.
   4245 			 * We do so, because we just need to make sure that, while transform feedback
   4246 			 * is paused, all draw calls executed with an active program object which
   4247 			 * includes a geometry shader, are valid.
   4248 			 */
   4249 			gs_codes[j + 3 * i] = "${VERSION}\n"
   4250 								  "${GEOMETRY_SHADER_REQUIRE}\n"
   4251 								  "\n"
   4252 								  "layout (" +
   4253 								  gs_inputs[i] + ") in;\n"
   4254 												 "layout (" +
   4255 								  gs_outputs[j] + ", max_vertices = " + gs_max_output_vertices[j] +
   4256 								  ") out;\n"
   4257 								  "\n"
   4258 								  "out vec2 out_gs_1;\n"
   4259 								  "\n"
   4260 								  "void main()\n"
   4261 								  "{\n"
   4262 								  "    out_gs_1    = vec2(1.0, 2.0);\n"
   4263 								  "    gl_Position = vec4(0, 0, 0, 1);\n"
   4264 								  "    EmitVertex();\n"
   4265 								  "}\n";
   4266 		}
   4267 	}
   4268 
   4269 	bool			  has_shader_compilation_failed = true;
   4270 	bool			  result						= true;
   4271 	const glw::GLuint tf_modes[3]					= { GL_POINTS, GL_LINES, GL_TRIANGLES };
   4272 	const glw::GLuint draw_call_modes[5]			= { GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES,
   4273 											 GL_TRIANGLES_ADJACENCY };
   4274 
   4275 	/* This test should only run if EXT_geometry_shader is supported. */
   4276 	if (!m_is_geometry_shader_extension_supported)
   4277 	{
   4278 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   4279 	}
   4280 
   4281 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   4282 
   4283 	/* Create program objects. */
   4284 	for (int i = 0; i < number_of_combinations; ++i)
   4285 	{
   4286 		m_po_ids[i] = gl.createProgram();
   4287 	}
   4288 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
   4289 
   4290 	/* Specify output variables to be captured. */
   4291 	const char* tf_varyings[] = { "out_gs_1" };
   4292 
   4293 	for (int i = 0; i < number_of_combinations; ++i)
   4294 	{
   4295 		gl.transformFeedbackVaryings(m_po_ids[i], 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
   4296 	}
   4297 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
   4298 
   4299 	/* Create shader objects. */
   4300 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   4301 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   4302 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   4303 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   4304 
   4305 	/* Try to link the test program object */
   4306 	std::string fs_code_specialized		= specializeShader(1, &dummy_fs_code);
   4307 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
   4308 
   4309 	std::string vs_code_specialized		= specializeShader(1, &dummy_vs_code);
   4310 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
   4311 
   4312 	for (int i = 0; i < number_of_combinations; ++i)
   4313 	{
   4314 		const char* gs_code					= gs_codes[i].c_str();
   4315 		std::string gs_code_specialized		= specializeShader(1, &gs_code);
   4316 		const char* gs_code_specialized_raw = gs_code_specialized.c_str();
   4317 
   4318 		if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,			  /* n_sh1_body_parts */
   4319 										&fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
   4320 										&gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
   4321 										&vs_code_specialized_raw, &has_shader_compilation_failed))
   4322 		{
   4323 			m_testCtx.getLog() << tcu::TestLog::Message
   4324 							   << "Program object linking failed whereas a success was expected."
   4325 							   << tcu::TestLog::EndMessage;
   4326 
   4327 			result = false;
   4328 		}
   4329 	}
   4330 
   4331 	if (!result)
   4332 	{
   4333 		goto end;
   4334 	}
   4335 
   4336 	/* Create Vertex Array Object. */
   4337 	gl.genVertexArrays(1, &m_vao_id);
   4338 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
   4339 
   4340 	gl.bindVertexArray(m_vao_id);
   4341 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
   4342 
   4343 	/* Create Buffer Object for Transform Feedback data. */
   4344 	gl.genBuffers(1, &m_tfbo_id);
   4345 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
   4346 
   4347 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
   4348 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
   4349 
   4350 	gl.bufferData(GL_ARRAY_BUFFER,
   4351 				  sizeof(glw::GLfloat) * 2 * 3 /* capture 2 float vector components times 3 triangle vertices */, NULL,
   4352 				  GL_STREAM_READ);
   4353 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
   4354 
   4355 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
   4356 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
   4357 
   4358 	gl.enable(GL_RASTERIZER_DISCARD);
   4359 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
   4360 
   4361 	for (int i = 0; i < 3 /* number of TF modes */ && result; ++i)
   4362 	{
   4363 		for (int j = 0; j < 5 /*number of draw call modes*/ && result; ++j)
   4364 		{
   4365 			for (int k = 0; k < 3 /* number of output GS primitive types */; ++k)
   4366 			{
   4367 				/* Turn on program object. */
   4368 				gl.useProgram(m_po_ids[k + 3 * j]);
   4369 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
   4370 
   4371 				gl.beginTransformFeedback(tf_modes[i]);
   4372 				GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
   4373 
   4374 				gl.pauseTransformFeedback();
   4375 				GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback() call(s) failed.");
   4376 
   4377 				gl.drawArrays(draw_call_modes[j], 0 /*first*/, 3 /*count*/);
   4378 				errorCode = gl.getError();
   4379 
   4380 				gl.resumeTransformFeedback();
   4381 				GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback() call(s) failed.");
   4382 
   4383 				gl.endTransformFeedback();
   4384 				GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
   4385 
   4386 				/* If draw call fails stop test execution. */
   4387 				if (GL_NO_ERROR != errorCode)
   4388 				{
   4389 					m_testCtx.getLog() << tcu::TestLog::Message
   4390 									   << "glDrawArrays() call generated an error while transform feedback was paused."
   4391 									   << tcu::TestLog::EndMessage;
   4392 
   4393 					result = false;
   4394 					break;
   4395 				}
   4396 			}
   4397 		}
   4398 	}
   4399 
   4400 	gl.disable(GL_RASTERIZER_DISCARD);
   4401 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
   4402 
   4403 end:
   4404 
   4405 	if (result)
   4406 	{
   4407 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   4408 	}
   4409 	else
   4410 	{
   4411 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   4412 	}
   4413 
   4414 	return STOP;
   4415 }
   4416 
   4417 } // namespace glcts
   4418