1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 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 Shader state query tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fShaderStateQueryTests.hpp"
25 #include "es31fInfoLogQueryShared.hpp"
26 #include "glsStateQueryUtil.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuStringTemplate.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "gluRenderContext.hpp"
31 #include "gluCallLogWrapper.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluStrUtil.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36 
37 namespace deqp
38 {
39 namespace gles31
40 {
41 namespace Functional
42 {
43 namespace
44 {
45 
46 static const char* const s_brokenSource =	"#version 310 es\n"
47 											"broken, this should not compile,\n"
48 											"{";
49 
50 class BaseTypeCase : public TestCase
51 {
52 public:
53 	struct TestTypeInfo
54 	{
55 		glw::GLenum	glType;
56 		const char*	declarationStr;
57 		const char*	accessStr;
58 	};
59 
60 										BaseTypeCase		(Context& ctx, const char* name, const char* desc, const char* extension);
61 
62 private:
63 	IterateResult						iterate				(void);
64 	virtual std::vector<TestTypeInfo>	getInfos			(void) const = 0;
65 	virtual void						checkRequirements	(void) const;
66 
67 	const char* const					m_extension;
68 };
69 
BaseTypeCase(Context & ctx,const char * name,const char * desc,const char * extension)70 BaseTypeCase::BaseTypeCase (Context& ctx, const char* name, const char* desc, const char* extension)
71 	: TestCase		(ctx, name, desc)
72 	, m_extension	(extension)
73 {
74 }
75 
iterate(void)76 BaseTypeCase::IterateResult BaseTypeCase::iterate (void)
77 {
78 	static const char* const	vertexSource			=	"#version 310 es\n"
79 															"in highp vec4 a_position;\n"
80 															"void main(void)\n"
81 															"{\n"
82 															"	gl_Position = a_position;\n"
83 															"}\n";
84 	static const char* const	fragmentSourceTemplate	=	"#version 310 es\n"
85 															"${EXTENSIONSTATEMENT}"
86 															"${DECLARATIONSTR};\n"
87 															"layout(location = 0) out highp vec4 dEQP_FragColor;\n"
88 															"void main(void)\n"
89 															"{\n"
90 															"	dEQP_FragColor = vec4(${ACCESSSTR});\n"
91 															"}\n";
92 
93 	tcu::ResultCollector		result			(m_testCtx.getLog());
94 	std::vector<TestTypeInfo>	samplerTypes	= getInfos();
95 
96 	if (m_extension && !m_context.getContextInfo().isExtensionSupported(m_extension))
97 		throw tcu::NotSupportedError("Test requires " + std::string(m_extension));
98 	checkRequirements();
99 
100 	for (int typeNdx = 0; typeNdx < (int)samplerTypes.size(); ++typeNdx)
101 	{
102 		const tcu::ScopedLogSection			section	(m_testCtx.getLog(),
103 													 std::string(glu::getShaderVarTypeStr(samplerTypes[typeNdx].glType).toString()),
104 													 "Uniform type " + glu::getShaderVarTypeStr(samplerTypes[typeNdx].glType).toString());
105 
106 		std::map<std::string, std::string>	shaderArgs;
107 		shaderArgs["DECLARATIONSTR"]		= samplerTypes[typeNdx].declarationStr;
108 		shaderArgs["ACCESSSTR"]				= samplerTypes[typeNdx].accessStr;
109 		shaderArgs["EXTENSIONSTATEMENT"]	= (m_extension) ? (std::string() + "#extension " + m_extension + " : require\n") : ("");
110 
111 		const std::string					fragmentSource	= tcu::StringTemplate(fragmentSourceTemplate).specialize(shaderArgs);
112 		const glw::Functions&				gl				= m_context.getRenderContext().getFunctions();
113 		glu::ShaderProgram					program			(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource));
114 
115 		m_testCtx.getLog() << tcu::TestLog::Message << "Building program with uniform sampler of type " << glu::getShaderVarTypeStr(samplerTypes[typeNdx].glType) << tcu::TestLog::EndMessage;
116 
117 		if (!program.isOk())
118 		{
119 			m_testCtx.getLog() << program;
120 			result.fail("could not build shader");
121 		}
122 		else
123 		{
124 			// only one uniform -- uniform at index 0
125 			int uniforms = 0;
126 			gl.getProgramiv(program.getProgram(), GL_ACTIVE_UNIFORMS, &uniforms);
127 
128 			if (uniforms != 1)
129 				result.fail("Unexpected GL_ACTIVE_UNIFORMS, expected 1");
130 			else
131 			{
132 				// check type
133 				const glw::GLuint	uniformIndex	= 0;
134 				glw::GLint			type			= 0;
135 
136 				m_testCtx.getLog() << tcu::TestLog::Message << "Verifying uniform type." << tcu::TestLog::EndMessage;
137 				gl.getActiveUniformsiv(program.getProgram(), 1, &uniformIndex, GL_UNIFORM_TYPE, &type);
138 
139 				if (type != (glw::GLint)samplerTypes[typeNdx].glType)
140 				{
141 					std::ostringstream buf;
142 					buf << "Invalid type, expected " << samplerTypes[typeNdx].glType << ", got " << type;
143 					result.fail(buf.str());
144 				}
145 			}
146 		}
147 
148 		GLU_EXPECT_NO_ERROR(gl.getError(), "");
149 	}
150 
151 	result.setTestContextResult(m_testCtx);
152 	return STOP;
153 }
154 
checkRequirements(void) const155 void BaseTypeCase::checkRequirements (void) const
156 {
157 }
158 
159 class CoreSamplerTypeCase : public BaseTypeCase
160 {
161 public:
162 								CoreSamplerTypeCase	(Context& ctx, const char* name, const char* desc);
163 
164 private:
165 	std::vector<TestTypeInfo>	getInfos			(void) const;
166 };
167 
CoreSamplerTypeCase(Context & ctx,const char * name,const char * desc)168 CoreSamplerTypeCase::CoreSamplerTypeCase (Context& ctx, const char* name, const char* desc)
169 	: BaseTypeCase(ctx, name, desc, DE_NULL)
170 {
171 }
172 
getInfos(void) const173 std::vector<BaseTypeCase::TestTypeInfo> CoreSamplerTypeCase::getInfos (void) const
174 {
175 	static const TestTypeInfo samplerTypes[] =
176 	{
177 		{ GL_SAMPLER_2D_MULTISAMPLE,				"uniform highp sampler2DMS u_sampler",	"texelFetch(u_sampler, ivec2(gl_FragCoord.xy), 0)" },
178 		{ GL_INT_SAMPLER_2D_MULTISAMPLE,			"uniform highp isampler2DMS u_sampler",	"texelFetch(u_sampler, ivec2(gl_FragCoord.xy), 0)" },
179 		{ GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE,	"uniform highp usampler2DMS u_sampler",	"texelFetch(u_sampler, ivec2(gl_FragCoord.xy), 0)" },
180 	};
181 
182 	std::vector<TestTypeInfo> infos;
183 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
184 		infos.push_back(samplerTypes[ndx]);
185 
186 	return infos;
187 }
188 
189 class MSArraySamplerTypeCase : public BaseTypeCase
190 {
191 public:
192 								MSArraySamplerTypeCase	(Context& ctx, const char* name, const char* desc);
193 
194 private:
195 	std::vector<TestTypeInfo>	getInfos				(void) const;
196 };
197 
MSArraySamplerTypeCase(Context & ctx,const char * name,const char * desc)198 MSArraySamplerTypeCase::MSArraySamplerTypeCase (Context& ctx, const char* name, const char* desc)
199 	: BaseTypeCase(ctx, name, desc, "GL_OES_texture_storage_multisample_2d_array")
200 {
201 }
202 
getInfos(void) const203 std::vector<BaseTypeCase::TestTypeInfo> MSArraySamplerTypeCase::getInfos (void) const
204 {
205 	static const TestTypeInfo samplerTypes[] =
206 	{
207 		{ GL_SAMPLER_2D_MULTISAMPLE_ARRAY,				"uniform highp sampler2DMSArray u_sampler",		"texelFetch(u_sampler, ivec3(gl_FragCoord.xyz), 0)" },
208 		{ GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,			"uniform highp isampler2DMSArray u_sampler",	"texelFetch(u_sampler, ivec3(gl_FragCoord.xyz), 0)" },
209 		{ GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,	"uniform highp usampler2DMSArray u_sampler",	"texelFetch(u_sampler, ivec3(gl_FragCoord.xyz), 0)" },
210 	};
211 
212 	std::vector<TestTypeInfo> infos;
213 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
214 		infos.push_back(samplerTypes[ndx]);
215 
216 	return infos;
217 }
218 
219 class TextureBufferSamplerTypeCase : public BaseTypeCase
220 {
221 public:
222 								TextureBufferSamplerTypeCase	(Context& ctx, const char* name, const char* desc);
223 
224 private:
225 	std::vector<TestTypeInfo>	getInfos						(void) const;
226 };
227 
TextureBufferSamplerTypeCase(Context & ctx,const char * name,const char * desc)228 TextureBufferSamplerTypeCase::TextureBufferSamplerTypeCase (Context& ctx, const char* name, const char* desc)
229 	: BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer")
230 {
231 }
232 
getInfos(void) const233 std::vector<BaseTypeCase::TestTypeInfo> TextureBufferSamplerTypeCase::getInfos (void) const
234 {
235 	static const TestTypeInfo samplerTypes[] =
236 	{
237 		{ GL_SAMPLER_BUFFER,				"uniform highp samplerBuffer u_sampler",	"texelFetch(u_sampler, int(gl_FragCoord.x))" },
238 		{ GL_INT_SAMPLER_BUFFER,			"uniform highp isamplerBuffer u_sampler",	"texelFetch(u_sampler, int(gl_FragCoord.x))" },
239 		{ GL_UNSIGNED_INT_SAMPLER_BUFFER,	"uniform highp usamplerBuffer u_sampler",	"texelFetch(u_sampler, int(gl_FragCoord.x))" },
240 	};
241 
242 	std::vector<TestTypeInfo> infos;
243 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
244 		infos.push_back(samplerTypes[ndx]);
245 
246 	return infos;
247 }
248 
249 class TextureBufferImageTypeCase : public BaseTypeCase
250 {
251 public:
252 								TextureBufferImageTypeCase	(Context& ctx, const char* name, const char* desc);
253 
254 private:
255 	std::vector<TestTypeInfo>	getInfos					(void) const;
256 	void						checkRequirements			(void) const;
257 };
258 
TextureBufferImageTypeCase(Context & ctx,const char * name,const char * desc)259 TextureBufferImageTypeCase::TextureBufferImageTypeCase (Context& ctx, const char* name, const char* desc)
260 	: BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer")
261 {
262 }
263 
getInfos(void) const264 std::vector<BaseTypeCase::TestTypeInfo> TextureBufferImageTypeCase::getInfos (void) const
265 {
266 	static const TestTypeInfo samplerTypes[] =
267 	{
268 		{ GL_IMAGE_BUFFER,				"layout(binding=0, rgba8) readonly uniform highp imageBuffer u_image",	"imageLoad(u_image, int(gl_FragCoord.x))" },
269 		{ GL_INT_IMAGE_BUFFER,			"layout(binding=0, r32i) readonly uniform highp iimageBuffer u_image",	"imageLoad(u_image, int(gl_FragCoord.x))" },
270 		{ GL_UNSIGNED_INT_IMAGE_BUFFER,	"layout(binding=0, r32ui) readonly uniform highp uimageBuffer u_image",	"imageLoad(u_image, int(gl_FragCoord.x))" },
271 	};
272 
273 	std::vector<TestTypeInfo> infos;
274 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
275 		infos.push_back(samplerTypes[ndx]);
276 
277 	return infos;
278 }
279 
checkRequirements(void) const280 void TextureBufferImageTypeCase::checkRequirements (void) const
281 {
282 	if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) < 1)
283 		throw tcu::NotSupportedError("Test requires fragment images");
284 }
285 
286 class CubeArraySamplerTypeCase : public BaseTypeCase
287 {
288 public:
289 								CubeArraySamplerTypeCase	(Context& ctx, const char* name, const char* desc);
290 
291 private:
292 	std::vector<TestTypeInfo>	getInfos						(void) const;
293 };
294 
CubeArraySamplerTypeCase(Context & ctx,const char * name,const char * desc)295 CubeArraySamplerTypeCase::CubeArraySamplerTypeCase (Context& ctx, const char* name, const char* desc)
296 	: BaseTypeCase(ctx, name, desc, "GL_EXT_texture_cube_map_array")
297 {
298 }
299 
getInfos(void) const300 std::vector<BaseTypeCase::TestTypeInfo> CubeArraySamplerTypeCase::getInfos (void) const
301 {
302 	static const TestTypeInfo samplerTypes[] =
303 	{
304 		{ GL_SAMPLER_CUBE_MAP_ARRAY,				"uniform highp samplerCubeArray u_sampler",			"texture(u_sampler, gl_FragCoord.xxyz)"			},
305 		{ GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW,			"uniform highp samplerCubeArrayShadow u_sampler",	"texture(u_sampler, gl_FragCoord.xxyz, 0.5)"	},
306 		{ GL_INT_SAMPLER_CUBE_MAP_ARRAY,			"uniform highp isamplerCubeArray u_sampler",		"texture(u_sampler, gl_FragCoord.xxyz)"			},
307 		{ GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY,	"uniform highp usamplerCubeArray u_sampler",		"texture(u_sampler, gl_FragCoord.xxyz)"			},
308 	};
309 
310 	std::vector<TestTypeInfo> infos;
311 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
312 		infos.push_back(samplerTypes[ndx]);
313 
314 	return infos;
315 }
316 
317 class CubeArrayImageTypeCase : public BaseTypeCase
318 {
319 public:
320 								CubeArrayImageTypeCase	(Context& ctx, const char* name, const char* desc);
321 
322 private:
323 	std::vector<TestTypeInfo>	getInfos				(void) const;
324 	void						checkRequirements		(void) const;
325 };
326 
CubeArrayImageTypeCase(Context & ctx,const char * name,const char * desc)327 CubeArrayImageTypeCase::CubeArrayImageTypeCase (Context& ctx, const char* name, const char* desc)
328 	: BaseTypeCase(ctx, name, desc, "GL_EXT_texture_cube_map_array")
329 {
330 }
331 
getInfos(void) const332 std::vector<BaseTypeCase::TestTypeInfo> CubeArrayImageTypeCase::getInfos (void) const
333 {
334 	static const TestTypeInfo samplerTypes[] =
335 	{
336 		{ GL_IMAGE_CUBE_MAP_ARRAY,				"layout(binding=0, rgba8) readonly uniform highp imageCubeArray u_image",	"imageLoad(u_image, ivec3(gl_FragCoord.xyx))"	},
337 		{ GL_INT_IMAGE_CUBE_MAP_ARRAY,			"layout(binding=0, r32i) readonly uniform highp iimageCubeArray u_image",	"imageLoad(u_image, ivec3(gl_FragCoord.xyx))"	},
338 		{ GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY,	"layout(binding=0, r32ui) readonly uniform highp uimageCubeArray u_image",	"imageLoad(u_image, ivec3(gl_FragCoord.xyx))"	},
339 	};
340 
341 	std::vector<TestTypeInfo> infos;
342 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
343 		infos.push_back(samplerTypes[ndx]);
344 
345 	return infos;
346 }
347 
checkRequirements(void) const348 void CubeArrayImageTypeCase::checkRequirements (void) const
349 {
350 	if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) < 1)
351 		throw tcu::NotSupportedError("Test requires fragment images");
352 }
353 
354 class ShaderLogCase : public TestCase
355 {
356 public:
357 							ShaderLogCase	(Context& ctx, const char* name, const char* desc, glu::ShaderType shaderType);
358 
359 private:
360 	void					init			(void);
361 	IterateResult			iterate			(void);
362 
363 	const glu::ShaderType	m_shaderType;
364 };
365 
ShaderLogCase(Context & ctx,const char * name,const char * desc,glu::ShaderType shaderType)366 ShaderLogCase::ShaderLogCase (Context& ctx, const char* name, const char* desc, glu::ShaderType shaderType)
367 	: TestCase		(ctx, name, desc)
368 	, m_shaderType	(shaderType)
369 {
370 }
371 
init(void)372 void ShaderLogCase::init (void)
373 {
374 	switch (m_shaderType)
375 	{
376 		case glu::SHADERTYPE_VERTEX:
377 		case glu::SHADERTYPE_FRAGMENT:
378 		case glu::SHADERTYPE_COMPUTE:
379 			break;
380 
381 		case glu::SHADERTYPE_GEOMETRY:
382 			if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
383 				throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
384 			break;
385 
386 		case glu::SHADERTYPE_TESSELLATION_CONTROL:
387 		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
388 			if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
389 				throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
390 			break;
391 
392 		default:
393 			DE_ASSERT(false);
394 			break;
395 	}
396 }
397 
iterate(void)398 ShaderLogCase::IterateResult ShaderLogCase::iterate (void)
399 {
400 	using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
401 
402 	tcu::ResultCollector					result		(m_testCtx.getLog());
403 	glu::CallLogWrapper						gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
404 	deUint32								shader		= 0;
405 	StateQueryMemoryWriteGuard<glw::GLint>	logLen;
406 
407 	gl.enableLogging(true);
408 
409 	m_testCtx.getLog() << tcu::TestLog::Message << "Trying to compile broken shader source." << tcu::TestLog::EndMessage;
410 
411 	shader = gl.glCreateShader(glu::getGLShaderType(m_shaderType));
412 	GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "create shader");
413 
414 	gl.glShaderSource(shader, 1, &s_brokenSource, DE_NULL);
415 	gl.glCompileShader(shader);
416 	GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "compile");
417 
418 	gl.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLen);
419 	logLen.verifyValidity(result);
420 
421 	if (!logLen.isUndefined())
422 		verifyInfoLogQuery(result, gl, logLen, shader, &glu::CallLogWrapper::glGetShaderInfoLog, "glGetShaderInfoLog");
423 
424 	gl.glDeleteShader(shader);
425 	GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "delete");
426 
427 	result.setTestContextResult(m_testCtx);
428 	return STOP;
429 }
430 
431 } // anonymous
432 
ShaderStateQueryTests(Context & context)433 ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
434 	: TestCaseGroup(context, "shader", "Shader state query tests")
435 {
436 }
437 
~ShaderStateQueryTests(void)438 ShaderStateQueryTests::~ShaderStateQueryTests (void)
439 {
440 }
441 
init(void)442 void ShaderStateQueryTests::init (void)
443 {
444 	addChild(new CoreSamplerTypeCase			(m_context, "sampler_type",						"Sampler type cases"));
445 	addChild(new MSArraySamplerTypeCase			(m_context, "sampler_type_multisample_array",	"MSAA array sampler type cases"));
446 	addChild(new TextureBufferSamplerTypeCase	(m_context, "sampler_type_texture_buffer",		"Texture buffer sampler type cases"));
447 	addChild(new TextureBufferImageTypeCase		(m_context, "image_type_texture_buffer",		"Texture buffer image type cases"));
448 	addChild(new CubeArraySamplerTypeCase		(m_context, "sampler_type_cube_array",			"Cube array sampler type cases"));
449 	addChild(new CubeArrayImageTypeCase			(m_context, "image_type_cube_array",			"Cube array image type cases"));
450 
451 	// shader info log tests
452 	// \note, there exists similar tests in gles3 module. However, the gles31 could use a different
453 	//        shader compiler with different INFO_LOG bugs.
454 	{
455 		static const struct
456 		{
457 			const char*		caseName;
458 			glu::ShaderType	caseType;
459 		} shaderTypes[] =
460 		{
461 			{ "info_log_vertex",		glu::SHADERTYPE_VERTEX					},
462 			{ "info_log_fragment",		glu::SHADERTYPE_FRAGMENT				},
463 			{ "info_log_geometry",		glu::SHADERTYPE_GEOMETRY				},
464 			{ "info_log_tess_ctrl",		glu::SHADERTYPE_TESSELLATION_CONTROL	},
465 			{ "info_log_tess_eval",		glu::SHADERTYPE_TESSELLATION_EVALUATION	},
466 			{ "info_log_compute",		glu::SHADERTYPE_COMPUTE					},
467 		};
468 
469 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
470 			addChild(new ShaderLogCase(m_context, shaderTypes[ndx].caseName, "", shaderTypes[ndx].caseType));
471 	}
472 }
473 
474 } // Functional
475 } // gles31
476 } // deqp
477