• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  **/
GeometryShaderCreateShaderProgramvTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)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. */
deinit()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. */
initFBO()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 */
initPipelineObject()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  **/
iterate()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  **/
GeometryShaderGetShaderivTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)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. */
deinit()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  **/
iterate()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  **/
GeometryShaderGetProgramivTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)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. */
deinit()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  **/
iterate()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  **/
GeometryShaderGetProgramiv2Test(Context & context,const ExtParameters & extParams,const char * name,const char * description)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. */
deinit()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  **/
iterate()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  **/
GeometryShaderGetProgramiv3Test(Context & context,const ExtParameters & extParams,const char * name,const char * description)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 */
buildShader(glw::GLuint so_id,const char * so_body)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  */
buildShaderProgram(glw::GLuint * out_spo_id,glw::GLenum spo_bits,const char * spo_body)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. */
deinit()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. */
deinitPO()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. */
deinitSOs(bool release_all_SOs)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. */
deinitSPOs(bool release_all_SPOs)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  */
getLayoutQualifierForPrimitiveType(glw::GLenum primitive_type)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  */
getGSCode(const _run & run)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. */
initTestRuns()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  **/
iterate()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  **/
GeometryShaderDrawCallWithFSAndGS(Context & context,const ExtParameters & extParams,const char * name,const char * description)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. */
deinit()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  **/
iterate()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  **/
GeometryShaderMaxImageUniformsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)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. */
deinit()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  */
getGSCode()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  **/
iterate()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 	/* Retrieve GL_MAX_IMAGE_UNITS pname value */
1558 	glw::GLint m_gl_max_image_units_value = 0;
1559 	gl.getIntegerv(GL_MAX_IMAGE_UNITS, &m_gl_max_image_units_value);
1560 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_IMAGE_UNITS pname");
1561 
1562 	/* Check if m_gl_max_geometry_image_uniforms_value is less than or equal zero. */
1563 	if (m_gl_max_geometry_image_uniforms_ext_value <= 0)
1564 	{
1565 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
1566 						   << "[" << m_gl_max_geometry_image_uniforms_ext_value
1567 						   << "]"
1568 							  " is less than or equal zero. Image uniforms in Geometry Shader"
1569 							  " are not supported."
1570 						   << tcu::TestLog::EndMessage;
1571 
1572 		if (m_gl_max_geometry_image_uniforms_ext_value == 0)
1573 		{
1574 			throw tcu::NotSupportedError("GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT is 0");
1575 		}
1576 		else
1577 		{
1578 			result = false;
1579 			goto end;
1580 		}
1581 	}
1582 
1583 	/* Check if m_gl_max_image_units_value is less than m_gl_max_geometry_image_uniforms_value. */
1584 	if (m_gl_max_image_units_value < m_gl_max_geometry_image_uniforms_ext_value)
1585 	{
1586 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
1587 						   << "[" << m_gl_max_geometry_image_uniforms_ext_value
1588 						   << "]"
1589 							  " is greater than GL_MAX_IMAGE_UNITS query value "
1590 							  "["
1591 						   << m_gl_max_image_units_value << "]." << tcu::TestLog::EndMessage;
1592 
1593 		result = false;
1594 		goto end;
1595 	}
1596 
1597 	/* Create a program object. */
1598 	m_po_id = gl.createProgram();
1599 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1600 
1601 	/* Create shader objects. */
1602 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1603 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1604 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1605 
1606 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1607 
1608 	/* Configure which outputs should be captured by Transform Feedback. */
1609 	gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
1610 
1611 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
1612 
1613 	/* Try to link the test program object */
1614 	fs_code_specialized		= specializeShader(1, &dummy_fs_code);
1615 	fs_code_specialized_raw = fs_code_specialized.c_str();
1616 
1617 	gs_code_specialized		= getGSCode();
1618 	gs_code_specialized_raw = gs_code_specialized.c_str();
1619 
1620 	vs_code_specialized		= specializeShader(1, &dummy_vs_code);
1621 	vs_code_specialized_raw = vs_code_specialized.c_str();
1622 
1623 	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
1624 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1625 									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1626 									&fs_code_specialized_raw, &has_shader_compilation_failed))
1627 	{
1628 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
1629 
1630 		result = false;
1631 		goto end;
1632 	}
1633 
1634 	/* Use program. */
1635 	gl.useProgram(m_po_id);
1636 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1637 
1638 	/* Allocate memory for m_max_image_units_value Texture Objects. */
1639 	m_texture_ids = new glw::GLuint[m_gl_max_geometry_image_uniforms_ext_value];
1640 
1641 	/* Generate m_max_image_units_value Texture Objects. */
1642 	gl.genTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids);
1643 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
1644 
1645 	/* Set GL_PACK_ALIGNMENT to 1. */
1646 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1647 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname.");
1648 
1649 	/* Bind integer 2D texture objects of resolution 1x1 to image units. */
1650 	for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
1651 	{
1652 		glw::GLint texture = m_texture_ids[n_img];
1653 		glw::GLint value   = n_img + 1;
1654 
1655 		gl.bindTexture(GL_TEXTURE_2D, texture);
1656 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1657 
1658 		gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_R32I, 1 /*width*/, 1 /*height*/);
1659 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1660 
1661 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /*level*/, 0 /*xoffset*/, 0 /*yoffset*/, 1 /*width*/, 1 /*height*/,
1662 						 GL_RED_INTEGER, GL_INT, &value);
1663 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
1664 
1665 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1666 		GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
1667 
1668 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1669 		GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
1670 
1671 		gl.bindImageTexture(n_img, texture, 0 /*level*/, GL_FALSE /*is layered?*/, 0 /*layer*/, GL_READ_ONLY, GL_R32I);
1672 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed.");
1673 	}
1674 
1675 	/* Configure VAO. */
1676 	gl.genVertexArrays(1, &m_vao_id);
1677 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1678 
1679 	gl.bindVertexArray(m_vao_id);
1680 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1681 
1682 	/* Create a Buffer Object for Transform Feedback's outputs. */
1683 	gl.genBuffers(1, &m_tfbo_id);
1684 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1685 
1686 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
1687 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1688 
1689 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, NULL, GL_STATIC_READ);
1690 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1691 
1692 	/* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
1693 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tfbo_id);
1694 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
1695 
1696 	/* Disable rasterization and make a draw call. After that, turn on rasterization. */
1697 	gl.enable(GL_RASTERIZER_DISCARD);
1698 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
1699 
1700 	gl.beginTransformFeedback(GL_POINTS);
1701 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
1702 
1703 	gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
1704 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
1705 
1706 	gl.endTransformFeedback();
1707 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
1708 
1709 	gl.disable(GL_RASTERIZER_DISCARD);
1710 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
1711 
1712 	/* Retrieve value from Transform Feedback. */
1713 	counter = 0;
1714 	ptr		= (glw::GLfloat*)gl.mapBufferRange(
1715 		GL_ARRAY_BUFFER, 0, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
1716 
1717 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
1718 
1719 	counter = int(ptr[0] + 0.5f);
1720 
1721 	gl.unmapBuffer(GL_ARRAY_BUFFER);
1722 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
1723 
1724 	/* Calculate expected value. */
1725 	expectedValue = m_gl_max_geometry_image_uniforms_ext_value * (m_gl_max_geometry_image_uniforms_ext_value + 1) / 2;
1726 
1727 	if (counter != expectedValue)
1728 	{
1729 		result = false;
1730 	}
1731 
1732 end:
1733 	if (result)
1734 	{
1735 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1736 	}
1737 	else
1738 	{
1739 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1740 	}
1741 
1742 	return STOP;
1743 }
1744 
1745 /** Constructor
1746  *
1747  * @param context       Test context
1748  * @param extParams     Not used.
1749  * @param name          Test case's name
1750  * @param description   Test case's description
1751  **/
GeometryShaderMaxShaderStorageBlocksTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1752 GeometryShaderMaxShaderStorageBlocksTest::GeometryShaderMaxShaderStorageBlocksTest(Context&				context,
1753 																				   const ExtParameters& extParams,
1754 																				   const char*			name,
1755 																				   const char*			description)
1756 	: TestCaseBase(context, extParams, name, description)
1757 	, m_fs_id(0)
1758 	, m_gl_max_geometry_shader_storage_blocks_ext_value(0)
1759 	, m_gs_id(0)
1760 	, m_po_id(0)
1761 	, m_ssbo_id(0)
1762 	, m_tfbo_id(0)
1763 	, m_vao_id(0)
1764 	, m_vs_id(0)
1765 {
1766 }
1767 
1768 /** Deinitializes GLES objects created during the test. */
deinit()1769 void GeometryShaderMaxShaderStorageBlocksTest::deinit()
1770 {
1771 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1772 
1773 	if (m_fs_id != 0)
1774 	{
1775 		gl.deleteShader(m_fs_id);
1776 		m_fs_id = 0;
1777 	}
1778 
1779 	if (m_gs_id != 0)
1780 	{
1781 		gl.deleteShader(m_gs_id);
1782 		m_gs_id = 0;
1783 	}
1784 
1785 	if (m_po_id != 0)
1786 	{
1787 		gl.deleteProgram(m_po_id);
1788 		m_po_id = 0;
1789 	}
1790 
1791 	if (m_ssbo_id != 0)
1792 	{
1793 		gl.deleteBuffers(1, &m_ssbo_id);
1794 		m_ssbo_id = 0;
1795 	}
1796 
1797 	if (m_tfbo_id != 0)
1798 	{
1799 		gl.deleteBuffers(1, &m_tfbo_id);
1800 		m_tfbo_id = 0;
1801 	}
1802 
1803 	if (m_vao_id != 0)
1804 	{
1805 		gl.deleteVertexArrays(1, &m_vao_id);
1806 		m_vao_id = 0;
1807 	}
1808 
1809 	if (m_vs_id != 0)
1810 	{
1811 		gl.deleteShader(m_vs_id);
1812 		m_vs_id = 0;
1813 	}
1814 
1815 	/* Release base class */
1816 	TestCaseBase::deinit();
1817 }
1818 
1819 /* Retrieves test-specific geometry shader source code.
1820  *
1821  * @return Requested string.
1822  */
getGSCode()1823 std::string GeometryShaderMaxShaderStorageBlocksTest::getGSCode()
1824 {
1825 	std::stringstream code_sstream;
1826 
1827 	/* Form the GS */
1828 	code_sstream << "${VERSION}\n"
1829 					"${GEOMETRY_SHADER_REQUIRE}\n"
1830 					"\n"
1831 					"layout (points)                   in;\n"
1832 					"layout (points, max_vertices = 1) out;\n"
1833 					"\n"
1834 					"int counter = 0;\n"
1835 					"\n";
1836 
1837 	for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
1838 	{
1839 		code_sstream << "layout(binding = " << n_ssb << ") buffer ssb" << n_ssb << " \n{\n"
1840 					 << "    int value;\n"
1841 					 << "} S_SSB" << n_ssb << ";\n\n";
1842 	}
1843 
1844 	code_sstream << "\n"
1845 					"void main()\n"
1846 					"{\n";
1847 
1848 	for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
1849 	{
1850 		code_sstream << "    counter += S_SSB" << n_ssb << ".value++;\n";
1851 	}
1852 
1853 	code_sstream << "\n"
1854 					"    gl_Position = vec4(float(counter), 0.0, 0.0, 1.0);\n"
1855 					"    EmitVertex();\n"
1856 					"}\n";
1857 
1858 	/* Form a specialized version of the GS source code */
1859 	std::string gs_code				= code_sstream.str();
1860 	const char* gs_code_raw			= gs_code.c_str();
1861 	std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw);
1862 
1863 	return gs_code_specialized;
1864 }
1865 
1866 /** Executes the test.
1867  *
1868  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1869  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1870  *  Note the function throws exception should an error occur!
1871  **/
iterate()1872 tcu::TestNode::IterateResult GeometryShaderMaxShaderStorageBlocksTest::iterate()
1873 {
1874 	glw::GLint		   counter						 = 0;
1875 	glw::GLint		   expectedValue				 = 0;
1876 	const glw::GLchar* feedbackVaryings[]			 = { "gl_Position" };
1877 	bool			   has_shader_compilation_failed = true;
1878 	const glw::GLfloat initial_buffer_data[4]		 = { 0.0f, 0.0f, 0.0f, 0.0f };
1879 	glw::GLint		   int_alignment				 = 0;
1880 	const glw::GLint   int_size						 = sizeof(glw::GLint);
1881 	glw::GLint*		   ptrSSBO_data					 = DE_NULL;
1882 	glw::GLfloat*	  ptrTF_data					 = DE_NULL;
1883 	bool			   result						 = true;
1884 	glw::GLint		   ssbo_alignment				 = 0;
1885 	glw::GLint*		   ssbo_data					 = DE_NULL;
1886 	glw::GLint		   ssbo_data_size				 = 0;
1887 
1888 	std::string fs_code_specialized		= "";
1889 	const char* fs_code_specialized_raw = DE_NULL;
1890 	std::string gs_code_specialized		= "";
1891 	const char* gs_code_specialized_raw = DE_NULL;
1892 	std::string vs_code_specialized		= "";
1893 	const char* vs_code_specialized_raw = DE_NULL;
1894 
1895 	/* This test should only run if EXT_geometry_shader is supported. */
1896 	if (!m_is_geometry_shader_extension_supported)
1897 	{
1898 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1899 	}
1900 
1901 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1902 
1903 	/* Retrieve GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname value */
1904 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
1905 				   &m_gl_max_geometry_shader_storage_blocks_ext_value);
1906 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname");
1907 
1908 	/* Retrieve GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname value */
1909 	glw::GLint m_gl_max_shader_storage_buffer_bindings_value = 0;
1910 
1911 	gl.getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &m_gl_max_shader_storage_buffer_bindings_value);
1912 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname");
1913 
1914 	/* Check if m_gl_max_shader_storage_blocks_value is less than or equal zero. */
1915 	if (m_gl_max_geometry_shader_storage_blocks_ext_value <= 0)
1916 	{
1917 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
1918 						   << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
1919 						   << "]"
1920 							  " is less than or equal zero. Shader Storage Blocks"
1921 							  " in Geometry Shader are not supported."
1922 						   << tcu::TestLog::EndMessage;
1923 
1924 		if (m_gl_max_geometry_shader_storage_blocks_ext_value == 0)
1925 		{
1926 			throw tcu::NotSupportedError("GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT is 0");
1927 		}
1928 		else
1929 		{
1930 			result = false;
1931 			goto end;
1932 		}
1933 	}
1934 
1935 	/* Check if m_gl_max_shader_storage_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
1936 	if (m_gl_max_shader_storage_buffer_bindings_value < m_gl_max_geometry_shader_storage_blocks_ext_value)
1937 	{
1938 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
1939 						   << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
1940 						   << "]"
1941 							  " is greater than GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS query value "
1942 							  "["
1943 						   << m_gl_max_shader_storage_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
1944 
1945 		result = false;
1946 		goto end;
1947 	}
1948 
1949 	/* Create a program object. */
1950 	m_po_id = gl.createProgram();
1951 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1952 
1953 	/* Create shader objects. */
1954 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1955 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1956 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1957 
1958 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1959 
1960 	/* Configure which outputs should be captured by Transform Feedback. */
1961 	gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
1962 
1963 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
1964 
1965 	/* Try to link the test program object */
1966 	fs_code_specialized		= specializeShader(1, &dummy_fs_code);
1967 	fs_code_specialized_raw = fs_code_specialized.c_str();
1968 
1969 	gs_code_specialized		= getGSCode();
1970 	gs_code_specialized_raw = gs_code_specialized.c_str();
1971 
1972 	vs_code_specialized		= specializeShader(1, &dummy_vs_code);
1973 	vs_code_specialized_raw = vs_code_specialized.c_str();
1974 
1975 	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
1976 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1977 									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1978 									&fs_code_specialized_raw, &has_shader_compilation_failed))
1979 	{
1980 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
1981 
1982 		result = false;
1983 		goto end;
1984 	}
1985 
1986 	/* Prepare data for Shader Storage Buffer Object. */
1987 	gl.getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_alignment);
1988 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
1989 
1990 	int_alignment  = ssbo_alignment / int_size;
1991 	ssbo_data_size = m_gl_max_geometry_shader_storage_blocks_ext_value * ssbo_alignment;
1992 	ssbo_data	  = new glw::GLint[ssbo_data_size];
1993 
1994 	if ((ssbo_alignment % int_size) != 0)
1995 	{
1996 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT query value "
1997 													   "["
1998 						   << ssbo_alignment << "]"
1999 												"divide with remainder by the size of GLint "
2000 												"["
2001 						   << int_size << "]" << tcu::TestLog::EndMessage;
2002 
2003 		result = false;
2004 		goto end;
2005 	}
2006 
2007 	for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
2008 	{
2009 		ssbo_data[i * int_alignment] = i + 1;
2010 	}
2011 
2012 	/* Create Shader Storage Buffer Object. */
2013 	gl.genBuffers(1, &m_ssbo_id);
2014 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2015 
2016 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo_id);
2017 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2018 
2019 	gl.bufferData(GL_SHADER_STORAGE_BUFFER, ssbo_data_size, ssbo_data, GL_DYNAMIC_COPY);
2020 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2021 
2022 	/* Free unused memory. */
2023 	delete[] ssbo_data;
2024 	ssbo_data = NULL;
2025 
2026 	/* Bind specific m_ssbo_id buffer region to a specific Shader Storage Buffer binding point. */
2027 	for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
2028 	{
2029 		glw::GLuint offset = n_ssb * ssbo_alignment;
2030 
2031 		gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, n_ssb /*binding index*/, m_ssbo_id, offset, int_size);
2032 		GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2033 	}
2034 
2035 	/* Configure VAO. */
2036 	gl.genVertexArrays(1, &m_vao_id);
2037 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2038 
2039 	gl.bindVertexArray(m_vao_id);
2040 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2041 
2042 	/* Create a Buffer Object for Transform Feedback's outputs. */
2043 	gl.genBuffers(1, &m_tfbo_id);
2044 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2045 
2046 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
2047 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2048 
2049 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, initial_buffer_data,
2050 				  GL_STATIC_READ);
2051 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2052 
2053 	/* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
2054 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
2055 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
2056 
2057 	/* Use program. */
2058 	gl.useProgram(m_po_id);
2059 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2060 
2061 	/* Disable rasterization and make a draw call. After that, turn on rasterization. */
2062 	gl.enable(GL_RASTERIZER_DISCARD);
2063 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
2064 
2065 	gl.beginTransformFeedback(GL_POINTS);
2066 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2067 
2068 	gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
2069 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2070 
2071 	gl.endTransformFeedback();
2072 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
2073 
2074 	gl.disable(GL_RASTERIZER_DISCARD);
2075 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
2076 
2077 	/* Retrieve value from Transform Feedback. */
2078 	ptrTF_data = (glw::GLfloat*)gl.mapBufferRange(
2079 		GL_ARRAY_BUFFER, 0 /*offset*/, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
2080 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2081 
2082 	counter = int(ptrTF_data[0] + 0.5f);
2083 
2084 	gl.unmapBuffer(GL_ARRAY_BUFFER);
2085 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2086 
2087 	ptrTF_data = NULL;
2088 
2089 	/* Retrieve values from Shader Storage Buffer Object. */
2090 	ptrSSBO_data =
2091 		(glw::GLint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /*offset*/, ssbo_data_size, GL_MAP_READ_BIT);
2092 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2093 
2094 	for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
2095 	{
2096 		if (ptrSSBO_data[i * int_alignment] != i + 2)
2097 		{
2098 			result = false;
2099 
2100 			m_testCtx.getLog() << tcu::TestLog::Message << "Value read from Shader Storage Buffer "
2101 														   "["
2102 							   << ptrSSBO_data[i * int_alignment] << "] "
2103 																	 "at index "
2104 																	 "["
2105 							   << i * int_alignment << "]"
2106 													   "is not equal to expected value "
2107 													   "["
2108 							   << i + 2 << "]" << tcu::TestLog::EndMessage;
2109 
2110 			break;
2111 		}
2112 	}
2113 
2114 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
2115 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2116 
2117 	ptrSSBO_data = NULL;
2118 
2119 	/* Calculate expected value. */
2120 	expectedValue =
2121 		m_gl_max_geometry_shader_storage_blocks_ext_value * (m_gl_max_geometry_shader_storage_blocks_ext_value + 1) / 2;
2122 
2123 	if (counter != expectedValue)
2124 	{
2125 		result = false;
2126 	}
2127 
2128 end:
2129 	if (result)
2130 	{
2131 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2132 	}
2133 	else
2134 	{
2135 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2136 	}
2137 
2138 	return STOP;
2139 }
2140 
2141 /** Constructor
2142  *
2143  * @param context       Test context
2144  * @param extParams     Not used.
2145  * @param name          Test case's name
2146  * @param description   Test case's description
2147  **/
GeometryShaderMaxAtomicCountersTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2148 GeometryShaderMaxAtomicCountersTest::GeometryShaderMaxAtomicCountersTest(Context&			  context,
2149 																		 const ExtParameters& extParams,
2150 																		 const char* name, const char* description)
2151 	: TestCaseBase(context, extParams, name, description)
2152 	, m_acbo_id(0)
2153 	, m_fs_id(0)
2154 	, m_gl_max_geometry_atomic_counters_ext_value(0)
2155 	, m_gs_id(0)
2156 	, m_po_id(0)
2157 	, m_vao_id(0)
2158 	, m_vs_id(0)
2159 {
2160 }
2161 
2162 /** Deinitializes GLES objects created during the test. */
deinit()2163 void GeometryShaderMaxAtomicCountersTest::deinit()
2164 {
2165 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2166 
2167 	if (m_acbo_id != 0)
2168 	{
2169 		gl.deleteBuffers(1, &m_acbo_id);
2170 		m_acbo_id = 0;
2171 	}
2172 
2173 	if (m_fs_id != 0)
2174 	{
2175 		gl.deleteShader(m_fs_id);
2176 		m_fs_id = 0;
2177 	}
2178 
2179 	if (m_gs_id != 0)
2180 	{
2181 		gl.deleteShader(m_gs_id);
2182 		m_gs_id = 0;
2183 	}
2184 
2185 	if (m_po_id != 0)
2186 	{
2187 		gl.deleteProgram(m_po_id);
2188 		m_po_id = 0;
2189 	}
2190 
2191 	if (m_vao_id != 0)
2192 	{
2193 		gl.deleteVertexArrays(1, &m_vao_id);
2194 		m_vao_id = 0;
2195 	}
2196 
2197 	if (m_vs_id != 0)
2198 	{
2199 		gl.deleteShader(m_vs_id);
2200 		m_vs_id = 0;
2201 	}
2202 
2203 	/* Release base class */
2204 	TestCaseBase::deinit();
2205 }
2206 
2207 /* Retrieves test-specific geometry shader source code.
2208  *
2209  * @return Requested string.
2210  */
getGSCode()2211 std::string GeometryShaderMaxAtomicCountersTest::getGSCode()
2212 {
2213 	std::stringstream code_sstream;
2214 
2215 	/* Form the GS */
2216 	code_sstream << "${VERSION}\n"
2217 					"${GEOMETRY_SHADER_REQUIRE}\n"
2218 					"\n"
2219 					"layout (points)                   in;\n"
2220 					"layout (points, max_vertices = 1) out;\n"
2221 					"\n"
2222 					"uniform int n_loop_iterations;\n"
2223 					"flat in int vertex_id[];\n"
2224 					"\n";
2225 
2226 	code_sstream << "layout(binding = 0) uniform atomic_uint acs[" << m_gl_max_geometry_atomic_counters_ext_value
2227 				 << "];\n"
2228 				 << "\n"
2229 					"void main()\n"
2230 					"{\n"
2231 					"    for (int counter_id = 1;\n"
2232 					"             counter_id <= n_loop_iterations;\n"
2233 					"           ++counter_id)\n"
2234 					"    {\n"
2235 					"        if ((vertex_id[0] % counter_id) == 0)\n"
2236 					"        {\n"
2237 					"            atomicCounterIncrement(acs[counter_id - 1]);\n"
2238 					"        }\n"
2239 					"    }\n"
2240 					"\n"
2241 					"    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2242 					"    EmitVertex();\n"
2243 					"}\n";
2244 
2245 	/* Form a specialized version of the GS source code */
2246 	std::string gs_code				= code_sstream.str();
2247 	const char* gs_code_raw			= gs_code.c_str();
2248 	std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
2249 
2250 	return gs_code_specialized;
2251 }
2252 
2253 /** Executes the test.
2254  *
2255  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2256  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2257  *  Note the function throws exception should an error occur!
2258  **/
iterate()2259 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCountersTest::iterate()
2260 {
2261 	/* Define Vertex Shader's code for the purpose of this test. */
2262 	const char* vs_code = "${VERSION}\n"
2263 						  "\n"
2264 						  "flat out int vertex_id;\n"
2265 						  "\n"
2266 						  "void main()\n"
2267 						  "{\n"
2268 						  "    vertex_id    = gl_VertexID;\n"
2269 						  "    gl_Position  = vec4(1.0, 0.0, 0.0, 1.0);\n"
2270 						  "}\n";
2271 
2272 	bool			   has_shader_compilation_failed	  = true;
2273 	glw::GLuint*	   initial_ac_data					  = DE_NULL;
2274 	const unsigned int n_draw_call_vertices				  = 4;
2275 	glw::GLint		   n_loop_iterations_uniform_location = -1;
2276 	glw::GLuint*	   ptrACBO_data						  = DE_NULL;
2277 	bool			   result							  = true;
2278 
2279 	std::string fs_code_specialized		= "";
2280 	const char* fs_code_specialized_raw = DE_NULL;
2281 	std::string gs_code_specialized		= "";
2282 	const char* gs_code_specialized_raw = DE_NULL;
2283 	std::string vs_code_specialized		= "";
2284 	const char* vs_code_specialized_raw = DE_NULL;
2285 
2286 	/* This test should only run if EXT_geometry_shader is supported. */
2287 	if (!m_is_geometry_shader_extension_supported)
2288 	{
2289 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2290 	}
2291 
2292 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2293 
2294 	/* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname value */
2295 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTERS, &m_gl_max_geometry_atomic_counters_ext_value);
2296 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname");
2297 
2298 	/* Check if m_gl_max_atomic_counters_value is less than or equal zero. */
2299 	if (m_gl_max_geometry_atomic_counters_ext_value <= 0)
2300 	{
2301 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT query value "
2302 						   << "[" << m_gl_max_geometry_atomic_counters_ext_value
2303 						   << "]"
2304 							  " is less than or equal to zero. Atomic Counters"
2305 							  " in Geometry Shader are not supported."
2306 						   << tcu::TestLog::EndMessage;
2307 
2308 		if (m_gl_max_geometry_atomic_counters_ext_value == 0)
2309 		{
2310 			throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT is 0");
2311 		}
2312 		else
2313 		{
2314 			result = false;
2315 			goto end;
2316 		}
2317 	}
2318 
2319 	/* Create a program object. */
2320 	m_po_id = gl.createProgram();
2321 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2322 
2323 	/* Create shader objects. */
2324 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2325 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2326 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2327 
2328 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2329 
2330 	/* Try to link the test program object */
2331 	fs_code_specialized		= specializeShader(1, &dummy_fs_code);
2332 	fs_code_specialized_raw = fs_code_specialized.c_str();
2333 
2334 	gs_code_specialized		= getGSCode();
2335 	gs_code_specialized_raw = gs_code_specialized.c_str();
2336 
2337 	vs_code_specialized		= specializeShader(1, &vs_code);
2338 	vs_code_specialized_raw = vs_code_specialized.c_str();
2339 
2340 	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
2341 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2342 									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2343 									&fs_code_specialized_raw, &has_shader_compilation_failed))
2344 	{
2345 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
2346 
2347 		result = false;
2348 		goto end;
2349 	}
2350 
2351 	/* Create Atomic Counter Buffer Objects. */
2352 	gl.genBuffers(1, &m_acbo_id);
2353 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2354 
2355 	/* Prepare initial data - zeroes - to fill the Atomic Counter Buffer Object. */
2356 	initial_ac_data = new glw::GLuint[m_gl_max_geometry_atomic_counters_ext_value];
2357 	memset(initial_ac_data, 0, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value);
2358 
2359 	gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_id);
2360 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2361 
2362 	gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value, NULL,
2363 				  GL_DYNAMIC_COPY);
2364 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2365 
2366 	gl.bufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2367 					 sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
2368 					 initial_ac_data /*initialize with zeroes*/);
2369 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
2370 
2371 	gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0 /*binding index*/, m_acbo_id /*buffer*/);
2372 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2373 
2374 	/* Configure VAO. */
2375 	gl.genVertexArrays(1, &m_vao_id);
2376 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2377 
2378 	gl.bindVertexArray(m_vao_id);
2379 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2380 
2381 	/* Use program. */
2382 	n_loop_iterations_uniform_location = gl.getUniformLocation(m_po_id, "n_loop_iterations");
2383 
2384 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
2385 	if (n_loop_iterations_uniform_location == -1)
2386 	{
2387 		TCU_FAIL("n_loop_iterations uniform is considered inactive");
2388 	}
2389 	else
2390 	{
2391 		gl.useProgram(m_po_id);
2392 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2393 
2394 		gl.uniform1i(n_loop_iterations_uniform_location, m_gl_max_geometry_atomic_counters_ext_value);
2395 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
2396 	}
2397 
2398 	/* Issue the draw call */
2399 	gl.drawArrays(GL_POINTS, 0, n_draw_call_vertices);
2400 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2401 
2402 	/* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
2403 	ptrACBO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2404 												   sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
2405 												   GL_MAP_READ_BIT);
2406 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2407 
2408 	for (glw::GLint n_ac = 0; n_ac < m_gl_max_geometry_atomic_counters_ext_value; ++n_ac)
2409 	{
2410 		unsigned int expected_value = 0;
2411 
2412 		for (unsigned int n_draw_call_vertex = 0; n_draw_call_vertex < n_draw_call_vertices; ++n_draw_call_vertex)
2413 		{
2414 			if ((n_draw_call_vertex % (n_ac + 1)) == 0)
2415 			{
2416 				++expected_value;
2417 			}
2418 		}
2419 
2420 		if (ptrACBO_data[n_ac] != expected_value)
2421 		{
2422 			result = false;
2423 			break;
2424 		}
2425 	}
2426 
2427 	gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2428 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2429 
2430 	ptrACBO_data = NULL;
2431 
2432 end:
2433 	if (result)
2434 	{
2435 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2436 	}
2437 	else
2438 	{
2439 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2440 	}
2441 
2442 	return STOP;
2443 }
2444 
2445 /** Constructor
2446  *
2447  * @param context       Test context
2448  * @param extParams     Not used.
2449  * @param name          Test case's name
2450  * @param description   Test case's description
2451  **/
GeometryShaderMaxAtomicCounterBuffersTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2452 GeometryShaderMaxAtomicCounterBuffersTest::GeometryShaderMaxAtomicCounterBuffersTest(Context&			  context,
2453 																					 const ExtParameters& extParams,
2454 																					 const char*		  name,
2455 																					 const char*		  description)
2456 	: TestCaseBase(context, extParams, name, description)
2457 	, m_acbo_ids(NULL)
2458 	, m_fs_id(0)
2459 	, m_gl_max_atomic_counter_buffer_bindings_value(0)
2460 	, m_gl_max_geometry_atomic_counter_buffers_ext_value(0)
2461 	, m_gs_id(0)
2462 	, m_po_id(0)
2463 	, m_vao_id(0)
2464 	, m_vs_id(0)
2465 {
2466 }
2467 
2468 /** Deinitializes GLES objects created during the test. */
deinit()2469 void GeometryShaderMaxAtomicCounterBuffersTest::deinit()
2470 {
2471 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2472 
2473 	if (m_acbo_ids != NULL)
2474 	{
2475 		if (m_gl_max_geometry_atomic_counter_buffers_ext_value > 0)
2476 		{
2477 			gl.deleteBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
2478 
2479 			delete[] m_acbo_ids;
2480 			m_acbo_ids = NULL;
2481 		}
2482 	}
2483 
2484 	if (m_fs_id != 0)
2485 	{
2486 		gl.deleteShader(m_fs_id);
2487 		m_fs_id = 0;
2488 	}
2489 
2490 	if (m_gs_id != 0)
2491 	{
2492 		gl.deleteShader(m_gs_id);
2493 		m_gs_id = 0;
2494 	}
2495 
2496 	if (m_po_id != 0)
2497 	{
2498 		gl.deleteProgram(m_po_id);
2499 		m_po_id = 0;
2500 	}
2501 
2502 	if (m_vao_id != 0)
2503 	{
2504 		gl.deleteVertexArrays(1, &m_vao_id);
2505 		m_vao_id = 0;
2506 	}
2507 
2508 	if (m_vs_id != 0)
2509 	{
2510 		gl.deleteShader(m_vs_id);
2511 		m_vs_id = 0;
2512 	}
2513 
2514 	/* Release base class */
2515 	TestCaseBase::deinit();
2516 }
2517 
2518 /* Retrieves test-specific geometry shader source code.
2519  *
2520  * @return Requested string.
2521  */
getGSCode()2522 std::string GeometryShaderMaxAtomicCounterBuffersTest::getGSCode()
2523 {
2524 	std::stringstream code_sstream;
2525 
2526 	/* Form the GS */
2527 	code_sstream << "${VERSION}\n"
2528 					"${GEOMETRY_SHADER_REQUIRE}\n"
2529 					"\n"
2530 					"layout (points)                   in;\n"
2531 					"layout (points, max_vertices = 1) out;\n"
2532 					"\n"
2533 					"flat in int vertex_id[];\n"
2534 					"\n";
2535 
2536 	for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
2537 	{
2538 		code_sstream << "layout(binding = " << n_ac << ") uniform atomic_uint ac" << n_ac << ";\n";
2539 	}
2540 
2541 	code_sstream << "\n"
2542 					"void main()\n"
2543 					"{\n"
2544 					"    for(int counter_id = 1; counter_id <= "
2545 				 << m_gl_max_geometry_atomic_counter_buffers_ext_value
2546 				 << "; ++counter_id)\n"
2547 					"    {\n"
2548 					"        if((vertex_id[0] % counter_id) == 0)\n"
2549 					"        {\n";
2550 
2551 	for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
2552 	{
2553 		code_sstream << "            atomicCounterIncrement(ac" << n_ac << ");\n";
2554 	}
2555 
2556 	code_sstream << "        }\n"
2557 					"    }\n";
2558 
2559 	code_sstream << "\n"
2560 					"    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2561 					"    EmitVertex();\n"
2562 					"}\n";
2563 
2564 	/* Form a specialized version of the GS source code */
2565 	std::string gs_code				= code_sstream.str();
2566 	const char* gs_code_raw			= gs_code.c_str();
2567 	std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
2568 
2569 	return gs_code_specialized;
2570 }
2571 
2572 /** Executes the test.
2573  *
2574  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2575  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2576  *  Note the function throws exception should an error occur!
2577  **/
iterate()2578 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCounterBuffersTest::iterate()
2579 {
2580 	/* Define Vertex Shader's code for the purpose of this test. */
2581 	const char* vs_code = "${VERSION}\n"
2582 						  "\n"
2583 						  "flat out int vertex_id;\n"
2584 						  "\n"
2585 						  "void main()\n"
2586 						  "{\n"
2587 						  "    vertex_id    = gl_VertexID;\n"
2588 						  "    gl_Position  = vec4(1.0, 0.0, 0.0, 1.0);\n"
2589 						  "}\n";
2590 
2591 	unsigned int		  expected_value				= 0;
2592 	const glw::Functions& gl							= m_context.getRenderContext().getFunctions();
2593 	bool				  has_shader_compilation_failed = true;
2594 	const glw::GLuint	 initial_ac_data				= 0;
2595 	const glw::GLuint	 number_of_indices				= 128 * m_gl_max_geometry_atomic_counter_buffers_ext_value;
2596 	bool				  result						= true;
2597 
2598 	std::string fs_code_specialized		= "";
2599 	const char* fs_code_specialized_raw = DE_NULL;
2600 	std::string gs_code_specialized		= "";
2601 	const char* gs_code_specialized_raw = DE_NULL;
2602 	std::string vs_code_specialized		= "";
2603 	const char* vs_code_specialized_raw = DE_NULL;
2604 
2605 	/* This test should only run if EXT_geometry_shader is supported. */
2606 	if (!m_is_geometry_shader_extension_supported)
2607 	{
2608 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2609 	}
2610 
2611 	/* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname value */
2612 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS,
2613 				   &m_gl_max_geometry_atomic_counter_buffers_ext_value);
2614 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname");
2615 
2616 	/* Retrieve GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname value */
2617 	gl.getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_gl_max_atomic_counter_buffer_bindings_value);
2618 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname");
2619 
2620 	/* Check if m_gl_max_geometry_atomic_counter_buffers_ext_value is less than or equal zero. */
2621 	if (m_gl_max_geometry_atomic_counter_buffers_ext_value <= 0)
2622 	{
2623 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
2624 						   << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
2625 						   << "]"
2626 							  " is less than or equal to zero. Atomic Counter Buffers"
2627 							  " are not supported."
2628 						   << tcu::TestLog::EndMessage;
2629 
2630 		if (m_gl_max_geometry_atomic_counter_buffers_ext_value == 0)
2631 		{
2632 			throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT is 0");
2633 		}
2634 		else
2635 		{
2636 			result = false;
2637 			goto end;
2638 		}
2639 	}
2640 
2641 	/* Check if m_gl_max_atomic_counter_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
2642 	if (m_gl_max_atomic_counter_buffer_bindings_value < m_gl_max_geometry_atomic_counter_buffers_ext_value)
2643 	{
2644 		m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
2645 						   << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
2646 						   << "]"
2647 							  " is greater than GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS query value "
2648 							  "["
2649 						   << m_gl_max_atomic_counter_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
2650 
2651 		result = false;
2652 		goto end;
2653 	}
2654 
2655 	/* Create a program object. */
2656 	m_po_id = gl.createProgram();
2657 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2658 
2659 	/* Create shader objects. */
2660 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2661 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2662 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2663 
2664 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2665 
2666 	/* Try to link the test program object */
2667 	fs_code_specialized		= specializeShader(1, &dummy_fs_code);
2668 	fs_code_specialized_raw = fs_code_specialized.c_str();
2669 
2670 	gs_code_specialized		= getGSCode();
2671 	gs_code_specialized_raw = gs_code_specialized.c_str();
2672 
2673 	vs_code_specialized		= specializeShader(1, &vs_code);
2674 	vs_code_specialized_raw = vs_code_specialized.c_str();
2675 
2676 	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
2677 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2678 									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2679 									&fs_code_specialized_raw, &has_shader_compilation_failed))
2680 	{
2681 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
2682 
2683 		result = false;
2684 		goto end;
2685 	}
2686 
2687 	/* Create Atomic Counter Buffer Objects. */
2688 	m_acbo_ids = new glw::GLuint[m_gl_max_geometry_atomic_counter_buffers_ext_value];
2689 
2690 	gl.genBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
2691 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2692 
2693 	for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
2694 	{
2695 		gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
2696 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2697 
2698 		gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint), &initial_ac_data /*initialize with zeroes*/,
2699 					  GL_DYNAMIC_COPY);
2700 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2701 
2702 		gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, n_acb /*binding index*/, m_acbo_ids[n_acb] /*buffer*/);
2703 		GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2704 	}
2705 
2706 	/* Configure VAO. */
2707 	gl.genVertexArrays(1, &m_vao_id);
2708 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2709 
2710 	gl.bindVertexArray(m_vao_id);
2711 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2712 
2713 	/* Use program. */
2714 	gl.useProgram(m_po_id);
2715 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2716 
2717 	gl.drawArrays(GL_POINTS, 0 /*starting index*/, number_of_indices);
2718 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2719 
2720 	/* Calculate expected value. */
2721 	/* For each point being processed by Geometry Shader. */
2722 	for (glw::GLuint vertex_id = 0; vertex_id < number_of_indices; ++vertex_id)
2723 	{
2724 		/* And for each atomic counter ID. */
2725 		for (int atomic_counter_id = 1; atomic_counter_id <= m_gl_max_geometry_atomic_counter_buffers_ext_value;
2726 			 ++atomic_counter_id)
2727 		{
2728 			/* Check if (vertex_id % atomic_counter_id) == 0. If it is true, increment expected_value. */
2729 			if (vertex_id % atomic_counter_id == 0)
2730 			{
2731 				++expected_value;
2732 			}
2733 		}
2734 	}
2735 
2736 	/* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
2737 	for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
2738 	{
2739 		gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
2740 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2741 
2742 		glw::GLuint* ptrABO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2743 																   sizeof(glw::GLuint) /*length*/, GL_MAP_READ_BIT);
2744 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2745 
2746 		if (ptrABO_data[0] != expected_value)
2747 		{
2748 			result = false;
2749 			break;
2750 		}
2751 
2752 		gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2753 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2754 
2755 		ptrABO_data = NULL;
2756 	}
2757 
2758 end:
2759 	if (result)
2760 	{
2761 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2762 	}
2763 	else
2764 	{
2765 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2766 	}
2767 
2768 	return STOP;
2769 }
2770 
2771 /** Constructor
2772  *
2773  * @param context       Test context
2774  * @param extParams     Not used.
2775  * @param name          Test case's name
2776  * @param description   Test case's description
2777  **/
2778 GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::
GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2779 	GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context& context, const ExtParameters& extParams,
2780 																 const char* name, const char* description)
2781 	: TestCaseBase(context, extParams, name, description)
2782 	, m_fs_id(0)
2783 	, m_fs_po_id(0)
2784 	, m_gs_id(0)
2785 	, m_gs_po_id(0)
2786 	, m_ppo_id(0)
2787 	, m_vao_id(0)
2788 {
2789 }
2790 
2791 /** Deinitializes GLES objects created during the test. */
deinit()2792 void GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::deinit()
2793 {
2794 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2795 
2796 	if (m_fs_id != 0)
2797 	{
2798 		gl.deleteShader(m_fs_id);
2799 		m_fs_id = 0;
2800 	}
2801 
2802 	if (m_fs_po_id != 0)
2803 	{
2804 		gl.deleteProgram(m_fs_po_id);
2805 		m_fs_po_id = 0;
2806 	}
2807 
2808 	if (m_gs_id != 0)
2809 	{
2810 		gl.deleteShader(m_gs_id);
2811 		m_gs_id = 0;
2812 	}
2813 
2814 	if (m_gs_po_id != 0)
2815 	{
2816 		gl.deleteProgram(m_gs_po_id);
2817 		m_gs_po_id = 0;
2818 	}
2819 
2820 	if (m_ppo_id != 0)
2821 	{
2822 		gl.deleteProgramPipelines(1, &m_ppo_id);
2823 		m_ppo_id = 0;
2824 	}
2825 
2826 	if (m_vao_id != 0)
2827 	{
2828 		gl.deleteVertexArrays(1, &m_vao_id);
2829 		m_vao_id = 0;
2830 	}
2831 
2832 	/* Release base class */
2833 	TestCaseBase::deinit();
2834 }
2835 
2836 /** Executes the test.
2837  *
2838  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2839  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2840  *  Note the function throws exception should an error occur!
2841  **/
iterate()2842 tcu::TestNode::IterateResult GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::iterate()
2843 {
2844 	bool		has_shader_compilation_failed = true;
2845 	bool		result						  = true;
2846 	glw::GLenum error						  = GL_NO_ERROR;
2847 
2848 	/* This test should only run if EXT_geometry_shader is supported. */
2849 	if (!m_is_geometry_shader_extension_supported)
2850 	{
2851 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2852 	}
2853 
2854 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2855 
2856 	/* Create separable program objects. */
2857 	m_fs_po_id = gl.createProgram();
2858 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2859 
2860 	gl.programParameteri(m_fs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2861 	GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
2862 
2863 	m_gs_po_id = gl.createProgram();
2864 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2865 
2866 	gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2867 	GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
2868 
2869 	/* Create shader objects. */
2870 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2871 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2872 
2873 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2874 
2875 	/* Try to link the test program object */
2876 	std::string fs_code_specialized		= specializeShader(1, &dummy_fs_code);
2877 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
2878 	std::string gs_code_specialized		= specializeShader(1, &dummy_gs_code);
2879 	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
2880 
2881 	if (!TestCaseBase::buildProgram(m_fs_po_id, m_fs_id, 1,			/* n_sh1_body_parts */
2882 									&fs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
2883 									NULL, 0, 0,						/* n_sh3_body_parts */
2884 									NULL, &has_shader_compilation_failed))
2885 	{
2886 		m_testCtx.getLog() << tcu::TestLog::Message << "Fragment Shader Program object linking failed."
2887 						   << tcu::TestLog::EndMessage;
2888 
2889 		result = false;
2890 		goto end;
2891 	}
2892 
2893 	if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1,			/* n_sh1_body_parts */
2894 									&gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
2895 									NULL, 0, 0,						/* n_sh3_body_parts */
2896 									NULL, &has_shader_compilation_failed))
2897 	{
2898 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
2899 						   << tcu::TestLog::EndMessage;
2900 
2901 		result = false;
2902 		goto end;
2903 	}
2904 
2905 	/* Configure Pipeline Object. */
2906 	gl.genProgramPipelines(1, &m_ppo_id);
2907 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
2908 
2909 	gl.useProgramStages(m_ppo_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
2910 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
2911 
2912 	gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
2913 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
2914 
2915 	/* Configure VAO. */
2916 	gl.genVertexArrays(1, &m_vao_id);
2917 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2918 
2919 	gl.bindVertexArray(m_vao_id);
2920 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2921 
2922 	/* Use Program Pipeline Object. */
2923 	gl.bindProgramPipeline(m_ppo_id);
2924 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
2925 
2926 	gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
2927 
2928 	error = gl.getError();
2929 
2930 	/* Check if correct error was generated. */
2931 	if (GL_INVALID_OPERATION != error)
2932 	{
2933 		result = false;
2934 
2935 		m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
2936 						   << tcu::TestLog::EndMessage;
2937 	}
2938 
2939 end:
2940 	if (result)
2941 	{
2942 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2943 	}
2944 	else
2945 	{
2946 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2947 	}
2948 
2949 	return STOP;
2950 }
2951 
2952 /** Constructor
2953  *
2954  * @param context       Test context
2955  * @param extParams     Not used.
2956  * @param name          Test case's name
2957  * @param description   Test case's description
2958  **/
GeometryShaderIncompatibleDrawCallModeTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2959 GeometryShaderIncompatibleDrawCallModeTest::GeometryShaderIncompatibleDrawCallModeTest(Context&				context,
2960 																					   const ExtParameters& extParams,
2961 																					   const char*			name,
2962 																					   const char*			description)
2963 	: TestCaseBase(context, extParams, name, description)
2964 	, m_fs_id(0)
2965 	, m_gs_ids(NULL)
2966 	, m_number_of_gs(5 /*taken from test spec*/)
2967 	, m_po_ids(NULL)
2968 {
2969 	m_vao_id = 0;
2970 	m_vs_id  = 0;
2971 }
2972 
2973 /** Deinitializes GLES objects created during the test. */
deinit()2974 void GeometryShaderIncompatibleDrawCallModeTest::deinit()
2975 {
2976 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2977 
2978 	if (m_fs_id != 0)
2979 	{
2980 		gl.deleteShader(m_fs_id);
2981 		m_fs_id = 0;
2982 	}
2983 
2984 	if (m_gs_ids != 0)
2985 	{
2986 		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2987 		{
2988 			gl.deleteShader(m_gs_ids[i]);
2989 			m_gs_ids[i] = 0;
2990 		}
2991 
2992 		delete[] m_gs_ids;
2993 		m_gs_ids = NULL;
2994 	}
2995 
2996 	if (m_po_ids != 0)
2997 	{
2998 		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2999 		{
3000 			gl.deleteProgram(m_po_ids[i]);
3001 			m_po_ids[i] = 0;
3002 		}
3003 
3004 		delete[] m_po_ids;
3005 		m_po_ids = NULL;
3006 	}
3007 
3008 	if (m_vao_id != 0)
3009 	{
3010 		gl.deleteVertexArrays(1, &m_vao_id);
3011 		m_vao_id = 0;
3012 	}
3013 
3014 	if (m_vs_id != 0)
3015 	{
3016 		gl.deleteShader(m_vs_id);
3017 		m_vs_id = 0;
3018 	}
3019 
3020 	/* Release base class */
3021 	TestCaseBase::deinit();
3022 }
3023 
3024 /** Executes the test.
3025  *
3026  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3027  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3028  *  Note the function throws exception should an error occur!
3029  **/
iterate()3030 tcu::TestNode::IterateResult GeometryShaderIncompatibleDrawCallModeTest::iterate()
3031 {
3032 	/* Define 5 Geometry Shaders for purpose of this test. */
3033 	const char* gs_code_points = "${VERSION}\n"
3034 								 "${GEOMETRY_SHADER_REQUIRE}\n"
3035 								 "\n"
3036 								 "layout (points)                   in;\n"
3037 								 "layout (points, max_vertices = 1) out;\n"
3038 								 "\n"
3039 								 "${IN_PER_VERTEX_DECL_ARRAY}"
3040 								 "\n"
3041 								 "void main()\n"
3042 								 "{\n"
3043 								 "    gl_Position = gl_in[0].gl_Position;\n"
3044 								 "    EmitVertex();\n"
3045 								 "}\n";
3046 
3047 	const char* gs_code_lines = "${VERSION}\n"
3048 								"${GEOMETRY_SHADER_REQUIRE}\n"
3049 								"\n"
3050 								"layout (lines)                    in;\n"
3051 								"layout (points, max_vertices = 1) out;\n"
3052 								"\n"
3053 								"${IN_PER_VERTEX_DECL_ARRAY}"
3054 								"\n"
3055 								"void main()\n"
3056 								"{\n"
3057 								"    gl_Position = gl_in[0].gl_Position;\n"
3058 								"    EmitVertex();\n"
3059 								"}\n";
3060 
3061 	const char* gs_code_lines_adjacency = "${VERSION}\n"
3062 										  "${GEOMETRY_SHADER_REQUIRE}\n"
3063 										  "\n"
3064 										  "layout (lines_adjacency)          in;\n"
3065 										  "layout (points, max_vertices = 1) out;\n"
3066 										  "\n"
3067 										  "${IN_PER_VERTEX_DECL_ARRAY}"
3068 										  "\n"
3069 										  "void main()\n"
3070 										  "{\n"
3071 										  "    gl_Position = gl_in[0].gl_Position;\n"
3072 										  "    EmitVertex();\n"
3073 										  "}\n";
3074 
3075 	const char* gs_code_triangles = "${VERSION}\n"
3076 									"${GEOMETRY_SHADER_REQUIRE}\n"
3077 									"\n"
3078 									"layout (triangles)                in;\n"
3079 									"layout (points, max_vertices = 1) out;\n"
3080 									"\n"
3081 									"${IN_PER_VERTEX_DECL_ARRAY}"
3082 									"\n"
3083 									"void main()\n"
3084 									"{\n"
3085 									"    gl_Position = gl_in[0].gl_Position;\n"
3086 									"    EmitVertex();\n"
3087 									"}\n";
3088 
3089 	const char* gs_code_triangles_adjacency = "${VERSION}\n"
3090 											  "${GEOMETRY_SHADER_REQUIRE}\n"
3091 											  "\n"
3092 											  "layout (triangles_adjacency)      in;\n"
3093 											  "layout (points, max_vertices = 1) out;\n"
3094 											  "\n"
3095 											  "${IN_PER_VERTEX_DECL_ARRAY}"
3096 											  "\n"
3097 											  "void main()\n"
3098 											  "{\n"
3099 											  "    gl_Position = gl_in[0].gl_Position;\n"
3100 											  "    EmitVertex();\n"
3101 											  "}\n";
3102 
3103 	bool has_shader_compilation_failed = true;
3104 	bool result						   = true;
3105 
3106 	m_gs_ids = new glw::GLuint[m_number_of_gs];
3107 	m_po_ids = new glw::GLuint[m_number_of_gs];
3108 
3109 	/* This test should only run if EXT_geometry_shader is supported. */
3110 	if (!m_is_geometry_shader_extension_supported)
3111 	{
3112 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3113 	}
3114 
3115 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3116 
3117 	/* Create program objects & geometry shader objects. */
3118 	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3119 	{
3120 		m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
3121 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3122 
3123 		m_po_ids[i] = gl.createProgram();
3124 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3125 	}
3126 
3127 	/* Create shader object. */
3128 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3129 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3130 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3131 
3132 	/* Try to link the test program object */
3133 	std::string fs_code_specialized		= specializeShader(1, &dummy_fs_code);
3134 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
3135 
3136 	std::string gs_codes_specialized[] = { specializeShader(1, &gs_code_points), specializeShader(1, &gs_code_lines),
3137 										   specializeShader(1, &gs_code_lines_adjacency),
3138 										   specializeShader(1, &gs_code_triangles),
3139 										   specializeShader(1, &gs_code_triangles_adjacency) };
3140 
3141 	const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str(),
3142 											   gs_codes_specialized[2].c_str(), gs_codes_specialized[3].c_str(),
3143 											   gs_codes_specialized[4].c_str() };
3144 	std::string vs_code_specialized		= specializeShader(1, &dummy_vs_code);
3145 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3146 
3147 	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3148 	{
3149 		if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,				  /* n_sh1_body_parts */
3150 										&fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
3151 										&gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
3152 										&vs_code_specialized_raw, &has_shader_compilation_failed))
3153 		{
3154 			m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
3155 							   << "[" << i << "]." << tcu::TestLog::EndMessage;
3156 
3157 			result = false;
3158 			break;
3159 		}
3160 	}
3161 
3162 	if (result)
3163 	{
3164 		/* Configure VAO. */
3165 		gl.genVertexArrays(1, &m_vao_id);
3166 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3167 
3168 		gl.bindVertexArray(m_vao_id);
3169 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3170 
3171 		for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
3172 		{
3173 			/* Use Program Object. */
3174 			gl.useProgram(m_po_ids[po]);
3175 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3176 
3177 			if (po != 0)
3178 			{
3179 				gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
3180 
3181 				if (GL_INVALID_OPERATION != gl.getError())
3182 				{
3183 					result = false;
3184 
3185 					m_testCtx.getLog() << tcu::TestLog::Message
3186 									   << "Error different than GL_INVALID_OPEARATION was generated."
3187 									   << tcu::TestLog::EndMessage;
3188 
3189 					break;
3190 				}
3191 			}
3192 
3193 			if (po != 1)
3194 			{
3195 				gl.drawArrays(GL_LINES, 0 /*starting index*/, 2 /*number of indices*/);
3196 
3197 				if (GL_INVALID_OPERATION != gl.getError())
3198 				{
3199 					result = false;
3200 
3201 					m_testCtx.getLog() << tcu::TestLog::Message
3202 									   << "Error different than GL_INVALID_OPEARATION was generated."
3203 									   << tcu::TestLog::EndMessage;
3204 
3205 					break;
3206 				}
3207 
3208 				gl.drawArrays(GL_LINE_LOOP, 0 /*starting index*/, 2 /*number of indices*/);
3209 
3210 				if (GL_INVALID_OPERATION != gl.getError())
3211 				{
3212 					result = false;
3213 
3214 					m_testCtx.getLog() << tcu::TestLog::Message
3215 									   << "Error different than GL_INVALID_OPEARATION was generated."
3216 									   << tcu::TestLog::EndMessage;
3217 
3218 					break;
3219 				}
3220 
3221 				gl.drawArrays(GL_LINE_STRIP, 0 /*starting index*/, 2 /*number of indices*/);
3222 
3223 				if (GL_INVALID_OPERATION != gl.getError())
3224 				{
3225 					result = false;
3226 
3227 					m_testCtx.getLog() << tcu::TestLog::Message
3228 									   << "Error different than GL_INVALID_OPEARATION was generated."
3229 									   << tcu::TestLog::EndMessage;
3230 
3231 					break;
3232 				}
3233 			}
3234 
3235 			if (po != 2)
3236 			{
3237 				gl.drawArrays(GL_LINES_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
3238 
3239 				if (GL_INVALID_OPERATION != gl.getError())
3240 				{
3241 					result = false;
3242 
3243 					m_testCtx.getLog() << tcu::TestLog::Message
3244 									   << "Error different than GL_INVALID_OPEARATION was generated."
3245 									   << tcu::TestLog::EndMessage;
3246 
3247 					break;
3248 				}
3249 
3250 				gl.drawArrays(GL_LINE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
3251 
3252 				if (GL_INVALID_OPERATION != gl.getError())
3253 				{
3254 					result = false;
3255 
3256 					m_testCtx.getLog() << tcu::TestLog::Message
3257 									   << "Error different than GL_INVALID_OPEARATION was generated."
3258 									   << tcu::TestLog::EndMessage;
3259 
3260 					break;
3261 				}
3262 			}
3263 
3264 			if (po != 3)
3265 			{
3266 				gl.drawArrays(GL_TRIANGLES, 0 /*starting index*/, 3 /*number of indices*/);
3267 
3268 				if (GL_INVALID_OPERATION != gl.getError())
3269 				{
3270 					result = false;
3271 
3272 					m_testCtx.getLog() << tcu::TestLog::Message
3273 									   << "Error different than GL_INVALID_OPEARATION was generated."
3274 									   << tcu::TestLog::EndMessage;
3275 
3276 					break;
3277 				}
3278 
3279 				gl.drawArrays(GL_TRIANGLE_FAN, 0 /*starting index*/, 3 /*number of indices*/);
3280 
3281 				if (GL_INVALID_OPERATION != gl.getError())
3282 				{
3283 					result = false;
3284 
3285 					m_testCtx.getLog() << tcu::TestLog::Message
3286 									   << "Error different than GL_INVALID_OPEARATION was generated."
3287 									   << tcu::TestLog::EndMessage;
3288 
3289 					break;
3290 				}
3291 
3292 				gl.drawArrays(GL_TRIANGLE_STRIP, 0 /*starting index*/, 3 /*number of indices*/);
3293 
3294 				if (GL_INVALID_OPERATION != gl.getError())
3295 				{
3296 					result = false;
3297 
3298 					m_testCtx.getLog() << tcu::TestLog::Message
3299 									   << "Error different than GL_INVALID_OPEARATION was generated."
3300 									   << tcu::TestLog::EndMessage;
3301 
3302 					break;
3303 				}
3304 			}
3305 
3306 			if (po != 4)
3307 			{
3308 				gl.drawArrays(GL_TRIANGLES_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
3309 
3310 				if (GL_INVALID_OPERATION != gl.getError())
3311 				{
3312 					result = false;
3313 
3314 					m_testCtx.getLog() << tcu::TestLog::Message
3315 									   << "Error different than GL_INVALID_OPEARATION was generated."
3316 									   << tcu::TestLog::EndMessage;
3317 
3318 					break;
3319 				}
3320 
3321 				gl.drawArrays(GL_TRIANGLE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
3322 
3323 				if (GL_INVALID_OPERATION != gl.getError())
3324 				{
3325 					result = false;
3326 
3327 					m_testCtx.getLog() << tcu::TestLog::Message
3328 									   << "Error different than GL_INVALID_OPEARATION was generated."
3329 									   << tcu::TestLog::EndMessage;
3330 
3331 					break;
3332 				}
3333 			}
3334 		}
3335 	}
3336 
3337 	if (result)
3338 	{
3339 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3340 	}
3341 	else
3342 	{
3343 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3344 	}
3345 
3346 	return STOP;
3347 }
3348 
3349 /** Constructor
3350  *
3351  * @param context       Test context
3352  * @param extParams     Not used.
3353  * @param name          Test case's name
3354  * @param description   Test case's description
3355  **/
GeometryShaderInsufficientEmittedVerticesTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)3356 GeometryShaderInsufficientEmittedVerticesTest::GeometryShaderInsufficientEmittedVerticesTest(
3357 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
3358 	: TestCaseBase(context, extParams, name, description)
3359 	, m_fbo_id(0)
3360 	, m_fs_id(0)
3361 	, m_gs_ids(NULL)
3362 	, m_number_of_color_components(4)
3363 	, m_number_of_gs(2 /*taken from test spec*/)
3364 	, m_po_ids(NULL)
3365 	, m_texture_height(16)
3366 	, m_texture_id(0)
3367 	, m_texture_width(16)
3368 {
3369 	m_vao_id = 0;
3370 	m_vs_id  = 0;
3371 
3372 	/* Allocate enough memory for glReadPixels() data which is respectively: width, height, RGBA components number. */
3373 	m_pixels = new glw::GLubyte[m_texture_height * m_texture_width * m_number_of_color_components];
3374 }
3375 
3376 /** Deinitializes GLES objects created during the test. */
deinit()3377 void GeometryShaderInsufficientEmittedVerticesTest::deinit()
3378 {
3379 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3380 
3381 	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
3382 
3383 	if (m_pixels != NULL)
3384 	{
3385 		delete[] m_pixels;
3386 		m_pixels = NULL;
3387 	}
3388 
3389 	if (m_fbo_id != 0)
3390 	{
3391 		gl.deleteFramebuffers(1, &m_fbo_id);
3392 		m_fbo_id = 0;
3393 	}
3394 
3395 	if (m_fs_id != 0)
3396 	{
3397 		gl.deleteShader(m_fs_id);
3398 		m_fs_id = 0;
3399 	}
3400 
3401 	if (m_gs_ids != 0)
3402 	{
3403 		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3404 		{
3405 			gl.deleteShader(m_gs_ids[i]);
3406 			m_gs_ids[i] = 0;
3407 		}
3408 
3409 		delete[] m_gs_ids;
3410 		m_gs_ids = NULL;
3411 	}
3412 
3413 	if (m_po_ids != 0)
3414 	{
3415 		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3416 		{
3417 			gl.deleteProgram(m_po_ids[i]);
3418 			m_po_ids[i] = 0;
3419 		}
3420 
3421 		delete[] m_po_ids;
3422 		m_po_ids = NULL;
3423 	}
3424 
3425 	if (m_texture_id != 0)
3426 	{
3427 		gl.deleteTextures(1, &m_texture_id);
3428 		m_texture_id = 0;
3429 	}
3430 
3431 	if (m_vao_id != 0)
3432 	{
3433 		gl.deleteVertexArrays(1, &m_vao_id);
3434 		m_vao_id = 0;
3435 	}
3436 
3437 	if (m_vs_id != 0)
3438 	{
3439 		gl.deleteShader(m_vs_id);
3440 		m_vs_id = 0;
3441 	}
3442 
3443 	/* Release base class */
3444 	TestCaseBase::deinit();
3445 }
3446 
3447 /** Executes the test.
3448  *
3449  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3450  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3451  *  Note the function throws exception should an error occur!
3452  **/
iterate()3453 tcu::TestNode::IterateResult GeometryShaderInsufficientEmittedVerticesTest::iterate()
3454 {
3455 	/* Define Fragment Shader for purpose of this test. */
3456 	const char* fs_code = "${VERSION}\n"
3457 						  "\n"
3458 						  "precision highp float;\n"
3459 						  "\n"
3460 						  "out vec4 result;\n"
3461 						  "\n"
3462 						  "void main()\n"
3463 						  "{\n"
3464 						  "    result = vec4(1.0, 0.0, 0.0, 0.0);\n"
3465 						  "}\n";
3466 
3467 	/* Define 2 Geometry Shaders for purpose of this test. */
3468 	const char* gs_line_strip = "${VERSION}\n"
3469 								"${GEOMETRY_SHADER_REQUIRE}\n"
3470 								"\n"
3471 								"layout (points)                       in;\n"
3472 								"layout (line_strip, max_vertices = 2) out;\n"
3473 								"\n"
3474 								"${IN_PER_VERTEX_DECL_ARRAY}"
3475 								"\n"
3476 								"void main()\n"
3477 								"{\n"
3478 								"    gl_Position    = gl_in[0].gl_Position;\n"
3479 								"    gl_Position.zw = vec2(0.0, 1.0);\n"
3480 								"    EmitVertex();\n"
3481 								"}\n";
3482 
3483 	const char* gs_triangle_strip = "${VERSION}\n"
3484 									"${GEOMETRY_SHADER_REQUIRE}\n"
3485 									"\n"
3486 									"layout (points)                           in;\n"
3487 									"layout (triangle_strip, max_vertices = 3) out;\n"
3488 									"\n"
3489 									"${IN_PER_VERTEX_DECL_ARRAY}"
3490 									"\n"
3491 									"void main()\n"
3492 									"{\n"
3493 									"    gl_Position    = gl_in[0].gl_Position;\n"
3494 									"    gl_Position.zw = vec2(0.0, 1.0);\n"
3495 									"    EmitVertex();\n"
3496 
3497 									"    gl_Position    = gl_in[0].gl_Position;\n"
3498 									"    gl_Position.zw = vec2(0.0, 1.0);\n"
3499 									"    EmitVertex();\n"
3500 									"}\n";
3501 
3502 	bool has_shader_compilation_failed = true;
3503 	bool result						   = true;
3504 
3505 	m_gs_ids = new glw::GLuint[m_number_of_gs];
3506 	m_po_ids = new glw::GLuint[m_number_of_gs];
3507 
3508 	/* This test should only run if EXT_geometry_shader is supported. */
3509 	if (!m_is_geometry_shader_extension_supported)
3510 	{
3511 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3512 	}
3513 
3514 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3515 
3516 	/* Create program objects & geometry shader objects. */
3517 	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3518 	{
3519 		m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
3520 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3521 
3522 		m_po_ids[i] = gl.createProgram();
3523 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3524 	}
3525 
3526 	/* Create shader object. */
3527 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3528 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3529 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3530 
3531 	/* Try to link the test program object */
3532 	std::string fs_code_specialized		= specializeShader(1, &fs_code);
3533 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
3534 
3535 	std::string gs_codes_specialized[] = { specializeShader(1, &gs_line_strip),
3536 										   specializeShader(1, &gs_triangle_strip) };
3537 
3538 	const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str() };
3539 
3540 	std::string vs_code_specialized		= specializeShader(1, &dummy_vs_code);
3541 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3542 
3543 	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3544 	{
3545 		if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,				  /* n_sh1_body_parts */
3546 										&fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
3547 										&gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
3548 										&vs_code_specialized_raw, &has_shader_compilation_failed))
3549 		{
3550 			m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
3551 							   << "[" << i << "]." << tcu::TestLog::EndMessage;
3552 
3553 			result = false;
3554 			break;
3555 		}
3556 	}
3557 
3558 	if (result)
3559 	{
3560 		/* Create a 2D texture. */
3561 		gl.genTextures(1, &m_texture_id);
3562 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
3563 
3564 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
3565 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
3566 
3567 		gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_RGBA8, 16 /*width taken from spec*/,
3568 						16 /*height taken from spec*/);
3569 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
3570 
3571 		/* Configure FBO. */
3572 		gl.genFramebuffers(1, &m_fbo_id);
3573 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
3574 
3575 		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
3576 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
3577 
3578 		gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /*level*/);
3579 		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
3580 
3581 		/* Configure VAO. */
3582 		gl.genVertexArrays(1, &m_vao_id);
3583 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3584 
3585 		gl.bindVertexArray(m_vao_id);
3586 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3587 
3588 		gl.clearColor(0.0f, 1.0f, 0.0f, 0.0f);
3589 		GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
3590 
3591 		for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
3592 		{
3593 			/* Use Program Object. */
3594 			gl.useProgram(m_po_ids[po]);
3595 			GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3596 
3597 			gl.clear(GL_COLOR_BUFFER_BIT);
3598 			GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
3599 
3600 			gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3601 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
3602 
3603 			gl.readPixels(0 /*x*/, 0 /*y*/, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
3604 			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
3605 
3606 			for (glw::GLuint pixel = 0; pixel < (m_texture_width * m_texture_height * m_number_of_color_components -
3607 												 m_number_of_color_components);
3608 				 pixel += m_number_of_color_components)
3609 			{
3610 				if (m_pixels[pixel] != 0 && m_pixels[pixel + 1] != 255 && m_pixels[pixel + 2] != 0 &&
3611 					m_pixels[pixel + 3] != 0)
3612 				{
3613 					result = false;
3614 
3615 					m_testCtx.getLog() << tcu::TestLog::Message << "Pixel [" << pixel << "] has color = ["
3616 									   << m_pixels[pixel] << ", " << m_pixels[pixel + 1] << ", " << m_pixels[pixel + 2]
3617 									   << ", " << m_pixels[pixel + 3] << "] "
3618 									   << "instead of [0, 255, 0, 0]." << tcu::TestLog::EndMessage;
3619 
3620 					break;
3621 				}
3622 			}
3623 		}
3624 	}
3625 
3626 	if (result)
3627 	{
3628 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3629 	}
3630 	else
3631 	{
3632 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3633 	}
3634 
3635 	return STOP;
3636 }
3637 
3638 /** Constructor
3639  *
3640  * @param context       Test context
3641  * @param extParams     Not used.
3642  * @param name          Test case's name
3643  * @param description   Test case's description
3644  **/
3645 GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::
GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)3646 	GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context&			 context,
3647 																					const ExtParameters& extParams,
3648 																					const char*			 name,
3649 																					const char*			 description)
3650 	: TestCaseBase(context, extParams, name, description)
3651 	, m_gs_id(0)
3652 	, m_gs_po_id(0)
3653 	, m_ppo_id(0)
3654 	, m_tfbo_id(0)
3655 	, m_vao_id(0)
3656 	, m_vs_id(0)
3657 	, m_vs_po_id(0)
3658 {
3659 }
3660 
3661 /** Deinitializes GLES objects created during the test. */
deinit()3662 void GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::deinit()
3663 {
3664 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3665 
3666 	if (m_gs_id != 0)
3667 	{
3668 		gl.deleteShader(m_gs_id);
3669 		m_gs_id = 0;
3670 	}
3671 
3672 	if (m_gs_po_id != 0)
3673 	{
3674 		gl.deleteProgram(m_gs_po_id);
3675 		m_gs_po_id = 0;
3676 	}
3677 
3678 	if (m_ppo_id != 0)
3679 	{
3680 		gl.deleteProgramPipelines(1, &m_ppo_id);
3681 		m_ppo_id = 0;
3682 	}
3683 
3684 	if (m_tfbo_id != 0)
3685 	{
3686 		gl.deleteBuffers(1, &m_tfbo_id);
3687 		m_tfbo_id = 0;
3688 	}
3689 
3690 	if (m_vao_id != 0)
3691 	{
3692 		gl.deleteVertexArrays(1, &m_vao_id);
3693 		m_vao_id = 0;
3694 	}
3695 
3696 	if (m_vs_id != 0)
3697 	{
3698 		gl.deleteShader(m_vs_id);
3699 		m_vs_id = 0;
3700 	}
3701 
3702 	if (m_vs_po_id != 0)
3703 	{
3704 		gl.deleteProgram(m_vs_po_id);
3705 		m_vs_po_id = 0;
3706 	}
3707 
3708 	/* Release base class */
3709 	TestCaseBase::deinit();
3710 }
3711 
3712 /** Executes the test.
3713  *
3714  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3715  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3716  *  Note the function throws exception should an error occur!
3717  **/
iterate()3718 tcu::TestNode::IterateResult GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::iterate()
3719 {
3720 	/* Define Geometry Shader for purpose of this test. */
3721 	const char* gs_code =
3722 		"${VERSION}\n"
3723 		"${GEOMETRY_SHADER_REQUIRE}\n"
3724 		"${IN_PER_VERTEX_DECL_ARRAY}\n"
3725 		"${OUT_PER_VERTEX_DECL}\n"
3726 		"\n"
3727 		"layout (points)                   in;\n"
3728 		"layout (points, max_vertices = 1) out;\n"
3729 		"\n"
3730 		"flat in int   vertexID[];\n"
3731 		"flat in ivec4 out_vs_1[];\n"
3732 		"\n"
3733 		"out vec4 out_gs_1;\n"
3734 		"\n"
3735 		"void main()\n"
3736 		"{\n"
3737 		"    out_gs_1 = vec4(vertexID[0] * 2, vertexID[0] * 2 + 1, vertexID[0] * 2 + 2, vertexID[0] * 2 + 3);\n"
3738 		"    gl_Position = vec4(0, 0, 0, 1);\n"
3739 		"    EmitVertex();\n"
3740 		"}\n";
3741 
3742 	/* Define Vertex Shader for purpose of this test. */
3743 	const char* vs_code = "${VERSION}\n"
3744 						  "${OUT_PER_VERTEX_DECL}\n"
3745 						  "\n"
3746 						  "flat out ivec4 out_vs_1;\n"
3747 						  "flat out int vertexID;\n"
3748 						  "\n"
3749 						  "void main()\n"
3750 						  "{\n"
3751 						  "    vertexID = gl_VertexID;\n"
3752 						  "    out_vs_1 = ivec4(gl_VertexID, gl_VertexID + 1, gl_VertexID + 2, gl_VertexID + 3);\n"
3753 						  "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3754 						  "}\n";
3755 
3756 	bool		  has_shader_compilation_failed = true;
3757 	bool		  result						= true;
3758 	glw::GLfloat* ptrTF_data_f					= NULL;
3759 	glw::GLuint*  ptrTF_data_ui					= NULL;
3760 	glw::GLfloat  expected_geom_results[]		= { 0.0f, 1.0f, 2.0f, 3.0f };
3761 	glw::GLuint   expected_vertex_results[]		= { 0, 1, 2, 3 };
3762 	glw::GLfloat  epsilon						= 1e-5f;
3763 
3764 	/* This test should only run if EXT_geometry_shader is supported. */
3765 	if (!m_is_geometry_shader_extension_supported)
3766 	{
3767 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3768 	}
3769 
3770 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3771 
3772 	/* Create separable program objects. */
3773 	m_gs_po_id = gl.createProgram();
3774 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3775 
3776 	gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
3777 	GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
3778 
3779 	m_vs_po_id = gl.createProgram();
3780 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3781 
3782 	gl.programParameteri(m_vs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
3783 	GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
3784 
3785 	/* Create shader objects. */
3786 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
3787 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3788 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3789 
3790 	/* Try to link the test program object */
3791 	std::string gs_code_specialized		= specializeShader(1, &gs_code);
3792 	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
3793 
3794 	std::string vs_code_specialized		= specializeShader(1, &vs_code);
3795 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3796 
3797 	/* Specify output variables to be captured. */
3798 	const char* tf_varyings[2] = { "out_gs_1", "out_vs_1" };
3799 
3800 	gl.transformFeedbackVaryings(m_gs_po_id, 1 /*count*/, &tf_varyings[0], GL_INTERLEAVED_ATTRIBS);
3801 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
3802 
3803 	gl.transformFeedbackVaryings(m_vs_po_id, 1 /*count*/, &tf_varyings[1], GL_INTERLEAVED_ATTRIBS);
3804 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
3805 
3806 	if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1,			/* n_sh1_body_parts */
3807 									&gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
3808 									NULL, 0, 0,						/* n_sh3_body_parts */
3809 									NULL, &has_shader_compilation_failed))
3810 	{
3811 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
3812 						   << tcu::TestLog::EndMessage;
3813 
3814 		result = false;
3815 		goto end;
3816 	}
3817 
3818 	if (!TestCaseBase::buildProgram(m_vs_po_id, m_vs_id, 1,			/* n_sh1_body_parts */
3819 									&vs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
3820 									NULL, 0, 0,						/* n_sh3_body_parts */
3821 									NULL, &has_shader_compilation_failed))
3822 	{
3823 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
3824 						   << tcu::TestLog::EndMessage;
3825 
3826 		result = false;
3827 		goto end;
3828 	}
3829 
3830 	/* Create and configure Program Pipeline Object. */
3831 	gl.genProgramPipelines(1, &m_ppo_id);
3832 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call(s) failed.");
3833 
3834 	gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
3835 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3836 
3837 	gl.useProgramStages(m_ppo_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
3838 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3839 
3840 	/* Create Vertex Array Object. */
3841 	gl.genVertexArrays(1, &m_vao_id);
3842 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
3843 
3844 	gl.bindVertexArray(m_vao_id);
3845 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
3846 
3847 	/* Create Buffer Object for Transform Feedback data. */
3848 	gl.genBuffers(1, &m_tfbo_id);
3849 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
3850 
3851 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
3852 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
3853 
3854 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4, NULL, GL_STREAM_READ);
3855 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
3856 
3857 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
3858 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
3859 
3860 	/* Ensure that there is no program object already bound and bind program pipeline. */
3861 	gl.useProgram(0);
3862 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
3863 
3864 	gl.bindProgramPipeline(m_ppo_id);
3865 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
3866 
3867 	gl.enable(GL_RASTERIZER_DISCARD);
3868 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
3869 
3870 	/* First pass - Vertex and Geometry Shaders On. */
3871 	gl.beginTransformFeedback(GL_POINTS);
3872 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
3873 
3874 	gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3875 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
3876 
3877 	gl.endTransformFeedback();
3878 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
3879 
3880 	/* Retrieve data and check if it is correct. */
3881 	ptrTF_data_f =
3882 		(glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
3883 										 sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
3884 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3885 
3886 	for (size_t i = 0; i < 4; ++i)
3887 	{
3888 		if (fabs(ptrTF_data_f[i] - expected_geom_results[i]) >= epsilon)
3889 		{
3890 			result = false;
3891 			break;
3892 		}
3893 	}
3894 
3895 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3896 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3897 
3898 	ptrTF_data_f = NULL;
3899 
3900 	if (!result)
3901 	{
3902 		goto end;
3903 	}
3904 
3905 	/* Deactivate Geometry Shader Program Object from Program Pipeline Object. */
3906 	gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, 0 /* program */);
3907 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3908 
3909 	/* Second pass - only Vertex Shader Program On. */
3910 	gl.beginTransformFeedback(GL_POINTS);
3911 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
3912 
3913 	gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3914 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
3915 
3916 	gl.endTransformFeedback();
3917 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
3918 
3919 	gl.disable(GL_RASTERIZER_DISCARD);
3920 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
3921 
3922 	/* Retrieve data and check if it is correct. */
3923 	ptrTF_data_ui =
3924 		(glw::GLuint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
3925 										sizeof(glw::GLuint) * 4 /* four float vector components */, GL_MAP_READ_BIT);
3926 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3927 
3928 	for (size_t i = 0; i < 4; ++i)
3929 	{
3930 		if (ptrTF_data_ui[i] != expected_vertex_results[i])
3931 		{
3932 			result = false;
3933 			break;
3934 		}
3935 	}
3936 
3937 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3938 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3939 
3940 	ptrTF_data_ui = NULL;
3941 
3942 end:
3943 	if (result)
3944 	{
3945 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3946 	}
3947 	else
3948 	{
3949 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3950 	}
3951 
3952 	return STOP;
3953 }
3954 
3955 /** Constructor
3956  *
3957  * @param context       Test context
3958  * @param extParams     Not used.
3959  * @param name          Test case's name
3960  * @param description   Test case's description
3961  **/
GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives(Context & context,const ExtParameters & extParams,const char * name,const char * description)3962 GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives(
3963 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
3964 	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_tfbo_id(0)
3965 {
3966 	m_vao_id = 0;
3967 	m_vs_id  = 0;
3968 }
3969 
3970 /** Deinitializes GLES objects created during the test. */
deinit()3971 void GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::deinit()
3972 {
3973 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3974 
3975 	if (m_fs_id != 0)
3976 	{
3977 		gl.deleteShader(m_fs_id);
3978 		m_fs_id = 0;
3979 	}
3980 
3981 	if (m_gs_id != 0)
3982 	{
3983 		gl.deleteShader(m_gs_id);
3984 		m_gs_id = 0;
3985 	}
3986 
3987 	if (m_po_id != 0)
3988 	{
3989 		gl.deleteProgram(m_po_id);
3990 		m_po_id = 0;
3991 	}
3992 
3993 	if (m_tfbo_id != 0)
3994 	{
3995 		gl.deleteBuffers(1, &m_tfbo_id);
3996 		m_tfbo_id = 0;
3997 	}
3998 
3999 	if (m_vao_id != 0)
4000 	{
4001 		gl.deleteVertexArrays(1, &m_vao_id);
4002 		m_vao_id = 0;
4003 	}
4004 
4005 	if (m_vs_id != 0)
4006 	{
4007 		gl.deleteShader(m_vs_id);
4008 		m_vs_id = 0;
4009 	}
4010 
4011 	/* Release base class */
4012 	TestCaseBase::deinit();
4013 }
4014 
4015 /** Executes the test.
4016  *
4017  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4018  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
4019  *  Note the function throws exception should an error occur!
4020  **/
iterate()4021 tcu::TestNode::IterateResult GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::iterate()
4022 {
4023 	/* Define Geometry Shader for purpose of this test. */
4024 	const char* gs_code = "${VERSION}\n"
4025 						  "${GEOMETRY_SHADER_REQUIRE}\n"
4026 						  "\n"
4027 						  "layout (lines)                            in;\n"
4028 						  "layout (triangle_strip, max_vertices = 3) out;\n"
4029 						  "\n"
4030 						  "out vec4 out_gs_1;\n"
4031 						  "\n"
4032 						  "void main()\n"
4033 						  "{\n"
4034 						  "    out_gs_1 = vec4(4.0, 3.0, 2.0, 1.0);\n"
4035 						  "\n"
4036 						  "    gl_Position = vec4(0, 0, 0, 1);\n"
4037 						  "    EmitVertex();\n"
4038 						  "\n"
4039 						  "    gl_Position = vec4(1, 0, 0, 1);\n"
4040 						  "    EmitVertex();\n"
4041 						  "\n"
4042 						  "    gl_Position = vec4(1, 1, 0, 1);\n"
4043 						  "    EmitVertex();\n"
4044 						  "\n"
4045 						  "    EndPrimitive();"
4046 						  "}\n";
4047 
4048 	bool		has_shader_compilation_failed = true;
4049 	bool		result						  = true;
4050 	glw::GLenum error						  = GL_NO_ERROR;
4051 
4052 	/* This test should only run if EXT_geometry_shader is supported. */
4053 	if (!m_is_geometry_shader_extension_supported)
4054 	{
4055 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
4056 	}
4057 
4058 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4059 
4060 	/* Create program object. */
4061 	m_po_id = gl.createProgram();
4062 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
4063 
4064 	/* Specify output variables to be captured. */
4065 	const char* tf_varyings[] = { "out_gs_1" };
4066 
4067 	gl.transformFeedbackVaryings(m_po_id, 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
4068 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
4069 
4070 	/* Create shader objects. */
4071 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4072 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4073 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4074 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4075 
4076 	/* Try to link the test program object */
4077 	std::string fs_code_specialized		= specializeShader(1, &dummy_fs_code);
4078 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
4079 
4080 	std::string gs_code_specialized		= specializeShader(1, &gs_code);
4081 	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
4082 
4083 	std::string vs_code_specialized		= specializeShader(1, &dummy_vs_code);
4084 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
4085 
4086 	if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1,				  /* n_sh1_body_parts */
4087 									&fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
4088 									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
4089 									&vs_code_specialized_raw, &has_shader_compilation_failed))
4090 	{
4091 		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed whereas a success was expected."
4092 						   << tcu::TestLog::EndMessage;
4093 
4094 		result = false;
4095 		goto end;
4096 	}
4097 
4098 	/* Create Vertex Array Object. */
4099 	gl.genVertexArrays(1, &m_vao_id);
4100 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
4101 
4102 	gl.bindVertexArray(m_vao_id);
4103 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
4104 
4105 	/* Create Buffer Object for Transform Feedback data. */
4106 	gl.genBuffers(1, &m_tfbo_id);
4107 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
4108 
4109 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
4110 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4111 
4112 	gl.bufferData(GL_ARRAY_BUFFER,
4113 				  sizeof(glw::GLfloat) * 4 * 3 /* capture 4 float vector components times 3 triangle vertices */, NULL,
4114 				  GL_STREAM_READ);
4115 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
4116 
4117 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
4118 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
4119 
4120 	/* Turn on program object. */
4121 	gl.useProgram(m_po_id);
4122 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
4123 
4124 	gl.enable(GL_RASTERIZER_DISCARD);
4125 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
4126 
4127 	gl.beginTransformFeedback(GL_LINES);
4128 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
4129 
4130 	gl.drawArrays(GL_TRIANGLES, 0 /*first*/, 3 /*count*/);
4131 
4132 	error = gl.getError();
4133 
4134 	if (error != GL_INVALID_OPERATION)
4135 	{
4136 		result = false;
4137 
4138 		m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
4139 						   << tcu::TestLog::EndMessage;
4140 	}
4141 
4142 	gl.endTransformFeedback();
4143 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
4144 
4145 	gl.disable(GL_RASTERIZER_DISCARD);
4146 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
4147 
4148 end:
4149 
4150 	if (result)
4151 	{
4152 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4153 	}
4154 	else
4155 	{
4156 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4157 	}
4158 
4159 	return STOP;
4160 }
4161 
4162 /** Constructor
4163  *
4164  * @param context       Test context
4165  * @param extParams     Not used.
4166  * @param name          Test case's name
4167  * @param description   Test case's description
4168  **/
GeometryShaderDrawCallsWhileTFPaused(Context & context,const ExtParameters & extParams,const char * name,const char * description)4169 GeometryShaderDrawCallsWhileTFPaused::GeometryShaderDrawCallsWhileTFPaused(Context&				context,
4170 																		   const ExtParameters& extParams,
4171 																		   const char* name, const char* description)
4172 	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_tfbo_id(0)
4173 {
4174 	m_vao_id = 0;
4175 	m_vs_id  = 0;
4176 }
4177 
4178 /** Deinitializes GLES objects created during the test. */
deinit()4179 void GeometryShaderDrawCallsWhileTFPaused::deinit()
4180 {
4181 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4182 
4183 	if (m_fs_id != 0)
4184 	{
4185 		gl.deleteShader(m_fs_id);
4186 		m_fs_id = 0;
4187 	}
4188 
4189 	if (m_gs_id != 0)
4190 	{
4191 		gl.deleteShader(m_gs_id);
4192 		m_gs_id = 0;
4193 	}
4194 
4195 	for (int i = 0; i < 15 /* All combinations of possible inputs and outputs in GS */; ++i)
4196 	{
4197 		if (m_po_ids[i] != 0)
4198 		{
4199 			gl.deleteProgram(m_po_ids[i]);
4200 			m_po_ids[i] = 0;
4201 		}
4202 	}
4203 
4204 	if (m_tfbo_id != 0)
4205 	{
4206 		gl.deleteBuffers(1, &m_tfbo_id);
4207 		m_tfbo_id = 0;
4208 	}
4209 
4210 	if (m_vao_id != 0)
4211 	{
4212 		gl.deleteVertexArrays(1, &m_vao_id);
4213 		m_vao_id = 0;
4214 	}
4215 
4216 	if (m_vs_id != 0)
4217 	{
4218 		gl.deleteShader(m_vs_id);
4219 		m_vs_id = 0;
4220 	}
4221 
4222 	/* Release base class */
4223 	TestCaseBase::deinit();
4224 }
4225 
4226 /** Executes the test.
4227  *
4228  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4229  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
4230  *  Note the function throws exception should an error occur!
4231  **/
iterate()4232 tcu::TestNode::IterateResult GeometryShaderDrawCallsWhileTFPaused::iterate()
4233 {
4234 	/* Define 15 (all combinations of possible inputs and outputs in geometry shader) Geometry Shaders for purpose of this test. */
4235 	const std::string gs_inputs[]  = { "points", "lines", "lines_adjacency", "triangles", "triangles_adjacency" };
4236 	const std::string gs_outputs[] = { "points", "line_strip", "triangle_strip" };
4237 	const std::string gs_max_output_vertices[] = { "1", "2", "3" };
4238 
4239 	const unsigned short number_of_combinations =
4240 		(sizeof(gs_inputs) / sizeof(gs_inputs[0]) * (sizeof(gs_outputs) / sizeof(gs_outputs[0])));
4241 
4242 	std::string gs_codes[number_of_combinations];
4243 	glw::GLenum errorCode;
4244 
4245 	for (size_t i = 0; i < (sizeof(gs_inputs) / sizeof(gs_inputs[0])) /*5 possible GS inputs*/; ++i)
4246 	{
4247 		for (size_t j = 0; j < (sizeof(gs_outputs) / sizeof(gs_outputs[0])) /*3 possible GS outputs*/; ++j)
4248 		{
4249 			/* This shader will not emit primitives for anything but points.
4250 			 * We do so, because we just need to make sure that, while transform feedback
4251 			 * is paused, all draw calls executed with an active program object which
4252 			 * includes a geometry shader, are valid.
4253 			 */
4254 			gs_codes[j + 3 * i] = "${VERSION}\n"
4255 								  "${GEOMETRY_SHADER_REQUIRE}\n"
4256 								  "\n"
4257 								  "layout (" +
4258 								  gs_inputs[i] + ") in;\n"
4259 												 "layout (" +
4260 								  gs_outputs[j] + ", max_vertices = " + gs_max_output_vertices[j] +
4261 								  ") out;\n"
4262 								  "\n"
4263 								  "out vec2 out_gs_1;\n"
4264 								  "\n"
4265 								  "void main()\n"
4266 								  "{\n"
4267 								  "    out_gs_1    = vec2(1.0, 2.0);\n"
4268 								  "    gl_Position = vec4(0, 0, 0, 1);\n"
4269 								  "    EmitVertex();\n"
4270 								  "}\n";
4271 		}
4272 	}
4273 
4274 	bool			  has_shader_compilation_failed = true;
4275 	bool			  result						= true;
4276 	const glw::GLuint tf_modes[3]					= { GL_POINTS, GL_LINES, GL_TRIANGLES };
4277 	const glw::GLuint draw_call_modes[5]			= { GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES,
4278 											 GL_TRIANGLES_ADJACENCY };
4279 
4280 	/* This test should only run if EXT_geometry_shader is supported. */
4281 	if (!m_is_geometry_shader_extension_supported)
4282 	{
4283 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
4284 	}
4285 
4286 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4287 
4288 	/* Create program objects. */
4289 	for (int i = 0; i < number_of_combinations; ++i)
4290 	{
4291 		m_po_ids[i] = gl.createProgram();
4292 	}
4293 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
4294 
4295 	/* Specify output variables to be captured. */
4296 	const char* tf_varyings[] = { "out_gs_1" };
4297 
4298 	for (int i = 0; i < number_of_combinations; ++i)
4299 	{
4300 		gl.transformFeedbackVaryings(m_po_ids[i], 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
4301 	}
4302 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
4303 
4304 	/* Create shader objects. */
4305 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4306 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4307 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4308 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4309 
4310 	/* Try to link the test program object */
4311 	std::string fs_code_specialized		= specializeShader(1, &dummy_fs_code);
4312 	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
4313 
4314 	std::string vs_code_specialized		= specializeShader(1, &dummy_vs_code);
4315 	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
4316 
4317 	for (int i = 0; i < number_of_combinations; ++i)
4318 	{
4319 		const char* gs_code					= gs_codes[i].c_str();
4320 		std::string gs_code_specialized		= specializeShader(1, &gs_code);
4321 		const char* gs_code_specialized_raw = gs_code_specialized.c_str();
4322 
4323 		if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,			  /* n_sh1_body_parts */
4324 										&fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
4325 										&gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
4326 										&vs_code_specialized_raw, &has_shader_compilation_failed))
4327 		{
4328 			m_testCtx.getLog() << tcu::TestLog::Message
4329 							   << "Program object linking failed whereas a success was expected."
4330 							   << tcu::TestLog::EndMessage;
4331 
4332 			result = false;
4333 		}
4334 	}
4335 
4336 	if (!result)
4337 	{
4338 		goto end;
4339 	}
4340 
4341 	/* Create Vertex Array Object. */
4342 	gl.genVertexArrays(1, &m_vao_id);
4343 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
4344 
4345 	gl.bindVertexArray(m_vao_id);
4346 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
4347 
4348 	/* Create Buffer Object for Transform Feedback data. */
4349 	gl.genBuffers(1, &m_tfbo_id);
4350 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
4351 
4352 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
4353 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4354 
4355 	gl.bufferData(GL_ARRAY_BUFFER,
4356 				  sizeof(glw::GLfloat) * 2 * 3 /* capture 2 float vector components times 3 triangle vertices */, NULL,
4357 				  GL_STREAM_READ);
4358 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
4359 
4360 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
4361 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
4362 
4363 	gl.enable(GL_RASTERIZER_DISCARD);
4364 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
4365 
4366 	for (int i = 0; i < 3 /* number of TF modes */ && result; ++i)
4367 	{
4368 		for (int j = 0; j < 5 /*number of draw call modes*/ && result; ++j)
4369 		{
4370 			for (int k = 0; k < 3 /* number of output GS primitive types */; ++k)
4371 			{
4372 				/* Turn on program object. */
4373 				gl.useProgram(m_po_ids[k + 3 * j]);
4374 				GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
4375 
4376 				gl.beginTransformFeedback(tf_modes[i]);
4377 				GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
4378 
4379 				gl.pauseTransformFeedback();
4380 				GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback() call(s) failed.");
4381 
4382 				gl.drawArrays(draw_call_modes[j], 0 /*first*/, 3 /*count*/);
4383 				errorCode = gl.getError();
4384 
4385 				gl.resumeTransformFeedback();
4386 				GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback() call(s) failed.");
4387 
4388 				gl.endTransformFeedback();
4389 				GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
4390 
4391 				/* If draw call fails stop test execution. */
4392 				if (GL_NO_ERROR != errorCode)
4393 				{
4394 					m_testCtx.getLog() << tcu::TestLog::Message
4395 									   << "glDrawArrays() call generated an error while transform feedback was paused."
4396 									   << tcu::TestLog::EndMessage;
4397 
4398 					result = false;
4399 					break;
4400 				}
4401 			}
4402 		}
4403 	}
4404 
4405 	gl.disable(GL_RASTERIZER_DISCARD);
4406 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
4407 
4408 end:
4409 
4410 	if (result)
4411 	{
4412 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4413 	}
4414 	else
4415 	{
4416 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4417 	}
4418 
4419 	return STOP;
4420 }
4421 
4422 } // namespace glcts
4423