1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24#include "esextcGeometryShaderProgramResource.hpp"
25#include "gluContextInfo.hpp"
26#include "glwEnums.hpp"
27#include "glwFunctions.hpp"
28#include "tcuTestLog.hpp"
29
30namespace glcts
31{
32/* Shared shaders' code */
33const char* const GeometryShaderProgramResourceTest::m_common_shader_code_definitions_body =
34	"// uniforms\n"
35	"uniform mat4 uni_model_view_projection; // not referenced in GS\n"
36	"uniform vec4 uni_colors_white;          // referenced in GS\n"
37	"\n"
38	"// uniforms blocks\n"
39	"uniform Matrices\n"
40	"{\n"
41	"    mat4 model;\n"
42	"    mat4 view;\n"
43	"    mat4 projection;\n"
44	"} uni_matrices; // not referenced at all\n"
45	"\n"
46	"uniform Colors\n"
47	"{\n"
48	"    vec4 red;\n"
49	"    vec4 green;\n"
50	"    vec4 blue;\n"
51	"} uni_colors; // referenced in GS\n"
52	"\n";
53
54const char* const GeometryShaderProgramResourceTest::m_common_shader_code_definitions_atomic_counter_body =
55	"// atomic counter buffers\n"
56	"layout (binding = 0) uniform atomic_uint uni_atom_horizontal; // not referenced in GS\n"
57	"layout (binding = 1) uniform atomic_uint uni_atom_vertical;   // referenced in GS\n"
58	"\n";
59
60const char* const GeometryShaderProgramResourceTest::m_common_shader_code_definitions_ssbo_body =
61	"// ssbos\n"
62	"buffer Positions\n"
63	"{\n"
64	"    vec4 position[4]; // referenced in GS\n"
65	"} storage_positions;  // referenced in GS\n"
66	"\n"
67	"buffer Ids\n"
68	"{\n"
69	"    int ids[4]; // not referenced in GS\n"
70	"} storage_ids;  // not referenced in GS\n"
71	"\n";
72
73/* Vertex shader */
74const char* const GeometryShaderProgramResourceTest::m_vertex_shader_code_preamble = "${VERSION}\n"
75																					 "\n"
76																					 "precision highp float;\n"
77																					 "\n"
78																					 "// uniforms included here\n";
79
80const char* const GeometryShaderProgramResourceTest::m_vertex_shader_code_body =
81	"// attributes\n"
82	"in vec4 vs_in_position; // not referenced in GS\n"
83	"in vec4 vs_in_color;    // not referenced in GS\n"
84	"\n"
85	"// output\n"
86	"out vec4 vs_out_color; // referenced in GS\n"
87	"\n"
88	"void main()\n"
89	"{\n"
90	"    gl_Position  = uni_model_view_projection * vs_in_position;\n"
91	"    vs_out_color = vs_in_color;\n";
92
93const char* const GeometryShaderProgramResourceTest::m_vertex_shader_code_atomic_counter_body =
94	"    // write atomic counters\n"
95	"    if (0.0 <= gl_Position.x)\n"
96	"    {\n"
97	"        atomicCounterIncrement(uni_atom_vertical);\n"
98	"    }\n"
99	"\n"
100	"    if (0.0 <= gl_Position.y)\n"
101	"    {\n"
102	"        atomicCounterIncrement(uni_atom_horizontal);\n"
103	"    }\n";
104
105const char* const GeometryShaderProgramResourceTest::m_vertex_shader_code_ssbo_body =
106	"    // write shader storage buffers\n"
107	"    storage_positions.position[gl_VertexID] = gl_Position;\n"
108	"    storage_ids.ids[gl_VertexID]            = gl_VertexID;\n";
109
110/* Geometry shader */
111const char* const GeometryShaderProgramResourceTest::m_geometry_shader_code_preamble =
112	"${VERSION}\n"
113	"\n"
114	"${GEOMETRY_SHADER_REQUIRE}\n"
115	"\n"
116	"precision highp float;\n"
117	"\n"
118	"layout (points)                           in;\n"
119	"layout (triangle_strip, max_vertices = 6) out;\n"
120	"\n"
121	"// uniforms included here\n";
122
123const char* const GeometryShaderProgramResourceTest::m_geometry_shader_code_body =
124	"// input from vs + gl_Position\n"
125	"in vec4 vs_out_color[1];\n"
126	"\n"
127	"out vec4 gs_out_color;\n"
128	"\n"
129	"void main()\n"
130	"{\n"
131	"    // access uniform\n"
132	"    gl_Position = vec4(0, 0, 0, 0);\n"
133	"    gs_out_color = uni_colors_white;\n"
134	"    EmitVertex();\n"
135	"\n"
136	"    // access uniform block\n"
137	"    gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.1, 0, 0);\n"
138	"    gs_out_color = vs_out_color[0] + uni_colors.red;\n"
139	"    EmitVertex();\n"
140	"\n"
141	"    gl_Position = gl_in[0].gl_Position + vec4(-0.1, -0.1, 0, 0);\n"
142	"    gs_out_color = vs_out_color[0] + uni_colors.green;\n"
143	"    EmitVertex();\n"
144	"\n"
145	"    gl_Position = gl_in[0].gl_Position + vec4(0.1, -0.1, 0, 0);\n"
146	"    gs_out_color = vs_out_color[0] + uni_colors.blue;\n"
147	"    EmitVertex();\n";
148
149const char* const GeometryShaderProgramResourceTest::m_geometry_shader_code_atomic_counter_body =
150	"    // access atomic counter\n"
151	"    gl_Position = vec4(0, 0, 0, 0);\n"
152	"    uint  counter = atomicCounter(uni_atom_vertical);\n"
153	"    gs_out_color     = vec4(counter / 255u);\n"
154	"    EmitVertex();\n";
155
156const char* const GeometryShaderProgramResourceTest::m_geometry_shader_code_ssbo_body =
157	"    // access shader storage buffers\n"
158	"    gl_Position = storage_positions.position[0] + vec4(0.1, 0.1, 0, 0);\n"
159	"    gs_out_color     = vec4(1.0);\n"
160	"    EmitVertex();\n";
161
162/* Fragment shader */
163const char* const GeometryShaderProgramResourceTest::m_fragment_shader_code =
164	"${VERSION}\n"
165	"\n"
166	"precision highp float;\n"
167	"\n"
168	"// input from gs\n"
169	"in vec4 gs_out_color;\n"
170	"layout(location = 0) out vec4 fs_out_color;\n"
171	"\n"
172	"void main()\n"
173	"{\n"
174	"    fs_out_color = gs_out_color;\n"
175	"}\n"
176	"\n";
177
178/** Constructor
179 *
180 * @param context     Test context
181 * @param name        Test case's name
182 * @param description Test case's desricption
183 **/
184GeometryShaderProgramResourceTest::GeometryShaderProgramResourceTest(Context& context, const ExtParameters& extParams,
185																	 const char* name, const char* description)
186	: TestCaseBase(context, extParams, name, description)
187	, m_fragment_shader_id(0)
188	, m_geometry_shader_id(0)
189	, m_vertex_shader_id(0)
190	, m_program_object_id(0)
191	, m_atomic_counters_supported(false)
192	, m_ssbos_supported(false)
193{
194	/* Nothing to be done here */
195}
196
197/** Initializes GLES objects used during the test.
198 *
199 **/
200void GeometryShaderProgramResourceTest::initTest()
201{
202	/* Check if geometry_shader extension is supported */
203	if (!m_is_geometry_shader_extension_supported)
204	{
205		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
206	}
207
208	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
209
210	glw::GLint maxVSAtomicCounters = 0;
211	gl.getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &maxVSAtomicCounters);
212
213	glw::GLint maxGSAtomicCounters = 0;
214	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, &maxGSAtomicCounters);
215
216	m_atomic_counters_supported = maxVSAtomicCounters >= 2 && maxGSAtomicCounters >= 1;
217
218	glw::GLint maxVSStorageBlocks = 0;
219	gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVSStorageBlocks);
220
221	glw::GLint maxGSStorageBlocks = 0;
222	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &maxGSStorageBlocks);
223
224	m_ssbos_supported = maxVSStorageBlocks >= 2 && maxGSStorageBlocks >= 1;
225
226	glw::GLuint nCodeParts = 0;
227	const char* vertex_shader_code_parts[8];
228	const char* geometry_shader_code_parts[8];
229
230	/* Vertex & geometry shaders */
231	if (m_atomic_counters_supported && m_ssbos_supported)
232	{
233		vertex_shader_code_parts[0] = m_vertex_shader_code_preamble;
234		vertex_shader_code_parts[1] = m_common_shader_code_definitions_body;
235		vertex_shader_code_parts[2] = m_common_shader_code_definitions_atomic_counter_body;
236		vertex_shader_code_parts[3] = m_common_shader_code_definitions_ssbo_body;
237		vertex_shader_code_parts[4] = m_vertex_shader_code_body;
238		vertex_shader_code_parts[5] = m_vertex_shader_code_atomic_counter_body;
239		vertex_shader_code_parts[6] = m_vertex_shader_code_ssbo_body;
240		vertex_shader_code_parts[7] = "}\n";
241
242		geometry_shader_code_parts[0] = m_geometry_shader_code_preamble;
243		geometry_shader_code_parts[1] = m_common_shader_code_definitions_body;
244		geometry_shader_code_parts[2] = m_common_shader_code_definitions_atomic_counter_body;
245		geometry_shader_code_parts[3] = m_common_shader_code_definitions_ssbo_body;
246		geometry_shader_code_parts[4] = m_geometry_shader_code_body;
247		geometry_shader_code_parts[5] = m_geometry_shader_code_atomic_counter_body;
248		geometry_shader_code_parts[6] = m_geometry_shader_code_ssbo_body;
249		geometry_shader_code_parts[7] = "}\n";
250
251		nCodeParts = 8;
252	}
253	else if (m_atomic_counters_supported)
254	{
255		vertex_shader_code_parts[0] = m_vertex_shader_code_preamble;
256		vertex_shader_code_parts[1] = m_common_shader_code_definitions_body;
257		vertex_shader_code_parts[2] = m_common_shader_code_definitions_atomic_counter_body;
258		vertex_shader_code_parts[3] = m_vertex_shader_code_body;
259		vertex_shader_code_parts[4] = m_vertex_shader_code_atomic_counter_body;
260		vertex_shader_code_parts[5] = "}\n";
261
262		geometry_shader_code_parts[0] = m_geometry_shader_code_preamble;
263		geometry_shader_code_parts[1] = m_common_shader_code_definitions_body;
264		geometry_shader_code_parts[2] = m_common_shader_code_definitions_atomic_counter_body;
265		geometry_shader_code_parts[3] = m_geometry_shader_code_body;
266		geometry_shader_code_parts[4] = m_geometry_shader_code_atomic_counter_body;
267		geometry_shader_code_parts[5] = "}\n";
268
269		nCodeParts = 6;
270	}
271	else if (m_ssbos_supported)
272	{
273		vertex_shader_code_parts[0] = m_vertex_shader_code_preamble;
274		vertex_shader_code_parts[1] = m_common_shader_code_definitions_body;
275		vertex_shader_code_parts[2] = m_common_shader_code_definitions_ssbo_body;
276		vertex_shader_code_parts[3] = m_vertex_shader_code_body;
277		vertex_shader_code_parts[4] = m_vertex_shader_code_ssbo_body;
278		vertex_shader_code_parts[5] = "}\n";
279
280		geometry_shader_code_parts[0] = m_geometry_shader_code_preamble;
281		geometry_shader_code_parts[1] = m_common_shader_code_definitions_body;
282		geometry_shader_code_parts[2] = m_common_shader_code_definitions_ssbo_body;
283		geometry_shader_code_parts[3] = m_geometry_shader_code_body;
284		geometry_shader_code_parts[4] = m_geometry_shader_code_ssbo_body;
285		geometry_shader_code_parts[5] = "}\n";
286
287		nCodeParts = 6;
288	}
289	else
290	{
291		vertex_shader_code_parts[0] = m_vertex_shader_code_preamble;
292		vertex_shader_code_parts[1] = m_common_shader_code_definitions_body;
293		vertex_shader_code_parts[2] = m_vertex_shader_code_body;
294		vertex_shader_code_parts[3] = "}\n";
295
296		geometry_shader_code_parts[0] = m_geometry_shader_code_preamble;
297		geometry_shader_code_parts[1] = m_common_shader_code_definitions_body;
298		geometry_shader_code_parts[2] = m_geometry_shader_code_body;
299		geometry_shader_code_parts[3] = "}\n";
300
301		nCodeParts = 4;
302	}
303
304	/* Create shader objects */
305	m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
306	m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
307	m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
308
309	/* Create program object */
310	m_program_object_id = gl.createProgram();
311
312	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object");
313
314	/* Build program object */
315	if (true !=
316		buildProgram(m_program_object_id, m_fragment_shader_id, 1,				 /* Fragment shader parts number */
317					 &m_fragment_shader_code, m_geometry_shader_id, nCodeParts,  /* Geometry shader parts number */
318					 geometry_shader_code_parts, m_vertex_shader_id, nCodeParts, /* Vertex shader parts number */
319					 vertex_shader_code_parts))
320	{
321		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
322	}
323}
324
325/** Executes the test.
326 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
327 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
328 *  Note the function throws exception should an error occur!
329 **/
330tcu::TestCase::IterateResult GeometryShaderProgramResourceTest::iterate()
331{
332	initTest();
333
334	/* Results */
335	bool result = true;
336
337	/* Results of checks, names come from shaders */
338	bool is_gl_fs_out_color_program_output_referenced		  = false;
339	bool is_ids_ids_buffer_variable_referenced				  = false;
340	bool is_positions_position_buffer_variable_referenced	 = false;
341	bool is_storage_ids_shader_storage_block_referenced		  = false;
342	bool is_storage_positions_shader_storage_block_referenced = false;
343	bool is_uni_atom_horizontal_uniform_referenced			  = false;
344	bool is_uni_atom_vertical_uniform_referenced			  = false;
345	bool is_uni_colors_uniform_referenced					  = false;
346	bool is_uni_colors_white_uniform_referenced				  = false;
347	bool is_uni_matrices_uniform_referenced					  = false;
348	bool is_uni_model_view_projection_uniform_referenced	  = false;
349	bool is_vs_in_color_program_input_referenced			  = false;
350	bool is_vs_in_position_program_input_referenced			  = false;
351
352	/* Check whether uniform variables are referenced */
353	is_uni_model_view_projection_uniform_referenced =
354		checkIfResourceIsReferenced(m_program_object_id, GL_UNIFORM, "uni_model_view_projection");
355	is_uni_colors_white_uniform_referenced =
356		checkIfResourceIsReferenced(m_program_object_id, GL_UNIFORM, "uni_colors_white");
357
358	/* For: uniform Matrices {} uni_matrices; uniform block name is: Matrices */
359	is_uni_matrices_uniform_referenced = checkIfResourceIsReferenced(m_program_object_id, GL_UNIFORM_BLOCK, "Matrices");
360	is_uni_colors_uniform_referenced   = checkIfResourceIsReferenced(m_program_object_id, GL_UNIFORM_BLOCK, "Colors");
361
362	/* For: buffer Positions {} storage_positions; storage block name is: Positions */
363	if (m_ssbos_supported)
364	{
365		is_storage_positions_shader_storage_block_referenced =
366			checkIfResourceIsReferenced(m_program_object_id, GL_SHADER_STORAGE_BLOCK, "Positions");
367		is_storage_ids_shader_storage_block_referenced =
368			checkIfResourceIsReferenced(m_program_object_id, GL_SHADER_STORAGE_BLOCK, "Ids");
369
370		is_positions_position_buffer_variable_referenced =
371			checkIfResourceIsReferenced(m_program_object_id, GL_BUFFER_VARIABLE, "Positions.position");
372		is_ids_ids_buffer_variable_referenced =
373			checkIfResourceIsReferenced(m_program_object_id, GL_BUFFER_VARIABLE, "Ids.ids");
374	}
375
376	/* Check whether input attributes are referenced */
377	is_vs_in_position_program_input_referenced =
378		checkIfResourceIsReferenced(m_program_object_id, GL_PROGRAM_INPUT, "vs_in_position");
379	is_vs_in_color_program_input_referenced =
380		checkIfResourceIsReferenced(m_program_object_id, GL_PROGRAM_INPUT, "vs_in_color");
381
382	/* Check whether output attributes are referenced */
383	is_gl_fs_out_color_program_output_referenced =
384		checkIfResourceIsReferenced(m_program_object_id, GL_PROGRAM_OUTPUT, "fs_out_color");
385
386	/*
387	 *     For the ATOMIC_COUNTER_BUFFER interface, the list of active buffer binding
388	 *     points is built by identifying each unique binding point associated with
389	 *     one or more active atomic counter uniform variables.  Active atomic
390	 *     counter buffers do not have an associated name string.
391	 */
392	if (m_atomic_counters_supported)
393	{
394		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
395
396		/* First get corresponding uniform indices */
397		glw::GLuint atom_horizontal_uniform_indx =
398			gl.getProgramResourceIndex(m_program_object_id, GL_UNIFORM, "uni_atom_horizontal");
399		glw::GLuint atom_vertical_uniform_indx =
400			gl.getProgramResourceIndex(m_program_object_id, GL_UNIFORM, "uni_atom_vertical");
401
402		/* Then get atomic buffer indices */
403		glw::GLuint atom_horizontal_uniform_buffer_indx = GL_INVALID_INDEX;
404		glw::GLuint atom_vertical_uniform_buffer_indx   = GL_INVALID_INDEX;
405
406		/* Data for getProgramResourceiv */
407		glw::GLint  params[] = { 0 };
408		glw::GLenum props[]  = { GL_ATOMIC_COUNTER_BUFFER_INDEX };
409
410		/* Get property value */
411		gl.getProgramResourceiv(m_program_object_id, GL_UNIFORM, atom_horizontal_uniform_indx, 1, /* propCount */
412								props, 1,														  /* bufSize */
413								0,																  /* length */
414								params);
415		atom_horizontal_uniform_buffer_indx = params[0];
416
417		gl.getProgramResourceiv(m_program_object_id, GL_UNIFORM, atom_vertical_uniform_indx, 1, /* propCount */
418								props, 1,														/* bufSize */
419								0,																/* length */
420								params);
421		atom_vertical_uniform_buffer_indx = params[0];
422
423		/* Check whether atomic counters are referenced using the atomic buffer indices */
424		is_uni_atom_horizontal_uniform_referenced = checkIfResourceAtIndexIsReferenced(
425			m_program_object_id, GL_ATOMIC_COUNTER_BUFFER, atom_horizontal_uniform_buffer_indx);
426		is_uni_atom_vertical_uniform_referenced = checkIfResourceAtIndexIsReferenced(
427			m_program_object_id, GL_ATOMIC_COUNTER_BUFFER, atom_vertical_uniform_buffer_indx);
428	}
429
430	/* Verify results: referenced properties */
431	if (true != is_uni_colors_white_uniform_referenced)
432	{
433		m_testCtx.getLog() << tcu::TestLog::Message
434						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_UNIFORM"
435						   << tcu::TestLog::EndMessage;
436
437		result = false;
438	}
439
440	if (true != is_uni_colors_uniform_referenced)
441	{
442		m_testCtx.getLog() << tcu::TestLog::Message
443						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_UNIFORM_BLOCK"
444						   << tcu::TestLog::EndMessage;
445
446		result = false;
447	}
448
449	if (true != is_uni_atom_vertical_uniform_referenced && m_atomic_counters_supported)
450	{
451		m_testCtx.getLog()
452			<< tcu::TestLog::Message
453			<< "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_ATOMIC_COUNTER_BUFFER"
454			<< tcu::TestLog::EndMessage;
455
456		result = false;
457	}
458
459	if (false != is_uni_atom_horizontal_uniform_referenced && m_atomic_counters_supported)
460	{
461		m_testCtx.getLog()
462			<< tcu::TestLog::Message
463			<< "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_ATOMIC_COUNTER_BUFFER"
464			<< tcu::TestLog::EndMessage;
465
466		result = false;
467	}
468
469	if (true != is_storage_positions_shader_storage_block_referenced && m_ssbos_supported)
470	{
471		m_testCtx.getLog() << tcu::TestLog::Message
472						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_SHADER_STORAGE_BLOCK"
473						   << tcu::TestLog::EndMessage;
474
475		result = false;
476	}
477
478	if (false != is_storage_ids_shader_storage_block_referenced && m_ssbos_supported)
479	{
480		m_testCtx.getLog() << tcu::TestLog::Message
481						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_SHADER_STORAGE_BLOCK"
482						   << tcu::TestLog::EndMessage;
483
484		result = false;
485	}
486
487	if (true != is_positions_position_buffer_variable_referenced && m_ssbos_supported)
488	{
489		m_testCtx.getLog() << tcu::TestLog::Message
490						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_BUFFER_VARIABLE"
491						   << tcu::TestLog::EndMessage;
492
493		result = false;
494	}
495
496	if (false != is_ids_ids_buffer_variable_referenced && m_ssbos_supported)
497	{
498		m_testCtx.getLog() << tcu::TestLog::Message
499						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_BUFFER_VARIABLE"
500						   << tcu::TestLog::EndMessage;
501
502		result = false;
503	}
504
505	/* Verify results: properties that are not referenced */
506	if (false != is_uni_model_view_projection_uniform_referenced)
507	{
508		m_testCtx.getLog() << tcu::TestLog::Message
509						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_UNIFORM"
510						   << tcu::TestLog::EndMessage;
511
512		result = false;
513	}
514
515	if (false != is_uni_matrices_uniform_referenced)
516	{
517		m_testCtx.getLog() << tcu::TestLog::Message
518						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_UNIFORM_BLOCK"
519						   << tcu::TestLog::EndMessage;
520
521		result = false;
522	}
523
524	if (false != is_vs_in_position_program_input_referenced)
525	{
526		m_testCtx.getLog() << tcu::TestLog::Message
527						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_PROGRAM_INPUT"
528						   << tcu::TestLog::EndMessage;
529
530		result = false;
531	}
532
533	if (false != is_vs_in_color_program_input_referenced)
534	{
535		m_testCtx.getLog() << tcu::TestLog::Message
536						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_PROGRAM_INPUT"
537						   << tcu::TestLog::EndMessage;
538
539		result = false;
540	}
541
542	if (false != is_gl_fs_out_color_program_output_referenced)
543	{
544		m_testCtx.getLog() << tcu::TestLog::Message
545						   << "Wrong value of property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for GL_PROGRAM_OUTPUT"
546						   << tcu::TestLog::EndMessage;
547
548		result = false;
549	}
550
551	/* Set test result */
552	if (true == result)
553	{
554		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
555	}
556	else
557	{
558		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
559	}
560
561	/* Done */
562	return STOP;
563}
564
565/** Deinitializes GLES objects created during the test.
566 *
567 */
568void GeometryShaderProgramResourceTest::deinit()
569{
570	/* GL */
571	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
572
573	/* Reset OpenGL ES state */
574	gl.useProgram(0);
575
576	/* Delete program objects and shader objects */
577	if (m_program_object_id != 0)
578	{
579		gl.deleteProgram(m_program_object_id);
580	}
581
582	if (m_vertex_shader_id != 0)
583	{
584		gl.deleteShader(m_vertex_shader_id);
585	}
586
587	if (m_geometry_shader_id != 0)
588	{
589		gl.deleteShader(m_geometry_shader_id);
590	}
591
592	if (m_fragment_shader_id != 0)
593	{
594		gl.deleteShader(m_fragment_shader_id);
595	}
596
597	/* Release base class */
598	TestCaseBase::deinit();
599}
600
601/** Queries property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for resource at specified index in specific interface.
602 *  Program object must be linked.
603 *
604 *  @param program_object_id Program which will be inspected;
605 *  @param interface         Queried interface;
606 *  @param index             Resource's index.
607 *
608 *  @return  true            Property value is 1
609 *           false           Property value is 0
610 **/
611bool GeometryShaderProgramResourceTest::checkIfResourceAtIndexIsReferenced(glw::GLuint program_object_id,
612																		   glw::GLenum interface,
613																		   glw::GLuint index) const
614{
615	(void)program_object_id;
616
617	/* GL */
618	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
619
620	/* Data for getProgramResourceiv */
621	glw::GLint  params[] = { 0 };
622	glw::GLenum props[]  = { m_glExtTokens.REFERENCED_BY_GEOMETRY_SHADER };
623
624	/* Get property value */
625	gl.getProgramResourceiv(m_program_object_id, interface, index, 1, /* propCount */
626							props, 1,								  /* bufSize */
627							0,										  /* length */
628							params);
629
630	/**
631	 *     The value one is written to <params> if an active
632	 *     variable is referenced by the corresponding shader, or if an active
633	 *     uniform block, shader storage block, or atomic counter buffer contains
634	 *     at least one variable referenced by the corresponding shader.  Otherwise,
635	 *     the value zero is written to <params>.
636	 **/
637	if (1 == params[0])
638	{
639		return true;
640	}
641	else
642	{
643		return false;
644	}
645}
646
647/** Queries property GL_REFERENCED_BY_GEOMETRY_SHADER_EXT for resource with specified name in specific interface.
648 *  Program object must be linked.
649 *
650 *  @param program_object_id Program which will be inspected
651 *  @param interface         Queried interface
652 *  @param name              Resource's name
653 *
654 *  @return  true            Property value is 1
655 *           false           Property value is 0, or resource is not available
656 **/
657bool GeometryShaderProgramResourceTest::checkIfResourceIsReferenced(glw::GLuint program_object_id,
658																	glw::GLenum interface, const char* name) const
659{
660	/* GL */
661	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
662
663	/* Resource index */
664	glw::GLuint index = GL_INVALID_INDEX;
665
666	/* Get resource's index by name */
667	index = gl.getProgramResourceIndex(program_object_id, interface, name);
668
669	/**
670	 *     Otherwise, <name> is considered not to be the name
671	 *     of an active resource, and INVALID_INDEX is returned.
672	 **/
673	if (GL_INVALID_INDEX == index)
674	{
675		return false;
676	}
677
678	/* Get property by index */
679	return checkIfResourceAtIndexIsReferenced(program_object_id, interface, index);
680}
681
682} /* glcts */
683