Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2016 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 Negative Shader Storage Tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fNegativeShaderStorageTests.hpp"
     25 
     26 #include "gluShaderProgram.hpp"
     27 #include "glwDefs.hpp"
     28 #include "glwEnums.hpp"
     29 
     30 namespace deqp
     31 {
     32 namespace gles31
     33 {
     34 namespace Functional
     35 {
     36 namespace NegativeTestShared
     37 {
     38 namespace
     39 {
     40 
     41 void verifyProgram(NegativeTestContext& ctx, glu::ProgramSources sources)
     42 {
     43 	tcu::TestLog&				log			= ctx.getLog();
     44 	const glu::ShaderProgram	program		(ctx.getRenderContext(), sources);
     45 	bool						testFailed	= false;
     46 
     47 	log << program;
     48 
     49 	testFailed = program.getProgramInfo().linkOk;
     50 
     51 	if (testFailed)
     52 	{
     53 		const char* const message("Program was not expected to link.");
     54 		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
     55 		ctx.fail(message);
     56 	}
     57 }
     58 
     59 const char* getShaderExtensionDeclaration (glw::GLenum glShaderType)
     60 {
     61 	switch (glShaderType)
     62 	{
     63 		case GL_TESS_CONTROL_SHADER:
     64 		case GL_TESS_EVALUATION_SHADER: return "#extension GL_EXT_tessellation_shader : require\n";
     65 		case GL_GEOMETRY_SHADER:		return "#extension GL_EXT_geometry_shader : require\n";
     66 		default:
     67 			return "";
     68 	}
     69 }
     70 
     71 glu::ShaderType getGLUShaderType (glw::GLenum glShaderType)
     72 {
     73 	switch (glShaderType)
     74 	{
     75 		case GL_VERTEX_SHADER:			 return glu::SHADERTYPE_VERTEX;
     76 		case GL_FRAGMENT_SHADER:		 return glu::SHADERTYPE_FRAGMENT;
     77 		case GL_TESS_CONTROL_SHADER:	 return glu::SHADERTYPE_TESSELLATION_CONTROL;
     78 		case GL_TESS_EVALUATION_SHADER:	 return glu::SHADERTYPE_TESSELLATION_EVALUATION;
     79 		case GL_GEOMETRY_SHADER:		 return glu::SHADERTYPE_GEOMETRY;
     80 		case GL_COMPUTE_SHADER:			 return glu::SHADERTYPE_COMPUTE;
     81 		default:
     82 			DE_FATAL("Unknown shader type");
     83 			return glu::SHADERTYPE_LAST;
     84 	}
     85 }
     86 
     87 glw::GLenum getMaxSSBlockSizeEnum (glw::GLenum glShaderType)
     88 {
     89 	switch (glShaderType)
     90 	{
     91 		case GL_VERTEX_SHADER:			 return GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
     92 		case GL_FRAGMENT_SHADER:		 return GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
     93 		case GL_TESS_CONTROL_SHADER:	 return GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
     94 		case GL_TESS_EVALUATION_SHADER:	 return GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
     95 		case GL_GEOMETRY_SHADER:		 return GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
     96 		case GL_COMPUTE_SHADER:			 return GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
     97 		default:
     98 			 DE_FATAL("Unknown shader type");
     99 			 return -1;
    100 	}
    101 }
    102 
    103 int getMaxSSBlockSize (NegativeTestContext& ctx, glw::GLenum glShaderType)
    104 {
    105 	int maxSSBlocks = 0;
    106 	ctx.glGetIntegerv(getMaxSSBlockSizeEnum(glShaderType), &maxSSBlocks);
    107 
    108 	return maxSSBlocks;
    109 }
    110 
    111 std::string genBlockSource (NegativeTestContext& ctx, deInt64 numSSBlocks, glw::GLenum shaderType)
    112 {
    113 	const bool				isES32		= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    114 	const glu::GLSLVersion	version		= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
    115 	std::ostringstream		source;
    116 
    117 	source	<< glu::getGLSLVersionDeclaration(version) << "\n"
    118 			<< ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
    119 
    120 	switch (shaderType)
    121 	{
    122 		case GL_VERTEX_SHADER:
    123 		case GL_FRAGMENT_SHADER:
    124 			break;
    125 
    126 		case GL_COMPUTE_SHADER:
    127 			source << "layout (local_size_x = 1) in;\n";
    128 			break;
    129 
    130 		case GL_GEOMETRY_SHADER:
    131 			source << "layout(points) in;\n"
    132 				   << "layout(line_strip, max_vertices = 3) out;\n";
    133 			break;
    134 
    135 		case GL_TESS_CONTROL_SHADER:
    136 			source << "layout(vertices = 10) out;\n";
    137 			break;
    138 
    139 		case GL_TESS_EVALUATION_SHADER:
    140 			source << "layout(triangles) in;\n";
    141 			break;
    142 
    143 		default:
    144 			DE_FATAL("Unknown shader type");
    145 			break;
    146 	}
    147 
    148 	source  << "\n"
    149 			<< "layout(std430, binding = 0) buffer Block {\n"
    150 			<< "    int value;\n"
    151 			<< "} sb_in[" << numSSBlocks << "];\n"
    152 			<< "void main(void) { sb_in[0].value = 1; }\n";
    153 
    154 	return source.str();
    155 }
    156 
    157 std::string genCommonSource (NegativeTestContext& ctx, glw::GLenum shaderType)
    158 {
    159 	const bool				isES32		= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
    160 	const glu::GLSLVersion	version		= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
    161 	std::ostringstream		source;
    162 
    163 	source << glu::getGLSLVersionDeclaration(version) << "\n"
    164 		   << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
    165 
    166 	switch (shaderType)
    167 	{
    168 		case GL_TESS_CONTROL_SHADER:
    169 			source	<< "layout(vertices = 3) out;\n"
    170 					<< "void main() {}\n";
    171 			break;
    172 
    173 		case GL_TESS_EVALUATION_SHADER:
    174 			source	<< "layout(triangles, equal_spacing, cw) in;\n"
    175 					<< "void main() {}\n";
    176 			break;
    177 
    178 		default:
    179 			source  << "void main() {}\n";
    180 			break;
    181 	}
    182 
    183 	return source.str();
    184 }
    185 
    186 int genMaxSSBlocksSource (NegativeTestContext& ctx, glw::GLenum glShaderType, glu::ProgramSources& sources)
    187 {
    188 	int		maxSSBlocks				= getMaxSSBlockSize(ctx, glShaderType);
    189 	const	std::string shaderSrc	= genBlockSource(ctx, (maxSSBlocks), glShaderType);
    190 
    191 	sources.sources[getGLUShaderType(glShaderType)].push_back(shaderSrc);
    192 
    193 	return maxSSBlocks;
    194 }
    195 
    196 void block_number_limits (NegativeTestContext& ctx)
    197 {
    198 	const glw::GLenum glShaderTypes[] =
    199 	{
    200 		GL_VERTEX_SHADER,
    201 		GL_FRAGMENT_SHADER,
    202 		GL_TESS_CONTROL_SHADER,
    203 		GL_TESS_EVALUATION_SHADER,
    204 		GL_GEOMETRY_SHADER,
    205 		GL_COMPUTE_SHADER,
    206 	};
    207 
    208 	const std::string	vertSource			= genCommonSource(ctx, GL_VERTEX_SHADER);
    209 	const std::string	fragSource			= genCommonSource(ctx, GL_FRAGMENT_SHADER);
    210 	const std::string	tessControlSource	= genCommonSource(ctx, GL_TESS_CONTROL_SHADER);
    211 	const std::string	tessEvalSource		= genCommonSource(ctx, GL_TESS_EVALUATION_SHADER);
    212 
    213 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(glShaderTypes); ndx++)
    214 	{
    215 		ctx.beginSection("maxShaderStorageBlocks: Exceed limits");
    216 
    217 		if (!ctx.isShaderSupported(static_cast<glu::ShaderType>(getGLUShaderType(glShaderTypes[ndx]))))
    218 		{
    219 			ctx.endSection();
    220 			continue;
    221 		}
    222 
    223 		int					maxSSBlocks			= getMaxSSBlockSize(ctx, glShaderTypes[ndx]);
    224 		std::string			source				= genBlockSource(ctx, maxSSBlocks+1, glShaderTypes[ndx]);
    225 
    226 		glu::ProgramSources sources;
    227 
    228 		if (maxSSBlocks == 0)
    229 		{
    230 			ctx.endSection();
    231 			continue;
    232 		}
    233 
    234 		switch (glShaderTypes[ndx])
    235 		{
    236 			case GL_VERTEX_SHADER:
    237 				sources << glu::VertexSource(source)
    238 						<< glu::FragmentSource(fragSource);
    239 				break;
    240 
    241 			case GL_FRAGMENT_SHADER:
    242 				sources << glu::VertexSource(vertSource)
    243 						<< glu::FragmentSource(source);
    244 				break;
    245 
    246 			case GL_TESS_CONTROL_SHADER:
    247 				sources << glu::VertexSource(vertSource)
    248 						<< glu::FragmentSource(fragSource)
    249 						<< glu::TessellationControlSource(source)
    250 						<< glu::TessellationEvaluationSource(tessEvalSource);
    251 				break;
    252 
    253 			case GL_TESS_EVALUATION_SHADER:
    254 				sources << glu::VertexSource(vertSource)
    255 						<< glu::FragmentSource(fragSource)
    256 						<< glu::TessellationControlSource(tessControlSource)
    257 						<< glu::TessellationEvaluationSource(source);
    258 				break;
    259 
    260 			case GL_GEOMETRY_SHADER:
    261 				sources << glu::VertexSource(vertSource)
    262 						<< glu::FragmentSource(fragSource)
    263 						<< glu::GeometrySource(source);
    264 				break;
    265 
    266 			case GL_COMPUTE_SHADER:
    267 				sources << glu::ComputeSource(source);
    268 				break;
    269 
    270 			default:
    271 				DE_FATAL("Unknown shader type");
    272 				break;
    273 		}
    274 
    275 		verifyProgram(ctx, sources);
    276 		ctx.endSection();
    277 	}
    278 }
    279 
    280 void max_combined_block_number_limit (NegativeTestContext& ctx)
    281 {
    282 	ctx.beginSection("maxCombinedShaderStorageBlocks: Exceed limits");
    283 
    284 	glu::ProgramSources sources;
    285 
    286 	int combinedSSBlocks	= 0;
    287 	int maxCombinedSSBlocks = 0;
    288 
    289 	combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_VERTEX_SHADER, sources);
    290 	combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_FRAGMENT_SHADER, sources);
    291 
    292 	if ((ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_CONTROL)) && (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION)))
    293 	{
    294 		combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_CONTROL_SHADER, sources);
    295 		combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_EVALUATION_SHADER, sources);
    296 	}
    297 
    298 	if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY))
    299 		combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_GEOMETRY_SHADER, sources);
    300 
    301 	ctx.glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedSSBlocks);
    302 
    303 	ctx.getLog() << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << maxCombinedSSBlocks << tcu::TestLog::EndMessage;
    304 	ctx.getLog() << tcu::TestLog::Message << "Combined shader storage blocks: " << combinedSSBlocks << tcu::TestLog::EndMessage;
    305 
    306 	if (combinedSSBlocks > maxCombinedSSBlocks)
    307 		verifyProgram(ctx, sources);
    308 	else
    309 		ctx.getLog() << tcu::TestLog::Message << "Test skipped: Combined shader storage blocks < GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << tcu::TestLog::EndMessage;
    310 
    311 	ctx.endSection();
    312 }
    313 
    314 } // anonymous
    315 
    316 std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions ()
    317 {
    318 	const FunctionContainer funcs[] =
    319 	{
    320 		{ block_number_limits,				"block_number_limits",				"Invalid shader linkage" },
    321 		{ max_combined_block_number_limit,	"max_combined_block_number_limit",	"Invalid shader linkage" },
    322 	};
    323 
    324 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
    325 }
    326 
    327 } // NegativeTestShared
    328 } // Functional
    329 } // gles31
    330 } // deqp
    331