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