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 
35 namespace deqp
36 {
37 namespace gles31
38 {
39 namespace Functional
40 {
41 namespace
42 {
43 
44 using namespace gls::StateQueryUtil;
45 
getVerifierSuffix(QueryType type)46 static const char* getVerifierSuffix (QueryType type)
47 {
48 	switch (type)
49 	{
50 		case QUERY_PROGRAM_INTEGER_VEC3:
51 		case QUERY_PROGRAM_INTEGER:
52 			return "get_programiv";
53 
54 		default:
55 			DE_ASSERT(DE_FALSE);
56 			return DE_NULL;
57 	}
58 }
59 
60 class ProgramSeparableCase : public TestCase
61 {
62 public:
63 						ProgramSeparableCase	(Context& context, QueryType verifier, const char* name, const char* desc);
64 	IterateResult		iterate					(void);
65 
66 private:
67 	const QueryType		m_verifier;
68 };
69 
ProgramSeparableCase(Context & context,QueryType verifier,const char * name,const char * desc)70 ProgramSeparableCase::ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc)
71 	: TestCase		(context, name, desc)
72 	, m_verifier	(verifier)
73 {
74 }
75 
iterate(void)76 ProgramSeparableCase::IterateResult ProgramSeparableCase::iterate (void)
77 {
78 	static const char* const s_vertexSource = 	"#version 310 es\n"
79 												"out highp vec4 v_color;\n"
80 												"void main()\n"
81 												"{\n"
82 												"	gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n"
83 												"	v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n"
84 												"}\n";
85 	static const char* const s_fragmentSource = "#version 310 es\n"
86 												"in highp vec4 v_color;\n"
87 												"layout(location=0) out highp vec4 o_color;\n"
88 												"void main()\n"
89 												"{\n"
90 												"	o_color = v_color;\n"
91 												"}\n";
92 
93 	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
94 	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
95 	glu::Shader				vtxShader	(m_context.getRenderContext(), glu::SHADERTYPE_VERTEX);
96 	glu::Shader				frgShader	(m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
97 
98 	vtxShader.setSources(1, &s_vertexSource, DE_NULL);
99 	frgShader.setSources(1, &s_fragmentSource, DE_NULL);
100 
101 	vtxShader.compile();
102 	frgShader.compile();
103 
104 	{
105 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxShader", "Vertex shader");
106 		m_testCtx.getLog() << vtxShader;
107 	}
108 
109 	{
110 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgShader", "Fragment shader");
111 		m_testCtx.getLog() << frgShader;
112 	}
113 
114 	if (!vtxShader.getCompileStatus() || !frgShader.getCompileStatus())
115 		throw tcu::TestError("failed to build shaders");
116 
117 	gl.enableLogging(true);
118 
119 	{
120 		const tcu::ScopedLogSection	section	(m_testCtx.getLog(), "Initial", "Initial");
121 		glu::Program				program	(m_context.getRenderContext());
122 
123 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
124 	}
125 
126 	{
127 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "SetFalse", "SetFalse");
128 		glu::Program				program		(m_context.getRenderContext());
129 		int							linkStatus	= 0;
130 
131 		gl.glAttachShader(program.getProgram(), vtxShader.getShader());
132 		gl.glAttachShader(program.getProgram(), frgShader.getShader());
133 		gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
134 		gl.glLinkProgram(program.getProgram());
135 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
136 
137 		gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
138 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
139 
140 		if (linkStatus == GL_FALSE)
141 			throw tcu::TestError("failed to link program");
142 
143 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
144 	}
145 
146 	{
147 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "SetTrue", "SetTrue");
148 		glu::Program				program		(m_context.getRenderContext());
149 		int							linkStatus	= 0;
150 
151 		gl.glAttachShader(program.getProgram(), vtxShader.getShader());
152 		gl.glAttachShader(program.getProgram(), frgShader.getShader());
153 		gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
154 		gl.glLinkProgram(program.getProgram());
155 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
156 
157 		gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
158 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
159 
160 		if (linkStatus == GL_FALSE)
161 			throw tcu::TestError("failed to link program");
162 
163 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE, m_verifier);
164 	}
165 
166 	result.setTestContextResult(m_testCtx);
167 	return STOP;
168 }
169 
170 class ComputeWorkGroupSizeCase : public TestCase
171 {
172 public:
173 						ComputeWorkGroupSizeCase	(Context& context, QueryType verifier, const char* name, const char* desc);
174 	IterateResult		iterate						(void);
175 
176 private:
177 	const QueryType		m_verifier;
178 };
179 
ComputeWorkGroupSizeCase(Context & context,QueryType verifier,const char * name,const char * desc)180 ComputeWorkGroupSizeCase::ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc)
181 	: TestCase		(context, name, desc)
182 	, m_verifier	(verifier)
183 {
184 }
185 
iterate(void)186 ComputeWorkGroupSizeCase::IterateResult ComputeWorkGroupSizeCase::iterate (void)
187 {
188 	static const char* const s_computeSource1D =	"#version 310 es\n"
189 													"layout (local_size_x = 3) in;\n"
190 													"layout(binding = 0) buffer Output\n"
191 													"{\n"
192 													"	highp float val;\n"
193 													"} sb_out;\n"
194 													"\n"
195 													"void main (void)\n"
196 													"{\n"
197 													"	sb_out.val = 1.0;\n"
198 													"}\n";
199 	static const char* const s_computeSource2D =	"#version 310 es\n"
200 													"layout (local_size_x = 3, local_size_y = 2) in;\n"
201 													"layout(binding = 0) buffer Output\n"
202 													"{\n"
203 													"	highp float val;\n"
204 													"} sb_out;\n"
205 													"\n"
206 													"void main (void)\n"
207 													"{\n"
208 													"	sb_out.val = 1.0;\n"
209 													"}\n";
210 	static const char* const s_computeSource3D =	"#version 310 es\n"
211 													"layout (local_size_x = 3, local_size_y = 2, local_size_z = 4) in;\n"
212 													"layout(binding = 0) buffer Output\n"
213 													"{\n"
214 													"	highp float val;\n"
215 													"} sb_out;\n"
216 													"\n"
217 													"void main (void)\n"
218 													"{\n"
219 													"	sb_out.val = 1.0;\n"
220 													"}\n";
221 
222 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
223 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
224 
225 	gl.enableLogging(true);
226 
227 	{
228 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "OneDimensional", "1D");
229 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource1D));
230 
231 		m_testCtx.getLog() << program;
232 		if (!program.isOk())
233 			throw tcu::TestError("failed to build program");
234 
235 		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 1, 1), m_verifier);
236 	}
237 
238 	{
239 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "TwoDimensional", "2D");
240 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource2D));
241 
242 		m_testCtx.getLog() << program;
243 		if (!program.isOk())
244 			throw tcu::TestError("failed to build program");
245 
246 		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 1), m_verifier);
247 	}
248 
249 	{
250 		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "TreeDimensional", "3D");
251 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource3D));
252 
253 		m_testCtx.getLog() << program;
254 		if (!program.isOk())
255 			throw tcu::TestError("failed to build program");
256 
257 		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 4), m_verifier);
258 	}
259 
260 	result.setTestContextResult(m_testCtx);
261 	return STOP;
262 }
263 
264 class ActiveAtomicCounterBuffersCase : public TestCase
265 {
266 public:
267 						ActiveAtomicCounterBuffersCase	(Context& context, QueryType verifier, const char* name, const char* desc);
268 	IterateResult		iterate							(void);
269 
270 private:
271 	const QueryType		m_verifier;
272 };
273 
ActiveAtomicCounterBuffersCase(Context & context,QueryType verifier,const char * name,const char * desc)274 ActiveAtomicCounterBuffersCase::ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc)
275 	: TestCase		(context, name, desc)
276 	, m_verifier	(verifier)
277 {
278 }
279 
iterate(void)280 ActiveAtomicCounterBuffersCase::IterateResult ActiveAtomicCounterBuffersCase::iterate (void)
281 {
282 	static const char* const s_computeSource0 =	"#version 310 es\n"
283 												"layout (local_size_x = 3) in;\n"
284 												"layout(binding = 0) buffer Output\n"
285 												"{\n"
286 												"	highp float val;\n"
287 												"} sb_out;\n"
288 												"\n"
289 												"void main (void)\n"
290 												"{\n"
291 												"	sb_out.val = 1.0;\n"
292 												"}\n";
293 	static const char* const s_computeSource1 =	"#version 310 es\n"
294 												"layout (local_size_x = 3) in;\n"
295 												"layout(binding = 0) uniform highp atomic_uint u_counters[2];\n"
296 												"layout(binding = 0) buffer Output\n"
297 												"{\n"
298 												"	highp float val;\n"
299 												"} sb_out;\n"
300 												"\n"
301 												"void main (void)\n"
302 												"{\n"
303 												"	sb_out.val = float(atomicCounterIncrement(u_counters[0])) + float(atomicCounterIncrement(u_counters[1]));\n"
304 												"}\n";
305 
306 	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
307 	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
308 
309 	gl.enableLogging(true);
310 
311 	{
312 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Initial", "Initial");
313 		glu::Program				program		(m_context.getRenderContext());
314 
315 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
316 	}
317 
318 	{
319 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "NoBuffers", "No buffers");
320 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource0));
321 
322 		m_testCtx.getLog() << program;
323 		if (!program.isOk())
324 			throw tcu::TestError("failed to build program");
325 
326 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
327 	}
328 
329 	{
330 		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "OneBuffer", "One buffer");
331 		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource1));
332 
333 		m_testCtx.getLog() << program;
334 		if (!program.isOk())
335 			throw tcu::TestError("failed to build program");
336 
337 		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 1, m_verifier);
338 	}
339 
340 	result.setTestContextResult(m_testCtx);
341 	return STOP;
342 }
343 
344 class ProgramLogCase : public TestCase
345 {
346 public:
347 	enum BuildErrorType
348 	{
349 		BUILDERROR_VERTEX_FRAGMENT = 0,
350 		BUILDERROR_COMPUTE,
351 		BUILDERROR_GEOMETRY,
352 		BUILDERROR_TESSELLATION,
353 	};
354 
355 							ProgramLogCase		(Context& ctx, const char* name, const char* desc, BuildErrorType errorType);
356 
357 private:
358 	void					init				(void);
359 	IterateResult			iterate				(void);
360 	glu::ProgramSources		getProgramSources	(void) const;
361 
362 	const BuildErrorType	m_buildErrorType;
363 };
364 
ProgramLogCase(Context & ctx,const char * name,const char * desc,BuildErrorType errorType)365 ProgramLogCase::ProgramLogCase (Context& ctx, const char* name, const char* desc, BuildErrorType errorType)
366 	: TestCase			(ctx, name, desc)
367 	, m_buildErrorType	(errorType)
368 {
369 }
370 
init(void)371 void ProgramLogCase::init (void)
372 {
373 	switch (m_buildErrorType)
374 	{
375 		case BUILDERROR_VERTEX_FRAGMENT:
376 		case BUILDERROR_COMPUTE:
377 			break;
378 
379 		case BUILDERROR_GEOMETRY:
380 			if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
381 				throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
382 			break;
383 
384 		case BUILDERROR_TESSELLATION:
385 			if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
386 				throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
387 			break;
388 
389 		default:
390 			DE_ASSERT(false);
391 			break;
392 	}
393 }
394 
iterate(void)395 ProgramLogCase::IterateResult ProgramLogCase::iterate (void)
396 {
397 	using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
398 
399 	tcu::ResultCollector					result		(m_testCtx.getLog());
400 	glu::CallLogWrapper						gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
401 	glu::ShaderProgram						program		(m_context.getRenderContext(), getProgramSources());
402 	StateQueryMemoryWriteGuard<glw::GLint>	logLen;
403 
404 	gl.enableLogging(true);
405 
406 	m_testCtx.getLog() << tcu::TestLog::Message << "Trying to link a broken program." << tcu::TestLog::EndMessage;
407 
408 	gl.glGetProgramiv(program.getProgram(), GL_INFO_LOG_LENGTH, &logLen);
409 	logLen.verifyValidity(result);
410 
411 	if (logLen.verifyValidity(result))
412 		verifyInfoLogQuery(result, gl, logLen, program.getProgram(), &glu::CallLogWrapper::glGetProgramInfoLog, "glGetProgramInfoLog");
413 
414 	result.setTestContextResult(m_testCtx);
415 	return STOP;
416 }
417 
getProgramSources(void) const418 glu::ProgramSources ProgramLogCase::getProgramSources (void) const
419 {
420 	switch (m_buildErrorType)
421 	{
422 		case BUILDERROR_VERTEX_FRAGMENT:
423 			return glu::ProgramSources()
424 					<< glu::VertexSource("#version 310 es\n"
425 										 "in highp vec4 a_pos;\n"
426 										 "uniform highp vec4 u_uniform;\n"
427 										 "void main()\n"
428 										 "{\n"
429 										 "	gl_Position = a_pos + u_uniform;\n"
430 										 "}\n")
431 					<< glu::FragmentSource("#version 310 es\n"
432 										   "in highp vec4 v_missingVar;\n"
433 										   "uniform highp int u_uniform;\n"
434 										   "layout(location = 0) out mediump vec4 fragColor;\n"
435 										   "void main()\n"
436 										   "{\n"
437 										   "	fragColor = v_missingVar + vec4(float(u_uniform));\n"
438 										   "}\n");
439 
440 		case BUILDERROR_COMPUTE:
441 			return glu::ProgramSources()
442 					<< glu::ComputeSource("#version 310 es\n"
443 										 "layout (binding = 0) buffer IOBuffer { highp float buf_var; };\n"
444 										 "uniform highp vec4 u_uniform;\n"
445 										 "void main()\n"
446 										 "{\n"
447 										 "	buf_var = u_uniform.x;\n"
448 										 "}\n");
449 
450 		case BUILDERROR_GEOMETRY:
451 			return glu::ProgramSources()
452 					<< glu::VertexSource("#version 310 es\n"
453 										 "in highp vec4 a_pos;\n"
454 										 "uniform highp vec4 u_uniform;\n"
455 										 "void main()\n"
456 										 "{\n"
457 										 "	gl_Position = a_pos + u_uniform;\n"
458 										 "}\n")
459 					<< glu::GeometrySource("#version 310 es\n"
460 										   "#extension GL_EXT_geometry_shader : require\n"
461 										   "layout(triangles) in;\n"
462 										   "layout(max_vertices=1, points) out;\n"
463 										   "in highp vec4 v_missingVar[];\n"
464 										   "uniform highp int u_uniform;\n"
465 										   "void main()\n"
466 										   "{\n"
467 										   "	gl_Position = gl_in[0].gl_Position + v_missingVar[2] + vec4(float(u_uniform));\n"
468 										   "	EmitVertex();\n"
469 										   "}\n")
470 					<< glu::FragmentSource("#version 310 es\n"
471 										   "layout(location = 0) out mediump vec4 fragColor;\n"
472 										   "void main()\n"
473 										   "{\n"
474 										   "	fragColor = vec4(1.0);\n"
475 										   "}\n");
476 
477 		case BUILDERROR_TESSELLATION:
478 			return glu::ProgramSources()
479 					<< glu::VertexSource("#version 310 es\n"
480 										 "in highp vec4 a_pos;\n"
481 										 "void main()\n"
482 										 "{\n"
483 										 "	gl_Position = a_pos;\n"
484 										 "}\n")
485 					<< glu::TessellationControlSource("#version 310 es\n"
486 													  "#extension GL_EXT_tessellation_shader : require\n"
487 													  "layout(vertices=2) out;"
488 													  "patch out highp vec2 vp_var;\n"
489 													  "void main()\n"
490 													  "{\n"
491 													  "	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position\n"
492 													  "	gl_TessLevelOuter[0] = 0.8;\n"
493 													  "	gl_TessLevelOuter[1] = 0.8;\n"
494 													  "	if (gl_InvocationID == 0)\n"
495 													  "		vp_var = gl_in[gl_InvocationID].gl_Position.xy;\n"
496 													  "}\n")
497 					<< glu::TessellationEvaluationSource("#version 310 es\n"
498 														 "#extension GL_EXT_tessellation_shader : require\n"
499 														 "layout(isolines) in;"
500 														 "in highp float vp_var[];\n"
501 														 "void main()\n"
502 														 "{\n"
503 														 "	gl_Position = gl_in[gl_InvocationID].gl_Position + vec4(vp_var[1]);\n"
504 														 "}\n")
505 					<< glu::FragmentSource("#version 310 es\n"
506 										   "layout(location = 0) out mediump vec4 fragColor;\n"
507 										   "void main()\n"
508 										   "{\n"
509 										   "	fragColor = vec4(1.0);\n"
510 										   "}\n");
511 
512 		default:
513 			DE_ASSERT(false);
514 			return glu::ProgramSources();
515 	}
516 }
517 
518 } // anonymous
519 
ProgramStateQueryTests(Context & context)520 ProgramStateQueryTests::ProgramStateQueryTests (Context& context)
521 	: TestCaseGroup(context, "program", "Program State Query tests")
522 {
523 }
524 
~ProgramStateQueryTests(void)525 ProgramStateQueryTests::~ProgramStateQueryTests (void)
526 {
527 }
528 
init(void)529 void ProgramStateQueryTests::init (void)
530 {
531 	static const QueryType intVerifiers[] =
532 	{
533 		QUERY_PROGRAM_INTEGER,
534 	};
535 	static const QueryType intVec3Verifiers[] =
536 	{
537 		QUERY_PROGRAM_INTEGER_VEC3,
538 	};
539 
540 #define FOR_EACH_INT_VERIFIER(X) \
541 	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVerifiers); ++verifierNdx)	\
542 	{																							\
543 		const char* verifierSuffix = getVerifierSuffix(intVerifiers[verifierNdx]);				\
544 		const QueryType verifier = intVerifiers[verifierNdx];									\
545 		this->addChild(X);																		\
546 	}
547 
548 #define FOR_EACH_VEC_VERIFIER(X) \
549 	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVec3Verifiers); ++verifierNdx)	\
550 	{																								\
551 		const char* verifierSuffix = getVerifierSuffix(intVec3Verifiers[verifierNdx]);				\
552 		const QueryType verifier = intVec3Verifiers[verifierNdx];									\
553 		this->addChild(X);																			\
554 	}
555 
556 	FOR_EACH_INT_VERIFIER(new ProgramSeparableCase				(m_context, verifier, (std::string("program_separable_") + verifierSuffix).c_str(),				"Test PROGRAM_SEPARABLE"));
557 	FOR_EACH_VEC_VERIFIER(new ComputeWorkGroupSizeCase			(m_context, verifier, (std::string("compute_work_group_size_") + verifierSuffix).c_str(),		"Test COMPUTE_WORK_GROUP_SIZE"));
558 	FOR_EACH_INT_VERIFIER(new ActiveAtomicCounterBuffersCase	(m_context, verifier, (std::string("active_atomic_counter_buffers_") + verifierSuffix).c_str(),	"Test ACTIVE_ATOMIC_COUNTER_BUFFERS"));
559 
560 #undef FOR_EACH_INT_VERIFIER
561 #undef FOR_EACH_VEC_VERIFIER
562 
563 	// program info log tests
564 	// \note, there exists similar tests in gles3 module. However, the gles31 could use a different
565 	//        shader compiler with different INFO_LOG bugs.
566 	{
567 		static const struct
568 		{
569 			const char*						caseName;
570 			ProgramLogCase::BuildErrorType	caseType;
571 		} shaderTypes[] =
572 		{
573 			{ "info_log_vertex_fragment_link_fail",		ProgramLogCase::BUILDERROR_VERTEX_FRAGMENT	},
574 			{ "info_log_compute_link_fail",				ProgramLogCase::BUILDERROR_COMPUTE			},
575 			{ "info_log_geometry_link_fail",			ProgramLogCase::BUILDERROR_GEOMETRY			},
576 			{ "info_log_tessellation_link_fail",		ProgramLogCase::BUILDERROR_TESSELLATION		},
577 		};
578 
579 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
580 			addChild(new ProgramLogCase(m_context, shaderTypes[ndx].caseName, "", shaderTypes[ndx].caseType));
581 	}
582 }
583 
584 } // Functional
585 } // gles31
586 } // deqp
587