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