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 "esextcGeometryShaderLinking.hpp"
24
25#include "gluDefs.hpp"
26#include "glwEnums.hpp"
27#include "glwFunctions.hpp"
28#include "tcuTestLog.hpp"
29#include <cstring>
30
31namespace glcts
32{
33
34static const char* minimal_fs_code = "${VERSION}\n"
35								   "\n"
36								   "precision highp float;\n"
37								   "\n"
38								   "out vec4 result;\n"
39								   "\n"
40								   "void main()\n"
41								   "{\n"
42								   "    result = vec4(1.0);\n"
43								   "}\n";
44
45static const char* minimal_gs_code = "${VERSION}\n"
46								   "${GEOMETRY_SHADER_REQUIRE}\n"
47								   "\n"
48								   "layout (points)                   in;\n"
49								   "layout (points, max_vertices = 1) out;\n"
50								   "\n"
51								   "${OUT_PER_VERTEX_DECL}"
52								   "${IN_DATA_DECL}"
53								   "\n"
54								   "void main()\n"
55								   "{\n"
56								   "${POSITION_WITH_IN_DATA}"
57								   "    EmitVertex();\n"
58								   "}\n";
59
60static const char* minimal_vs_code = "${VERSION}\n"
61								   "\n"
62								   "${OUT_PER_VERTEX_DECL}"
63								   "\n"
64								   "void main()\n"
65								   "{\n"
66								   "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
67								   "}\n";
68
69/** Constructor
70 *
71 * @param context       Test context
72 * @param extParams     Not used.
73 * @param name          Test case's name
74 * @param description   Test case's description
75 **/
76GeometryShaderIncompleteProgramObjectsTest::GeometryShaderIncompleteProgramObjectsTest(Context&				context,
77																					   const ExtParameters& extParams,
78																					   const char*			name,
79																					   const char*			description)
80	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0)
81{
82}
83
84/** Deinitializes GLES objects created during the test. */
85void GeometryShaderIncompleteProgramObjectsTest::deinit()
86{
87	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
88
89	if (m_fs_id != 0)
90	{
91		gl.deleteShader(m_fs_id);
92
93		m_fs_id = 0;
94	}
95
96	if (m_gs_id != 0)
97	{
98		gl.deleteShader(m_gs_id);
99
100		m_gs_id = 0;
101	}
102
103	if (m_po_id != 0)
104	{
105		gl.deleteProgram(m_po_id);
106
107		m_po_id = 0;
108	}
109
110	/* Release base class */
111	TestCaseBase::deinit();
112}
113
114/** Initializes shader objects for the conformance test */
115void GeometryShaderIncompleteProgramObjectsTest::initShaderObjects()
116{
117	const glw::Functions& gl					  = m_context.getRenderContext().getFunctions();
118	std::string			  specialized_fs_code	 = specializeShader(1, &minimal_fs_code);
119	const char*			  specialized_fs_code_raw = specialized_fs_code.c_str();
120	std::string			  specialized_gs_code	 = specializeShader(1, &minimal_gs_code);
121	const char*			  specialized_gs_code_raw = specialized_gs_code.c_str();
122
123	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
124	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
125
126	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
127
128	for (unsigned int n_shader_type = 0; n_shader_type < 2; /* fs, gs */
129		 n_shader_type++)
130	{
131		glw::GLint  compile_status = GL_FALSE;
132		const char* so_code		   = (n_shader_type == 0) ? specialized_fs_code_raw : specialized_gs_code_raw;
133		glw::GLuint so_id		   = (n_shader_type == 0) ? m_fs_id : m_gs_id;
134
135		gl.shaderSource(so_id, 1,			/* count */
136						&so_code, DE_NULL); /* length */
137
138		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
139
140		gl.compileShader(so_id);
141		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
142
143		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
144
145		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
146
147		if (compile_status != GL_TRUE)
148		{
149			TCU_FAIL("Shader compilation process failed.");
150		}
151	} /* for (both shader stages) */
152}
153
154/** Initializes test runs, to be executed by the conformance test. */
155void GeometryShaderIncompleteProgramObjectsTest::initTestRuns()
156{
157	/*                         use_fs| use_gs| use_separable_po
158	 *                         ------|-------|-----------------*/
159	m_test_runs.push_back(_run(false, true, false));
160	m_test_runs.push_back(_run(false, true, true));
161	m_test_runs.push_back(_run(true, true, false));
162	m_test_runs.push_back(_run(true, true, true));
163}
164
165/** Executes the test.
166 *
167 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
168 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
169 *  Note the function throws exception should an error occur!
170 **/
171tcu::TestNode::IterateResult GeometryShaderIncompleteProgramObjectsTest::iterate()
172{
173	bool result = true;
174
175	/* This test should only run if EXT_geometry_shader is supported. */
176	if (!m_is_geometry_shader_extension_supported)
177	{
178		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
179	}
180
181	/* Initialize test runs */
182	initTestRuns();
183
184	/* Set up shader objects */
185	initShaderObjects();
186
187	/* Iterate over the test run set */
188	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
189
190	for (unsigned int run_index = 0; run_index < m_test_runs.size(); ++run_index)
191	{
192		const _run& current_run = m_test_runs[run_index];
193
194		/* Set up a program object */
195		m_po_id = gl.createProgram();
196		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
197
198		if (current_run.use_separable_po)
199		{
200			gl.programParameteri(m_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
201			GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed");
202		} /* if (current_run.use_separable_po) */
203
204		if (current_run.use_fs)
205		{
206			gl.attachShader(m_po_id, m_fs_id);
207		}
208
209		if (current_run.use_gs)
210		{
211			gl.attachShader(m_po_id, m_gs_id);
212		}
213
214		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed");
215
216		/* Try to link the PO */
217		gl.linkProgram(m_po_id);
218		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
219
220		/* Verify the link status */
221		glw::GLint link_status = GL_FALSE;
222
223		gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
224		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
225
226		if ((current_run.use_separable_po && link_status != GL_TRUE) ||
227			(!current_run.use_separable_po && link_status == GL_TRUE))
228		{
229			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid link status reported for a "
230							   << ((current_run.use_separable_po) ? "separable" : "")
231							   << " program object, to which the following SOs were attached: "
232							   << "FS:" << ((current_run.use_fs) ? "YES" : "NO")
233							   << ", GS:" << ((current_run.use_gs) ? "YES" : "NO") << tcu::TestLog::EndMessage;
234
235			result = false;
236		}
237
238		/* Clean up for the next iteration */
239		gl.deleteProgram(m_po_id);
240		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed");
241	} /* for (all test runs) */
242
243	if (result)
244	{
245		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
246	}
247	else
248	{
249		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
250	}
251
252	return STOP;
253}
254
255/** Constructor
256 *
257 * @param context       Test context
258 * @param extParams     Not used.
259 * @param name          Test case's name
260 * @param description   Test case's description
261 **/
262GeometryShaderIncompleteGSTest::GeometryShaderIncompleteGSTest(Context& context, const ExtParameters& extParams,
263															   const char* name, const char* description)
264	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
265{
266}
267
268/** Deinitializes GLES objects created during the test. */
269void GeometryShaderIncompleteGSTest::deinit()
270{
271	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
272
273	deinitSOs();
274
275	if (m_po_id != 0)
276	{
277		gl.deleteProgram(m_po_id);
278
279		m_po_id = 0;
280	}
281
282	/* Release base class */
283	TestCaseBase::deinit();
284}
285
286/** Deinitializes shader objects created for the conformance test. */
287void GeometryShaderIncompleteGSTest::deinitSOs()
288{
289	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
290
291	if (m_fs_id != 0)
292	{
293		gl.deleteShader(m_fs_id);
294
295		m_fs_id = 0;
296	}
297
298	if (m_gs_id != 0)
299	{
300		gl.deleteShader(m_gs_id);
301
302		m_gs_id = 0;
303	}
304
305	if (m_vs_id != 0)
306	{
307		gl.deleteShader(m_vs_id);
308
309		m_vs_id = 0;
310	}
311}
312
313/** Returns geometry shader's source code, built according to the test run's settings.
314 *
315 *  @param current_run Test run descriptor.
316 *
317 *  @return Requested string.
318 */
319std::string GeometryShaderIncompleteGSTest::getGeometryShaderCode(const _run& current_run)
320{
321	std::stringstream gs_code_sstream;
322
323	gs_code_sstream << "${VERSION}\n"
324					   "${GEOMETRY_SHADER_REQUIRE}\n"
325					   "\n";
326
327	if (current_run.is_input_primitive_type_defined)
328	{
329		gs_code_sstream << "layout(points) in;\n";
330	}
331
332	if (current_run.is_max_vertices_defined || current_run.is_output_primitive_type_defined)
333	{
334		gs_code_sstream << "layout(";
335
336		if (current_run.is_max_vertices_defined)
337		{
338			gs_code_sstream << "max_vertices = 1";
339
340			if (current_run.is_output_primitive_type_defined)
341			{
342				gs_code_sstream << ", ";
343			}
344		} /* if (current_run.is_max_vertices_defined) */
345
346		if (current_run.is_output_primitive_type_defined)
347		{
348			gs_code_sstream << "points";
349		}
350
351		gs_code_sstream << ") out;\n";
352	}
353
354	gs_code_sstream << "\n"
355					   "void main()\n"
356					   "{\n"
357					   "    gl_Position = gl_in[0].gl_Position;\n"
358					   "    EmitVertex();\n"
359					   "}\n";
360
361	return gs_code_sstream.str();
362}
363
364/** Initializes fragment / geometry / vertex shader objects, according to the test run descriptor.
365 *
366 *  @param current_run                      Test run descriptor.
367 *  @param out_has_fs_compiled_successfully Deref will be set to false, if FS has failed to compile
368 *                                          successfully. Otherwise, it will be set to true.
369 *  @param out_has_gs_compiled_successfully Deref will be set to false, if GS has failed to compile
370 *                                          successfully. Otherwise, it will be set to true.
371 *  @param out_has_vs_compiled_successfully Deref will be set to false, if VS has failed to compile
372 *                                          successfully. Otherwise, it will be set to true.
373 *
374 */
375void GeometryShaderIncompleteGSTest::initShaderObjects(const _run& current_run, bool* out_has_fs_compiled_successfully,
376													   bool* out_has_gs_compiled_successfully,
377													   bool* out_has_vs_compiled_successfully)
378{
379	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
380
381	std::string specialized_fs_code = specializeShader(1, &minimal_fs_code);
382	std::string gs_code				= getGeometryShaderCode(current_run);
383	const char* gs_code_raw			= gs_code.c_str();
384	std::string specialized_gs_code = specializeShader(1, &gs_code_raw);
385	std::string specialized_vs_code = specializeShader(1, &minimal_vs_code);
386
387	const char* specialized_fs_code_raw = specialized_fs_code.c_str();
388	const char* specialized_gs_code_raw = specialized_gs_code.c_str();
389	const char* specialized_vs_code_raw = specialized_vs_code.c_str();
390
391	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
392	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
393	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
394
395	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
396
397	for (unsigned int n_shader_type = 0; n_shader_type < 3; /* fs, gs, vs */
398		 n_shader_type++)
399	{
400		glw::GLint compile_status = GL_FALSE;
401		bool*	  out_current_compile_result =
402			(n_shader_type == 0) ?
403				out_has_fs_compiled_successfully :
404				(n_shader_type == 1) ? out_has_gs_compiled_successfully : out_has_vs_compiled_successfully;
405
406		const char* so_code = (n_shader_type == 0) ?
407								  specialized_fs_code_raw :
408								  (n_shader_type == 1) ? specialized_gs_code_raw : specialized_vs_code_raw;
409
410		glw::GLuint so_id = (n_shader_type == 0) ? m_fs_id : (n_shader_type == 1) ? m_gs_id : m_vs_id;
411
412		gl.shaderSource(so_id, 1,			/* count */
413						&so_code, DE_NULL); /* length */
414
415		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
416
417		gl.compileShader(so_id);
418		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
419
420		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
421		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
422
423		*out_current_compile_result = (compile_status == GL_TRUE);
424	} /* for (both shader stages) */
425}
426
427/** Initializes all test runs */
428void GeometryShaderIncompleteGSTest::initTestRuns()
429{
430	/*                         input_primitive_defined | max_vertices_defined | output_primitive_defined
431	 *                         ------------------------|----------------------|-------------------------*/
432	m_test_runs.push_back(_run(false, false, false));
433	m_test_runs.push_back(_run(false, false, true));
434	m_test_runs.push_back(_run(false, true, false));
435	m_test_runs.push_back(_run(true, true, false));
436	m_test_runs.push_back(_run(false, true, true));
437}
438
439/** Executes the test.
440 *
441 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
442 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
443 *  Note the function throws exception should an error occur!
444 **/
445tcu::TestNode::IterateResult GeometryShaderIncompleteGSTest::iterate()
446{
447	bool result = true;
448
449	/* This test should only run if EXT_geometry_shader is supported. */
450	if (!m_is_geometry_shader_extension_supported)
451	{
452		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
453	}
454
455	/* Initialize test runs */
456	initTestRuns();
457
458	/* Iterate over the test run set */
459	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
460
461	for (unsigned int run_index = 0; run_index < m_test_runs.size(); ++run_index)
462	{
463		const _run& current_run = m_test_runs[run_index];
464
465		/* Release shader objects initialized in previous iterations */
466		deinitSOs();
467
468		/* Set up shader objects */
469		bool has_fs_compiled = false;
470		bool has_gs_compiled = false;
471		bool has_vs_compiled = false;
472
473		initShaderObjects(current_run, &has_fs_compiled, &has_gs_compiled, &has_vs_compiled);
474
475		if (!has_fs_compiled || !has_vs_compiled)
476		{
477			m_testCtx.getLog() << tcu::TestLog::Message << "Minimal FS and/or minimal VS failed to compile"
478							   << tcu::TestLog::EndMessage;
479
480			result = false;
481			break;
482		}
483
484		/* Set up a program object */
485		m_po_id = gl.createProgram();
486		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
487
488		gl.attachShader(m_po_id, m_fs_id);
489		gl.attachShader(m_po_id, m_gs_id);
490		gl.attachShader(m_po_id, m_vs_id);
491
492		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed");
493
494		/* Try to link the PO */
495		gl.linkProgram(m_po_id);
496		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
497
498		/* Verify the link status */
499		glw::GLint link_status = GL_FALSE;
500
501		gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
502		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
503
504		if (link_status == GL_TRUE)
505		{
506			m_testCtx.getLog() << tcu::TestLog::Message
507							   << "PO with a malformed Geometry Shader was linked successfully."
508							   << " [input primitive type]:"
509							   << ((current_run.is_input_primitive_type_defined) ? "DEFINED" : "NOT DEFINED")
510							   << " [output primitive type]:"
511							   << ((current_run.is_output_primitive_type_defined) ? "DEFINED" : "NOT DEFINED")
512							   << " [max_vertices]:"
513							   << ((current_run.is_max_vertices_defined) ? "DEFINED" : "NOT DEFINED")
514							   << tcu::TestLog::EndMessage;
515
516			result = false;
517		}
518
519		/* Clean up for the next iteration */
520		gl.deleteProgram(m_po_id);
521		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed");
522	} /* for (all test runs) */
523
524	if (result)
525	{
526		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
527	}
528	else
529	{
530		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
531	}
532
533	return STOP;
534}
535
536/** Constructor
537 *
538 * @param context       Test context
539 * @param extParams     Not used.
540 * @param name          Test case's name
541 * @param description   Test case's description
542 **/
543GeometryShaderInvalidArrayedInputVariablesTest::GeometryShaderInvalidArrayedInputVariablesTest(
544	Context& context, const ExtParameters& extParams, const char* name, const char* description)
545	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
546{
547}
548
549/** Deinitializes GLES objects created during the test. */
550void GeometryShaderInvalidArrayedInputVariablesTest::deinit()
551{
552	deinitSOs();
553
554	/* Release the PO */
555	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
556
557	if (m_po_id != 0)
558	{
559		gl.deleteProgram(m_po_id);
560
561		m_po_id = 0;
562	}
563
564	/* Release base class */
565	TestCaseBase::deinit();
566}
567
568/** Deinitializes shader objects created for the conformance test. */
569void GeometryShaderInvalidArrayedInputVariablesTest::deinitSOs()
570{
571	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
572
573	if (m_fs_id != 0)
574	{
575		gl.deleteShader(m_fs_id);
576
577		m_fs_id = 0;
578	}
579
580	if (m_gs_id != 0)
581	{
582		gl.deleteShader(m_gs_id);
583
584		m_gs_id = 0;
585	}
586
587	if (m_vs_id != 0)
588	{
589		gl.deleteShader(m_vs_id);
590
591		m_vs_id = 0;
592	}
593}
594
595/** Returns test-specific geometry shader source code, built for caller-specified input primitive type.
596 *
597 *  @param gs_input_primitive_type Input primitive type to be used for the process.
598 *
599 *  @return Requested shader source code.
600 **/
601std::string GeometryShaderInvalidArrayedInputVariablesTest::getGSCode(glw::GLenum gs_input_primitive_type) const
602{
603	std::stringstream  code_sstream;
604	const unsigned int valid_array_size = getValidInputVariableArraySize(gs_input_primitive_type);
605
606	code_sstream << "${VERSION}\n"
607					"${GEOMETRY_SHADER_REQUIRE}\n"
608					"\n"
609					"layout ("
610				 << getInputPrimitiveTypeQualifier(gs_input_primitive_type)
611				 << ") in;\n"
612					"layout (points, max_vertices = 1) out;\n"
613					"\n"
614					"in vec4 data["
615				 << (valid_array_size + 1) << "];\n"
616											  "\n"
617											  "void main()\n"
618											  "{\n"
619											  "    gl_Position = data["
620				 << valid_array_size << "];\n"
621										"    EmitVertex();\n"
622										"}\n";
623
624	return code_sstream.str();
625}
626
627/** Returns a string holding the ES SL layout qualifier corresponding to user-specified input primitive type
628 *  expressed as a GLenum value.
629 *
630 *  @param gs_input_primitive_type Geometry Shader's input primitive type, expressed as a GLenum value.
631 *
632 *  @return Requested string
633 */
634std::string GeometryShaderInvalidArrayedInputVariablesTest::getInputPrimitiveTypeQualifier(
635	glw::GLenum gs_input_primitive_type) const
636{
637	std::string result;
638
639	switch (gs_input_primitive_type)
640	{
641	case GL_POINTS:
642		result = "points";
643		break;
644	case GL_LINES:
645		result = "lines";
646		break;
647	case GL_LINES_ADJACENCY:
648		result = "lines_adjacency";
649		break;
650	case GL_TRIANGLES:
651		result = "triangles";
652		break;
653	case GL_TRIANGLES_ADJACENCY:
654		result = "triangles_adjacency";
655		break;
656
657	default:
658	{
659		DE_ASSERT(0);
660	}
661	} /* switch (gs_input_primitive_type) */
662
663	return result;
664}
665
666/** Retrieves a specialized version of the vertex shader to be used for the conformance test. */
667std::string GeometryShaderInvalidArrayedInputVariablesTest::getSpecializedVSCode() const
668{
669	std::string vs_code = "${VERSION}\n"
670						  "\n"
671						  "out vec4 data;\n"
672						  "\n"
673						  "void main()\n"
674						  "{\n"
675						  "    data = vec4(gl_VertexID, 0, 0, 1);\n"
676						  "}\n";
677	const char* vs_code_raw			= vs_code.c_str();
678	std::string specialized_vs_code = specializeShader(1, /* parts */
679													   &vs_code_raw);
680
681	return specialized_vs_code;
682}
683
684/** Returns array size that should be used for input variable declaration in GS, specific to
685 *  to the caller-specified input primitive type.
686 *
687 *  @param gs_input_primitive_type Input primitive type to use for the query.
688 *
689 *  @return Requested value.
690 */
691glw::GLuint GeometryShaderInvalidArrayedInputVariablesTest::getValidInputVariableArraySize(
692	glw::GLenum gs_input_primitive_type) const
693{
694	glw::GLuint result = 0;
695
696	switch (gs_input_primitive_type)
697	{
698	case GL_POINTS:
699		result = 1;
700		break;
701	case GL_LINES:
702		result = 2;
703		break;
704	case GL_LINES_ADJACENCY:
705		result = 4;
706		break;
707	case GL_TRIANGLES:
708		result = 3;
709		break;
710	case GL_TRIANGLES_ADJACENCY:
711		result = 6;
712		break;
713
714	default:
715	{
716		DE_ASSERT(0);
717	}
718	} /* switch (gs_input_primitive_type) */
719
720	return result;
721}
722
723/** Initializes fragment / geometry / vertex shader objects, according to the user-specified GS input primitive type.
724 *
725 *  @param gs_input_primitive_type          Input primitive type, to be used for GS.
726 *  @param out_has_fs_compiled_successfully Deref will be set to false, if FS has failed to compile
727 *                                          successfully. Otherwise, it will be set to true.
728 *  @param out_has_gs_compiled_successfully Deref will be set to false, if GS has failed to compile
729 *                                          successfully. Otherwise, it will be set to true.
730 *  @param out_has_vs_compiled_successfully Deref will be set to false, if VS has failed to compile
731 *                                          successfully. Otherwise, it will be set to true.
732 *
733 */
734void GeometryShaderInvalidArrayedInputVariablesTest::initShaderObjects(glw::GLenum gs_input_primitive_type,
735																	   bool*	   out_has_fs_compiled_successfully,
736																	   bool*	   out_has_gs_compiled_successfully,
737																	   bool*	   out_has_vs_compiled_successfully)
738{
739	const glw::Functions& gl					  = m_context.getRenderContext().getFunctions();
740	std::string			  specialized_fs_code	 = specializeShader(1, &minimal_fs_code);
741	const char*			  specialized_fs_code_raw = specialized_fs_code.c_str();
742	std::string			  gs_code				  = getGSCode(gs_input_primitive_type);
743	const char*			  gs_code_raw			  = gs_code.c_str();
744	std::string			  specialized_gs_code	 = specializeShader(1, &gs_code_raw);
745	const char*			  specialized_gs_code_raw = specialized_gs_code.c_str();
746	std::string			  specialized_vs_code	 = getSpecializedVSCode();
747	const char*			  specialized_vs_code_raw = specialized_vs_code.c_str();
748
749	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
750	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
751	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
752
753	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
754
755	for (unsigned int n_shader_type = 0; n_shader_type < 3; /* fs, gs, vs */
756		 n_shader_type++)
757	{
758		glw::GLint compile_status	 = GL_FALSE;
759		bool*	  out_compile_result = (n_shader_type == 0) ? out_has_fs_compiled_successfully :
760														  (n_shader_type == 1) ? out_has_gs_compiled_successfully :
761																				 out_has_vs_compiled_successfully;
762
763		const char* so_code = (n_shader_type == 0) ?
764								  specialized_fs_code_raw :
765								  (n_shader_type == 1) ? specialized_gs_code_raw : specialized_vs_code_raw;
766
767		glw::GLuint so_id = (n_shader_type == 0) ? m_fs_id : (n_shader_type == 1) ? m_gs_id : m_vs_id;
768
769		gl.shaderSource(so_id, 1,			/* count */
770						&so_code, DE_NULL); /* length */
771
772		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
773
774		gl.compileShader(so_id);
775		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
776
777		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
778		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
779
780		*out_compile_result = (compile_status == GL_TRUE);
781	} /* for (both shader stages) */
782}
783
784/** Executes the test.
785 *
786 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
787 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
788 *  Note the function throws exception should an error occur!
789 **/
790tcu::TestNode::IterateResult GeometryShaderInvalidArrayedInputVariablesTest::iterate()
791{
792	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
793	bool				  result = true;
794
795	/* This test should only run if EXT_geometry_shader is supported. */
796	if (!m_is_geometry_shader_extension_supported)
797	{
798		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
799	}
800
801	/* Iterate over all valid input primitive types */
802	const glw::GLenum input_primitive_types[] = { GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES,
803												  GL_TRIANGLES_ADJACENCY };
804	const unsigned int n_input_primitive_types = sizeof(input_primitive_types) / sizeof(input_primitive_types[0]);
805
806	for (unsigned int n_input_primitive_type = 0; n_input_primitive_type < n_input_primitive_types;
807		 ++n_input_primitive_type)
808	{
809		const glw::GLenum input_primitive_type = input_primitive_types[n_input_primitive_type];
810
811		/* Release shader objects initialized in previous iterations */
812		deinitSOs();
813
814		/* Set up shader objects */
815		bool has_fs_compiled = false;
816		bool has_gs_compiled = false;
817		bool has_vs_compiled = false;
818
819		initShaderObjects(input_primitive_type, &has_fs_compiled, &has_gs_compiled, &has_vs_compiled);
820
821		if (!has_fs_compiled || !has_gs_compiled || !has_vs_compiled)
822		{
823			m_testCtx.getLog()
824				<< tcu::TestLog::Message
825				<< "One of the shaders failed to compile (but shouldn't have). Shaders that failed to compile:"
826				<< ((!has_fs_compiled) ? "FS " : "") << ((!has_gs_compiled) ? "GS " : "")
827				<< ((!has_vs_compiled) ? "VS" : "") << ". Input primitive type: ["
828				<< getInputPrimitiveTypeQualifier(input_primitive_type) << "]" << tcu::TestLog::EndMessage;
829
830			continue;
831		}
832
833		/* Set up a program object */
834		m_po_id = gl.createProgram();
835		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
836
837		gl.attachShader(m_po_id, m_fs_id);
838		gl.attachShader(m_po_id, m_gs_id);
839		gl.attachShader(m_po_id, m_vs_id);
840
841		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed");
842
843		/* Try to link the PO */
844		gl.linkProgram(m_po_id);
845		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
846
847		/* Verify the link status */
848		glw::GLint link_status = GL_FALSE;
849
850		gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
851		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
852
853		if (link_status == GL_TRUE)
854		{
855			m_testCtx.getLog() << tcu::TestLog::Message << "A PO using a malformed GS has linked successfully. "
856							   << "Test input primitive type: " << getInputPrimitiveTypeQualifier(input_primitive_type)
857							   << tcu::TestLog::EndMessage;
858
859			result = false;
860		}
861	} /* for (all input primitive types) */
862
863	if (result)
864	{
865		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
866	}
867	else
868	{
869		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
870	}
871
872	return STOP;
873}
874
875/** Constructor
876 *
877 * @param context       Test context
878 * @param extParams     Not used.
879 * @param name          Test case's name
880 * @param description   Test case's description
881 **/
882GeometryShaderVSGSVariableTypeMismatchTest::GeometryShaderVSGSVariableTypeMismatchTest(Context&				context,
883																					   const ExtParameters& extParams,
884																					   const char*			name,
885																					   const char*			description)
886	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
887{
888}
889
890/** Deinitializes GLES objects created during the test. */
891void GeometryShaderVSGSVariableTypeMismatchTest::deinit()
892{
893	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
894
895	if (m_fs_id != 0)
896	{
897		gl.deleteShader(m_fs_id);
898
899		m_fs_id = 0;
900	}
901
902	if (m_gs_id != 0)
903	{
904		gl.deleteShader(m_gs_id);
905
906		m_gs_id = 0;
907	}
908
909	if (m_po_id != 0)
910	{
911		gl.deleteProgram(m_po_id);
912
913		m_po_id = 0;
914	}
915
916	if (m_vs_id != 0)
917	{
918		gl.deleteShader(m_vs_id);
919
920		m_vs_id = 0;
921	}
922
923	/* Release base class */
924	TestCaseBase::deinit();
925}
926
927/** Executes the test.
928 *
929 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
930 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
931 *  Note the function throws exception should an error occur!
932 **/
933tcu::TestNode::IterateResult GeometryShaderVSGSVariableTypeMismatchTest::iterate()
934{
935	bool has_shader_compilation_failed = true;
936	bool result						   = true;
937
938	/* This test should only run if EXT_geometry_shader is supported. */
939	if (!m_is_geometry_shader_extension_supported)
940	{
941		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
942	}
943
944	/* Create a program object */
945	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
946
947	m_po_id = gl.createProgram();
948
949	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
950
951	/* Create shader objects */
952	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
953	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
954	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
955
956	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
957
958	/* Try to link the test program object */
959	const char* gs_code_raw = "${VERSION}\n"
960							  "${GEOMETRY_SHADER_REQUIRE}\n"
961							  "\n"
962							  "layout (points)                   in;\n"
963							  "layout (points, max_vertices = 1) out;\n"
964							  "\n"
965							  "in vec4 test[];\n"
966							  "\n"
967							  "void main()\n"
968							  "{\n"
969							  "    gl_Position = test[0];\n"
970							  "    EmitVertex();\n"
971							  "}\n";
972
973	const char* vs_code_raw = "${VERSION}\n"
974							  "\n"
975							  "out vec3 test;\n"
976							  "\n"
977							  "void main()\n"
978							  "{\n"
979							  "    test = vec3(gl_VertexID);\n"
980							  "}\n";
981
982	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
983	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
984	std::string gs_code_specialized		= specializeShader(1, &gs_code_raw);
985	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
986	std::string vs_code_specialized		= specializeShader(1, &vs_code_raw);
987	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
988
989	if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,					 /* n_sh1_body_parts */
990								   &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
991								   &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
992								   &fs_code_specialized_raw, &has_shader_compilation_failed))
993	{
994		m_testCtx.getLog() << tcu::TestLog::Message
995						   << "Program object was linked successfully, whereas a failure was expected."
996						   << tcu::TestLog::EndMessage;
997
998		result = false;
999	}
1000
1001	if (has_shader_compilation_failed)
1002	{
1003		m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed unexpectedly."
1004						   << tcu::TestLog::EndMessage;
1005
1006		result = false;
1007	}
1008
1009	if (result)
1010	{
1011		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1012	}
1013	else
1014	{
1015		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1016	}
1017
1018	return STOP;
1019}
1020
1021/** Constructor
1022 *
1023 * @param context       Test context
1024 * @param extParams     Not used.
1025 * @param name          Test case's name
1026 * @param description   Test case's description
1027 **/
1028GeometryShaderVSGSVariableQualifierMismatchTest::GeometryShaderVSGSVariableQualifierMismatchTest(
1029	Context& context, const ExtParameters& extParams, const char* name, const char* description)
1030	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
1031{
1032}
1033
1034/** Deinitializes GLES objects created during the test. */
1035void GeometryShaderVSGSVariableQualifierMismatchTest::deinit()
1036{
1037	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1038
1039	if (m_fs_id != 0)
1040	{
1041		gl.deleteShader(m_fs_id);
1042
1043		m_fs_id = 0;
1044	}
1045
1046	if (m_gs_id != 0)
1047	{
1048		gl.deleteShader(m_gs_id);
1049
1050		m_gs_id = 0;
1051	}
1052
1053	if (m_po_id != 0)
1054	{
1055		gl.deleteProgram(m_po_id);
1056
1057		m_po_id = 0;
1058	}
1059
1060	if (m_vs_id != 0)
1061	{
1062		gl.deleteShader(m_vs_id);
1063
1064		m_vs_id = 0;
1065	}
1066
1067	/* Release base class */
1068	TestCaseBase::deinit();
1069}
1070
1071/** Executes the test.
1072 *
1073 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1074 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1075 *  Note the function throws exception should an error occur!
1076 **/
1077tcu::TestNode::IterateResult GeometryShaderVSGSVariableQualifierMismatchTest::iterate()
1078{
1079	bool has_shader_compilation_failed = true;
1080	bool result						   = true;
1081
1082	/* This test should only run if EXT_geometry_shader is supported. */
1083	if (!m_is_geometry_shader_extension_supported)
1084	{
1085		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1086	}
1087
1088	/* Create a program object */
1089	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1090
1091	m_po_id = gl.createProgram();
1092
1093	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1094
1095	/* Create shader objects */
1096	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1097	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1098	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1099
1100	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1101
1102	/* Try to link the test program object */
1103	const char* gs_code_raw = "${VERSION}\n"
1104							  "${GEOMETRY_SHADER_REQUIRE}\n"
1105							  "\n"
1106							  "layout (points)                   in;\n"
1107							  "layout (points, max_vertices = 1) out;\n"
1108							  "\n"
1109							  "in flat vec4 test[];\n"
1110							  "\n"
1111							  "void main()\n"
1112							  "{\n"
1113							  "    gl_Position = test[0];\n"
1114							  "    EmitVertex();\n"
1115							  "}\n";
1116
1117	const char* vs_code_raw = "${VERSION}\n"
1118							  "${GEOMETRY_SHADER_REQUIRE}\n"
1119							  "\n"
1120							  "out vec4 test;\n"
1121							  "\n"
1122							  "void main()\n"
1123							  "{\n"
1124							  "    test = vec4(gl_VertexID);\n"
1125							  "}\n";
1126
1127	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
1128	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
1129	std::string gs_code_specialized		= specializeShader(1, &gs_code_raw);
1130	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
1131	std::string vs_code_specialized		= specializeShader(1, &vs_code_raw);
1132	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
1133
1134	bool buildSuccess = TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,					 /* n_sh1_body_parts */
1135												   &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1136												   &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1137												   &fs_code_specialized_raw, &has_shader_compilation_failed);
1138
1139	if (!buildSuccess && glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)))
1140	{
1141		m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed. Success was expected."
1142						   << tcu::TestLog::EndMessage;
1143
1144		result = false;
1145	}
1146
1147	if (buildSuccess && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)))
1148	{
1149		m_testCtx.getLog() << tcu::TestLog::Message
1150						   << "Program object was linked successfully, whereas a failure was expected."
1151						   << tcu::TestLog::EndMessage;
1152		result = false;
1153	}
1154
1155	if (has_shader_compilation_failed)
1156	{
1157		m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed unexpectedly."
1158						   << tcu::TestLog::EndMessage;
1159
1160		result = false;
1161	}
1162
1163	if (result)
1164	{
1165		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1166	}
1167	else
1168	{
1169		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1170	}
1171
1172	return STOP;
1173}
1174
1175/** Constructor
1176 *
1177 * @param context       Test context
1178 * @param extParams     Not used.
1179 * @param name          Test case's name
1180 * @param description   Test case's description
1181 **/
1182GeometryShaderVSGSArrayedVariableSizeMismatchTest::GeometryShaderVSGSArrayedVariableSizeMismatchTest(
1183	Context& context, const ExtParameters& extParams, const char* name, const char* description)
1184	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
1185{
1186}
1187
1188/** Deinitializes GLES objects created during the test. */
1189void GeometryShaderVSGSArrayedVariableSizeMismatchTest::deinit()
1190{
1191	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1192
1193	if (m_fs_id != 0)
1194	{
1195		gl.deleteShader(m_fs_id);
1196
1197		m_fs_id = 0;
1198	}
1199
1200	if (m_gs_id != 0)
1201	{
1202		gl.deleteShader(m_gs_id);
1203
1204		m_gs_id = 0;
1205	}
1206
1207	if (m_po_id != 0)
1208	{
1209		gl.deleteProgram(m_po_id);
1210
1211		m_po_id = 0;
1212	}
1213
1214	if (m_vs_id != 0)
1215	{
1216		gl.deleteShader(m_vs_id);
1217
1218		m_vs_id = 0;
1219	}
1220
1221	/* Release base class */
1222	TestCaseBase::deinit();
1223}
1224
1225/** Executes the test.
1226 *
1227 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1228 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1229 *  Note the function throws exception should an error occur!
1230 **/
1231tcu::TestNode::IterateResult GeometryShaderVSGSArrayedVariableSizeMismatchTest::iterate()
1232{
1233	bool has_shader_compilation_failed = true;
1234	bool result						   = true;
1235
1236	/* This test should only run if EXT_geometry_shader is supported. */
1237	if (!m_is_geometry_shader_extension_supported)
1238	{
1239		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1240	}
1241
1242	/* Create a program object */
1243	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1244
1245	m_po_id = gl.createProgram();
1246
1247	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1248
1249	/* Create shader objects */
1250	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1251	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1252	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1253
1254	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1255
1256	/* Try to link the test program object */
1257	const char* gs_code_raw = "${VERSION}\n"
1258							  "${GEOMETRY_SHADER_REQUIRE}\n"
1259							  "\n"
1260							  "layout (points)                   in;\n"
1261							  "layout (points, max_vertices = 1) out;\n"
1262							  "\n"
1263							  "in vec4 Color1[];\n"
1264							  "in vec4 Color2[2];\n"
1265							  "in vec4 Color3[3];\n"
1266							  "\n"
1267							  "void main()\n"
1268							  "{\n"
1269							  "    gl_Position = Color1[0] + Color2[1] + Color3[2];\n"
1270							  "    EmitVertex();\n"
1271							  "}\n";
1272
1273	const char* vs_code_raw = "${VERSION}\n"
1274							  "${GEOMETRY_SHADER_REQUIRE}\n"
1275							  "\n"
1276							  "out vec4 Color1;\n"
1277							  "out vec4 Color2;\n"
1278							  "out vec4 Color3;\n"
1279							  "\n"
1280							  "void main()\n"
1281							  "{\n"
1282							  "    Color1 = vec4(gl_VertexID, 0.0,         0.0,         0.0);\n"
1283							  "    Color2 = vec4(0.0,         gl_VertexID, 0.0,         0.0);\n"
1284							  "    Color3 = vec4(0.0,         0.0,         gl_VertexID, 0.0);\n"
1285							  "}\n";
1286
1287	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
1288	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
1289	std::string gs_code_specialized		= specializeShader(1, &gs_code_raw);
1290	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
1291	std::string vs_code_specialized		= specializeShader(1, &vs_code_raw);
1292	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
1293
1294	if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,					 /* n_sh1_body_parts */
1295								   &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1296								   &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1297								   &fs_code_specialized_raw, &has_shader_compilation_failed))
1298	{
1299		m_testCtx.getLog() << tcu::TestLog::Message
1300						   << "Program object was linked successfully, whereas a failure was expected."
1301						   << tcu::TestLog::EndMessage;
1302
1303		result = false;
1304	}
1305
1306	if (result)
1307	{
1308		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1309	}
1310	else
1311	{
1312		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1313	}
1314
1315	return STOP;
1316}
1317
1318/** Constructor
1319 *
1320 * @param context       Test context
1321 * @param extParams     Not used.
1322 * @param name          Test case's name
1323 * @param description   Test case's description
1324 **/
1325GeometryShaderFragCoordRedeclarationTest::GeometryShaderFragCoordRedeclarationTest(Context&				context,
1326																				   const ExtParameters& extParams,
1327																				   const char*			name,
1328																				   const char*			description)
1329	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
1330{
1331}
1332
1333/** Deinitializes GLES objects created during the test. */
1334void GeometryShaderFragCoordRedeclarationTest::deinit()
1335{
1336	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1337
1338	if (m_fs_id != 0)
1339	{
1340		gl.deleteShader(m_fs_id);
1341
1342		m_fs_id = 0;
1343	}
1344
1345	if (m_gs_id != 0)
1346	{
1347		gl.deleteShader(m_gs_id);
1348
1349		m_gs_id = 0;
1350	}
1351
1352	if (m_po_id != 0)
1353	{
1354		gl.deleteProgram(m_po_id);
1355
1356		m_po_id = 0;
1357	}
1358
1359	if (m_vs_id != 0)
1360	{
1361		gl.deleteShader(m_vs_id);
1362
1363		m_vs_id = 0;
1364	}
1365
1366	/* Release base class */
1367	TestCaseBase::deinit();
1368}
1369
1370/** Executes the test.
1371 *
1372 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1373 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1374 *  Note the function throws exception should an error occur!
1375 **/
1376tcu::TestNode::IterateResult GeometryShaderFragCoordRedeclarationTest::iterate()
1377{
1378	bool has_shader_compilation_failed = true;
1379	bool result						   = true;
1380
1381	/* This test should only run if EXT_geometry_shader is supported. */
1382	if (!m_is_geometry_shader_extension_supported)
1383	{
1384		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1385	}
1386
1387	/* Create a program object */
1388	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1389
1390	m_po_id = gl.createProgram();
1391
1392	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1393
1394	/* Create shader objects */
1395	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1396	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1397	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1398
1399	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1400
1401	/* Try to link the test program object */
1402	const char* gs_code_raw = "${VERSION}\n"
1403							  "${GEOMETRY_SHADER_REQUIRE}\n"
1404							  "\n"
1405							  "layout (points)                   in;\n"
1406							  "layout (points, max_vertices = 1) out;\n"
1407							  "\n"
1408							  "in vec4 gl_FragCoord;\n"
1409							  "\n"
1410							  "void main()\n"
1411							  "{\n"
1412							  "    gl_Position = gl_FragCoord;\n"
1413							  "    EmitVertex();\n"
1414							  "}\n";
1415
1416	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
1417	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
1418	std::string gs_code_specialized		= specializeShader(1, &gs_code_raw);
1419	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
1420	std::string vs_code_specialized		= specializeShader(1, &minimal_vs_code);
1421	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
1422
1423	if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,					 /* n_sh1_body_parts */
1424								   &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1425								   &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1426								   &fs_code_specialized_raw, &has_shader_compilation_failed))
1427	{
1428		m_testCtx.getLog() << tcu::TestLog::Message
1429						   << "Program object was linked successfully, whereas a failure was expected."
1430						   << tcu::TestLog::EndMessage;
1431
1432		result = false;
1433	}
1434
1435	if (result)
1436	{
1437		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1438	}
1439	else
1440	{
1441		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1442	}
1443
1444	return STOP;
1445}
1446
1447/** Constructor
1448 *
1449 * @param context       Test context
1450 * @param extParams     Not used.
1451 * @param name          Test case's name
1452 * @param description   Test case's description
1453 **/
1454GeometryShaderLocationAliasingTest::GeometryShaderLocationAliasingTest(Context& context, const ExtParameters& extParams,
1455																	   const char* name, const char* description)
1456	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
1457{
1458}
1459
1460/** Deinitializes GLES objects created during the test. */
1461void GeometryShaderLocationAliasingTest::deinit()
1462{
1463	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1464
1465	if (m_fs_id != 0)
1466	{
1467		gl.deleteShader(m_fs_id);
1468
1469		m_fs_id = 0;
1470	}
1471
1472	if (m_gs_id != 0)
1473	{
1474		gl.deleteShader(m_gs_id);
1475
1476		m_gs_id = 0;
1477	}
1478
1479	if (m_po_id != 0)
1480	{
1481		gl.deleteProgram(m_po_id);
1482
1483		m_po_id = 0;
1484	}
1485
1486	if (m_vs_id != 0)
1487	{
1488		gl.deleteShader(m_vs_id);
1489
1490		m_vs_id = 0;
1491	}
1492
1493	/* Release base class */
1494	TestCaseBase::deinit();
1495}
1496
1497/** Executes the test.
1498 *
1499 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1500 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1501 *  Note the function throws exception should an error occur!
1502 **/
1503tcu::TestNode::IterateResult GeometryShaderLocationAliasingTest::iterate()
1504{
1505	bool has_program_link_succeeded	= true;
1506	bool result						   = true;
1507
1508	/* This test should only run if EXT_geometry_shader is supported. */
1509	if (!m_is_geometry_shader_extension_supported)
1510	{
1511		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1512	}
1513
1514	/* Create a program object */
1515	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1516
1517	m_po_id = gl.createProgram();
1518
1519	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1520
1521	/* Create shader objects */
1522	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1523	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1524	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1525
1526	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1527
1528	/* Try to link the test program object */
1529	const char* gs_code_raw = "${VERSION}\n"
1530							  "${GEOMETRY_SHADER_REQUIRE}\n"
1531							  "\n"
1532							  "layout (points)                   in;\n"
1533							  "layout (points, max_vertices = 1) out;\n"
1534							  "\n"
1535							  "layout (location = 2) out vec4 test;\n"
1536							  "layout (location = 2) out vec4 test2;\n"
1537							  "\n"
1538							  "void main()\n"
1539							  "{\n"
1540							  "    gl_Position = gl_in[0].gl_Position;\n"
1541							  "    test = vec4(1.0, 0.0, 0.0, 1.0);\n"
1542							  "    test2 = vec4(1.0, 0.0, 0.0, 1.0);\n"
1543							  "    EmitVertex();\n"
1544							  "}\n";
1545
1546	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
1547	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
1548	std::string gs_code_specialized		= specializeShader(1, &gs_code_raw);
1549	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
1550	std::string vs_code_specialized		= specializeShader(1, &minimal_vs_code);
1551	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
1552
1553	has_program_link_succeeded = TestCaseBase::buildProgram(
1554		m_po_id, m_gs_id, 1 /* n_sh1_body_parts */, &gs_code_specialized_raw, m_vs_id, 1 /* n_sh2_body_parts */,
1555		&vs_code_specialized_raw, m_fs_id, 1 /* n_sh3_body_parts */, &fs_code_specialized_raw, NULL);
1556	if (has_program_link_succeeded)
1557	{
1558		m_testCtx.getLog() << tcu::TestLog::Message
1559						   << "Program object was compiled and linked successfully, whereas a failure was expected."
1560						   << tcu::TestLog::EndMessage;
1561
1562		result = false;
1563	}
1564
1565	if (result)
1566	{
1567		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1568	}
1569	else
1570	{
1571		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1572	}
1573
1574	return STOP;
1575}
1576
1577/** Constructor
1578 *
1579 * @param context       Test context
1580 * @param extParams     Not used.
1581 * @param name          Test case's name
1582 * @param description   Test case's description
1583 **/
1584GeometryShaderMoreACsInGSThanSupportedTest::GeometryShaderMoreACsInGSThanSupportedTest(Context&				context,
1585																					   const ExtParameters& extParams,
1586																					   const char*			name,
1587																					   const char*			description)
1588	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
1589{
1590}
1591
1592/** Deinitializes GLES objects created during the test. */
1593void GeometryShaderMoreACsInGSThanSupportedTest::deinit()
1594{
1595	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1596
1597	if (m_fs_id != 0)
1598	{
1599		gl.deleteShader(m_fs_id);
1600
1601		m_fs_id = 0;
1602	}
1603
1604	if (m_gs_id != 0)
1605	{
1606		gl.deleteShader(m_gs_id);
1607
1608		m_gs_id = 0;
1609	}
1610
1611	if (m_po_id != 0)
1612	{
1613		gl.deleteProgram(m_po_id);
1614
1615		m_po_id = 0;
1616	}
1617
1618	if (m_vs_id != 0)
1619	{
1620		gl.deleteShader(m_vs_id);
1621
1622		m_vs_id = 0;
1623	}
1624
1625	/* Release base class */
1626	TestCaseBase::deinit();
1627}
1628
1629/* Retrieves test-specific geometry shader source code.
1630 *
1631 * @return Requested string.
1632 */
1633std::string GeometryShaderMoreACsInGSThanSupportedTest::getGSCode()
1634{
1635	std::stringstream	 code_sstream;
1636	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
1637	glw::GLint			  gl_max_ACs_value = 0;
1638
1639	/* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname value */
1640	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTERS, &gl_max_ACs_value);
1641	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname");
1642
1643	/* Form the GS */
1644	code_sstream << "${VERSION}\n"
1645					"${GEOMETRY_SHADER_REQUIRE}\n"
1646					"\n"
1647					"layout (points)                   in;\n"
1648					"layout (points, max_vertices = 1) out;\n"
1649					"\n";
1650
1651	for (glw::GLint n_ac = 0; n_ac < (gl_max_ACs_value + 1); ++n_ac)
1652	{
1653		code_sstream << "layout(binding = 0) uniform atomic_uint counter" << n_ac << ";\n";
1654	}
1655
1656	code_sstream << "\n"
1657					"void main()\n"
1658					"{\n";
1659
1660	for (glw::GLint n_ac = 0; n_ac < (gl_max_ACs_value + 1); ++n_ac)
1661	{
1662		code_sstream << "    if ((gl_PrimitiveIDIn % " << (n_ac + 1) << ") == 0) atomicCounterIncrement(counter" << n_ac
1663					 << ");\n";
1664	}
1665
1666	code_sstream << "\n"
1667					"    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1668					"    EmitVertex();\n"
1669					"}\n";
1670
1671	/* Form a specialized version of the GS source code */
1672	std::string gs_code				= code_sstream.str();
1673	const char* gs_code_raw			= gs_code.c_str();
1674	std::string gs_code_specialized = specializeShader(1, /* parts */
1675													   &gs_code_raw);
1676
1677	return gs_code_specialized;
1678}
1679
1680/** Executes the test.
1681 *
1682 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1683 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1684 *  Note the function throws exception should an error occur!
1685 **/
1686tcu::TestNode::IterateResult GeometryShaderMoreACsInGSThanSupportedTest::iterate()
1687{
1688	bool has_shader_compilation_failed = true;
1689	bool result						   = true;
1690
1691	/* This test should only run if EXT_geometry_shader is supported. */
1692	if (!m_is_geometry_shader_extension_supported)
1693	{
1694		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1695	}
1696
1697	/* Create a program object */
1698	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1699
1700	m_po_id = gl.createProgram();
1701
1702	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1703
1704	/* Create shader objects */
1705	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1706	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1707	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1708
1709	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1710
1711	/* Try to link the test program object */
1712	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
1713	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
1714	std::string gs_code_specialized		= getGSCode();
1715	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
1716	std::string vs_code_specialized		= specializeShader(1, &minimal_vs_code);
1717	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
1718
1719	if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,					 /* n_sh1_body_parts */
1720								   &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1721								   &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1722								   &fs_code_specialized_raw, &has_shader_compilation_failed))
1723	{
1724		m_testCtx.getLog() << tcu::TestLog::Message
1725						   << "Program object was linked successfully, whereas a failure was expected."
1726						   << tcu::TestLog::EndMessage;
1727
1728		result = false;
1729	}
1730
1731	if (result)
1732	{
1733		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1734	}
1735	else
1736	{
1737		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1738	}
1739
1740	return STOP;
1741}
1742
1743/** Constructor
1744 *
1745 * @param context       Test context
1746 * @param extParams     Not used.
1747 * @param name          Test case's name
1748 * @param description   Test case's description
1749 **/
1750GeometryShaderMoreACBsInGSThanSupportedTest::GeometryShaderMoreACBsInGSThanSupportedTest(Context&			  context,
1751																						 const ExtParameters& extParams,
1752																						 const char*		  name,
1753																						 const char* description)
1754	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
1755{
1756}
1757
1758/** Deinitializes GLES objects created during the test. */
1759void GeometryShaderMoreACBsInGSThanSupportedTest::deinit()
1760{
1761	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1762
1763	if (m_fs_id != 0)
1764	{
1765		gl.deleteShader(m_fs_id);
1766
1767		m_fs_id = 0;
1768	}
1769
1770	if (m_gs_id != 0)
1771	{
1772		gl.deleteShader(m_gs_id);
1773
1774		m_gs_id = 0;
1775	}
1776
1777	if (m_po_id != 0)
1778	{
1779		gl.deleteProgram(m_po_id);
1780
1781		m_po_id = 0;
1782	}
1783
1784	if (m_vs_id != 0)
1785	{
1786		gl.deleteShader(m_vs_id);
1787
1788		m_vs_id = 0;
1789	}
1790
1791	/* Release base class */
1792	TestCaseBase::deinit();
1793}
1794
1795/* Retrieves test-specific geometry shader source code.
1796 *
1797 * @return Requested string.
1798 */
1799std::string GeometryShaderMoreACBsInGSThanSupportedTest::getGSCode()
1800{
1801	std::stringstream	 code_sstream;
1802	const glw::Functions& gl				= m_context.getRenderContext().getFunctions();
1803	glw::GLint			  gl_max_ACBs_value = 0;
1804
1805	/* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname value */
1806	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, &gl_max_ACBs_value);
1807	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname");
1808
1809	/* Form the GS */
1810	code_sstream << "${VERSION}\n"
1811					"${GEOMETRY_SHADER_REQUIRE}\n"
1812					"\n"
1813					"layout (points)                   in;\n"
1814					"layout (points, max_vertices = 1) out;\n"
1815					"\n";
1816
1817	for (glw::GLint n_acb = 0; n_acb < (gl_max_ACBs_value + 1); ++n_acb)
1818	{
1819		code_sstream << "layout(binding = " << n_acb << ") uniform atomic_uint counter" << n_acb << ";\n";
1820	}
1821
1822	code_sstream << "\n"
1823					"void main()\n"
1824					"{\n";
1825
1826	for (glw::GLint n_acb = 0; n_acb < (gl_max_ACBs_value + 1); ++n_acb)
1827	{
1828		code_sstream << "    if ((gl_PrimitiveIDIn % " << (n_acb + 1) << ") == 0) atomicCounterIncrement(counter"
1829					 << n_acb << ");\n";
1830	}
1831
1832	code_sstream << "\n"
1833					"    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
1834					"    EmitVertex();\n"
1835					"}\n";
1836
1837	/* Form a specialized version of the GS source code */
1838	std::string gs_code				= code_sstream.str();
1839	const char* gs_code_raw			= gs_code.c_str();
1840	std::string gs_code_specialized = specializeShader(1, /* parts */
1841													   &gs_code_raw);
1842
1843	return gs_code_specialized;
1844}
1845
1846/** Executes the test.
1847 *
1848 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1849 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1850 *  Note the function throws exception should an error occur!
1851 **/
1852tcu::TestNode::IterateResult GeometryShaderMoreACBsInGSThanSupportedTest::iterate()
1853{
1854	bool has_shader_compilation_failed = true;
1855	bool result						   = true;
1856
1857	/* This test should only run if EXT_geometry_shader is supported. */
1858	if (!m_is_geometry_shader_extension_supported)
1859	{
1860		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1861	}
1862
1863	/* Create a program object */
1864	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1865
1866	m_po_id = gl.createProgram();
1867
1868	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1869
1870	/* Create shader objects */
1871	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1872	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1873	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1874
1875	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1876
1877	/* Try to link the test program object */
1878	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
1879	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
1880	std::string gs_code_specialized		= getGSCode();
1881	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
1882	std::string vs_code_specialized		= specializeShader(1, &minimal_vs_code);
1883	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
1884
1885	if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,					 /* n_sh1_body_parts */
1886								   &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1887								   &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1888								   &fs_code_specialized_raw, &has_shader_compilation_failed))
1889	{
1890		m_testCtx.getLog() << tcu::TestLog::Message
1891						   << "Program object was linked successfully, whereas a failure was expected."
1892						   << tcu::TestLog::EndMessage;
1893
1894		result = false;
1895	}
1896
1897	if (result)
1898	{
1899		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1900	}
1901	else
1902	{
1903		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1904	}
1905
1906	return STOP;
1907}
1908
1909/** Constructor
1910 *
1911 * @param context       Test context
1912 * @param extParams     Not used.
1913 * @param name          Test case's name
1914 * @param description   Test case's description
1915 **/
1916GeometryShaderCompilationFailTest::GeometryShaderCompilationFailTest(Context& context, const ExtParameters& extParams,
1917																	 const char* name, const char* description)
1918	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
1919{
1920}
1921
1922/** Deinitializes GLES objects created during the test. */
1923void GeometryShaderCompilationFailTest::deinit()
1924{
1925	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1926
1927	if (m_fs_id != 0)
1928	{
1929		gl.deleteShader(m_fs_id);
1930
1931		m_fs_id = 0;
1932	}
1933
1934	if (m_gs_id != 0)
1935	{
1936		gl.deleteShader(m_gs_id);
1937
1938		m_gs_id = 0;
1939	}
1940
1941	if (m_po_id != 0)
1942	{
1943		gl.deleteProgram(m_po_id);
1944
1945		m_po_id = 0;
1946	}
1947
1948	if (m_vs_id != 0)
1949	{
1950		gl.deleteShader(m_vs_id);
1951
1952		m_vs_id = 0;
1953	}
1954
1955	/* Release base class */
1956	TestCaseBase::deinit();
1957}
1958
1959/** Executes the test.
1960 *
1961 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1962 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1963 *  Note the function throws exception should an error occur!
1964 **/
1965tcu::TestNode::IterateResult GeometryShaderCompilationFailTest::iterate()
1966{
1967	/* Define Vertex Shader's code for the purpose of this test. */
1968	const char* gs_code = "${VERSION}\n"
1969						  "${GEOMETRY_SHADER_REQUIRE}\n"
1970						  "\n"
1971						  "layout (points)                   in;\n"
1972						  "layout (points, max_vertices = 1) out;\n"
1973						  "\n"
1974						  "void main()\n"
1975						  "{\n"
1976						  "    gl_Position = gl_in[0].gl_Position;\n"
1977						  "    mitVertex();\n"
1978						  "}\n";
1979
1980	bool has_shader_compilation_failed = true;
1981	bool result						   = true;
1982
1983	/* This test should only run if EXT_geometry_shader is supported. */
1984	if (!m_is_geometry_shader_extension_supported)
1985	{
1986		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1987	}
1988
1989	/* Create a program object */
1990	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1991
1992	m_po_id = gl.createProgram();
1993
1994	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1995
1996	/* Create shader objects */
1997	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1998	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1999	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2000
2001	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2002
2003	/* Try to link the test program object */
2004	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
2005	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
2006
2007	std::string gs_code_specialized		= specializeShader(1, &gs_code);
2008	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
2009
2010	std::string vs_code_specialized		= specializeShader(1, &minimal_vs_code);
2011	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
2012
2013	if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,					 /* n_sh1_body_parts */
2014								   &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2015								   &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2016								   &fs_code_specialized_raw, &has_shader_compilation_failed))
2017	{
2018		m_testCtx.getLog() << tcu::TestLog::Message
2019						   << "Program object was linked successfully, whereas a failure was expected."
2020						   << tcu::TestLog::EndMessage;
2021
2022		result = false;
2023	}
2024
2025	if (!has_shader_compilation_failed)
2026	{
2027		m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation succeeded, whereas a failure was expected."
2028						   << tcu::TestLog::EndMessage;
2029
2030		result = false;
2031	}
2032
2033	if (result)
2034	{
2035		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2036	}
2037	else
2038	{
2039		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2040	}
2041
2042	return STOP;
2043}
2044
2045/** Constructor
2046 *
2047 * @param context       Test context
2048 * @param extParams     Not used.
2049 * @param name          Test case's name
2050 * @param description   Test case's description
2051 **/
2052GeometryShaderMoreInputVerticesThanAvailableTest::GeometryShaderMoreInputVerticesThanAvailableTest(
2053	Context& context, const ExtParameters& extParams, const char* name, const char* description)
2054	: TestCaseBase(context, extParams, name, description)
2055	, m_fs_id(0)
2056	, m_gs_ids(NULL)
2057	, m_number_of_gs(5 /*taken from test spec*/)
2058	, m_po_ids(NULL)
2059	, m_vs_id(0)
2060	, m_vao_id(0)
2061{
2062}
2063
2064/** Deinitializes GLES objects created during the test. */
2065void GeometryShaderMoreInputVerticesThanAvailableTest::deinit()
2066{
2067	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2068
2069	if (m_fs_id != 0)
2070	{
2071		gl.deleteShader(m_fs_id);
2072		m_fs_id = 0;
2073	}
2074
2075	if (m_gs_ids != 0)
2076	{
2077		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2078		{
2079			gl.deleteShader(m_gs_ids[i]);
2080			m_gs_ids[i] = 0;
2081		}
2082
2083		delete[] m_gs_ids;
2084		m_gs_ids = NULL;
2085	}
2086
2087	if (m_po_ids != 0)
2088	{
2089		for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2090		{
2091			gl.deleteProgram(m_po_ids[i]);
2092			m_po_ids[i] = 0;
2093		}
2094
2095		delete[] m_po_ids;
2096		m_po_ids = NULL;
2097	}
2098
2099	if (m_vs_id != 0)
2100	{
2101		gl.deleteShader(m_vs_id);
2102		m_vs_id = 0;
2103	}
2104
2105	if (m_vao_id != 0)
2106	{
2107		gl.deleteVertexArrays(1, &m_vao_id);
2108		m_vao_id = 0;
2109	}
2110
2111	/* Release base class */
2112	TestCaseBase::deinit();
2113}
2114
2115/** Executes the test.
2116 *
2117 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2118 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2119 *  Note the function throws exception should an error occur!
2120 **/
2121tcu::TestNode::IterateResult GeometryShaderMoreInputVerticesThanAvailableTest::iterate()
2122{
2123	/* Define 5 Geometry Shaders for purpose of this test. */
2124	const char* gs_code_points = "${VERSION}\n"
2125								 "${GEOMETRY_SHADER_REQUIRE}\n"
2126								 "\n"
2127								 "layout (points)                   in;\n"
2128								 "layout (points, max_vertices = 1) out;\n"
2129								 "\n"
2130								 "void main()\n"
2131								 "{\n"
2132								 "    gl_Position = gl_in[1].gl_Position;\n"
2133								 "    EmitVertex();\n"
2134								 "}\n";
2135
2136	const char* gs_code_lines = "${VERSION}\n"
2137								"${GEOMETRY_SHADER_REQUIRE}\n"
2138								"\n"
2139								"layout (lines)                    in;\n"
2140								"layout (points, max_vertices = 1) out;\n"
2141								"\n"
2142								"void main()\n"
2143								"{\n"
2144								"    gl_Position = gl_in[2].gl_Position;\n"
2145								"    EmitVertex();\n"
2146								"}\n";
2147
2148	const char* gs_code_lines_adjacency = "${VERSION}\n"
2149										  "${GEOMETRY_SHADER_REQUIRE}\n"
2150										  "\n"
2151										  "layout (lines_adjacency)          in;\n"
2152										  "layout (points, max_vertices = 1) out;\n"
2153										  "\n"
2154										  "void main()\n"
2155										  "{\n"
2156										  "    gl_Position = gl_in[4].gl_Position;\n"
2157										  "    EmitVertex();\n"
2158										  "}\n";
2159
2160	const char* gs_code_triangles = "${VERSION}\n"
2161									"${GEOMETRY_SHADER_REQUIRE}\n"
2162									"\n"
2163									"layout (triangles)                in;\n"
2164									"layout (points, max_vertices = 1) out;\n"
2165									"\n"
2166									"void main()\n"
2167									"{\n"
2168									"    gl_Position = gl_in[3].gl_Position;\n"
2169									"    EmitVertex();\n"
2170									"}\n";
2171
2172	const char* gs_code_triangles_adjacency = "${VERSION}\n"
2173											  "${GEOMETRY_SHADER_REQUIRE}\n"
2174											  "\n"
2175											  "layout (triangles_adjacency)      in;\n"
2176											  "layout (points, max_vertices = 1) out;\n"
2177											  "\n"
2178											  "void main()\n"
2179											  "{\n"
2180											  "    gl_Position = gl_in[6].gl_Position;\n"
2181											  "    EmitVertex();\n"
2182											  "}\n";
2183
2184	bool has_shader_compilation_failed = true;
2185	bool result						   = true;
2186
2187	m_gs_ids = new glw::GLuint[m_number_of_gs];
2188	m_po_ids = new glw::GLuint[m_number_of_gs];
2189
2190	/* This test should only run if EXT_geometry_shader is supported. */
2191	if (!m_is_geometry_shader_extension_supported)
2192	{
2193		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2194	}
2195
2196	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2197
2198	/* Create program objects & geometry shader objects. */
2199	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2200	{
2201		m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
2202		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2203
2204		m_po_ids[i] = gl.createProgram();
2205		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2206	}
2207
2208	/* Create shader object. */
2209	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2210	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2211	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2212
2213	/* Try to link the test program object */
2214	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
2215	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
2216
2217	std::string gs_codes_specialized[] = { specializeShader(1, &gs_code_points), specializeShader(1, &gs_code_lines),
2218										   specializeShader(1, &gs_code_lines_adjacency),
2219										   specializeShader(1, &gs_code_triangles),
2220										   specializeShader(1, &gs_code_triangles_adjacency) };
2221
2222	const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str(),
2223											   gs_codes_specialized[2].c_str(), gs_codes_specialized[3].c_str(),
2224											   gs_codes_specialized[4].c_str() };
2225
2226	std::string vs_code_specialized		= specializeShader(1, &minimal_vs_code);
2227	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
2228
2229	for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2230	{
2231		if (TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1,					 /* n_sh1_body_parts */
2232									   &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
2233									   &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
2234									   &vs_code_specialized_raw, &has_shader_compilation_failed))
2235		{
2236			m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking successful for i = "
2237							   << "[" << i << "], whereas a failure was expected." << tcu::TestLog::EndMessage;
2238
2239			result = false;
2240			break;
2241		}
2242	}
2243
2244	if (result)
2245	{
2246		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2247	}
2248	else
2249	{
2250		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2251	}
2252
2253	return STOP;
2254}
2255
2256/** Constructor
2257 *
2258 * @param context       Test context
2259 * @param extParams     Not used.
2260 * @param name          Test case's name
2261 * @param description   Test case's description
2262 **/
2263GeometryShaderTransformFeedbackVertexAndGeometryShaderCaptureTest::
2264	GeometryShaderTransformFeedbackVertexAndGeometryShaderCaptureTest(Context& context, const ExtParameters& extParams,
2265																	  const char* name, const char* description)
2266	: TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0)
2267{
2268}
2269
2270/** Deinitializes GLES objects created during the test. */
2271void GeometryShaderTransformFeedbackVertexAndGeometryShaderCaptureTest::deinit()
2272{
2273	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2274
2275	if (m_fs_id != 0)
2276	{
2277		gl.deleteShader(m_fs_id);
2278		m_fs_id = 0;
2279	}
2280
2281	if (m_gs_id != 0)
2282	{
2283		gl.deleteShader(m_gs_id);
2284		m_gs_id = 0;
2285	}
2286
2287	if (m_po_id != 0)
2288	{
2289		gl.deleteProgram(m_po_id);
2290		m_po_id = 0;
2291	}
2292
2293	if (m_vs_id != 0)
2294	{
2295		gl.deleteShader(m_vs_id);
2296		m_vs_id = 0;
2297	}
2298
2299	/* Release base class */
2300	TestCaseBase::deinit();
2301}
2302
2303/** Executes the test.
2304 *
2305 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2306 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2307 *  Note the function throws exception should an error occur!
2308 **/
2309tcu::TestNode::IterateResult GeometryShaderTransformFeedbackVertexAndGeometryShaderCaptureTest::iterate()
2310{
2311	/* Define Geometry Shader for purpose of this test. */
2312	const char* gs_code =
2313		"${VERSION}\n"
2314		"${GEOMETRY_SHADER_REQUIRE}\n"
2315		"\n"
2316		"layout (points)                   in;\n"
2317		"layout (points, max_vertices = 1) out;\n"
2318		"\n"
2319		"in int vertexID;\n"
2320		"out vec4 out_gs_1;\n"
2321		"\n"
2322		"void main()\n"
2323		"{\n"
2324		"    out_gs_1 = vec4(vertexID[0] * 2, vertexID[0] * 2 + 1, vertexID[0] * 2 + 2, vertexID[0] * 2 + 3);\n"
2325		"    gl_Position = vec4(0, 0, 0, 1);\n"
2326		"    EmitVertex();\n"
2327		"}\n";
2328
2329	/* Define Vertex Shader for purpose of this test. */
2330	const char* vs_code = "${VERSION}\n"
2331						  "\n"
2332						  "flat out ivec4 out_vs_1;\n"
2333						  "flat out int vertexID;\n"
2334						  "\n"
2335						  "void main()\n"
2336						  "{\n"
2337						  "    vertexID = gl_VertexID;\n"
2338						  "    out_vs_1 = ivec4(gl_VertexID, gl_VertexID + 1, gl_VertexID + 2, gl_VertexID + 3);\n"
2339						  "    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2340						  "}\n";
2341
2342	bool has_shader_compilation_failed = true;
2343	bool result						   = true;
2344
2345	/* This test should only run if EXT_geometry_shader is supported. */
2346	if (!m_is_geometry_shader_extension_supported)
2347	{
2348		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2349	}
2350
2351	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2352
2353	/* Create program object. */
2354	m_po_id = gl.createProgram();
2355	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
2356
2357	/* Specify output variables to be captured. */
2358	const char* tf_varyings[] = { "out_vs_1", "out_gs_1" };
2359
2360	gl.transformFeedbackVaryings(m_po_id, 2 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
2361	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
2362
2363	/* Create shader objects. */
2364	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2365	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2366	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2367	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2368
2369	/* Try to link the test program object */
2370	std::string fs_code_specialized		= specializeShader(1, &minimal_fs_code);
2371	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
2372
2373	std::string gs_code_specialized		= specializeShader(1, &gs_code);
2374	const char* gs_code_specialized_raw = fs_code_specialized.c_str();
2375
2376	std::string vs_code_specialized		= specializeShader(1, &vs_code);
2377	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
2378
2379	if (TestCaseBase::buildProgram(m_po_id, m_fs_id, 1,					 /* n_sh1_body_parts */
2380								   &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
2381								   &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
2382								   &vs_code_specialized_raw, &has_shader_compilation_failed))
2383	{
2384		m_testCtx.getLog() << tcu::TestLog::Message
2385						   << "Program object linking successful, whereas a failure was expected."
2386						   << tcu::TestLog::EndMessage;
2387
2388		result = false;
2389	}
2390
2391	if (result)
2392	{
2393		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2394	}
2395	else
2396	{
2397		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2398	}
2399
2400	return STOP;
2401}
2402
2403} // namespace glcts
2404