1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2015 The Android Open Source Project
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 Program State Query tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fProgramStateQueryTests.hpp"
25 #include "es31fInfoLogQueryShared.hpp"
26 #include "glsStateQueryUtil.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluCallLogWrapper.hpp"
29 #include "gluContextInfo.hpp"
30 #include "gluObjectWrapper.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "glwFunctions.hpp"
33 #include "glwEnums.hpp"
34 #include "tcuStringTemplate.hpp"
35 
36 namespace deqp
37 {
38 
39 using std::string;
40 using std::map;
41 
42 namespace gles31
43 {
44 namespace Functional
45 {
46 namespace
47 {
48 
49 using namespace gls::StateQueryUtil;
50 
getVerifierSuffix(QueryType type)51 static const char* getVerifierSuffix (QueryType type)
52 {
53 	switch (type)
54 	{
55 		case QUERY_PROGRAM_INTEGER_VEC3:
56 		case QUERY_PROGRAM_INTEGER:
57 			return "get_programiv";
58 
59 		default:
60 			DE_ASSERT(DE_FALSE);
61 			return DE_NULL;
62 	}
63 }
64 
specializeShader(Context & context,const char * code)65 static std::string specializeShader(Context& context, const char* code)
66 {
67 	const glu::GLSLVersion				glslVersion			= glu::getContextTypeGLSLVersion(context.getRenderContext().getType());
68 	std::map<std::string, std::string>	specializationMap;
69 
70 	specializationMap["GLSL_VERSION_DECL"] = glu::getGLSLVersionDeclaration(glslVersion);
71 
72 	if (glu::contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
73 	{
74 		specializationMap["GEOMETRY_SHADER_REQUIRE"] = "";
75 		specializationMap["TESSELLATION_SHADER_REQUIRE"] = "";
76 	}
77 	else
78 	{
79 		specializationMap["GEOMETRY_SHADER_REQUIRE"] = "#extension GL_EXT_geometry_shader : require";
80 		specializationMap["TESSELLATION_SHADER_REQUIRE"] = "#extension GL_EXT_tessellation_shader : require";
81 	}
82 
83 	return tcu::StringTemplate(code).specialize(specializationMap);
84 }
85 
86 
87 class GeometryShaderCase : public TestCase
88 {
89 public:
90 						GeometryShaderCase		(Context& context, QueryType verifier, const char* name, const char* desc);
91 	IterateResult		iterate					(void);
92 
93 private:
94 	const QueryType		m_verifier;
95 };
96 
GeometryShaderCase(Context & context,QueryType verifier,const char * name,const char * desc)97 GeometryShaderCase::GeometryShaderCase (Context& context, QueryType verifier, const char* name, const char* desc)
98 	: TestCase		(context, name, desc)
99 	, m_verifier	(verifier)
100 {
101 }
102 
iterate(void)103 GeometryShaderCase::IterateResult GeometryShaderCase::iterate (void)
104 {
105 	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
106 
107 	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
108 		TCU_THROW(NotSupportedError, "Geometry shader tests require GL_EXT_geometry_shader extension or an OpenGL ES 3.2 or higher context.");
109 
110 
111 	static const char* const	s_vtxFragTemplate	=	"${GLSL_VERSION_DECL}\n"
112 														"void main()\n"
113 														"{\n"
114 														"}\n";
115 
116 	static const char* const	s_geometryTemplate1	=	"${GLSL_VERSION_DECL}\n"
117 														"${GEOMETRY_SHADER_REQUIRE}\n"
118 														"layout(triangles) in;"
119 														"layout(triangle_strip, max_vertices = 3) out;\n"
120 														"void main()\n"
121 														"{\n"
122 														"   EndPrimitive();\n"
123 														"}\n";
124 
125 	static const char* const	s_geometryTemplate2	=	"${GLSL_VERSION_DECL}\n"
126 														"${GEOMETRY_SHADER_REQUIRE}\n"
127 														"layout(points) in;"
128 														"layout(line_strip, max_vertices = 5) out;\n"
129 														"void main()\n"
130 														"{\n"
131 														"   EndPrimitive();\n"
132 														"}\n";
133 
134 	static const char* const	s_geometryTemplate3	=	"${GLSL_VERSION_DECL}\n"
135 														"${GEOMETRY_SHADER_REQUIRE}\n"
136 														"layout(points) in;"
137 														"layout(points, max_vertices = 50) out;\n"
138 														"void main()\n"
139 														"{\n"
140 														"   EndPrimitive();\n"
141 														"}\n";
142 
143 	glu::CallLogWrapper			gl						(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
144 	tcu::ResultCollector		result					(m_testCtx.getLog(), " // ERROR: ");
145 
146 	gl.enableLogging(true);
147 
148 	{
149 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Layout", "triangles in, triangle strip out, 3 vertices");
150 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources()
151 			<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
152 			<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
153 			<< glu::GeometrySource(specializeShader(m_context, s_geometryTemplate1)));
154 
155 		TCU_CHECK_MSG(program.isOk(), "Compile failed");
156 
157 		m_testCtx.getLog() << program;
158 
159 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 3, m_verifier);
160 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_TRIANGLES, m_verifier);
161 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_TRIANGLE_STRIP, m_verifier);
162 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_SHADER_INVOCATIONS, 1, m_verifier);
163 	}
164 
165 	{
166 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Layout", "points in, line strip out, 5 vertices");
167 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources()
168 			<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
169 			<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
170 			<< glu::GeometrySource(specializeShader(m_context, s_geometryTemplate2)));
171 
172 		TCU_CHECK_MSG(program.isOk(), "Compile failed");
173 
174 		m_testCtx.getLog() << program;
175 
176 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 5, m_verifier);
177 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_POINTS, m_verifier);
178 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_LINE_STRIP, m_verifier);
179 	}
180 
181 	{
182 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Layout", "points in, points out, 50 vertices");
183 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources()
184 			<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
185 			<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
186 			<< glu::GeometrySource(specializeShader(m_context, s_geometryTemplate3)));
187 
188 		TCU_CHECK_MSG(program.isOk(), "Compile failed");
189 
190 		m_testCtx.getLog() << program;
191 
192 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_VERTICES_OUT, 50, m_verifier);
193 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_INPUT_TYPE, GL_POINTS, m_verifier);
194 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_GEOMETRY_OUTPUT_TYPE, GL_POINTS, m_verifier);
195 	}
196 
197 	result.setTestContextResult(m_testCtx);
198 	return STOP;
199 }
200 
201 class TessellationShaderCase : public TestCase
202 {
203 public:
204 						TessellationShaderCase		(Context& context, QueryType verifier, const char* name, const char* desc);
205 	IterateResult		iterate					(void);
206 
207 private:
208 	const QueryType		m_verifier;
209 };
210 
TessellationShaderCase(Context & context,QueryType verifier,const char * name,const char * desc)211 TessellationShaderCase::TessellationShaderCase (Context& context, QueryType verifier, const char* name, const char* desc)
212 	: TestCase		(context, name, desc)
213 	, m_verifier	(verifier)
214 {
215 }
216 
iterate(void)217 TessellationShaderCase::IterateResult TessellationShaderCase::iterate (void)
218 {
219 	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
220 
221 	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
222 		TCU_THROW(NotSupportedError, "Tessellation shader tests require GL_EXT_tessellation_shader extension or an OpenGL ES 3.2 or higher context.");
223 
224 
225 	static const char* const	s_vtxFragTemplate	=	"${GLSL_VERSION_DECL}\n"
226 														"void main()\n"
227 														"{\n"
228 														"}\n";
229 
230 	static const char* const	s_tessCtrlTemplate1	=	"${GLSL_VERSION_DECL}\n"
231 														"${TESSELLATION_SHADER_REQUIRE}\n"
232 														"layout(vertices = 3) out;\n"
233 														"void main()\n"
234 														"{\n"
235 														"}\n";
236 
237 	static const char* const	s_tessEvalTemplate1	=	"${GLSL_VERSION_DECL}\n"
238 														"${TESSELLATION_SHADER_REQUIRE}\n"
239 														"layout(triangles, equal_spacing, cw) in;\n"
240 														"void main()\n"
241 														"{\n"
242 														"}\n";
243 
244 	static const char* const	s_tessCtrlTemplate2	=	"${GLSL_VERSION_DECL}\n"
245 														"${TESSELLATION_SHADER_REQUIRE}\n"
246 														"layout(vertices = 5) out;\n"
247 														"void main()\n"
248 														"{\n"
249 														"}\n";
250 
251 	static const char* const	s_tessEvalTemplate2	=	"${GLSL_VERSION_DECL}\n"
252 														"${TESSELLATION_SHADER_REQUIRE}\n"
253 														"layout(quads, fractional_even_spacing, ccw) in;\n"
254 														"void main()\n"
255 														"{\n"
256 														"}\n";
257 
258 	static const char* const	s_tessEvalTemplate3	=	"${GLSL_VERSION_DECL}\n"
259 														"${TESSELLATION_SHADER_REQUIRE}\n"
260 														"layout(isolines, fractional_odd_spacing, ccw, point_mode) in;\n"
261 														"void main()\n"
262 														"{\n"
263 														"}\n";
264 
265 	glu::CallLogWrapper			gl						(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
266 	tcu::ResultCollector		result					(m_testCtx.getLog(), " // ERROR: ");
267 
268 	gl.enableLogging(true);
269 
270 	{
271 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Query State", "3 vertices, triangles, equal_spacing, cw");
272 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources()
273 			<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
274 			<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
275 			<< glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate1))
276 			<< glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate1)));
277 
278 		TCU_CHECK_MSG(program.isOk(), "Compile failed");
279 
280 		m_testCtx.getLog() << program;
281 
282 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 3, m_verifier);
283 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_TRIANGLES, m_verifier);
284 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_EQUAL, m_verifier);
285 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CW, m_verifier);
286 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_FALSE, m_verifier);
287 	}
288 
289 	{
290 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Query State", "5 vertices, quads, fractional_even_spacing, ccw");
291 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources()
292 			<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
293 			<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
294 			<< glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate2))
295 			<< glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate2)));
296 
297 		TCU_CHECK_MSG(program.isOk(), "Compile failed");
298 
299 		m_testCtx.getLog() << program;
300 
301 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 5, m_verifier);
302 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_QUADS, m_verifier);
303 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_FRACTIONAL_EVEN, m_verifier);
304 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CCW, m_verifier);
305 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_FALSE, m_verifier);
306 	}
307 
308 	{
309 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Query State", "5 vertices, isolines, fractional_odd_spacing, ccw, point_mode");
310 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources()
311 			<< glu::VertexSource(specializeShader(m_context, s_vtxFragTemplate))
312 			<< glu::FragmentSource(specializeShader(m_context, s_vtxFragTemplate))
313 			<< glu::TessellationControlSource(specializeShader(m_context, s_tessCtrlTemplate2))
314 			<< glu::TessellationEvaluationSource(specializeShader(m_context, s_tessEvalTemplate3)));
315 
316 		TCU_CHECK_MSG(program.isOk(), "Compile failed");
317 
318 		m_testCtx.getLog() << program;
319 
320 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_CONTROL_OUTPUT_VERTICES, 5, m_verifier);
321 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_MODE, GL_ISOLINES, m_verifier);
322 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_SPACING, GL_FRACTIONAL_ODD, m_verifier);
323 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_VERTEX_ORDER, GL_CCW, m_verifier);
324 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_TESS_GEN_POINT_MODE, GL_TRUE, m_verifier);
325 	}
326 
327 	result.setTestContextResult(m_testCtx);
328 	return STOP;
329 }
330 
331 class ProgramSeparableCase : public TestCase
332 {
333 public:
334 						ProgramSeparableCase	(Context& context, QueryType verifier, const char* name, const char* desc);
335 	IterateResult		iterate					(void);
336 
337 private:
338 	const QueryType		m_verifier;
339 };
340 
ProgramSeparableCase(Context & context,QueryType verifier,const char * name,const char * desc)341 ProgramSeparableCase::ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc)
342 	: TestCase		(context, name, desc)
343 	, m_verifier	(verifier)
344 {
345 }
346 
iterate(void)347 ProgramSeparableCase::IterateResult ProgramSeparableCase::iterate (void)
348 {
349 	const string				vtxTemplate	=	"${GLSL_VERSION_DECL}\n"
350 												"out highp vec4 v_color;\n"
351 												"void main()\n"
352 												"{\n"
353 												"	gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n"
354 												"	v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n"
355 												"}\n";
356 	const string				fragTemplate =	"${GLSL_VERSION_DECL}\n"
357 												"in highp vec4 v_color;\n"
358 												"layout(location=0) out highp vec4 o_color;\n"
359 												"void main()\n"
360 												"{\n"
361 												"	o_color = v_color;\n"
362 												"}\n";
363 
364 	glu::CallLogWrapper			gl				(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
365 	tcu::ResultCollector		result			(m_testCtx.getLog(), " // ERROR: ");
366 	glu::Shader					vtxShader		(m_context.getRenderContext(), glu::SHADERTYPE_VERTEX);
367 	glu::Shader					frgShader		(m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
368 
369 	const std::string			vStr			= specializeShader(m_context, vtxTemplate.c_str());
370 	const std::string			fStr			= specializeShader(m_context, fragTemplate.c_str());
371 	const char* const			vtxSourcePtr	= vStr.c_str();
372 	const char* const			fragSourcePtr	= fStr.c_str();
373 
374 	vtxShader.setSources(1, &vtxSourcePtr, DE_NULL);
375 	frgShader.setSources(1, &fragSourcePtr, DE_NULL);
376 
377 	vtxShader.compile();
378 	frgShader.compile();
379 
380 	{
381 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxShader", "Vertex shader");
382 		m_testCtx.getLog() << vtxShader;
383 	}
384 
385 	{
386 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgShader", "Fragment shader");
387 		m_testCtx.getLog() << frgShader;
388 	}
389 
390 	TCU_CHECK_MSG(vtxShader.getCompileStatus() && frgShader.getCompileStatus(), "failed to build shaders");
391 
392 	gl.enableLogging(true);
393 
394 	{
395 		const tcu::ScopedLogSection	section	(m_testCtx.getLog(), "Initial", "Initial");
396 		glu::Program				program	(m_context.getRenderContext());
397 
398 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
399 	}
400 
401 	{
402 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "SetFalse", "SetFalse");
403 		glu::Program				program		(m_context.getRenderContext());
404 		int							linkStatus	= 0;
405 
406 		gl.glAttachShader(program.getProgram(), vtxShader.getShader());
407 		gl.glAttachShader(program.getProgram(), frgShader.getShader());
408 		gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
409 		gl.glLinkProgram(program.getProgram());
410 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
411 
412 		gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
413 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
414 
415 		TCU_CHECK_MSG(linkStatus == GL_TRUE, "failed to link program");
416 
417 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
418 	}
419 
420 	{
421 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "SetTrue", "SetTrue");
422 		glu::Program				program		(m_context.getRenderContext());
423 		int							linkStatus	= 0;
424 
425 		gl.glAttachShader(program.getProgram(), vtxShader.getShader());
426 		gl.glAttachShader(program.getProgram(), frgShader.getShader());
427 		gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
428 		gl.glLinkProgram(program.getProgram());
429 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
430 
431 		gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
432 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
433 
434 		TCU_CHECK_MSG(linkStatus == GL_TRUE, "failed to link program");
435 
436 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE, m_verifier);
437 	}
438 
439 	result.setTestContextResult(m_testCtx);
440 	return STOP;
441 }
442 
443 class ComputeWorkGroupSizeCase : public TestCase
444 {
445 public:
446 						ComputeWorkGroupSizeCase	(Context& context, QueryType verifier, const char* name, const char* desc);
447 	IterateResult		iterate						(void);
448 
449 private:
450 	const QueryType		m_verifier;
451 };
452 
ComputeWorkGroupSizeCase(Context & context,QueryType verifier,const char * name,const char * desc)453 ComputeWorkGroupSizeCase::ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc)
454 	: TestCase		(context, name, desc)
455 	, m_verifier	(verifier)
456 {
457 }
458 
iterate(void)459 ComputeWorkGroupSizeCase::IterateResult ComputeWorkGroupSizeCase::iterate (void)
460 {
461 	static const char* const	s_computeTemplate1D =	"${GLSL_VERSION_DECL}\n"
462 														"layout (local_size_x = 3) in;\n"
463 														"layout(binding = 0) buffer Output\n"
464 														"{\n"
465 														"	highp float val;\n"
466 														"} sb_out;\n"
467 														"\n"
468 														"void main (void)\n"
469 														"{\n"
470 														"	sb_out.val = 1.0;\n"
471 														"}\n";
472 	static const char* const	s_computeTemplate2D =	"${GLSL_VERSION_DECL}\n"
473 														"layout (local_size_x = 3, local_size_y = 2) in;\n"
474 														"layout(binding = 0) buffer Output\n"
475 														"{\n"
476 														"	highp float val;\n"
477 														"} sb_out;\n"
478 														"\n"
479 														"void main (void)\n"
480 														"{\n"
481 														"	sb_out.val = 1.0;\n"
482 														"}\n";
483 	static const char* const	s_computeTemplate3D =	"${GLSL_VERSION_DECL}\n"
484 														"layout (local_size_x = 3, local_size_y = 2, local_size_z = 4) in;\n"
485 														"layout(binding = 0) buffer Output\n"
486 														"{\n"
487 														"	highp float val;\n"
488 														"} sb_out;\n"
489 														"\n"
490 														"void main (void)\n"
491 														"{\n"
492 														"	sb_out.val = 1.0;\n"
493 														"}\n";
494 
495 	glu::CallLogWrapper			gl						(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
496 	tcu::ResultCollector		result					(m_testCtx.getLog(), " // ERROR: ");
497 
498 	gl.enableLogging(true);
499 
500 	{
501 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "OneDimensional", "1D");
502 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate1D)));
503 
504 		m_testCtx.getLog() << program;
505 
506 		TCU_CHECK_MSG(program.isOk(), "failed to build program");
507 
508 		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 1, 1), m_verifier);
509 	}
510 
511 	{
512 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "TwoDimensional", "2D");
513 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate2D)));
514 
515 		m_testCtx.getLog() << program;
516 
517 		TCU_CHECK_MSG(program.isOk(), "failed to build program");
518 
519 		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 1), m_verifier);
520 	}
521 
522 	{
523 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "TreeDimensional", "3D");
524 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate3D)));
525 
526 		m_testCtx.getLog() << program;
527 
528 		TCU_CHECK_MSG(program.isOk(), "failed to build program");
529 
530 		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 4), m_verifier);
531 	}
532 
533 	result.setTestContextResult(m_testCtx);
534 	return STOP;
535 }
536 
537 class ActiveAtomicCounterBuffersCase : public TestCase
538 {
539 public:
540 						ActiveAtomicCounterBuffersCase	(Context& context, QueryType verifier, const char* name, const char* desc);
541 	IterateResult		iterate							(void);
542 
543 private:
544 	const QueryType		m_verifier;
545 };
546 
ActiveAtomicCounterBuffersCase(Context & context,QueryType verifier,const char * name,const char * desc)547 ActiveAtomicCounterBuffersCase::ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc)
548 	: TestCase		(context, name, desc)
549 	, m_verifier	(verifier)
550 {
551 }
552 
iterate(void)553 ActiveAtomicCounterBuffersCase::IterateResult ActiveAtomicCounterBuffersCase::iterate (void)
554 {
555 	static const char* const	s_computeTemplate0	=	"${GLSL_VERSION_DECL}\n"
556 														"layout (local_size_x = 3) in;\n"
557 														"layout(binding = 0) buffer Output\n"
558 														"{\n"
559 														"	highp float val;\n"
560 														"} sb_out;\n"
561 														"\n"
562 														"void main (void)\n"
563 														"{\n"
564 														"	sb_out.val = 1.0;\n"
565 														"}\n";
566 	static const char* const	s_computeTemplate1	=	"${GLSL_VERSION_DECL}\n"
567 														"layout (local_size_x = 3) in;\n"
568 														"layout(binding = 0) uniform highp atomic_uint u_counters[2];\n"
569 														"layout(binding = 0) buffer Output\n"
570 														"{\n"
571 														"	highp float val;\n"
572 														"} sb_out;\n"
573 														"\n"
574 														"void main (void)\n"
575 														"{\n"
576 														"	sb_out.val = float(atomicCounterIncrement(u_counters[0])) + float(atomicCounterIncrement(u_counters[1]));\n"
577 														"}\n";
578 
579 	glu::CallLogWrapper			gl						(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
580 	tcu::ResultCollector		result					(m_testCtx.getLog(), " // ERROR: ");
581 
582 	gl.enableLogging(true);
583 
584 	{
585 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Initial", "Initial");
586 		glu::Program				program		(m_context.getRenderContext());
587 
588 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
589 	}
590 
591 	{
592 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "NoBuffers", "No buffers");
593 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate0)));
594 
595 		m_testCtx.getLog() << program;
596 
597 		TCU_CHECK_MSG(program.isOk(), "failed to build program");
598 
599 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
600 	}
601 
602 	{
603 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "OneBuffer", "One buffer");
604 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, s_computeTemplate1)));
605 
606 		m_testCtx.getLog() << program;
607 
608 		TCU_CHECK_MSG(program.isOk(), "failed to build program");
609 
610 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 1, m_verifier);
611 	}
612 
613 	result.setTestContextResult(m_testCtx);
614 	return STOP;
615 }
616 
617 class ProgramLogCase : public TestCase
618 {
619 public:
620 	enum BuildErrorType
621 	{
622 		BUILDERROR_VERTEX_FRAGMENT = 0,
623 		BUILDERROR_COMPUTE,
624 		BUILDERROR_GEOMETRY,
625 		BUILDERROR_TESSELLATION,
626 	};
627 
628 							ProgramLogCase		(Context& ctx, const char* name, const char* desc, BuildErrorType errorType);
629 
630 private:
631 	void					init				(void);
632 	IterateResult			iterate				(void);
633 	glu::ProgramSources		getProgramSources	(void) const;
634 
635 	const BuildErrorType	m_buildErrorType;
636 };
637 
ProgramLogCase(Context & ctx,const char * name,const char * desc,BuildErrorType errorType)638 ProgramLogCase::ProgramLogCase (Context& ctx, const char* name, const char* desc, BuildErrorType errorType)
639 	: TestCase			(ctx, name, desc)
640 	, m_buildErrorType	(errorType)
641 {
642 }
643 
init(void)644 void ProgramLogCase::init (void)
645 {
646 	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
647 
648 	switch (m_buildErrorType)
649 	{
650 		case BUILDERROR_VERTEX_FRAGMENT:
651 		case BUILDERROR_COMPUTE:
652 			break;
653 
654 		case BUILDERROR_GEOMETRY:
655 			if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
656 				TCU_THROW(NotSupportedError, "Test requires GL_EXT_geometry_shader extension");
657 			break;
658 
659 		case BUILDERROR_TESSELLATION:
660 			if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
661 				TCU_THROW(NotSupportedError, "Test requires GL_EXT_tessellation_shader extension");
662 			break;
663 
664 		default:
665 			DE_ASSERT(false);
666 			break;
667 	}
668 }
669 
iterate(void)670 ProgramLogCase::IterateResult ProgramLogCase::iterate (void)
671 {
672 	using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
673 
674 	tcu::ResultCollector					result		(m_testCtx.getLog());
675 	glu::CallLogWrapper						gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
676 	glu::ShaderProgram						program		(m_context.getRenderContext(), getProgramSources());
677 	StateQueryMemoryWriteGuard<glw::GLint>	logLen;
678 
679 	gl.enableLogging(true);
680 
681 	m_testCtx.getLog() << tcu::TestLog::Message << "Trying to link a broken program." << tcu::TestLog::EndMessage;
682 
683 	gl.glGetProgramiv(program.getProgram(), GL_INFO_LOG_LENGTH, &logLen);
684 	logLen.verifyValidity(result);
685 
686 	if (logLen.verifyValidity(result))
687 		verifyInfoLogQuery(result, gl, logLen, program.getProgram(), &glu::CallLogWrapper::glGetProgramInfoLog, "glGetProgramInfoLog");
688 
689 	result.setTestContextResult(m_testCtx);
690 	return STOP;
691 }
692 
getProgramSources(void) const693 glu::ProgramSources ProgramLogCase::getProgramSources (void) const
694 {
695 	const char* const	vertexTemplate1 =	"${GLSL_VERSION_DECL}\n"
696 											"in highp vec4 a_pos;\n"
697 											"uniform highp vec4 u_uniform;\n"
698 											"void main()\n"
699 											"{\n"
700 											"	gl_Position = a_pos + u_uniform;\n"
701 											"}\n";
702 	const char* const	vertexTemplate2 =	"${GLSL_VERSION_DECL}\n"
703 											"in highp vec4 a_pos;\n"
704 											"void main()\n"
705 											"{\n"
706 											"	gl_Position = a_pos;\n"
707 											"}\n";
708 	const char* const	fragmentTemplate1 =	"${GLSL_VERSION_DECL}\n"
709 											"in highp vec4 v_missingVar;\n"
710 											"uniform highp int u_uniform;\n"
711 											"layout(location = 0) out mediump vec4 fragColor;\n"
712 											"void main()\n"
713 											"{\n"
714 											"	fragColor = v_missingVar + vec4(float(u_uniform));\n"
715 											"}\n";
716 
717 	const char* const	fragmentTemplate2 =	"${GLSL_VERSION_DECL}\n"
718 											"layout(location = 0) out mediump vec4 fragColor;\n"
719 											"void main()\n"
720 											"{\n"
721 											"	fragColor = vec4(1.0);\n"
722 											"}\n";
723 	const char* const	computeTemplate1 =	"${GLSL_VERSION_DECL}\n"
724 											"layout (binding = 0) buffer IOBuffer { highp float buf_var; };\n"
725 											"uniform highp vec4 u_uniform;\n"
726 											"void main()\n"
727 											"{\n"
728 											"	buf_var = u_uniform.x;\n"
729 											"}\n";
730 	const char* const	geometryTemplate1 =	"${GLSL_VERSION_DECL}\n"
731 											"${GEOMETRY_SHADER_REQUIRE}\n"
732 											"layout(triangles) in;\n"
733 											"layout(max_vertices=1, points) out;\n"
734 											"in highp vec4 v_missingVar[];\n"
735 											"uniform highp int u_uniform;\n"
736 											"void main()\n"
737 											"{\n"
738 											"	gl_Position = gl_in[0].gl_Position + v_missingVar[2] + vec4(float(u_uniform));\n"
739 											"	EmitVertex();\n"
740 											"}\n";
741 	const char* const	tessCtrlTemplate1 =	"${GLSL_VERSION_DECL}\n"
742 											"${TESSELLATION_SHADER_REQUIRE}\n"
743 											"layout(vertices=2) out;"
744 											"patch out highp vec2 vp_var;\n"
745 											"void main()\n"
746 											"{\n"
747 											"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position\n"
748 											"	gl_TessLevelOuter[0] = 0.8;\n"
749 											"	gl_TessLevelOuter[1] = 0.8;\n"
750 											"	if (gl_InvocationID == 0)\n"
751 											"		vp_var = gl_in[gl_InvocationID].gl_Position.xy;\n"
752 											"}\n";
753 	const char* const	tessEvalTemplate1 =	"${GLSL_VERSION_DECL}\n"
754 											"${TESSELLATION_SHADER_REQUIRE}\n"
755 											"layout(isolines) in;"
756 											"in highp float vp_var[];\n"
757 											"void main()\n"
758 											"{\n"
759 											"	gl_Position = gl_in[gl_InvocationID].gl_Position + vec4(vp_var[1]);\n"
760 											"}\n";
761 
762 	switch (m_buildErrorType)
763 	{
764 		case BUILDERROR_VERTEX_FRAGMENT:
765 			return glu::ProgramSources()
766 					<< glu::VertexSource(specializeShader(m_context, vertexTemplate1))
767 					<< glu::FragmentSource(specializeShader(m_context, fragmentTemplate1));
768 
769 		case BUILDERROR_COMPUTE:
770 			return glu::ProgramSources()
771 					<< glu::ComputeSource(specializeShader(m_context, computeTemplate1));
772 
773 		case BUILDERROR_GEOMETRY:
774 			return glu::ProgramSources()
775 					<< glu::VertexSource(specializeShader(m_context, vertexTemplate1))
776 					<< glu::GeometrySource(specializeShader(m_context, geometryTemplate1))
777 					<< glu::FragmentSource(specializeShader(m_context, fragmentTemplate2));
778 
779 		case BUILDERROR_TESSELLATION:
780 			return glu::ProgramSources()
781 					<< glu::VertexSource(specializeShader(m_context, vertexTemplate2))
782 					<< glu::TessellationControlSource(specializeShader(m_context, tessCtrlTemplate1))
783 					<< glu::TessellationEvaluationSource(specializeShader(m_context, tessEvalTemplate1))
784 					<< glu::FragmentSource(specializeShader(m_context, fragmentTemplate2));
785 
786 		default:
787 			DE_ASSERT(false);
788 			return glu::ProgramSources();
789 	}
790 }
791 
792 } // anonymous
793 
ProgramStateQueryTests(Context & context)794 ProgramStateQueryTests::ProgramStateQueryTests (Context& context)
795 	: TestCaseGroup(context, "program", "Program State Query tests")
796 {
797 }
798 
~ProgramStateQueryTests(void)799 ProgramStateQueryTests::~ProgramStateQueryTests (void)
800 {
801 }
802 
init(void)803 void ProgramStateQueryTests::init (void)
804 {
805 	static const QueryType intVerifiers[] =
806 	{
807 		QUERY_PROGRAM_INTEGER,
808 	};
809 	static const QueryType intVec3Verifiers[] =
810 	{
811 		QUERY_PROGRAM_INTEGER_VEC3,
812 	};
813 
814 #define FOR_EACH_INT_VERIFIER(X) \
815 	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVerifiers); ++verifierNdx)	\
816 	{																							\
817 		const char* verifierSuffix = getVerifierSuffix(intVerifiers[verifierNdx]);				\
818 		const QueryType verifier = intVerifiers[verifierNdx];									\
819 		this->addChild(X);																		\
820 	}
821 
822 #define FOR_EACH_VEC_VERIFIER(X) \
823 	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVec3Verifiers); ++verifierNdx)	\
824 	{																								\
825 		const char* verifierSuffix = getVerifierSuffix(intVec3Verifiers[verifierNdx]);				\
826 		const QueryType verifier = intVec3Verifiers[verifierNdx];									\
827 		this->addChild(X);																			\
828 	}
829 
830 	FOR_EACH_INT_VERIFIER(new ProgramSeparableCase				(m_context, verifier, (std::string("program_separable_") + verifierSuffix).c_str(),				"Test PROGRAM_SEPARABLE"));
831 	FOR_EACH_VEC_VERIFIER(new ComputeWorkGroupSizeCase			(m_context, verifier, (std::string("compute_work_group_size_") + verifierSuffix).c_str(),		"Test COMPUTE_WORK_GROUP_SIZE"));
832 	FOR_EACH_INT_VERIFIER(new ActiveAtomicCounterBuffersCase	(m_context, verifier, (std::string("active_atomic_counter_buffers_") + verifierSuffix).c_str(),	"Test ACTIVE_ATOMIC_COUNTER_BUFFERS"));
833 	FOR_EACH_INT_VERIFIER(new GeometryShaderCase				(m_context, verifier, (std::string("geometry_shader_state_") + verifierSuffix).c_str(),			"Test Geometry Shader State"));
834 	FOR_EACH_INT_VERIFIER(new TessellationShaderCase			(m_context, verifier, (std::string("tesselation_shader_state_") + verifierSuffix).c_str(),		"Test Tesselation Shader State"));
835 
836 #undef FOR_EACH_INT_VERIFIER
837 #undef FOR_EACH_VEC_VERIFIER
838 
839 	// program info log tests
840 	// \note, there exists similar tests in gles3 module. However, the gles31 could use a different
841 	//        shader compiler with different INFO_LOG bugs.
842 	{
843 		static const struct
844 		{
845 			const char*						caseName;
846 			ProgramLogCase::BuildErrorType	caseType;
847 		} shaderTypes[] =
848 		{
849 			{ "info_log_vertex_fragment_link_fail",		ProgramLogCase::BUILDERROR_VERTEX_FRAGMENT	},
850 			{ "info_log_compute_link_fail",				ProgramLogCase::BUILDERROR_COMPUTE			},
851 			{ "info_log_geometry_link_fail",			ProgramLogCase::BUILDERROR_GEOMETRY			},
852 			{ "info_log_tessellation_link_fail",		ProgramLogCase::BUILDERROR_TESSELLATION		},
853 		};
854 
855 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
856 			addChild(new ProgramLogCase(m_context, shaderTypes[ndx].caseName, "", shaderTypes[ndx].caseType));
857 	}
858 }
859 
860 } // Functional
861 } // gles31
862 } // deqp
863