Home | History | Annotate | Download | only in functional
      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 
     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 
     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 
    155 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 
    168 CoreSamplerTypeCase::CoreSamplerTypeCase (Context& ctx, const char* name, const char* desc)
    169 	: BaseTypeCase(ctx, name, desc, DE_NULL)
    170 {
    171 }
    172 
    173 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 
    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 
    203 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 
    228 TextureBufferSamplerTypeCase::TextureBufferSamplerTypeCase (Context& ctx, const char* name, const char* desc)
    229 	: BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer")
    230 {
    231 }
    232 
    233 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 
    259 TextureBufferImageTypeCase::TextureBufferImageTypeCase (Context& ctx, const char* name, const char* desc)
    260 	: BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer")
    261 {
    262 }
    263 
    264 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 
    280 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 
    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 
    300 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 
    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 
    332 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 
    348 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 
    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 
    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 
    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 
    433 ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
    434 	: TestCaseGroup(context, "shader", "Shader state query tests")
    435 {
    436 }
    437 
    438 ShaderStateQueryTests::~ShaderStateQueryTests (void)
    439 {
    440 }
    441 
    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